diff --git a/DEPS b/DEPS
index a338b199..b2e33af7 100644
--- a/DEPS
+++ b/DEPS
@@ -162,11 +162,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'c13cb6e62441c499c2dca6b899c67f2c3e9208fe',
+  'skia_revision': 'ba36ee78262ab644513bb2f0acfeae2e8e0846f7',
   # 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': '75ba649d1c6fea41b60bfd21417bd135793b5073',
+  'v8_revision': '6de79412590cd8936926db7e4ea8c00494900791',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -174,15 +174,15 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '9dbfeac8b553427eabe2c4b5bce322efecc0b440',
+  'angle_revision': '8ac49e182aa03e90fd11c925b3e1018cf3652e0a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': 'cebb9635a5d54578385edb8cf5c4794703dc8f30',
+  'swiftshader_revision': '5f1b4c0ba92e3b37ba64b9a9dd4d6e03c37cac19',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '9fafe62237ad4cf5c502f9f81a5ce302fc69db3c',
+  'pdfium_revision': 'f27abc1aaeeae6893e3b24533e2d696db5e84eac',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -225,7 +225,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': 'c5f9c068212598f72a2f07356be1d7452ce9861b',
+  'catapult_revision': 'fc09aa89b962d9e59d5fda153be9ed4c493c9200',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -867,7 +867,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'cc6f585f055ae696170b22f0e8db906d27afe636',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '2ae039a065a6afa10e1a067f5af7c5403a6dd895',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -1246,7 +1246,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'b2f1e4bfc51fc79f0fd7a7aaef5cc68566bc31c8',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '9fb2ed7f23e89d808c1c8faf54eb62436236acb4',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1414,7 +1414,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'abaae129d9a0c6e1e092067e0b105475df43352e',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '9a91161b9f65df0cbe64009827ca6b8d1c172675',
+    Var('webrtc_git') + '/src.git' + '@' + '7e2441234b947a4a7a915391369d8f10c2e97549',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1455,7 +1455,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@61336619eaf0d77cea9906b16f26377eb6441c4f',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@e1fb182f7519158cf1f4e08e57e88973c31e763b',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index bdaca7a..7cd30bc 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -1122,6 +1122,8 @@
       ),
       False,
       (
+        r'^fuchsia/engine/browser/url_request_rewrite_rules_manager\.cc$',
+        r'^fuchsia/engine/url_request_rewrite_type_converters\.cc$',
         r'^third_party/blink/.*\.(cc|h)$',
         r'^content/renderer/.*\.(cc|h)$',
       ),
diff --git a/android_webview/browser/aw_metrics_service_client.cc b/android_webview/browser/aw_metrics_service_client.cc
index fe9cee8..6c835e7 100644
--- a/android_webview/browser/aw_metrics_service_client.cc
+++ b/android_webview/browser/aw_metrics_service_client.cc
@@ -11,7 +11,6 @@
 #include "android_webview/browser/aw_feature_list.h"
 #include "android_webview/browser/aw_metrics_log_uploader.h"
 #include "android_webview/browser_jni_headers/AwMetricsServiceClient_jni.h"
-#include "android_webview/common/aw_switches.h"
 #include "base/android/jni_android.h"
 #include "base/android/jni_array.h"
 #include "base/android/jni_string.h"
@@ -184,7 +183,8 @@
 
 bool AwMetricsServiceClient::IsReportingEnabled() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return EnabledStateProvider::IsReportingEnabled() && is_in_sample_;
+  return IsMetricsReportingForceEnabled() ||
+         (EnabledStateProvider::IsReportingEnabled() && is_in_sample_);
 }
 
 metrics::MetricsService* AwMetricsServiceClient::GetMetricsService() {
diff --git a/android_webview/browser/aw_metrics_service_client_unittest.cc b/android_webview/browser/aw_metrics_service_client_unittest.cc
index 3b911106..ab6dad1 100644
--- a/android_webview/browser/aw_metrics_service_client_unittest.cc
+++ b/android_webview/browser/aw_metrics_service_client_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "android_webview/browser/aw_metrics_service_client.h"
 
+#include "base/command_line.h"
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/run_loop.h"
@@ -11,6 +12,7 @@
 #include "base/test/test_simple_task_runner.h"
 #include "components/metrics/metrics_pref_names.h"
 #include "components/metrics/metrics_service.h"
+#include "components/metrics/metrics_switches.h"
 #include "components/prefs/testing_pref_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -23,7 +25,7 @@
 
 class TestClient : public AwMetricsServiceClient {
  public:
-  TestClient() {}
+  TestClient() : in_sample_(true) {}
   ~TestClient() override {}
 
   bool IsRecordingActive() {
@@ -32,11 +34,13 @@
       return service->recording_active();
     return false;
   }
+  void SetInSample(bool value) { in_sample_ = value; }
 
  protected:
   bool IsInSample() override { return true; }
 
  private:
+  bool in_sample_;
   DISALLOW_COPY_AND_ASSIGN(TestClient);
 };
 
@@ -125,4 +129,22 @@
   ASSERT_FALSE(prefs->HasPrefPath(metrics::prefs::kMetricsClientID));
 }
 
+TEST_F(AwMetricsServiceClientTest, TestCanForceEnableMetrics) {
+  auto prefs = CreateTestPrefs();
+  auto client = CreateAndInitTestClient(prefs.get());
+
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      metrics::switches::kForceEnableMetricsReporting);
+
+  // Flip everything to false; flag should have higher precedence.
+  client->SetHaveMetricsConsent(false);
+  client->SetInSample(false);
+  ASSERT_TRUE(client->IsReportingEnabled());
+
+  // Flip things to true just to double-check everything still works.
+  client->SetHaveMetricsConsent(true);
+  client->SetInSample(true);
+  ASSERT_TRUE(client->IsReportingEnabled());
+}
+
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_settings.cc b/android_webview/browser/aw_settings.cc
index ea56be3c..5c668e43 100644
--- a/android_webview/browser/aw_settings.cc
+++ b/android_webview/browser/aw_settings.cc
@@ -496,30 +496,53 @@
   web_prefs->scroll_top_left_interop_enabled =
       Java_AwSettings_getScrollTopLeftInteropEnabledLocked(env, obj);
 
+  bool is_dark_mode;
   switch (Java_AwSettings_getForceDarkModeLocked(env, obj)) {
     case ForceDarkMode::FORCE_DARK_OFF:
-      web_prefs->force_dark_mode_enabled = false;
+      is_dark_mode = false;
       break;
     case ForceDarkMode::FORCE_DARK_ON:
-      web_prefs->force_dark_mode_enabled = true;
+      is_dark_mode = true;
       break;
     case ForceDarkMode::FORCE_DARK_AUTO: {
       AwContents* contents = AwContents::FromWebContents(web_contents());
-      web_prefs->force_dark_mode_enabled =
-          contents && contents->GetViewTreeForceDarkState();
+      is_dark_mode = contents && contents->GetViewTreeForceDarkState();
       break;
     }
   }
-
-  // Blink's behavior is that if the preferred color scheme matches the
-  // supported color scheme, then force dark will be disabled, otherwise
-  // the preferred color scheme will be reset to no preference. Therefore
-  // when enabling force dark, we also set the preferred color scheme to
-  // dark so that dark themed content will be preferred over force darkening.
   web_prefs->preferred_color_scheme =
-      web_prefs->force_dark_mode_enabled
-          ? blink::PreferredColorScheme::kDark
-          : blink::PreferredColorScheme::kNoPreference;
+      is_dark_mode ? blink::PreferredColorScheme::kDark
+                   : blink::PreferredColorScheme::kNoPreference;
+  if (is_dark_mode) {
+    switch (Java_AwSettings_getDarkModePreferencesLocked(env, obj)) {
+      case DarkModePreferences::FORCE_DARK_ONLY: {
+        web_prefs->preferred_color_scheme =
+            blink::PreferredColorScheme::kNoPreference;
+        web_prefs->force_dark_mode_enabled = true;
+        break;
+      }
+      case DarkModePreferences::MEDIA_QUERY_ONLY: {
+        web_prefs->preferred_color_scheme = blink::PreferredColorScheme::kDark;
+        web_prefs->force_dark_mode_enabled = false;
+        break;
+      }
+      // Blink's behavior is that if the preferred color scheme matches the
+      // supported color scheme, then force dark will be disabled, otherwise
+      // the preferred color scheme will be reset to no preference. Therefore
+      // when enabling force dark, we also set the preferred color scheme to
+      // dark so that dark themed content will be preferred over force
+      // darkening.
+      case DarkModePreferences::PREFER_MEDIA_QUERY_OVER_FORCE_DARK: {
+        web_prefs->preferred_color_scheme = blink::PreferredColorScheme::kDark;
+        web_prefs->force_dark_mode_enabled = true;
+        break;
+      }
+    }
+  } else {
+    web_prefs->preferred_color_scheme =
+        blink::PreferredColorScheme::kNoPreference;
+    web_prefs->force_dark_mode_enabled = false;
+  }
 }
 
 bool AwSettings::GetAllowFileAccess() {
diff --git a/android_webview/browser/aw_settings.h b/android_webview/browser/aw_settings.h
index 0d4324c..8687588 100644
--- a/android_webview/browser/aw_settings.h
+++ b/android_webview/browser/aw_settings.h
@@ -28,6 +28,13 @@
     FORCE_DARK_ON = 2,
   };
 
+  // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.android_webview.settings
+  enum DarkModePreferences {
+    FORCE_DARK_ONLY = 0,
+    MEDIA_QUERY_ONLY = 1,
+    PREFER_MEDIA_QUERY_OVER_FORCE_DARK = 2,
+  };
+
   static AwSettings* FromWebContents(content::WebContents* web_contents);
   static bool GetAllowSniffingFileUrls();
 
diff --git a/android_webview/browser/safe_browsing/aw_safe_browsing_ui_manager.h b/android_webview/browser/safe_browsing/aw_safe_browsing_ui_manager.h
index 0d3897e..85032ef 100644
--- a/android_webview/browser/safe_browsing/aw_safe_browsing_ui_manager.h
+++ b/android_webview/browser/safe_browsing/aw_safe_browsing_ui_manager.h
@@ -1,10 +1,6 @@
 // Copyright (c) 2017 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-//
-// The Safe Browsing service is responsible for downloading anti-phishing and
-// anti-malware tables and checking urls against them. This is android_webview
-// specific ui_manager.
 
 #ifndef ANDROID_WEBVIEW_BROWSER_SAFE_BROWSING_AW_SAFE_BROWSING_UI_MANAGER_H_
 #define ANDROID_WEBVIEW_BROWSER_SAFE_BROWSING_AW_SAFE_BROWSING_UI_MANAGER_H_
@@ -24,6 +20,9 @@
 
 namespace android_webview {
 
+// The Safe Browsing service is responsible for checking URLs against
+// anti-phishing and anti-malware tables. This is an Android WebView-specific UI
+// manager.
 class AwSafeBrowsingUIManager : public safe_browsing::BaseUIManager {
  public:
   class UIManagerClient {
diff --git a/android_webview/java/src/org/chromium/android_webview/AwSettings.java b/android_webview/java/src/org/chromium/android_webview/AwSettings.java
index ad54094..fd07ab3 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwSettings.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwSettings.java
@@ -16,6 +16,7 @@
 import android.util.Log;
 import android.webkit.WebSettings;
 
+import org.chromium.android_webview.settings.DarkModePreferences;
 import org.chromium.android_webview.settings.ForceDarkMode;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.ThreadUtils;
@@ -62,6 +63,15 @@
     @ForceDarkMode
     private int mForceDarkMode = ForceDarkMode.FORCE_DARK_AUTO;
 
+    public static final int FORCE_DARK_ONLY = DarkModePreferences.FORCE_DARK_ONLY;
+    public static final int MEDIA_QUERY_ONLY = DarkModePreferences.MEDIA_QUERY_ONLY;
+    // This option requires RuntimeEnabledFeatures::MetaColorSchemeEnabled()
+    public static final int PREFER_MEDIA_QUERY_OVER_FORCE_DARK =
+            DarkModePreferences.PREFER_MEDIA_QUERY_OVER_FORCE_DARK;
+
+    @DarkModePreferences
+    private int mDarkModePreferences = DarkModePreferences.PREFER_MEDIA_QUERY_OVER_FORCE_DARK;
+
     // This class must be created on the UI thread. Afterwards, it can be
     // used from any thread. Internally, the class uses a message queue
     // to call native code on the UI thread only.
@@ -1712,6 +1722,29 @@
         }
     }
 
+    @DarkModePreferences
+    public int getDarkModePreferences() {
+        synchronized (mAwSettingsLock) {
+            return getDarkModePreferencesLocked();
+        }
+    }
+
+    @CalledByNative
+    @DarkModePreferences
+    public int getDarkModePreferencesLocked() {
+        assert Thread.holdsLock(mAwSettingsLock);
+        return mDarkModePreferences;
+    }
+
+    public void setDarkModePreferences(@DarkModePreferences int darkModePreferences) {
+        synchronized (mAwSettingsLock) {
+            if (mDarkModePreferences != darkModePreferences) {
+                mDarkModePreferences = darkModePreferences;
+                mEventHandler.updateWebkitPreferencesLocked();
+            }
+        }
+    }
+
     @CalledByNative
     private boolean getAllowRunningInsecureContentLocked() {
         assert Thread.holdsLock(mAwSettingsLock);
diff --git a/ash/components/fast_ink/fast_ink_view.cc b/ash/components/fast_ink/fast_ink_view.cc
index 3ccafc8..c4c01bf 100644
--- a/ash/components/fast_ink/fast_ink_view.cc
+++ b/ash/components/fast_ink/fast_ink_view.cc
@@ -15,6 +15,7 @@
 #include "cc/base/math_util.h"
 #include "cc/trees/layer_tree_frame_sink.h"
 #include "cc/trees/layer_tree_frame_sink_client.h"
+#include "components/viz/common/frame_timing_details.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "components/viz/common/hit_test/hit_test_region_list.h"
 #include "components/viz/common/quads/compositor_frame.h"
@@ -230,10 +231,10 @@
       view_->DidReceiveCompositorFrameAck();
   }
   void DidPresentCompositorFrame(
-      uint32_t presentation_token,
-      const gfx::PresentationFeedback& feedback) override {
+      uint32_t frame_token,
+      const viz::FrameTimingDetails& details) override {
     if (view_)
-      view_->DidPresentCompositorFrame(feedback);
+      view_->DidPresentCompositorFrame(details.presentation_feedback);
   }
   void DidLoseLayerTreeFrameSink() override {
     exported_resources_.clear();
diff --git a/ash/display/display_prefs.cc b/ash/display/display_prefs.cc
index e9c540a..89f2cb1 100644
--- a/ash/display/display_prefs.cc
+++ b/ash/display/display_prefs.cc
@@ -724,7 +724,7 @@
   const std::set<int64_t>& external_display_mirror_info =
       GetDisplayManager()->external_display_mirror_info();
   for (const auto& id : external_display_mirror_info)
-    pref_data->GetList().emplace_back(base::Value(base::NumberToString(id)));
+    pref_data->Append(base::Value(base::NumberToString(id)));
 }
 
 // Stores mixed mirror mode parameters. Clear the preferences if
@@ -745,7 +745,7 @@
 
   base::ListValue mirroring_destination_ids_value;
   for (const auto& id : mixed_params->destination_ids) {
-    mirroring_destination_ids_value.GetList().emplace_back(
+    mirroring_destination_ids_value.Append(
         base::Value(base::NumberToString(id)));
   }
   pref_data->SetKey(kMirroringDestinationIds,
diff --git a/ash/display/display_prefs_unittest.cc b/ash/display/display_prefs_unittest.cc
index b20754b..fe58a463 100644
--- a/ash/display/display_prefs_unittest.cc
+++ b/ash/display/display_prefs_unittest.cc
@@ -224,7 +224,7 @@
     base::ListValue* pref_data = update.Get();
     pref_data->Clear();
     for (const auto& id : external_display_mirror_info)
-      pref_data->GetList().emplace_back(base::Value(base::NumberToString(id)));
+      pref_data->Append(base::Value(base::NumberToString(id)));
   }
 
   std::string GetRegisteredDisplayPlacementStr(
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc
index e451ea9..8f59f2f 100644
--- a/ash/shelf/shelf_layout_manager.cc
+++ b/ash/shelf/shelf_layout_manager.cc
@@ -233,6 +233,7 @@
     : visibility_state(SHELF_VISIBLE),
       auto_hide_state(SHELF_AUTO_HIDE_HIDDEN),
       window_state(WorkspaceWindowState::kDefault),
+      hotseat_state(HotseatState::kShown),
       pre_lock_screen_animation_active(false),
       session_state(session_manager::SessionState::UNKNOWN) {}
 
diff --git a/ash/wm/overview/overview_session.cc b/ash/wm/overview/overview_session.cc
index ed07279b..5d7dfc0b 100644
--- a/ash/wm/overview/overview_session.cc
+++ b/ash/wm/overview/overview_session.cc
@@ -628,7 +628,7 @@
       callback.Run(settings.get());
     }
     window->SetTransform(
-        gfx::Transform(1.f, 0.f, 0.f, 1.f, 0.f, static_cast<float>(new_y)));
+        gfx::Transform(1.f, 0.f, 0.f, 1.f, 0.f, static_cast<float>(-new_y)));
     window->layer()->SetOpacity(opacity);
     return settings;
   }
diff --git a/ash/wm/tablet_mode/tablet_mode_window_manager.cc b/ash/wm/tablet_mode/tablet_mode_window_manager.cc
index b029d059..7d2ad60 100644
--- a/ash/wm/tablet_mode/tablet_mode_window_manager.cc
+++ b/ash/wm/tablet_mode/tablet_mode_window_manager.cc
@@ -233,27 +233,6 @@
 }
 
 void TabletModeWindowManager::Init() {
-  // If clamshell split view mode is not enabled, still keep the old behavior:
-  // end overview if it's active. And carry over snapped windows to splitscreen
-  // if possible.
-  if (!IsClamshellSplitViewModeEnabled())
-    Shell::Get()->overview_controller()->EndOverview();
-
-  // If clamshell splitview mode is enabled, there are 3 cases when entering
-  // tablet mode:
-  // 1) overview is active but split view is inactive: keep overview active in
-  //    tablet mode.
-  // 2) overview and splitview are both active (splitview can only be active
-  //    when overview is active in clamshell mode): keep overview and splitview
-  //    both active in tablet mode.
-  // 3) overview is inactive: keep the current behavior, i.e.,
-  //    a. if the top window is a snapped window, put it in splitview
-  //    b. if the second top window is also a snapped window and snapped to
-  //       the other side, put it in split view as well. Otherwise, open
-  //       overview on the other side of the screen
-  //    c. if the top window is not a snapped window, maximize all windows
-  //       when entering tablet mode.
-
   {
     ScopedObserveWindowAnimation scoped_observe(GetTopWindow(), this,
                                                 /*exiting_tablet_mode=*/false);
@@ -570,6 +549,27 @@
 }
 
 void TabletModeWindowManager::ArrangeWindowsForTabletMode() {
+  // If clamshell split view mode is not enabled, still keep the old behavior:
+  // end overview if it's active. And carry over snapped windows to
+  // splitscreen if possible.
+  if (!IsClamshellSplitViewModeEnabled())
+    Shell::Get()->overview_controller()->EndOverview();
+
+  // If clamshell splitview mode is enabled, there are 3 cases when entering
+  // tablet mode:
+  // 1) overview is active but split view is inactive: keep overview active in
+  //    tablet mode.
+  // 2) overview and splitview are both active (splitview can only be active
+  //    when overview is active in clamshell mode): keep overview and splitview
+  //    both active in tablet mode.
+  // 3) overview is inactive: keep the current behavior, i.e.,
+  //    a. if the top window is a snapped window, put it in splitview
+  //    b. if the second top window is also a snapped window and snapped to
+  //       the other side, put it in split view as well. Otherwise, open
+  //       overview on the other side of the screen
+  //    c. if the top window is not a snapped window, maximize all windows
+  //       when entering tablet mode.
+
   // |activatable_windows| includes all windows to be tracked, and that includes
   // windows on the lock screen via |scoped_skip_user_session_blocked_check|.
   ScopedSkipUserSessionBlockedCheck scoped_skip_user_session_blocked_check;
diff --git a/base/android/orderfile/orderfile_call_graph_instrumentation.cc b/base/android/orderfile/orderfile_call_graph_instrumentation.cc
index 936df1b..fce1de4b 100644
--- a/base/android/orderfile/orderfile_call_graph_instrumentation.cc
+++ b/base/android/orderfile/orderfile_call_graph_instrumentation.cc
@@ -283,10 +283,10 @@
       caller_count.SetStringKey("caller_offset",
                                 base::StringPrintf("%" PRIu32, caller_offset));
       caller_count.SetStringKey("count", base::StringPrintf("%" PRIu32, count));
-      callers_list.GetList().push_back(std::move(caller_count));
+      callers_list.Append(std::move(caller_count));
     }
     callee_element.SetKey("caller_and_count", std::move(callers_list));
-    call_graph.GetList().push_back(std::move(callee_element));
+    call_graph.Append(std::move(callee_element));
   }
 
   root.SetKey("call_graph", std::move(call_graph));
diff --git a/base/json/json_perftest.cc b/base/json/json_perftest.cc
index 1e0ea33..c62f951 100644
--- a/base/json/json_perftest.cc
+++ b/base/json/json_perftest.cc
@@ -25,10 +25,10 @@
   root.SetStringKey("String", "Foo");
 
   ListValue list;
-  list.GetList().emplace_back(2.718);
-  list.GetList().emplace_back(false);
-  list.GetList().emplace_back(123);
-  list.GetList().emplace_back("Bar");
+  list.Append(2.718);
+  list.Append(false);
+  list.Append(123);
+  list.Append("Bar");
   root.SetKey("List", std::move(list));
 
   return root;
diff --git a/base/json/json_writer_unittest.cc b/base/json/json_writer_unittest.cc
index 291a225..a536b910 100644
--- a/base/json/json_writer_unittest.cc
+++ b/base/json/json_writer_unittest.cc
@@ -61,9 +61,9 @@
   ListValue list;
   DictionaryValue inner_dict;
   inner_dict.SetIntKey("inner int", 10);
-  list.GetList().push_back(std::move(inner_dict));
-  list.GetList().emplace_back(Value::Type::LIST);
-  list.GetList().emplace_back(true);
+  list.Append(std::move(inner_dict));
+  list.Append(Value(Value::Type::LIST));
+  list.Append(true);
   root_dict.SetKey("list", std::move(list));
 
   // Test the pretty-printer.
@@ -121,11 +121,11 @@
   EXPECT_TRUE(output_js.empty());
 
   ListValue binary_list;
-  binary_list.GetList().emplace_back(kBufferSpan);
-  binary_list.GetList().emplace_back(5);
-  binary_list.GetList().emplace_back(kBufferSpan);
-  binary_list.GetList().emplace_back(2);
-  binary_list.GetList().emplace_back(kBufferSpan);
+  binary_list.Append(Value(kBufferSpan));
+  binary_list.Append(5);
+  binary_list.Append(Value(kBufferSpan));
+  binary_list.Append(2);
+  binary_list.Append(Value(kBufferSpan));
   EXPECT_FALSE(JSONWriter::Write(binary_list, &output_js));
   EXPECT_TRUE(JSONWriter::WriteWithOptions(
       binary_list, JSONWriter::OPTIONS_OMIT_BINARY_VALUES, &output_js));
diff --git a/base/linux_util.cc b/base/linux_util.cc
index b771a26d..2da24e1 100644
--- a/base/linux_util.cc
+++ b/base/linux_util.cc
@@ -148,6 +148,11 @@
     "Unknown";
 #endif
 
+// This function is only supposed to be used in tests. The declaration in the
+// header file is guarded by "#if defined(UNIT_TEST)" so that they can be used
+// by tests but not non-test code. However, this .cc file is compiled as part
+// of "base" where "UNIT_TEST" is not defined. So we need to specify
+// "BASE_EXPORT" here again so that they are visible to tests.
 BASE_EXPORT std::string GetKeyValueFromOSReleaseFileForTesting(
     const std::string& input,
     const char* key) {
diff --git a/base/test/task_environment.h b/base/test/task_environment.h
index e7761cb..bfd32e0 100644
--- a/base/test/task_environment.h
+++ b/base/test/task_environment.h
@@ -152,19 +152,19 @@
   };
 
   // List of traits that are valid inputs for the constructor below.
-  struct ValidTrait {
-    ValidTrait(TimeSource);
-    ValidTrait(MainThreadType);
-    ValidTrait(ThreadPoolExecutionMode);
-    ValidTrait(SubclassCreatesDefaultTaskRunner);
-    ValidTrait(ThreadingMode);
+  struct ValidTraits {
+    ValidTraits(TimeSource);
+    ValidTraits(MainThreadType);
+    ValidTraits(ThreadPoolExecutionMode);
+    ValidTraits(SubclassCreatesDefaultTaskRunner);
+    ValidTraits(ThreadingMode);
   };
 
   // Constructor accepts zero or more traits which customize the testing
   // environment.
   template <typename... TaskEnvironmentTraits,
             class CheckArgumentsAreValid = std::enable_if_t<
-                trait_helpers::AreValidTraits<ValidTrait,
+                trait_helpers::AreValidTraits<ValidTraits,
                                               TaskEnvironmentTraits...>::value>>
   NOINLINE explicit TaskEnvironment(TaskEnvironmentTraits... traits)
       : TaskEnvironment(
diff --git a/base/trace_event/OWNERS b/base/trace_event/OWNERS
index aa3ab84..8d95238 100644
--- a/base/trace_event/OWNERS
+++ b/base/trace_event/OWNERS
@@ -1,4 +1,3 @@
-chiniforooshan@chromium.org
 eseckler@chromium.org
 oysteine@chromium.org
 primiano@chromium.org
diff --git a/base/trace_event/trace_config.cc b/base/trace_event/trace_config.cc
index 061100c..22d6098 100644
--- a/base/trace_event/trace_config.cc
+++ b/base/trace_event/trace_config.cc
@@ -163,7 +163,7 @@
   std::set<base::ProcessId> ordered_set(included_process_ids_.begin(),
                                         included_process_ids_.end());
   for (auto process_id : ordered_set)
-    list->GetList().emplace_back(static_cast<int>(process_id));
+    list->Append(static_cast<int>(process_id));
 }
 
 bool TraceConfig::ProcessFilterConfig::IsEnabled(
diff --git a/base/trace_event/traced_value.cc b/base/trace_event/traced_value.cc
index b1ea5aab..5b6467a 100644
--- a/base/trace_event/traced_value.cc
+++ b/base/trace_event/traced_value.cc
@@ -341,7 +341,7 @@
             stack.push_back(cur_dict);
             cur_dict = cur_dict->SetKey(ReadKeyName(it), std::move(new_dict));
           } else {
-            cur_list->GetList().push_back(std::move(new_dict));
+            cur_list->Append(std::move(new_dict));
             // |new_dict| is invalidated at this point, so |cur_dict| needs to
             // be reset.
             cur_dict = &cur_list->GetList().back();
@@ -369,7 +369,7 @@
             cur_list = cur_dict->SetKey(ReadKeyName(it), std::move(new_list));
             cur_dict = nullptr;
           } else {
-            cur_list->GetList().push_back(std::move(new_list));
+            cur_list->Append(std::move(new_list));
             stack.push_back(cur_list);
             // |cur_list| is invalidated at this point by the Append, so it
             // needs to be reset.
@@ -383,7 +383,7 @@
           if (cur_dict) {
             cur_dict->SetBoolKey(ReadKeyName(it), value);
           } else {
-            cur_list->GetList().emplace_back(value);
+            cur_list->Append(value);
           }
         } break;
 
@@ -393,7 +393,7 @@
           if (cur_dict) {
             cur_dict->SetIntKey(ReadKeyName(it), value);
           } else {
-            cur_list->GetList().emplace_back(value);
+            cur_list->Append(value);
           }
         } break;
 
@@ -403,7 +403,7 @@
           if (cur_dict) {
             cur_dict->SetDoubleKey(ReadKeyName(it), value);
           } else {
-            cur_list->GetList().emplace_back(value);
+            cur_list->Append(value);
           }
         } break;
 
@@ -413,7 +413,7 @@
           if (cur_dict) {
             cur_dict->SetStringKey(ReadKeyName(it), std::move(value));
           } else {
-            cur_list->GetList().emplace_back(std::move(value));
+            cur_list->Append(std::move(value));
           }
         } break;
 
diff --git a/base/values.cc b/base/values.cc
index abe496f..89c0728 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -58,7 +58,7 @@
   for (const auto& entry : list.GetList()) {
     std::unique_ptr<Value> child_copy = CopyWithoutEmptyChildren(entry);
     if (child_copy)
-      copy.GetList().push_back(std::move(*child_copy));
+      copy.Append(std::move(*child_copy));
   }
   return copy.GetList().empty() ? nullptr
                                 : std::make_unique<Value>(std::move(copy));
diff --git a/base/values_unittest.cc b/base/values_unittest.cc
index dce41457..4cc13d6 100644
--- a/base/values_unittest.cc
+++ b/base/values_unittest.cc
@@ -1221,7 +1221,7 @@
   DictionaryValue new_bookmark;
   new_bookmark.SetKey("name", Value("Froogle"));
   new_bookmark.SetKey("url", Value("http://froogle.com"));
-  toolbar_bookmarks->GetList().push_back(std::move(new_bookmark));
+  toolbar_bookmarks->Append(std::move(new_bookmark));
 
   Value* bookmark_list = settings.FindPath("global.toolbar.bookmarks");
   ASSERT_TRUE(bookmark_list);
diff --git a/build/android/gradle/root.jinja b/build/android/gradle/root.jinja
index 3895fc43..38d73875 100644
--- a/build/android/gradle/root.jinja
+++ b/build/android/gradle/root.jinja
@@ -10,7 +10,7 @@
     }
     dependencies {
 {% if channel == 'canary' %}
-        classpath "com.android.tools.build:gradle:3.6.0-alpha03"
+        classpath "com.android.tools.build:gradle:3.6.0-alpha10"
 {% elif channel == 'beta' %}
         classpath "com.android.tools.build:gradle:3.1.0-beta4"
 {% else %}
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index b5cbbb6..e3b3148 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -1924,7 +1924,7 @@
   }
 
   if (is_mac || is_ios) {
-    if (symbol_level == 2) {
+    if (symbol_level > 0) {
       # Mac dead code stripping requires symbols.
       common_optimize_on_ldflags += [ "-Wl,-dead_strip" ]
     }
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 0bf082cf3..f6dd1c8e 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-8902626326861029680
\ No newline at end of file
+8902595185658947296
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 9a9205b..92d4dce8 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-8902625321346829424
\ No newline at end of file
+8902598355793962064
\ No newline at end of file
diff --git a/cc/base/BUILD.gn b/cc/base/BUILD.gn
index 9546cd27..4b0775b86 100644
--- a/cc/base/BUILD.gn
+++ b/cc/base/BUILD.gn
@@ -4,7 +4,7 @@
 
 import("//cc/cc.gni")
 
-component("base") {
+cc_component("base") {
   output_name = "cc_base"
   sources = [
     "base_export.h",
diff --git a/cc/metrics/compositor_frame_reporting_controller.cc b/cc/metrics/compositor_frame_reporting_controller.cc
index f996975..f4dd100e 100644
--- a/cc/metrics/compositor_frame_reporting_controller.cc
+++ b/cc/metrics/compositor_frame_reporting_controller.cc
@@ -5,6 +5,7 @@
 #include "cc/metrics/compositor_frame_reporting_controller.h"
 
 #include "cc/metrics/compositor_frame_reporter.h"
+#include "components/viz/common/frame_timing_details.h"
 #include "components/viz/common/quads/compositor_frame_metadata.h"
 
 namespace cc {
@@ -187,7 +188,7 @@
 
 void CompositorFrameReportingController::DidPresentCompositorFrame(
     uint32_t frame_token,
-    base::TimeTicks presentation_time) {
+    const viz::FrameTimingDetails& details) {
   while (!submitted_compositor_frames_.empty()) {
     auto submitted_frame = submitted_compositor_frames_.begin();
     if (viz::FrameTokenGT(submitted_frame->frame_token, frame_token))
@@ -199,8 +200,8 @@
       termination_status =
           CompositorFrameReporter::FrameTerminationStatus::kDidNotPresentFrame;
 
-    submitted_frame->reporter->TerminateFrame(termination_status,
-                                              presentation_time);
+    submitted_frame->reporter->TerminateFrame(
+        termination_status, details.presentation_feedback.timestamp);
     submitted_compositor_frames_.erase(submitted_frame);
   }
 }
diff --git a/cc/metrics/compositor_frame_reporting_controller.h b/cc/metrics/compositor_frame_reporting_controller.h
index ef37fcda..339723e4 100644
--- a/cc/metrics/compositor_frame_reporting_controller.h
+++ b/cc/metrics/compositor_frame_reporting_controller.h
@@ -15,6 +15,10 @@
 #include "cc/metrics/compositor_frame_reporter.h"
 #include "cc/metrics/frame_sequence_tracker.h"
 
+namespace viz {
+struct FrameTimingDetails;
+}
+
 namespace cc {
 class RollingTimeDeltaHistory;
 
@@ -54,8 +58,9 @@
   virtual void DidActivate();
   virtual void DidSubmitCompositorFrame(uint32_t frame_token);
   virtual void DidNotProduceFrame();
-  virtual void DidPresentCompositorFrame(uint32_t frame_token,
-                                         base::TimeTicks presentation_time);
+  virtual void DidPresentCompositorFrame(
+      uint32_t frame_token,
+      const viz::FrameTimingDetails& details);
 
   virtual void AddActiveTracker(FrameSequenceTrackerType type);
   virtual void RemoveActiveTracker(FrameSequenceTrackerType type);
diff --git a/cc/metrics/compositor_frame_reporting_controller_unittest.cc b/cc/metrics/compositor_frame_reporting_controller_unittest.cc
index e12ba768..19b125c 100644
--- a/cc/metrics/compositor_frame_reporting_controller_unittest.cc
+++ b/cc/metrics/compositor_frame_reporting_controller_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/macros.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "components/viz/common/frame_timing_details.h"
 #include "components/viz/common/quads/compositor_frame_metadata.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -93,8 +94,9 @@
   void SimulatePresentCompositorFrame() {
     ++next_token_;
     SimulateSubmitCompositorFrame(*next_token_);
-    reporting_controller_.DidPresentCompositorFrame(*next_token_,
-                                                    base::TimeTicks::Now());
+    viz::FrameTimingDetails details = {};
+    details.presentation_feedback.timestamp = base::TimeTicks::Now();
+    reporting_controller_.DidPresentCompositorFrame(*next_token_, details);
   }
 
  protected:
diff --git a/cc/metrics/compositor_timing_history.cc b/cc/metrics/compositor_timing_history.cc
index 0e478f8..7a905855 100644
--- a/cc/metrics/compositor_timing_history.cc
+++ b/cc/metrics/compositor_timing_history.cc
@@ -1062,9 +1062,9 @@
 
 void CompositorTimingHistory::DidPresentCompositorFrame(
     uint32_t frame_token,
-    base::TimeTicks presentation_time) {
-  compositor_frame_reporting_controller_->DidPresentCompositorFrame(
-      frame_token, presentation_time);
+    const viz::FrameTimingDetails& details) {
+  compositor_frame_reporting_controller_->DidPresentCompositorFrame(frame_token,
+                                                                    details);
 }
 
 void CompositorTimingHistory::SetTreePriority(TreePriority priority) {
diff --git a/cc/metrics/compositor_timing_history.h b/cc/metrics/compositor_timing_history.h
index 8f83b3be..e7fcd5d 100644
--- a/cc/metrics/compositor_timing_history.h
+++ b/cc/metrics/compositor_timing_history.h
@@ -18,6 +18,10 @@
 }  // namespace trace_event
 }  // namespace base
 
+namespace viz {
+struct FrameTimingDetails;
+}
+
 namespace cc {
 
 class CompositorFrameReportingController;
@@ -92,7 +96,7 @@
   void DidNotProduceFrame();
   void DidReceiveCompositorFrameAck();
   void DidPresentCompositorFrame(uint32_t frame_token,
-                                 base::TimeTicks presentation_time);
+                                 const viz::FrameTimingDetails& details);
   void WillInvalidateOnImplSide();
   void SetTreePriority(TreePriority priority);
 
diff --git a/cc/mojo_embedder/async_layer_tree_frame_sink.cc b/cc/mojo_embedder/async_layer_tree_frame_sink.cc
index c66fe89..058dd878 100644
--- a/cc/mojo_embedder/async_layer_tree_frame_sink.cc
+++ b/cc/mojo_embedder/async_layer_tree_frame_sink.cc
@@ -292,8 +292,7 @@
     const viz::BeginFrameArgs& args,
     const viz::FrameTimingDetailsMap& timing_details) {
   for (const auto& pair : timing_details) {
-    client_->DidPresentCompositorFrame(pair.first,
-                                       pair.second.presentation_feedback);
+    client_->DidPresentCompositorFrame(pair.first, pair.second);
   }
 
   DCHECK_LE(pipeline_reporting_frame_times_.size(), 25u);
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc
index 6a14640..8cd62e94 100644
--- a/cc/scheduler/scheduler.cc
+++ b/cc/scheduler/scheduler.cc
@@ -196,10 +196,10 @@
   state_machine_.DidPrepareTiles();
 }
 
-void Scheduler::DidPresentCompositorFrame(uint32_t frame_token,
-                                          base::TimeTicks presentation_time) {
-  compositor_timing_history_->DidPresentCompositorFrame(frame_token,
-                                                        presentation_time);
+void Scheduler::DidPresentCompositorFrame(
+    uint32_t frame_token,
+    const viz::FrameTimingDetails& details) {
+  compositor_timing_history_->DidPresentCompositorFrame(frame_token, details);
 }
 
 void Scheduler::DidLoseLayerTreeFrameSink() {
diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h
index 6168d88..6b2620f 100644
--- a/cc/scheduler/scheduler.h
+++ b/cc/scheduler/scheduler.h
@@ -27,6 +27,10 @@
 class SingleThreadTaskRunner;
 }
 
+namespace viz {
+struct FrameTimingDetails;
+}
+
 namespace cc {
 
 class CompositorTimingHistory;
@@ -182,7 +186,7 @@
   // |DidPresentCompositorFrame| is called when the renderer receives
   // presentation feedback.
   void DidPresentCompositorFrame(uint32_t frame_token,
-                                 base::TimeTicks presentation_time);
+                                 const viz::FrameTimingDetails& details);
 
   void DidLoseLayerTreeFrameSink();
   void DidCreateAndInitializeLayerTreeFrameSink();
diff --git a/cc/test/fake_compositor_frame_reporting_controller.cc b/cc/test/fake_compositor_frame_reporting_controller.cc
index daa86626..1b8daa2a 100644
--- a/cc/test/fake_compositor_frame_reporting_controller.cc
+++ b/cc/test/fake_compositor_frame_reporting_controller.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "cc/test/fake_compositor_frame_reporting_controller.h"
+#include "components/viz/common/frame_timing_details.h"
 
 namespace cc {
 FakeCompositorFrameReportingController::FakeCompositorFrameReportingController(
@@ -48,11 +49,14 @@
 void FakeCompositorFrameReportingController::DidSubmitCompositorFrame(
     uint32_t frame_token) {
   CompositorFrameReportingController::DidSubmitCompositorFrame(frame_token);
-  CompositorFrameReportingController::DidPresentCompositorFrame(
-      frame_token, base::TimeTicks::Now());
+
+  viz::FrameTimingDetails details;
+  details.presentation_feedback.timestamp = base::TimeTicks::Now();
+  CompositorFrameReportingController::DidPresentCompositorFrame(frame_token,
+                                                                details);
 }
 
 void FakeCompositorFrameReportingController::DidPresentCompositorFrame(
     uint32_t frame_token,
-    base::TimeTicks presentation_time) {}
+    const viz::FrameTimingDetails& details) {}
 }  // namespace cc
diff --git a/cc/test/fake_compositor_frame_reporting_controller.h b/cc/test/fake_compositor_frame_reporting_controller.h
index 57176a1..1a28bbb15 100644
--- a/cc/test/fake_compositor_frame_reporting_controller.h
+++ b/cc/test/fake_compositor_frame_reporting_controller.h
@@ -7,6 +7,10 @@
 
 #include "cc/metrics/compositor_frame_reporting_controller.h"
 
+namespace viz {
+struct FrameTimingDetails;
+}
+
 namespace cc {
 // This class is to be used for testing, during cases where the DCHECKs won't
 // hold due to testing only a portion of the compositor pipeline. This class
@@ -30,8 +34,9 @@
   void WillActivate() override;
   void DidActivate() override;
   void DidSubmitCompositorFrame(uint32_t frame_token) override;
-  void DidPresentCompositorFrame(uint32_t frame_token,
-                                 base::TimeTicks presentation_time) override;
+  void DidPresentCompositorFrame(
+      uint32_t frame_token,
+      const viz::FrameTimingDetails& details) override;
 };
 }  // namespace cc
 
diff --git a/cc/test/fake_layer_tree_frame_sink_client.h b/cc/test/fake_layer_tree_frame_sink_client.h
index b415f2e..b429ba3ab 100644
--- a/cc/test/fake_layer_tree_frame_sink_client.h
+++ b/cc/test/fake_layer_tree_frame_sink_client.h
@@ -9,6 +9,10 @@
 
 #include "cc/trees/managed_memory_policy.h"
 
+namespace viz {
+struct FrameTimingDetails;
+}
+
 namespace cc {
 
 class FakeLayerTreeFrameSinkClient : public LayerTreeFrameSinkClient {
@@ -19,8 +23,8 @@
   base::Optional<viz::HitTestRegionList> BuildHitTestData() override;
   void DidReceiveCompositorFrameAck() override;
   void DidPresentCompositorFrame(
-      uint32_t presentation_token,
-      const gfx::PresentationFeedback& feedback) override {}
+      uint32_t frame_token,
+      const viz::FrameTimingDetails& details) override {}
   void ReclaimResources(
       const std::vector<viz::ReturnedResource>& resources) override {}
   void DidLoseLayerTreeFrameSink() override;
diff --git a/cc/test/fake_layer_tree_host_impl_client.h b/cc/test/fake_layer_tree_host_impl_client.h
index 0f8b96c6..1dd44c8 100644
--- a/cc/test/fake_layer_tree_host_impl_client.h
+++ b/cc/test/fake_layer_tree_host_impl_client.h
@@ -8,6 +8,10 @@
 #include "cc/trees/layer_tree_host_impl.h"
 #include "components/viz/common/frame_sinks/begin_frame_args.h"
 
+namespace viz {
+struct FrameTimingDetails;
+}
+
 namespace cc {
 
 class FakeLayerTreeHostImplClient : public LayerTreeHostImplClient {
@@ -43,7 +47,7 @@
   void DidPresentCompositorFrameOnImplThread(
       uint32_t frame_token,
       std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
-      const gfx::PresentationFeedback& feedback) override {}
+      const viz::FrameTimingDetails& details) override {}
 
   void NotifyAnimationWorkletStateChange(AnimationWorkletMutationState state,
                                          ElementListType tree_type) override {}
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index 5df7f28..ebc3206d 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -40,6 +40,7 @@
 #include "cc/trees/proxy_main.h"
 #include "cc/trees/single_thread_proxy.h"
 #include "components/ukm/test_ukm_recorder.h"
+#include "components/viz/common/frame_timing_details.h"
 #include "components/viz/service/display/skia_output_surface.h"
 #include "components/viz/test/begin_frame_args_test.h"
 #include "components/viz/test/fake_output_surface.h"
@@ -356,10 +357,10 @@
 
   void DidPresentCompositorFrame(
       uint32_t presentation_token,
-      const gfx::PresentationFeedback& feedback) override {
-    LayerTreeHostImpl::DidPresentCompositorFrame(presentation_token, feedback);
-    test_hooks_->DidReceivePresentationTimeOnThread(this, presentation_token,
-                                                    feedback);
+      const viz::FrameTimingDetails& details) override {
+    LayerTreeHostImpl::DidPresentCompositorFrame(presentation_token, details);
+    test_hooks_->DidReceivePresentationTimeOnThread(
+        this, presentation_token, details.presentation_feedback);
   }
   AnimationHost* animation_host() const {
     return static_cast<AnimationHost*>(mutator_host());
diff --git a/cc/test/test_layer_tree_frame_sink.cc b/cc/test/test_layer_tree_frame_sink.cc
index a6a3631..2a205ca 100644
--- a/cc/test/test_layer_tree_frame_sink.cc
+++ b/cc/test/test_layer_tree_frame_sink.cc
@@ -229,8 +229,7 @@
     const viz::BeginFrameArgs& args,
     const viz::FrameTimingDetailsMap& timing_details) {
   for (const auto& pair : timing_details)
-    client_->DidPresentCompositorFrame(pair.first,
-                                       pair.second.presentation_feedback);
+    client_->DidPresentCompositorFrame(pair.first, pair.second);
   external_begin_frame_source_.OnBeginFrame(args);
 }
 
diff --git a/cc/trees/layer_tree_frame_sink_client.h b/cc/trees/layer_tree_frame_sink_client.h
index 50848593..e56d9c56 100644
--- a/cc/trees/layer_tree_frame_sink_client.h
+++ b/cc/trees/layer_tree_frame_sink_client.h
@@ -15,12 +15,12 @@
 #include "ui/gfx/geometry/rect.h"
 
 namespace gfx {
-struct PresentationFeedback;
 class Transform;
 }
 
 namespace viz {
 class BeginFrameSource;
+struct FrameTimingDetails;
 struct HitTestRegionList;
 }
 
@@ -57,11 +57,10 @@
   // so that frames are submitted only at the rate it can handle them.
   virtual void DidReceiveCompositorFrameAck() = 0;
 
-  // See ui/gfx/presentation_feedback.h for details on args. |time| is always
-  // non-zero.
+  // See components/viz/common/frame_timing_details.h for details on args.
   virtual void DidPresentCompositorFrame(
-      uint32_t presentation_token,
-      const gfx::PresentationFeedback& feedback) = 0;
+      uint32_t frame_token,
+      const viz::FrameTimingDetails& details) = 0;
 
   // The LayerTreeFrameSink is lost when the viz::ContextProviders held by it
   // encounter an error. In this case the LayerTreeFrameSink (and the
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 4058342..fd4e8b4 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -92,6 +92,7 @@
 #include "components/viz/common/features.h"
 #include "components/viz/common/frame_sinks/copy_output_request.h"
 #include "components/viz/common/frame_sinks/delay_based_time_source.h"
+#include "components/viz/common/frame_timing_details.h"
 #include "components/viz/common/hit_test/hit_test_region_list.h"
 #include "components/viz/common/quads/compositor_frame.h"
 #include "components/viz/common/quads/compositor_frame_metadata.h"
@@ -117,7 +118,6 @@
 #include "ui/gfx/geometry/scroll_offset.h"
 #include "ui/gfx/geometry/size_conversions.h"
 #include "ui/gfx/geometry/vector2d_conversions.h"
-#include "ui/gfx/presentation_feedback.h"
 #include "ui/gfx/skia_util.h"
 
 namespace cc {
@@ -1982,21 +1982,23 @@
 
 void LayerTreeHostImpl::DidPresentCompositorFrame(
     uint32_t frame_token,
-    const gfx::PresentationFeedback& feedback) {
-  frame_trackers_.NotifyFramePresented(frame_token, feedback);
+    const viz::FrameTimingDetails& details) {
+  frame_trackers_.NotifyFramePresented(frame_token,
+                                       details.presentation_feedback);
   PresentationTimeCallbackBuffer::PendingCallbacks activated =
       presentation_time_callbacks_.PopPendingCallbacks(frame_token);
 
   // Update compositor frame latency and smoothness stats only for frames
   // that caused on-screen damage.
   if (!activated.frame_time.is_null()) {
-    frame_metrics_.AddFrameDisplayed(activated.frame_time, feedback.timestamp);
+    frame_metrics_.AddFrameDisplayed(activated.frame_time,
+                                     details.presentation_feedback.timestamp);
   }
 
   // Send all the main-thread callbacks to the client in one batch. The client
   // is in charge of posting them to the main thread.
   client_->DidPresentCompositorFrameOnImplThread(
-      frame_token, std::move(activated.main_thread_callbacks), feedback);
+      frame_token, std::move(activated.main_thread_callbacks), details);
 }
 
 void LayerTreeHostImpl::DidNotNeedBeginFrame() {
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index c6939a5f..f85ee235 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -68,6 +68,7 @@
 namespace viz {
 class CompositorFrame;
 class CompositorFrameMetadata;
+struct FrameTimingDetails;
 }  // namespace viz
 
 namespace cc {
@@ -159,7 +160,7 @@
   virtual void DidPresentCompositorFrameOnImplThread(
       uint32_t frame_token,
       std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
-      const gfx::PresentationFeedback& feedback) = 0;
+      const viz::FrameTimingDetails& details) = 0;
 
   // Returns whether the main-thread is expected to receive a BeginMainFrame.
   virtual bool IsBeginMainFrameExpected() = 0;
@@ -493,7 +494,7 @@
   void DidReceiveCompositorFrameAck() override;
   void DidPresentCompositorFrame(
       uint32_t frame_token,
-      const gfx::PresentationFeedback& feedback) override;
+      const viz::FrameTimingDetails& details) override;
   void ReclaimResources(
       const std::vector<viz::ReturnedResource>& resources) override;
   void SetMemoryPolicy(const ManagedMemoryPolicy& policy) override;
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 5383b3c5..b8e1373a 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -107,6 +107,10 @@
 using ::testing::_;
 using media::VideoFrame;
 
+namespace viz {
+struct FrameTimingDetails;
+}
+
 namespace cc {
 namespace {
 
@@ -237,7 +241,7 @@
   void DidPresentCompositorFrameOnImplThread(
       uint32_t frame_token,
       std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
-      const gfx::PresentationFeedback& feedback) override {}
+      const viz::FrameTimingDetails& details) override {}
   void NotifyAnimationWorkletStateChange(AnimationWorkletMutationState state,
                                          ElementListType tree_type) override {}
   void NotifyPaintWorkletStateChange(
diff --git a/cc/trees/proxy_impl.cc b/cc/trees/proxy_impl.cc
index ed8eb19..636f21d 100644
--- a/cc/trees/proxy_impl.cc
+++ b/cc/trees/proxy_impl.cc
@@ -26,10 +26,10 @@
 #include "cc/trees/render_frame_metadata_observer.h"
 #include "cc/trees/task_runner_provider.h"
 #include "components/viz/common/frame_sinks/delay_based_time_source.h"
+#include "components/viz/common/frame_timing_details.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "services/metrics/public/cpp/ukm_recorder.h"
-#include "ui/gfx/presentation_feedback.h"
 
 namespace cc {
 
@@ -500,13 +500,14 @@
 void ProxyImpl::DidPresentCompositorFrameOnImplThread(
     uint32_t frame_token,
     std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
-    const gfx::PresentationFeedback& feedback) {
+    const viz::FrameTimingDetails& details) {
   MainThreadTaskRunner()->PostTask(
-      FROM_HERE, base::BindOnce(&ProxyMain::DidPresentCompositorFrame,
-                                proxy_main_weak_ptr_, frame_token,
-                                std::move(callbacks), feedback));
+      FROM_HERE,
+      base::BindOnce(&ProxyMain::DidPresentCompositorFrame,
+                     proxy_main_weak_ptr_, frame_token, std::move(callbacks),
+                     details.presentation_feedback));
   if (scheduler_)
-    scheduler_->DidPresentCompositorFrame(frame_token, feedback.timestamp);
+    scheduler_->DidPresentCompositorFrame(frame_token, details);
 }
 
 void ProxyImpl::NotifyAnimationWorkletStateChange(
diff --git a/cc/trees/proxy_impl.h b/cc/trees/proxy_impl.h
index d8222df2..6320aab 100644
--- a/cc/trees/proxy_impl.h
+++ b/cc/trees/proxy_impl.h
@@ -14,6 +14,10 @@
 #include "cc/scheduler/scheduler.h"
 #include "cc/trees/layer_tree_host_impl.h"
 
+namespace viz {
+struct FrameTimingDetails;
+}
+
 namespace cc {
 class LayerTreeHost;
 class ProxyMain;
@@ -109,7 +113,7 @@
   void DidPresentCompositorFrameOnImplThread(
       uint32_t frame_token,
       std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
-      const gfx::PresentationFeedback& feedback) override;
+      const viz::FrameTimingDetails& details) override;
   void NotifyAnimationWorkletStateChange(
       AnimationWorkletMutationState state,
       ElementListType element_list_type) override;
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index e7ca5dc..11d8044 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -26,8 +26,8 @@
 #include "cc/trees/render_frame_metadata_observer.h"
 #include "cc/trees/scoped_abort_remaining_swap_promises.h"
 #include "components/viz/common/frame_sinks/delay_based_time_source.h"
+#include "components/viz/common/frame_timing_details.h"
 #include "components/viz/common/gpu/context_provider.h"
-#include "ui/gfx/presentation_feedback.h"
 
 namespace cc {
 
@@ -529,13 +529,12 @@
 void SingleThreadProxy::DidPresentCompositorFrameOnImplThread(
     uint32_t frame_token,
     std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
-    const gfx::PresentationFeedback& feedback) {
+    const viz::FrameTimingDetails& details) {
   layer_tree_host_->DidPresentCompositorFrame(frame_token, std::move(callbacks),
-                                              feedback);
+                                              details.presentation_feedback);
 
   if (scheduler_on_impl_thread_) {
-    scheduler_on_impl_thread_->DidPresentCompositorFrame(frame_token,
-                                                         feedback.timestamp);
+    scheduler_on_impl_thread_->DidPresentCompositorFrame(frame_token, details);
   }
 }
 
diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h
index fc5a266..3d40bfb 100644
--- a/cc/trees/single_thread_proxy.h
+++ b/cc/trees/single_thread_proxy.h
@@ -17,6 +17,7 @@
 
 namespace viz {
 class BeginFrameSource;
+struct FrameTimingDetails;
 }
 
 namespace cc {
@@ -130,7 +131,7 @@
   void DidPresentCompositorFrameOnImplThread(
       uint32_t frame_token,
       std::vector<LayerTreeHost::PresentationTimeCallback> callbacks,
-      const gfx::PresentationFeedback& feedback) override;
+      const viz::FrameTimingDetails& details) override;
   void NotifyAnimationWorkletStateChange(
       AnimationWorkletMutationState state,
       ElementListType element_list_type) override;
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 357d964..a3427977 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -407,6 +407,7 @@
     ":chrome_locale_config",
     ":photo_picker_aidl",
     ":resource_id_javagen",
+    ":sync_user_settings_enums_java",
     "//chrome:assist_ranker_prediction_enum_javagen",
     "//chrome:content_setting_javagen",
     "//chrome:content_settings_type_javagen",
@@ -607,6 +608,12 @@
   ]
 }
 
+java_cpp_enum("sync_user_settings_enums_java") {
+  sources = [
+    "//components/sync/driver/sync_user_settings.h",
+  ]
+}
+
 java_cpp_strings("chrome_android_java_switches_srcjar") {
   sources = [
     "//chrome/common/chrome_switches.cc",
@@ -2000,10 +2007,13 @@
     "//chrome/browser/profiling_host:profiling_host_javatests",
     "//chrome/browser/ui/android/widget:ui_widget_java_tests",
   ]
+
+  data_deps = [
+    "//testing/buildbot/filters:chrome_public_test_apk_filters",
+  ]
+
   if (enable_chrome_android_internal) {
-    data_deps = [
-      "//clank/build/bot/filters:chrome_public_test_apk_filters",
-    ]
+    data_deps += [ "//clank/build/bot/filters:chrome_public_test_apk_filters" ]
   }
   additional_apks = [
     "//chrome/android/webapk/libs/runtime_library/javatests/apk_with_webapk_service:apk_with_webapk_service",
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml
index 9f952911..d84c2170 100644
--- a/chrome/android/java/AndroidManifest.xml
+++ b/chrome/android/java/AndroidManifest.xml
@@ -1266,8 +1266,6 @@
         <receiver android:name="org.chromium.chrome.browser.send_tab_to_self.NotificationManager$TimeoutReceiver"
             android:exported="false"/>
 
-        <receiver android:name="org.chromium.chrome.browser.sharing.SharingNotificationUtil$ActionReceiver"
-            android:exported="false"/>
         <receiver android:name="org.chromium.chrome.browser.sharing.click_to_call.ClickToCallMessageHandler$TapReceiver"
             android:exported="false"/>
         <receiver android:name="org.chromium.chrome.browser.sharing.shared_clipboard.SharedClipboardMessageHandler$TapReceiver"
diff --git a/chrome/android/java/monochrome_public_bundle__base_bundle_module.AndroidManifest.expected b/chrome/android/java/monochrome_public_bundle__base_bundle_module.AndroidManifest.expected
index 7e5046b..e5cdbdc3 100644
--- a/chrome/android/java/monochrome_public_bundle__base_bundle_module.AndroidManifest.expected
+++ b/chrome/android/java/monochrome_public_bundle__base_bundle_module.AndroidManifest.expected
@@ -1354,9 +1354,6 @@
         android:name="org.chromium.chrome.browser.send_tab_to_self.NotificationManager$TimeoutReceiver"/>
     <receiver
         android:exported="false"
-        android:name="org.chromium.chrome.browser.sharing.SharingNotificationUtil$ActionReceiver"/>
-    <receiver
-        android:exported="false"
         android:name="org.chromium.chrome.browser.sharing.click_to_call.ClickToCallMessageHandler$TapReceiver"/>
     <receiver
         android:exported="false"
diff --git a/chrome/android/java/res/layout/omnibox_results_container.xml b/chrome/android/java/res/layout/omnibox_results_container.xml
index 2430af6f..8ecbe8a 100644
--- a/chrome/android/java/res/layout/omnibox_results_container.xml
+++ b/chrome/android/java/res/layout/omnibox_results_container.xml
@@ -8,4 +8,5 @@
     android:visibility="gone"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
+    android:descendantFocusability="blocksDescendants"
     />
diff --git a/chrome/android/java/res/layout/sharing_device_picker.xml b/chrome/android/java/res/layout/sharing_device_picker.xml
index 0bd6b40..c16f78a 100644
--- a/chrome/android/java/res/layout/sharing_device_picker.xml
+++ b/chrome/android/java/res/layout/sharing_device_picker.xml
@@ -47,7 +47,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:paddingBottom="32dp"
-        android:orientation="vertical">
+        android:orientation="vertical"
+        android:visibility="gone">
 
       <ImageView
           android:id="@+id/empty_state_image"
diff --git a/chrome/android/java/res_download/layout/download_manager_prefetch_item.xml b/chrome/android/java/res_download/layout/download_manager_prefetch_item.xml
index 102c447..f6d830a 100644
--- a/chrome/android/java/res_download/layout/download_manager_prefetch_item.xml
+++ b/chrome/android/java/res_download/layout/download_manager_prefetch_item.xml
@@ -32,11 +32,15 @@
         style="@style/AsyncImageView"
         tools:ignore="ContentDescription" />
 
-    <org.chromium.chrome.browser.download.home.view.SelectionView
-        android:id="@+id/selection"
-        style="@style/DownloadItemSelectionView"
+    <!-- Add a spacer so that even if the thumbnail is hidden the other elements
+         are still spaced correctly.  This view matches the padding of the
+         thumbnail. -->
+    <Space
+        android:layout_width="10dp"
+        android:layout_height="114dp"
         app:layout_column="0"
-        app:layout_row="0"/>
+        app:layout_row="0"
+        app:layout_rowSpan="4" />
 
     <Space
         android:layout_width="wrap_content"
@@ -107,4 +111,20 @@
             android:paddingTop="12dp"
             app:layout_column="3"
             app:layout_row="0" />
+
+    <!-- Wrap this in a FrameLayout so that if the thumbnail is hidden this view
+         does not negatively affect layout.  The FrameLayout spans the whole
+         parent so it will not impact the rest of the views. -->
+    <FrameLayout
+        android:layout_width="wrap_content"
+        android:layout_height="0dp"
+        app:layout_gravity="fill"
+        app:layout_column="0"
+        app:layout_row="0"
+        app:layout_columnSpan="4"
+        app:layout_rowSpan="4">
+        <org.chromium.chrome.browser.download.home.view.SelectionView
+            android:id="@+id/selection"
+            style="@style/DownloadItemSelectionView"/>
+    </FrameLayout>
 </android.support.v7.widget.GridLayout>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
index 9f0ac38..eb9b2b3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
@@ -904,8 +904,9 @@
         if (referrer == null) return ParallelRequestStatus.FAILURE_INVALID_REFERRER;
         if (policy < 0 || policy > ReferrerPolicy.LAST) policy = ReferrerPolicy.DEFAULT;
 
-        if (url.toString().equals("") || !isValid(url))
+        if (url.toString().equals("") || !isValid(url)) {
             return ParallelRequestStatus.FAILURE_INVALID_URL;
+        }
         if (!canDoParallelRequest(session, referrer)) {
             return ParallelRequestStatus.FAILURE_INVALID_REFERRER_FOR_SESSION;
         }
@@ -1141,20 +1142,16 @@
     }
 
     /**
-     * Notifies the application of a page load metric for a single metric.
+     * Creates a Bundle with a value for navigation start and the specified page load metric.
      *
-     * TODD(lizeb): Move this to a proper method in {@link CustomTabsCallback} once one is
-     * available.
-     *
-     * @param session Session identifier.
      * @param metricName Name of the page load metric.
      * @param navigationStartTick Absolute navigation start time, as TimeTicks taken from native.
      * @param offsetMs Offset in ms from navigationStart for the page load metric.
      *
-     * @return Whether the metric has been dispatched to the client.
+     * @return A Bundle containing navigation start and the page load metric.
      */
-    boolean notifySinglePageLoadMetric(CustomTabsSessionToken session, String metricName,
-            long navigationStartTick, long offsetMs) {
+    Bundle createBundleWithNavigationStartAndPageLoadMetric(
+            String metricName, long navigationStartTick, long offsetMs) {
         if (!mNativeTickOffsetUsComputed) {
             // Compute offset from time ticks to uptimeMillis.
             mNativeTickOffsetUsComputed = true;
@@ -1170,8 +1167,24 @@
         // SystemClock.uptimeMillis() value.
         args.putLong(PageLoadMetrics.NAVIGATION_START,
                 (navigationStartTick - mNativeTickOffsetUs) / 1000);
+        return args;
+    }
 
-        return notifyPageLoadMetrics(session, args);
+    /**
+     * Notifies the application of a page load metric for a single metric.
+     *
+     * @param session Session identifier.
+     * @param metricName Name of the page load metric.
+     * @param navigationStartTick Absolute navigation start time, as TimeTicks taken from native.
+     * @param offsetMs Offset in ms from navigationStart for the page load metric.
+     *
+     * @return Whether the metric has been dispatched to the client.
+     */
+    boolean notifySinglePageLoadMetric(CustomTabsSessionToken session, String metricName,
+            long navigationStartTick, long offsetMs) {
+        return notifyPageLoadMetrics(session,
+                createBundleWithNavigationStartAndPageLoadMetric(
+                        metricName, navigationStartTick, offsetMs));
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PageLoadMetricsObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PageLoadMetricsObserver.java
index 1301ff5..63fb448 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PageLoadMetricsObserver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PageLoadMetricsObserver.java
@@ -53,6 +53,19 @@
     }
 
     @Override
+    public void onLargestContentfulPaint(WebContents webContents, long navigationId,
+            long navigationStartTick, long largestContentfulPaintMs,
+            long largestContentfulPaintSize) {
+        if (webContents != mTab.getWebContents()) return;
+
+        Bundle args = mConnection.createBundleWithNavigationStartAndPageLoadMetric(
+                PageLoadMetrics.LARGEST_CONTENTFUL_PAINT, navigationStartTick,
+                largestContentfulPaintMs);
+        args.putLong(PageLoadMetrics.LARGEST_CONTENTFUL_PAINT_SIZE, largestContentfulPaintSize);
+        mConnection.notifyPageLoadMetrics(mSession, args);
+    }
+
+    @Override
     public void onLoadEventStart(WebContents webContents, long navigationId,
             long navigationStartTick, long loadEventStartMs) {
         if (webContents != mTab.getWebContents()) return;
@@ -77,4 +90,26 @@
         args.putLong(PageLoadMetrics.SEND_END, sendEndMs);
         mConnection.notifyPageLoadMetrics(mSession, args);
     }
+
+    @Override
+    public void onFirstInputDelay(
+            WebContents webContents, long navigationId, long firstInputDelayMs) {
+        if (webContents != mTab.getWebContents()) return;
+
+        Bundle args = new Bundle();
+        args.putLong(PageLoadMetrics.FIRST_INPUT_DELAY, firstInputDelayMs);
+        mConnection.notifyPageLoadMetrics(mSession, args);
+    }
+
+    @Override
+    public void onLayoutShiftScore(WebContents webContents, long navigationId,
+            float layoutShiftScoreBeforeInputOrScroll, float layoutShiftScoreOverall) {
+        if (webContents != mTab.getWebContents()) return;
+
+        Bundle args = new Bundle();
+        args.putFloat(PageLoadMetrics.LAYOUT_SHIFT_SCORE, layoutShiftScoreOverall);
+        args.putFloat(PageLoadMetrics.LAYOUT_SHIFT_SCORE_BEFORE_INPUT_OR_SCROLL,
+                layoutShiftScoreBeforeInputOrScroll);
+        mConnection.notifyPageLoadMetrics(mSession, args);
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/OfflineItemViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/OfflineItemViewHolder.java
index 63b63706b..9e0338a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/OfflineItemViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/OfflineItemViewHolder.java
@@ -99,14 +99,20 @@
 
         // Push 'thumbnail' state.
         if (mThumbnail != null) {
-            mThumbnail.setImageResizer(
-                    new BitmapResizer(mThumbnail, Filters.fromOfflineItem(offlineItem)));
-            mThumbnail.setAsyncImageDrawable((consumer, width, height) -> {
-                return properties.get(ListProperties.PROVIDER_VISUALS)
-                        .getVisuals(offlineItem, width, height, (id, visuals) -> {
-                            consumer.onResult(onThumbnailRetrieved(visuals));
-                        });
-            }, offlineItem.id);
+            if (offlineItem.ignoreVisuals) {
+                mThumbnail.setVisibility(View.GONE);
+                mThumbnail.setImageDrawable(null);
+            } else {
+                mThumbnail.setVisibility(View.VISIBLE);
+                mThumbnail.setImageResizer(
+                        new BitmapResizer(mThumbnail, Filters.fromOfflineItem(offlineItem)));
+                mThumbnail.setAsyncImageDrawable((consumer, width, height) -> {
+                    return properties.get(ListProperties.PROVIDER_VISUALS)
+                            .getVisuals(offlineItem, width, height, (id, visuals) -> {
+                                consumer.onResult(onThumbnailRetrieved(visuals));
+                            });
+                }, offlineItem.id);
+            }
         }
 
         mCanRename = mRenameCallback != null && offlineItem.canRename;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorNotificationBridgeUi.java b/chrome/android/java/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorNotificationBridgeUi.java
index da5a8ee..0cd0833 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorNotificationBridgeUi.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/items/OfflineContentAggregatorNotificationBridgeUi.java
@@ -182,6 +182,7 @@
     }
 
     private boolean needsVisualsForUi(OfflineItem item) {
+        if (item.ignoreVisuals) return false;
         switch (item.state) {
             case OfflineItemState.IN_PROGRESS:
             case OfflineItemState.PENDING:
@@ -197,6 +198,7 @@
     }
 
     private boolean shouldCacheVisuals(OfflineItem item) {
+        if (item.ignoreVisuals) return false;
         switch (item.state) {
             case OfflineItemState.IN_PROGRESS:
             case OfflineItemState.PENDING:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunSignInProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunSignInProcessor.java
index a6662256..bc04fbe 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunSignInProcessor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunSignInProcessor.java
@@ -12,6 +12,7 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.browser.ChromeFeatureList;
+import org.chromium.chrome.browser.SyncFirstSetupCompleteSource;
 import org.chromium.chrome.browser.preferences.PreferencesLauncher;
 import org.chromium.chrome.browser.preferences.sync.SyncAndServicesPreferences;
 import org.chromium.chrome.browser.signin.IdentityServicesProvider;
@@ -83,7 +84,8 @@
                     openSignInSettings(activity);
                 } else if (ChromeFeatureList.isEnabled(
                                    ChromeFeatureList.SYNC_MANUAL_START_ANDROID)) {
-                    ProfileSyncService.get().setFirstSetupComplete();
+                    ProfileSyncService.get().setFirstSetupComplete(
+                            SyncFirstSetupCompleteSource.BASIC_FLOW);
                 }
                 setFirstRunFlowSignInComplete(true);
             }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/PageLoadMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/PageLoadMetrics.java
index 9a79212..e85a64a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/PageLoadMetrics.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/PageLoadMetrics.java
@@ -17,8 +17,14 @@
  */
 public class PageLoadMetrics {
     public static final String FIRST_CONTENTFUL_PAINT = "firstContentfulPaint";
+    public static final String LARGEST_CONTENTFUL_PAINT = "largestContentfulPaint";
+    public static final String LARGEST_CONTENTFUL_PAINT_SIZE = "largestContentfulPaintSize";
     public static final String NAVIGATION_START = "navigationStart";
     public static final String LOAD_EVENT_START = "loadEventStart";
+    public static final String FIRST_INPUT_DELAY = "firstInputDelay";
+    public static final String LAYOUT_SHIFT_SCORE = "layoutShiftScore";
+    public static final String LAYOUT_SHIFT_SCORE_BEFORE_INPUT_OR_SCROLL =
+            "layoutShiftScoreBeforeInputOrScroll";
     public static final String DOMAIN_LOOKUP_START = "domainLookupStart";
     public static final String DOMAIN_LOOKUP_END = "domainLookupEnd";
     public static final String CONNECT_START = "connectStart";
@@ -71,6 +77,19 @@
                 long navigationStartTick, long firstContentfulPaintMs) {}
 
         /**
+         * Called when the largest contentful paint page load metric is available.
+         *
+         * @param webContents the WebContents this metrics is related to.
+         * @param navigationId the unique id of a navigation this metrics is related to.
+         * @param navigationStartTick Absolute navigation start time, as TimeTicks.
+         * @param largestContentfulPaintMs Time to largest contentful paint from navigation start.
+         * @param largestContentfulPaintSize Size of largest contentful paint, in CSS pixels.
+         */
+        default void onLargestContentfulPaint(WebContents webContents, long navigationId,
+                long navigationStartTick, long largestContentfulPaintMs,
+                long largestContentfulPaintSize) {}
+
+        /**
          * Called when the first meaningful paint page load metric is available. See
          * FirstMeaningfulPaintDetector.cpp
          *
@@ -83,6 +102,16 @@
                 long navigationStartTick, long firstMeaningfulPaintMs) {}
 
         /**
+         * Called when the first input delay page load metric is available.
+         *
+         * @param webContents the WebContents this metrics is related to.
+         * @param navigationId the unique id of a navigation this metrics is related to.
+         * @param firstInputDelayMs First input delay.
+         */
+        default void onFirstInputDelay(
+                WebContents webContents, long navigationId, long firstInputDelayMs) {}
+
+        /**
          * Called when the load event start metric is available.
          *
          * @param webContents the WebContents this metrics is related to.
@@ -105,6 +134,19 @@
         default void onLoadedMainResource(WebContents webContents, long navigationId,
                 long dnsStartMs, long dnsEndMs, long connectStartMs, long connectEndMs,
                 long requestStartMs, long sendStartMs, long sendEndMs) {}
+
+        /**
+         * Called when the layout shift score is available.
+         *
+         * @param webContents the WebContents this metrics is related to.
+         * @param navigationId the unique id of a navigation this metrics is related to.
+         * @param layoutShiftScoreBeforeInputOrScroll the cumulative layout shift score, before user
+         *         input or scroll.
+         * @param layoutShiftScoreOverall the cumulative layout shift score over the lifetime of the
+         *         web page.
+         */
+        default void onLayoutShiftScore(WebContents webContents, long navigationId,
+                float layoutShiftScoreBeforeInputOrScroll, float layoutShiftScoreOverall) {}
     }
 
     private static ObserverList<Observer> sObservers;
@@ -155,6 +197,18 @@
     }
 
     @CalledByNative
+    static void onLargestContentfulPaint(WebContents webContents, long navigationId,
+            long navigationStartTick, long largestContentfulPaintMs,
+            long largestContentfulPaintSize) {
+        ThreadUtils.assertOnUiThread();
+        if (sObservers == null) return;
+        for (Observer observer : sObservers) {
+            observer.onLargestContentfulPaint(webContents, navigationId, navigationStartTick,
+                    largestContentfulPaintMs, largestContentfulPaintSize);
+        }
+    }
+
+    @CalledByNative
     static void onFirstMeaningfulPaint(WebContents webContents, long navigationId,
             long navigationStartTick, long firstMeaningfulPaintMs) {
         ThreadUtils.assertOnUiThread();
@@ -166,6 +220,16 @@
     }
 
     @CalledByNative
+    static void onFirstInputDelay(
+            WebContents webContents, long navigationId, long firstInputDelayMs) {
+        ThreadUtils.assertOnUiThread();
+        if (sObservers == null) return;
+        for (Observer observer : sObservers) {
+            observer.onFirstInputDelay(webContents, navigationId, firstInputDelayMs);
+        }
+    }
+
+    @CalledByNative
     static void onLoadEventStart(WebContents webContents, long navigationId,
             long navigationStartTick, long loadEventStartMs) {
         ThreadUtils.assertOnUiThread();
@@ -188,5 +252,16 @@
         }
     }
 
+    @CalledByNative
+    static void onLayoutShiftScore(WebContents webContents, long navigationId,
+            float layoutShiftScoreBeforeInputOrScroll, float layoutShiftScoreOverall) {
+        ThreadUtils.assertOnUiThread();
+        if (sObservers == null) return;
+        for (Observer observer : sObservers) {
+            observer.onLayoutShiftScore(webContents, navigationId,
+                    layoutShiftScoreBeforeInputOrScroll, layoutShiftScoreOverall);
+        }
+    }
+
     private PageLoadMetrics() {}
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java
index 3338dd4..aa67b56 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java
@@ -91,7 +91,7 @@
             ActionType.DOWNLOAD_PAGE_RESUME, ActionType.DOWNLOAD_PAGE_CANCEL,
             ActionType.CONTENT_SUGGESTION_SETTINGS, ActionType.WEB_APP_ACTION_SHARE,
             ActionType.WEB_APP_ACTION_OPEN_IN_CHROME,
-            ActionType.OFFLINE_CONTENT_SUGGESTION_SETTINGS})
+            ActionType.OFFLINE_CONTENT_SUGGESTION_SETTINGS, ActionType.SHARING_TRY_AGAIN})
     @Retention(RetentionPolicy.SOURCE)
     public @interface ActionType {
         int UNKNOWN = -1;
@@ -116,7 +116,7 @@
         // Setting button in offline content suggestion notification.
         int OFFLINE_CONTENT_SUGGESTION_SETTINGS = 9;
         // Dismiss button on sharing notification.
-        int SHARING_DISMISS = 10;
+        // int SHARING_DISMISS = 10; deprecated
         // Try again button on sharing error notification.
         int SHARING_TRY_AGAIN = 11;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java
index 8084cab4..b98b8d6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java
@@ -7,6 +7,7 @@
 import android.os.Bundle;
 import android.support.v4.app.Fragment;
 import android.text.InputType;
+import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -18,18 +19,19 @@
 import android.widget.ImageButton;
 
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.widget.ChromeTextInputLayout;
 import org.chromium.ui.widget.Toast;
 
 /**
  * Password entry editor that allows editing passwords stored in Chrome.
  */
-public class PasswordEntryEditor extends Fragment {
 
+public class PasswordEntryEditor extends Fragment {
     private EditText mSiteText;
     private EditText mUsernameText;
     private EditText mPasswordText;
     private ImageButton mViewPasswordButton;
-
+    private ChromeTextInputLayout mPasswordLabel;
     private boolean mViewButtonPressed;
     static final String VIEW_BUTTON_PRESSED = "viewButtonPressed";
     public static final String CREDENTIAL_URL = "credentialUrl";
@@ -50,6 +52,7 @@
         mSiteText = (EditText) view.findViewById(R.id.site_edit);
         mUsernameText = (EditText) view.findViewById(R.id.username_edit);
         mPasswordText = (EditText) view.findViewById(R.id.password_edit);
+        mPasswordLabel = (ChromeTextInputLayout) view.findViewById(R.id.password_label);
         mViewPasswordButton = view.findViewById(R.id.password_entry_editor_view_password);
         mSiteText.setText(getArguments().getString(CREDENTIAL_URL));
         mUsernameText.setText(getArguments().getString(CREDENTIAL_NAME));
@@ -80,7 +83,7 @@
     public boolean onOptionsItemSelected(MenuItem item) {
         int id = item.getItemId();
         if (id == R.id.action_save_edited_password) {
-            getActivity().finish();
+            saveChanges();
             return true;
         }
         return super.onOptionsItemSelected(item);
@@ -125,6 +128,17 @@
         }
     }
 
+    private void saveChanges() {
+        String password = mPasswordText.getText().toString();
+        if (TextUtils.isEmpty(password)) {
+            mPasswordLabel.setError(getContext().getString(
+                    R.string.pref_edit_dialog_field_required_validation_message));
+        } else {
+            // TODO(crbug.com/377410): Save the changes if everything was ok.
+            getActivity().finish();
+        }
+    }
+
     @Override
     public void onSaveInstanceState(Bundle savedInstanceState) {
         super.onSaveInstanceState(savedInstanceState);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SyncAndServicesPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SyncAndServicesPreferences.java
index 11f2356..f441d1d3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SyncAndServicesPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/sync/SyncAndServicesPreferences.java
@@ -37,6 +37,7 @@
 import org.chromium.base.task.PostTask;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
+import org.chromium.chrome.browser.SyncFirstSetupCompleteSource;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial;
 import org.chromium.chrome.browser.help.HelpAndFeedback;
 import org.chromium.chrome.browser.invalidation.InvalidationController;
@@ -170,6 +171,7 @@
             assert actionBar != null;
             actionBar.setHomeActionContentDescription(
                     R.string.prefs_sync_and_services_content_description);
+            RecordUserAction.record("Signin_Signin_ShowAdvancedSyncSettings");
         }
 
         PreferenceUtils.addPreferencesFromResource(this, R.xml.sync_and_services_preferences);
@@ -332,7 +334,8 @@
                     && wasSigninFlowInterrupted()) {
                 // This flow should only be reached when user toggles sync on.
                 assert (boolean) newValue;
-                mProfileSyncService.setFirstSetupComplete();
+                mProfileSyncService.setFirstSetupComplete(
+                        SyncFirstSetupCompleteSource.ADVANCED_FLOW_INTERRUPTED_TURN_SYNC_ON);
             }
             PostTask.postTask(UiThreadTaskTraits.DEFAULT, this::updatePreferences);
         } else if (PREF_SEARCH_SUGGESTIONS.equals(key)) {
@@ -637,7 +640,8 @@
             // error again), but turn sync off.
             assert !mSyncRequested.isChecked();
             SyncPreferenceUtils.enableSync(false);
-            mProfileSyncService.setFirstSetupComplete();
+            mProfileSyncService.setFirstSetupComplete(
+                    SyncFirstSetupCompleteSource.ADVANCED_FLOW_INTERRUPTED_LEAVE_SYNC_OFF);
         }
         if (!mIsFromSigninScreen) return false; // Let parent activity handle it.
         showCancelSyncDialog();
@@ -654,7 +658,8 @@
     private void confirmSettings() {
         RecordUserAction.record("Signin_Signin_ConfirmAdvancedSyncSettings");
         if (ChromeFeatureList.isEnabled(ChromeFeatureList.SYNC_MANUAL_START_ANDROID)) {
-            ProfileSyncService.get().setFirstSetupComplete();
+            ProfileSyncService.get().setFirstSetupComplete(
+                    SyncFirstSetupCompleteSource.ADVANCED_FLOW_CONFIRM);
         }
         UnifiedConsentServiceBridge.recordSyncSetupDataTypesHistogram();
         // Settings will be applied when mSyncSetupInProgressHandle is released in onDestroy.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sharing/SharingNotificationUtil.java b/chrome/android/java/src/org/chromium/chrome/browser/sharing/SharingNotificationUtil.java
index 5cbd6ae..2fb7433 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sharing/SharingNotificationUtil.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sharing/SharingNotificationUtil.java
@@ -5,10 +5,7 @@
 package org.chromium.chrome.browser.sharing;
 
 import android.app.Notification;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.Intent;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -29,42 +26,13 @@
 import org.chromium.chrome.browser.notifications.PendingIntentProvider;
 import org.chromium.chrome.browser.notifications.channels.ChannelDefinitions;
 
-import java.util.HashSet;
-
 /**
  * Provides common functionality for handling sharing notifications.
  */
 public final class SharingNotificationUtil {
-    private static final String EXTRA_NOTIFICATION_TAG = "notification_tag";
-    private static final String EXTRA_NOTIFICATION_ID = "notification_id";
-    private static final String EXTRA_NOTIFICATION_TOKEN = "notification_token";
-    private static final int REQUEST_CODE_DISMISS = 100;
-
     // TODO(himanshujaju) - We have only two small icons, one for error and one for non error. We
     // could avoid passing them around.
 
-    private static HashSet<Integer> sDismissedSendingNotifications = new HashSet<>();
-    private static int sSendingNotificationCount;
-
-    /**
-     * Handles the action of a notification.
-     */
-    public static final class ActionReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            // Currently only dismiss is supported.
-            String tag = intent.getStringExtra(EXTRA_NOTIFICATION_TAG);
-            int id = intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1);
-            int token = intent.getIntExtra(EXTRA_NOTIFICATION_TOKEN, -1);
-            if (tag == null || id == -1 || token == -1) {
-                return;
-            }
-
-            new NotificationManagerProxyImpl(context).cancel(tag, id);
-            sDismissedSendingNotifications.add(token);
-        }
-    }
-
     /**
      * Shows a notification with a configuration common to all sharing notifications.
      *
@@ -120,25 +88,13 @@
      * @param group The notification group.
      * @param id The notification id.
      * @param targetName The name of target device
-     * @return token of notification created to be used to call {@link #showSendErrorNotification}
      */
-    public static int showSendingNotification(
+    public static void showSendingNotification(
             @SystemNotificationType int type, String group, int id, String targetName) {
-        int token = sSendingNotificationCount;
-        sSendingNotificationCount++;
-
         Context context = ContextUtils.getApplicationContext();
         Resources resources = context.getResources();
-        PendingIntentProvider dismissIntent =
-                PendingIntentProvider.getBroadcast(context, REQUEST_CODE_DISMISS,
-                        new Intent(context, ActionReceiver.class)
-                                .putExtra(EXTRA_NOTIFICATION_TAG, group)
-                                .putExtra(EXTRA_NOTIFICATION_ID, id)
-                                .putExtra(EXTRA_NOTIFICATION_TOKEN, token),
-                        PendingIntent.FLAG_UPDATE_CURRENT);
         String contentTitle =
                 resources.getString(R.string.sharing_sending_notification_title, targetName);
-        String dismissTitle = resources.getString(R.string.sharing_dismiss_action);
         ChromeNotificationBuilder builder =
                 NotificationBuilderFactory
                         .createChromeNotificationBuilder(/*preferCompat=*/true,
@@ -153,16 +109,12 @@
                         .setSmallIcon(R.drawable.ic_devices_16dp)
                         .setProgress(/*max=*/0, /*percentage=*/0, true)
                         .setOngoing(true)
-                        .addAction(R.drawable.ic_cancel_circle, dismissTitle, dismissIntent,
-                                NotificationUmaTracker.ActionType.SHARING_DISMISS)
                         .setDefaults(Notification.DEFAULT_ALL);
         ChromeNotification notification = builder.buildChromeNotification();
 
         new NotificationManagerProxyImpl(context).notify(notification);
         NotificationUmaTracker.getInstance().onNotificationShown(
                 type, notification.getNotification());
-
-        return token;
     }
 
     /**
@@ -173,16 +125,11 @@
      * @param id The notification id.
      * @param contentTitle The title of the notification.
      * @param contentText The text shown in the notification.
-     * @param token Token returned from {@link #showSendingNotification}.
      * @param tryAgainIntent PendingIntent to try sharing to same device again.
      */
     public static void showSendErrorNotification(@SystemNotificationType int type, String group,
-            int id, String contentTitle, String contentText, int token,
+            int id, String contentTitle, String contentText,
             @Nullable PendingIntentProvider tryAgainIntent) {
-        if (sDismissedSendingNotifications.remove(token)) {
-            return;
-        }
-
         Context context = ContextUtils.getApplicationContext();
         Resources resources = context.getResources();
         ChromeNotificationBuilder builder =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardMessageHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardMessageHandler.java
index 8c94072..4ccf16a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardMessageHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardMessageHandler.java
@@ -71,7 +71,7 @@
             return;
         }
 
-        int token = SharingNotificationUtil.showSendingNotification(
+        SharingNotificationUtil.showSendingNotification(
                 NotificationUmaTracker.SystemNotificationType.SHARED_CLIPBOARD,
                 NotificationConstants.GROUP_SHARED_CLIPBOARD,
                 NotificationConstants.NOTIFICATION_ID_SHARED_CLIPBOARD_OUTGOING, deviceName);
@@ -101,7 +101,7 @@
                         NotificationUmaTracker.SystemNotificationType.SHARED_CLIPBOARD,
                         NotificationConstants.GROUP_SHARED_CLIPBOARD,
                         NotificationConstants.NOTIFICATION_ID_SHARED_CLIPBOARD_OUTGOING,
-                        contentTitle, contentText, token, tryAgainIntent);
+                        contentTitle, contentText, tryAgainIntent);
             }
         });
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardShareActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardShareActivity.java
index 41014f4..537fa79 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardShareActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardShareActivity.java
@@ -35,7 +35,6 @@
 public class SharedClipboardShareActivity
         extends AsyncInitializationActivity implements OnItemClickListener {
     private SharingAdapter mAdapter;
-    private ListView mListView;
 
     /**
      * Checks whether sending shared clipboard message is enabled for the user and enables/disables
@@ -75,13 +74,6 @@
         View mask = findViewById(R.id.mask);
         mask.setOnClickListener(v -> finish());
 
-        mListView = findViewById(R.id.device_picker_list);
-        mListView.setAdapter(mAdapter);
-        mListView.setOnItemClickListener(this);
-        mListView.setEmptyView(findViewById(R.id.empty_state));
-
-        View content = findViewById(R.id.device_picker_content);
-        content.startAnimation(AnimationUtils.loadAnimation(this, R.anim.slide_in_up));
 
         ButtonCompat chromeSettingsButton = findViewById(R.id.chrome_settings);
         if (!AndroidSyncSettings.get().isChromeSyncEnabled()) {
@@ -109,7 +101,13 @@
             findViewById(R.id.device_picker_toolbar).setVisibility(View.VISIBLE);
         }
 
-        mListView.setAdapter(mAdapter);
+        ListView listView = findViewById(R.id.device_picker_list);
+        listView.setAdapter(mAdapter);
+        listView.setOnItemClickListener(this);
+        listView.setEmptyView(findViewById(R.id.empty_state));
+
+        View content = findViewById(R.id.device_picker_content);
+        content.startAnimation(AnimationUtils.loadAnimation(this, R.anim.slide_in_up));
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragment.java
index 7d0a7c37..2cab59f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragment.java
@@ -14,6 +14,7 @@
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
+import org.chromium.chrome.browser.SyncFirstSetupCompleteSource;
 import org.chromium.chrome.browser.preferences.PreferencesLauncher;
 import org.chromium.chrome.browser.preferences.sync.SyncAndServicesPreferences;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
@@ -143,7 +144,8 @@
                                     SyncAndServicesPreferences.createArguments(true));
                         } else if (ChromeFeatureList.isEnabled(
                                            ChromeFeatureList.SYNC_MANUAL_START_ANDROID)) {
-                            ProfileSyncService.get().setFirstSetupComplete();
+                            ProfileSyncService.get().setFirstSetupComplete(
+                                    SyncFirstSetupCompleteSource.BASIC_FLOW);
                         }
 
                         recordSigninCompletedHistogramAccountInfo();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/TileGroup.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/TileGroup.java
index 99924605..049154b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/TileGroup.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/TileGroup.java
@@ -123,6 +123,18 @@
     }
 
     /**
+     * Delegate for handling interactions with tiles.
+     */
+    public interface TileInteractionDelegate extends OnClickListener, OnCreateContextMenuListener {
+        /**
+         * Set a runnable for click events on the tile. This is primarily used to track interaction
+         * with the tile used by feature engagement purposes.
+         * @param clickRunnable The {@link Runnable} to be executed when tile is clicked.
+         */
+        void setOnClickRunnable(Runnable clickRunnable);
+    }
+
+    /**
      * Constants used to track the current operations on the group and notify the {@link Delegate}
      * when the expected sequence of potentially asynchronous operations is complete.
      */
@@ -203,7 +215,7 @@
     private final TileSetupDelegate mTileSetupDelegate = new TileSetupDelegate() {
         @Override
         public TileInteractionDelegate createInteractionDelegate(Tile tile) {
-            return new TileInteractionDelegate(tile.getData());
+            return new TileInteractionDelegateImpl(tile.getData());
         }
 
         @Override
@@ -510,15 +522,12 @@
         }
     }
 
-    /**
-     * Implements various listener and delegate interfaces to handle user interactions with tiles.
-     */
-    public class TileInteractionDelegate
-            implements ContextMenuManager.Delegate, OnClickListener, OnCreateContextMenuListener {
+    private class TileInteractionDelegateImpl
+            implements TileInteractionDelegate, ContextMenuManager.Delegate {
         private final SiteSuggestion mSuggestion;
         private Runnable mOnClickRunnable;
 
-        public TileInteractionDelegate(SiteSuggestion suggestion) {
+        public TileInteractionDelegateImpl(SiteSuggestion suggestion) {
             mSuggestion = suggestion;
         }
 
@@ -587,11 +596,7 @@
             mContextMenuManager.createContextMenu(contextMenu, view, this);
         }
 
-        /**
-         * Set a runnable for click events on the tile. This is primarily used to track interaction
-         * with the tile used by feature engagement purposes.
-         * @param clickRunnable The {@link Runnable} to be executed when tile is clicked.
-         */
+        @Override
         public void setOnClickRunnable(Runnable clickRunnable) {
             mOnClickRunnable = clickRunnable;
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java
index da6e38b7..d8fb9340 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java
@@ -13,6 +13,7 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.chrome.browser.ChromeFeatureList;
+import org.chromium.chrome.browser.SyncFirstSetupCompleteSource;
 import org.chromium.components.sync.ModelType;
 import org.chromium.components.sync.Passphrase;
 
@@ -379,8 +380,8 @@
         nativeTriggerRefresh(mNativeProfileSyncServiceAndroid);
     }
 
-    public void setFirstSetupComplete() {
-        nativeSetFirstSetupComplete(mNativeProfileSyncServiceAndroid);
+    public void setFirstSetupComplete(int syncFirstSetupCompleteSource) {
+        nativeSetFirstSetupComplete(mNativeProfileSyncServiceAndroid, syncFirstSetupCompleteSource);
     }
 
     public boolean isFirstSetupComplete() {
@@ -454,7 +455,8 @@
                 setSetupInProgress(false);
                 if (!ChromeFeatureList.isEnabled(ChromeFeatureList.SYNC_MANUAL_START_ANDROID)) {
                     // The user has finished setting up sync at least once.
-                    setFirstSetupComplete();
+                    setFirstSetupComplete(
+                            SyncFirstSetupCompleteSource.ENGINE_INITIALIZED_WITH_AUTO_START);
                 }
             }
         }
@@ -658,7 +660,8 @@
     private native void nativeTriggerRefresh(long nativeProfileSyncServiceAndroid);
     private native void nativeSetSetupInProgress(
             long nativeProfileSyncServiceAndroid, boolean inProgress);
-    private native void nativeSetFirstSetupComplete(long nativeProfileSyncServiceAndroid);
+    private native void nativeSetFirstSetupComplete(
+            long nativeProfileSyncServiceAndroid, int syncFirstSetupCompleteSource);
     private native boolean nativeIsFirstSetupComplete(long nativeProfileSyncServiceAndroid);
     private native boolean nativeIsSyncRequested(long nativeProfileSyncServiceAndroid);
     private native boolean nativeCanSyncFeatureStart(long nativeProfileSyncServiceAndroid);
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 9f5f9a0..09d17e0 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -3861,9 +3861,6 @@
       <message name="IDS_SHARING_SENDING_NOTIFICATION_TITLE" desc="Title text displayed in a sharing sending notification.">
         Sharing to <ph name="DEVICE_NAME">%1$s<ex>Pixel 3</ex></ph>
       </message>
-      <message name="IDS_SHARING_DISMISS_ACTION" desc="Text for action that dismiss a sharing sending notification.">
-        Dismiss
-      </message>
       <message name="IDS_SHARING_NO_DEVICES_AVAILABLE_TITLE" desc="Text to show when no device targets are available for sharing.">
         Turn on sync to share across devices
       </message>
diff --git a/chrome/android/java/strings/android_chrome_strings_grd/IDS_SHARING_DISMISS_ACTION.png.sha1 b/chrome/android/java/strings/android_chrome_strings_grd/IDS_SHARING_DISMISS_ACTION.png.sha1
deleted file mode 100644
index a79552b..0000000
--- a/chrome/android/java/strings/android_chrome_strings_grd/IDS_SHARING_DISMISS_ACTION.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-da0b6aa681f1f02735f8b1f355c734a8c2e8f58e
\ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
index fb66bef7..fd2df91 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -2703,8 +2703,10 @@
     private void checkPageLoadMetrics(boolean allowMetrics)
             throws InterruptedException, TimeoutException {
         final AtomicReference<Long> firstContentfulPaintMs = new AtomicReference<>(-1L);
+        final AtomicReference<Long> largestContentfulPaintMs = new AtomicReference<>(-1L);
         final AtomicReference<Long> activityStartTimeMs = new AtomicReference<>(-1L);
         final AtomicReference<Long> loadEventStartMs = new AtomicReference<>(-1L);
+        final AtomicReference<Float> layoutShiftScore = new AtomicReference<>(-1f);
         final AtomicReference<Boolean> sawNetworkQualityEstimates = new AtomicReference<>(false);
 
         CustomTabsCallback cb = new CustomTabsCallback() {
@@ -2721,6 +2723,12 @@
                     sawNetworkQualityEstimates.set(true);
                 }
 
+                float layoutShiftScoreValue =
+                        args.getFloat(PageLoadMetrics.LAYOUT_SHIFT_SCORE, -1f);
+                if (layoutShiftScoreValue >= 0f) {
+                    layoutShiftScore.set(layoutShiftScoreValue);
+                }
+
                 long navigationStart = args.getLong(PageLoadMetrics.NAVIGATION_START, -1);
                 if (navigationStart == -1) {
                     // Untested metric callback.
@@ -2737,6 +2745,13 @@
                     firstContentfulPaintMs.set(firstContentfulPaint);
                 }
 
+                long largestContentfulPaint =
+                        args.getLong(PageLoadMetrics.LARGEST_CONTENTFUL_PAINT, -1);
+                if (largestContentfulPaint > 0) {
+                    Assert.assertTrue(largestContentfulPaint <= (current - navigationStart));
+                    largestContentfulPaintMs.set(largestContentfulPaint);
+                }
+
                 long loadEventStart = args.getLong(PageLoadMetrics.LOAD_EVENT_START, -1);
                 if (loadEventStart > 0) {
                     Assert.assertTrue(loadEventStart <= (current - navigationStart));
@@ -2772,6 +2787,25 @@
                 // Expected.
             }
             assertEquals(-1L, (long) firstContentfulPaintMs.get());
+
+            try {
+                CriteriaHelper.pollInstrumentationThread(() -> largestContentfulPaintMs.get() > 0);
+            } catch (AssertionError e) {
+                // Expected.
+            }
+            assertEquals(-1L, (long) largestContentfulPaintMs.get());
+        }
+
+        // Navigate to a new page, as metrics like LCP are only reported at the end of the page load
+        // lifetime.
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            final CustomTabActivity activity = mCustomTabActivityTestRule.getActivity();
+            activity.getComponent().resolveNavigationController().navigate("about:blank");
+        });
+
+        if (allowMetrics) {
+            CriteriaHelper.pollInstrumentationThread(() -> largestContentfulPaintMs.get() > 0);
+            CriteriaHelper.pollInstrumentationThread(() -> layoutShiftScore.get() != -1f);
         }
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninTest.java
index c356b093..02d6bca4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninTest.java
@@ -28,6 +28,7 @@
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
+import org.chromium.chrome.browser.SyncFirstSetupCompleteSource;
 import org.chromium.chrome.browser.bookmarks.BookmarkBridge;
 import org.chromium.chrome.browser.preferences.MainPreferences;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
@@ -344,7 +345,9 @@
         // in the resume of the Main activity, but we forcefully do this here.
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
         TestThreadUtils.runOnUiThreadBlocking(
-                () -> ProfileSyncService.get().setFirstSetupComplete());
+                ()
+                        -> ProfileSyncService.get().setFirstSetupComplete(
+                                SyncFirstSetupCompleteSource.BASIC_FLOW));
         prefActivity.finish();
 
         // Verify that signin succeeded.
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 12cebd6c..862a1f59 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1135,7 +1135,8 @@
     "performance_manager/observers/metrics_collector.cc",
     "performance_manager/observers/metrics_collector.h",
     "performance_manager/performance_manager.cc",
-    "performance_manager/performance_manager.h",
+    "performance_manager/performance_manager_impl.cc",
+    "performance_manager/performance_manager_impl.h",
     "performance_manager/performance_manager_tab_helper.cc",
     "performance_manager/performance_manager_tab_helper.h",
     "performance_manager/persistence/site_data/exponential_moving_average.cc",
@@ -1177,6 +1178,7 @@
     "performance_manager/public/graph/process_node.h",
     "performance_manager/public/graph/system_node.h",
     "performance_manager/public/graph/worker_node.h",
+    "performance_manager/public/performance_manager.h",
     "performance_manager/public/render_process_host_proxy.h",
     "performance_manager/public/web_contents_proxy.h",
     "performance_manager/render_process_host_proxy.cc",
@@ -2840,6 +2842,7 @@
       "password_manager/save_password_infobar_delegate_android.h",
       "password_manager/touch_to_fill_controller.cc",
       "password_manager/touch_to_fill_controller.h",
+      "password_manager/touch_to_fill_view.h",
       "password_manager/update_password_infobar_delegate_android.cc",
       "password_manager/update_password_infobar_delegate_android.h",
       "payments/android/can_make_payment_query_android.cc",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index bccf13f..bcc9616 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -369,7 +369,6 @@
   "+chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.h",
   "+chrome/browser/performance_manager/chrome_content_browser_client_performance_manager_part.h",
   "+chrome/browser/performance_manager/graph/policies/policy_features.h",
-  "+chrome/browser/performance_manager/performance_manager.h",
   "+chrome/browser/performance_manager/performance_manager_tab_helper.h",
   "+chrome/browser/performance_manager/test_support",
 
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 2cfa1c2..2b793fa 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -857,11 +857,16 @@
      base::size(kOmniboxDocumentProviderServerAndClientScoring), nullptr}};
 #endif  // defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
 
+const FeatureEntry::FeatureParam kOmniboxOnFocusSuggestionsParamSERP[] = {
+    {"ZeroSuggestVariant:6:*", ZeroSuggestProvider::kRemoteSendUrlVariant}};
 const FeatureEntry::FeatureParam kOmniboxOnFocusSuggestionsParamNTPOmnibox[] = {
     {"ZeroSuggestVariant:7:*", ZeroSuggestProvider::kRemoteNoUrlVariant}};
 const FeatureEntry::FeatureParam kOmniboxOnFocusSuggestionsParamNTPRealbox[] = {
     {"ZeroSuggestVariant:15:*", ZeroSuggestProvider::kRemoteNoUrlVariant}};
 const FeatureEntry::FeatureVariation kOmniboxOnFocusSuggestionsVariations[] = {
+    {"SERP - RemoteSendURL", kOmniboxOnFocusSuggestionsParamSERP,
+     base::size(kOmniboxOnFocusSuggestionsParamNTPOmnibox),
+     "t3315869" /* variation_id */},
     {"NTP Omnibox - Remote", kOmniboxOnFocusSuggestionsParamNTPOmnibox,
      base::size(kOmniboxOnFocusSuggestionsParamNTPOmnibox),
      "t3316133" /* variation_id */},
@@ -2791,6 +2796,10 @@
      FEATURE_WITH_PARAMS_VALUE_TYPE(omnibox::kDocumentProvider,
                                     kOmniboxDocumentProviderVariations,
                                     "OmniboxBundledExperimentV1")},
+    {"omnibox-autocomplete-titles",
+     flag_descriptions::kOmniboxAutocompleteTitlesName,
+     flag_descriptions::kOmniboxAutocompleteTitlesDescription, kOsDesktop,
+     FEATURE_VALUE_TYPE(omnibox::kAutocompleteTitles)},
 #endif  // defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
 
     {"enable-speculative-service-worker-start-on-query-input",
@@ -2997,10 +3006,6 @@
      flag_descriptions::kScrollableTabStripDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(features::kScrollableTabStrip)},
 
-    {"drag-to-pin-tabs", flag_descriptions::kDragToPinTabsName,
-     flag_descriptions::kDragToPinTabsDescription, kOsDesktop,
-     FEATURE_VALUE_TYPE(features::kDragToPinTabs)},
-
     {"tab-outlines-in-low-contrast-themes",
      flag_descriptions::kTabOutlinesInLowContrastThemesName,
      flag_descriptions::kTabOutlinesInLowContrastThemesDescription, kOsDesktop,
diff --git a/chrome/browser/battery/battery_metrics.cc b/chrome/browser/battery/battery_metrics.cc
index 1cd5ec9..6f7c5a7 100644
--- a/chrome/browser/battery/battery_metrics.cc
+++ b/chrome/browser/battery/battery_metrics.cc
@@ -11,7 +11,6 @@
 #include "base/metrics/histogram_macros.h"
 #include "build/build_config.h"
 #include "content/public/browser/system_connector.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/service_filter.h"
@@ -36,9 +35,9 @@
 
   // Don't create a long lived BatteryMonitor on windows. crbug.com/794105.
 #if !defined(OS_WIN)
-  content::GetSystemConnector()->BindInterface(
+  content::GetSystemConnector()->Connect(
       service_manager::ServiceFilter::ByName(device::mojom::kServiceName),
-      mojo::MakeRequest(&battery_monitor_));
+      battery_monitor_.BindNewPipeAndPassReceiver());
   QueryNextStatus();
 #endif  // !defined(OS_WIN)
 }
diff --git a/chrome/browser/battery/battery_metrics.h b/chrome/browser/battery/battery_metrics.h
index 0c94cd5..65455944 100644
--- a/chrome/browser/battery/battery_metrics.h
+++ b/chrome/browser/battery/battery_metrics.h
@@ -9,6 +9,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "base/sequence_checker.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "services/device/public/mojom/battery_monitor.mojom.h"
 #include "services/device/public/mojom/battery_status.mojom.h"
 
@@ -38,7 +39,7 @@
   base::Optional<float> last_recorded_battery_level_;
 
   // The battery monitor backend for the device Chrome is running on.
-  device::mojom::BatteryMonitorPtr battery_monitor_;
+  mojo::Remote<device::mojom::BatteryMonitor> battery_monitor_;
 
   SEQUENCE_CHECKER(sequence_checker_);
 
diff --git a/chrome/browser/battery/battery_metrics_browsertest.cc b/chrome/browser/battery/battery_metrics_browsertest.cc
index f63c892..3c742b72 100644
--- a/chrome/browser/battery/battery_metrics_browsertest.cc
+++ b/chrome/browser/battery/battery_metrics_browsertest.cc
@@ -15,8 +15,8 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "content/public/common/service_manager_connection.h"
 #include "content/public/test/browser_test_utils.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/device/public/mojom/battery_monitor.mojom.h"
 #include "services/device/public/mojom/battery_status.mojom.h"
 #include "services/device/public/mojom/constants.mojom.h"
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index f53e5a5..0a1c1e29 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -94,6 +94,7 @@
     "//chromeos/dbus:metrics_event_proto",
     "//chromeos/dbus:oobe_config_proto",
     "//chromeos/dbus:plugin_vm_service_proto",
+    "//chromeos/dbus:update_engine_proto",
     "//chromeos/dbus:vm_plugin_dispatcher_proto",
     "//chromeos/dbus/audio",
     "//chromeos/dbus/auth_policy",
diff --git a/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_manager_browsertest.cc b/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_manager_browsertest.cc
index 5acaebb..cc92088 100644
--- a/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_manager_browsertest.cc
+++ b/chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_manager_browsertest.cc
@@ -92,6 +92,7 @@
   }
 
   void TearDownOnMainThread() override {
+    owner_settings_service_.reset();
     settings_helper_.RestoreRealDeviceSettingsProvider();
   }
 
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc b/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc
index 1865851..68a4939 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc
@@ -269,6 +269,7 @@
   }
 
   void TearDownOnMainThread() override {
+    owner_settings_service_.reset();
     settings_helper_.RestoreRealDeviceSettingsProvider();
   }
 
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_update_service_browsertest.cc b/chrome/browser/chromeos/app_mode/kiosk_app_update_service_browsertest.cc
index 155382d..781a320 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_update_service_browsertest.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_update_service_browsertest.cc
@@ -145,8 +145,8 @@
   }
 
   void FireUpdatedNeedReboot() {
-    UpdateEngineClient::Status status;
-    status.status = UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT;
+    update_engine::StatusResult status;
+    status.set_current_operation(update_engine::Operation::UPDATED_NEED_REBOOT);
     run_loop_.reset(new base::RunLoop);
     automatic_reboot_manager_->UpdateStatusChanged(status);
     run_loop_->Run();
diff --git a/chrome/browser/chromeos/login/configuration_based_oobe_browsertest.cc b/chrome/browser/chromeos/login/configuration_based_oobe_browsertest.cc
index 8f28536..676c722 100644
--- a/chrome/browser/chromeos/login/configuration_based_oobe_browsertest.cc
+++ b/chrome/browser/chromeos/login/configuration_based_oobe_browsertest.cc
@@ -308,9 +308,9 @@
 
 // Check that when configuration has ONC and EULA, we get to update screen.
 IN_PROC_BROWSER_TEST_F(OobeConfigurationTest, MAYBE_TestAcceptEula) {
-  UpdateEngineClient::Status status;
-  status.status = UpdateEngineClient::UPDATE_STATUS_DOWNLOADING;
-  status.download_progress = 0.1;
+  update_engine::StatusResult status;
+  status.set_current_operation(update_engine::Operation::DOWNLOADING);
+  status.set_progress(0.1);
   fake_update_engine_client_->set_default_status(status);
 
   LoadConfiguration();
diff --git a/chrome/browser/chromeos/login/kiosk_browsertest.cc b/chrome/browser/chromeos/login/kiosk_browsertest.cc
index f66aebf4..cb58511 100644
--- a/chrome/browser/chromeos/login/kiosk_browsertest.cc
+++ b/chrome/browser/chromeos/login/kiosk_browsertest.cc
@@ -521,6 +521,7 @@
   }
 
   void TearDownOnMainThread() override {
+    owner_settings_service_.reset();
     settings_helper_.RestoreRealDeviceSettingsProvider();
     AppLaunchController::SetNetworkTimeoutCallbackForTesting(NULL);
     AppLaunchSigninScreen::SetUserManagerForTesting(NULL);
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.cc b/chrome/browser/chromeos/login/lock/screen_locker.cc
index 28e73e4..04706c80 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker.cc
+++ b/chrome/browser/chromeos/login/lock/screen_locker.cc
@@ -187,8 +187,8 @@
                       bundle.GetRawDataResource(IDR_SOUND_LOCK_WAV));
   manager->Initialize(SOUND_UNLOCK,
                       bundle.GetRawDataResource(IDR_SOUND_UNLOCK_WAV));
-  content::GetSystemConnector()->BindInterface(device::mojom::kServiceName,
-                                               &fp_service_);
+  content::GetSystemConnector()->Connect(
+      device::mojom::kServiceName, fp_service_.BindNewPipeAndPassReceiver());
 
   device::mojom::FingerprintObserverPtr observer;
   fingerprint_observer_binding_.Bind(mojo::MakeRequest(&observer));
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.h b/chrome/browser/chromeos/login/lock/screen_locker.h
index bbd8ac1..ac73c23d 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker.h
+++ b/chrome/browser/chromeos/login/lock/screen_locker.h
@@ -28,6 +28,7 @@
 #include "chromeos/login/auth/user_context.h"
 #include "components/user_manager/user.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "services/device/public/mojom/fingerprint.mojom.h"
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/base/ime/chromeos/input_method_manager.h"
@@ -285,7 +286,7 @@
 
   scoped_refptr<input_method::InputMethodManager::State> saved_ime_state_;
 
-  device::mojom::FingerprintPtr fp_service_;
+  mojo::Remote<device::mojom::Fingerprint> fp_service_;
   mojo::Binding<device::mojom::FingerprintObserver>
       fingerprint_observer_binding_;
 
diff --git a/chrome/browser/chromeos/login/reset_browsertest.cc b/chrome/browser/chromeos/login/reset_browsertest.cc
index 340e9fc..3aab402 100644
--- a/chrome/browser/chromeos/login/reset_browsertest.cc
+++ b/chrome/browser/chromeos/login/reset_browsertest.cc
@@ -521,8 +521,8 @@
   EXPECT_EQ(1, update_engine_client_->rollback_call_count());
   test::OobeJS().ExpectHasClass("revert-promise-view", {"reset"});
 
-  UpdateEngineClient::Status error_update_status;
-  error_update_status.status = UpdateEngineClient::UPDATE_STATUS_ERROR;
+  update_engine::StatusResult error_update_status;
+  error_update_status.set_current_operation(update_engine::Operation::ERROR);
   update_engine_client_->NotifyObserversThatStatusChanged(error_update_status);
   OobeScreenWaiter(ErrorScreenView::kScreenId).Wait();
 
diff --git a/chrome/browser/chromeos/login/screens/reset_screen.cc b/chrome/browser/chromeos/login/screens/reset_screen.cc
index fe6734ca..6fbf857 100644
--- a/chrome/browser/chromeos/login/screens/reset_screen.cc
+++ b/chrome/browser/chromeos/login/screens/reset_screen.cc
@@ -412,17 +412,17 @@
 }
 
 void ResetScreen::UpdateStatusChanged(
-    const UpdateEngineClient::Status& status) {
-  VLOG(1) << "Update status change to " << status.status;
-  if (status.status == UpdateEngineClient::UPDATE_STATUS_ERROR ||
-      status.status ==
-          UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT) {
+    const update_engine::StatusResult& status) {
+  VLOG(1) << "Update status operation change to " << status.current_operation();
+  if (status.current_operation() == update_engine::Operation::ERROR ||
+      status.current_operation() ==
+          update_engine::Operation::REPORTING_ERROR_EVENT) {
     view_->SetScreenState(ResetView::State::kError);
     // Show error screen.
     error_screen_->SetUIState(NetworkError::UI_STATE_ROLLBACK_ERROR);
     error_screen_->Show();
-  } else if (status.status ==
-             UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT) {
+  } else if (status.current_operation() ==
+             update_engine::Operation::UPDATED_NEED_REBOOT) {
     PowerManagerClient::Get()->RequestRestart(
         power_manager::REQUEST_RESTART_FOR_UPDATE, "login reset screen update");
   }
diff --git a/chrome/browser/chromeos/login/screens/reset_screen.h b/chrome/browser/chromeos/login/screens/reset_screen.h
index 4f825811..384a0b06 100644
--- a/chrome/browser/chromeos/login/screens/reset_screen.h
+++ b/chrome/browser/chromeos/login/screens/reset_screen.h
@@ -73,7 +73,7 @@
   void OnUserAction(const std::string& action_id) override;
 
   // UpdateEngineClient::Observer implementation:
-  void UpdateStatusChanged(const UpdateEngineClient::Status& status) override;
+  void UpdateStatusChanged(const update_engine::StatusResult& status) override;
 
   void OnRollbackCheck(bool can_rollback);
   void OnTPMFirmwareUpdateAvailableCheck(
diff --git a/chrome/browser/chromeos/login/screens/update_screen.cc b/chrome/browser/chromeos/login/screens/update_screen.cc
index 5609dd51..feab9d0 100644
--- a/chrome/browser/chromeos/login/screens/update_screen.cc
+++ b/chrome/browser/chromeos/login/screens/update_screen.cc
@@ -185,19 +185,20 @@
 
 void UpdateScreen::UpdateInfoChanged(
     const VersionUpdater::UpdateInfo& update_info) {
-  const UpdateEngineClient::Status& status = update_info.status;
+  const update_engine::StatusResult& status = update_info.status;
   hide_progress_on_exit_ = false;
   bool need_refresh_view = true;
-  switch (status.status) {
-    case UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE:
-      // Do nothing in this case, we don't want to notify the user of the
+  switch (status.current_operation()) {
+    case update_engine::Operation::CHECKING_FOR_UPDATE:
+      // Do nothing in these cases, we don't want to notify the user of the
       // check unless there is an update.
-    case UpdateEngineClient::UPDATE_STATUS_ATTEMPTING_ROLLBACK:
-    case UpdateEngineClient::UPDATE_STATUS_IDLE:
+    case update_engine::Operation::ATTEMPTING_ROLLBACK:
+    case update_engine::Operation::DISABLED:
+    case update_engine::Operation::IDLE:
       need_refresh_view = false;
       break;
-    case UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE:
-    case UpdateEngineClient::UPDATE_STATUS_DOWNLOADING:
+    case update_engine::Operation::UPDATE_AVAILABLE:
+    case update_engine::Operation::DOWNLOADING:
       MakeSureScreenIsShown();
       if (!is_critical_checked_) {
         // Because update engine doesn't send UPDATE_STATUS_UPDATE_AVAILABLE we
@@ -205,20 +206,20 @@
         // notification.
         is_critical_checked_ = true;
         if (!HasCriticalUpdate()) {
-          VLOG(1) << "Non-critical update available: " << status.new_version;
+          VLOG(1) << "Non-critical update available: " << status.new_version();
           hide_progress_on_exit_ = true;
           ExitUpdate(Result::UPDATE_NOT_REQUIRED);
         } else {
-          VLOG(1) << "Critical update available: " << status.new_version;
+          VLOG(1) << "Critical update available: " << status.new_version();
         }
       }
       break;
-    case UpdateEngineClient::UPDATE_STATUS_VERIFYING:
-    case UpdateEngineClient::UPDATE_STATUS_FINALIZING:
-    case UpdateEngineClient::UPDATE_STATUS_NEED_PERMISSION_TO_UPDATE:
+    case update_engine::Operation::VERIFYING:
+    case update_engine::Operation::FINALIZING:
+    case update_engine::Operation::NEED_PERMISSION_TO_UPDATE:
       MakeSureScreenIsShown();
       break;
-    case UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT:
+    case update_engine::Operation::UPDATED_NEED_REBOOT:
       MakeSureScreenIsShown();
       if (HasCriticalUpdate()) {
         version_updater_->RebootAfterUpdate();
@@ -227,8 +228,8 @@
         ExitUpdate(Result::UPDATE_NOT_REQUIRED);
       }
       break;
-    case UpdateEngineClient::UPDATE_STATUS_ERROR:
-    case UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT:
+    case update_engine::Operation::ERROR:
+    case update_engine::Operation::REPORTING_ERROR_EVENT:
       // Ignore update errors for non-critical updates to prevent blocking the
       // user from getting to login screen during OOBE if the pending update is
       // not critical.
@@ -239,6 +240,8 @@
       }
       need_refresh_view = false;
       break;
+    default:
+      NOTREACHED();
   }
   if (need_refresh_view)
     RefreshView(update_info);
diff --git a/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc
index 90eb7c9..8fd8831e 100644
--- a/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc
@@ -136,16 +136,16 @@
   EXPECT_TRUE(update_screen_->GetShowTimerForTesting()->IsRunning());
   update_screen_->GetShowTimerForTesting()->Stop();
 
-  UpdateEngineClient::Status status;
-  status.status = UpdateEngineClient::UPDATE_STATUS_IDLE;
+  update_engine::StatusResult status;
+  status.set_current_operation(update_engine::Operation::IDLE);
   fake_update_engine_client_->set_default_status(status);
   fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
 
-  status.status = UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE;
+  status.set_current_operation(update_engine::Operation::CHECKING_FOR_UPDATE);
   fake_update_engine_client_->set_default_status(status);
   fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
 
-  status.status = UpdateEngineClient::UPDATE_STATUS_IDLE;
+  status.set_current_operation(update_engine::Operation::IDLE);
   fake_update_engine_client_->set_default_status(status);
   fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
 
@@ -166,12 +166,12 @@
   update_screen_->Show();
   EXPECT_TRUE(update_screen_->GetShowTimerForTesting()->IsRunning());
 
-  UpdateEngineClient::Status status;
-  status.status = UpdateEngineClient::UPDATE_STATUS_IDLE;
+  update_engine::StatusResult status;
+  status.set_current_operation(update_engine::Operation::IDLE);
   fake_update_engine_client_->set_default_status(status);
   fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
 
-  status.status = UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE;
+  status.set_current_operation(update_engine::Operation::CHECKING_FOR_UPDATE);
   fake_update_engine_client_->set_default_status(status);
   fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
 
@@ -188,7 +188,7 @@
       {"oobe-update-md", "cellular-permission-dialog"});
   test::OobeJS().ExpectHiddenPath({"oobe-update-md", "updating-dialog"});
 
-  status.status = UpdateEngineClient::UPDATE_STATUS_IDLE;
+  status.set_current_operation(update_engine::Operation::IDLE);
   // GetLastStatus() will be called via ExitUpdate() called from
   // UpdateStatusChanged().
   fake_update_engine_client_->set_default_status(status);
@@ -203,10 +203,10 @@
   update_screen_->set_ignore_update_deadlines_for_testing(true);
   update_screen_->Show();
 
-  UpdateEngineClient::Status status;
-  status.status = UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE;
-  status.new_version = "latest and greatest";
-  status.new_size = 1000000000;
+  update_engine::StatusResult status;
+  status.set_current_operation(update_engine::Operation::CHECKING_FOR_UPDATE);
+  status.set_new_version("latest and greatest");
+  status.set_new_size(1000000000);
   fake_update_engine_client_->set_default_status(status);
   fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
 
@@ -223,13 +223,13 @@
   test::OobeJS().ExpectHiddenPath(
       {"oobe-update-md", "cellular-permission-dialog"});
 
-  status.status = UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE;
-  status.download_progress = 0.0;
+  status.set_current_operation(update_engine::Operation::UPDATE_AVAILABLE);
+  status.set_progress(0.0);
   fake_update_engine_client_->set_default_status(status);
   fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
 
-  status.status = UpdateEngineClient::UPDATE_STATUS_DOWNLOADING;
-  status.download_progress = 0.0;
+  status.set_current_operation(update_engine::Operation::DOWNLOADING);
+  status.set_progress(0.0);
   fake_update_engine_client_->set_default_status(status);
   fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
 
@@ -252,7 +252,7 @@
   test::OobeJS().ExpectHiddenPath({"oobe-update-md", "update-complete-msg"});
 
   tick_clock_.Advance(base::TimeDelta::FromSeconds(60));
-  status.download_progress = 0.01;
+  status.set_progress(0.01);
   fake_update_engine_client_->set_default_status(status);
   fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
 
@@ -267,7 +267,7 @@
   test::OobeJS().ExpectHiddenPath({"oobe-update-md", "update-complete-msg"});
 
   tick_clock_.Advance(base::TimeDelta::FromSeconds(60));
-  status.download_progress = 0.08;
+  status.set_progress(0.08);
   fake_update_engine_client_->set_default_status(status);
   fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
 
@@ -282,7 +282,7 @@
   test::OobeJS().ExpectHiddenPath({"oobe-update-md", "update-complete-msg"});
 
   tick_clock_.Advance(base::TimeDelta::FromSeconds(10));
-  status.download_progress = 0.7;
+  status.set_progress(0.7);
   fake_update_engine_client_->set_default_status(status);
   fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
 
@@ -297,7 +297,7 @@
   test::OobeJS().ExpectHiddenPath({"oobe-update-md", "update-complete-msg"});
 
   tick_clock_.Advance(base::TimeDelta::FromSeconds(10));
-  status.download_progress = 0.9;
+  status.set_progress(0.9);
   fake_update_engine_client_->set_default_status(status);
   fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
 
@@ -312,8 +312,8 @@
   test::OobeJS().ExpectHiddenPath({"oobe-update-md", "update-complete-msg"});
 
   tick_clock_.Advance(base::TimeDelta::FromSeconds(10));
-  status.status = UpdateEngineClient::UPDATE_STATUS_VERIFYING;
-  status.download_progress = 1.0;
+  status.set_current_operation(update_engine::Operation::VERIFYING);
+  status.set_progress(1.0);
   fake_update_engine_client_->set_default_status(status);
   fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
 
@@ -328,7 +328,7 @@
   test::OobeJS().ExpectHiddenPath({"oobe-update-md", "update-complete-msg"});
 
   tick_clock_.Advance(base::TimeDelta::FromSeconds(10));
-  status.status = UpdateEngineClient::UPDATE_STATUS_FINALIZING;
+  status.set_current_operation(update_engine::Operation::FINALIZING);
   fake_update_engine_client_->set_default_status(status);
   fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
 
@@ -343,7 +343,7 @@
   test::OobeJS().ExpectHiddenPath({"oobe-update-md", "update-complete-msg"});
 
   tick_clock_.Advance(base::TimeDelta::FromSeconds(10));
-  status.status = UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT;
+  status.set_current_operation(update_engine::Operation::UPDATED_NEED_REBOOT);
   fake_update_engine_client_->set_default_status(status);
   fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
 
@@ -387,8 +387,8 @@
 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestErrorCheckingForUpdate) {
   update_screen_->Show();
 
-  UpdateEngineClient::Status status;
-  status.status = UpdateEngineClient::UPDATE_STATUS_ERROR;
+  update_engine::StatusResult status;
+  status.set_current_operation(update_engine::Operation::ERROR);
   // GetLastStatus() will be called via ExitUpdate() called from
   // UpdateStatusChanged().
   fake_update_engine_client_->set_default_status(status);
@@ -404,9 +404,9 @@
 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestErrorUpdating) {
   update_screen_->Show();
 
-  UpdateEngineClient::Status status;
-  status.status = UpdateEngineClient::UPDATE_STATUS_ERROR;
-  status.new_version = "latest and greatest";
+  update_engine::StatusResult status;
+  status.set_current_operation(update_engine::Operation::ERROR);
+  status.set_new_version("latest and greatest");
 
   fake_update_engine_client_->set_default_status(status);
   fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
@@ -436,14 +436,14 @@
       NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE);
   EXPECT_FALSE(update_screen_->GetErrorMessageTimerForTesting()->IsRunning());
 
-  UpdateEngineClient::Status status;
-  status.status = UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE;
+  update_engine::StatusResult status;
+  status.set_current_operation(update_engine::Operation::CHECKING_FOR_UPDATE);
   fake_update_engine_client_->set_default_status(status);
   fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
 
   EXPECT_TRUE(update_screen_->GetShowTimerForTesting()->IsRunning());
 
-  status.status = UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE;
+  status.set_current_operation(update_engine::Operation::UPDATE_AVAILABLE);
   fake_update_engine_client_->set_default_status(status);
   fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
 
@@ -461,7 +461,7 @@
       {"oobe-update-md", "cellular-permission-dialog"});
   test::OobeJS().ExpectHiddenPath({"oobe-update-md", "updating-dialog"});
 
-  status.status = UpdateEngineClient::UPDATE_STATUS_IDLE;
+  status.set_current_operation(update_engine::Operation::IDLE);
   fake_update_engine_client_->set_default_status(status);
   fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
 
@@ -575,9 +575,10 @@
 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, UpdateOverCellularAccepted) {
   update_screen_->set_ignore_update_deadlines_for_testing(true);
 
-  UpdateEngineClient::Status status;
-  status.status = UpdateEngineClient::UPDATE_STATUS_NEED_PERMISSION_TO_UPDATE;
-  status.new_version = "latest and greatest";
+  update_engine::StatusResult status;
+  status.set_current_operation(
+      update_engine::Operation::NEED_PERMISSION_TO_UPDATE);
+  status.set_new_version("latest and greatest");
 
   update_screen_->Show();
 
@@ -608,7 +609,7 @@
   test::OobeJS().ExpectHiddenPath(
       {"oobe-update-md", "checking-for-updates-dialog"});
 
-  status.status = UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT;
+  status.set_current_operation(update_engine::Operation::UPDATED_NEED_REBOOT);
   version_updater_->UpdateStatusChangedForTesting(status);
 
   // UpdateStatusChanged(status) calls RebootAfterUpdate().
@@ -619,9 +620,10 @@
 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, UpdateOverCellularRejected) {
   update_screen_->set_ignore_update_deadlines_for_testing(true);
 
-  UpdateEngineClient::Status status;
-  status.status = UpdateEngineClient::UPDATE_STATUS_NEED_PERMISSION_TO_UPDATE;
-  status.new_version = "latest and greatest";
+  update_engine::StatusResult status;
+  status.set_current_operation(
+      update_engine::Operation::NEED_PERMISSION_TO_UPDATE);
+  status.set_new_version("latest and greatest");
 
   update_screen_->Show();
 
diff --git a/chrome/browser/chromeos/login/screens/update_screen_unittest.cc b/chrome/browser/chromeos/login/screens/update_screen_unittest.cc
index 6ed8db8..9d033e4d 100644
--- a/chrome/browser/chromeos/login/screens/update_screen_unittest.cc
+++ b/chrome/browser/chromeos/login/screens/update_screen_unittest.cc
@@ -42,9 +42,9 @@
       const std::unique_ptr<UpdateScreen>& update_screen,
       bool available,
       bool critical) {
-    UpdateEngineClient::Status update_engine_status;
-    update_engine_status.status =
-        UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE;
+    update_engine::StatusResult update_engine_status;
+    update_engine_status.set_current_operation(
+        update_engine::Operation::CHECKING_FOR_UPDATE);
     fake_update_engine_client_->NotifyObserversThatStatusChanged(
         update_engine_status);
 
@@ -53,9 +53,9 @@
                                 "critical if one is not even available.";
       update_screen->set_ignore_update_deadlines_for_testing(true);
     }
-    update_engine_status.status =
-        available ? UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE
-                  : UpdateEngineClient::UPDATE_STATUS_IDLE;
+    update_engine_status.set_current_operation(
+        available ? update_engine::Operation::UPDATE_AVAILABLE
+                  : update_engine::Operation::IDLE);
 
     fake_update_engine_client_->NotifyObserversThatStatusChanged(
         update_engine_status);
@@ -182,9 +182,9 @@
 
   EXPECT_FALSE(last_screen_result_.has_value());
 
-  UpdateEngineClient::Status update_engine_status;
-  update_engine_status.status =
-      UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT;
+  update_engine::StatusResult update_engine_status;
+  update_engine_status.set_current_operation(
+      update_engine::Operation::REPORTING_ERROR_EVENT);
   fake_update_engine_client_->NotifyObserversThatStatusChanged(
       update_engine_status);
 
diff --git a/chrome/browser/chromeos/login/test/oobe_screens_utils.cc b/chrome/browser/chromeos/login/test/oobe_screens_utils.cc
index 983de3e..47dae1d 100644
--- a/chrome/browser/chromeos/login/test/oobe_screens_utils.cc
+++ b/chrome/browser/chromeos/login/test/oobe_screens_utils.cc
@@ -67,8 +67,8 @@
 }
 
 void ExitUpdateScreenNoUpdate() {
-  UpdateEngineClient::Status status;
-  status.status = UpdateEngineClient::UPDATE_STATUS_ERROR;
+  update_engine::StatusResult status;
+  status.set_current_operation(update_engine::Operation::ERROR);
 
   UpdateScreen* screen = UpdateScreen::Get(
       WizardController::default_controller()->screen_manager());
diff --git a/chrome/browser/chromeos/login/version_updater/version_updater.cc b/chrome/browser/chromeos/login/version_updater/version_updater.cc
index 082588f9..912c635 100644
--- a/chrome/browser/chromeos/login/version_updater/version_updater.cc
+++ b/chrome/browser/chromeos/login/version_updater/version_updater.cc
@@ -121,7 +121,7 @@
 }
 
 void VersionUpdater::UpdateStatusChangedForTesting(
-    const UpdateEngineClient::Status& status) {
+    const update_engine::StatusResult& status) {
   UpdateStatusChanged(status);
 }
 
@@ -141,38 +141,39 @@
 }
 
 void VersionUpdater::UpdateStatusChanged(
-    const UpdateEngineClient::Status& status) {
+    const update_engine::StatusResult& status) {
   update_info_.status = status;
 
   if (update_info_.is_checking_for_update &&
-      status.status > UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE &&
-      status.status != UpdateEngineClient::UPDATE_STATUS_ERROR &&
-      status.status !=
-          UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT) {
+      status.current_operation() >
+          update_engine::Operation::CHECKING_FOR_UPDATE &&
+      status.current_operation() != update_engine::Operation::ERROR &&
+      status.current_operation() !=
+          update_engine::Operation::REPORTING_ERROR_EVENT) {
     update_info_.is_checking_for_update = false;
   }
   if (ignore_idle_status_ &&
-      status.status > UpdateEngineClient::UPDATE_STATUS_IDLE) {
+      status.current_operation() > update_engine::Operation::IDLE) {
     ignore_idle_status_ = false;
   }
 
-  switch (status.status) {
-    case UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE:
+  switch (status.current_operation()) {
+    case update_engine::Operation::CHECKING_FOR_UPDATE:
       break;
-    case UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE:
+    case update_engine::Operation::UPDATE_AVAILABLE:
       update_info_.progress = kBeforeDownloadProgress;
       update_info_.progress_message =
           l10n_util::GetStringUTF16(IDS_UPDATE_AVAILABLE);
       update_info_.show_estimated_time_left = false;
       update_info_.progress_unavailable = false;
       break;
-    case UpdateEngineClient::UPDATE_STATUS_DOWNLOADING:
+    case update_engine::Operation::DOWNLOADING:
       if (!is_downloading_update_) {
         is_downloading_update_ = true;
 
         download_start_time_ = download_last_time_ = tick_clock_->NowTicks();
-        download_start_progress_ = status.download_progress;
-        download_last_progress_ = status.download_progress;
+        download_start_progress_ = status.progress();
+        download_last_progress_ = status.progress();
         is_download_average_speed_computed_ = false;
         download_average_speed_ = 0.0;
         update_info_.progress_message =
@@ -181,67 +182,70 @@
       }
       UpdateDownloadingStats(status);
       break;
-    case UpdateEngineClient::UPDATE_STATUS_VERIFYING:
+    case update_engine::Operation::VERIFYING:
       update_info_.progress = kBeforeVerifyingProgress;
       update_info_.progress_message =
           l10n_util::GetStringUTF16(IDS_UPDATE_VERIFYING);
       update_info_.show_estimated_time_left = false;
       break;
-    case UpdateEngineClient::UPDATE_STATUS_FINALIZING:
+    case update_engine::Operation::FINALIZING:
       update_info_.progress = kBeforeFinalizingProgress;
       update_info_.progress_message =
           l10n_util::GetStringUTF16(IDS_UPDATE_FINALIZING);
       update_info_.show_estimated_time_left = false;
       break;
-    case UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT:
+    case update_engine::Operation::UPDATED_NEED_REBOOT:
       update_info_.progress = kProgressComplete;
       update_info_.show_estimated_time_left = false;
       update_info_.progress_unavailable = false;
       break;
-    case UpdateEngineClient::UPDATE_STATUS_NEED_PERMISSION_TO_UPDATE:
+    case update_engine::Operation::NEED_PERMISSION_TO_UPDATE:
       VLOG(1) << "Update requires user permission to proceed.";
       update_info_.state = State::STATE_REQUESTING_USER_PERMISSION;
-      update_info_.update_version = status.new_version;
-      update_info_.update_size = status.new_size;
+      update_info_.update_version = status.new_version();
+      update_info_.update_size = status.new_size();
       update_info_.requires_permission_for_cellular = true;
       update_info_.progress_unavailable = false;
 
       DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(this);
       break;
-    case UpdateEngineClient::UPDATE_STATUS_ATTEMPTING_ROLLBACK:
+    case update_engine::Operation::ATTEMPTING_ROLLBACK:
       VLOG(1) << "Attempting rollback";
       break;
-    case UpdateEngineClient::UPDATE_STATUS_IDLE:
+    case update_engine::Operation::IDLE:
       // Exit update only if update engine was in non-idle status before.
       // Otherwise, it's possible that the update request has not yet been
       // started.
       if (!ignore_idle_status_)
         StartExitUpdate(Result::UPDATE_NOT_REQUIRED);
       break;
-    case UpdateEngineClient::UPDATE_STATUS_ERROR:
-    case UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT:
+    case update_engine::Operation::DISABLED:
+    case update_engine::Operation::ERROR:
+    case update_engine::Operation::REPORTING_ERROR_EVENT:
       break;
+    default:
+      NOTREACHED();
   }
 
   delegate_->UpdateInfoChanged(update_info_);
 }
 
 void VersionUpdater::UpdateDownloadingStats(
-    const UpdateEngineClient::Status& status) {
+    const update_engine::StatusResult& status) {
   base::TimeTicks download_current_time = tick_clock_->NowTicks();
   if (download_current_time >= download_last_time_ + kMinTimeStep) {
     // Estimate downloading rate.
     double progress_delta =
-        std::max(status.download_progress - download_last_progress_, 0.0);
+        std::max(status.progress() - download_last_progress_, 0.0);
     double time_delta =
         (download_current_time - download_last_time_).InSecondsF();
-    double download_rate = status.new_size * progress_delta / time_delta;
+    double download_rate = status.new_size() * progress_delta / time_delta;
 
     download_last_time_ = download_current_time;
-    download_last_progress_ = status.download_progress;
+    download_last_progress_ = status.progress();
 
     // Estimate time left.
-    double progress_left = std::max(1.0 - status.download_progress, 0.0);
+    double progress_left = std::max(1.0 - status.progress(), 0.0);
     if (!is_download_average_speed_computed_) {
       download_average_speed_ = download_rate;
       is_download_average_speed_computed_ = true;
@@ -251,11 +255,11 @@
         (1.0 - kDownloadSpeedSmoothFactor) * download_average_speed_;
     if (download_average_speed_ < kDownloadAverageSpeedDropBound) {
       time_delta = (download_current_time - download_start_time_).InSecondsF();
-      download_average_speed_ =
-          status.new_size *
-          (status.download_progress - download_start_progress_) / time_delta;
+      download_average_speed_ = status.new_size() *
+                                (status.progress() - download_start_progress_) /
+                                time_delta;
     }
-    double work_left = progress_left * status.new_size;
+    double work_left = progress_left * status.new_size();
     // time_left is in seconds.
     double time_left = work_left / download_average_speed_;
     // |time_left| may be large enough or even +infinity. So we must
@@ -267,7 +271,7 @@
   }
 
   int download_progress =
-      static_cast<int>(status.download_progress * kDownloadProgressIncrement);
+      static_cast<int>(status.progress() * kDownloadProgressIncrement);
   update_info_.progress = kBeforeDownloadProgress + download_progress;
 }
 
diff --git a/chrome/browser/chromeos/login/version_updater/version_updater.h b/chrome/browser/chromeos/login/version_updater/version_updater.h
index 8c73f6c..a6b20567 100644
--- a/chrome/browser/chromeos/login/version_updater/version_updater.h
+++ b/chrome/browser/chromeos/login/version_updater/version_updater.h
@@ -45,7 +45,7 @@
   struct UpdateInfo {
     UpdateInfo();
 
-    UpdateEngineClient::Status status = UpdateEngineClient::Status();
+    update_engine::StatusResult status;
 
     // Estimated time left, in seconds.
     int estimated_time_left_in_secs = 0;
@@ -114,17 +114,17 @@
   }
 
   base::OneShotTimer* GetRebootTimerForTesting();
-  void UpdateStatusChangedForTesting(const UpdateEngineClient::Status& status);
+  void UpdateStatusChangedForTesting(const update_engine::StatusResult& status);
 
  private:
   void RequestUpdateCheck();
 
   // UpdateEngineClient::Observer implementation:
-  void UpdateStatusChanged(const UpdateEngineClient::Status& status) override;
+  void UpdateStatusChanged(const update_engine::StatusResult& status) override;
 
   // Updates downloading stats (remaining time and downloading
   // progress), which are stored in update_info_.
-  void UpdateDownloadingStats(const UpdateEngineClient::Status& status);
+  void UpdateDownloadingStats(const update_engine::StatusResult& status);
 
   // NetworkPortalDetector::Observer implementation:
   void OnPortalDetectionCompleted(
diff --git a/chrome/browser/chromeos/login/version_updater/version_updater_unittest.cc b/chrome/browser/chromeos/login/version_updater/version_updater_unittest.cc
index 8c8b850..007b54e 100644
--- a/chrome/browser/chromeos/login/version_updater/version_updater_unittest.cc
+++ b/chrome/browser/chromeos/login/version_updater/version_updater_unittest.cc
@@ -40,14 +40,13 @@
  public:
   VersionUpdaterUnitTest() : local_state_(TestingBrowserProcess::GetGlobal()) {}
 
-  void SetUpdateEngineStatus(UpdateEngineClient::UpdateStatusOperation status) {
-    UpdateEngineClient::Status update_engine_status;
-    update_engine_status.status = status;
-    fake_update_engine_client_->NotifyObserversThatStatusChanged(
-        update_engine_status);
+  void SetUpdateEngineStatus(update_engine::Operation operation) {
+    update_engine::StatusResult status;
+    status.set_current_operation(operation);
+    fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
   }
 
-  void SetStatusWithChecks(UpdateEngineClient::UpdateStatusOperation status) {
+  void SetStatusWithChecks(update_engine::Operation operation) {
     testing::MockFunction<void(int check_point_name)> check;
     {
       testing::InSequence s;
@@ -56,7 +55,7 @@
       EXPECT_CALL(check, Call(checks_count_));
     }
 
-    SetUpdateEngineStatus(status);
+    SetUpdateEngineStatus(operation);
     check.Call(checks_count_);
     ++checks_count_;
   }
@@ -139,13 +138,13 @@
   // Verify that the DUT checks for an update.
   EXPECT_EQ(fake_update_engine_client_->request_update_check_call_count(), 1);
 
-  SetStatusWithChecks(UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE);
+  SetStatusWithChecks(update_engine::Operation::CHECKING_FOR_UPDATE);
 
   // No updates are available.
   EXPECT_CALL(*mock_delegate_,
               FinishExitUpdate(VersionUpdater::Result::UPDATE_NOT_REQUIRED))
       .Times(1);
-  SetStatusWithChecks(UpdateEngineClient::UPDATE_STATUS_IDLE);
+  SetStatusWithChecks(update_engine::Operation::IDLE);
 }
 
 TEST_F(VersionUpdaterUnitTest, HandlesAvailableUpdate) {
@@ -156,19 +155,19 @@
   // Verify that the DUT checks for an update.
   EXPECT_EQ(fake_update_engine_client_->request_update_check_call_count(), 1);
 
-  SetStatusWithChecks(UpdateEngineClient::UPDATE_STATUS_IDLE);
+  SetStatusWithChecks(update_engine::Operation::IDLE);
 
-  SetStatusWithChecks(UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE);
+  SetStatusWithChecks(update_engine::Operation::CHECKING_FOR_UPDATE);
 
-  SetStatusWithChecks(UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE);
+  SetStatusWithChecks(update_engine::Operation::UPDATE_AVAILABLE);
 
-  SetStatusWithChecks(UpdateEngineClient::UPDATE_STATUS_DOWNLOADING);
+  SetStatusWithChecks(update_engine::Operation::DOWNLOADING);
 
-  SetStatusWithChecks(UpdateEngineClient::UPDATE_STATUS_VERIFYING);
+  SetStatusWithChecks(update_engine::Operation::VERIFYING);
 
-  SetStatusWithChecks(UpdateEngineClient::UPDATE_STATUS_FINALIZING);
+  SetStatusWithChecks(update_engine::Operation::FINALIZING);
 
-  SetStatusWithChecks(UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT);
+  SetStatusWithChecks(update_engine::Operation::UPDATED_NEED_REBOOT);
 
   EXPECT_EQ(fake_update_engine_client_->reboot_after_update_call_count(), 0);
   version_updater_->RebootAfterUpdate();
@@ -184,11 +183,11 @@
   // Verify that the DUT checks for an update.
   EXPECT_EQ(fake_update_engine_client_->request_update_check_call_count(), 1);
 
-  SetStatusWithChecks(UpdateEngineClient::UPDATE_STATUS_IDLE);
+  SetStatusWithChecks(update_engine::Operation::IDLE);
 
-  SetStatusWithChecks(UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE);
+  SetStatusWithChecks(update_engine::Operation::CHECKING_FOR_UPDATE);
 
-  SetStatusWithChecks(UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE);
+  SetStatusWithChecks(update_engine::Operation::UPDATE_AVAILABLE);
 
   EXPECT_CALL(*mock_delegate_,
               FinishExitUpdate(VersionUpdater::Result::UPDATE_NOT_REQUIRED))
@@ -206,13 +205,13 @@
   // Verify that the DUT checks for an update.
   EXPECT_EQ(fake_update_engine_client_->request_update_check_call_count(), 1);
 
-  SetStatusWithChecks(UpdateEngineClient::UPDATE_STATUS_IDLE);
+  SetStatusWithChecks(update_engine::Operation::IDLE);
 
-  SetStatusWithChecks(UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE);
+  SetStatusWithChecks(update_engine::Operation::CHECKING_FOR_UPDATE);
 
-  SetStatusWithChecks(UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE);
+  SetStatusWithChecks(update_engine::Operation::UPDATE_AVAILABLE);
 
-  SetStatusWithChecks(UpdateEngineClient::UPDATE_STATUS_DOWNLOADING);
+  SetStatusWithChecks(update_engine::Operation::DOWNLOADING);
 
   EXPECT_CALL(*mock_delegate_,
               FinishExitUpdate(VersionUpdater::Result::UPDATE_NOT_REQUIRED))
@@ -230,13 +229,13 @@
   // Verify that the DUT checks for an update.
   EXPECT_EQ(fake_update_engine_client_->request_update_check_call_count(), 1);
 
-  SetStatusWithChecks(UpdateEngineClient::UPDATE_STATUS_IDLE);
+  SetStatusWithChecks(update_engine::Operation::IDLE);
 
-  SetStatusWithChecks(UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE);
+  SetStatusWithChecks(update_engine::Operation::CHECKING_FOR_UPDATE);
 
-  SetStatusWithChecks(UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE);
+  SetStatusWithChecks(update_engine::Operation::UPDATE_AVAILABLE);
 
-  SetStatusWithChecks(UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT);
+  SetStatusWithChecks(update_engine::Operation::REPORTING_ERROR_EVENT);
 
   EXPECT_CALL(*mock_delegate_,
               FinishExitUpdate(VersionUpdater::Result::UPDATE_ERROR))
diff --git a/chrome/browser/chromeos/ownership/fake_owner_settings_service.cc b/chrome/browser/chromeos/ownership/fake_owner_settings_service.cc
index 30990ae6..9efd229 100644
--- a/chrome/browser/chromeos/ownership/fake_owner_settings_service.cc
+++ b/chrome/browser/chromeos/ownership/fake_owner_settings_service.cc
@@ -31,8 +31,7 @@
       set_management_settings_result_(true),
       settings_provider_(provider) {}
 
-FakeOwnerSettingsService::~FakeOwnerSettingsService() {
-}
+FakeOwnerSettingsService::~FakeOwnerSettingsService() = default;
 
 bool FakeOwnerSettingsService::IsOwner() {
   return !InstallAttributes::Get()->IsEnterpriseManaged() &&
@@ -46,13 +45,4 @@
   return true;
 }
 
-void FakeOwnerSettingsService::Observe(
-    int type,
-    const content::NotificationSource& source,
-    const content::NotificationDetails& details) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  if (!ignore_profile_creation_notifications_)
-    OwnerSettingsServiceChromeOS::Observe(type, source, details);
-}
-
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/ownership/fake_owner_settings_service.h b/chrome/browser/chromeos/ownership/fake_owner_settings_service.h
index 59ccc1e..552e399 100644
--- a/chrome/browser/chromeos/ownership/fake_owner_settings_service.h
+++ b/chrome/browser/chromeos/ownership/fake_owner_settings_service.h
@@ -34,10 +34,6 @@
     set_management_settings_result_ = success;
   }
 
-  void set_ignore_profile_creation_notification(bool ignore) {
-    ignore_profile_creation_notifications_ = ignore;
-  }
-
   const ManagementSettings& last_settings() const {
     return last_settings_;
   }
@@ -46,19 +42,10 @@
   bool IsOwner() override;
   bool Set(const std::string& setting, const base::Value& value) override;
 
-  // NotificationObserver:
-  void Observe(int type,
-               const content::NotificationSource& source,
-               const content::NotificationDetails& details) override;
-
  private:
   bool set_management_settings_result_ = true;
   ManagementSettings last_settings_;
   StubCrosSettingsProvider* settings_provider_;
-  // Creating TestingProfiles after constructing a FakeOwnerSettingsService
-  // causes the underlying OwnerSettingsServiceChromeOS::Observe to be called,
-  // which can be bad in tests.
-  bool ignore_profile_creation_notifications_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(FakeOwnerSettingsService);
 };
diff --git a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc
index 6b5b07f..86da9ef5 100644
--- a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc
+++ b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc
@@ -19,13 +19,14 @@
 #include "base/stl_util.h"
 #include "base/task/post_task.h"
 #include "base/threading/thread_checker.h"
-#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
 #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/chromeos/settings/device_settings_provider.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/tpm/install_attributes.h"
 #include "chromeos/tpm/tpm_token_loader.h"
@@ -35,9 +36,6 @@
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_source.h"
 #include "content/public/common/content_switches.h"
 #include "crypto/nss_key_util.h"
 #include "crypto/nss_util.h"
@@ -204,10 +202,6 @@
   if (device_settings_service_)
     device_settings_service_->AddObserver(this);
 
-  registrar_.Add(this,
-                 chrome::NOTIFICATION_PROFILE_CREATED,
-                 content::Source<Profile>(profile_));
-
   if (!user_manager::UserManager::IsInitialized()) {
     // interactive_ui_tests does not set user manager.
     waiting_for_easy_unlock_operation_finshed_ = false;
@@ -217,11 +211,18 @@
   UserSessionManager::GetInstance()->WaitForEasyUnlockKeyOpsFinished(
       base::Bind(&OwnerSettingsServiceChromeOS::OnEasyUnlockKeyOpsFinished,
                  weak_factory_.GetWeakPtr()));
+  // The ProfileManager may be null in unit tests.
+  if (g_browser_process->profile_manager())
+    g_browser_process->profile_manager()->AddObserver(this);
 }
 
 OwnerSettingsServiceChromeOS::~OwnerSettingsServiceChromeOS() {
   DCHECK(thread_checker_.CalledOnValidThread());
 
+  // The ProfileManager may be null in unit tests.
+  if (g_browser_process->profile_manager())
+    g_browser_process->profile_manager()->RemoveObserver(this);
+
   if (device_settings_service_)
     device_settings_service_->RemoveObserver(this);
 
@@ -349,20 +350,12 @@
   return true;
 }
 
-void OwnerSettingsServiceChromeOS::Observe(
-    int type,
-    const content::NotificationSource& source,
-    const content::NotificationDetails& details) {
+void OwnerSettingsServiceChromeOS::OnProfileAdded(Profile* profile) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK_EQ(chrome::NOTIFICATION_PROFILE_CREATED, type);
-
-  Profile* profile = content::Source<Profile>(source).ptr();
-  if (profile != profile_) {
-    NOTREACHED();
+  if (profile != profile_)
     return;
-  }
 
-  waiting_for_profile_creation_ = false;
+  g_browser_process->profile_manager()->RemoveObserver(this);
   ReloadKeypair();
 }
 
@@ -693,11 +686,17 @@
          const scoped_refptr<PrivateKey>& private_key)>& callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  if (waiting_for_profile_creation_ || waiting_for_tpm_token_ ||
-      waiting_for_easy_unlock_operation_finshed_) {
+  // The profile may not be fully created yet: abort, and wait till it is. The
+  // ProfileManager may be null in unit tests, in which case we can assume the
+  // profile is valid.
+  if (g_browser_process->profile_manager() &&
+      !g_browser_process->profile_manager()->IsValidProfile(profile_)) {
     return;
   }
 
+  if (waiting_for_tpm_token_ || waiting_for_easy_unlock_operation_finshed_)
+    return;
+
   bool rv = base::PostTask(
       FROM_HERE, {BrowserThread::IO},
       base::BindOnce(&LoadPrivateKeyOnIOThread, owner_key_util_,
diff --git a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h
index 18c591d..aa54cb9 100644
--- a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h
+++ b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h
@@ -13,14 +13,13 @@
 #include "base/macros.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/settings/device_settings_service.h"
+#include "chrome/browser/profiles/profile_manager_observer.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/ownership/owner_key_util.h"
 #include "components/ownership/owner_settings_service.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
 
 class Profile;
 
@@ -42,7 +41,7 @@
 // TODO (ygorshenin@): move write path for device settings here
 // (crbug.com/230018).
 class OwnerSettingsServiceChromeOS : public ownership::OwnerSettingsService,
-                                     public content::NotificationObserver,
+                                     public ProfileManagerObserver,
                                      public SessionManagerClient::Observer,
                                      public DeviceSettingsService::Observer {
  public:
@@ -78,10 +77,8 @@
   bool CommitTentativeDeviceSettings(
       std::unique_ptr<enterprise_management::PolicyData> policy) override;
 
-  // NotificationObserver implementation:
-  void Observe(int type,
-               const content::NotificationSource& source,
-               const content::NotificationDetails& details) override;
+  // ProfileManagerObserver:
+  void OnProfileAdded(Profile* profile) override;
 
   // SessionManagerClient::Observer:
   void OwnerKeySet(bool success) override;
@@ -165,9 +162,6 @@
   // User ID this service instance belongs to.
   std::string user_id_;
 
-  // Whether profile still needs to be initialized.
-  bool waiting_for_profile_creation_ = true;
-
   // Whether TPM token still needs to be initialized.
   bool waiting_for_tpm_token_ = true;
 
@@ -185,8 +179,6 @@
   std::unique_ptr<enterprise_management::ChromeDeviceSettingsProto>
       tentative_settings_;
 
-  content::NotificationRegistrar registrar_;
-
   base::WeakPtrFactory<OwnerSettingsServiceChromeOS> weak_factory_{this};
 
   base::WeakPtrFactory<OwnerSettingsServiceChromeOS> store_settings_factory_{
diff --git a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.cc b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.cc
index aa1e343..1724e18 100644
--- a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.cc
+++ b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.cc
@@ -37,11 +37,10 @@
 OwnerSettingsServiceChromeOSFactory::OwnerSettingsServiceChromeOSFactory()
     : BrowserContextKeyedServiceFactory(
           "OwnerSettingsService",
-          BrowserContextDependencyManager::GetInstance()) {
-}
+          BrowserContextDependencyManager::GetInstance()) {}
 
-OwnerSettingsServiceChromeOSFactory::~OwnerSettingsServiceChromeOSFactory() {
-}
+OwnerSettingsServiceChromeOSFactory::~OwnerSettingsServiceChromeOSFactory() =
+    default;
 
 // static
 OwnerSettingsServiceChromeOS*
@@ -87,18 +86,29 @@
   owner_key_util_ = owner_key_util;
 }
 
-// static
-KeyedService* OwnerSettingsServiceChromeOSFactory::BuildInstanceFor(
-    content::BrowserContext* browser_context) {
-  Profile* profile = static_cast<Profile*>(browser_context);
-  if (profile->IsGuestSession() || ProfileHelper::IsSigninProfile(profile) ||
+content::BrowserContext*
+OwnerSettingsServiceChromeOSFactory::GetBrowserContextToUse(
+    content::BrowserContext* context) const {
+  Profile* profile = Profile::FromBrowserContext(context);
+  if (profile->IsOffTheRecord() || ProfileHelper::IsSigninProfile(profile) ||
       ProfileHelper::IsLockScreenAppProfile(profile)) {
     return nullptr;
   }
 
+  return context;
+}
+
+bool OwnerSettingsServiceChromeOSFactory::ServiceIsCreatedWithBrowserContext()
+    const {
+  return true;
+}
+
+KeyedService* OwnerSettingsServiceChromeOSFactory::BuildServiceInstanceFor(
+    content::BrowserContext* context) const {
   // If g_stub_cros_settings_provider_for_testing_ is set, we treat the current
   // user as the owner, and write settings directly to the stubbed provider.
   // This is done using the FakeOwnerSettingsService.
+  Profile* profile = Profile::FromBrowserContext(context);
   if (g_stub_cros_settings_provider_for_testing_ != nullptr) {
     return new FakeOwnerSettingsService(
         g_stub_cros_settings_provider_for_testing_, profile,
@@ -111,14 +121,4 @@
       GetInstance()->GetOwnerKeyUtil());
 }
 
-bool OwnerSettingsServiceChromeOSFactory::ServiceIsCreatedWithBrowserContext()
-    const {
-  return true;
-}
-
-KeyedService* OwnerSettingsServiceChromeOSFactory::BuildServiceInstanceFor(
-    content::BrowserContext* context) const {
-  return BuildInstanceFor(context);
-}
-
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h
index bf7d6f6..2854bdb8 100644
--- a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h
+++ b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h
@@ -53,9 +53,9 @@
   OwnerSettingsServiceChromeOSFactory();
   ~OwnerSettingsServiceChromeOSFactory() override;
 
-  static KeyedService* BuildInstanceFor(content::BrowserContext* context);
-
   // BrowserContextKeyedServiceFactory overrides:
+  content::BrowserContext* GetBrowserContextToUse(
+      content::BrowserContext* context) const override;
   bool ServiceIsCreatedWithBrowserContext() const override;
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* browser_context) const override;
diff --git a/chrome/browser/chromeos/policy/scheduled_update_checker/device_scheduled_update_checker_unittest.cc b/chrome/browser/chromeos/policy/scheduled_update_checker/device_scheduled_update_checker_unittest.cc
index a21e534..9bb0263 100644
--- a/chrome/browser/chromeos/policy/scheduled_update_checker/device_scheduled_update_checker_unittest.cc
+++ b/chrome/browser/chromeos/policy/scheduled_update_checker/device_scheduled_update_checker_unittest.cc
@@ -348,10 +348,9 @@
   // Notifies status update from |fake_update_engine_client_| and runs scheduled
   // tasks to ensure that the pending policy refresh completes.
   void NotifyUpdateCheckStatus(
-      chromeos::UpdateEngineClient::UpdateStatusOperation
-          update_status_operation) {
-    chromeos::UpdateEngineClient::Status status = {};
-    status.status = update_status_operation;
+      update_engine::Operation update_status_operation) {
+    update_engine::StatusResult status;
+    status.set_current_operation(update_status_operation);
     fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
     task_environment_.RunUntilIdle();
   }
@@ -430,9 +429,7 @@
     task_environment_.FastForwardBy(small_delay);
 
     // Simulate update check succeeding.
-    NotifyUpdateCheckStatus(
-        chromeos::UpdateEngineClient::UpdateStatusOperation::
-            UPDATE_STATUS_UPDATED_NEED_REBOOT);
+    NotifyUpdateCheckStatus(update_engine::Operation::UPDATED_NEED_REBOOT);
     if (!CheckStats(expected_update_checks, expected_update_check_requests,
                     expected_update_check_completions)) {
       return false;
@@ -447,9 +444,7 @@
       task_environment_.FastForwardBy(base::TimeDelta::FromDays(1));
 
       // Simulate update check succeeding.
-      NotifyUpdateCheckStatus(
-          chromeos::UpdateEngineClient::UpdateStatusOperation::
-              UPDATE_STATUS_UPDATED_NEED_REBOOT);
+      NotifyUpdateCheckStatus(update_engine::Operation::UPDATED_NEED_REBOOT);
       if (!CheckStats(expected_update_checks, expected_update_check_requests,
                       expected_update_check_completions)) {
         return false;
@@ -578,9 +573,7 @@
     expected_update_check_completions += 1;
     task_environment_.FastForwardBy(small_delay);
     // Simulate update check succeeding.
-    NotifyUpdateCheckStatus(
-        chromeos::UpdateEngineClient::UpdateStatusOperation::
-            UPDATE_STATUS_UPDATED_NEED_REBOOT);
+    NotifyUpdateCheckStatus(update_engine::Operation::UPDATED_NEED_REBOOT);
     if (!CheckStats(expected_update_checks, expected_update_check_requests,
                     expected_update_check_completions)) {
       ADD_FAILURE()
@@ -641,8 +634,7 @@
   expected_update_check_completions += 1;
   task_environment_.FastForwardBy(small_delay);
   // Simulate update check succeeding.
-  NotifyUpdateCheckStatus(chromeos::UpdateEngineClient::UpdateStatusOperation::
-                              UPDATE_STATUS_UPDATED_NEED_REBOOT);
+  NotifyUpdateCheckStatus(update_engine::Operation::UPDATED_NEED_REBOOT);
   EXPECT_TRUE(CheckStats(expected_update_checks, expected_update_check_requests,
                          expected_update_check_completions));
 
@@ -652,8 +644,7 @@
   expected_update_check_completions += 1;
   task_environment_.FastForwardBy(base::TimeDelta::FromDays(7));
   // Simulate update check succeeding.
-  NotifyUpdateCheckStatus(chromeos::UpdateEngineClient::UpdateStatusOperation::
-                              UPDATE_STATUS_UPDATED_NEED_REBOOT);
+  NotifyUpdateCheckStatus(update_engine::Operation::UPDATED_NEED_REBOOT);
   EXPECT_TRUE(CheckStats(expected_update_checks, expected_update_check_requests,
                          expected_update_check_completions));
 }
@@ -692,8 +683,7 @@
   expected_update_check_completions += 1;
   task_environment_.FastForwardBy(small_delay);
   // Simulate update check succeeding.
-  NotifyUpdateCheckStatus(chromeos::UpdateEngineClient::UpdateStatusOperation::
-                              UPDATE_STATUS_UPDATED_NEED_REBOOT);
+  NotifyUpdateCheckStatus(update_engine::Operation::UPDATED_NEED_REBOOT);
   EXPECT_TRUE(CheckStats(expected_update_checks, expected_update_check_requests,
                          expected_update_check_completions));
 
@@ -712,8 +702,7 @@
   EXPECT_GT(second_update_check_delay, update_checker_internal::kInvalidDelay);
   task_environment_.FastForwardBy(second_update_check_delay);
   // Simulate update check succeeding.
-  NotifyUpdateCheckStatus(chromeos::UpdateEngineClient::UpdateStatusOperation::
-                              UPDATE_STATUS_UPDATED_NEED_REBOOT);
+  NotifyUpdateCheckStatus(update_engine::Operation::UPDATED_NEED_REBOOT);
   EXPECT_TRUE(CheckStats(expected_update_checks, expected_update_check_requests,
                          expected_update_check_completions));
 }
@@ -747,8 +736,7 @@
       std::move(policy_and_next_update_check_time.first));
   task_environment_.FastForwardBy(delay_from_now);
   // Simulate update check succeeding.
-  NotifyUpdateCheckStatus(chromeos::UpdateEngineClient::UpdateStatusOperation::
-                              UPDATE_STATUS_UPDATED_NEED_REBOOT);
+  NotifyUpdateCheckStatus(update_engine::Operation::UPDATED_NEED_REBOOT);
   EXPECT_TRUE(CheckStats(expected_update_checks, expected_update_check_requests,
                          expected_update_check_completions));
 
@@ -777,9 +765,7 @@
     expected_update_check_completions += 1;
     task_environment_.FastForwardBy(small_delay);
     // Simulate update check succeeding.
-    NotifyUpdateCheckStatus(
-        chromeos::UpdateEngineClient::UpdateStatusOperation::
-            UPDATE_STATUS_UPDATED_NEED_REBOOT);
+    NotifyUpdateCheckStatus(update_engine::Operation::UPDATED_NEED_REBOOT);
     EXPECT_TRUE(CheckStats(expected_update_checks,
                            expected_update_check_requests,
                            expected_update_check_completions));
@@ -844,9 +830,7 @@
     expected_update_check_completions += 1;
     task_environment_.FastForwardBy(small_delay);
     // Simulate update check succeeding.
-    NotifyUpdateCheckStatus(
-        chromeos::UpdateEngineClient::UpdateStatusOperation::
-            UPDATE_STATUS_UPDATED_NEED_REBOOT);
+    NotifyUpdateCheckStatus(update_engine::Operation::UPDATED_NEED_REBOOT);
     EXPECT_TRUE(CheckStats(expected_update_checks,
                            expected_update_check_requests,
                            expected_update_check_completions));
@@ -923,8 +907,7 @@
   int expected_update_check_requests = 1;
   int expected_update_check_completions = 0;
   task_environment_.FastForwardBy(delay_from_now);
-  NotifyUpdateCheckStatus(
-      chromeos::UpdateEngineClient::UpdateStatusOperation::UPDATE_STATUS_ERROR);
+  NotifyUpdateCheckStatus(update_engine::Operation::ERROR);
   EXPECT_TRUE(CheckStats(expected_update_checks, expected_update_check_requests,
                          expected_update_check_completions));
 
@@ -938,8 +921,7 @@
     task_environment_.FastForwardBy(
         update_checker_internal::kOsAndPoliciesUpdateCheckerRetryTime);
     // Simulate update check failing.
-    NotifyUpdateCheckStatus(chromeos::UpdateEngineClient::
-                                UpdateStatusOperation::UPDATE_STATUS_ERROR);
+    NotifyUpdateCheckStatus(update_engine::Operation::ERROR);
     EXPECT_TRUE(CheckStats(expected_update_checks,
                            expected_update_check_requests,
                            expected_update_check_completions));
@@ -986,8 +968,7 @@
   int expected_update_check_completions = 0;
   task_environment_.FastForwardBy(delay_from_now);
   // Simulate update check succeeding.
-  NotifyUpdateCheckStatus(
-      chromeos::UpdateEngineClient::UpdateStatusOperation::UPDATE_STATUS_ERROR);
+  NotifyUpdateCheckStatus(update_engine::Operation::ERROR);
   EXPECT_TRUE(CheckStats(expected_update_checks, expected_update_check_requests,
                          expected_update_check_completions));
 
@@ -1001,8 +982,7 @@
     expected_update_check_requests += 1;
     task_environment_.FastForwardBy(
         update_checker_internal::kOsAndPoliciesUpdateCheckerRetryTime);
-    NotifyUpdateCheckStatus(chromeos::UpdateEngineClient::
-                                UpdateStatusOperation::UPDATE_STATUS_ERROR);
+    NotifyUpdateCheckStatus(update_engine::Operation::ERROR);
     EXPECT_TRUE(CheckStats(expected_update_checks,
                            expected_update_check_requests,
                            expected_update_check_completions));
@@ -1014,8 +994,7 @@
   expected_update_check_completions += 1;
   task_environment_.FastForwardBy(
       update_checker_internal::kOsAndPoliciesUpdateCheckerRetryTime);
-  NotifyUpdateCheckStatus(chromeos::UpdateEngineClient::UpdateStatusOperation::
-                              UPDATE_STATUS_UPDATED_NEED_REBOOT);
+  NotifyUpdateCheckStatus(update_engine::Operation::UPDATED_NEED_REBOOT);
   EXPECT_TRUE(CheckStats(expected_update_checks, expected_update_check_requests,
                          expected_update_check_completions));
 }
@@ -1052,8 +1031,7 @@
       std::move(policy_and_next_update_check_time.first));
   expected_update_check_completions += 1;
   // Simulate update check succeeding.
-  NotifyUpdateCheckStatus(chromeos::UpdateEngineClient::UpdateStatusOperation::
-                              UPDATE_STATUS_UPDATED_NEED_REBOOT);
+  NotifyUpdateCheckStatus(update_engine::Operation::UPDATED_NEED_REBOOT);
   EXPECT_TRUE(CheckStats(expected_update_checks, expected_update_check_requests,
                          expected_update_check_completions));
 
@@ -1064,8 +1042,7 @@
   expected_update_check_completions += 1;
   task_environment_.FastForwardBy(delay_from_now);
   // Simulate update check succeeding.
-  NotifyUpdateCheckStatus(chromeos::UpdateEngineClient::UpdateStatusOperation::
-                              UPDATE_STATUS_UPDATED_NEED_REBOOT);
+  NotifyUpdateCheckStatus(update_engine::Operation::UPDATED_NEED_REBOOT);
   EXPECT_TRUE(CheckStats(expected_update_checks, expected_update_check_requests,
                          expected_update_check_completions));
 }
@@ -1127,8 +1104,7 @@
       base::TimeDelta::FromDays(1) -
       update_checker_internal::kWaitForNetworkTimeout);
   // Simulate update check succeeding.
-  NotifyUpdateCheckStatus(chromeos::UpdateEngineClient::UpdateStatusOperation::
-                              UPDATE_STATUS_UPDATED_NEED_REBOOT);
+  NotifyUpdateCheckStatus(update_engine::Operation::UPDATED_NEED_REBOOT);
   EXPECT_TRUE(CheckStats(expected_update_checks, expected_update_check_requests,
                          expected_update_check_completions));
 }
@@ -1172,8 +1148,7 @@
   expected_update_check_requests += 1;
   expected_update_check_completions += 1;
   // Simulate update check succeeding.
-  NotifyUpdateCheckStatus(chromeos::UpdateEngineClient::UpdateStatusOperation::
-                              UPDATE_STATUS_UPDATED_NEED_REBOOT);
+  NotifyUpdateCheckStatus(update_engine::Operation::UPDATED_NEED_REBOOT);
   EXPECT_TRUE(CheckStats(expected_update_checks, expected_update_check_requests,
                          expected_update_check_completions));
 }
@@ -1204,8 +1179,7 @@
   task_environment_.RunUntilIdle();
 
   // Simulate update check succeeding.
-  NotifyUpdateCheckStatus(chromeos::UpdateEngineClient::UpdateStatusOperation::
-                              UPDATE_STATUS_UPDATED_NEED_REBOOT);
+  NotifyUpdateCheckStatus(update_engine::Operation::UPDATED_NEED_REBOOT);
 
   base::Optional<int> active_wake_locks_after_update_check;
   wake_lock_provider_.GetActiveWakeLocksForTests(
diff --git a/chrome/browser/chromeos/policy/scheduled_update_checker/os_and_policies_update_checker.cc b/chrome/browser/chromeos/policy/scheduled_update_checker/os_and_policies_update_checker.cc
index 4f0caf8..95656088 100644
--- a/chrome/browser/chromeos/policy/scheduled_update_checker/os_and_policies_update_checker.cc
+++ b/chrome/browser/chromeos/policy/scheduled_update_checker/os_and_policies_update_checker.cc
@@ -81,9 +81,8 @@
 void OsAndPoliciesUpdateChecker::ScheduleUpdateCheck() {
   // If an update was downloaded but not applied then update engine won't do
   // anything. Move straight to the policy state.
-  if (update_engine_client_->GetLastStatus().status ==
-      chromeos::UpdateEngineClient::UpdateStatusOperation::
-          UPDATE_STATUS_UPDATED_NEED_REBOOT) {
+  if (update_engine_client_->GetLastStatus().current_operation() ==
+      update_engine::Operation::UPDATED_NEED_REBOOT) {
     RefreshPolicies(true /* update_check_result */);
     return;
   }
@@ -138,17 +137,16 @@
 }
 
 void OsAndPoliciesUpdateChecker::UpdateStatusChanged(
-    const chromeos::UpdateEngineClient::Status& status) {
+    const update_engine::StatusResult& status) {
   // Only ignore idle state if it is the first and only non-error state in the
   // state machine.
   if (ignore_idle_status_ &&
-      status.status > chromeos::UpdateEngineClient::UPDATE_STATUS_IDLE) {
+      status.current_operation() > update_engine::Operation::IDLE) {
     ignore_idle_status_ = false;
   }
 
-  switch (status.status) {
-    case chromeos::UpdateEngineClient::UpdateStatusOperation::
-        UPDATE_STATUS_IDLE:
+  switch (status.current_operation()) {
+    case update_engine::Operation::IDLE:
       if (!ignore_idle_status_) {
         // No update to download or an error occured mid-way of an existing
         // update download.
@@ -158,38 +156,32 @@
       }
       break;
 
-    case chromeos::UpdateEngineClient::UpdateStatusOperation::
-        UPDATE_STATUS_UPDATED_NEED_REBOOT:
+    case update_engine::Operation::UPDATED_NEED_REBOOT:
       // Refresh policies after the update check is finished successfully or
       // unsuccessfully.
       RefreshPolicies(true /* update_check_result */);
       break;
 
-    case chromeos::UpdateEngineClient::UpdateStatusOperation::
-        UPDATE_STATUS_ERROR:
-    case chromeos::UpdateEngineClient::UpdateStatusOperation::
-        UPDATE_STATUS_NEED_PERMISSION_TO_UPDATE:
-    case chromeos::UpdateEngineClient::UpdateStatusOperation::
-        UPDATE_STATUS_REPORTING_ERROR_EVENT:
+    case update_engine::Operation::ERROR:
+    case update_engine::Operation::DISABLED:
+    case update_engine::Operation::NEED_PERMISSION_TO_UPDATE:
+    case update_engine::Operation::REPORTING_ERROR_EVENT:
       update_check_task_executor_.ScheduleRetry(
           base::BindOnce(&OsAndPoliciesUpdateChecker::StartUpdateCheck,
                          base::Unretained(this)));
       break;
 
-    case chromeos::UpdateEngineClient::UpdateStatusOperation::
-        UPDATE_STATUS_FINALIZING:
-    case chromeos::UpdateEngineClient::UpdateStatusOperation::
-        UPDATE_STATUS_VERIFYING:
-    case chromeos::UpdateEngineClient::UpdateStatusOperation::
-        UPDATE_STATUS_DOWNLOADING:
-    case chromeos::UpdateEngineClient::UpdateStatusOperation::
-        UPDATE_STATUS_UPDATE_AVAILABLE:
-    case chromeos::UpdateEngineClient::UpdateStatusOperation::
-        UPDATE_STATUS_CHECKING_FOR_UPDATE:
-    case chromeos::UpdateEngineClient::UpdateStatusOperation::
-        UPDATE_STATUS_ATTEMPTING_ROLLBACK:
+    case update_engine::Operation::FINALIZING:
+    case update_engine::Operation::VERIFYING:
+    case update_engine::Operation::DOWNLOADING:
+    case update_engine::Operation::UPDATE_AVAILABLE:
+    case update_engine::Operation::CHECKING_FOR_UPDATE:
+    case update_engine::Operation::ATTEMPTING_ROLLBACK:
       // Do nothing on intermediate states.
       break;
+
+    default:
+      NOTREACHED();
   }
 }
 
diff --git a/chrome/browser/chromeos/policy/scheduled_update_checker/os_and_policies_update_checker.h b/chrome/browser/chromeos/policy/scheduled_update_checker/os_and_policies_update_checker.h
index 34051e9..af57ae2 100644
--- a/chrome/browser/chromeos/policy/scheduled_update_checker/os_and_policies_update_checker.h
+++ b/chrome/browser/chromeos/policy/scheduled_update_checker/os_and_policies_update_checker.h
@@ -86,8 +86,7 @@
   void StartUpdateCheck();
 
   // UpdateEngineClient::Observer overrides.
-  void UpdateStatusChanged(
-      const chromeos::UpdateEngineClient::Status& status) override;
+  void UpdateStatusChanged(const update_engine::StatusResult& status) override;
 
   // Tells whether starting an update check succeeded or not.
   void OnUpdateCheckStarted(
diff --git a/chrome/browser/chromeos/policy/status_collector/child_status_collector_browsertest.cc b/chrome/browser/chromeos/policy/status_collector/child_status_collector_browsertest.cc
index cfa5ab7..3cfdc2f2 100644
--- a/chrome/browser/chromeos/policy/status_collector/child_status_collector_browsertest.cc
+++ b/chrome/browser/chromeos/policy/status_collector/child_status_collector_browsertest.cc
@@ -214,8 +214,6 @@
     TestingChildStatusCollector::RegisterProfilePrefs(
         profile_pref_service_.registry());
 
-    owner_settings_service_.set_ignore_profile_creation_notification(true);
-
     TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_);
 
     // Use FakeUpdateEngineClient.
diff --git a/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc b/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc
index 98d663db..41fcaf5 100644
--- a/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc
+++ b/chrome/browser/chromeos/policy/status_collector/device_status_collector.cc
@@ -1745,7 +1745,7 @@
   os_update_status->set_new_required_platform_version(
       required_platfrom_version.GetString());
 
-  const chromeos::UpdateEngineClient::Status update_engine_status =
+  const update_engine::StatusResult update_engine_status =
       chromeos::DBusThreadManager::Get()
           ->GetUpdateEngineClient()
           ->GetLastStatus();
@@ -1761,7 +1761,7 @@
   // As the timestamp precision return from UpdateEngine is in seconds (see
   // time_t). It should be converted to milliseconds before being reported.
   const base::Time last_checked_timestamp =
-      base::Time::FromTimeT(update_engine_status.last_checked_time);
+      base::Time::FromTimeT(update_engine_status.last_checked_time());
 
   os_update_status->set_last_checked_timestamp(
       last_checked_timestamp.ToJavaTime());
@@ -1771,24 +1771,24 @@
     return true;
   }
 
-  if (update_engine_status.status ==
-          chromeos::UpdateEngineClient::UPDATE_STATUS_DOWNLOADING ||
-      update_engine_status.status ==
-          chromeos::UpdateEngineClient::UPDATE_STATUS_VERIFYING ||
-      update_engine_status.status ==
-          chromeos::UpdateEngineClient::UPDATE_STATUS_FINALIZING) {
+  if (update_engine_status.current_operation() ==
+          update_engine::Operation::DOWNLOADING ||
+      update_engine_status.current_operation() ==
+          update_engine::Operation::VERIFYING ||
+      update_engine_status.current_operation() ==
+          update_engine::Operation::FINALIZING) {
     os_update_status->set_update_status(
         em::OsUpdateStatus::OS_IMAGE_DOWNLOAD_IN_PROGRESS);
     os_update_status->set_new_platform_version(
-        update_engine_status.new_version);
-  } else if (update_engine_status.status ==
-             chromeos::UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT) {
+        update_engine_status.new_version());
+  } else if (update_engine_status.current_operation() ==
+             update_engine::Operation::UPDATED_NEED_REBOOT) {
     os_update_status->set_update_status(
         em::OsUpdateStatus::OS_UPDATE_NEED_REBOOT);
     // Note the new_version could be a dummy "0.0.0.0" for some edge cases,
     // e.g. update engine is somehow restarted without a reboot.
     os_update_status->set_new_platform_version(
-        update_engine_status.new_version);
+        update_engine_status.new_version());
   } else {
     os_update_status->set_update_status(
         em::OsUpdateStatus::OS_IMAGE_DOWNLOAD_NOT_STARTED);
diff --git a/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc b/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc
index 6cfa7ba..fe6bfd5 100644
--- a/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc
+++ b/chrome/browser/chromeos/policy/status_collector/device_status_collector_browsertest.cc
@@ -421,8 +421,6 @@
     TestingDeviceStatusCollector::RegisterProfilePrefs(
         profile_pref_service_.registry());
 
-    owner_settings_service_.set_ignore_profile_creation_notification(true);
-
     // Set up a fake local state for KioskAppManager.
     TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_);
     chromeos::KioskAppManager::RegisterPrefs(local_state_.registry());
@@ -2005,24 +2003,23 @@
   MockAutoLaunchKioskAppWithRequiredPlatformVersion(
       fake_kiosk_device_local_account_, "1235");
 
-  chromeos::UpdateEngineClient::Status update_status;
-  update_status.status = chromeos::UpdateEngineClient::UPDATE_STATUS_IDLE;
+  update_engine::StatusResult update_status;
+  update_status.set_current_operation(update_engine::Operation::IDLE);
 
   GetStatus();
   ASSERT_TRUE(device_status_.has_os_update_status());
   EXPECT_EQ(em::OsUpdateStatus::OS_IMAGE_DOWNLOAD_NOT_STARTED,
             device_status_.os_update_status().update_status());
 
-  const chromeos::UpdateEngineClient::UpdateStatusOperation kUpdateEngineOps[] =
-      {
-          chromeos::UpdateEngineClient::UPDATE_STATUS_DOWNLOADING,
-          chromeos::UpdateEngineClient::UPDATE_STATUS_VERIFYING,
-          chromeos::UpdateEngineClient::UPDATE_STATUS_FINALIZING,
-      };
+  const update_engine::Operation kUpdateEngineOps[] = {
+      update_engine::Operation::DOWNLOADING,
+      update_engine::Operation::VERIFYING,
+      update_engine::Operation::FINALIZING,
+  };
 
   for (size_t i = 0; i < base::size(kUpdateEngineOps); ++i) {
-    update_status.status = kUpdateEngineOps[i];
-    update_status.new_version = "1235.1.2";
+    update_status.set_current_operation(kUpdateEngineOps[i]);
+    update_status.set_new_version("1235.1.2");
     update_engine_client_->PushLastStatus(update_status);
 
     GetStatus();
@@ -2036,8 +2033,8 @@
         device_status_.os_update_status().new_required_platform_version());
   }
 
-  update_status.status =
-      chromeos::UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT;
+  update_status.set_current_operation(
+      update_engine::Operation::UPDATED_NEED_REBOOT);
   update_engine_client_->PushLastStatus(update_status);
   GetStatus();
   ASSERT_TRUE(device_status_.has_os_update_status());
@@ -2067,9 +2064,9 @@
   const int64 kLastCheckedTimes[] = {10, 20, 30};
 
   for (size_t i = 0; i < base::size(kLastCheckedTimes); ++i) {
-    chromeos::UpdateEngineClient::Status update_status;
-    update_status.new_version = kDefaultPlatformVersion;
-    update_status.last_checked_time = kLastCheckedTimes[i];
+    update_engine::StatusResult update_status;
+    update_status.set_new_version(kDefaultPlatformVersion);
+    update_status.set_last_checked_time(kLastCheckedTimes[i]);
     update_engine_client_->PushLastStatus(update_status);
 
     GetStatus();
diff --git a/chrome/browser/chromeos/system/automatic_reboot_manager.cc b/chrome/browser/chromeos/system/automatic_reboot_manager.cc
index ce12a10..5145dc3a 100644
--- a/chrome/browser/chromeos/system/automatic_reboot_manager.cc
+++ b/chrome/browser/chromeos/system/automatic_reboot_manager.cc
@@ -210,11 +210,12 @@
 }
 
 void AutomaticRebootManager::UpdateStatusChanged(
-    const UpdateEngineClient::Status& status) {
+    const update_engine::StatusResult& status) {
   // Ignore repeated notifications that a reboot is necessary. This is important
   // so that only the time of the first notification is taken into account and
   // repeated notifications do not postpone the reboot request and grace period.
-  if (status.status != UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT ||
+  if (status.current_operation() !=
+          update_engine::Operation::UPDATED_NEED_REBOOT ||
       !boot_time_ || update_reboot_needed_time_) {
     return;
   }
diff --git a/chrome/browser/chromeos/system/automatic_reboot_manager.h b/chrome/browser/chromeos/system/automatic_reboot_manager.h
index 16a205f..1264c38 100644
--- a/chrome/browser/chromeos/system/automatic_reboot_manager.h
+++ b/chrome/browser/chromeos/system/automatic_reboot_manager.h
@@ -103,7 +103,7 @@
   void SuspendDone(const base::TimeDelta& sleep_duration) override;
 
   // UpdateEngineClient::Observer:
-  void UpdateStatusChanged(const UpdateEngineClient::Status& status) override;
+  void UpdateStatusChanged(const update_engine::StatusResult& status) override;
 
   // ui::UserActivityObserver:
   void OnUserActivity(const ui::Event* event) override;
diff --git a/chrome/browser/chromeos/system/automatic_reboot_manager_unittest.cc b/chrome/browser/chromeos/system/automatic_reboot_manager_unittest.cc
index 9efe791b..7c5e209 100644
--- a/chrome/browser/chromeos/system/automatic_reboot_manager_unittest.cc
+++ b/chrome/browser/chromeos/system/automatic_reboot_manager_unittest.cc
@@ -537,8 +537,9 @@
 }
 
 void AutomaticRebootManagerBasicTest::SetUpdateStatusNeedReboot() {
-  UpdateEngineClient::Status client_status;
-  client_status.status = UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT;
+  update_engine::StatusResult client_status;
+  client_status.set_current_operation(
+      update_engine::Operation::UPDATED_NEED_REBOOT);
   update_engine_client_->set_default_status(client_status);
 }
 
diff --git a/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest_chromeos.cc b/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest_chromeos.cc
index 97b4ffd67..1388674 100644
--- a/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest_chromeos.cc
+++ b/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest_chromeos.cc
@@ -39,19 +39,14 @@
   }
 
   void TearDownOnMainThread() override {
-    PlatformAppBrowserTest::TearDownOnMainThread();
+    owner_settings_service_.reset();
     settings_helper_.RestoreRealDeviceSettingsProvider();
+    PlatformAppBrowserTest::TearDownOnMainThread();
     user_manager_enabler_.reset();
     fake_user_manager_ = nullptr;
   }
 
  protected:
-  chromeos::FakeChromeUserManager* fake_user_manager_;
-  std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_;
-
-  chromeos::ScopedCrosSettingsTestHelper settings_helper_;
-  std::unique_ptr<chromeos::FakeOwnerSettingsService> owner_settings_service_;
-
   void EnterKioskSession() {
     fake_user_manager_ = new chromeos::FakeChromeUserManager();
     user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>(
@@ -72,6 +67,12 @@
   chromeos::KioskAppManager* manager() const {
     return chromeos::KioskAppManager::Get();
   }
+
+  chromeos::FakeChromeUserManager* fake_user_manager_;
+  std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_;
+
+  chromeos::ScopedCrosSettingsTestHelper settings_helper_;
+  std::unique_ptr<chromeos::FakeOwnerSettingsService> owner_settings_service_;
 };
 
 IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTestChromeOs,
diff --git a/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc b/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc
index b2e4c22d..5eb5d196 100644
--- a/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc
+++ b/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc
@@ -106,7 +106,8 @@
   syncer::SyncService* sync_service =
       ProfileSyncServiceFactory::GetForProfile(profile);
   sync_service->GetUserSettings()->SetSyncRequested(true);
-  sync_service->GetUserSettings()->SetFirstSetupComplete();
+  sync_service->GetUserSettings()->SetFirstSetupComplete(
+      syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
 
   ASSERT_EQ(sync_ui_util::SYNCED, sync_ui_util::GetStatus(profile));
   // Clear browsing data.
diff --git a/chrome/browser/extensions/api/chrome_extensions_api_client.cc b/chrome/browser/extensions/api/chrome_extensions_api_client.cc
index 4772d8e..4db7f5c5 100644
--- a/chrome/browser/extensions/api/chrome_extensions_api_client.cc
+++ b/chrome/browser/extensions/api/chrome_extensions_api_client.cc
@@ -39,8 +39,8 @@
 #include "chrome/browser/guest_view/mime_handler_view/chrome_mime_handler_view_guest_delegate.h"
 #include "chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.h"
 #include "chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
 #include "chrome/browser/performance_manager/performance_manager_tab_helper.h"
+#include "chrome/browser/performance_manager/public/performance_manager.h"
 #include "chrome/browser/search/instant_service.h"
 #include "chrome/browser/search/instant_service_factory.h"
 #include "chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.h"
diff --git a/chrome/browser/extensions/api/system_private/system_private_api.cc b/chrome/browser/extensions/api/system_private/system_private_api.cc
index 99b8663..a657176 100644
--- a/chrome/browser/extensions/api/system_private/system_private_api.cc
+++ b/chrome/browser/extensions/api/system_private/system_private_api.cc
@@ -71,46 +71,49 @@
 #if defined(OS_CHROMEOS)
   // With UpdateEngineClient, we can provide more detailed information about
   // system updates on ChromeOS.
-  const chromeos::UpdateEngineClient::Status status =
-      chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()->
-      GetLastStatus();
+  const update_engine::StatusResult status = chromeos::DBusThreadManager::Get()
+                                                 ->GetUpdateEngineClient()
+                                                 ->GetLastStatus();
   // |download_progress| is set to 1 after download finishes
   // (i.e. verify, finalize and need-reboot phase) to indicate the progress
   // even though |status.download_progress| is 0 in these phases.
-  switch (status.status) {
-    case chromeos::UpdateEngineClient::UPDATE_STATUS_ERROR:
+  switch (status.current_operation()) {
+    case update_engine::Operation::ERROR:
+    case update_engine::Operation::DISABLED:
       state = kNotAvailableState;
       break;
-    case chromeos::UpdateEngineClient::UPDATE_STATUS_IDLE:
+    case update_engine::Operation::IDLE:
       state = kNotAvailableState;
       break;
-    case chromeos::UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE:
+    case update_engine::Operation::CHECKING_FOR_UPDATE:
       state = kNotAvailableState;
       break;
-    case chromeos::UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE:
+    case update_engine::Operation::UPDATE_AVAILABLE:
       state = kUpdatingState;
       break;
-    case chromeos::UpdateEngineClient::UPDATE_STATUS_DOWNLOADING:
+    case update_engine::Operation::DOWNLOADING:
       state = kUpdatingState;
-      download_progress = status.download_progress;
+      download_progress = status.progress();
       break;
-    case chromeos::UpdateEngineClient::UPDATE_STATUS_VERIFYING:
+    case update_engine::Operation::VERIFYING:
       state = kUpdatingState;
       download_progress = 1;
       break;
-    case chromeos::UpdateEngineClient::UPDATE_STATUS_FINALIZING:
+    case update_engine::Operation::FINALIZING:
       state = kUpdatingState;
       download_progress = 1;
       break;
-    case chromeos::UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT:
+    case update_engine::Operation::UPDATED_NEED_REBOOT:
       state = kNeedRestartState;
       download_progress = 1;
       break;
-    case chromeos::UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT:
-    case chromeos::UpdateEngineClient::UPDATE_STATUS_ATTEMPTING_ROLLBACK:
-    case chromeos::UpdateEngineClient::UPDATE_STATUS_NEED_PERMISSION_TO_UPDATE:
+    case update_engine::Operation::REPORTING_ERROR_EVENT:
+    case update_engine::Operation::ATTEMPTING_ROLLBACK:
+    case update_engine::Operation::NEED_PERMISSION_TO_UPDATE:
       state = kNotAvailableState;
       break;
+    default:
+      NOTREACHED();
   }
 #else
   if (UpgradeDetector::GetInstance()->notify_upgrade()) {
diff --git a/chrome/browser/extensions/api/system_private/system_private_apitest.cc b/chrome/browser/extensions/api/system_private/system_private_apitest.cc
index 6f14af1..c2f658b 100644
--- a/chrome/browser/extensions/api/system_private/system_private_apitest.cc
+++ b/chrome/browser/extensions/api/system_private/system_private_apitest.cc
@@ -52,14 +52,14 @@
 };
 
 IN_PROC_BROWSER_TEST_F(GetUpdateStatusApiTest, Progress) {
-  UpdateEngineClient::Status status_not_available;
-  status_not_available.status = UpdateEngineClient::UPDATE_STATUS_IDLE;
-  UpdateEngineClient::Status status_updating;
-  status_updating.status = UpdateEngineClient::UPDATE_STATUS_DOWNLOADING;
-  status_updating.download_progress = 0.5;
-  UpdateEngineClient::Status status_boot_needed;
-  status_boot_needed.status =
-      UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT;
+  update_engine::StatusResult status_not_available;
+  status_not_available.set_current_operation(update_engine::Operation::IDLE);
+  update_engine::StatusResult status_updating;
+  status_updating.set_current_operation(update_engine::Operation::DOWNLOADING);
+  status_updating.set_progress(0.5);
+  update_engine::StatusResult status_boot_needed;
+  status_boot_needed.set_current_operation(
+      update_engine::Operation::UPDATED_NEED_REBOOT);
 
   // The fake client returns the last status in this order.
   fake_update_engine_client_->PushLastStatus(status_not_available);
diff --git a/chrome/browser/extensions/chrome_extension_host_delegate.cc b/chrome/browser/extensions/chrome_extension_host_delegate.cc
index 39f9169..ee85f5c 100644
--- a/chrome/browser/extensions/chrome_extension_host_delegate.cc
+++ b/chrome/browser/extensions/chrome_extension_host_delegate.cc
@@ -14,8 +14,8 @@
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_tab_util.h"
 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
 #include "chrome/browser/performance_manager/performance_manager_tab_helper.h"
+#include "chrome/browser/performance_manager/public/performance_manager.h"
 #include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
 #include "chrome/browser/ui/prefs/prefs_tab_helper.h"
 #include "components/app_modal/javascript_dialog_manager.h"
diff --git a/chrome/browser/extensions/extension_service_sync_unittest.cc b/chrome/browser/extensions/extension_service_sync_unittest.cc
index b7e69b88..216de842 100644
--- a/chrome/browser/extensions/extension_service_sync_unittest.cc
+++ b/chrome/browser/extensions/extension_service_sync_unittest.cc
@@ -94,6 +94,8 @@
 const char good_crx[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
 const char page_action[] = "obcimlgaoabeegjmmpldobjndiealpln";
 const char theme2_crx[] = "ibcijncamhmjjdodjamgiipcgnnaeagd";
+const syncer::SyncFirstSetupCompleteSource kSetSourceFromTest =
+    syncer::SyncFirstSetupCompleteSource::BASIC_FLOW;
 
 #if BUILDFLAG(ENABLE_SUPERVISED_USERS)
 const char autoupdate[] = "ogjcoiohnmldgjemafoockdghcjciccf";
@@ -354,7 +356,7 @@
   // The user has enabled sync.
   syncer::SyncService* sync_service =
       ProfileSyncServiceFactory::GetForProfile(profile());
-  sync_service->GetUserSettings()->SetFirstSetupComplete();
+  sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
 
   service()->Init();
   ASSERT_TRUE(service()->is_ready());
@@ -391,7 +393,7 @@
   // Enable sync.
   syncer::SyncService* sync_service =
       ProfileSyncServiceFactory::GetForProfile(profile());
-  sync_service->GetUserSettings()->SetFirstSetupComplete();
+  sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
 
   service()->Init();
 
@@ -473,7 +475,7 @@
   // Enable sync.
   syncer::SyncService* sync_service =
       ProfileSyncServiceFactory::GetForProfile(profile());
-  sync_service->GetUserSettings()->SetFirstSetupComplete();
+  sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
 
   service()->Init();
 
@@ -539,7 +541,7 @@
   // The user has enabled sync.
   syncer::SyncService* sync_service =
       ProfileSyncServiceFactory::GetForProfile(profile());
-  sync_service->GetUserSettings()->SetFirstSetupComplete();
+  sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
   // Make sure ExtensionSyncService is created, so it'll be notified of changes.
   extension_sync_service();
 
@@ -602,7 +604,7 @@
   // The user has enabled sync.
   ProfileSyncServiceFactory::GetForProfile(profile())
       ->GetUserSettings()
-      ->SetFirstSetupComplete();
+      ->SetFirstSetupComplete(kSetSourceFromTest);
   // Make sure ExtensionSyncService is created, so it'll be notified of changes.
   extension_sync_service();
 
@@ -1732,7 +1734,7 @@
   // The user has enabled sync.
   ProfileSyncServiceFactory::GetForProfile(profile())
       ->GetUserSettings()
-      ->SetFirstSetupComplete();
+      ->SetFirstSetupComplete(kSetSourceFromTest);
   // Make sure ExtensionSyncService is created, so it'll be notified of changes.
   extension_sync_service();
 
@@ -2663,7 +2665,7 @@
     // Enable sync.
     syncer::SyncService* sync_service =
         ProfileSyncServiceFactory::GetForProfile(profile());
-    sync_service->GetUserSettings()->SetFirstSetupComplete();
+    sync_service->GetUserSettings()->SetFirstSetupComplete(kSetSourceFromTest);
 
     test_blacklist_.Attach(service()->blacklist_);
     service()->Init();
diff --git a/chrome/browser/extensions/extension_view_host.cc b/chrome/browser/extensions/extension_view_host.cc
index 52cb6380..6008b981 100644
--- a/chrome/browser/extensions/extension_view_host.cc
+++ b/chrome/browser/extensions/extension_view_host.cc
@@ -12,8 +12,8 @@
 #include "chrome/browser/extensions/extension_view.h"
 #include "chrome/browser/extensions/window_controller.h"
 #include "chrome/browser/file_select_helper.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
 #include "chrome/browser/performance_manager/performance_manager_tab_helper.h"
+#include "chrome/browser/performance_manager/public/performance_manager.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/ui/autofill/chrome_autofill_client.h"
 #include "chrome/browser/ui/browser.h"
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 2d9bb43a..2b2e993e0 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -771,11 +771,6 @@
     "expiry_milestone": 80
   },
   {
-    "name": "drag-to-pin-tabs",
-    "owners": ["chrome-desktop-ui-seattle@google.com", "cyan", "tbergquist"],
-    "expiry_milestone": 82
-  },
-  {
     "name": "draw-vertically-edge-to-edge",
     "owners": [ "chrome-android-app@chromium.org" ],
     "expiry_milestone": 88
@@ -2539,6 +2534,11 @@
     "expiry_milestone": 80
   },
   {
+    "name": "omnibox-autocomplete-titles",
+    "owners": [ "manukh", "chrome-omnibox-team@google.com" ],
+    "expiry_milestone": 85
+  },
+  {
     "name": "omnibox-disable-instant-extended-limit",
     "owners": [ "pnoland", "chrome-omnibox-team@google.com" ],
     "expiry_milestone": 80
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 5fdca325..b106ce2 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -698,11 +698,6 @@
 const char kDownloadAutoResumptionNativeDescription[] =
     "Enables download auto-resumption in native";
 
-const char kDragToPinTabsName[] = "Drag to Modify Tab Pinnedness";
-const char kDragToPinTabsDescription[] =
-    "Allows users to drag tabs between pinned and unpinned tabs to modify the "
-    "pinned state of the tab.";
-
 const char kEnableCSSBackdropFilterName[] = "Enable backdrop-filter";
 const char kEnableCSSBackdropFilterDescription[] =
     "Enable a new CSS property called backdrop-filter.";
@@ -1334,6 +1329,11 @@
     "Shows an alternate separator before the description of omnibox matches. "
     "In English, this changes the separator from '-' to '|'.";
 
+const char kOmniboxAutocompleteTitlesName[] = "Omnibox Autocomplete Titles";
+const char kOmniboxAutocompleteTitlesDescription[] =
+    "Allows autocompleting bookmark, history, and document suggestions when the"
+    " user input is a prefix of their titles, as opposed to their URLs.";
+
 const char kOmniboxDisplayTitleForCurrentUrlName[] =
     "Include title for the current URL in the omnibox";
 const char kOmniboxDisplayTitleForCurrentUrlDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index a34ce5e..d4a8c230 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -502,9 +502,6 @@
 extern const char kDownloadAutoResumptionNativeName[];
 extern const char kDownloadAutoResumptionNativeDescription[];
 
-extern const char kDragToPinTabsName[];
-extern const char kDragToPinTabsDescription[];
-
 extern const char kEnableNewDownloadBackendName[];
 extern const char kEnableNewDownloadBackendDescription[];
 
@@ -816,6 +813,9 @@
 extern const char kOmniboxAlternateMatchDescriptionSeparatorName[];
 extern const char kOmniboxAlternateMatchDescriptionSeparatorDescription[];
 
+extern const char kOmniboxAutocompleteTitlesName[];
+extern const char kOmniboxAutocompleteTitlesDescription[];
+
 extern const char kOmniboxDisableInstantExtendedLimitName[];
 extern const char kOmniboxDisableInstantExtendedLimitDescription[];
 
diff --git a/chrome/browser/lifetime/termination_notification.cc b/chrome/browser/lifetime/termination_notification.cc
index c3d7611..743b019 100644
--- a/chrome/browser/lifetime/termination_notification.cc
+++ b/chrome/browser/lifetime/termination_notification.cc
@@ -59,8 +59,8 @@
     // or else signal the session manager to log out.
     chromeos::UpdateEngineClient* update_engine_client =
         chromeos::DBusThreadManager::Get()->GetUpdateEngineClient();
-    if (update_engine_client->GetLastStatus().status ==
-            chromeos::UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT ||
+    if (update_engine_client->GetLastStatus().current_operation() ==
+            update_engine::Operation::UPDATED_NEED_REBOOT ||
         reboot_policy == RebootPolicy::kForceReboot) {
       update_engine_client->RebootAfterUpdate();
     } else if (chrome::IsAttemptingShutdown()) {
diff --git a/chrome/browser/memory/enterprise_memory_limit_evaluator.cc b/chrome/browser/memory/enterprise_memory_limit_evaluator.cc
index 50188d0..44b8c8e 100644
--- a/chrome/browser/memory/enterprise_memory_limit_evaluator.cc
+++ b/chrome/browser/memory/enterprise_memory_limit_evaluator.cc
@@ -5,8 +5,8 @@
 #include "chrome/browser/memory/enterprise_memory_limit_evaluator.h"
 
 #include "base/bind.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
 #include "chrome/browser/performance_manager/public/graph/process_node.h"
+#include "chrome/browser/performance_manager/public/performance_manager.h"
 
 namespace memory {
 
@@ -55,7 +55,7 @@
   performance_manager::PerformanceManager::CallOnGraph(
       FROM_HERE, base::BindOnce(
                      [](performance_manager::GraphOwned* observer,
-                        performance_manager::GraphImpl* graph) {
+                        performance_manager::Graph* graph) {
                        // This will destroy the observer since TakeFromGraph
                        // returns a unique_ptr.
                        graph->TakeFromGraph(observer);
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter.cc b/chrome/browser/metrics/process_memory_metrics_emitter.cc
index 0f9fc74..37c0d40 100644
--- a/chrome/browser/metrics/process_memory_metrics_emitter.cc
+++ b/chrome/browser/metrics/process_memory_metrics_emitter.cc
@@ -20,7 +20,7 @@
 #include "chrome/browser/performance_manager/graph/graph_impl_operations.h"
 #include "chrome/browser/performance_manager/graph/page_node_impl.h"
 #include "chrome/browser/performance_manager/graph/process_node_impl.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "content/public/browser/audio_service_info.h"
 #include "content/public/browser/render_process_host.h"
@@ -587,7 +587,7 @@
       base::SequencedTaskRunnerHandle::Get(),
       scoped_refptr<ProcessMemoryMetricsEmitter>(this));
 
-  performance_manager::PerformanceManager::CallOnGraph(
+  performance_manager::PerformanceManagerImpl::CallOnGraphImpl(
       FROM_HERE,
       base::BindOnce(&ProcessMemoryMetricsEmitter::GetProcessToPageInfoMap,
                      std::move(callback2)));
diff --git a/chrome/browser/metrics/ukm_browsertest.cc b/chrome/browser/metrics/ukm_browsertest.cc
index 7ebec22e..a7b1c742 100644
--- a/chrome/browser/metrics/ukm_browsertest.cc
+++ b/chrome/browser/metrics/ukm_browsertest.cc
@@ -206,7 +206,12 @@
   void BuildAndStoreUkmLog() {
     auto* service = ukm_service();
     DCHECK(service);
+    // Wait for initialization to complete before flushing.
+    base::RunLoop run_loop;
+    service->SetInitializationCompleteCallbackForTesting(run_loop.QuitClosure());
+    run_loop.Run();
     DCHECK(service->initialize_complete_);
+
     service->Flush();
     DCHECK(service->reporting_service_.ukm_log_store()->has_unsent_logs());
   }
@@ -540,13 +545,7 @@
 // Keep in sync with UkmTest.testMetricConsent in
 // chrome/android/javatests/src/org/chromium/chrome/browser/sync/
 // UkmTest.java.
-#if defined(OS_CHROMEOS)
-// TODO(https://crbug.com/996823): Re-enable this test.
-#define MAYBE_MetricsConsentCheck DISABLED_MetricsConsentCheck
-#else
-#define MAYBE_MetricsConsentCheck MetricsConsentCheck
-#endif
-IN_PROC_BROWSER_TEST_P(UkmBrowserTest, MAYBE_MetricsConsentCheck) {
+IN_PROC_BROWSER_TEST_P(UkmBrowserTest, MetricsConsentCheck) {
   MetricsConsentOverride metrics_consent(true);
 
   Profile* profile = ProfileManager::GetActiveUserProfile();
@@ -576,13 +575,7 @@
   CloseBrowserSynchronously(sync_browser);
 }
 
-#if defined(OS_CHROMEOS)
-// TODO(https://crbug.com/996823): Re-enable this test.
-#define MAYBE_LogProtoData DISABLED_LogProtoData
-#else
-#define MAYBE_LogProtoData LogProtoData
-#endif
-IN_PROC_BROWSER_TEST_P(UkmBrowserTest, MAYBE_LogProtoData) {
+IN_PROC_BROWSER_TEST_P(UkmBrowserTest, LogProtoData) {
   MetricsConsentOverride metrics_consent(true);
 
   Profile* profile = ProfileManager::GetActiveUserProfile();
@@ -622,16 +615,7 @@
 
 // Verifies that network provider attaches effective connection type correctly
 // to the UKM report.
-#if defined(OS_CHROMEOS)
-// TODO(https://crbug.com/996823): Re-enable this test.
-#define MAYBE_NetworkProviderPopulatesSystemProfile \
-  DISABLED_NetworkProviderPopulatesSystemProfile
-#else
-#define MAYBE_NetworkProviderPopulatesSystemProfile \
-  NetworkProviderPopulatesSystemProfile
-#endif
-IN_PROC_BROWSER_TEST_P(UkmBrowserTest,
-                       MAYBE_NetworkProviderPopulatesSystemProfile) {
+IN_PROC_BROWSER_TEST_P(UkmBrowserTest, NetworkProviderPopulatesSystemProfile) {
   // Override network quality to 2G. This should cause the
   // |max_effective_connection_type| in the system profile to be set to 2G.
   g_browser_process->network_quality_tracker()
diff --git a/chrome/browser/notifications/scheduler/internal/notification_scheduler.cc b/chrome/browser/notifications/scheduler/internal/notification_scheduler.cc
index 1888e66..e1a690e1 100644
--- a/chrome/browser/notifications/scheduler/internal/notification_scheduler.cc
+++ b/chrome/browser/notifications/scheduler/internal/notification_scheduler.cc
@@ -89,6 +89,114 @@
   DISALLOW_COPY_AND_ASSIGN(InitHelper);
 };
 
+// Helper class to display multiple notifications, and invoke a callback when
+// finished.
+class DisplayHelper {
+ public:
+  // Invoked with the total number of notification shown when all the display
+  // flows are done.
+  using FinishCallback = base::OnceCallback<void(int)>;
+  DisplayHelper(const std::set<std::string>& guids,
+                NotificationSchedulerContext* context,
+                FinishCallback finish_callback)
+      : guids_(guids),
+        context_(context),
+        finish_callback_(std::move(finish_callback)),
+        shown_count_(0) {
+    if (guids_.empty()) {
+      std::move(finish_callback_).Run(0);
+      return;
+    }
+
+    for (const auto& guid : guids) {
+      context_->notification_manager()->DisplayNotification(
+          guid, base::BindOnce(&DisplayHelper::BeforeDisplay,
+                               weak_ptr_factory_.GetWeakPtr(), guid));
+    }
+  }
+
+  ~DisplayHelper() = default;
+
+ private:
+  void BeforeDisplay(const std::string& guid,
+                     std::unique_ptr<NotificationEntry> entry) {
+    if (!entry) {
+      DLOG(ERROR) << "Notification entry is null";
+      MaybeFinish(guid, false /*shown*/);
+      return;
+    }
+
+    // Inform the client to update notification data.
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&DisplayHelper::NotifyClientBeforeDisplay,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(entry)));
+  }
+
+  void NotifyClientBeforeDisplay(std::unique_ptr<NotificationEntry> entry) {
+    auto* client = context_->client_registrar()->GetClient(entry->type);
+    if (!client) {
+      MaybeFinish(entry->guid, false /*shown*/);
+      return;
+    }
+
+    // Detach the notification data for client to rewrite.
+    auto notification_data =
+        std::make_unique<NotificationData>(std::move(entry->notification_data));
+    client->BeforeShowNotification(
+        std::move(notification_data),
+        base::BindOnce(&DisplayHelper::AfterClientUpdateData,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(entry)));
+  }
+
+  void AfterClientUpdateData(
+      std::unique_ptr<NotificationEntry> entry,
+      std::unique_ptr<NotificationData> updated_notification_data) {
+    if (!updated_notification_data) {
+      stats::LogNotificationLifeCycleEvent(
+          stats::NotificationLifeCycleEvent::kClientCancel, entry->type);
+      MaybeFinish(entry->guid, false /*shown*/);
+      return;
+    }
+
+    // Tracks user impression on the notification to be shown.
+    context_->impression_tracker()->AddImpression(
+        entry->type, entry->guid, entry->schedule_params.impression_mapping,
+        updated_notification_data->custom_data);
+
+    stats::LogNotificationShow(*updated_notification_data, entry->type);
+
+    // Show the notification in UI.
+    auto system_data = std::make_unique<DisplayAgent::SystemData>();
+    system_data->type = entry->type;
+    system_data->guid = entry->guid;
+    context_->display_agent()->ShowNotification(
+        std::move(updated_notification_data), std::move(system_data));
+
+    MaybeFinish(entry->guid, true /*shown*/);
+  }
+
+  // Called when notification display flow is finished. Invokes
+  // |finish_callback_| when all display flows are done.
+  void MaybeFinish(const std::string& guid, bool shown) {
+    if (base::Contains(guids_, guid) && shown) {
+      shown_count_++;
+    }
+    guids_.erase(guid);
+    if (guids_.empty() && finish_callback_) {
+      std::move(finish_callback_).Run(shown_count_);
+    }
+  }
+
+  std::set<std::string> guids_;
+  NotificationSchedulerContext* context_;
+  FinishCallback finish_callback_;
+  int shown_count_;
+  base::WeakPtrFactory<DisplayHelper> weak_ptr_factory_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(DisplayHelper);
+};
+
 // Implementation of NotificationScheduler.
 class NotificationSchedulerImpl : public NotificationScheduler,
                                   public ImpressionHistoryTracker::Delegate {
@@ -103,13 +211,11 @@
  private:
   // NotificationScheduler implementation.
   void Init(InitCallback init_callback) override {
-    auto helper = std::make_unique<InitHelper>();
-    auto* helper_ptr = helper.get();
-    helper_ptr->Init(
-        context_.get(), this,
-        base::BindOnce(&NotificationSchedulerImpl::OnInitialized,
-                       weak_ptr_factory_.GetWeakPtr(), std::move(helper),
-                       std::move(init_callback)));
+    init_helper_ = std::make_unique<InitHelper>();
+    init_helper_->Init(context_.get(), this,
+                       base::BindOnce(&NotificationSchedulerImpl::OnInitialized,
+                                      weak_ptr_factory_.GetWeakPtr(),
+                                      std::move(init_callback)));
   }
 
   void Schedule(
@@ -137,10 +243,9 @@
                                                         std::move(callback));
   }
 
-  void OnInitialized(std::unique_ptr<InitHelper>,
-                     InitCallback init_callback,
-                     bool success) {
+  void OnInitialized(InitCallback init_callback, bool success) {
     // TODO(xingliu): Tear down internal components if initialization failed.
+    init_helper_.reset();
     std::move(init_callback).Run(success);
     NotifyClientsAfterInit(success);
   }
@@ -181,13 +286,7 @@
     context_->impression_tracker()->AnalyzeImpressionHistory();
 
     // Show notifications.
-    FindNotificationToShow(task_start_time_);
-
-    // Schedule the next background task based on scheduled notifications.
-    ScheduleBackgroundTask();
-
-    stats::LogBackgroundTaskEvent(stats::BackgroundTaskEvent::kFinish);
-    std::move(callback).Run(false /*need_reschedule*/);
+    FindNotificationToShow(task_start_time_, std::move(callback));
   }
 
   void OnStopTask(SchedulerTaskTime task_time) override {
@@ -196,59 +295,6 @@
     ScheduleBackgroundTask();
   }
 
-  // TODO(xingliu): Tracks each display flow, and call finish callback and
-  // schedule background task after everything is done.
-  void BeforeDisplay(std::unique_ptr<NotificationEntry> entry) {
-    if (!entry) {
-      DLOG(ERROR) << "Notification entry is null";
-      return;
-    }
-
-    // Inform the client to update notification data.
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&NotificationSchedulerImpl::NotifyClientBeforeDisplay,
-                       weak_ptr_factory_.GetWeakPtr(), std::move(entry)));
-  }
-
-  void NotifyClientBeforeDisplay(std::unique_ptr<NotificationEntry> entry) {
-    auto* client = context_->client_registrar()->GetClient(entry->type);
-    if (!client)
-      return;
-
-    // Detach the notification data for client to rewrite.
-    auto notification_data =
-        std::make_unique<NotificationData>(std::move(entry->notification_data));
-    client->BeforeShowNotification(
-        std::move(notification_data),
-        base::BindOnce(&NotificationSchedulerImpl::AfterClientUpdateData,
-                       weak_ptr_factory_.GetWeakPtr(), std::move(entry)));
-  }
-
-  void AfterClientUpdateData(
-      std::unique_ptr<NotificationEntry> entry,
-      std::unique_ptr<NotificationData> updated_notification_data) {
-    if (!updated_notification_data) {
-      stats::LogNotificationLifeCycleEvent(
-          stats::NotificationLifeCycleEvent::kClientCancel, entry->type);
-      return;
-    }
-
-    // Tracks user impression on the notification to be shown.
-    context_->impression_tracker()->AddImpression(
-        entry->type, entry->guid, entry->schedule_params.impression_mapping,
-        updated_notification_data->custom_data);
-
-    stats::LogNotificationShow(*updated_notification_data, entry->type);
-
-    // Show the notification in UI.
-    auto system_data = std::make_unique<DisplayAgent::SystemData>();
-    system_data->type = entry->type;
-    system_data->guid = entry->guid;
-    context_->display_agent()->ShowNotification(
-        std::move(updated_notification_data), std::move(system_data));
-  }
-
   // ImpressionHistoryTracker::Delegate implementation.
   void OnImpressionUpdated() override {
     // TODO(xingliu): Fix duplicate ScheduleBackgroundTask() call.
@@ -256,7 +302,8 @@
   }
 
   // TODO(xingliu): Remove |task_start_time|.
-  void FindNotificationToShow(SchedulerTaskTime task_start_time) {
+  void FindNotificationToShow(SchedulerTaskTime task_start_time,
+                              TaskFinishedCallback task_finish_callback) {
     DisplayDecider::Results results;
     ScheduledNotificationManager::Notifications notifications;
     context_->notification_manager()->GetAllNotifications(&notifications);
@@ -270,12 +317,22 @@
     context_->display_decider()->FindNotificationsToShow(
         std::move(notifications), std::move(client_states), &results);
 
-    for (const auto& guid : results) {
-      context_->notification_manager()->DisplayNotification(
-          guid, base::BindOnce(&NotificationSchedulerImpl::BeforeDisplay,
-                               weak_ptr_factory_.GetWeakPtr()));
-    }
-    stats::LogBackgroundTaskNotificationShown(results.size());
+    display_helper_ = std::make_unique<DisplayHelper>(
+        results, context_.get(),
+        base::BindOnce(&NotificationSchedulerImpl::AfterNotificationsShown,
+                       weak_ptr_factory_.GetWeakPtr(),
+                       std::move(task_finish_callback)));
+  }
+
+  void AfterNotificationsShown(TaskFinishedCallback task_finish_callback,
+                               int shown_count) {
+    stats::LogBackgroundTaskNotificationShown(shown_count);
+
+    // Schedule the next background task based on scheduled notifications.
+    ScheduleBackgroundTask();
+
+    stats::LogBackgroundTaskEvent(stats::BackgroundTaskEvent::kFinish);
+    std::move(task_finish_callback).Run(false /*need_reschedule*/);
   }
 
   void ScheduleBackgroundTask() {
@@ -316,6 +373,8 @@
   }
 
   std::unique_ptr<NotificationSchedulerContext> context_;
+  std::unique_ptr<InitHelper> init_helper_;
+  std::unique_ptr<DisplayHelper> display_helper_;
 
   // The start time of the background task. SchedulerTaskTime::kUnknown if
   // currently not running in a background task.
diff --git a/chrome/browser/notifications/scheduler/internal/notification_scheduler_unittest.cc b/chrome/browser/notifications/scheduler/internal/notification_scheduler_unittest.cc
index a35c9185..4652446 100644
--- a/chrome/browser/notifications/scheduler/internal/notification_scheduler_unittest.cc
+++ b/chrome/browser/notifications/scheduler/internal/notification_scheduler_unittest.cc
@@ -107,6 +107,18 @@
     run_loop.Run();
   }
 
+  // Starts the background task and wait for task finished callback to invoke.
+  void OnStartTask() {
+    base::RunLoop loop;
+    auto task_finish_callback =
+        base::BindOnce([](base::RepeatingClosure quit_closure,
+                          bool needs_reschedule) { quit_closure.Run(); },
+                       loop.QuitClosure());
+    scheduler()->OnStartTask(SchedulerTaskTime::kMorning,
+                             std::move(task_finish_callback));
+    loop.Run();
+  }
+
   NotificationScheduler* scheduler() { return notification_scheduler_.get(); }
 
   test::MockImpressionHistoryTracker* impression_tracker() {
@@ -272,7 +284,7 @@
   EXPECT_CALL(*notification_manager(), DisplayNotification(_, _)).Times(0);
   EXPECT_CALL(*task_coordinator(), ScheduleBackgroundTask(_, _));
 
-  scheduler()->OnStartTask(SchedulerTaskTime::kMorning, base::DoNothing());
+  OnStartTask();
 }
 
 MATCHER_P(NotifcationDataEq, title, "Verify notification data.") {
@@ -289,7 +301,6 @@
 // Test to simulate a background task flow with some notifications shown.
 TEST_F(NotificationSchedulerTest, BackgroundTaskStartShowNotification) {
   Init();
-  base::RunLoop loop;
 
   // Mock the notification to show.
   auto entry =
@@ -301,6 +312,9 @@
   DisplayDecider::Results result({kGuid});
   EXPECT_CALL(*display_decider(), FindNotificationsToShow(_, _, _))
       .WillOnce(SetArgPointee<2>(result));
+
+  EXPECT_CALL(*task_coordinator(), ScheduleBackgroundTask(_, _));
+  EXPECT_CALL(*impression_tracker(), AddImpression(_, _, _, _));
   EXPECT_CALL(*notification_manager(), DisplayNotification(_, _))
       .WillOnce(
           Invoke([&](const std::string& guid,
@@ -315,19 +329,64 @@
             // The client updates the notification data here.
             notification_data->title = base::UTF8ToUTF16(kTitle);
             std::move(callback).Run(std::move(notification_data));
-            loop.Quit();
           }));
 
+  OnStartTask();
+}
+
+// Verifies if the entry is failed to load, the background task flow can still
+// be finished.
+TEST_F(NotificationSchedulerTest, BackgroundTaskStartNoEntry) {
+  Init();
+
+  DisplayDecider::Results result({kGuid});
+  EXPECT_CALL(*display_decider(), FindNotificationsToShow(_, _, _))
+      .WillOnce(SetArgPointee<2>(result));
+
   EXPECT_CALL(*task_coordinator(), ScheduleBackgroundTask(_, _));
-  EXPECT_CALL(*impression_tracker(), AddImpression(_, _, _, _));
-  scheduler()->OnStartTask(SchedulerTaskTime::kMorning, base::DoNothing());
-  loop.Run();
+  EXPECT_CALL(*impression_tracker(), AddImpression(_, _, _, _)).Times(0);
+  EXPECT_CALL(*display_agent(), ShowNotification(_, _)).Times(0);
+  EXPECT_CALL(*client(), BeforeShowNotification(_, _)).Times(0);
+  EXPECT_CALL(*notification_manager(), DisplayNotification(_, _))
+      .WillOnce(
+          Invoke([&](const std::string& guid,
+                     ScheduledNotificationManager::DisplayCallback callback) {
+            std::move(callback).Run(nullptr /*entry*/);
+          }));
+
+  OnStartTask();
+}
+
+// Verifies if the client is not found during display flow, the background task
+// flow can still be finished.
+TEST_F(NotificationSchedulerTest, BackgroundTaskStartNoClient) {
+  Init();
+
+  // Creates entry without corresponding client.
+  auto entry_no_client =
+      std::make_unique<NotificationEntry>(SchedulerClientType::kTest2, kGuid);
+
+  DisplayDecider::Results result({kGuid});
+  EXPECT_CALL(*display_decider(), FindNotificationsToShow(_, _, _))
+      .WillOnce(SetArgPointee<2>(result));
+
+  EXPECT_CALL(*task_coordinator(), ScheduleBackgroundTask(_, _));
+  EXPECT_CALL(*impression_tracker(), AddImpression(_, _, _, _)).Times(0);
+  EXPECT_CALL(*display_agent(), ShowNotification(_, _)).Times(0);
+  EXPECT_CALL(*client(), BeforeShowNotification(_, _)).Times(0);
+  EXPECT_CALL(*notification_manager(), DisplayNotification(_, _))
+      .WillOnce(
+          Invoke([&](const std::string& guid,
+                     ScheduledNotificationManager::DisplayCallback callback) {
+            std::move(callback).Run(std::move(entry_no_client));
+          }));
+
+  OnStartTask();
 }
 
 // Verifies the case that the client dropped the notification data.
 TEST_F(NotificationSchedulerTest, ClientDropNotification) {
   Init();
-  base::RunLoop loop;
 
   // Mock the notification to show.
   auto entry =
@@ -348,15 +407,13 @@
           [&](std::unique_ptr<NotificationData> notification_data,
               NotificationSchedulerClient::NotificationDataCallback callback) {
             std::move(callback).Run(nullptr);
-            loop.Quit();
           }));
 
   EXPECT_CALL(*task_coordinator(), ScheduleBackgroundTask(_, _));
   EXPECT_CALL(*impression_tracker(), AddImpression(_, _, _, _)).Times(0);
   EXPECT_CALL(*display_agent(), ShowNotification(_, _)).Times(0);
 
-  scheduler()->OnStartTask(SchedulerTaskTime::kMorning, base::DoNothing());
-  loop.Run();
+  OnStartTask();
 }
 
 // Test to simulate a background task stopped by the OS.
diff --git a/chrome/browser/page_load_metrics/observers/android_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/android_page_load_metrics_observer.cc
index 77993b2..6b0af2a7 100644
--- a/chrome/browser/page_load_metrics/observers/android_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/android_page_load_metrics_observer.cc
@@ -40,6 +40,39 @@
   return CONTINUE_OBSERVING;
 }
 
+page_load_metrics::PageLoadMetricsObserver::ObservePolicy
+AndroidPageLoadMetricsObserver::FlushMetricsOnAppEnterBackground(
+    const page_load_metrics::mojom::PageLoadTiming& timing) {
+  // FlushMetricsOnAppEnterBackground is invoked on Android in cases where the
+  // app is about to be backgrounded, as part of the Activity.onPause()
+  // flow. After this method is invoked, Chrome may be killed without further
+  // notification, so we record final metrics collected up to this point.
+  ReportBufferedMetrics(timing);
+
+  // We continue observing after being backgrounded, in case we are foregrounded
+  // again without being killed. In those cases we may still report non-buffered
+  // metrics such as FCP after being re-foregrounded.
+  return CONTINUE_OBSERVING;
+}
+
+AndroidPageLoadMetricsObserver::ObservePolicy
+AndroidPageLoadMetricsObserver::OnHidden(
+    const page_load_metrics::mojom::PageLoadTiming& timing) {
+  ReportBufferedMetrics(timing);
+  return CONTINUE_OBSERVING;
+}
+
+void AndroidPageLoadMetricsObserver::OnDidFinishSubFrameNavigation(
+    content::NavigationHandle* navigation_handle) {
+  largest_contentful_paint_handler_.OnDidFinishSubFrameNavigation(
+      navigation_handle, GetDelegate());
+}
+
+void AndroidPageLoadMetricsObserver::OnComplete(
+    const page_load_metrics::mojom::PageLoadTiming& timing) {
+  ReportBufferedMetrics(timing);
+}
+
 void AndroidPageLoadMetricsObserver::OnFirstContentfulPaintInPage(
     const page_load_metrics::mojom::PageLoadTiming& timing) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -50,6 +83,14 @@
       first_contentful_paint_ms);
 }
 
+void AndroidPageLoadMetricsObserver::OnFirstInputInPage(
+    const page_load_metrics::mojom::PageLoadTiming& timing) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  int64_t first_input_delay_ms =
+      timing.interactive_timing->first_input_delay->InMilliseconds();
+  ReportFirstInputDelay(first_input_delay_ms);
+}
+
 void AndroidPageLoadMetricsObserver::OnFirstMeaningfulPaintInMainFrameDocument(
     const page_load_metrics::mojom::PageLoadTiming& timing) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -103,6 +144,13 @@
   }
 }
 
+void AndroidPageLoadMetricsObserver::OnTimingUpdate(
+    content::RenderFrameHost* subframe_rfh,
+    const page_load_metrics::mojom::PageLoadTiming& timing) {
+  largest_contentful_paint_handler_.RecordTiming(timing.paint_timing,
+                                                 subframe_rfh);
+}
+
 void AndroidPageLoadMetricsObserver::ReportNewNavigation() {
   DCHECK_GE(navigation_id_, 0);
   base::android::ScopedJavaLocalRef<jobject> java_web_contents =
@@ -112,6 +160,41 @@
                                        static_cast<jlong>(navigation_id_));
 }
 
+void AndroidPageLoadMetricsObserver::ReportBufferedMetrics(
+    const page_load_metrics::mojom::PageLoadTiming& timing) {
+  // This method may be invoked multiple times. Make sure that if we already
+  // reported, we do not report again.
+  if (reported_buffered_metrics_)
+    return;
+  reported_buffered_metrics_ = true;
+
+  // Buffered metrics aren't available until after the navigation commits.
+  if (!GetDelegate().DidCommit())
+    return;
+
+  base::android::ScopedJavaLocalRef<jobject> java_web_contents =
+      GetDelegate().GetWebContents()->GetJavaWebContents();
+  JNIEnv* env = base::android::AttachCurrentThread();
+  int64_t navigation_start_tick =
+      (GetDelegate().GetNavigationStart() - base::TimeTicks()).InMicroseconds();
+  const page_load_metrics::ContentfulPaintTimingInfo& largest_contentful_paint =
+      largest_contentful_paint_handler_.MergeMainFrameAndSubframes();
+  if (!largest_contentful_paint.IsEmpty()) {
+    Java_PageLoadMetrics_onLargestContentfulPaint(
+        env, java_web_contents, static_cast<jlong>(navigation_id_),
+        static_cast<jlong>(navigation_start_tick),
+        static_cast<jlong>(largest_contentful_paint.Time()->InMilliseconds()),
+        static_cast<jlong>(largest_contentful_paint.Size()));
+  }
+  Java_PageLoadMetrics_onLayoutShiftScore(
+      env, java_web_contents, static_cast<jlong>(navigation_id_),
+      static_cast<jfloat>(GetDelegate()
+                              .GetMainFrameRenderData()
+                              .layout_shift_score_before_input_or_scroll),
+      static_cast<jfloat>(
+          GetDelegate().GetPageRenderData().layout_shift_score));
+}
+
 void AndroidPageLoadMetricsObserver::ReportNetworkQualityEstimate(
     net::EffectiveConnectionType connection_type,
     int64_t http_rtt_ms,
@@ -179,3 +262,13 @@
       static_cast<jlong>(request_start_ms), static_cast<jlong>(send_start_ms),
       static_cast<jlong>(send_end_ms));
 }
+
+void AndroidPageLoadMetricsObserver::ReportFirstInputDelay(
+    int64_t first_input_delay_ms) {
+  base::android::ScopedJavaLocalRef<jobject> java_web_contents =
+      GetDelegate().GetWebContents()->GetJavaWebContents();
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_PageLoadMetrics_onFirstInputDelay(
+      env, java_web_contents, static_cast<jlong>(navigation_id_),
+      static_cast<jlong>(first_input_delay_ms));
+}
diff --git a/chrome/browser/page_load_metrics/observers/android_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/android_page_load_metrics_observer.h
index 289e9f0..d03045c3 100644
--- a/chrome/browser/page_load_metrics/observers/android_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/android_page_load_metrics_observer.h
@@ -8,6 +8,7 @@
 #include <jni.h>
 
 #include "base/macros.h"
+#include "chrome/browser/page_load_metrics/observers/largest_contentful_paint_handler.h"
 #include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
 
 namespace network {
@@ -23,17 +24,33 @@
   AndroidPageLoadMetricsObserver();
 
   // page_load_metrics::PageLoadMetricsObserver:
+  // PageLoadMetricsObserver lifecycle callbacks
   ObservePolicy OnStart(content::NavigationHandle* navigation_handle,
                         const GURL& currently_committed_url,
                         bool started_in_foreground) override;
+  ObservePolicy FlushMetricsOnAppEnterBackground(
+      const page_load_metrics::mojom::PageLoadTiming& timing) override;
+  ObservePolicy OnHidden(
+      const page_load_metrics::mojom::PageLoadTiming& timing) override;
+  void OnDidFinishSubFrameNavigation(
+      content::NavigationHandle* navigation_handle) override;
+  void OnComplete(
+      const page_load_metrics::mojom::PageLoadTiming& timing) override;
+
+  // PageLoadMetricsObserver event callbacks
   void OnFirstContentfulPaintInPage(
       const page_load_metrics::mojom::PageLoadTiming& timing) override;
+  void OnFirstInputInPage(
+      const page_load_metrics::mojom::PageLoadTiming& timing) override;
   void OnFirstMeaningfulPaintInMainFrameDocument(
       const page_load_metrics::mojom::PageLoadTiming& timing) override;
   void OnLoadEventStart(
       const page_load_metrics::mojom::PageLoadTiming& timing) override;
   void OnLoadedResource(const page_load_metrics::ExtraRequestCompleteInfo&
                             extra_request_complete_info) override;
+  void OnTimingUpdate(
+      content::RenderFrameHost* subframe_rfh,
+      const page_load_metrics::mojom::PageLoadTiming& timing) override;
 
  protected:
   AndroidPageLoadMetricsObserver(
@@ -42,6 +59,9 @@
 
   virtual void ReportNewNavigation();
 
+  virtual void ReportBufferedMetrics(
+      const page_load_metrics::mojom::PageLoadTiming& timing);
+
   virtual void ReportNetworkQualityEstimate(
       net::EffectiveConnectionType connection_type,
       int64_t http_rtt_ms,
@@ -64,12 +84,18 @@
                                         int64_t send_start_ms,
                                         int64_t send_end_ms);
 
+  virtual void ReportFirstInputDelay(int64_t first_input_delay_ms);
+
  private:
   bool did_dispatch_on_main_resource_ = false;
+  bool reported_buffered_metrics_ = false;
   int64_t navigation_id_ = -1;
 
   network::NetworkQualityTracker* network_quality_tracker_ = nullptr;
 
+  page_load_metrics::LargestContentfulPaintHandler
+      largest_contentful_paint_handler_;
+
   DISALLOW_COPY_AND_ASSIGN(AndroidPageLoadMetricsObserver);
 };
 
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc
index 2677f74..09f69b8a 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client.cc
+++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/browsing_data/browsing_data_helper.h"
 #include "chrome/browser/favicon/favicon_service_factory.h"
 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
+#include "chrome/browser/password_manager/account_storage/account_password_store_factory.h"
 #include "chrome/browser/password_manager/password_store_factory.h"
 #include "chrome/browser/password_manager/touch_to_fill_controller.h"
 #include "chrome/browser/prerender/prerender_contents.h"
@@ -338,8 +339,10 @@
     UpdatePasswordInfoBarDelegate::Create(web_contents(),
                                           std::move(form_to_save));
   } else {
-    SavePasswordInfoBarDelegate::Create(web_contents(),
-                                        std::move(form_to_save));
+    auto saving_flow_recorder(
+        std::make_unique<password_manager::SavingFlowMetricsRecorder>());
+    SavePasswordInfoBarDelegate::Create(web_contents(), std::move(form_to_save),
+                                        std::move(saving_flow_recorder));
   }
 #endif  // !defined(OS_ANDROID)
   return true;
@@ -682,12 +685,19 @@
 ChromePasswordManagerClient::GetProfilePasswordStore() const {
   // Always use EXPLICIT_ACCESS as the password manager checks IsIncognito
   // itself when it shouldn't access the PasswordStore.
-  // TODO(gcasto): Is is safe to change this to
-  // ServiceAccessType::IMPLICIT_ACCESS?
   return PasswordStoreFactory::GetForProfile(
              profile_, ServiceAccessType::EXPLICIT_ACCESS).get();
 }
 
+password_manager::PasswordStore*
+ChromePasswordManagerClient::GetAccountPasswordStore() const {
+  // Always use EXPLICIT_ACCESS as the password manager checks IsIncognito
+  // itself when it shouldn't access the PasswordStore.
+  return AccountPasswordStoreFactory::GetForProfile(
+             profile_, ServiceAccessType::EXPLICIT_ACCESS)
+      .get();
+}
+
 password_manager::SyncState ChromePasswordManagerClient::GetPasswordSyncState()
     const {
   const syncer::SyncService* sync_service =
@@ -909,11 +919,15 @@
     popup_controller_->GenerationElementLostFocus();
 }
 
+#if defined(OS_ANDROID)
 void ChromePasswordManagerClient::OnOnboardingSuccessful(
-    std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save) {
-  PromptUserToSaveOrUpdatePassword(std::move(form_to_save),
-                                   /* is_password_update */ false);
+    std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save,
+    std::unique_ptr<password_manager::SavingFlowMetricsRecorder>
+        saving_flow_recorder) {
+  SavePasswordInfoBarDelegate::Create(web_contents(), std::move(form_to_save),
+                                      std::move(saving_flow_recorder));
 }
+#endif  // defined(OS_ANDROID)
 
 const GURL& ChromePasswordManagerClient::GetMainFrameURL() const {
   return web_contents()->GetVisibleURL();
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.h b/chrome/browser/password_manager/chrome_password_manager_client.h
index 23ffcf50..e2d14a9 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client.h
+++ b/chrome/browser/password_manager/chrome_password_manager_client.h
@@ -27,6 +27,7 @@
 #include "components/password_manager/core/browser/password_manager_client_helper.h"
 #include "components/password_manager/core/browser/password_manager_metrics_recorder.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
+#include "components/password_manager/core/browser/password_manager_onboarding.h"
 #include "components/password_manager/core/browser/password_reuse_detection_manager.h"
 #include "components/password_manager/core/browser/sync_credentials_filter.h"
 #include "components/prefs/pref_member.h"
@@ -125,6 +126,7 @@
 
   PrefService* GetPrefs() const override;
   password_manager::PasswordStore* GetProfilePasswordStore() const override;
+  password_manager::PasswordStore* GetAccountPasswordStore() const override;
   password_manager::SyncState GetPasswordSyncState() const override;
   bool WasLastNavigationHTTPError() const override;
   net::CertStatus GetMainFrameCertStatus() const override;
@@ -169,10 +171,14 @@
   void FrameWasScrolled() override;
   void GenerationElementLostFocus() override;
 
+#if defined(OS_ANDROID)
   // This is called when the onboarding experience was shown successfully,
   // which means that the user should now be prompted to save their password.
   void OnOnboardingSuccessful(
-      std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save);
+      std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save,
+      std::unique_ptr<password_manager::SavingFlowMetricsRecorder>
+          saving_flow_recorder);
+#endif  // defined(OS_ANDROID)
 
 #if defined(ON_FOCUS_PING_ENABLED)
   void CheckSafeBrowsingReputation(const GURL& form_action,
diff --git a/chrome/browser/password_manager/save_password_infobar_delegate_android.cc b/chrome/browser/password_manager/save_password_infobar_delegate_android.cc
index 5981b172..d302813 100644
--- a/chrome/browser/password_manager/save_password_infobar_delegate_android.cc
+++ b/chrome/browser/password_manager/save_password_infobar_delegate_android.cc
@@ -27,7 +27,9 @@
 // static
 void SavePasswordInfoBarDelegate::Create(
     content::WebContents* web_contents,
-    std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save) {
+    std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save,
+    std::unique_ptr<password_manager::SavingFlowMetricsRecorder>
+        saving_flow_recorder) {
   Profile* profile =
       Profile::FromBrowserContext(web_contents->GetBrowserContext());
   syncer::SyncService* sync_service =
@@ -36,10 +38,10 @@
       password_bubble_experiment::IsSmartLockUser(sync_service);
   InfoBarService* infobar_service =
       InfoBarService::FromWebContents(web_contents);
-  infobar_service->AddInfoBar(
-      std::make_unique<SavePasswordInfoBar>(base::WrapUnique(
-          new SavePasswordInfoBarDelegate(web_contents, std::move(form_to_save),
-                                          is_smartlock_branding_enabled))));
+  infobar_service->AddInfoBar(std::make_unique<SavePasswordInfoBar>(
+      base::WrapUnique(new SavePasswordInfoBarDelegate(
+          web_contents, std::move(form_to_save), is_smartlock_branding_enabled,
+          std::move(saving_flow_recorder)))));
 }
 
 SavePasswordInfoBarDelegate::~SavePasswordInfoBarDelegate() {
@@ -47,15 +49,19 @@
   if (auto* recorder = form_to_save_->GetMetricsRecorder()) {
     recorder->RecordUIDismissalReason(infobar_response_);
   }
+  saving_flow_recorder_->SetFlowResult(infobar_response_);
 }
 
 SavePasswordInfoBarDelegate::SavePasswordInfoBarDelegate(
     content::WebContents* web_contents,
     std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save,
-    bool is_smartlock_branding_enabled)
+    bool is_smartlock_branding_enabled,
+    std::unique_ptr<password_manager::SavingFlowMetricsRecorder>
+        saving_flow_recorder)
     : PasswordManagerInfoBarDelegate(),
       form_to_save_(std::move(form_to_save)),
-      infobar_response_(password_manager::metrics_util::NO_DIRECT_INTERACTION) {
+      infobar_response_(password_manager::metrics_util::NO_DIRECT_INTERACTION),
+      saving_flow_recorder_(std::move(saving_flow_recorder)) {
   base::string16 message;
   PasswordTitleType type =
       form_to_save_->GetPendingCredentials().federation_origin.opaque()
diff --git a/chrome/browser/password_manager/save_password_infobar_delegate_android.h b/chrome/browser/password_manager/save_password_infobar_delegate_android.h
index 8a3f487..601474d 100644
--- a/chrome/browser/password_manager/save_password_infobar_delegate_android.h
+++ b/chrome/browser/password_manager/save_password_infobar_delegate_android.h
@@ -13,6 +13,7 @@
 #include "components/infobars/core/confirm_infobar_delegate.h"
 #include "components/password_manager/core/browser/password_form_manager_for_ui.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
+#include "components/password_manager/core/browser/password_manager_onboarding.h"
 #include "ui/gfx/range/range.h"
 
 namespace content {
@@ -32,7 +33,9 @@
   // for |web_contents|.
   static void Create(
       content::WebContents* web_contents,
-      std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save);
+      std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save,
+      std::unique_ptr<password_manager::SavingFlowMetricsRecorder>
+          saving_flow_recorder);
 
   ~SavePasswordInfoBarDelegate() override;
 
@@ -48,7 +51,9 @@
   SavePasswordInfoBarDelegate(
       content::WebContents* web_contents,
       std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save,
-      bool is_smartlock_branding_enabled);
+      bool is_smartlock_branding_enabled,
+      std::unique_ptr<password_manager::SavingFlowMetricsRecorder>
+          saving_flow_recorder);
 
  private:
   // The PasswordFormManager managing the form we're asking the user about,
@@ -62,6 +67,9 @@
   // signal.
   base::ElapsedTimer timer_;
 
+  std::unique_ptr<password_manager::SavingFlowMetricsRecorder>
+      saving_flow_recorder_;
+
   DISALLOW_COPY_AND_ASSIGN(SavePasswordInfoBarDelegate);
 };
 
diff --git a/chrome/browser/password_manager/save_password_infobar_delegate_android_unittest.cc b/chrome/browser/password_manager/save_password_infobar_delegate_android_unittest.cc
index f4775f33..f2c6a9a6 100644
--- a/chrome/browser/password_manager/save_password_infobar_delegate_android_unittest.cc
+++ b/chrome/browser/password_manager/save_password_infobar_delegate_android_unittest.cc
@@ -73,10 +73,13 @@
   TestSavePasswordInfoBarDelegate(
       content::WebContents* web_contents,
       std::unique_ptr<password_manager::PasswordFormManager> form_to_save,
-      bool is_smartlock_branding_enabled)
+      bool is_smartlock_branding_enabled,
+      std::unique_ptr<password_manager::SavingFlowMetricsRecorder>
+          saving_flow_recorder)
       : SavePasswordInfoBarDelegate(web_contents,
                                     std::move(form_to_save),
-                                    is_smartlock_branding_enabled) {}
+                                    is_smartlock_branding_enabled,
+                                    std::move(saving_flow_recorder)) {}
 
   ~TestSavePasswordInfoBarDelegate() override = default;
 };
@@ -163,11 +166,10 @@
     std::unique_ptr<password_manager::PasswordFormManager>
         password_form_manager,
     bool is_smartlock_branding_enabled) {
-  std::unique_ptr<PasswordManagerInfoBarDelegate> delegate(
-      new TestSavePasswordInfoBarDelegate(web_contents(),
-                                          std::move(password_form_manager),
-                                          is_smartlock_branding_enabled));
-  return delegate;
+  return std::make_unique<TestSavePasswordInfoBarDelegate>(
+      web_contents(), std::move(password_form_manager),
+      is_smartlock_branding_enabled,
+      std::make_unique<password_manager::SavingFlowMetricsRecorder>());
 }
 
 void SavePasswordInfoBarDelegateTest::SetUp() {
diff --git a/chrome/browser/password_manager/touch_to_fill_view.h b/chrome/browser/password_manager/touch_to_fill_view.h
new file mode 100644
index 0000000..3c4cfd8
--- /dev/null
+++ b/chrome/browser/password_manager/touch_to_fill_view.h
@@ -0,0 +1,41 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PASSWORD_MANAGER_TOUCH_TO_FILL_VIEW_H_
+#define CHROME_BROWSER_PASSWORD_MANAGER_TOUCH_TO_FILL_VIEW_H_
+
+#include "base/callback_forward.h"
+#include "base/containers/span.h"
+#include "base/strings/string_piece_forward.h"
+
+namespace password_manager {
+struct CredentialPair;
+}
+
+// This class represents the interface used for communicating between the Touch
+// To Fill controller with the Android frontend.
+class TouchToFillView {
+ public:
+  using ShowCallback =
+      base::OnceCallback<void(const password_manager::CredentialPair&)>;
+
+  TouchToFillView() = default;
+  TouchToFillView(const TouchToFillView&) = delete;
+  TouchToFillView& operator=(const TouchToFillView&) = delete;
+  virtual ~TouchToFillView() = default;
+
+  // Instructs Touch To Fill to show the provided |credentials| to the user.
+  // |formatted_url| contains a human friendly version of the current origin.
+  // Invokes |callback| once the user chose a credential.
+  virtual void Show(
+      base::StringPiece16 formatted_url,
+      base::span<const password_manager::CredentialPair> credentials,
+      ShowCallback callback) = 0;
+
+  // Invoked if the user dismissed the Touch To Fill sheet without choosing a
+  // credential.
+  virtual void OnDismiss() = 0;
+};
+
+#endif  // CHROME_BROWSER_PASSWORD_MANAGER_TOUCH_TO_FILL_VIEW_H_
diff --git a/chrome/browser/performance_manager/browser_child_process_watcher.cc b/chrome/browser/performance_manager/browser_child_process_watcher.cc
index beea7245..e4feef9 100644
--- a/chrome/browser/performance_manager/browser_child_process_watcher.cc
+++ b/chrome/browser/performance_manager/browser_child_process_watcher.cc
@@ -12,7 +12,7 @@
 #include "base/stl_util.h"
 #include "build/build_config.h"
 #include "chrome/browser/performance_manager/graph/process_node_impl.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 #include "chrome/browser/performance_manager/public/render_process_host_proxy.h"
 #include "content/public/browser/child_process_data.h"
 #include "content/public/browser/child_process_termination_info.h"
@@ -31,8 +31,9 @@
   DCHECK(!browser_process_node_);
   DCHECK(gpu_process_nodes_.empty());
 
-  browser_process_node_ = PerformanceManager::GetInstance()->CreateProcessNode(
-      RenderProcessHostProxy());
+  browser_process_node_ =
+      PerformanceManagerImpl::GetInstance()->CreateProcessNode(
+          RenderProcessHostProxy());
   OnProcessLaunched(base::Process::Current(), browser_process_node_.get());
   BrowserChildProcessObserver::Add(this);
 }
@@ -40,7 +41,8 @@
 void BrowserChildProcessWatcher::TearDown() {
   BrowserChildProcessObserver::Remove(this);
 
-  PerformanceManager* performance_manager = PerformanceManager::GetInstance();
+  PerformanceManagerImpl* performance_manager =
+      PerformanceManagerImpl::GetInstance();
   performance_manager->DeleteNode(std::move(browser_process_node_));
   for (auto& node : gpu_process_nodes_)
     performance_manager->DeleteNode(std::move(node.second));
@@ -51,7 +53,7 @@
     const content::ChildProcessData& data) {
   if (data.process_type == content::PROCESS_TYPE_GPU) {
     std::unique_ptr<ProcessNodeImpl> gpu_node =
-        PerformanceManager::GetInstance()->CreateProcessNode(
+        PerformanceManagerImpl::GetInstance()->CreateProcessNode(
             RenderProcessHostProxy());
     OnProcessLaunched(data.GetProcess(), gpu_node.get());
     gpu_process_nodes_[data.id] = std::move(gpu_node);
@@ -67,7 +69,7 @@
     // launch-and-connect notification arrives.
     // See https://crbug.com/942500.
     if (it != gpu_process_nodes_.end()) {
-      PerformanceManager::GetInstance()->DeleteNode(std::move(it->second));
+      PerformanceManagerImpl::GetInstance()->DeleteNode(std::move(it->second));
       gpu_process_nodes_.erase(it);
     }
   }
@@ -93,7 +95,8 @@
   // specifically on crash.
   if (base::Contains(gpu_process_nodes_, id)) {
     auto* process_node = gpu_process_nodes_[id].get();
-    PerformanceManager* performance_manager = PerformanceManager::GetInstance();
+    PerformanceManagerImpl* performance_manager =
+        PerformanceManagerImpl::GetInstance();
 
     performance_manager->task_runner()->PostTask(
         FROM_HERE, base::BindOnce(&ProcessNodeImpl::SetProcessExitStatus,
@@ -115,7 +118,8 @@
       process.CreationTime();
 #endif
 
-  PerformanceManager* performance_manager = PerformanceManager::GetInstance();
+  PerformanceManagerImpl* performance_manager =
+      PerformanceManagerImpl::GetInstance();
   performance_manager->task_runner()->PostTask(
       FROM_HERE, base::BindOnce(&ProcessNodeImpl::SetProcess,
                                 base::Unretained(process_node),
diff --git a/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc b/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc
index 8d0dba4..4238caf 100644
--- a/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc
+++ b/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc
@@ -7,7 +7,7 @@
 #include <utility>
 
 #include "chrome/browser/performance_manager/browser_child_process_watcher.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 #include "chrome/browser/performance_manager/performance_manager_tab_helper.h"
 #include "chrome/browser/performance_manager/render_process_user_data.h"
 
@@ -17,7 +17,7 @@
     ~ChromeBrowserMainExtraPartsPerformanceManager() = default;
 
 void ChromeBrowserMainExtraPartsPerformanceManager::PostCreateThreads() {
-  performance_manager_ = performance_manager::PerformanceManager::Create();
+  performance_manager_ = performance_manager::PerformanceManagerImpl::Create();
   browser_child_process_watcher_ =
       std::make_unique<performance_manager::BrowserChildProcessWatcher>();
   browser_child_process_watcher_->Initialize();
@@ -39,6 +39,6 @@
   // frame nodes.
   performance_manager::RenderProcessUserData::DetachAndDestroyAll();
 
-  performance_manager::PerformanceManager::Destroy(
+  performance_manager::PerformanceManagerImpl::Destroy(
       std::move(performance_manager_));
 }
diff --git a/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.h b/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.h
index 44cc4ed..4872a4b 100644
--- a/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.h
+++ b/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.h
@@ -13,7 +13,7 @@
 
 namespace performance_manager {
 class BrowserChildProcessWatcher;
-class PerformanceManager;
+class PerformanceManagerImpl;
 }  // namespace performance_manager
 
 class ChromeBrowserMainExtraPartsPerformanceManager
@@ -27,7 +27,8 @@
   void PostCreateThreads() override;
   void PostMainMessageLoopRun() override;
 
-  std::unique_ptr<performance_manager::PerformanceManager> performance_manager_;
+  std::unique_ptr<performance_manager::PerformanceManagerImpl>
+      performance_manager_;
 
   std::unique_ptr<performance_manager::BrowserChildProcessWatcher>
       browser_child_process_watcher_;
diff --git a/chrome/browser/performance_manager/chrome_content_browser_client_performance_manager_part.cc b/chrome/browser/performance_manager/chrome_content_browser_client_performance_manager_part.cc
index 67e37ae3..6f0f1432 100644
--- a/chrome/browser/performance_manager/chrome_content_browser_client_performance_manager_part.cc
+++ b/chrome/browser/performance_manager/chrome_content_browser_client_performance_manager_part.cc
@@ -10,7 +10,7 @@
 #include "base/logging.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "chrome/browser/performance_manager/graph/process_node_impl.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 #include "chrome/browser/performance_manager/render_process_user_data.h"
 #include "content/public/browser/render_process_host.h"
 #include "services/resource_coordinator/public/mojom/coordination_unit.mojom.h"
@@ -29,8 +29,8 @@
       performance_manager::RenderProcessUserData::GetForRenderProcessHost(
           render_process_host);
 
-  performance_manager::PerformanceManager* performance_manager =
-      performance_manager::PerformanceManager::GetInstance();
+  performance_manager::PerformanceManagerImpl* performance_manager =
+      performance_manager::PerformanceManagerImpl::GetInstance();
   DCHECK(performance_manager);
 
   performance_manager->task_runner()->PostTask(
diff --git a/chrome/browser/performance_manager/graph/page_node_impl_browsertest.cc b/chrome/browser/performance_manager/graph/page_node_impl_browsertest.cc
index cc33ad4..6f130297 100644
--- a/chrome/browser/performance_manager/graph/page_node_impl_browsertest.cc
+++ b/chrome/browser/performance_manager/graph/page_node_impl_browsertest.cc
@@ -11,7 +11,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "chrome/browser/performance_manager/decorators/freeze_origin_trial_policy_aggregator.h"
 #include "chrome/browser/performance_manager/graph/page_node_impl.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
@@ -158,10 +158,10 @@
 
 void RunOriginTrialTestOnPMSequence(
     const resource_coordinator::mojom::InterventionPolicy expected_policy) {
-  auto* perf_manager = PerformanceManager::GetInstance();
+  auto* perf_manager = PerformanceManagerImpl::GetInstance();
   ASSERT_TRUE(perf_manager);
   base::RunLoop run_loop;
-  perf_manager->CallOnGraph(
+  perf_manager->CallOnGraphImpl(
       FROM_HERE, base::BindOnce(
                      [](base::OnceClosure quit_closure,
                         const resource_coordinator::mojom::InterventionPolicy
diff --git a/chrome/browser/performance_manager/graph/policies/dynamic_tcmalloc_policy_linux_unittest.cc b/chrome/browser/performance_manager/graph/policies/dynamic_tcmalloc_policy_linux_unittest.cc
index bf93f11..b9183c7 100644
--- a/chrome/browser/performance_manager/graph/policies/dynamic_tcmalloc_policy_linux_unittest.cc
+++ b/chrome/browser/performance_manager/graph/policies/dynamic_tcmalloc_policy_linux_unittest.cc
@@ -11,7 +11,7 @@
 #include "chrome/browser/performance_manager/graph/page_node_impl.h"
 #include "chrome/browser/performance_manager/graph/policies/policy_features.h"
 #include "chrome/browser/performance_manager/graph/process_node_impl.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 #include "chrome/browser/performance_manager/test_support/graph_test_harness.h"
 #include "chrome/browser/performance_manager/test_support/mock_graphs.h"
 #include "content/public/browser/browser_task_traits.h"
diff --git a/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_chromeos.cc b/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_chromeos.cc
index e08b80b2..4b07eb4 100644
--- a/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_chromeos.cc
+++ b/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_chromeos.cc
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "chrome/browser/performance_manager/graph/policies/policy_features.h"
 #include "chrome/browser/performance_manager/mechanisms/working_set_trimmer.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 #include "chrome/browser/performance_manager/public/graph/frame_node.h"
 #include "chrome/browser/performance_manager/public/graph/graph.h"
 #include "chrome/browser/performance_manager/public/graph/page_node.h"
diff --git a/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_chromeos_unittest.cc b/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_chromeos_unittest.cc
index 4d9c577..cc7574b 100644
--- a/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_chromeos_unittest.cc
+++ b/chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy_chromeos_unittest.cc
@@ -8,7 +8,7 @@
 #include "chrome/browser/performance_manager/graph/graph_impl_operations.h"
 #include "chrome/browser/performance_manager/graph/page_node_impl.h"
 #include "chrome/browser/performance_manager/graph/process_node_impl.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 #include "chrome/browser/performance_manager/test_support/graph_test_harness.h"
 #include "chrome/browser/performance_manager/test_support/mock_graphs.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/performance_manager/performance_manager.cc b/chrome/browser/performance_manager/performance_manager.cc
index 9126d2af..36ce28e 100644
--- a/chrome/browser/performance_manager/performance_manager.cc
+++ b/chrome/browser/performance_manager/performance_manager.cc
@@ -1,95 +1,19 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2019 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/public/performance_manager.h"
 
-#include <atomic>
-#include <memory>
-#include <utility>
-
-#include "base/containers/flat_set.h"
-#include "base/feature_list.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/task/post_task.h"
-#include "base/task/task_traits.h"
-#include "build/build_config.h"
-#include "chrome/browser/performance_manager/decorators/freeze_origin_trial_policy_aggregator.h"
-#include "chrome/browser/performance_manager/decorators/frozen_frame_aggregator.h"
-#include "chrome/browser/performance_manager/decorators/page_almost_idle_decorator.h"
-#include "chrome/browser/performance_manager/decorators/process_metrics_decorator.h"
-#include "chrome/browser/performance_manager/graph/frame_node_impl.h"
-#include "chrome/browser/performance_manager/graph/page_node_impl.h"
-#include "chrome/browser/performance_manager/graph/policies/policy_features.h"
-#include "chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy.h"
-#include "chrome/browser/performance_manager/graph/process_node_impl.h"
-#include "chrome/browser/performance_manager/graph/system_node_impl.h"
-#include "chrome/browser/performance_manager/graph/worker_node_impl.h"
-#include "chrome/browser/performance_manager/observers/isolation_context_metrics.h"
-#include "chrome/browser/performance_manager/observers/metrics_collector.h"
-#include "content/public/browser/system_connector.h"
-#include "content/public/common/content_features.h"
-
-#if defined(OS_LINUX)
-#include "base/allocator/buildflags.h"
-#if BUILDFLAG(USE_TCMALLOC)
-#include "chrome/browser/performance_manager/graph/policies/dynamic_tcmalloc_policy_linux.h"
-#include "chrome/common/performance_manager/mojom/tcmalloc.mojom.h"
-#endif  // BUILDFLAG(USE_TCMALLOC)
-#endif  // defined(OS_LINUX)
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 
 namespace performance_manager {
 
-namespace {
-
-class Singleton {
- public:
-  Singleton() = default;
-  ~Singleton() = default;
-
-  // Safe to call from any thread.
-  PerformanceManager* Get() {
-    return instance_.load(std::memory_order_acquire);
-  }
-
-  // Should be called from the main thread only.
-  void Set(PerformanceManager* instance) {
-    DCHECK_NE(nullptr, instance);
-    auto* old_value = instance_.exchange(instance, std::memory_order_release);
-    DCHECK_EQ(nullptr, old_value);
-  }
-
-  // Should be called from the main thread only.
-  void Clear(PerformanceManager* instance) {
-    DCHECK_NE(nullptr, instance);
-    auto* old_value = instance_.exchange(nullptr, std::memory_order_release);
-    DCHECK_EQ(instance, old_value);
-  }
-
- private:
-  std::atomic<PerformanceManager*> instance_{nullptr};
-};
-Singleton g_performance_manager;
-
-scoped_refptr<base::SequencedTaskRunner> CreateTaskRunner() {
-  return base::CreateSequencedTaskRunner(
-      {base::ThreadPool(), base::TaskPriority::USER_VISIBLE,
-       base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN, base::MayBlock()});
-}
-
-}  // namespace
-
-PerformanceManager::~PerformanceManager() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  // TODO(https://crbug.com/966840): Move this to a TearDown function.
-  graph_.TearDown();
-}
+PerformanceManager::PerformanceManager() = default;
+PerformanceManager::~PerformanceManager() = default;
 
 // static
 bool PerformanceManager::IsAvailable() {
-  return g_performance_manager.Get();
+  return PerformanceManagerImpl::GetInstance();
 }
 
 // static
@@ -100,9 +24,10 @@
   // Passing |pm| unretained is safe as it is actually destroyed on the
   // destination sequence, and g_performance_manager.Get() would return nullptr
   // if its deletion task was already posted.
-  auto* pm = g_performance_manager.Get();
+  auto* pm = PerformanceManagerImpl::GetInstance();
+  // TODO(siggi): Unwrap this by binding the loose param.
   pm->task_runner_->PostTask(
-      from_here, base::BindOnce(&PerformanceManager::CallOnGraphImpl,
+      from_here, base::BindOnce(&PerformanceManagerImpl::RunCallbackWithGraph,
                                 base::Unretained(pm), std::move(callback)));
 }
 
@@ -114,242 +39,11 @@
   // Passing |graph_| unretained is safe as it is actually destroyed on the
   // destination sequence, and g_performance_manager.Get() would return nullptr
   // if its deletion task was already posted.
-  auto* pm = g_performance_manager.Get();
+  auto* pm = PerformanceManagerImpl::GetInstance();
   pm->task_runner_->PostTask(
       from_here,
       base::BindOnce(&GraphImpl::PassToGraph, base::Unretained(&pm->graph_),
                      std::move(graph_owned)));
 }
 
-PerformanceManager* PerformanceManager::GetInstance() {
-  return g_performance_manager.Get();
-}
-
-// static
-std::unique_ptr<PerformanceManager> PerformanceManager::Create() {
-  std::unique_ptr<PerformanceManager> instance =
-      base::WrapUnique(new PerformanceManager());
-
-  instance->OnStart();
-  g_performance_manager.Set(instance.get());
-
-  return instance;
-}
-
-// static
-void PerformanceManager::Destroy(std::unique_ptr<PerformanceManager> instance) {
-  g_performance_manager.Clear(instance.get());
-  instance->task_runner_->DeleteSoon(FROM_HERE, instance.release());
-}
-
-std::unique_ptr<FrameNodeImpl> PerformanceManager::CreateFrameNode(
-    ProcessNodeImpl* process_node,
-    PageNodeImpl* page_node,
-    FrameNodeImpl* parent_frame_node,
-    int frame_tree_node_id,
-    const base::UnguessableToken& dev_tools_token,
-    int32_t browsing_instance_id,
-    int32_t site_instance_id) {
-  return CreateNodeImpl<FrameNodeImpl>(
-      FrameNodeCreationCallback(), process_node, page_node, parent_frame_node,
-      frame_tree_node_id, dev_tools_token, browsing_instance_id,
-      site_instance_id);
-}
-
-std::unique_ptr<FrameNodeImpl> PerformanceManager::CreateFrameNode(
-    ProcessNodeImpl* process_node,
-    PageNodeImpl* page_node,
-    FrameNodeImpl* parent_frame_node,
-    int frame_tree_node_id,
-    const base::UnguessableToken& dev_tools_token,
-    int32_t browsing_instance_id,
-    int32_t site_instance_id,
-    FrameNodeCreationCallback creation_callback) {
-  return CreateNodeImpl<FrameNodeImpl>(
-      std::move(creation_callback), process_node, page_node, parent_frame_node,
-      frame_tree_node_id, dev_tools_token, browsing_instance_id,
-      site_instance_id);
-}
-
-std::unique_ptr<PageNodeImpl> PerformanceManager::CreatePageNode(
-    const WebContentsProxy& contents_proxy,
-    const std::string& browser_context_id,
-    bool is_visible,
-    bool is_audible) {
-  return CreateNodeImpl<PageNodeImpl>(base::OnceCallback<void(PageNodeImpl*)>(),
-                                      contents_proxy, browser_context_id,
-                                      is_visible, is_audible);
-}
-
-std::unique_ptr<ProcessNodeImpl> PerformanceManager::CreateProcessNode(
-    RenderProcessHostProxy proxy) {
-  return CreateNodeImpl<ProcessNodeImpl>(
-      base::OnceCallback<void(ProcessNodeImpl*)>(), proxy);
-}
-
-std::unique_ptr<WorkerNodeImpl> PerformanceManager::CreateWorkerNode(
-    const std::string& browser_context_id,
-    WorkerNode::WorkerType worker_type,
-    ProcessNodeImpl* process_node,
-    const GURL& url,
-    const base::UnguessableToken& dev_tools_token) {
-  return CreateNodeImpl<WorkerNodeImpl>(
-      base::OnceCallback<void(WorkerNodeImpl*)>(), browser_context_id,
-      worker_type, process_node, url, dev_tools_token);
-}
-
-void PerformanceManager::BatchDeleteNodes(
-    std::vector<std::unique_ptr<NodeBase>> nodes) {
-  task_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&PerformanceManager::BatchDeleteNodesImpl,
-                                base::Unretained(this), std::move(nodes)));
-}
-
-PerformanceManager::PerformanceManager() : task_runner_(CreateTaskRunner()) {
-  DETACH_FROM_SEQUENCE(sequence_checker_);
-}
-
-namespace {
-
-// Helper function for adding a node to a graph, and invoking a post-creation
-// callback immediately afterwards.
-template <typename NodeType>
-void AddNodeAndInvokeCreationCallback(
-    base::OnceCallback<void(NodeType*)> callback,
-    NodeType* node,
-    GraphImpl* graph) {
-  graph->AddNewNode(node);
-  if (callback)
-    std::move(callback).Run(node);
-}
-
-}  // namespace
-
-template <typename NodeType, typename... Args>
-std::unique_ptr<NodeType> PerformanceManager::CreateNodeImpl(
-    base::OnceCallback<void(NodeType*)> creation_callback,
-    Args&&... constructor_args) {
-  std::unique_ptr<NodeType> new_node = std::make_unique<NodeType>(
-      &graph_, std::forward<Args>(constructor_args)...);
-  task_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&AddNodeAndInvokeCreationCallback<NodeType>,
-                                std::move(creation_callback),
-                                base::Unretained(new_node.get()),
-                                base::Unretained(&graph_)));
-  return new_node;
-}
-
-void PerformanceManager::PostDeleteNode(std::unique_ptr<NodeBase> node) {
-  task_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&PerformanceManager::DeleteNodeImpl,
-                                base::Unretained(this), std::move(node)));
-}
-
-void PerformanceManager::DeleteNodeImpl(std::unique_ptr<NodeBase> node) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  graph_.RemoveNode(node.get());
-}
-
-namespace {
-
-void RemoveFrameAndChildrenFromGraph(FrameNodeImpl* frame_node) {
-  // Recurse on the first child while there is one.
-  while (!frame_node->child_frame_nodes().empty())
-    RemoveFrameAndChildrenFromGraph(*(frame_node->child_frame_nodes().begin()));
-
-  // Now that all children are deleted, delete this frame.
-  frame_node->graph()->RemoveNode(frame_node);
-}
-
-}  // namespace
-
-void PerformanceManager::BatchDeleteNodesImpl(
-    std::vector<std::unique_ptr<NodeBase>> nodes) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  base::flat_set<ProcessNodeImpl*> process_nodes;
-
-  for (auto it = nodes.begin(); it != nodes.end(); ++it) {
-    switch ((*it)->type()) {
-      case PageNodeImpl::Type(): {
-        auto* page_node = PageNodeImpl::FromNodeBase(it->get());
-
-        // Delete the main frame nodes until no more exist.
-        while (!page_node->main_frame_nodes().empty())
-          RemoveFrameAndChildrenFromGraph(
-              *(page_node->main_frame_nodes().begin()));
-
-        graph_.RemoveNode(page_node);
-        break;
-      }
-      case ProcessNodeImpl::Type(): {
-        // Keep track of the process nodes for removing once all frames nodes
-        // are removed.
-        auto* process_node = ProcessNodeImpl::FromNodeBase(it->get());
-        process_nodes.insert(process_node);
-        break;
-      }
-      case FrameNodeImpl::Type():
-        break;
-      case SystemNodeImpl::Type():
-      case NodeTypeEnum::kInvalidType:
-      default: {
-        NOTREACHED();
-        break;
-      }
-    }
-  }
-
-  // Remove the process nodes from the graph.
-  for (auto* process_node : process_nodes)
-    graph_.RemoveNode(process_node);
-
-  // When |nodes| goes out of scope, all nodes are deleted.
-}
-
-void PerformanceManager::OnStart() {
-  // Some tests don't initialize the service manager connection, so this class
-  // tolerates its absence for tests.
-  auto* connector = content::GetSystemConnector();
-  task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&PerformanceManager::OnStartImpl, base::Unretained(this),
-                     connector ? connector->Clone() : nullptr));
-}
-
-void PerformanceManager::CallOnGraphImpl(GraphCallback graph_callback) {
-  std::move(graph_callback).Run(&graph_);
-}
-
-void PerformanceManager::OnStartImpl(
-    std::unique_ptr<service_manager::Connector> connector) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  graph_.PassToGraph(std::make_unique<FreezeOriginTrialPolicyAggregator>());
-  graph_.PassToGraph(std::make_unique<FrozenFrameAggregator>());
-  graph_.PassToGraph(std::make_unique<PageAlmostIdleDecorator>());
-  graph_.PassToGraph(std::make_unique<IsolationContextMetrics>());
-  graph_.PassToGraph(std::make_unique<MetricsCollector>());
-  graph_.PassToGraph(std::make_unique<ProcessMetricsDecorator>());
-
-  if (policies::WorkingSetTrimmerPolicy::PlatformSupportsWorkingSetTrim()) {
-    graph_.PassToGraph(
-        policies::WorkingSetTrimmerPolicy::CreatePolicyForPlatform());
-  }
-
-#if defined(OS_LINUX)
-#if BUILDFLAG(USE_TCMALLOC)
-  if (base::FeatureList::IsEnabled(features::kDynamicTcmallocTuning)) {
-    graph_.PassToGraph(std::make_unique<policies::DynamicTcmallocPolicy>());
-  }
-#endif  // BUILDFLAG(USE_TCMALLOC)
-#endif  // defined(OS_LINUX)
-
-  if (connector) {
-    ukm_recorder_ = ukm::MojoUkmRecorder::Create(connector.get());
-    graph_.set_ukm_recorder(ukm_recorder_.get());
-  }
-}
-
 }  // namespace performance_manager
diff --git a/chrome/browser/performance_manager/performance_manager_impl.cc b/chrome/browser/performance_manager/performance_manager_impl.cc
new file mode 100644
index 0000000..014f3d1
--- /dev/null
+++ b/chrome/browser/performance_manager/performance_manager_impl.cc
@@ -0,0 +1,348 @@
+// 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/performance_manager/performance_manager_impl.h"
+
+#include <atomic>
+#include <memory>
+#include <utility>
+
+#include "base/containers/flat_set.h"
+#include "base/feature_list.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
+#include "build/build_config.h"
+#include "chrome/browser/performance_manager/decorators/freeze_origin_trial_policy_aggregator.h"
+#include "chrome/browser/performance_manager/decorators/frozen_frame_aggregator.h"
+#include "chrome/browser/performance_manager/decorators/page_almost_idle_decorator.h"
+#include "chrome/browser/performance_manager/decorators/process_metrics_decorator.h"
+#include "chrome/browser/performance_manager/graph/frame_node_impl.h"
+#include "chrome/browser/performance_manager/graph/page_node_impl.h"
+#include "chrome/browser/performance_manager/graph/policies/policy_features.h"
+#include "chrome/browser/performance_manager/graph/policies/working_set_trimmer_policy.h"
+#include "chrome/browser/performance_manager/graph/process_node_impl.h"
+#include "chrome/browser/performance_manager/graph/system_node_impl.h"
+#include "chrome/browser/performance_manager/graph/worker_node_impl.h"
+#include "chrome/browser/performance_manager/observers/isolation_context_metrics.h"
+#include "chrome/browser/performance_manager/observers/metrics_collector.h"
+#include "content/public/browser/system_connector.h"
+#include "content/public/common/content_features.h"
+
+#if defined(OS_LINUX)
+#include "base/allocator/buildflags.h"
+#if BUILDFLAG(USE_TCMALLOC)
+#include "chrome/browser/performance_manager/graph/policies/dynamic_tcmalloc_policy_linux.h"
+#include "chrome/common/performance_manager/mojom/tcmalloc.mojom.h"
+#endif  // BUILDFLAG(USE_TCMALLOC)
+#endif  // defined(OS_LINUX)
+
+namespace performance_manager {
+
+namespace {
+
+class Singleton {
+ public:
+  Singleton() = default;
+  ~Singleton() = default;
+
+  // Safe to call from any thread.
+  PerformanceManagerImpl* Get() {
+    return instance_.load(std::memory_order_acquire);
+  }
+
+  // Should be called from the main thread only.
+  void Set(PerformanceManagerImpl* instance) {
+    DCHECK_NE(nullptr, instance);
+    auto* old_value = instance_.exchange(instance, std::memory_order_release);
+    DCHECK_EQ(nullptr, old_value);
+  }
+
+  // Should be called from the main thread only.
+  void Clear(PerformanceManagerImpl* instance) {
+    DCHECK_NE(nullptr, instance);
+    auto* old_value = instance_.exchange(nullptr, std::memory_order_release);
+    DCHECK_EQ(instance, old_value);
+  }
+
+ private:
+  std::atomic<PerformanceManagerImpl*> instance_{nullptr};
+};
+Singleton g_performance_manager;
+
+scoped_refptr<base::SequencedTaskRunner> CreateTaskRunner() {
+  return base::CreateSequencedTaskRunner(
+      {base::ThreadPool(), base::TaskPriority::USER_VISIBLE,
+       base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN, base::MayBlock()});
+}
+
+}  // namespace
+
+PerformanceManagerImpl::~PerformanceManagerImpl() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  // TODO(https://crbug.com/966840): Move this to a TearDown function.
+  graph_.TearDown();
+}
+
+// static
+void PerformanceManagerImpl::CallOnGraphImpl(const base::Location& from_here,
+                                             GraphImplCallback callback) {
+  DCHECK(callback);
+
+  // Passing |pm| unretained is safe as it is actually destroyed on the
+  // destination sequence, and g_performance_manager.Get() would return nullptr
+  // if its deletion task was already posted.
+  auto* pm = g_performance_manager.Get();
+  pm->task_runner_->PostTask(
+      from_here,
+      base::BindOnce(&PerformanceManagerImpl::RunCallbackWithGraphImpl,
+                     base::Unretained(pm), std::move(callback)));
+}
+
+PerformanceManagerImpl* PerformanceManagerImpl::GetInstance() {
+  return g_performance_manager.Get();
+}
+
+// static
+std::unique_ptr<PerformanceManagerImpl> PerformanceManagerImpl::Create() {
+  std::unique_ptr<PerformanceManagerImpl> instance =
+      base::WrapUnique(new PerformanceManagerImpl());
+
+  instance->OnStart();
+  g_performance_manager.Set(instance.get());
+
+  return instance;
+}
+
+// static
+void PerformanceManagerImpl::Destroy(
+    std::unique_ptr<PerformanceManagerImpl> instance) {
+  g_performance_manager.Clear(instance.get());
+  instance->task_runner_->DeleteSoon(FROM_HERE, instance.release());
+}
+
+std::unique_ptr<FrameNodeImpl> PerformanceManagerImpl::CreateFrameNode(
+    ProcessNodeImpl* process_node,
+    PageNodeImpl* page_node,
+    FrameNodeImpl* parent_frame_node,
+    int frame_tree_node_id,
+    const base::UnguessableToken& dev_tools_token,
+    int32_t browsing_instance_id,
+    int32_t site_instance_id) {
+  return CreateNodeImpl<FrameNodeImpl>(
+      FrameNodeCreationCallback(), process_node, page_node, parent_frame_node,
+      frame_tree_node_id, dev_tools_token, browsing_instance_id,
+      site_instance_id);
+}
+
+std::unique_ptr<FrameNodeImpl> PerformanceManagerImpl::CreateFrameNode(
+    ProcessNodeImpl* process_node,
+    PageNodeImpl* page_node,
+    FrameNodeImpl* parent_frame_node,
+    int frame_tree_node_id,
+    const base::UnguessableToken& dev_tools_token,
+    int32_t browsing_instance_id,
+    int32_t site_instance_id,
+    FrameNodeCreationCallback creation_callback) {
+  return CreateNodeImpl<FrameNodeImpl>(
+      std::move(creation_callback), process_node, page_node, parent_frame_node,
+      frame_tree_node_id, dev_tools_token, browsing_instance_id,
+      site_instance_id);
+}
+
+std::unique_ptr<PageNodeImpl> PerformanceManagerImpl::CreatePageNode(
+    const WebContentsProxy& contents_proxy,
+    const std::string& browser_context_id,
+    bool is_visible,
+    bool is_audible) {
+  return CreateNodeImpl<PageNodeImpl>(base::OnceCallback<void(PageNodeImpl*)>(),
+                                      contents_proxy, browser_context_id,
+                                      is_visible, is_audible);
+}
+
+std::unique_ptr<ProcessNodeImpl> PerformanceManagerImpl::CreateProcessNode(
+    RenderProcessHostProxy proxy) {
+  return CreateNodeImpl<ProcessNodeImpl>(
+      base::OnceCallback<void(ProcessNodeImpl*)>(), proxy);
+}
+
+std::unique_ptr<WorkerNodeImpl> PerformanceManagerImpl::CreateWorkerNode(
+    const std::string& browser_context_id,
+    WorkerNode::WorkerType worker_type,
+    ProcessNodeImpl* process_node,
+    const GURL& url,
+    const base::UnguessableToken& dev_tools_token) {
+  return CreateNodeImpl<WorkerNodeImpl>(
+      base::OnceCallback<void(WorkerNodeImpl*)>(), browser_context_id,
+      worker_type, process_node, url, dev_tools_token);
+}
+
+void PerformanceManagerImpl::BatchDeleteNodes(
+    std::vector<std::unique_ptr<NodeBase>> nodes) {
+  task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&PerformanceManagerImpl::BatchDeleteNodesImpl,
+                                base::Unretained(this), std::move(nodes)));
+}
+
+PerformanceManagerImpl::PerformanceManagerImpl()
+    : task_runner_(CreateTaskRunner()) {
+  DETACH_FROM_SEQUENCE(sequence_checker_);
+}
+
+namespace {
+
+// Helper function for adding a node to a graph, and invoking a post-creation
+// callback immediately afterwards.
+template <typename NodeType>
+void AddNodeAndInvokeCreationCallback(
+    base::OnceCallback<void(NodeType*)> callback,
+    NodeType* node,
+    GraphImpl* graph) {
+  graph->AddNewNode(node);
+  if (callback)
+    std::move(callback).Run(node);
+}
+
+}  // namespace
+
+template <typename NodeType, typename... Args>
+std::unique_ptr<NodeType> PerformanceManagerImpl::CreateNodeImpl(
+    base::OnceCallback<void(NodeType*)> creation_callback,
+    Args&&... constructor_args) {
+  std::unique_ptr<NodeType> new_node = std::make_unique<NodeType>(
+      &graph_, std::forward<Args>(constructor_args)...);
+  task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&AddNodeAndInvokeCreationCallback<NodeType>,
+                                std::move(creation_callback),
+                                base::Unretained(new_node.get()),
+                                base::Unretained(&graph_)));
+  return new_node;
+}
+
+void PerformanceManagerImpl::PostDeleteNode(std::unique_ptr<NodeBase> node) {
+  task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&PerformanceManagerImpl::DeleteNodeImpl,
+                                base::Unretained(this), std::move(node)));
+}
+
+void PerformanceManagerImpl::DeleteNodeImpl(std::unique_ptr<NodeBase> node) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  graph_.RemoveNode(node.get());
+}
+
+namespace {
+
+void RemoveFrameAndChildrenFromGraph(FrameNodeImpl* frame_node) {
+  // Recurse on the first child while there is one.
+  while (!frame_node->child_frame_nodes().empty())
+    RemoveFrameAndChildrenFromGraph(*(frame_node->child_frame_nodes().begin()));
+
+  // Now that all children are deleted, delete this frame.
+  frame_node->graph()->RemoveNode(frame_node);
+}
+
+}  // namespace
+
+void PerformanceManagerImpl::BatchDeleteNodesImpl(
+    std::vector<std::unique_ptr<NodeBase>> nodes) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  base::flat_set<ProcessNodeImpl*> process_nodes;
+
+  for (auto it = nodes.begin(); it != nodes.end(); ++it) {
+    switch ((*it)->type()) {
+      case PageNodeImpl::Type(): {
+        auto* page_node = PageNodeImpl::FromNodeBase(it->get());
+
+        // Delete the main frame nodes until no more exist.
+        while (!page_node->main_frame_nodes().empty())
+          RemoveFrameAndChildrenFromGraph(
+              *(page_node->main_frame_nodes().begin()));
+
+        graph_.RemoveNode(page_node);
+        break;
+      }
+      case ProcessNodeImpl::Type(): {
+        // Keep track of the process nodes for removing once all frames nodes
+        // are removed.
+        auto* process_node = ProcessNodeImpl::FromNodeBase(it->get());
+        process_nodes.insert(process_node);
+        break;
+      }
+      case FrameNodeImpl::Type():
+        break;
+      case SystemNodeImpl::Type():
+      case NodeTypeEnum::kInvalidType:
+      default: {
+        NOTREACHED();
+        break;
+      }
+    }
+  }
+
+  // Remove the process nodes from the graph.
+  for (auto* process_node : process_nodes)
+    graph_.RemoveNode(process_node);
+
+  // When |nodes| goes out of scope, all nodes are deleted.
+}
+
+void PerformanceManagerImpl::OnStart() {
+  // Some tests don't initialize the service manager connection, so this class
+  // tolerates its absence for tests.
+  auto* connector = content::GetSystemConnector();
+  task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&PerformanceManagerImpl::OnStartImpl,
+                                base::Unretained(this),
+                                connector ? connector->Clone() : nullptr));
+}
+
+void PerformanceManagerImpl::RunCallbackWithGraphImpl(
+    GraphImplCallback graph_callback) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  std::move(graph_callback).Run(&graph_);
+}
+
+void PerformanceManagerImpl::RunCallbackWithGraph(
+    GraphCallback graph_callback) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  std::move(graph_callback).Run(&graph_);
+}
+
+void PerformanceManagerImpl::OnStartImpl(
+    std::unique_ptr<service_manager::Connector> connector) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  graph_.PassToGraph(std::make_unique<FreezeOriginTrialPolicyAggregator>());
+  graph_.PassToGraph(std::make_unique<FrozenFrameAggregator>());
+  graph_.PassToGraph(std::make_unique<PageAlmostIdleDecorator>());
+  graph_.PassToGraph(std::make_unique<IsolationContextMetrics>());
+  graph_.PassToGraph(std::make_unique<MetricsCollector>());
+  graph_.PassToGraph(std::make_unique<ProcessMetricsDecorator>());
+
+  if (policies::WorkingSetTrimmerPolicy::PlatformSupportsWorkingSetTrim()) {
+    graph_.PassToGraph(
+        policies::WorkingSetTrimmerPolicy::CreatePolicyForPlatform());
+  }
+
+#if defined(OS_LINUX)
+#if BUILDFLAG(USE_TCMALLOC)
+  if (base::FeatureList::IsEnabled(features::kDynamicTcmallocTuning)) {
+    graph_.PassToGraph(std::make_unique<policies::DynamicTcmallocPolicy>());
+  }
+#endif  // BUILDFLAG(USE_TCMALLOC)
+#endif  // defined(OS_LINUX)
+
+  if (connector) {
+    ukm_recorder_ = ukm::MojoUkmRecorder::Create(connector.get());
+    graph_.set_ukm_recorder(ukm_recorder_.get());
+  }
+}
+
+}  // namespace performance_manager
diff --git a/chrome/browser/performance_manager/performance_manager.h b/chrome/browser/performance_manager/performance_manager_impl.h
similarity index 75%
rename from chrome/browser/performance_manager/performance_manager.h
rename to chrome/browser/performance_manager/performance_manager_impl.h
index 1f691ae..8d83b240 100644
--- a/chrome/browser/performance_manager/performance_manager.h
+++ b/chrome/browser/performance_manager/performance_manager_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_PERFORMANCE_MANAGER_H_
-#define CHROME_BROWSER_PERFORMANCE_MANAGER_PERFORMANCE_MANAGER_H_
+#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_PERFORMANCE_MANAGER_IMPL_H_
+#define CHROME_BROWSER_PERFORMANCE_MANAGER_PERFORMANCE_MANAGER_IMPL_H_
 
 #include <memory>
 #include <string>
@@ -18,11 +18,10 @@
 #include "base/task_runner_util.h"
 #include "chrome/browser/performance_manager/graph/graph_impl.h"
 #include "chrome/browser/performance_manager/public/graph/worker_node.h"
+#include "chrome/browser/performance_manager/public/performance_manager.h"
 #include "chrome/browser/performance_manager/public/render_process_host_proxy.h"
 #include "chrome/browser/performance_manager/public/web_contents_proxy.h"
 #include "services/resource_coordinator/public/mojom/coordination_unit.mojom.h"
-#include "services/service_manager/public/cpp/bind_source_info.h"
-#include "services/service_manager/public/cpp/connector.h"
 
 class GURL;
 
@@ -32,32 +31,25 @@
 
 namespace performance_manager {
 
-class GraphOwned;
 class PageNodeImpl;
 
 // The performance manager is a rendezvous point for binding to performance
 // manager interfaces.
 // TODO(https://crbug.com/910288): Refactor this along with the
 // {Frame|Page|Process|System}ResourceCoordinator classes.
-class PerformanceManager {
+class PerformanceManagerImpl : public PerformanceManager {
  public:
   using FrameNodeCreationCallback = base::OnceCallback<void(FrameNodeImpl*)>;
 
-  ~PerformanceManager();
-
-  // Returns true if the performance manager is initialized. This is valid to
-  // call anywhere, but is only really meaningful on the main thread (where it
-  // will not change values within the scope of a task).
-  // TODO(chrisha): Move this to the public interface.
-  static bool IsAvailable();
+  ~PerformanceManagerImpl() override;
 
   // Posts a callback that will run on the PM sequence, and be provided a
   // pointer to the Graph. Valid to be called from the main thread only, and
   // only if "IsAvailable" returns true.
   // TODO(chrisha): Move this to the public interface.
-  using GraphCallback = base::OnceCallback<void(GraphImpl*)>;
-  static void CallOnGraph(const base::Location& from_here,
-                          GraphCallback graph_callback);
+  using GraphImplCallback = base::OnceCallback<void(GraphImpl*)>;
+  static void CallOnGraphImpl(const base::Location& from_here,
+                              GraphImplCallback graph_callback);
 
   // Posts a callback that will run on the PM sequence, and be provided a
   // pointer to the Graph. Valid to be called from the main thread only, and
@@ -69,24 +61,18 @@
       base::OnceCallback<TaskReturnType(GraphImpl*)> task,
       base::OnceCallback<void(TaskReturnType)> reply);
 
-  // Passes a GraphOwned object into the Graph on the PM sequence. Should only
-  // be called from the main thread and only if "IsAvailable" returns true.
-  // TODO(chrisha): Move this to the public interface.
-  static void PassToGraph(const base::Location& from_here,
-                          std::unique_ptr<GraphOwned> graph_owned);
-
   // Retrieves the currently registered instance.
   // The caller needs to ensure that the lifetime of the registered instance
   // exceeds the use of this function and the retrieved pointer.
   // This function can be called from any sequence with those caveats.
-  static PerformanceManager* GetInstance();
+  static PerformanceManagerImpl* GetInstance();
 
   // Creates, initializes and registers an instance.
-  static std::unique_ptr<PerformanceManager> Create();
+  static std::unique_ptr<PerformanceManagerImpl> Create();
 
   // Unregisters |instance| if it's currently registered and arranges for its
   // deletion on its sequence.
-  static void Destroy(std::unique_ptr<PerformanceManager> instance);
+  static void Destroy(std::unique_ptr<PerformanceManagerImpl> instance);
 
   // Creates a new node of the requested type and adds it to the graph.
   // May be called from any sequence. If a |creation_callback| is provided it
@@ -145,9 +131,9 @@
   }
 
  private:
-  PerformanceManager();
-  void PostBindInterface(const std::string& interface_name,
-                         mojo::ScopedMessagePipeHandle message_pipe);
+  friend class PerformanceManager;
+
+  PerformanceManagerImpl();
 
   template <typename NodeType, typename... Args>
   std::unique_ptr<NodeType> CreateNodeImpl(
@@ -160,10 +146,11 @@
 
   void OnStart();
   void OnStartImpl(std::unique_ptr<service_manager::Connector> connector);
-  void CallOnGraphImpl(GraphCallback graph_callback);
+  void RunCallbackWithGraphImpl(GraphImplCallback graph_callback);
+  void RunCallbackWithGraph(GraphCallback graph_callback);
 
   template <typename TaskReturnType>
-  TaskReturnType CallOnGraphAndReplyWithResultImpl(
+  TaskReturnType RunCallbackWithGraphAndReplyWithResult(
       base::OnceCallback<TaskReturnType(GraphImpl*)> task);
 
   // The performance task runner.
@@ -176,34 +163,37 @@
 
   SEQUENCE_CHECKER(sequence_checker_);
 
-  DISALLOW_COPY_AND_ASSIGN(PerformanceManager);
+  DISALLOW_COPY_AND_ASSIGN(PerformanceManagerImpl);
 };
 
 template <typename NodeType>
-void PerformanceManager::DeleteNode(std::unique_ptr<NodeType> node) {
+void PerformanceManagerImpl::DeleteNode(std::unique_ptr<NodeType> node) {
   PostDeleteNode(std::move(node));
 }
 
 template <typename TaskReturnType>
-void PerformanceManager::CallOnGraphAndReplyWithResult(
+void PerformanceManagerImpl::CallOnGraphAndReplyWithResult(
     const base::Location& from_here,
     base::OnceCallback<TaskReturnType(GraphImpl*)> task,
     base::OnceCallback<void(TaskReturnType)> reply) {
   auto* pm = GetInstance();
   base::PostTaskAndReplyWithResult(
       pm->task_runner_.get(), from_here,
-      base::BindOnce(&PerformanceManager::CallOnGraphAndReplyWithResultImpl<
-                         TaskReturnType>,
-                     base::Unretained(pm), std::move(task)),
+      base::BindOnce(
+          &PerformanceManagerImpl::RunCallbackWithGraphAndReplyWithResult<
+              TaskReturnType>,
+          base::Unretained(pm), std::move(task)),
       std::move(reply));
 }
 
 template <typename TaskReturnType>
-TaskReturnType PerformanceManager::CallOnGraphAndReplyWithResultImpl(
+TaskReturnType PerformanceManagerImpl::RunCallbackWithGraphAndReplyWithResult(
     base::OnceCallback<TaskReturnType(GraphImpl*)> task) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
   return std::move(task).Run(&graph_);
 }
 
 }  // namespace performance_manager
 
-#endif  // CHROME_BROWSER_PERFORMANCE_MANAGER_PERFORMANCE_MANAGER_H_
+#endif  // CHROME_BROWSER_PERFORMANCE_MANAGER_PERFORMANCE_MANAGER_IMPL_H_
diff --git a/chrome/browser/performance_manager/performance_manager_unittest.cc b/chrome/browser/performance_manager/performance_manager_impl_unittest.cc
similarity index 87%
rename from chrome/browser/performance_manager/performance_manager_unittest.cc
rename to chrome/browser/performance_manager/performance_manager_impl_unittest.cc
index 9c3d214..437ef18 100644
--- a/chrome/browser/performance_manager/performance_manager_unittest.cc
+++ b/chrome/browser/performance_manager/performance_manager_impl_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 
 #include <utility>
 
@@ -25,29 +25,30 @@
   ~PerformanceManagerTest() override {}
 
   void SetUp() override {
-    EXPECT_EQ(nullptr, PerformanceManager::GetInstance());
-    performance_manager_ = PerformanceManager::Create();
+    EXPECT_EQ(nullptr, PerformanceManagerImpl::GetInstance());
+    performance_manager_ = PerformanceManagerImpl::Create();
     // Make sure creation registers the created instance.
-    EXPECT_EQ(performance_manager_.get(), PerformanceManager::GetInstance());
+    EXPECT_EQ(performance_manager_.get(),
+              PerformanceManagerImpl::GetInstance());
   }
 
   void TearDown() override {
     if (performance_manager_) {
-      PerformanceManager::Destroy(std::move(performance_manager_));
+      PerformanceManagerImpl::Destroy(std::move(performance_manager_));
       // Make sure destruction unregisters the instance.
-      EXPECT_EQ(nullptr, PerformanceManager::GetInstance());
+      EXPECT_EQ(nullptr, PerformanceManagerImpl::GetInstance());
     }
 
     task_environment_.RunUntilIdle();
   }
 
  protected:
-  PerformanceManager* performance_manager() {
+  PerformanceManagerImpl* performance_manager() {
     return performance_manager_.get();
   }
 
  private:
-  std::unique_ptr<PerformanceManager> performance_manager_;
+  std::unique_ptr<PerformanceManagerImpl> performance_manager_;
   base::test::TaskEnvironment task_environment_;
 
   DISALLOW_COPY_AND_ASSIGN(PerformanceManagerTest);
@@ -120,7 +121,7 @@
   performance_manager()->BatchDeleteNodes(std::move(nodes));
 }
 
-TEST_F(PerformanceManagerTest, CallOnGraph) {
+TEST_F(PerformanceManagerTest, CallOnGraphImpl) {
   // Create a page node for something to target.
   std::unique_ptr<PageNodeImpl> page_node =
       performance_manager()->CreatePageNode(WebContentsProxy(), std::string(),
@@ -128,15 +129,15 @@
   base::RunLoop run_loop;
   base::OnceClosure quit_closure = run_loop.QuitClosure();
   EXPECT_FALSE(performance_manager()->OnPMTaskRunnerForTesting());
-  PerformanceManager::GraphCallback graph_callback =
+  PerformanceManagerImpl::GraphImplCallback graph_callback =
       base::BindLambdaForTesting([&](GraphImpl* graph) {
         EXPECT_TRUE(
-            PerformanceManager::GetInstance()->OnPMTaskRunnerForTesting());
+            PerformanceManagerImpl::GetInstance()->OnPMTaskRunnerForTesting());
         EXPECT_EQ(page_node.get()->graph(), graph);
         std::move(quit_closure).Run();
       });
 
-  performance_manager()->CallOnGraph(FROM_HERE, std::move(graph_callback));
+  performance_manager()->CallOnGraphImpl(FROM_HERE, std::move(graph_callback));
   run_loop.Run();
 
   performance_manager()->DeleteNode(std::move(page_node));
@@ -153,7 +154,7 @@
   base::OnceCallback<int(GraphImpl*)> task =
       base::BindLambdaForTesting([&](GraphImpl* graph) {
         EXPECT_TRUE(
-            PerformanceManager::GetInstance()->OnPMTaskRunnerForTesting());
+            PerformanceManagerImpl::GetInstance()->OnPMTaskRunnerForTesting());
         EXPECT_EQ(page_node.get()->graph(), graph);
         return 1;
       });
diff --git a/chrome/browser/performance_manager/performance_manager_tab_helper.cc b/chrome/browser/performance_manager/performance_manager_tab_helper.cc
index 7c14b30..eba7783 100644
--- a/chrome/browser/performance_manager/performance_manager_tab_helper.cc
+++ b/chrome/browser/performance_manager/performance_manager_tab_helper.cc
@@ -12,7 +12,7 @@
 #include "chrome/browser/performance_manager/graph/frame_node_impl.h"
 #include "chrome/browser/performance_manager/graph/page_node_impl.h"
 #include "chrome/browser/performance_manager/graph/process_node_impl.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 #include "chrome/browser/performance_manager/render_process_user_data.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/navigation_handle.h"
@@ -34,7 +34,7 @@
 PerformanceManagerTabHelper::PerformanceManagerTabHelper(
     content::WebContents* web_contents)
     : content::WebContentsObserver(web_contents),
-      performance_manager_(PerformanceManager::GetInstance()) {
+      performance_manager_(PerformanceManagerImpl::GetInstance()) {
   page_node_ = performance_manager_->CreatePageNode(
       WebContentsProxy(weak_factory_.GetWeakPtr()),
       web_contents->GetBrowserContext()->UniqueId(),
@@ -72,7 +72,8 @@
 }
 
 PerformanceManagerTabHelper::~PerformanceManagerTabHelper() {
-  // Ship our page and frame nodes to the PerformanceManager for incineration.
+  // Ship our page and frame nodes to the PerformanceManagerImpl for
+  // incineration.
   std::vector<std::unique_ptr<NodeBase>> nodes;
   nodes.push_back(std::move(page_node_));
   for (auto& kv : frames_)
diff --git a/chrome/browser/performance_manager/performance_manager_tab_helper.h b/chrome/browser/performance_manager/performance_manager_tab_helper.h
index 4a20d8f40..a2690f2 100644
--- a/chrome/browser/performance_manager/performance_manager_tab_helper.h
+++ b/chrome/browser/performance_manager/performance_manager_tab_helper.h
@@ -21,7 +21,7 @@
 
 class FrameNodeImpl;
 class PageNodeImpl;
-class PerformanceManager;
+class PerformanceManagerImpl;
 
 // This tab helper maintains a page node, and its associated tree of frame nodes
 // in the performance manager graph. It also sources a smattering of attributes
@@ -82,7 +82,7 @@
   void OnMainFrameNavigation(int64_t navigation_id);
 
   // The performance manager for this process, if any.
-  PerformanceManager* const performance_manager_;
+  PerformanceManagerImpl* const performance_manager_;
   std::unique_ptr<PageNodeImpl> page_node_;
   ukm::SourceId ukm_source_id_ = ukm::kInvalidSourceId;
 
diff --git a/chrome/browser/performance_manager/performance_manager_tab_helper_unittest.cc b/chrome/browser/performance_manager/performance_manager_tab_helper_unittest.cc
index 80dca0ad..bba3d63 100644
--- a/chrome/browser/performance_manager/performance_manager_tab_helper_unittest.cc
+++ b/chrome/browser/performance_manager/performance_manager_tab_helper_unittest.cc
@@ -65,10 +65,10 @@
   }
 };
 
-void CallOnGraphSync(PerformanceManager::GraphCallback callback) {
+void CallOnGraphSync(PerformanceManagerImpl::GraphImplCallback callback) {
   base::RunLoop run_loop;
 
-  PerformanceManager::GetInstance()->CallOnGraph(
+  PerformanceManagerImpl::GetInstance()->CallOnGraphImpl(
       FROM_HERE,
       base::BindLambdaForTesting([&run_loop, &callback](GraphImpl* graph) {
         std::move(callback).Run(graph);
@@ -196,7 +196,7 @@
 
   size_t num_hosts = CountAllRenderProcessHosts();
 
-  PerformanceManager::GetInstance()->CallOnGraph(
+  PerformanceManagerImpl::GetInstance()->CallOnGraphImpl(
       FROM_HERE, base::BindLambdaForTesting([num_hosts](GraphImpl* graph) {
         EXPECT_GE(num_hosts, graph->GetAllProcessNodeImpls().size());
         EXPECT_EQ(0u, graph->GetAllFrameNodeImpls().size());
diff --git a/chrome/browser/performance_manager/performance_manager_test_harness.cc b/chrome/browser/performance_manager/performance_manager_test_harness.cc
index 41fd230..62665e1 100644
--- a/chrome/browser/performance_manager/performance_manager_test_harness.cc
+++ b/chrome/browser/performance_manager/performance_manager_test_harness.cc
@@ -14,12 +14,12 @@
 
 void PerformanceManagerTestHarness::SetUp() {
   Super::SetUp();
-  perf_man_ = PerformanceManager::Create();
+  perf_man_ = PerformanceManagerImpl::Create();
 }
 
 void PerformanceManagerTestHarness::TearDown() {
   // Have the performance manager destroy itself.
-  PerformanceManager::Destroy(std::move(perf_man_));
+  PerformanceManagerImpl::Destroy(std::move(perf_man_));
   task_environment()->RunUntilIdle();
 
   Super::TearDown();
diff --git a/chrome/browser/performance_manager/performance_manager_test_harness.h b/chrome/browser/performance_manager/performance_manager_test_harness.h
index 6e9442b..c0cf1da 100644
--- a/chrome/browser/performance_manager/performance_manager_test_harness.h
+++ b/chrome/browser/performance_manager/performance_manager_test_harness.h
@@ -5,13 +5,13 @@
 #ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_PERFORMANCE_MANAGER_TEST_HARNESS_H_
 #define CHROME_BROWSER_PERFORMANCE_MANAGER_PERFORMANCE_MANAGER_TEST_HARNESS_H_
 
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "content/public/browser/web_contents.h"
 
 namespace performance_manager {
 
-// A test harness that initializes PerformanceManager, plus the entire
+// A test harness that initializes PerformanceManagerImpl, plus the entire
 // RenderViewHost harness. Allows for creating full WebContents, and their
 // accompanying structures in the graph. The task environment is accessed
 // via content::RenderViewHostTestHarness::test_bundle().
@@ -31,7 +31,7 @@
   std::unique_ptr<content::WebContents> CreateTestWebContents();
 
  private:
-  std::unique_ptr<PerformanceManager> perf_man_;
+  std::unique_ptr<PerformanceManagerImpl> perf_man_;
 
   DISALLOW_COPY_AND_ASSIGN(PerformanceManagerTestHarness);
 };
diff --git a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade.cc b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade.cc
index fc16b0731..4cd71dad 100644
--- a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade.cc
+++ b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade.cc
@@ -8,7 +8,7 @@
 
 #include "base/bind.h"
 #include "base/run_loop.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 #include "chrome/browser/performance_manager/persistence/site_data/site_data_cache_factory.h"
 #include "chrome/browser/performance_manager/persistence/site_data/site_data_cache_impl.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
@@ -48,7 +48,7 @@
 void SiteDataCacheFacade::WaitUntilCacheInitializedForTesting() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   base::RunLoop run_loop;
-  PerformanceManager::GetInstance()->CallOnGraph(
+  PerformanceManagerImpl::GetInstance()->CallOnGraphImpl(
       FROM_HERE, base::BindOnce(
                      [](base::OnceClosure quit_closure,
                         const std::string& browser_context_id,
diff --git a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_unittest.cc b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_unittest.cc
index 6f153d6..ce9cb0e1 100644
--- a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_unittest.cc
+++ b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_facade_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/run_loop.h"
 #include "base/task/post_task.h"
 #include "base/test/bind_test_util.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 #include "chrome/browser/performance_manager/persistence/site_data/leveldb_site_data_store.h"
 #include "chrome/browser/performance_manager/persistence/site_data/site_data_cache_factory.h"
 #include "chrome/browser/performance_manager/persistence/site_data/unittest_utils.h"
@@ -25,7 +25,7 @@
 TEST_F(SiteDataCacheFacadeTest, IsDataCacheRecordingForTesting) {
   // Create the SiteDataCacheFactory instance and pass it to the PM sequence for
   // ownership.
-  PerformanceManager::GetInstance()->CallOnGraph(
+  PerformanceManagerImpl::GetInstance()->CallOnGraphImpl(
       FROM_HERE,
       base::BindOnce(
           [](std::unique_ptr<SiteDataCacheFactory> site_data_cache_factory,
diff --git a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_factory.cc b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_factory.cc
index 4d69bf2..5d482eda 100644
--- a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_factory.cc
+++ b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_factory.cc
@@ -10,7 +10,7 @@
 #include "base/sequenced_task_runner.h"
 #include "base/stl_util.h"
 #include "base/task_runner_util.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 #include "chrome/browser/performance_manager/persistence/site_data/non_recording_site_data_cache.h"
 #include "chrome/browser/performance_manager/persistence/site_data/site_data_cache_impl.h"
 #include "chrome/browser/performance_manager/persistence/site_data/site_data_cache_inspector.h"
@@ -55,7 +55,7 @@
     DCHECK(browser_context->IsOffTheRecord());
     parent_context_id = parent_context->UniqueId();
   }
-  PerformanceManager::GetInstance()->CallOnGraph(
+  PerformanceManagerImpl::GetInstance()->CallOnGraphImpl(
       FROM_HERE, base::BindOnce(
                      [](SiteDataCacheFactory* factory,
                         const std::string& browser_context_id,
@@ -75,7 +75,7 @@
     content::BrowserContext* browser_context) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(factory);
-  PerformanceManager::GetInstance()->CallOnGraph(
+  PerformanceManagerImpl::GetInstance()->CallOnGraphImpl(
       FROM_HERE, base::BindOnce(
                      [](SiteDataCacheFactory* factory,
                         const std::string& browser_context_id,
@@ -121,7 +121,7 @@
     const std::string& browser_context_id,
     base::OnceCallback<void(bool)> cb) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  PerformanceManager::GetInstance()->CallOnGraph(
+  PerformanceManagerImpl::GetInstance()->CallOnGraphImpl(
       FROM_HERE,
       base::BindOnce(
           [](SiteDataCacheFactory* factory,
diff --git a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_factory.h b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_factory.h
index efca2d03..a1440ed 100644
--- a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_factory.h
+++ b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_factory.h
@@ -30,7 +30,8 @@
 
 // This class is responsible for tracking the SiteDataCache instances associated
 // with each browser context. It is meant to be used as a bridge between the
-// browser contexts living on the UI thread and the PerformanceManager sequence.
+// browser contexts living on the UI thread and the PerformanceManager
+// sequence.
 //
 // This can be created on any sequence but it then should be passed to the
 // graph and used on the PerformanceManager sequence.
diff --git a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_factory_unittest.cc b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_factory_unittest.cc
index 14752b0..f23f32f 100644
--- a/chrome/browser/performance_manager/persistence/site_data/site_data_cache_factory_unittest.cc
+++ b/chrome/browser/performance_manager/persistence/site_data/site_data_cache_factory_unittest.cc
@@ -23,7 +23,7 @@
   std::unique_ptr<SiteDataCacheFactory> factory =
       std::make_unique<SiteDataCacheFactory>();
   SiteDataCacheFactory* factory_raw = factory.get();
-  PerformanceManager::GetInstance()->CallOnGraph(
+  PerformanceManagerImpl::GetInstance()->CallOnGraphImpl(
       FROM_HERE,
       base::BindOnce(
           [](std::unique_ptr<SiteDataCacheFactory> site_data_cache_factory,
@@ -38,7 +38,7 @@
 
   {
     base::RunLoop run_loop;
-    PerformanceManager::GetInstance()->CallOnGraph(
+    PerformanceManagerImpl::GetInstance()->CallOnGraphImpl(
         FROM_HERE,
         base::BindOnce(
             [](SiteDataCacheFactory* factory,
@@ -60,7 +60,7 @@
                                                             &profile);
   {
     base::RunLoop run_loop;
-    PerformanceManager::GetInstance()->CallOnGraph(
+    PerformanceManagerImpl::GetInstance()->CallOnGraphImpl(
         FROM_HERE,
         base::BindOnce(
             [](SiteDataCacheFactory* factory,
diff --git a/chrome/browser/performance_manager/persistence/site_data/unittest_utils.cc b/chrome/browser/performance_manager/persistence/site_data/unittest_utils.cc
index dd5c5ca1..6909f5c3 100644
--- a/chrome/browser/performance_manager/persistence/site_data/unittest_utils.cc
+++ b/chrome/browser/performance_manager/persistence/site_data/unittest_utils.cc
@@ -47,16 +47,16 @@
 TestWithPerformanceManager::~TestWithPerformanceManager() = default;
 
 void TestWithPerformanceManager::SetUp() {
-  EXPECT_EQ(nullptr, PerformanceManager::GetInstance());
-  performance_manager_ = PerformanceManager::Create();
+  EXPECT_EQ(nullptr, PerformanceManagerImpl::GetInstance());
+  performance_manager_ = PerformanceManagerImpl::Create();
   // Make sure creation registers the created instance.
-  EXPECT_EQ(performance_manager_.get(), PerformanceManager::GetInstance());
+  EXPECT_EQ(performance_manager_.get(), PerformanceManagerImpl::GetInstance());
 }
 
 void TestWithPerformanceManager::TearDown() {
-  PerformanceManager::Destroy(std::move(performance_manager_));
+  PerformanceManagerImpl::Destroy(std::move(performance_manager_));
   // Make sure destruction unregisters the instance.
-  EXPECT_EQ(nullptr, PerformanceManager::GetInstance());
+  EXPECT_EQ(nullptr, PerformanceManagerImpl::GetInstance());
 
   task_environment_.RunUntilIdle();
 }
diff --git a/chrome/browser/performance_manager/persistence/site_data/unittest_utils.h b/chrome/browser/performance_manager/persistence/site_data/unittest_utils.h
index 5b3b76e3..7f78fcbe 100644
--- a/chrome/browser/performance_manager/persistence/site_data/unittest_utils.h
+++ b/chrome/browser/performance_manager/persistence/site_data/unittest_utils.h
@@ -9,7 +9,7 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 #include "chrome/browser/performance_manager/persistence/site_data/site_data_impl.h"
 #include "chrome/browser/performance_manager/persistence/site_data/site_data_store.h"
 #include "content/public/test/browser_task_environment.h"
@@ -62,7 +62,7 @@
   void TearDown() override;
 
  private:
-  std::unique_ptr<PerformanceManager> performance_manager_;
+  std::unique_ptr<PerformanceManagerImpl> performance_manager_;
   content::BrowserTaskEnvironment task_environment_;
 
   DISALLOW_COPY_AND_ASSIGN(TestWithPerformanceManager);
diff --git a/chrome/browser/performance_manager/public/performance_manager.h b/chrome/browser/performance_manager/public/performance_manager.h
new file mode 100644
index 0000000..13a23e7f
--- /dev/null
+++ b/chrome/browser/performance_manager/public/performance_manager.h
@@ -0,0 +1,46 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_PUBLIC_PERFORMANCE_MANAGER_H_
+#define CHROME_BROWSER_PERFORMANCE_MANAGER_PUBLIC_PERFORMANCE_MANAGER_H_
+
+#include "base/callback.h"
+#include "base/location.h"
+
+namespace performance_manager {
+
+class Graph;
+class GraphOwned;
+
+// The performance manager is a rendezvous point for communicating with the
+// performance manager graph on its dedicated sequence.
+class PerformanceManager {
+ public:
+  // Returns true if the performance manager is initialized. Valid to call from
+  // the main thread only.
+  static bool IsAvailable();
+
+  // Posts a callback that will run on the PM sequence, and be provided a
+  // pointer to the Graph. Valid to call from the main thread only, and only
+  // if "IsAvailable" returns true.
+  using GraphCallback = base::OnceCallback<void(Graph*)>;
+  static void CallOnGraph(const base::Location& from_here,
+                          GraphCallback graph_callback);
+
+  // Passes a GraphOwned object into the Graph on the PM sequence. Should only
+  // be called from the main thread and only if "IsAvailable" returns true.
+  static void PassToGraph(const base::Location& from_here,
+                          std::unique_ptr<GraphOwned> graph_owned);
+
+ protected:
+  PerformanceManager();
+  virtual ~PerformanceManager();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PerformanceManager);
+};
+
+}  // namespace performance_manager
+
+#endif  // CHROME_BROWSER_PERFORMANCE_MANAGER_PUBLIC_PERFORMANCE_MANAGER_H_
diff --git a/chrome/browser/performance_manager/render_process_host_proxy_unittest.cc b/chrome/browser/performance_manager/render_process_host_proxy_unittest.cc
index 38bc4fe..8194b08 100644
--- a/chrome/browser/performance_manager/render_process_host_proxy_unittest.cc
+++ b/chrome/browser/performance_manager/render_process_host_proxy_unittest.cc
@@ -82,7 +82,7 @@
   // what would happen with a policy message being posted from the graph.
   {
     base::RunLoop run_loop;
-    PerformanceManager::GetInstance()->CallOnGraph(
+    PerformanceManagerImpl::GetInstance()->CallOnGraphImpl(
         FROM_HERE,
         base::BindLambdaForTesting(
             [&deref_proxy, process_node,
@@ -102,7 +102,7 @@
   // Run the same test but make sure the RPH is gone first.
   {
     base::RunLoop run_loop;
-    PerformanceManager::GetInstance()->CallOnGraph(
+    PerformanceManagerImpl::GetInstance()->CallOnGraphImpl(
         FROM_HERE,
         base::BindLambdaForTesting([&rph_factory, &deref_proxy, process_node,
                                     host, quit_loop = run_loop.QuitClosure()](
diff --git a/chrome/browser/performance_manager/render_process_user_data.cc b/chrome/browser/performance_manager/render_process_user_data.cc
index 74d2b4f..2534dbb 100644
--- a/chrome/browser/performance_manager/render_process_user_data.cc
+++ b/chrome/browser/performance_manager/render_process_user_data.cc
@@ -13,7 +13,7 @@
 #include "base/memory/ptr_util.h"
 #include "build/build_config.h"
 #include "chrome/browser/performance_manager/graph/process_node_impl.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 #include "chrome/browser/performance_manager/public/render_process_host_proxy.h"
 #include "content/public/browser/child_process_termination_info.h"
 #include "content/public/browser/render_process_host.h"
@@ -33,7 +33,7 @@
     content::RenderProcessHost* render_process_host)
     : host_(render_process_host) {
   host_->AddObserver(this);
-  process_node_ = PerformanceManager::GetInstance()->CreateProcessNode(
+  process_node_ = PerformanceManagerImpl::GetInstance()->CreateProcessNode(
       RenderProcessHostProxy(host_->GetID()));
 
   // Push this instance to the list.
@@ -45,7 +45,7 @@
 }
 
 RenderProcessUserData::~RenderProcessUserData() {
-  PerformanceManager::GetInstance()->DeleteNode(std::move(process_node_));
+  PerformanceManagerImpl::GetInstance()->DeleteNode(std::move(process_node_));
   host_->RemoveObserver(this);
 
   if (first_ == this)
@@ -89,7 +89,8 @@
 
 void RenderProcessUserData::RenderProcessReady(
     content::RenderProcessHost* host) {
-  PerformanceManager* performance_manager = PerformanceManager::GetInstance();
+  PerformanceManagerImpl* performance_manager =
+      PerformanceManagerImpl::GetInstance();
 
   const base::Time launch_time =
 #if defined(OS_ANDROID)
@@ -110,7 +111,8 @@
 void RenderProcessUserData::RenderProcessExited(
     content::RenderProcessHost* host,
     const content::ChildProcessTerminationInfo& info) {
-  PerformanceManager* performance_manager = PerformanceManager::GetInstance();
+  PerformanceManagerImpl* performance_manager =
+      PerformanceManagerImpl::GetInstance();
 
   performance_manager->task_runner()->PostTask(
       FROM_HERE,
diff --git a/chrome/browser/performance_manager/web_contents_proxy_unittest.cc b/chrome/browser/performance_manager/web_contents_proxy_unittest.cc
index 3055d68..9ca220d6 100644
--- a/chrome/browser/performance_manager/web_contents_proxy_unittest.cc
+++ b/chrome/browser/performance_manager/web_contents_proxy_unittest.cc
@@ -48,7 +48,7 @@
   // would happen with a policy message being posted from the graph.
   {
     base::RunLoop run_loop;
-    PerformanceManager::GetInstance()->CallOnGraph(
+    PerformanceManagerImpl::GetInstance()->CallOnGraphImpl(
         FROM_HERE,
         base::BindLambdaForTesting(
             [&deref_proxy, page_node,
@@ -67,7 +67,7 @@
   // dereferencing the proxy.
   {
     base::RunLoop run_loop;
-    PerformanceManager::GetInstance()->CallOnGraph(
+    PerformanceManagerImpl::GetInstance()->CallOnGraphImpl(
         FROM_HERE,
         base::BindLambdaForTesting([&contents, &deref_proxy, page_node,
                                     quit_loop = run_loop.QuitClosure()](
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 08e1422a..2424fad 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -7029,7 +7029,15 @@
 };
 
 IN_PROC_BROWSER_TEST_P(ForceNetworkInProcessTest, IsRespected) {
-  ASSERT_EQ(content::IsInProcessNetworkService(), GetParam());
+  bool expected_in_process = GetParam();
+
+  // When run with --enable-features=NetworkServiceInProcess, the Network
+  // Service will always be in process. This configuration is used on some
+  // bots - see https://crbug.com/1002752.
+  expected_in_process |=
+      base::FeatureList::IsEnabled(features::kNetworkServiceInProcess);
+
+  ASSERT_EQ(expected_in_process, content::IsInProcessNetworkService());
 }
 
 INSTANTIATE_TEST_SUITE_P(
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.cc b/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.cc
index d870f5207..15dace26 100644
--- a/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.cc
+++ b/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.cc
@@ -7,7 +7,7 @@
 #include <utility>
 
 #include "base/task/post_task.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 #include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.h"
 #include "chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer.h"
 #include "chrome/browser/resource_coordinator/tab_helper.h"
@@ -104,7 +104,7 @@
   // ChromeRenderViewHostTestHarness::SetUp(), this will prevent the creation
   // of a non-mock version of a data store when browser_context() gets
   // initialized.
-  performance_manager_ = performance_manager::PerformanceManager::Create();
+  performance_manager_ = performance_manager::PerformanceManagerImpl::Create();
 
   LocalSiteCharacteristicsDataStoreFactory::EnableForTesting();
 
@@ -116,7 +116,7 @@
 }
 
 void ChromeTestHarnessWithLocalDB::TearDown() {
-  performance_manager::PerformanceManager::Destroy(
+  performance_manager::PerformanceManagerImpl::Destroy(
       std::move(performance_manager_));
   content::SetSystemConnectorForTesting(nullptr);
   ChromeRenderViewHostTestHarness::TearDown();
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h b/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h
index 96676169..f94faf3 100644
--- a/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h
+++ b/chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h
@@ -21,7 +21,7 @@
 }
 
 namespace performance_manager {
-class PerformanceManager;
+class PerformanceManagerImpl;
 }  // namespace performance_manager
 
 namespace resource_coordinator {
@@ -99,7 +99,8 @@
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
-  std::unique_ptr<performance_manager::PerformanceManager> performance_manager_;
+  std::unique_ptr<performance_manager::PerformanceManagerImpl>
+      performance_manager_;
 };
 
 }  // namespace testing
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer.cc b/chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer.cc
index 76a4593b..fe0c19c 100644
--- a/chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer.cc
+++ b/chrome/browser/resource_coordinator/local_site_characteristics_webcontents_observer.cc
@@ -7,7 +7,7 @@
 #include "base/bind.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/threading/sequenced_task_runner_handle.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 #include "chrome/browser/performance_manager/public/graph/frame_node.h"
 #include "chrome/browser/performance_manager/public/graph/graph.h"
 #include "chrome/browser/performance_manager/public/graph/page_node.h"
@@ -72,7 +72,7 @@
         content::WebContents* web_contents)
     : content::WebContentsObserver(web_contents) {
   // May not be present in some tests.
-  if (performance_manager::PerformanceManager::IsAvailable()) {
+  if (performance_manager::PerformanceManagerImpl::IsAvailable()) {
     // The performance manager has to be enabled in order to properly track the
     // non-persistent notification events.
     TabLoadTracker::Get()->AddObserver(this);
@@ -86,8 +86,8 @@
 
 // static
 void LocalSiteCharacteristicsWebContentsObserver::MaybeCreateGraphObserver() {
-  if (performance_manager::PerformanceManager::IsAvailable()) {
-    performance_manager::PerformanceManager::PassToGraph(
+  if (performance_manager::PerformanceManagerImpl::IsAvailable()) {
+    performance_manager::PerformanceManagerImpl::PassToGraph(
         FROM_HERE, std::make_unique<GraphObserver>());
   }
 }
@@ -105,7 +105,7 @@
 
 void LocalSiteCharacteristicsWebContentsObserver::WebContentsDestroyed() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (performance_manager::PerformanceManager::IsAvailable())
+  if (performance_manager::PerformanceManagerImpl::IsAvailable())
     TabLoadTracker::Get()->RemoveObserver(this);
   writer_.reset();
   writer_origin_ = url::Origin();
@@ -229,7 +229,7 @@
 void LocalSiteCharacteristicsWebContentsObserver::
     OnNonPersistentNotificationCreated() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(performance_manager::PerformanceManager::IsAvailable());
+  DCHECK(performance_manager::PerformanceManagerImpl::IsAvailable());
 
   MaybeNotifyBackgroundFeatureUsage(
       &SiteCharacteristicsDataWriter::NotifyUsesNotificationsInBackground,
diff --git a/chrome/browser/resource_coordinator/resource_coordinator_parts.cc b/chrome/browser/resource_coordinator/resource_coordinator_parts.cc
index 29ec90bc..4d72b60f 100644
--- a/chrome/browser/resource_coordinator/resource_coordinator_parts.cc
+++ b/chrome/browser/resource_coordinator/resource_coordinator_parts.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/resource_coordinator/resource_coordinator_parts.h"
 
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 
 namespace resource_coordinator {
 
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc
index dfb3326..f62c2b85 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc
@@ -9,7 +9,7 @@
 #include "base/stl_util.h"
 #include "base/task/post_task.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 #include "chrome/browser/performance_manager/public/graph/page_node.h"
 #include "chrome/browser/performance_manager/public/web_contents_proxy.h"
 #include "chrome/browser/resource_coordinator/discard_metrics_lifecycle_unit_observer.h"
@@ -148,8 +148,8 @@
 void TabLifecycleUnitSource::Start() {
   // TODO(sebmarchand): Remove the "IsAvailable" check, or merge the TM into the
   // PM. The TM and PM must always exist together.
-  if (performance_manager::PerformanceManager::IsAvailable()) {
-    performance_manager::PerformanceManager::PassToGraph(
+  if (performance_manager::PerformanceManagerImpl::IsAvailable()) {
+    performance_manager::PerformanceManagerImpl::PassToGraph(
         FROM_HERE, std::make_unique<TabLifecycleStateObserver>());
   }
 }
diff --git a/chrome/browser/resource_coordinator/tab_manager.cc b/chrome/browser/resource_coordinator/tab_manager.cc
index b565bf0..fd23e8b 100644
--- a/chrome/browser/resource_coordinator/tab_manager.cc
+++ b/chrome/browser/resource_coordinator/tab_manager.cc
@@ -32,7 +32,7 @@
 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
 #include "chrome/browser/media/webrtc/media_stream_capture_indicator.h"
 #include "chrome/browser/memory/oom_memory_details.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/performance_manager_impl.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/resource_coordinator/background_tab_navigation_throttle.h"
 #include "chrome/browser/resource_coordinator/resource_coordinator_parts.h"
@@ -211,8 +211,8 @@
   // EQT measurements.
   // TODO(sebmarchand): Remove the "IsAvailable" check, or merge the TM into the
   // PM. The TM and PM must always exist together.
-  if (performance_manager::PerformanceManager::IsAvailable()) {
-    performance_manager::PerformanceManager::CallOnGraph(
+  if (performance_manager::PerformanceManagerImpl::IsAvailable()) {
+    performance_manager::PerformanceManagerImpl::CallOnGraphImpl(
         FROM_HERE, base::BindOnce(
                        [](std::unique_ptr<ResourceCoordinatorSignalObserver>
                               rc_signal_observer,
diff --git a/chrome/browser/resources/plugin_metadata/plugins_linux.json b/chrome/browser/resources/plugin_metadata/plugins_linux.json
index d58562d..079eca1 100644
--- a/chrome/browser/resources/plugin_metadata/plugins_linux.json
+++ b/chrome/browser/resources/plugin_metadata/plugins_linux.json
@@ -1,5 +1,5 @@
 {
-  "x-version": 41,
+  "x-version": 42,
   "adobe-flash-player": {
     "mime_types": [
       "application/futuresplash",
@@ -10,9 +10,9 @@
     ],
     "versions": [
       {
-        "version": "32.0.0.207",
+        "version": "32.0.0.255",
         "status": "up_to_date",
-        "reference": "https://helpx.adobe.com/security/products/flash-player/apsb19-30.html"
+        "reference": "https://helpx.adobe.com/security/products/flash-player/apsb19-46.html"
       }
     ],
     "lang": "en-US",
diff --git a/chrome/browser/resources/plugin_metadata/plugins_mac.json b/chrome/browser/resources/plugin_metadata/plugins_mac.json
index eb67de5..0351e90 100644
--- a/chrome/browser/resources/plugin_metadata/plugins_mac.json
+++ b/chrome/browser/resources/plugin_metadata/plugins_mac.json
@@ -1,5 +1,5 @@
 {
-  "x-version": 47,
+  "x-version": 48,
   "adobe-flash-player": {
     "mime_types": [
       "application/futuresplash",
@@ -7,9 +7,9 @@
     ],
     "versions": [
       {
-        "version": "32.0.0.207",
+        "version": "32.0.0.255",
         "status": "requires_authorization",
-        "reference": "https://helpx.adobe.com/security/products/flash-player/apsb19-30.html"
+        "reference": "https://helpx.adobe.com/security/products/flash-player/apsb19-46.html"
       }
     ],
     "lang": "en-US",
diff --git a/chrome/browser/resources/plugin_metadata/plugins_win.json b/chrome/browser/resources/plugin_metadata/plugins_win.json
index ecf05d8..5df5cac 100644
--- a/chrome/browser/resources/plugin_metadata/plugins_win.json
+++ b/chrome/browser/resources/plugin_metadata/plugins_win.json
@@ -1,5 +1,5 @@
 {
-  "x-version": 56,
+  "x-version": 57,
   "adobe-flash-player": {
     "mime_types": [
       "application/futuresplash",
@@ -7,9 +7,9 @@
     ],
     "versions": [
       {
-        "version": "32.0.0.207",
+        "version": "32.0.0.255",
         "status": "requires_authorization",
-        "reference": "https://helpx.adobe.com/security/products/flash-player/apsb19-30.html"
+        "reference": "https://helpx.adobe.com/security/products/flash-player/apsb19-46.html"
       }
     ],
     "lang": "en-US",
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html
index a2c59cb6..54207da 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html
+++ b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html
@@ -225,7 +225,8 @@
           $i18n{pluginVmPageTitle}
         </div>
       </a>
-      <cr-button id="advancedButton" aria-active-attribute="aria-expanded"
+      <cr-button id="advancedButton"
+          aria-expanded$="[[boolToString_(advancedOpened)]]"
           on-click="onAdvancedButtonToggle_">
         <span>$i18n{advancedPageTitle}</span>
         <iron-icon icon="[[arrowState_(advancedOpened)]]">
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.js b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.js
index 2299d759..36873cd 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.js
+++ b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.js
@@ -108,4 +108,13 @@
     const submenu = /** @type {IronCollapseElement} */ (this.$.advancedSubmenu);
     return submenu.opened;
   },
+
+  /**
+   * @param {boolean} bool
+   * @return {string}
+   * @private
+   */
+  boolToString_: function(bool) {
+    return bool.toString();
+  },
 });
diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.html b/chrome/browser/resources/settings/settings_menu/settings_menu.html
index 4dabc3f..0bcf848 100644
--- a/chrome/browser/resources/settings/settings_menu/settings_menu.html
+++ b/chrome/browser/resources/settings/settings_menu/settings_menu.html
@@ -176,7 +176,8 @@
         <iron-icon icon="settings:power-settings-new"></iron-icon>
         $i18n{onStartup}
       </a>
-      <cr-button id="advancedButton" aria-active-attribute="aria-expanded"
+      <cr-button id="advancedButton"
+          aria-expanded$="[[boolToString_(advancedOpened)]]"
           on-click="onAdvancedButtonToggle_"
           hidden="[[!pageVisibility.advancedSettings]]">
         <span>$i18n{advancedPageTitle}</span>
diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.js b/chrome/browser/resources/settings/settings_menu/settings_menu.js
index 38bce70..5b25b17f 100644
--- a/chrome/browser/resources/settings/settings_menu/settings_menu.js
+++ b/chrome/browser/resources/settings/settings_menu/settings_menu.js
@@ -95,4 +95,13 @@
     chrome.metricsPrivate.recordUserAction(
         'SettingsMenu_ExtensionsLinkClicked');
   },
+
+  /**
+   * @param {boolean} bool
+   * @return {string}
+   * @private
+   */
+  boolToString_: function(bool) {
+    return bool.toString();
+  },
 });
diff --git a/chrome/browser/safe_browsing/advanced_protection_status_manager.cc b/chrome/browser/safe_browsing/advanced_protection_status_manager.cc
index 830a1de..695babb 100644
--- a/chrome/browser/safe_browsing/advanced_protection_status_manager.cc
+++ b/chrome/browser/safe_browsing/advanced_protection_status_manager.cc
@@ -48,7 +48,8 @@
 
 void AdvancedProtectionStatusManager::MaybeRefreshOnStartUp() {
   // Retrieves advanced protection service status from primary account's info.
-  CoreAccountInfo core_info = identity_manager_->GetPrimaryAccountInfo();
+  CoreAccountInfo core_info =
+      identity_manager_->GetUnconsentedPrimaryAccountInfo();
   if (core_info.account_id.empty())
     return;
 
@@ -91,7 +92,7 @@
 void AdvancedProtectionStatusManager::OnExtendedAccountInfoUpdated(
     const AccountInfo& info) {
   // Ignore update if the updated account is not the primary account.
-  if (!IsPrimaryAccount(info))
+  if (!IsUnconsentedPrimaryAccount(info))
     return;
 
   if (info.is_under_advanced_protection) {
@@ -106,24 +107,22 @@
 void AdvancedProtectionStatusManager::OnExtendedAccountInfoRemoved(
     const AccountInfo& info) {
   // If user signed out primary account, cancel refresh.
-  std::string primary_account_id = GetPrimaryAccountId();
-  if (!primary_account_id.empty() && primary_account_id == info.account_id) {
+  std::string unconsented_primary_account_id = GetUnconsentedPrimaryAccountId();
+  if (!unconsented_primary_account_id.empty() &&
+      unconsented_primary_account_id == info.account_id) {
     is_under_advanced_protection_ = false;
     OnAdvancedProtectionDisabled();
   }
 }
 
-void AdvancedProtectionStatusManager::OnPrimaryAccountSet(
+void AdvancedProtectionStatusManager::OnUnconsentedPrimaryAccountChanged(
     const CoreAccountInfo& account_info) {
   // TODO(crbug.com/926204): remove IdentityManager ensures that primary account
   // always has valid refresh token when it is set.
   if (account_info.is_under_advanced_protection)
     OnAdvancedProtectionEnabled();
-}
-
-void AdvancedProtectionStatusManager::OnPrimaryAccountCleared(
-    const CoreAccountInfo& account_info) {
-  OnAdvancedProtectionDisabled();
+  else
+    OnAdvancedProtectionDisabled();
 }
 
 void AdvancedProtectionStatusManager::OnAdvancedProtectionEnabled() {
@@ -170,8 +169,8 @@
 void AdvancedProtectionStatusManager::RefreshAdvancedProtectionStatus() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  std::string primary_account_id = GetPrimaryAccountId();
-  if (!identity_manager_ || primary_account_id.empty())
+  std::string unconsented_primary_account_id = GetUnconsentedPrimaryAccountId();
+  if (!identity_manager_ || unconsented_primary_account_id.empty())
     return;
 
   // If there's already a request going on, do nothing.
@@ -187,7 +186,7 @@
           "advanced_protection_status_manager", identity_manager_, scopes,
           base::BindOnce(
               &AdvancedProtectionStatusManager::OnAccessTokenFetchComplete,
-              base::Unretained(this), primary_account_id),
+              base::Unretained(this), unconsented_primary_account_id),
           signin::PrimaryAccountAccessTokenFetcher::Mode::kImmediate);
 }
 
@@ -224,10 +223,10 @@
   return force_enabled || is_under_advanced_protection();
 }
 
-bool AdvancedProtectionStatusManager::IsPrimaryAccount(
+bool AdvancedProtectionStatusManager::IsUnconsentedPrimaryAccount(
     const CoreAccountInfo& account_info) {
   return !account_info.account_id.empty() &&
-         account_info.account_id == GetPrimaryAccountId();
+         account_info.account_id == GetUnconsentedPrimaryAccountId();
 }
 
 void AdvancedProtectionStatusManager::OnGetIDToken(
@@ -235,8 +234,9 @@
     const std::string& id_token) {
   // Skips if the ID token is not for the primary account. Or user is no longer
   // signed in.
-  std::string primary_account_id = GetPrimaryAccountId();
-  if (primary_account_id.empty() || account_id != primary_account_id)
+  std::string unconsented_primary_account_id = GetUnconsentedPrimaryAccountId();
+  if (unconsented_primary_account_id.empty() ||
+      account_id != unconsented_primary_account_id)
     return;
 
   gaia::TokenServiceFlags service_flags = gaia::ParseServiceFlags(id_token);
@@ -246,7 +246,7 @@
   if (is_under_advanced_protection_ !=
       service_flags.is_under_advanced_protection) {
     identity_manager_->GetAccountsMutator()->UpdateAccountInfo(
-        GetPrimaryAccountId(), false,
+        GetUnconsentedPrimaryAccountId(), false,
         service_flags.is_under_advanced_protection);
   } else if (service_flags.is_under_advanced_protection) {
     OnAdvancedProtectionEnabled();
@@ -270,11 +270,13 @@
   MaybeRefreshOnStartUp();
 }
 
-std::string AdvancedProtectionStatusManager::GetPrimaryAccountId() const {
+std::string AdvancedProtectionStatusManager::GetUnconsentedPrimaryAccountId()
+    const {
   // TODO(triploblastic@): Remove explicit conversion once
   // AdvancedProtectionStatusManager has been fixed to use CoreAccountId.
-  return identity_manager_ ? identity_manager_->GetPrimaryAccountId().id
-                           : std::string();
+  return identity_manager_
+             ? identity_manager_->GetUnconsentedPrimaryAccountId().id
+             : std::string();
 }
 
 }  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/advanced_protection_status_manager.h b/chrome/browser/safe_browsing/advanced_protection_status_manager.h
index 0ce554a..021a909 100644
--- a/chrome/browser/safe_browsing/advanced_protection_status_manager.h
+++ b/chrome/browser/safe_browsing/advanced_protection_status_manager.h
@@ -71,6 +71,8 @@
                            AdvancedProtectionDisabledAfterSignin);
   FRIEND_TEST_ALL_PREFIXES(AdvancedProtectionStatusManagerTest,
                            StartupAfterLongWaitRefreshesImmediately);
+  FRIEND_TEST_ALL_PREFIXES(AdvancedProtectionStatusManagerTest,
+                           TracksUnconsentedPrimaryAccount);
 
   void Initialize();
 
@@ -85,8 +87,8 @@
   void UnsubscribeFromSigninEvents();
 
   // IdentityManager::Observer implementations.
-  void OnPrimaryAccountSet(const CoreAccountInfo& account_info) override;
-  void OnPrimaryAccountCleared(const CoreAccountInfo& account_info) override;
+  void OnUnconsentedPrimaryAccountChanged(
+      const CoreAccountInfo& account_info) override;
   void OnExtendedAccountInfoUpdated(const AccountInfo& info) override;
   void OnExtendedAccountInfoRemoved(const AccountInfo& info) override;
 
@@ -110,7 +112,7 @@
   // Sets |last_refresh_| to now and persists it.
   void UpdateLastRefreshTime();
 
-  bool IsPrimaryAccount(const CoreAccountInfo& account_info);
+  bool IsUnconsentedPrimaryAccount(const CoreAccountInfo& account_info);
 
   // Decodes |id_token| to get advanced protection status.
   void OnGetIDToken(const std::string& account_id, const std::string& id_token);
@@ -118,9 +120,9 @@
   // Only called in tests.
   void SetMinimumRefreshDelay(const base::TimeDelta& delay);
 
-  // Gets the account ID of the primary account of |profile_|.
+  // Gets the account ID of the unconsented primary account of |profile_|.
   // Returns an empty string if user is not signed in.
-  std::string GetPrimaryAccountId() const;
+  std::string GetUnconsentedPrimaryAccountId() const;
 
   // Only called in tests to set a customized minimum delay.
   AdvancedProtectionStatusManager(PrefService* pref_service,
diff --git a/chrome/browser/safe_browsing/advanced_protection_status_manager_unittest.cc b/chrome/browser/safe_browsing/advanced_protection_status_manager_unittest.cc
index a338843..d096177 100644
--- a/chrome/browser/safe_browsing/advanced_protection_status_manager_unittest.cc
+++ b/chrome/browser/safe_browsing/advanced_protection_status_manager_unittest.cc
@@ -93,7 +93,7 @@
   AdvancedProtectionStatusManager aps_manager(
       &pref_service_, identity_test_env_.identity_manager(),
       base::TimeDelta() /*no min delay*/);
-  ASSERT_TRUE(aps_manager.GetPrimaryAccountId().empty());
+  ASSERT_TRUE(aps_manager.GetUnconsentedPrimaryAccountId().empty());
 
   // If user's not signed-in. No refresh is required.
   EXPECT_FALSE(aps_manager.is_under_advanced_protection());
@@ -117,7 +117,7 @@
       &pref_service_, identity_test_env_.identity_manager(),
       base::TimeDelta() /*no min delay*/);
   base::RunLoop().RunUntilIdle();
-  ASSERT_FALSE(aps_manager.GetPrimaryAccountId().empty());
+  ASSERT_FALSE(aps_manager.GetUnconsentedPrimaryAccountId().empty());
 
   // Waits for access token request and respond with an error without advanced
   // protection set.
@@ -148,7 +148,7 @@
       &pref_service_, identity_test_env_.identity_manager(),
       base::TimeDelta() /*no min delay*/);
   base::RunLoop().RunUntilIdle();
-  ASSERT_FALSE(aps_manager.GetPrimaryAccountId().empty());
+  ASSERT_FALSE(aps_manager.GetUnconsentedPrimaryAccountId().empty());
 
   // Waits for access token request and respond with an error without advanced
   // protection set.
@@ -178,7 +178,7 @@
   AdvancedProtectionStatusManager aps_manager(
       &pref_service_, identity_test_env_.identity_manager(),
       base::TimeDelta() /*no min delay*/);
-  ASSERT_FALSE(aps_manager.GetPrimaryAccountId().empty());
+  ASSERT_FALSE(aps_manager.GetUnconsentedPrimaryAccountId().empty());
   base::RunLoop().RunUntilIdle();
   // Waits for access token request and respond with a token without advanced
   // protection set.
@@ -231,7 +231,7 @@
   AdvancedProtectionStatusManager aps_manager(
       &pref_service_, identity_test_env_.identity_manager(),
       base::TimeDelta() /*no min delay*/);
-  ASSERT_FALSE(aps_manager.GetPrimaryAccountId().empty());
+  ASSERT_FALSE(aps_manager.GetUnconsentedPrimaryAccountId().empty());
   ASSERT_TRUE(aps_manager.is_under_advanced_protection());
 
   // A refresh is scheduled in the future.
@@ -269,7 +269,7 @@
   AdvancedProtectionStatusManager aps_manager(
       &pref_service_, identity_test_env_.identity_manager(),
       base::TimeDelta() /*no min delay*/);
-  ASSERT_FALSE(aps_manager.GetPrimaryAccountId().empty());
+  ASSERT_FALSE(aps_manager.GetUnconsentedPrimaryAccountId().empty());
   ASSERT_TRUE(aps_manager.is_under_advanced_protection());
 
   // Simulate gets refresh token.
@@ -289,7 +289,7 @@
       &pref_service_, identity_test_env_.identity_manager(),
       base::TimeDelta() /*no min delay*/);
   ASSERT_FALSE(aps_manager.is_under_advanced_protection());
-  ASSERT_TRUE(aps_manager.GetPrimaryAccountId().empty());
+  ASSERT_TRUE(aps_manager.GetUnconsentedPrimaryAccountId().empty());
 
   SignIn("test@test.com",
          /* is_under_advanced_protection = */ true);
@@ -310,7 +310,7 @@
       &pref_service_, identity_test_env_.identity_manager(),
       base::TimeDelta() /*no min delay*/);
   ASSERT_FALSE(aps_manager.is_under_advanced_protection());
-  ASSERT_TRUE(aps_manager.GetPrimaryAccountId().empty());
+  ASSERT_TRUE(aps_manager.GetUnconsentedPrimaryAccountId().empty());
 
   std::string account_id = SignIn("test@test.com",
                                   /* is_under_advanced_protection = */ false);
@@ -381,7 +381,7 @@
   AdvancedProtectionStatusManager aps_manager(
       &pref_service_, identity_test_env_.identity_manager(),
       base::TimeDelta() /*no min delay*/);
-  ASSERT_FALSE(aps_manager.GetPrimaryAccountId().empty());
+  ASSERT_FALSE(aps_manager.GetUnconsentedPrimaryAccountId().empty());
   ASSERT_TRUE(aps_manager.is_under_advanced_protection());
   EXPECT_TRUE(aps_manager.IsRefreshScheduled());
 
@@ -394,4 +394,29 @@
   aps_manager.UnsubscribeFromSigninEvents();
 }
 
+// On ChromeOS, there is no unconsented primary account. We can only track the
+// primary account.
+#if !defined(OS_CHROMEOS)
+TEST_F(AdvancedProtectionStatusManagerTest, TracksUnconsentedPrimaryAccount) {
+  AdvancedProtectionStatusManager aps_manager(
+      &pref_service_, identity_test_env_.identity_manager(),
+      base::TimeDelta() /*no min delay*/);
+  ASSERT_FALSE(aps_manager.is_under_advanced_protection());
+  ASSERT_TRUE(aps_manager.GetUnconsentedPrimaryAccountId().empty());
+
+  // Sign in, but don't set this as the primary account.
+  AccountInfo account_info =
+      identity_test_env_.MakeAccountAvailable("test@test.com");
+  account_info.is_under_advanced_protection = true;
+  identity_test_env_.SetCookieAccounts(
+      {{account_info.email, account_info.gaia}});
+  identity_test_env_.UpdateAccountInfoForAccount(account_info);
+
+  EXPECT_TRUE(aps_manager.is_under_advanced_protection());
+  EXPECT_TRUE(aps_manager.IsRefreshScheduled());
+
+  aps_manager.UnsubscribeFromSigninEvents();
+}
+#endif
+
 }  // namespace safe_browsing
diff --git a/chrome/browser/send_tab_to_self/OWNERS b/chrome/browser/send_tab_to_self/OWNERS
index 59b3396..e58f618d 100644
--- a/chrome/browser/send_tab_to_self/OWNERS
+++ b/chrome/browser/send_tab_to_self/OWNERS
@@ -1,3 +1,3 @@
- file://components/send_tab_to_self/OWNERS
+file://components/send_tab_to_self/OWNERS
 
 # COMPONENT: UI>Browser>Sharing
diff --git a/chrome/browser/shell_integration_win.cc b/chrome/browser/shell_integration_win.cc
index f62c756..9b05880 100644
--- a/chrome/browser/shell_integration_win.cc
+++ b/chrome/browser/shell_integration_win.cc
@@ -43,6 +43,7 @@
 #include "chrome/browser/policy/policy_path_parser.h"
 #include "chrome/browser/shell_integration.h"
 #include "chrome/browser/web_applications/components/web_app_helpers.h"
+#include "chrome/browser/web_applications/components/web_app_shortcut_win.h"
 #include "chrome/browser/win/settings_app_monitor.h"
 #include "chrome/browser/win/util_win_service.h"
 #include "chrome/common/chrome_constants.h"
@@ -68,16 +69,6 @@
   if (profile_path.empty())
     return base::string16();
 
-  base::FilePath default_user_data_dir;
-  // Return empty string if profile_path is in default user data
-  // dir and is the default profile.
-  if (chrome::GetDefaultUserDataDirectory(&default_user_data_dir) &&
-      profile_path.DirName() == default_user_data_dir &&
-      profile_path.BaseName().value() ==
-          base::ASCIIToUTF16(chrome::kInitialProfile)) {
-    return base::string16();
-  }
-
   // Get joined basenames of user data dir and profile.
   base::string16 basenames = profile_path.DirName().BaseName().value() +
       L"." + profile_path.BaseName().value();
@@ -144,21 +135,6 @@
   return win::GetAppModelIdForProfile(app_name, profile_path);
 }
 
-void MigrateTaskbarPinsCallback() {
-  // Get full path of chrome.
-  base::FilePath chrome_exe;
-  if (!base::PathService::Get(base::FILE_EXE, &chrome_exe))
-    return;
-
-  base::FilePath pins_path;
-  if (!base::PathService::Get(base::DIR_TASKBAR_PINS, &pins_path)) {
-    NOTREACHED();
-    return;
-  }
-
-  win::MigrateShortcutsInPathInternal(chrome_exe, pins_path);
-}
-
 // Windows treats a given scheme as an Internet scheme only if its registry
 // entry has a "URL Protocol" key. Check this, otherwise we allow ProgIDs to be
 // used as custom protocols which leads to security bugs.
@@ -724,9 +700,28 @@
   // This needs to happen (e.g. so that the appid is fixed and the
   // run-time Chrome icon is merged with the taskbar shortcut), but it is not an
   // urgent task.
+  base::FilePath pins_path;
+  if (!base::PathService::Get(base::DIR_TASKBAR_PINS, &pins_path)) {
+    NOTREACHED();
+    return;
+  }
+
   base::CreateCOMSTATaskRunner(
       {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT})
-      ->PostTask(FROM_HERE, base::BindOnce(&MigrateTaskbarPinsCallback));
+      ->PostTask(FROM_HERE,
+                 base::BindOnce(&MigrateTaskbarPinsCallback, pins_path));
+}
+
+void MigrateTaskbarPinsCallback(const base::FilePath& pins_path) {
+  // Get full path of chrome.
+  base::FilePath chrome_exe;
+  if (!base::PathService::Get(base::FILE_EXE, &chrome_exe))
+    return;
+
+  win::MigrateShortcutsInPathInternal(chrome_exe, pins_path);
+
+  // Migrate any pinned PWA shortcuts.
+  win::MigrateShortcutsInPathInternal(web_app::GetChromeProxyPath(), pins_path);
 }
 
 void GetIsPinnedToTaskbarState(
@@ -785,6 +780,8 @@
     // |updated_properties|.
     base::win::ShortcutProperties updated_properties;
 
+    base::string16 current_app_id;
+
     // Validate the existing app id for the shortcut.
     Microsoft::WRL::ComPtr<IPropertyStore> property_store;
     propvariant.Reset();
@@ -802,7 +799,8 @@
             updated_properties.set_app_id(expected_app_id);
           break;
         case VT_LPWSTR:
-          if (expected_app_id != base::string16(propvariant.get().pwszVal))
+          current_app_id = base::string16(propvariant.get().pwszVal);
+          if (expected_app_id != current_app_id)
             updated_properties.set_app_id(expected_app_id);
           break;
         default:
@@ -816,7 +814,7 @@
     // |default_chromium_model_id|).
     base::string16 default_chromium_model_id(
         ShellUtil::GetBrowserModelId(is_per_user_install));
-    if (expected_app_id == default_chromium_model_id) {
+    if (current_app_id == default_chromium_model_id) {
       propvariant.Reset();
       if (property_store->GetValue(PKEY_AppUserModel_IsDualMode,
                                    propvariant.Receive()) != S_OK) {
diff --git a/chrome/browser/shell_integration_win.h b/chrome/browser/shell_integration_win.h
index 294ae248..3eb29a0 100644
--- a/chrome/browser/shell_integration_win.h
+++ b/chrome/browser/shell_integration_win.h
@@ -70,9 +70,12 @@
     const IsPinnedToTaskbarCallback& result_callback);
 
 // Migrates existing chrome taskbar pins by tagging them with correct app id.
-// see http://crbug.com/28104
+// see http://crbug.com/28104. Migrates taskbar pins via a task.
 void MigrateTaskbarPins();
 
+// Callback for MigrateTaskbarPins(). Exposed for testing.
+void MigrateTaskbarPinsCallback(const base::FilePath& pins_path);
+
 // Migrates all shortcuts in |path| which point to |chrome_exe| such that they
 // have the appropriate AppUserModelId. Also clears the legacy dual_mode
 // property from shortcuts with the default chrome app id.
diff --git a/chrome/browser/shell_integration_win_unittest.cc b/chrome/browser/shell_integration_win_unittest.cc
index c157b168..df47071 100644
--- a/chrome/browser/shell_integration_win_unittest.cc
+++ b/chrome/browser/shell_integration_win_unittest.cc
@@ -18,6 +18,7 @@
 #include "base/test/test_shortcut_win.h"
 #include "base/win/scoped_com_initializer.h"
 #include "chrome/browser/web_applications/components/web_app_helpers.h"
+#include "chrome/browser/web_applications/components/web_app_shortcut_win.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths_internal.h"
 #include "chrome/install_static/install_util.h"
@@ -65,6 +66,9 @@
     non_default_user_data_dir_and_profile_chrome_app_id_ =
         GetChromiumModelIdForProfile(
             non_default_user_data_dir_.Append(non_default_profile_));
+    default_profile_ = L"Default";
+    default_profile_chrome_app_id_ = GetChromiumModelIdForProfile(
+        default_user_data_dir.Append(default_profile_));
 
     extension_id_ = L"chromiumexampleappidforunittests";
     base::string16 app_name =
@@ -73,8 +77,6 @@
     extension_app_id_ = GetAppModelIdForProfile(app_name, default_profile_path);
     non_default_profile_extension_app_id_ = GetAppModelIdForProfile(
         app_name, default_user_data_dir.Append(non_default_profile_));
-
-    CreateShortcuts();
   }
 
   // Creates a test shortcut corresponding to |shortcut_properties| and resets
@@ -116,13 +118,13 @@
     // Shortcut 2 points to chrome.exe, but already has the right appid and thus
     // should only be migrated if dual_mode is desired.
     temp_properties.set_target(chrome_exe_);
-    temp_properties.set_app_id(chrome_app_id_);
+    temp_properties.set_app_id(default_profile_chrome_app_id_);
     ASSERT_NO_FATAL_FAILURE(
         AddTestShortcutAndResetProperties(&temp_properties));
 
     // Shortcut 3 is like shortcut 1, but it's appid is a prefix of the expected
     // appid instead of being totally different.
-    base::string16 chrome_app_id_is_prefix(chrome_app_id_);
+    base::string16 chrome_app_id_is_prefix(default_profile_chrome_app_id_);
     chrome_app_id_is_prefix.push_back(L'1');
     temp_properties.set_target(chrome_exe_);
     temp_properties.set_app_id(chrome_app_id_is_prefix);
@@ -131,7 +133,8 @@
 
     // Shortcut 4 is like shortcut 1, but it's appid is of the same size as the
     // expected appid.
-    base::string16 same_size_as_chrome_app_id(chrome_app_id_.size(), L'1');
+    base::string16 same_size_as_chrome_app_id(
+        default_profile_chrome_app_id_.size(), L'1');
     temp_properties.set_target(chrome_exe_);
     temp_properties.set_app_id(same_size_as_chrome_app_id);
     ASSERT_NO_FATAL_FAILURE(
@@ -191,9 +194,9 @@
     ASSERT_NO_FATAL_FAILURE(
         AddTestShortcutAndResetProperties(&temp_properties));
 
-    // Shortcut 11 points to chrome.exe, already has the right appid, and has
-    // dual_mode set and thus should only be migrated if dual_mode is being
-    // cleared.
+    // Shortcut 11 points to chrome.exe, has the chrome appid, and has
+    // dual_mode set and thus should be migrated to the
+    // default_profile_chrome_app_id, and dual_mode should be cleared.
     temp_properties.set_target(chrome_exe_);
     temp_properties.set_app_id(chrome_app_id_);
     temp_properties.set_dual_mode(true);
@@ -224,6 +227,12 @@
   // Chrome's AppUserModelId.
   base::string16 chrome_app_id_;
 
+  // Chrome's AppUserModelId for the default profile.
+  base::string16 default_profile_chrome_app_id_;
+
+  // The Default profile.
+  base::string16 default_profile_;
+
   // A profile that isn't the Default profile.
   base::string16 non_default_profile_;
 
@@ -256,22 +265,26 @@
 }  // namespace
 
 TEST_F(ShellIntegrationWinMigrateShortcutTest, ClearDualModeAndAdjustAppIds) {
-  // 9 shortcuts should have their app id updated below and shortcut 11 should
-  // be migrated away from dual_mode for a total of 10 shortcuts migrated.
-  EXPECT_EQ(10,
+  CreateShortcuts();
+  // 11 shortcuts should have their app id updated below including shortcut 11,
+  // which should also be migrated away from dual_mode.
+  EXPECT_EQ(11,
             MigrateShortcutsInPathInternal(chrome_exe_, temp_dir_.GetPath()));
 
-  // Shortcut 1, 3, 4, 5, 6, 7, 8, 9, and 10 should have had their app_id fixed.
-  shortcuts_[1].properties.set_app_id(chrome_app_id_);
-  shortcuts_[3].properties.set_app_id(chrome_app_id_);
-  shortcuts_[4].properties.set_app_id(chrome_app_id_);
-  shortcuts_[5].properties.set_app_id(chrome_app_id_);
+  // Shortcut 1, 3, 4, 5, 6, 7, 8, 9, 10, 11 and 12 should have had their app_id
+  // fixed.
+  shortcuts_[1].properties.set_app_id(default_profile_chrome_app_id_);
+  shortcuts_[3].properties.set_app_id(default_profile_chrome_app_id_);
+  shortcuts_[4].properties.set_app_id(default_profile_chrome_app_id_);
+  shortcuts_[5].properties.set_app_id(default_profile_chrome_app_id_);
   shortcuts_[6].properties.set_app_id(non_default_profile_chrome_app_id_);
   shortcuts_[7].properties.set_app_id(non_default_user_data_dir_chrome_app_id_);
   shortcuts_[8].properties.set_app_id(
       non_default_user_data_dir_and_profile_chrome_app_id_);
   shortcuts_[9].properties.set_app_id(extension_app_id_);
   shortcuts_[10].properties.set_app_id(non_default_profile_extension_app_id_);
+  shortcuts_[11].properties.set_app_id(default_profile_chrome_app_id_);
+  shortcuts_[12].properties.set_app_id(default_profile_chrome_app_id_);
 
   // No shortcut should still have the dual_mode property.
   for (size_t i = 0; i < shortcuts_.size(); ++i)
@@ -287,6 +300,24 @@
             MigrateShortcutsInPathInternal(chrome_exe_, temp_dir_.GetPath()));
 }
 
+// Test that a chrome_proxy.exe shortcut (PWA) has its app_id migrated
+// to include the default profile name.
+TEST_F(ShellIntegrationWinMigrateShortcutTest, MigrateChromeProxyTest) {
+  // Create shortcut to chrome_proxy_exe in executable directory,
+  // using the default profile, with the AppModelId not containing the
+  // profile name. "chrome_proxy.exe" won't exist, but it appears that
+  // creating the shortcut succeeds.
+  base::win::ShortcutProperties temp_properties;
+  temp_properties.set_target(web_app::GetChromeProxyPath());
+  temp_properties.set_app_id(L"Dumbo");
+  ASSERT_NO_FATAL_FAILURE(AddTestShortcutAndResetProperties(&temp_properties));
+
+  MigrateTaskbarPinsCallback(temp_dir_.GetPath());
+  // Verify that the migrated shortcut now contains the default profile name.
+  shortcuts_[0].properties.set_app_id(default_profile_chrome_app_id_);
+  base::win::ValidateShortcut(shortcuts_[0].path, shortcuts_[0].properties);
+}
+
 TEST(ShellIntegrationWinTest, GetAppModelIdForProfileTest) {
   const base::string16 base_app_id(install_static::GetBaseAppId());
 
@@ -294,12 +325,13 @@
   base::FilePath empty_path;
   EXPECT_EQ(base_app_id, GetAppModelIdForProfile(base_app_id, empty_path));
 
-  // Default profile path should get chrome::kBrowserAppID
+  // Default profile path should get chrome::kBrowserAppID joined with
+  // profile info.
   base::FilePath default_user_data_dir;
   chrome::GetDefaultUserDataDirectory(&default_user_data_dir);
   base::FilePath default_profile_path =
       default_user_data_dir.AppendASCII(chrome::kInitialProfile);
-  EXPECT_EQ(base_app_id,
+  EXPECT_EQ(base_app_id + L".UserData.Default",
             GetAppModelIdForProfile(base_app_id, default_profile_path));
 
   // Non-default profile path should get chrome::kBrowserAppID joined with
diff --git a/chrome/browser/sync/profile_sync_service_android.cc b/chrome/browser/sync/profile_sync_service_android.cc
index ed69b099..6ea3241d6 100644
--- a/chrome/browser/sync/profile_sync_service_android.cc
+++ b/chrome/browser/sync/profile_sync_service_android.cc
@@ -207,9 +207,11 @@
 
 void ProfileSyncServiceAndroid::SetFirstSetupComplete(
     JNIEnv* env,
-    const JavaParamRef<jobject>& obj) {
+    const JavaParamRef<jobject>& obj,
+    jint source) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  sync_service_->GetUserSettings()->SetFirstSetupComplete();
+  sync_service_->GetUserSettings()->SetFirstSetupComplete(
+      static_cast<syncer::SyncFirstSetupCompleteSource>(source));
 }
 
 ScopedJavaLocalRef<jintArray> ProfileSyncServiceAndroid::GetActiveDataTypes(
diff --git a/chrome/browser/sync/profile_sync_service_android.h b/chrome/browser/sync/profile_sync_service_android.h
index d3a70fff..b322c88 100644
--- a/chrome/browser/sync/profile_sync_service_android.h
+++ b/chrome/browser/sync/profile_sync_service_android.h
@@ -61,7 +61,8 @@
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj);
   void SetFirstSetupComplete(JNIEnv* env,
-                             const base::android::JavaParamRef<jobject>& obj);
+                             const base::android::JavaParamRef<jobject>& obj,
+                             jint source);
   base::android::ScopedJavaLocalRef<jintArray> GetActiveDataTypes(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj);
diff --git a/chrome/browser/sync/test/integration/profile_sync_service_harness.cc b/chrome/browser/sync/test/integration/profile_sync_service_harness.cc
index d5c531e..7d2e1cd 100644
--- a/chrome/browser/sync/test/integration/profile_sync_service_harness.cc
+++ b/chrome/browser/sync/test/integration/profile_sync_service_harness.cc
@@ -299,7 +299,8 @@
 
 void ProfileSyncServiceHarness::FinishSyncSetup() {
   sync_blocker_.reset();
-  service()->GetUserSettings()->SetFirstSetupComplete();
+  service()->GetUserSettings()->SetFirstSetupComplete(
+      syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
 }
 
 void ProfileSyncServiceHarness::StopSyncServiceAndClearData() {
@@ -332,7 +333,8 @@
   DVLOG(1) << "Passphrase decryption success.";
 
   blocker.reset();
-  service()->GetUserSettings()->SetFirstSetupComplete();
+  service()->GetUserSettings()->SetFirstSetupComplete(
+      syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
 
   if (!AwaitSyncSetupCompletion()) {
     LOG(FATAL) << "AwaitSyncSetupCompletion failed.";
diff --git a/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc b/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc
index a06927c..f781c80 100644
--- a/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc
@@ -37,6 +37,9 @@
 using testing::ElementsAre;
 using testing::IsEmpty;
 
+const syncer::SyncFirstSetupCompleteSource kSetSourceFromTest =
+    syncer::SyncFirstSetupCompleteSource::BASIC_FLOW;
+
 syncer::KeyParams KeystoreKeyParams(const std::string& key) {
   // Due to mis-encode of keystore keys to base64 we have to always encode such
   // keys to provide backward compatibility.
@@ -402,7 +405,8 @@
   // Sign in and enable Sync.
   ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount());
   GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
-  GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete();
+  GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete(
+      kSetSourceFromTest);
   ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive());
 
   ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureEnabled());
@@ -493,7 +497,8 @@
   // Sign in and enable Sync.
   ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount());
   GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
-  GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete();
+  GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete(
+      kSetSourceFromTest);
   ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
 
   ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureEnabled());
@@ -569,7 +574,8 @@
 
   // Turn on Sync-the-feature.
   GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
-  GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete();
+  GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete(
+      kSetSourceFromTest);
   ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
   ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureEnabled());
 
@@ -617,7 +623,8 @@
   // Make the account primary and turn on Sync-the-feature.
   secondary_account_helper::MakeAccountPrimary(GetProfile(0), "user@email.com");
   GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
-  GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete();
+  GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete(
+      kSetSourceFromTest);
   ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
   ASSERT_TRUE(GetSyncService(0)->IsSyncFeatureEnabled());
 
diff --git a/chrome/browser/sync/test/integration/single_client_secondary_account_sync_test.cc b/chrome/browser/sync/test/integration/single_client_secondary_account_sync_test.cc
index 46a4d284..471b034 100644
--- a/chrome/browser/sync/test/integration/single_client_secondary_account_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_secondary_account_sync_test.cc
@@ -141,7 +141,8 @@
   // set first-time setup to complete.
   secondary_account_helper::MakeAccountPrimary(profile(), "user@email.com");
   GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
-  GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete();
+  GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete(
+      syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
 
   EXPECT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
   EXPECT_EQ(syncer::SyncService::TransportState::ACTIVE,
diff --git a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
index af3b8535..005e41f 100644
--- a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
@@ -81,6 +81,8 @@
 const char kLocalGuidA[] = "EDC609ED-7EEE-4F27-B00C-423242A9C44A";
 const char kDifferentBillingAddressId[] = "another address entity ID";
 const base::Time kArbitraryDefaultTime = base::Time::FromDoubleT(25);
+const syncer::SyncFirstSetupCompleteSource kSetSourceFromTest =
+    syncer::SyncFirstSetupCompleteSource::BASIC_FLOW;
 
 template <class T>
 class AutofillWebDataServiceConsumer : public WebDataServiceConsumer {
@@ -401,7 +403,8 @@
   GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
   // StopAndClear() also clears the "first setup complete" flag, so set it
   // again.
-  GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete();
+  GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete(
+      kSetSourceFromTest);
   // Wait until Sync restores the card and it arrives at PDM.
   WaitForNumberOfCards(pdm, 1);
 
@@ -1261,7 +1264,8 @@
   // set first-time setup to complete.
   secondary_account_helper::MakeAccountPrimary(profile(), "user@email.com");
   GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
-  GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete();
+  GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete(
+      kSetSourceFromTest);
 
   // Wait for Sync to get reconfigured into feature mode.
   ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
@@ -1333,7 +1337,8 @@
   ASSERT_EQ(syncer::SyncService::TransportState::CONFIGURING,
             GetSyncService(0)->GetTransportState());
 
-  GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete();
+  GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete(
+      kSetSourceFromTest);
 
   // Wait for Sync to get reconfigured into feature mode.
   ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
@@ -1466,7 +1471,8 @@
 
   // STEP 5. Turn Sync-the-feature on again.
   GetSyncService(0)->GetUserSettings()->SetSyncRequested(true);
-  GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete();
+  GetSyncService(0)->GetUserSettings()->SetFirstSetupComplete(
+      kSetSourceFromTest);
 
   // Wait for Sync to get reconfigured into full feature mode again.
   ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion());
diff --git a/chrome/browser/ui/android/passwords/onboarding_dialog_view.cc b/chrome/browser/ui/android/passwords/onboarding_dialog_view.cc
index c930aef..28a631f 100644
--- a/chrome/browser/ui/android/passwords/onboarding_dialog_view.cc
+++ b/chrome/browser/ui/android/passwords/onboarding_dialog_view.cc
@@ -63,7 +63,10 @@
 OnboardingDialogView::OnboardingDialogView(
     ChromePasswordManagerClient* client,
     std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save)
-    : form_to_save_(std::move(form_to_save)), client_(client) {}
+    : form_to_save_(std::move(form_to_save)),
+      client_(client),
+      saving_flow_recorder_(
+          std::make_unique<password_manager::SavingFlowMetricsRecorder>()) {}
 
 OnboardingDialogView::~OnboardingDialogView() {
   Java_OnboardingDialogBridge_destroy(base::android::AttachCurrentThread(),
@@ -90,18 +93,24 @@
       password_manager::prefs::kPasswordManagerOnboardingState,
       static_cast<int>(
           password_manager::metrics_util::OnboardingState::kShown));
+
+  saving_flow_recorder_->SetOnboardingShown();
 }
 
 void OnboardingDialogView::DismissWithReasonAndDelete(
     password_manager::metrics_util::OnboardingUIDismissalReason reason) {
   password_manager::metrics_util::LogOnboardingUIDismissalReason(reason);
+  if (saving_flow_recorder_) {
+    saving_flow_recorder_->SetFlowResult(reason);
+  }
   delete this;
 }
 
 void OnboardingDialogView::OnboardingAccepted(
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& obj) {
-  client_->OnOnboardingSuccessful(std::move(form_to_save_));
+  client_->OnOnboardingSuccessful(std::move(form_to_save_),
+                                  std::move(saving_flow_recorder_));
   DismissWithReasonAndDelete(
       password_manager::metrics_util::OnboardingUIDismissalReason::kAccepted);
 }
diff --git a/chrome/browser/ui/android/passwords/onboarding_dialog_view.h b/chrome/browser/ui/android/passwords/onboarding_dialog_view.h
index b943a80..fca281c 100644
--- a/chrome/browser/ui/android/passwords/onboarding_dialog_view.h
+++ b/chrome/browser/ui/android/passwords/onboarding_dialog_view.h
@@ -9,6 +9,7 @@
 
 #include "base/android/scoped_java_ref.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
+#include "components/password_manager/core/browser/password_manager_onboarding.h"
 
 class ChromePasswordManagerClient;
 
@@ -63,6 +64,9 @@
   // retrieving web_contents and setting prefs.
   ChromePasswordManagerClient* client_;
 
+  std::unique_ptr<password_manager::SavingFlowMetricsRecorder>
+      saving_flow_recorder_;
+
   DISALLOW_COPY_AND_ASSIGN(OnboardingDialogView);
 };
 
diff --git a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
index fcfa96b..64f8b3b 100644
--- a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
+++ b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.cc
@@ -129,9 +129,8 @@
 BrowserShortcutLauncherItemController::BrowserShortcutLauncherItemController(
     ash::ShelfModel* shelf_model)
     : ash::ShelfItemDelegate(ash::ShelfID(extension_misc::kChromeAppId)),
-      shelf_model_(shelf_model),
-      browser_list_observer_(this) {
-  browser_list_observer_.Add(BrowserList::GetInstance());
+      shelf_model_(shelf_model) {
+  BrowserList::AddObserver(this);
   // Tag all open browser windows with the appropriate shelf id property. This
   // associates each window with the shelf item for the active web contents.
   for (auto* browser : *BrowserList::GetInstance()) {
@@ -144,7 +143,9 @@
 }
 
 BrowserShortcutLauncherItemController::
-    ~BrowserShortcutLauncherItemController() {}
+    ~BrowserShortcutLauncherItemController() {
+  BrowserList::RemoveObserver(this);
+}
 
 void BrowserShortcutLauncherItemController::UpdateBrowserItemState() {
   // Determine the new browser's active state and change if necessary.
diff --git a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h
index 02d22ae..ca8ee68d 100644
--- a/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h
+++ b/chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h
@@ -9,8 +9,6 @@
 
 #include "ash/public/cpp/shelf_item_delegate.h"
 #include "base/macros.h"
-#include "base/scoped_observer.h"
-#include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_list_observer.h"
 
 namespace ash {
@@ -71,9 +69,6 @@
   // The cached browser windows and tab indices shown in an application menu.
   std::vector<std::pair<Browser*, size_t>> app_menu_items_;
 
-  // Observer for browser windows adding and closing events.
-  ScopedObserver<BrowserList, BrowserListObserver> browser_list_observer_;
-
   std::unique_ptr<LauncherContextMenu> context_menu_;
 
   DISALLOW_COPY_AND_ASSIGN(BrowserShortcutLauncherItemController);
diff --git a/chrome/browser/ui/ash/media_client_impl.cc b/chrome/browser/ui/ash/media_client_impl.cc
index f497e38..44b0a144 100644
--- a/chrome/browser/ui/ash/media_client_impl.cc
+++ b/chrome/browser/ui/ash/media_client_impl.cc
@@ -138,7 +138,7 @@
 
 MediaClientImpl::MediaClientImpl() {
   MediaCaptureDevicesDispatcher::GetInstance()->AddObserver(this);
-  BrowserList::GetInstance()->AddObserver(this);
+  BrowserList::AddObserver(this);
 
   DCHECK(!g_media_client);
   g_media_client = this;
@@ -151,7 +151,7 @@
     media_controller_->SetClient(nullptr);
 
   MediaCaptureDevicesDispatcher::GetInstance()->RemoveObserver(this);
-  BrowserList::GetInstance()->RemoveObserver(this);
+  BrowserList::RemoveObserver(this);
 }
 
 // static
diff --git a/chrome/browser/ui/avatar_button_error_controller.cc b/chrome/browser/ui/avatar_button_error_controller.cc
index addc90e..f2dbdc2 100644
--- a/chrome/browser/ui/avatar_button_error_controller.cc
+++ b/chrome/browser/ui/avatar_button_error_controller.cc
@@ -8,7 +8,6 @@
 #include "chrome/browser/profiles/profiles_state.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/sync/sync_ui_util.h"
-#include "components/sync/driver/sync_service.h"
 
 AvatarButtonErrorController::AvatarButtonErrorController(
     AvatarButtonErrorControllerDelegate* delegate,
@@ -66,8 +65,7 @@
     Profile* profile,
     AvatarButtonErrorController* avatar_button_error_controller)
     : profile_(profile),
-      avatar_button_error_controller_(avatar_button_error_controller),
-      sync_observer_(this) {
+      avatar_button_error_controller_(avatar_button_error_controller) {
   syncer::SyncService* sync_service =
       ProfileSyncServiceFactory::GetForProfile(profile_);
   if (sync_service)
diff --git a/chrome/browser/ui/avatar_button_error_controller.h b/chrome/browser/ui/avatar_button_error_controller.h
index 9600fce..f81420c 100644
--- a/chrome/browser/ui/avatar_button_error_controller.h
+++ b/chrome/browser/ui/avatar_button_error_controller.h
@@ -8,6 +8,7 @@
 #include "base/scoped_observer.h"
 #include "chrome/browser/ui/avatar_button_error_controller_delegate.h"
 #include "components/signin/core/browser/signin_error_controller.h"
+#include "components/sync/driver/sync_service.h"
 #include "components/sync/driver/sync_service_observer.h"
 
 class Profile;
@@ -65,7 +66,8 @@
     Profile* profile_;
     AvatarButtonErrorController* avatar_button_error_controller_;
 
-    ScopedObserver<syncer::SyncService, SyncErrorObserver> sync_observer_;
+    ScopedObserver<syncer::SyncService, syncer::SyncServiceObserver>
+        sync_observer_{this};
 
     DISALLOW_COPY_AND_ASSIGN(SyncErrorObserver);
   };
diff --git a/chrome/browser/ui/browser_tab_restorer.cc b/chrome/browser/ui/browser_tab_restorer.cc
index deb5acb..c56811ed 100644
--- a/chrome/browser/ui/browser_tab_restorer.cc
+++ b/chrome/browser/ui/browser_tab_restorer.cc
@@ -58,7 +58,7 @@
 
 BrowserTabRestorer::~BrowserTabRestorer() {
   tab_restore_service_->RemoveObserver(this);
-  BrowserList::GetInstance()->RemoveObserver(this);
+  BrowserList::RemoveObserver(this);
 }
 
 // static
@@ -78,7 +78,7 @@
   DCHECK(tab_restore_service_);
   DCHECK(!tab_restore_service_->IsLoaded());
   tab_restore_service_->AddObserver(this);
-  BrowserList::GetInstance()->AddObserver(this);
+  BrowserList::AddObserver(this);
   browser_->profile()->SetUserData(kBrowserTabRestorerKey,
                                    base::WrapUnique(this));
   tab_restore_service_->LoadTabsFromLastSession();
diff --git a/chrome/browser/ui/cookie_controls/cookie_controls_controller.cc b/chrome/browser/ui/cookie_controls/cookie_controls_controller.cc
index fa2ba72..9a39cad 100644
--- a/chrome/browser/ui/cookie_controls/cookie_controls_controller.cc
+++ b/chrome/browser/ui/cookie_controls/cookie_controls_controller.cc
@@ -114,7 +114,7 @@
   observers_.AddObserver(obs);
 }
 
-void CookieControlsController::RemoveObserver(const CookieControlsView* obs) {
+void CookieControlsController::RemoveObserver(CookieControlsView* obs) {
   observers_.RemoveObserver(obs);
 }
 
diff --git a/chrome/browser/ui/cookie_controls/cookie_controls_controller.h b/chrome/browser/ui/cookie_controls/cookie_controls_controller.h
index 01ed932..866a14b 100644
--- a/chrome/browser/ui/cookie_controls/cookie_controls_controller.h
+++ b/chrome/browser/ui/cookie_controls/cookie_controls_controller.h
@@ -48,7 +48,7 @@
   int GetBlockedDomainCount();
 
   void AddObserver(CookieControlsView* obs);
-  void RemoveObserver(const CookieControlsView* obs);
+  void RemoveObserver(CookieControlsView* obs);
 
  private:
   // The observed WebContents changes during the lifetime of the
diff --git a/chrome/browser/ui/find_bar/find_bar_controller.cc b/chrome/browser/ui/find_bar/find_bar_controller.cc
index 3d1830a6..420c631 100644
--- a/chrome/browser/ui/find_bar/find_bar_controller.cc
+++ b/chrome/browser/ui/find_bar/find_bar_controller.cc
@@ -45,11 +45,11 @@
 class FindBrowserListObserver : public BrowserListObserver {
  public:
   FindBrowserListObserver() {
-    // Can't use base::ScopedObserver because BrowserListObserver isn't derived
-    // from Observer. Not that this object will ever be destructed anyway.
     BrowserList::AddObserver(this);
   }
 
+  ~FindBrowserListObserver() override { BrowserList::RemoveObserver(this); }
+
   static void EnsureInstance() {
     static base::NoDestructor<FindBrowserListObserver> the_instance;
     the_instance.get();
diff --git a/chrome/browser/ui/omnibox/omnibox_theme.cc b/chrome/browser/ui/omnibox/omnibox_theme.cc
index 4999235..54c9cd7 100644
--- a/chrome/browser/ui/omnibox/omnibox_theme.cc
+++ b/chrome/browser/ui/omnibox/omnibox_theme.cc
@@ -53,23 +53,18 @@
     dark = !dark;
 
   switch (part) {
-    case OmniboxPart::LOCATION_BAR_BACKGROUND: {
-      const bool hovered = state == OmniboxPartState::HOVERED;
-      return dark ? (hovered ? SkColorSetRGB(0x2F, 0x33, 0x36)
-                             : SkColorSetRGB(0x28, 0x2C, 0x2F))
-                  : (hovered ? gfx::kGoogleGrey200 : gfx::kGoogleGrey100);
-    }
+    case OmniboxPart::LOCATION_BAR_BACKGROUND:
+      if (state == OmniboxPartState::HOVERED) {
+        return color_utils::BlendTowardMaxContrast(
+            GetOmniboxColor(part, tint, OmniboxPartState::NORMAL), 0x0a);
+      }
+      return dark ? SkColorSetRGB(0x28, 0x2C, 0x2F) : gfx::kGoogleGrey100;
     case OmniboxPart::LOCATION_BAR_SECURITY_CHIP:
       return GetSecurityChipColor(tint, state);
     case OmniboxPart::LOCATION_BAR_SELECTED_KEYWORD:
       return dark ? gfx::kGoogleGrey100 : gfx::kGoogleBlue600;
     case OmniboxPart::RESULTS_BACKGROUND: {
-      // High contrast mode needs a darker base - Grey 800 with 16% white
-      // overlaid on it (see below) is hard to produce good contrast ratios
-      // against with colors other than white.
-      const SkColor dark_base_color =
-          high_contrast ? gfx::kGoogleGrey900 : gfx::kGoogleGrey800;
-      const SkColor base_color = dark ? dark_base_color : SK_ColorWHITE;
+      const SkColor base_color = dark ? gfx::kGoogleGrey900 : SK_ColorWHITE;
       // The spec calls for transparent black (or white) overlays for hover
       // (10%) and select (16%). Pre-blend these with the background for the
       // best text AA result.
@@ -80,19 +75,19 @@
     case OmniboxPart::LOCATION_BAR_CLEAR_ALL:
     case OmniboxPart::LOCATION_BAR_TEXT_DEFAULT:
     case OmniboxPart::RESULTS_TEXT_DEFAULT:
-      return dark ? gfx::kGoogleGrey100 : gfx::kGoogleGrey900;
+      return dark ? SK_ColorWHITE : gfx::kGoogleGrey900;
 
     case OmniboxPart::LOCATION_BAR_TEXT_DIMMED:
-      return dark ? gfx::kGoogleGrey500 : gfx::kGoogleGrey600;
     case OmniboxPart::RESULTS_ICON:
     case OmniboxPart::RESULTS_TEXT_DIMMED:
       // This is a pre-lightened (or darkened) variant of the base text color.
-      return dark ? gfx::kGoogleGrey400 : gfx::kGoogleGrey700;
+      return dark ? SkColorSetRGB(0x8D, 0x93, 0x99)
+                  : SkColorSetRGB(0x6B, 0x6F, 0x74);
 
     case OmniboxPart::RESULTS_TEXT_URL:
       if (high_contrast)
-        return dark ? gfx::kGoogleBlue300 : gfx::kGoogleBlue700;
-      return dark ? gfx::kGoogleBlue300 : gfx::kGoogleBlue600;
+        return dark ? gfx::kGoogleBlue200 : gfx::kGoogleBlue900;
+      return dark ? gfx::kGoogleBlue300 : gfx::kGoogleBlue800;
 
     case OmniboxPart::LOCATION_BAR_BUBBLE_OUTLINE:
       if (OmniboxFieldTrial::IsExperimentalKeywordModeEnabled())
diff --git a/chrome/browser/ui/search_engines/search_engine_tab_helper.h b/chrome/browser/ui/search_engines/search_engine_tab_helper.h
index 0c0c34891..0bca7a52 100644
--- a/chrome/browser/ui/search_engines/search_engine_tab_helper.h
+++ b/chrome/browser/ui/search_engines/search_engine_tab_helper.h
@@ -10,6 +10,7 @@
 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
 #include "chrome/browser/ui/find_bar/find_notification_details.h"
 #include "chrome/common/open_search_description_document_handler.mojom.h"
+#include "components/favicon/core/favicon_driver.h"
 #include "components/favicon/core/favicon_driver_observer.h"
 #include "content/public/browser/web_contents_binding_set.h"
 #include "content/public/browser/web_contents_observer.h"
diff --git a/chrome/browser/ui/send_tab_to_self/OWNERS b/chrome/browser/ui/send_tab_to_self/OWNERS
index 59b3396..e58f618d 100644
--- a/chrome/browser/ui/send_tab_to_self/OWNERS
+++ b/chrome/browser/ui/send_tab_to_self/OWNERS
@@ -1,3 +1,3 @@
- file://components/send_tab_to_self/OWNERS
+file://components/send_tab_to_self/OWNERS
 
 # COMPONENT: UI>Browser>Sharing
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc
index eb3a28fa..2e5a29fe 100644
--- a/chrome/browser/ui/tab_helpers.cc
+++ b/chrome/browser/ui/tab_helpers.cc
@@ -38,8 +38,8 @@
 #include "chrome/browser/optimization_guide/optimization_guide_web_contents_observer.h"
 #include "chrome/browser/page_load_metrics/page_load_metrics_initialize.h"
 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
 #include "chrome/browser/performance_manager/performance_manager_tab_helper.h"
+#include "chrome/browser/performance_manager/public/performance_manager.h"
 #include "chrome/browser/permissions/permission_request_manager.h"
 #include "chrome/browser/plugins/pdf_plugin_placeholder_observer.h"
 #include "chrome/browser/predictors/loading_predictor_factory.h"
@@ -368,7 +368,7 @@
   if (MediaEngagementService::IsEnabled())
     MediaEngagementService::CreateWebContentsObserver(web_contents);
 
-  if (performance_manager::PerformanceManager::GetInstance()) {
+  if (performance_manager::PerformanceManager::IsAvailable()) {
     performance_manager::PerformanceManagerTabHelper::CreateForWebContents(
         web_contents);
   }
diff --git a/chrome/browser/ui/tabs/pinned_tab_service.cc b/chrome/browser/ui/tabs/pinned_tab_service.cc
index 43a9890..c3d7629 100644
--- a/chrome/browser/ui/tabs/pinned_tab_service.cc
+++ b/chrome/browser/ui/tabs/pinned_tab_service.cc
@@ -7,6 +7,7 @@
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/tabs/pinned_tab_codec.h"
 #include "content/public/browser/notification_service.h"
 
@@ -17,10 +18,12 @@
   for (Browser* browser : *BrowserList::GetInstance())
     OnBrowserAdded(browser);
 
-  browser_list_observer_.Add(BrowserList::GetInstance());
+  BrowserList::AddObserver(this);
 }
 
-PinnedTabService::~PinnedTabService() {}
+PinnedTabService::~PinnedTabService() {
+  BrowserList::RemoveObserver(this);
+}
 
 void PinnedTabService::Observe(int type,
                                const content::NotificationSource& source,
diff --git a/chrome/browser/ui/tabs/pinned_tab_service.h b/chrome/browser/ui/tabs/pinned_tab_service.h
index 11c482f..f8f047fb 100644
--- a/chrome/browser/ui/tabs/pinned_tab_service.h
+++ b/chrome/browser/ui/tabs/pinned_tab_service.h
@@ -8,7 +8,6 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/scoped_observer.h"
-#include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_list_observer.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
@@ -59,8 +58,6 @@
 
   content::NotificationRegistrar registrar_;
 
-  ScopedObserver<BrowserList, BrowserListObserver> browser_list_observer_{this};
-
   DISALLOW_COPY_AND_ASSIGN(PinnedTabService);
 };
 
diff --git a/chrome/browser/ui/tabs/pinned_tab_service_browsertest.cc b/chrome/browser/ui/tabs/pinned_tab_service_browsertest.cc
index a26bfdd..6d6982b 100644
--- a/chrome/browser/ui/tabs/pinned_tab_service_browsertest.cc
+++ b/chrome/browser/ui/tabs/pinned_tab_service_browsertest.cc
@@ -7,6 +7,7 @@
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/tabs/pinned_tab_codec.h"
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
index 515952c..5a97528 100644
--- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
+++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
@@ -181,7 +181,8 @@
   // Time the menu is open for until a recent tab is selected.
   base::ElapsedTimer menu_opened_timer_;
 
-  ScopedObserver<sessions::TabRestoreService, RecentTabsSubMenuModel>
+  ScopedObserver<sessions::TabRestoreService,
+                 sessions::TabRestoreServiceObserver>
       tab_restore_service_observer_{this};
 
   std::unique_ptr<base::CallbackList<void()>::Subscription>
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model.cc b/chrome/browser/ui/toolbar/toolbar_actions_model.cc
index b036e66..26c0263e 100644
--- a/chrome/browser/ui/toolbar/toolbar_actions_model.cc
+++ b/chrome/browser/ui/toolbar/toolbar_actions_model.cc
@@ -34,7 +34,6 @@
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/browser/web_contents.h"
-#include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/extension_util.h"
 #include "extensions/browser/pref_names.h"
@@ -53,10 +52,7 @@
           extensions::ExtensionActionManager::Get(profile_)),
       actions_initialized_(false),
       highlight_type_(HIGHLIGHT_NONE),
-      has_active_bubble_(false),
-      extension_action_observer_(this),
-      extension_registry_observer_(this),
-      load_error_reporter_observer_(this) {
+      has_active_bubble_(false) {
   extensions::ExtensionSystem::Get(profile_)->ready().Post(
       FROM_HERE, base::BindOnce(&ToolbarActionsModel::OnReady,
                                 weak_ptr_factory_.GetWeakPtr()));
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model.h b/chrome/browser/ui/toolbar/toolbar_actions_model.h
index 71eb698..ef6618f78 100644
--- a/chrome/browser/ui/toolbar/toolbar_actions_model.h
+++ b/chrome/browser/ui/toolbar/toolbar_actions_model.h
@@ -18,6 +18,7 @@
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_registry_observer.h"
 #include "extensions/common/extension.h"
 
@@ -30,7 +31,6 @@
 namespace extensions {
 class ExtensionActionManager;
 class ExtensionMessageBubbleController;
-class ExtensionRegistry;
 }  // namespace extensions
 
 // Model for the browser actions toolbar. This is a per-profile instance, and
@@ -322,11 +322,11 @@
 
   ScopedObserver<extensions::ExtensionActionAPI,
                  extensions::ExtensionActionAPI::Observer>
-      extension_action_observer_;
+      extension_action_observer_{this};
 
   // Listen to extension load, unloaded notifications.
   ScopedObserver<extensions::ExtensionRegistry, ExtensionRegistryObserver>
-      extension_registry_observer_;
+      extension_registry_observer_{this};
 
   // For observing change of toolbar order preference by external entity (sync).
   PrefChangeRegistrar pref_change_registrar_;
@@ -334,7 +334,7 @@
 
   ScopedObserver<extensions::LoadErrorReporter,
                  extensions::LoadErrorReporter::Observer>
-      load_error_reporter_observer_;
+      load_error_reporter_observer_{this};
 
   base::WeakPtrFactory<ToolbarActionsModel> weak_ptr_factory_{this};
 
diff --git a/chrome/browser/ui/ui_features.cc b/chrome/browser/ui/ui_features.cc
index b9d4902..2984973 100644
--- a/chrome/browser/ui/ui_features.cc
+++ b/chrome/browser/ui/ui_features.cc
@@ -11,11 +11,6 @@
 const base::Feature kAnimatedAvatarButton{"AnimatedAvatarButton",
                                           base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Enables tabs to change pinned state when dragging in the tabstrip.
-// https://crbug.com/965681
-const base::Feature kDragToPinTabs{"DragToPinTabs",
-                                   base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Enables showing the EV certificate details in the Page Info bubble.
 const base::Feature kEvDetailsInPageInfo{"EvDetailsInPageInfo",
                                          base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/chrome/browser/ui/ui_features.h b/chrome/browser/ui/ui_features.h
index 9b67005..5f76f5f 100644
--- a/chrome/browser/ui/ui_features.h
+++ b/chrome/browser/ui/ui_features.h
@@ -19,8 +19,6 @@
 
 extern const base::Feature kAnimatedAvatarButton;
 
-extern const base::Feature kDragToPinTabs;
-
 extern const base::Feature kEvDetailsInPageInfo;
 
 extern const base::Feature kExtensionsToolbarMenu;
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_button.h b/chrome/browser/ui/views/extensions/extensions_menu_button.h
index 71e722e..eb2df3d8 100644
--- a/chrome/browser/ui/views/extensions/extensions_menu_button.h
+++ b/chrome/browser/ui/views/extensions/extensions_menu_button.h
@@ -29,10 +29,6 @@
                        ToolbarActionViewController* controller);
   ~ExtensionsMenuButton() override;
 
-  // Update pin button icon, color, tooltip, and visibility based on pinned
-  // state.
-  void UpdatePinButton();
-
   static const char kClassName[];
 
  private:
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_item_view.cc b/chrome/browser/ui/views/extensions/extensions_menu_item_view.cc
index 865af27..4a0758e 100644
--- a/chrome/browser/ui/views/extensions/extensions_menu_item_view.cc
+++ b/chrome/browser/ui/views/extensions/extensions_menu_item_view.cc
@@ -77,7 +77,6 @@
 
   context_menu_button_ = context_menu_button.get();
   AddChildView(std::move(context_menu_button));
-
   UpdatePinButton();
 }
 
@@ -117,16 +116,6 @@
   views::SetImageFromVectorIcon(
       pin_button_, IsPinned() ? views::kUnpinIcon : views::kPinIcon,
       kSecondaryIconSizeDp, icon_color);
-  pin_button_->SetVisible(IsPinned() || IsMouseHovered() ||
-                          IsContextMenuRunning());
-}
-
-void ExtensionsMenuItemView::OnMouseEntered(const ui::MouseEvent& event) {
-  UpdatePinButton();
-}
-
-void ExtensionsMenuItemView::OnMouseExited(const ui::MouseEvent& event) {
-  UpdatePinButton();
 }
 
 bool ExtensionsMenuItemView::IsContextMenuRunning() {
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_item_view.h b/chrome/browser/ui/views/extensions/extensions_menu_item_view.h
index 0a50a1a..9088bd51f 100644
--- a/chrome/browser/ui/views/extensions/extensions_menu_item_view.h
+++ b/chrome/browser/ui/views/extensions/extensions_menu_item_view.h
@@ -53,10 +53,6 @@
   ExtensionsMenuButton* primary_action_button_for_testing();
 
  private:
-  // views::Button:
-  void OnMouseEntered(const ui::MouseEvent& event) override;
-  void OnMouseExited(const ui::MouseEvent& event) override;
-
   ExtensionsMenuButton* const primary_action_button_;
 
   std::unique_ptr<ToolbarActionViewController> controller_;
diff --git a/chrome/browser/ui/views/frame/browser_root_view.h b/chrome/browser/ui/views/frame/browser_root_view.h
index 90565f26..d90c302 100644
--- a/chrome/browser/ui/views/frame/browser_root_view.h
+++ b/chrome/browser/ui/views/frame/browser_root_view.h
@@ -9,6 +9,8 @@
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "ui/views/widget/root_view.h"
 
+class ToolbarView;
+
 namespace ui {
 class OSExchangeData;
 }
diff --git a/chrome/browser/ui/views/frame/global_menu_bar_x11.cc b/chrome/browser/ui/views/frame/global_menu_bar_x11.cc
index 0ef67fa8..274f147c 100644
--- a/chrome/browser/ui/views/frame/global_menu_bar_x11.cc
+++ b/chrome/browser/ui/views/frame/global_menu_bar_x11.cc
@@ -211,7 +211,6 @@
       browser_view_(browser_view),
       xid_(host->GetAcceleratedWidget()),
       tab_restore_service_(nullptr),
-      scoped_observer_(this),
       last_command_id_(kFirstUnreservedCommandId - 1) {
   GlobalMenuBarRegistrarX11::GetInstance()->OnMenuBarCreated(this);
 }
diff --git a/chrome/browser/ui/views/frame/global_menu_bar_x11.h b/chrome/browser/ui/views/frame/global_menu_bar_x11.h
index a93ea65..5fcef30 100644
--- a/chrome/browser/ui/views/frame/global_menu_bar_x11.h
+++ b/chrome/browser/ui/views/frame/global_menu_bar_x11.h
@@ -19,6 +19,7 @@
 #include "chrome/browser/ui/browser_list_observer.h"
 #include "components/dbus/menu/menu.h"
 #include "components/history/core/browser/history_types.h"
+#include "components/history/core/browser/top_sites.h"
 #include "components/history/core/browser/top_sites_observer.h"
 #include "components/prefs/pref_change_registrar.h"
 #include "components/sessions/core/tab_restore_service.h"
@@ -27,10 +28,6 @@
 #include "ui/base/models/simple_menu_model.h"
 #include "ui/gfx/x/x11_types.h"
 
-namespace history {
-class TopSites;
-}
-
 namespace ui {
 class Accelerator;
 }
@@ -160,7 +157,8 @@
 
   std::unique_ptr<AvatarMenu> avatar_menu_;
 
-  ScopedObserver<history::TopSites, history::TopSitesObserver> scoped_observer_;
+  ScopedObserver<history::TopSites, history::TopSitesObserver> scoped_observer_{
+      this};
 
   // Maps from history item command ID to HistoryItem data.
   std::map<int, std::unique_ptr<HistoryItem>> history_items_;
diff --git a/chrome/browser/ui/views/frame/hosted_app_button_container.cc b/chrome/browser/ui/views/frame/hosted_app_button_container.cc
index eec0f61d..fccfc9f 100644
--- a/chrome/browser/ui/views/frame/hosted_app_button_container.cc
+++ b/chrome/browser/ui/views/frame/hosted_app_button_container.cc
@@ -189,8 +189,7 @@
     SkColor active_color,
     SkColor inactive_color,
     base::Optional<int> right_margin)
-    : scoped_widget_observer_(this),
-      browser_view_(browser_view),
+    : browser_view_(browser_view),
       active_color_(active_color),
       inactive_color_(inactive_color) {
   DCHECK(browser_view_);
diff --git a/chrome/browser/ui/views/frame/hosted_app_button_container.h b/chrome/browser/ui/views/frame/hosted_app_button_container.h
index ad451b35..7e209be 100644
--- a/chrome/browser/ui/views/frame/hosted_app_button_container.h
+++ b/chrome/browser/ui/views/frame/hosted_app_button_container.h
@@ -21,6 +21,7 @@
 #include "ui/views/controls/button/menu_button.h"
 #include "ui/views/controls/button/menu_button_listener.h"
 #include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_observer.h"
 
 namespace {
@@ -33,10 +34,6 @@
 class HostedAppOriginText;
 class HostedAppMenuButton;
 
-namespace views {
-class Widget;
-}
-
 // A container for hosted app buttons in the title bar.
 class HostedAppButtonContainer : public views::AccessiblePaneView,
                                  public BrowserActionsContainer::Delegate,
@@ -164,7 +161,8 @@
   // Whether we're waiting for the widget to become visible.
   bool pending_widget_visibility_ = true;
 
-  ScopedObserver<views::Widget, views::WidgetObserver> scoped_widget_observer_;
+  ScopedObserver<views::Widget, views::WidgetObserver> scoped_widget_observer_{
+      this};
 
   // Timers for synchronising their respective parts of the titlebar animation.
   base::OneShotTimer animation_start_delay_;
diff --git a/chrome/browser/ui/views/hung_renderer_view.cc b/chrome/browser/ui/views/hung_renderer_view.cc
index 5996325..5ccb318 100644
--- a/chrome/browser/ui/views/hung_renderer_view.cc
+++ b/chrome/browser/ui/views/hung_renderer_view.cc
@@ -31,9 +31,7 @@
 #include "components/favicon/content/content_favicon_driver.h"
 #include "components/web_modal/web_contents_modal_dialog_host.h"
 #include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
-#include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/result_codes.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -65,7 +63,7 @@
 // HungPagesTableModel, public:
 
 HungPagesTableModel::HungPagesTableModel(Delegate* delegate)
-    : delegate_(delegate), process_observer_(this), widget_observer_(this) {}
+    : delegate_(delegate) {}
 
 HungPagesTableModel::~HungPagesTableModel() {}
 
diff --git a/chrome/browser/ui/views/hung_renderer_view.h b/chrome/browser/ui/views/hung_renderer_view.h
index f9ad921..290a4f1e 100644
--- a/chrome/browser/ui/views/hung_renderer_view.h
+++ b/chrome/browser/ui/views/hung_renderer_view.h
@@ -12,7 +12,9 @@
 #include "base/macros.h"
 #include "base/scoped_observer.h"
 #include "components/favicon/content/content_favicon_driver.h"
+#include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_process_host_observer.h"
+#include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/render_widget_host_observer.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "ui/base/models/table_model.h"
@@ -123,10 +125,10 @@
   base::RepeatingClosure hang_monitor_restarter_;
 
   ScopedObserver<content::RenderProcessHost, content::RenderProcessHostObserver>
-      process_observer_;
+      process_observer_{this};
 
   ScopedObserver<content::RenderWidgetHost, content::RenderWidgetHostObserver>
-      widget_observer_;
+      widget_observer_{this};
 
   DISALLOW_COPY_AND_ASSIGN(HungPagesTableModel);
 };
diff --git a/chrome/browser/ui/views/ime/ime_warning_bubble_view.cc b/chrome/browser/ui/views/ime/ime_warning_bubble_view.cc
index d06e533..54c9cc06 100644
--- a/chrome/browser/ui/views/ime/ime_warning_bubble_view.cc
+++ b/chrome/browser/ui/views/ime/ime_warning_bubble_view.cc
@@ -92,8 +92,7 @@
     : extension_(extension),
       browser_view_(browser_view),
       browser_(browser_view->browser()),
-      response_callback_(callback),
-      toolbar_actions_bar_observer_(this) {
+      response_callback_(callback) {
   container_ = browser_view_->toolbar()->browser_actions();
   toolbar_actions_bar_ = container_->toolbar_actions_bar();
   BrowserList::AddObserver(this);
diff --git a/chrome/browser/ui/views/ime/ime_warning_bubble_view.h b/chrome/browser/ui/views/ime/ime_warning_bubble_view.h
index 6413178..2a020524 100644
--- a/chrome/browser/ui/views/ime/ime_warning_bubble_view.h
+++ b/chrome/browser/ui/views/ime/ime_warning_bubble_view.h
@@ -7,12 +7,12 @@
 
 #include "base/macros.h"
 #include "chrome/browser/ui/browser_list_observer.h"
+#include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_bar_observer.h"
 #include "ui/views/bubble/bubble_dialog_delegate_view.h"
 
 class BrowserActionsContainer;
 class BrowserView;
-class ToolbarActionsBar;
 enum class ImeWarningBubblePermissionStatus;
 
 namespace extensions {
@@ -92,7 +92,7 @@
   ToolbarActionsBar* toolbar_actions_bar_;
 
   ScopedObserver<ToolbarActionsBar, ToolbarActionsBarObserver>
-      toolbar_actions_bar_observer_;
+      toolbar_actions_bar_observer_{this};
 
   base::WeakPtrFactory<ImeWarningBubbleView> weak_ptr_factory_{this};
 
diff --git a/chrome/browser/ui/views/location_bar/cookie_controls_bubble_view.cc b/chrome/browser/ui/views/location_bar/cookie_controls_bubble_view.cc
index 1314f32..1fa0d5b 100644
--- a/chrome/browser/ui/views/location_bar/cookie_controls_bubble_view.cc
+++ b/chrome/browser/ui/views/location_bar/cookie_controls_bubble_view.cc
@@ -7,7 +7,6 @@
 #include <memory>
 #include "base/logging.h"
 #include "chrome/app/vector_icons/vector_icons.h"
-#include "chrome/browser/ui/cookie_controls/cookie_controls_controller.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/theme_resources.h"
diff --git a/chrome/browser/ui/views/location_bar/cookie_controls_bubble_view.h b/chrome/browser/ui/views/location_bar/cookie_controls_bubble_view.h
index 53c022d..691be2b3 100644
--- a/chrome/browser/ui/views/location_bar/cookie_controls_bubble_view.h
+++ b/chrome/browser/ui/views/location_bar/cookie_controls_bubble_view.h
@@ -6,13 +6,12 @@
 #define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_COOKIE_CONTROLS_BUBBLE_VIEW_H_
 
 #include "base/macros.h"
+#include "chrome/browser/ui/cookie_controls/cookie_controls_controller.h"
 #include "chrome/browser/ui/cookie_controls/cookie_controls_view.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
 #include "ui/views/controls/button/button.h"
 
-class CookieControlsController;
-
 namespace content {
 class WebContents;
 }
diff --git a/chrome/browser/ui/views/location_bar/star_view.cc b/chrome/browser/ui/views/location_bar/star_view.cc
index ee89d35f..a7e1c57 100644
--- a/chrome/browser/ui/views/location_bar/star_view.cc
+++ b/chrome/browser/ui/views/location_bar/star_view.cc
@@ -22,7 +22,6 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/gfx/paint_vector_icon.h"
-#include "ui/views/widget/widget_observer.h"
 
 namespace {
 
@@ -47,8 +46,7 @@
                    Browser* browser,
                    PageActionIconView::Delegate* delegate)
     : PageActionIconView(command_updater, IDC_BOOKMARK_THIS_TAB, delegate),
-      browser_(browser),
-      bookmark_promo_observer_(this) {
+      browser_(browser) {
   SetID(VIEW_ID_STAR_BUTTON);
   SetToggled(false);
 }
diff --git a/chrome/browser/ui/views/location_bar/star_view.h b/chrome/browser/ui/views/location_bar/star_view.h
index b4c6002..4c8fe39 100644
--- a/chrome/browser/ui/views/location_bar/star_view.h
+++ b/chrome/browser/ui/views/location_bar/star_view.h
@@ -8,6 +8,8 @@
 #include "base/macros.h"
 #include "base/scoped_observer.h"
 #include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_observer.h"
 
 class Browser;
 class CommandUpdater;
@@ -43,7 +45,8 @@
 
   // Observes the BookmarkPromoBubbleView's widget. Used to tell whether the
   // promo is open and gets called back when it closes.
-  ScopedObserver<views::Widget, views::WidgetObserver> bookmark_promo_observer_;
+  ScopedObserver<views::Widget, views::WidgetObserver> bookmark_promo_observer_{
+      this};
 
   DISALLOW_COPY_AND_ASSIGN(StarView);
 };
diff --git a/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc b/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc
index 4351fcb..2de6f803 100644
--- a/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc
+++ b/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc
@@ -108,7 +108,6 @@
 MediaRouterDialogControllerViews::MediaRouterDialogControllerViews(
     WebContents* web_contents)
     : MediaRouterDialogController(web_contents),
-      scoped_widget_observer_(this),
       media_router_ui_service_(GetMediaRouterUIService(web_contents)) {
   DCHECK(media_router_ui_service_);
   media_router_ui_service_->AddObserver(this);
diff --git a/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.h b/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.h
index d6a08f7..d1ee0083 100644
--- a/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.h
+++ b/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.h
@@ -13,6 +13,7 @@
 #include "chrome/browser/media/router/media_router_dialog_controller.h"
 #include "chrome/browser/ui/media_router/media_router_ui_service.h"
 #include "chrome/browser/ui/views/media_router/media_router_views_ui.h"
+#include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_observer.h"
 
 namespace media_router {
@@ -65,7 +66,8 @@
 
   base::RepeatingClosure dialog_creation_callback_;
 
-  ScopedObserver<views::Widget, views::WidgetObserver> scoped_widget_observer_;
+  ScopedObserver<views::Widget, views::WidgetObserver> scoped_widget_observer_{
+      this};
 
   // Service that provides MediaRouterActionController. It outlives |this|.
   MediaRouterUIService* const media_router_ui_service_;
diff --git a/chrome/browser/ui/views/media_router/web_contents_display_observer_view.cc b/chrome/browser/ui/views/media_router/web_contents_display_observer_view.cc
index 5b212209..3d4b9354a 100644
--- a/chrome/browser/ui/views/media_router/web_contents_display_observer_view.cc
+++ b/chrome/browser/ui/views/media_router/web_contents_display_observer_view.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "chrome/browser/ui/views/media_router/web_contents_display_observer_view.h"
+
 #include <memory>
 #include <utility>
 
-#include "chrome/browser/ui/views/media_router/web_contents_display_observer_view.h"
-
 #include "chrome/browser/ui/browser_list.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/display/screen.h"
@@ -34,13 +34,13 @@
     display_ = GetDisplayNearestWidget();
     widget_->AddObserver(this);
   }
-  BrowserList::GetInstance()->AddObserver(this);
+  BrowserList::AddObserver(this);
 }
 
 WebContentsDisplayObserverView::~WebContentsDisplayObserverView() {
   if (widget_)
     widget_->RemoveObserver(this);
-  BrowserList::GetInstance()->RemoveObserver(this);
+  BrowserList::RemoveObserver(this);
 }
 
 void WebContentsDisplayObserverView::OnBrowserSetLastActive(Browser* browser) {
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
index c5b5290..10cfd4a 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -37,7 +37,6 @@
 #include "components/omnibox/browser/omnibox_field_trial.h"
 #include "components/omnibox/browser/omnibox_popup_model.h"
 #include "components/omnibox/common/omnibox_features.h"
-#include "components/search_engines/template_url_service.h"
 #include "components/security_state/core/security_state.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/url_formatter/elide_url.h"
@@ -200,9 +199,7 @@
       saved_selection_for_focus_change_(gfx::Range::InvalidRange()),
       location_bar_view_(location_bar),
       latency_histogram_state_(NOT_ACTIVE),
-      friendly_suggestion_text_prefix_length_(0),
-      scoped_compositor_observer_(this),
-      scoped_template_url_service_observer_(this) {
+      friendly_suggestion_text_prefix_length_(0) {
   SetID(VIEW_ID_OMNIBOX);
   SetFontList(font_list);
 
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.h b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
index d2bb1ab..b40013e 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.h
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
@@ -17,6 +17,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/ui/send_tab_to_self/send_tab_to_self_sub_menu_model.h"
 #include "components/omnibox/browser/omnibox_view.h"
+#include "components/search_engines/template_url_service.h"
 #include "components/search_engines/template_url_service_observer.h"
 #include "ui/base/window_open_disposition.h"
 #include "ui/compositor/compositor.h"
@@ -366,9 +367,9 @@
   int friendly_suggestion_text_prefix_length_;
 
   ScopedObserver<ui::Compositor, ui::CompositorObserver>
-      scoped_compositor_observer_;
+      scoped_compositor_observer_{this};
   ScopedObserver<TemplateURLService, TemplateURLServiceObserver>
-      scoped_template_url_service_observer_;
+      scoped_template_url_service_observer_{this};
 
   // Send tab to self submenu.
   std::unique_ptr<send_tab_to_self::SendTabToSelfSubMenuModel>
diff --git a/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc b/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc
index 00c90f9..1a83aea 100644
--- a/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc
+++ b/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc
@@ -30,9 +30,7 @@
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_ink_drop_util.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/signin/public/identity_manager/identity_manager.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/models/menu_model.h"
 #include "ui/base/theme_provider.h"
 #include "ui/gfx/color_palette.h"
@@ -76,20 +74,17 @@
 
 AvatarToolbarButton::AvatarToolbarButton(Browser* browser)
     : ToolbarButton(nullptr),
-      browser_(browser),
-      profile_(browser_->profile()),
 #if !defined(OS_CHROMEOS)
-      error_controller_(this, profile_),
+      error_controller_(this, browser->profile()),
 #endif  // !defined(OS_CHROMEOS)
-      browser_list_observer_(this),
-      profile_observer_(this),
-      identity_manager_observer_(this) {
+      browser_(browser),
+      profile_(browser_->profile()) {
   profile_observer_.Add(
       &g_browser_process->profile_manager()->GetProfileAttributesStorage());
 
   State state = GetState();
   if (state == State::kIncognitoProfile) {
-    browser_list_observer_.Add(BrowserList::GetInstance());
+    BrowserList::AddObserver(this);
   } else if (state != State::kGuestSession) {
     signin::IdentityManager* identity_manager =
         IdentityManagerFactory::GetForProfile(profile_);
@@ -131,14 +126,13 @@
   UpdateText();
 
   md_observer_.Add(ui::MaterialDesignController::GetInstance());
-
-  personal_data_manager_ = autofill::PersonalDataManagerFactory::GetForProfile(
-      profile_->GetOriginalProfile());
-  personal_data_manager_->AddObserver(this);
+  personal_data_manager_observer_.Add(
+      autofill::PersonalDataManagerFactory::GetForProfile(
+          profile_->GetOriginalProfile()));
 }
 
 AvatarToolbarButton::~AvatarToolbarButton() {
-  personal_data_manager_->RemoveObserver(this);
+  BrowserList::RemoveObserver(this);
 }
 
 void AvatarToolbarButton::UpdateIcon() {
diff --git a/chrome/browser/ui/views/profiles/avatar_toolbar_button.h b/chrome/browser/ui/views/profiles/avatar_toolbar_button.h
index c097aa4..72073d7 100644
--- a/chrome/browser/ui/views/profiles/avatar_toolbar_button.h
+++ b/chrome/browser/ui/views/profiles/avatar_toolbar_button.h
@@ -17,6 +17,7 @@
 #include "components/autofill/core/browser/personal_data_manager.h"
 #include "components/autofill/core/browser/personal_data_manager_observer.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
+#include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/material_design/material_design_controller_observer.h"
 #include "ui/events/event.h"
 
@@ -108,11 +109,13 @@
   void ShowHighlightAnimation();
   void HideHighlightAnimation();
 
+#if !defined(OS_CHROMEOS)
+  AvatarButtonErrorController error_controller_;
+#endif  // !defined(OS_CHROMEOS)
+
   Browser* const browser_;
   Profile* const profile_;
 
-  autofill::PersonalDataManager* personal_data_manager_;
-
   // Whether the avatar highlight animation is visible. If true, hide avatar
   // button sync paused/error state and update highlight color.
   bool highlight_animation_visible_ = false;
@@ -128,18 +131,19 @@
   // We cannot show the animation before we fetch the new avatar.
   bool waiting_for_image_to_show_user_email_ = false;
 
-#if !defined(OS_CHROMEOS)
-  AvatarButtonErrorController error_controller_;
-#endif  // !defined(OS_CHROMEOS)
-  ScopedObserver<BrowserList, BrowserListObserver> browser_list_observer_;
-  ScopedObserver<ProfileAttributesStorage, AvatarToolbarButton>
-      profile_observer_;
-  ScopedObserver<signin::IdentityManager, AvatarToolbarButton>
-      identity_manager_observer_;
-  ScopedObserver<ui::MaterialDesignController, AvatarToolbarButton>
+  ScopedObserver<ProfileAttributesStorage, ProfileAttributesStorage::Observer>
+      profile_observer_{this};
+  ScopedObserver<signin::IdentityManager, signin::IdentityManager::Observer>
+      identity_manager_observer_{this};
+  ScopedObserver<ui::MaterialDesignController,
+                 ui::MaterialDesignControllerObserver>
       md_observer_{this};
+  ScopedObserver<autofill::PersonalDataManager,
+                 autofill::PersonalDataManagerObserver>
+      personal_data_manager_observer_{this};
 
   base::WeakPtrFactory<AvatarToolbarButton> weak_ptr_factory_{this};
+
   DISALLOW_COPY_AND_ASSIGN(AvatarToolbarButton);
 };
 
diff --git a/chrome/browser/ui/views/send_tab_to_self/OWNERS b/chrome/browser/ui/views/send_tab_to_self/OWNERS
index 59b3396..e58f618d 100644
--- a/chrome/browser/ui/views/send_tab_to_self/OWNERS
+++ b/chrome/browser/ui/views/send_tab_to_self/OWNERS
@@ -1,3 +1,3 @@
- file://components/send_tab_to_self/OWNERS
+file://components/send_tab_to_self/OWNERS
 
 # COMPONENT: UI>Browser>Sharing
diff --git a/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views.cc b/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views.cc
index 3fdaaf0..c52d782 100644
--- a/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views.cc
+++ b/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views.cc
@@ -10,6 +10,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "chrome/browser/infobars/infobar_service.h"
+#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -104,7 +105,7 @@
 
 TabSharingUIViews::TabSharingUIViews(const content::DesktopMediaID& media_id,
                                      base::string16 app_name)
-    : app_name_(std::move(app_name)) {
+    : shared_tab_media_id_(media_id), app_name_(std::move(app_name)) {
   shared_tab_ = content::WebContents::FromRenderFrameHost(
       content::RenderFrameHost::FromID(
           media_id.web_contents_id.render_process_id,
@@ -126,6 +127,7 @@
   stop_callback_ = std::move(stop_callback);
   CreateInfobarsForAllTabs();
   SetContentsBorderVisible(shared_tab_, true);
+  CreateTabCaptureIndicator();
   return 0;
 }
 
@@ -265,3 +267,14 @@
 
   infobars_.clear();
 }
+
+void TabSharingUIViews::CreateTabCaptureIndicator() {
+  const blink::MediaStreamDevice device(
+      blink::mojom::MediaStreamType::GUM_TAB_VIDEO_CAPTURE,
+      shared_tab_media_id_.ToString(), std::string());
+  tab_capture_indicator_ui_ = MediaCaptureDevicesDispatcher::GetInstance()
+                                  ->GetMediaStreamCaptureIndicator()
+                                  ->RegisterMediaStream(shared_tab_, {device});
+  tab_capture_indicator_ui_->OnStarted(
+      base::OnceClosure(), content::MediaStreamUI::SourceCallback());
+}
diff --git a/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views.h b/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views.h
index c28f98a..1b8bbf20 100644
--- a/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views.h
+++ b/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views.h
@@ -74,11 +74,15 @@
   void CreateInfobarForWebContents(content::WebContents* contents);
   void RemoveInfobarsForAllTabs();
 
+  void CreateTabCaptureIndicator();
+
   std::map<content::WebContents*, infobars::InfoBar*> infobars_;
+  content::DesktopMediaID shared_tab_media_id_;
   const base::string16 app_name_;
   content::WebContents* shared_tab_;
   base::string16 shared_tab_name_;
   Profile* profile_;
+  std::unique_ptr<content::MediaStreamUI> tab_capture_indicator_ui_;
 
   content::MediaStreamUI::SourceCallback source_callback_;
   base::OnceClosure stop_callback_;
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index 4c6125f..25b0fe6 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -60,7 +60,6 @@
 #include "ui/base/default_theme_provider.h"
 #include "ui/base/dragdrop/drag_drop_types.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/models/list_selection_model.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/display/display.h"
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h
index 2f195d0f..463ce3c 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.h
+++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -26,6 +26,7 @@
 #include "chrome/browser/ui/views/tabs/tab_controller.h"
 #include "chrome/browser/ui/views/tabs/tab_drag_context.h"
 #include "chrome/browser/ui/views/tabs/tab_strip.h"
+#include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/material_design/material_design_controller_observer.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/geometry/point.h"
@@ -48,7 +49,6 @@
 class TabStripController;
 class TabStripObserver;
 class TabStripLayoutHelper;
-class ViewObserver;
 
 namespace gfx {
 class Rect;
diff --git a/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc b/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc
index d17f268..154eee3 100644
--- a/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc
+++ b/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc
@@ -28,7 +28,6 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/feature_engagement/public/feature_constants.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/ui_base_features.h"
 #include "ui/compositor/paint_recorder.h"
diff --git a/chrome/browser/ui/views/toolbar/browser_app_menu_button.h b/chrome/browser/ui/views/toolbar/browser_app_menu_button.h
index 2f6e47be..aca48d9 100644
--- a/chrome/browser/ui/views/toolbar/browser_app_menu_button.h
+++ b/chrome/browser/ui/views/toolbar/browser_app_menu_button.h
@@ -15,13 +15,10 @@
 #include "chrome/browser/ui/toolbar/app_menu_icon_controller.h"
 #include "chrome/browser/ui/views/frame/app_menu_button.h"
 #include "components/feature_engagement/buildflags.h"
+#include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/material_design/material_design_controller_observer.h"
 #include "ui/views/view.h"
 
-namespace ui {
-class MaterialDesignController;
-}
-
 class ToolbarView;
 enum class InProductHelpFeature;
 
diff --git a/chrome/browser/ui/views/toolbar/extension_toolbar_menu_view.cc b/chrome/browser/ui/views/toolbar/extension_toolbar_menu_view.cc
index 19957f7..28be99b 100644
--- a/chrome/browser/ui/views/toolbar/extension_toolbar_menu_view.cc
+++ b/chrome/browser/ui/views/toolbar/extension_toolbar_menu_view.cc
@@ -9,7 +9,6 @@
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
-#include "chrome/browser/ui/views/frame/app_menu_button.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/toolbar/app_menu.h"
 #include "chrome/browser/ui/views/toolbar/browser_actions_container.h"
diff --git a/chrome/browser/ui/views/toolbar/extension_toolbar_menu_view.h b/chrome/browser/ui/views/toolbar/extension_toolbar_menu_view.h
index ac0e262..688ae2b7a 100644
--- a/chrome/browser/ui/views/toolbar/extension_toolbar_menu_view.h
+++ b/chrome/browser/ui/views/toolbar/extension_toolbar_menu_view.h
@@ -10,11 +10,11 @@
 #include "base/scoped_observer.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_bar_observer.h"
+#include "chrome/browser/ui/views/frame/app_menu_button.h"
 #include "chrome/browser/ui/views/frame/app_menu_button_observer.h"
 #include "ui/views/controls/scroll_view.h"
 
 class AppMenu;
-class AppMenuButton;
 class Browser;
 class BrowserActionsContainer;
 
diff --git a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
index 07fbc045..84fc958 100644
--- a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
+++ b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
@@ -44,10 +44,6 @@
 
   std::unique_ptr<AuthenticatorRequestSheetView> sheet_view;
   switch (dialog_model->current_step()) {
-    case Step::kWelcomeScreen:
-      sheet_view = std::make_unique<AuthenticatorRequestSheetView>(
-          std::make_unique<AuthenticatorWelcomeSheetModel>(dialog_model));
-      break;
     case Step::kTransportSelection:
       sheet_view = std::make_unique<AuthenticatorTransportSelectorSheetView>(
           std::make_unique<AuthenticatorTransportSelectorSheetModel>(
diff --git a/chrome/browser/ui/webauthn/sheet_models.cc b/chrome/browser/ui/webauthn/sheet_models.cc
index 5fea13d..35c6356 100644
--- a/chrome/browser/ui/webauthn/sheet_models.cc
+++ b/chrome/browser/ui/webauthn/sheet_models.cc
@@ -122,40 +122,6 @@
   dialog_model_ = nullptr;
 }
 
-// AuthenticatorWelcomeSheetModel ---------------------------------------------
-
-const gfx::VectorIcon& AuthenticatorWelcomeSheetModel::GetStepIllustration(
-    ImageColorScheme color_scheme) const {
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnWelcomeDarkIcon
-                                                 : kWebauthnWelcomeIcon;
-}
-
-base::string16 AuthenticatorWelcomeSheetModel::GetStepTitle() const {
-  return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_WELCOME_SCREEN_TITLE,
-                                    GetRelyingPartyIdString(dialog_model()));
-}
-
-base::string16 AuthenticatorWelcomeSheetModel::GetStepDescription() const {
-  return l10n_util::GetStringUTF16(IDS_WEBAUTHN_WELCOME_SCREEN_DESCRIPTION);
-}
-
-bool AuthenticatorWelcomeSheetModel::IsAcceptButtonVisible() const {
-  return true;
-}
-
-bool AuthenticatorWelcomeSheetModel::IsAcceptButtonEnabled() const {
-  return true;
-}
-
-base::string16 AuthenticatorWelcomeSheetModel::GetAcceptButtonLabel() const {
-  return l10n_util::GetStringUTF16(IDS_WEBAUTHN_WELCOME_SCREEN_NEXT);
-}
-
-void AuthenticatorWelcomeSheetModel::OnAccept() {
-  dialog_model()
-      ->StartGuidedFlowForMostLikelyTransportOrShowTransportSelection();
-}
-
 // AuthenticatorTransportSelectorSheetModel -----------------------------------
 
 bool AuthenticatorTransportSelectorSheetModel::IsBackButtonVisible() const {
diff --git a/chrome/browser/ui/webauthn/sheet_models.h b/chrome/browser/ui/webauthn/sheet_models.h
index f7a415c..4ce5b5f 100644
--- a/chrome/browser/ui/webauthn/sheet_models.h
+++ b/chrome/browser/ui/webauthn/sheet_models.h
@@ -60,23 +60,6 @@
   DISALLOW_COPY_AND_ASSIGN(AuthenticatorSheetModelBase);
 };
 
-// The initial sheet shown when the UX flow starts.
-class AuthenticatorWelcomeSheetModel : public AuthenticatorSheetModelBase {
- public:
-  using AuthenticatorSheetModelBase::AuthenticatorSheetModelBase;
-
- private:
-  // AuthenticatorSheetModelBase:
-  const gfx::VectorIcon& GetStepIllustration(
-      ImageColorScheme color_scheme) const override;
-  base::string16 GetStepTitle() const override;
-  base::string16 GetStepDescription() const override;
-  bool IsAcceptButtonVisible() const override;
-  bool IsAcceptButtonEnabled() const override;
-  base::string16 GetAcceptButtonLabel() const override;
-  void OnAccept() override;
-};
-
 // The sheet shown for selecting the transport over which the security key
 // should be accessed.
 class AuthenticatorTransportSelectorSheetModel
diff --git a/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.cc
index bf674ae6..dbbb2c2 100644
--- a/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.cc
@@ -55,8 +55,8 @@
     : BaseScreenHandler(kScreenId, js_calls_container) {
   set_user_acted_method_path("login.FingerprintSetupScreen.userActed");
 
-  content::GetSystemConnector()->BindInterface(device::mojom::kServiceName,
-                                               &fp_service_);
+  content::GetSystemConnector()->Connect(
+      device::mojom::kServiceName, fp_service_.BindNewPipeAndPassReceiver());
   device::mojom::FingerprintObserverPtr observer;
   binding_.Bind(mojo::MakeRequest(&observer));
   fp_service_->AddFingerprintObserver(std::move(observer));
diff --git a/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.h
index 8eef6b97..f9b285a 100644
--- a/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.h
@@ -8,6 +8,7 @@
 #include "base/macros.h"
 #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "services/device/public/mojom/fingerprint.mojom.h"
 
 namespace chromeos {
@@ -75,7 +76,7 @@
 
   FingerprintSetupScreen* screen_ = nullptr;
 
-  device::mojom::FingerprintPtr fp_service_;
+  mojo::Remote<device::mojom::Fingerprint> fp_service_;
   mojo::Binding<device::mojom::FingerprintObserver> binding_{this};
   int enrolled_finger_count_ = 0;
   bool enroll_session_started_ = false;
diff --git a/chrome/browser/ui/webui/discards/DEPS b/chrome/browser/ui/webui/discards/DEPS
deleted file mode 100644
index 3e1844b..0000000
--- a/chrome/browser/ui/webui/discards/DEPS
+++ /dev/null
@@ -1,6 +0,0 @@
-specific_include_rules = {
-  # Until CallOnGraph is in the public interface, the impl needs GraphImpl
-  "webui_graph_dump_impl\.cc": [
-    "+chrome/browser/performance_manager/graph",
-  ],
-}
diff --git a/chrome/browser/ui/webui/discards/discards_ui.cc b/chrome/browser/ui/webui/discards/discards_ui.cc
index 5ef03de..ff3badf9 100644
--- a/chrome/browser/ui/webui/discards/discards_ui.cc
+++ b/chrome/browser/ui/webui/discards/discards_ui.cc
@@ -14,7 +14,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/engagement/site_engagement_service.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/public/performance_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/resource_coordinator/lifecycle_unit.h"
 #include "chrome/browser/resource_coordinator/lifecycle_unit_state.mojom.h"
@@ -461,11 +461,9 @@
 
 void DiscardsUI::BindWebUIGraphDumpProvider(
     performance_manager::mojom::WebUIGraphDumpRequest request) {
-  performance_manager::PerformanceManager* performance_manager =
-      performance_manager::PerformanceManager::GetInstance();
-  if (performance_manager) {
+  if (performance_manager::PerformanceManager::IsAvailable()) {
     // Forward the interface request directly to the service.
-    performance_manager->CallOnGraph(
+    performance_manager::PerformanceManager::CallOnGraph(
         FROM_HERE,
         base::BindOnce(&performance_manager::WebUIGraphDumpImpl::CreateAndBind,
                        std::move(request)));
diff --git a/chrome/browser/ui/webui/discards/webui_graph_dump_impl.cc b/chrome/browser/ui/webui/discards/webui_graph_dump_impl.cc
index 5287174..3b219d4 100644
--- a/chrome/browser/ui/webui/discards/webui_graph_dump_impl.cc
+++ b/chrome/browser/ui/webui/discards/webui_graph_dump_impl.cc
@@ -14,9 +14,8 @@
 #include "base/task/post_task.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "chrome/browser/favicon/favicon_service_factory.h"
-#include "chrome/browser/performance_manager/graph/graph_impl.h"
-#include "chrome/browser/performance_manager/performance_manager.h"
 #include "chrome/browser/performance_manager/public/graph/graph.h"
+#include "chrome/browser/performance_manager/public/performance_manager.h"
 #include "chrome/browser/performance_manager/public/web_contents_proxy.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/favicon/core/favicon_service.h"
@@ -114,7 +113,7 @@
 
 // static
 void WebUIGraphDumpImpl::CreateAndBind(mojom::WebUIGraphDumpRequest request,
-                                       GraphImpl* graph) {
+                                       Graph* graph) {
   std::unique_ptr<WebUIGraphDumpImpl> dump =
       std::make_unique<WebUIGraphDumpImpl>();
 
diff --git a/chrome/browser/ui/webui/discards/webui_graph_dump_impl.h b/chrome/browser/ui/webui/discards/webui_graph_dump_impl.h
index beec338a..9c5a4e8 100644
--- a/chrome/browser/ui/webui/discards/webui_graph_dump_impl.h
+++ b/chrome/browser/ui/webui/discards/webui_graph_dump_impl.h
@@ -19,8 +19,6 @@
 
 namespace performance_manager {
 
-class GraphImpl;
-
 // TODO(siggi): Add workers to the WebUI graph.
 class WebUIGraphDumpImpl : public mojom::WebUIGraphDump,
                            public GraphOwned,
@@ -33,8 +31,7 @@
 
   // Creates a new WebUIGraphDumpImpl to service |request| and passes its
   // ownership to |graph|.
-  static void CreateAndBind(mojom::WebUIGraphDumpRequest request,
-                            GraphImpl* graph);
+  static void CreateAndBind(mojom::WebUIGraphDumpRequest request, Graph* graph);
 
   // Exposed for testing.
   void BindWithGraph(Graph* graph, mojom::WebUIGraphDumpRequest request);
@@ -117,7 +114,7 @@
       scoped_refptr<base::RefCountedMemory> bitmap_data);
 
   static void BindOnPMSequence(mojom::WebUIGraphDumpRequest request,
-                               GraphImpl* graph);
+                               Graph* graph);
   static void OnConnectionError(WebUIGraphDumpImpl* impl);
 
   Graph* graph_ = nullptr;
diff --git a/chrome/browser/ui/webui/help/version_updater_chromeos.cc b/chrome/browser/ui/webui/help/version_updater_chromeos.cc
index 55b74581..9ed9ceb 100644
--- a/chrome/browser/ui/webui/help/version_updater_chromeos.cc
+++ b/chrome/browser/ui/webui/help/version_updater_chromeos.cc
@@ -165,8 +165,8 @@
   if (!update_engine_client->HasObserver(this))
     update_engine_client->AddObserver(this);
 
-  if (update_engine_client->GetLastStatus().status !=
-      UpdateEngineClient::UPDATE_STATUS_IDLE) {
+  if (update_engine_client->GetLastStatus().current_operation() !=
+      update_engine::Operation::IDLE) {
     check_for_update_when_idle_ = true;
     return;
   }
@@ -259,7 +259,7 @@
 
 VersionUpdaterCros::VersionUpdaterCros(content::WebContents* web_contents)
     : context_(web_contents ? web_contents->GetBrowserContext() : nullptr),
-      last_operation_(UpdateEngineClient::UPDATE_STATUS_IDLE),
+      last_operation_(update_engine::Operation::IDLE),
       check_for_update_when_idle_(false) {}
 
 VersionUpdaterCros::~VersionUpdaterCros() {
@@ -269,64 +269,65 @@
 }
 
 void VersionUpdaterCros::UpdateStatusChanged(
-    const UpdateEngineClient::Status& status) {
+    const update_engine::StatusResult& status) {
   Status my_status = UPDATED;
   int progress = 0;
-  std::string version = status.new_version;
-  int64_t size = status.new_size;
+  std::string version = status.new_version();
+  int64_t size = status.new_size();
   base::string16 message;
 
   // If the updater is currently idle, just show the last operation (unless it
   // was previously checking for an update -- in that case, the system is
   // up to date now).  See http://crbug.com/120063 for details.
-  UpdateEngineClient::UpdateStatusOperation operation_to_show = status.status;
-  if (status.status == UpdateEngineClient::UPDATE_STATUS_IDLE &&
-      last_operation_ !=
-      UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE) {
+  update_engine::Operation operation_to_show = status.current_operation();
+  if (status.current_operation() == update_engine::Operation::IDLE &&
+      last_operation_ != update_engine::Operation::CHECKING_FOR_UPDATE) {
     operation_to_show = last_operation_;
   }
 
   switch (operation_to_show) {
-    case UpdateEngineClient::UPDATE_STATUS_ERROR:
-    case UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT:
-    case UpdateEngineClient::UPDATE_STATUS_ATTEMPTING_ROLLBACK:
+    case update_engine::Operation::IDLE:
+    case update_engine::Operation::DISABLED:
+    case update_engine::Operation::ERROR:
+    case update_engine::Operation::REPORTING_ERROR_EVENT:
+    case update_engine::Operation::ATTEMPTING_ROLLBACK:
       // This path previously used the FAILED status and IDS_UPGRADE_ERROR, but
       // the update engine reports errors for some conditions that shouldn't
       // actually be displayed as errors to users: http://crbug.com/146919.
       // Just use the UPDATED status instead.
       break;
-    case UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE:
+    case update_engine::Operation::CHECKING_FOR_UPDATE:
       my_status = CHECKING;
       break;
-    case UpdateEngineClient::UPDATE_STATUS_DOWNLOADING:
-      progress = static_cast<int>(round(status.download_progress * 100));
+    case update_engine::Operation::DOWNLOADING:
+      progress = static_cast<int>(round(status.progress() * 100));
       FALLTHROUGH;
-    case UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE:
+    case update_engine::Operation::UPDATE_AVAILABLE:
       my_status = UPDATING;
       break;
-    case UpdateEngineClient::UPDATE_STATUS_NEED_PERMISSION_TO_UPDATE:
+    case update_engine::Operation::NEED_PERMISSION_TO_UPDATE:
       my_status = NEED_PERMISSION_TO_UPDATE;
       break;
-    case UpdateEngineClient::UPDATE_STATUS_VERIFYING:
-    case UpdateEngineClient::UPDATE_STATUS_FINALIZING:
+    case update_engine::Operation::VERIFYING:
+    case update_engine::Operation::FINALIZING:
       // Once the download is finished, keep the progress at 100; it shouldn't
       // go down while the status is the same.
       progress = 100;
       my_status = UPDATING;
       break;
-    case UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT:
+    case update_engine::Operation::UPDATED_NEED_REBOOT:
       my_status = NEARLY_UPDATED;
       break;
     default:
-      break;
+      NOTREACHED();
   }
 
-  callback_.Run(my_status, progress, status.is_rollback, version, size,
-                message);
-  last_operation_ = status.status;
+  callback_.Run(my_status, progress, status.is_enterprise_rollback(), version,
+                size, message);
+  last_operation_ = status.current_operation();
 
   if (check_for_update_when_idle_ &&
-      status.status == UpdateEngineClient::UPDATE_STATUS_IDLE) {
+      status.current_operation() == update_engine::Operation::IDLE) {
     CheckForUpdate(callback_, VersionUpdater::PromoteCallback());
   }
 }
diff --git a/chrome/browser/ui/webui/help/version_updater_chromeos.h b/chrome/browser/ui/webui/help/version_updater_chromeos.h
index 3ec0916..8af847e2 100644
--- a/chrome/browser/ui/webui/help/version_updater_chromeos.h
+++ b/chrome/browser/ui/webui/help/version_updater_chromeos.h
@@ -44,8 +44,7 @@
 
  private:
   // UpdateEngineClient::Observer implementation.
-  void UpdateStatusChanged(
-      const chromeos::UpdateEngineClient::Status& status) override;
+  void UpdateStatusChanged(const update_engine::StatusResult& status) override;
 
   // Callback from UpdateEngineClient::RequestUpdateCheck().
   void OnUpdateCheck(chromeos::UpdateEngineClient::UpdateCheckResult result);
@@ -69,7 +68,7 @@
   StatusCallback callback_;
 
   // Last state received via UpdateStatusChanged().
-  chromeos::UpdateEngineClient::UpdateStatusOperation last_operation_;
+  update_engine::Operation last_operation_;
 
   // True if an update check should be scheduled when the update engine is idle.
   bool check_for_update_when_idle_;
diff --git a/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc b/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc
index 850f225d3..5115ce9 100644
--- a/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc
+++ b/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc
@@ -116,8 +116,8 @@
   version_updater_->SetChannel("beta-channel", true);
 
   {
-    UpdateEngineClient::Status status;
-    status.status = UpdateEngineClient::UPDATE_STATUS_IDLE;
+    update_engine::StatusResult status;
+    status.set_current_operation(update_engine::Operation::IDLE);
     fake_update_engine_client_->set_default_status(status);
     fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
   }
@@ -130,9 +130,9 @@
   EXPECT_EQ(1, fake_update_engine_client_->request_update_check_call_count());
 
   {
-    UpdateEngineClient::Status status;
-    status.status = UpdateEngineClient::UPDATE_STATUS_DOWNLOADING;
-    status.download_progress = 0.1;
+    update_engine::StatusResult status;
+    status.set_current_operation(update_engine::Operation::DOWNLOADING);
+    status.set_progress(0.1);
     fake_update_engine_client_->set_default_status(status);
     fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
   }
@@ -142,8 +142,9 @@
   // DOWNLOADING -> REPORTING_ERROR_EVENT transition since target channel is not
   // equal to downloading channel now.
   {
-    UpdateEngineClient::Status status;
-    status.status = UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT;
+    update_engine::StatusResult status;
+    status.set_current_operation(
+        update_engine::Operation::REPORTING_ERROR_EVENT);
     fake_update_engine_client_->set_default_status(status);
     fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
   }
@@ -155,8 +156,8 @@
   // REPORTING_ERROR_EVENT -> IDLE transition, update check should be
   // automatically scheduled.
   {
-    UpdateEngineClient::Status status;
-    status.status = UpdateEngineClient::UPDATE_STATUS_IDLE;
+    update_engine::StatusResult status;
+    status.set_current_operation(update_engine::Operation::IDLE);
     fake_update_engine_client_->set_default_status(status);
     fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
   }
diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
index 2dcf1f8..2a0001c 100644
--- a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
+++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
@@ -135,9 +135,7 @@
 }  // namespace
 
 NTPResourceCache::NTPResourceCache(Profile* profile)
-    : profile_(profile),
-      is_swipe_tracking_from_scroll_events_enabled_(false),
-      theme_observer_(this) {
+    : profile_(profile), is_swipe_tracking_from_scroll_events_enabled_(false) {
   registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
                  content::Source<ThemeService>(
                      ThemeServiceFactory::GetForProfile(profile)));
diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache.h b/chrome/browser/ui/webui/ntp/ntp_resource_cache.h
index 354de3c..d6f96e8 100644
--- a/chrome/browser/ui/webui/ntp/ntp_resource_cache.h
+++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache.h
@@ -13,6 +13,7 @@
 #include "components/prefs/pref_change_registrar.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
+#include "ui/native_theme/native_theme.h"
 #include "ui/native_theme/native_theme_observer.h"
 
 class Profile;
@@ -26,10 +27,6 @@
 class RenderProcessHost;
 }
 
-namespace ui {
-class NativeTheme;
-}
-
 // This class keeps a cache of NTP resources (HTML and CSS) so we don't have to
 // regenerate them all the time.
 // Note: This is only used for incognito and guest mode NTPs (NewTabUI), as well
@@ -97,7 +94,8 @@
   // Set based on platform_util::IsSwipeTrackingFromScrollEventsEnabled.
   bool is_swipe_tracking_from_scroll_events_enabled_;
 
-  ScopedObserver<ui::NativeTheme, NTPResourceCache> theme_observer_;
+  ScopedObserver<ui::NativeTheme, ui::NativeThemeObserver> theme_observer_{
+      this};
 
   DISALLOW_COPY_AND_ASSIGN(NTPResourceCache);
 };
diff --git a/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc b/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc
index 577dc77..e19b1c95 100644
--- a/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc
@@ -59,8 +59,8 @@
 
 FingerprintHandler::FingerprintHandler(Profile* profile)
     : profile_(profile), binding_(this), session_observer_(this) {
-  content::GetSystemConnector()->BindInterface(device::mojom::kServiceName,
-                                               &fp_service_);
+  content::GetSystemConnector()->Connect(
+      device::mojom::kServiceName, fp_service_.BindNewPipeAndPassReceiver());
   user_id_ = ProfileHelper::Get()->GetUserIdHashFromProfile(profile);
 }
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.h b/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.h
index 766d8842..d654bf7 100644
--- a/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.h
@@ -10,6 +10,7 @@
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 #include "components/session_manager/core/session_manager_observer.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "services/device/public/mojom/fingerprint.mojom.h"
 
 class Profile;
@@ -79,7 +80,7 @@
   std::vector<std::string> fingerprints_paths_;
   std::string user_id_;
 
-  device::mojom::FingerprintPtr fp_service_;
+  mojo::Remote<device::mojom::Fingerprint> fp_service_;
   mojo::Binding<device::mojom::FingerprintObserver> binding_;
   ScopedObserver<session_manager::SessionManager,
                  session_manager::SessionManagerObserver>
diff --git a/chrome/browser/ui/webui/settings/font_handler.cc b/chrome/browser/ui/webui/settings/font_handler.cc
index 2c25ebed..ea1fb9f 100644
--- a/chrome/browser/ui/webui/settings/font_handler.cc
+++ b/chrome/browser/ui/webui/settings/font_handler.cc
@@ -21,7 +21,6 @@
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/font_list_async.h"
 #include "content/public/browser/web_ui.h"
-#include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/extension_urls.h"
 
@@ -39,7 +38,7 @@
 namespace settings {
 
 FontHandler::FontHandler(content::WebUI* webui)
-    : extension_registry_observer_(this), profile_(Profile::FromWebUI(webui)) {
+    : profile_(Profile::FromWebUI(webui)) {
 #if defined(OS_MACOSX)
   // Perform validation for saved fonts.
   settings_utils::ValidateSavedFonts(profile_->GetPrefs());
diff --git a/chrome/browser/ui/webui/settings/font_handler.h b/chrome/browser/ui/webui/settings/font_handler.h
index f88659d..3c0a284c 100644
--- a/chrome/browser/ui/webui/settings/font_handler.h
+++ b/chrome/browser/ui/webui/settings/font_handler.h
@@ -12,6 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observer.h"
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
+#include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_registry_observer.h"
 
 namespace base {
@@ -24,7 +25,6 @@
 
 namespace extensions {
 class Extension;
-class ExtensionRegistry;
 }
 
 class Profile;
@@ -71,7 +71,7 @@
 
   ScopedObserver<extensions::ExtensionRegistry,
                  extensions::ExtensionRegistryObserver>
-      extension_registry_observer_;
+      extension_registry_observer_{this};
 
   Profile* profile_;  // Weak pointer.
 
diff --git a/chrome/browser/ui/webui/settings/people_handler.cc b/chrome/browser/ui/webui/settings/people_handler.cc
index 9975d4a..176db09 100644
--- a/chrome/browser/ui/webui/settings/people_handler.cc
+++ b/chrome/browser/ui/webui/settings/people_handler.cc
@@ -44,7 +44,6 @@
 #include "components/strings/grit/components_strings.h"
 #include "components/sync/base/passphrase_enums.h"
 #include "components/sync/base/user_selectable_type.h"
-#include "components/sync/driver/sync_service.h"
 #include "components/sync/driver/sync_service_utils.h"
 #include "components/sync/driver/sync_user_settings.h"
 #include "components/unified_consent/feature.h"
@@ -261,11 +260,7 @@
 const char PeopleHandler::kPassphraseFailedPageStatus[] = "passphraseFailed";
 
 PeopleHandler::PeopleHandler(Profile* profile)
-    : profile_(profile),
-      configuring_sync_(false),
-      identity_manager_observer_(this),
-      sync_service_observer_(this) {
-}
+    : profile_(profile), configuring_sync_(false) {}
 
 PeopleHandler::~PeopleHandler() {
   // Early exit if running unit tests (no actual WebUI is attached).
@@ -1154,7 +1149,8 @@
 
   // We're done configuring, so notify SyncService that it is OK to start
   // syncing.
-  service->GetUserSettings()->SetFirstSetupComplete();
+  service->GetUserSettings()->SetFirstSetupComplete(
+      syncer::SyncFirstSetupCompleteSource::ADVANCED_FLOW_CONFIRM);
   FireWebUIListener("sync-settings-saved");
 }
 
diff --git a/chrome/browser/ui/webui/settings/people_handler.h b/chrome/browser/ui/webui/settings/people_handler.h
index 51e9195e..e60362b 100644
--- a/chrome/browser/ui/webui/settings/people_handler.h
+++ b/chrome/browser/ui/webui/settings/people_handler.h
@@ -22,6 +22,7 @@
 #include "components/prefs/pref_change_registrar.h"
 #include "components/signin/public/base/signin_buildflags.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
+#include "components/sync/driver/sync_service.h"
 #include "components/sync/driver/sync_service_observer.h"
 #include "content/public/browser/web_contents_observer.h"
 
@@ -36,7 +37,6 @@
 }  // namespace signin_metrics
 
 namespace syncer {
-class SyncService;
 class SyncSetupInProgressHandle;
 }  // namespace syncer
 
@@ -262,9 +262,10 @@
   PrefChangeRegistrar profile_pref_registrar_;
 
   // Manages observer lifetimes.
-  ScopedObserver<signin::IdentityManager, PeopleHandler>
-      identity_manager_observer_;
-  ScopedObserver<syncer::SyncService, PeopleHandler> sync_service_observer_;
+  ScopedObserver<signin::IdentityManager, signin::IdentityManager::Observer>
+      identity_manager_observer_{this};
+  ScopedObserver<syncer::SyncService, syncer::SyncServiceObserver>
+      sync_service_observer_{this};
 
 #if defined(OS_CHROMEOS)
   base::WeakPtrFactory<PeopleHandler> weak_factory_{this};
diff --git a/chrome/browser/ui/webui/settings/people_handler_unittest.cc b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
index 9cbc8b0..d3dee7a 100644
--- a/chrome/browser/ui/webui/settings/people_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
@@ -1308,8 +1308,9 @@
         NotifySyncStateChanged();
       });
   EXPECT_CALL(*mock_sync_service_->GetMockUserSettings(),
-              SetFirstSetupComplete())
-      .WillOnce([&]() {
+              SetFirstSetupComplete(
+                  syncer::SyncFirstSetupCompleteSource::ADVANCED_FLOW_CONFIRM))
+      .WillOnce([&](syncer::SyncFirstSetupCompleteSource) {
         ON_CALL(*mock_sync_service_->GetMockUserSettings(),
                 IsFirstSetupComplete())
             .WillByDefault(Return(true));
@@ -1373,9 +1374,11 @@
         NotifySyncStateChanged();
       });
   if (!browser_defaults::kSyncAutoStarts) {
-    EXPECT_CALL(*mock_sync_service_->GetMockUserSettings(),
-                SetFirstSetupComplete())
-        .WillOnce([&]() {
+    EXPECT_CALL(
+        *mock_sync_service_->GetMockUserSettings(),
+        SetFirstSetupComplete(
+            syncer::SyncFirstSetupCompleteSource::ADVANCED_FLOW_CONFIRM))
+        .WillOnce([&](syncer::SyncFirstSetupCompleteSource) {
           ON_CALL(*mock_sync_service_->GetMockUserSettings(),
                   IsFirstSetupComplete())
               .WillByDefault(Return(true));
diff --git a/chrome/browser/ui/webui/settings/profile_info_handler.cc b/chrome/browser/ui/webui/settings/profile_info_handler.cc
index f99ba77..ec91b3e 100644
--- a/chrome/browser/ui/webui/settings/profile_info_handler.cc
+++ b/chrome/browser/ui/webui/settings/profile_info_handler.cc
@@ -35,12 +35,7 @@
 const char ProfileInfoHandler::kProfileStatsCountReadyEventName[] =
     "profile-stats-count-ready";
 
-ProfileInfoHandler::ProfileInfoHandler(Profile* profile)
-    : profile_(profile),
-#if defined(OS_CHROMEOS)
-      user_manager_observer_(this),
-#endif
-      profile_observer_(this) {
+ProfileInfoHandler::ProfileInfoHandler(Profile* profile) : profile_(profile) {
 #if defined(OS_CHROMEOS)
   // Set up the chrome://userimage/ source.
   content::URLDataSource::Add(profile,
diff --git a/chrome/browser/ui/webui/settings/profile_info_handler.h b/chrome/browser/ui/webui/settings/profile_info_handler.h
index 1c40211..354c27d 100644
--- a/chrome/browser/ui/webui/settings/profile_info_handler.h
+++ b/chrome/browser/ui/webui/settings/profile_info_handler.h
@@ -74,12 +74,12 @@
   Profile* profile_;
 
 #if defined(OS_CHROMEOS)
-  ScopedObserver<user_manager::UserManager, ProfileInfoHandler>
-      user_manager_observer_;
+  ScopedObserver<user_manager::UserManager, user_manager::UserManager::Observer>
+      user_manager_observer_{this};
 #endif
 
-  ScopedObserver<ProfileAttributesStorage, ProfileInfoHandler>
-      profile_observer_;
+  ScopedObserver<ProfileAttributesStorage, ProfileAttributesStorage::Observer>
+      profile_observer_{this};
 
   // Used to cancel callbacks when JavaScript becomes disallowed.
   base::WeakPtrFactory<ProfileInfoHandler> callback_weak_ptr_factory_{this};
diff --git a/chrome/browser/ui/webui/settings/settings_manage_profile_handler.cc b/chrome/browser/ui/webui/settings/settings_manage_profile_handler.cc
index 40505a4..ce95eecb 100644
--- a/chrome/browser/ui/webui/settings/settings_manage_profile_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_manage_profile_handler.cc
@@ -48,7 +48,7 @@
 }  // namespace
 
 ManageProfileHandler::ManageProfileHandler(Profile* profile)
-    : profile_(profile), observer_(this) {}
+    : profile_(profile) {}
 
 ManageProfileHandler::~ManageProfileHandler() {}
 
diff --git a/chrome/browser/ui/webui/settings/settings_manage_profile_handler.h b/chrome/browser/ui/webui/settings/settings_manage_profile_handler.h
index 210f76c..fc5ebe7 100644
--- a/chrome/browser/ui/webui/settings/settings_manage_profile_handler.h
+++ b/chrome/browser/ui/webui/settings/settings_manage_profile_handler.h
@@ -88,7 +88,8 @@
   Profile* profile_;
 
   // Used to observe profile avatar updates.
-  ScopedObserver<ProfileAttributesStorage, ManageProfileHandler> observer_;
+  ScopedObserver<ProfileAttributesStorage, ProfileAttributesStorage::Observer>
+      observer_{this};
 
   // For generating weak pointers to itself for callbacks.
   base::WeakPtrFactory<ManageProfileHandler> weak_factory_{this};
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.cc b/chrome/browser/ui/webui/settings/site_settings_handler.cc
index f77694a..3ece18d 100644
--- a/chrome/browser/ui/webui/settings/site_settings_handler.cc
+++ b/chrome/browser/ui/webui/settings/site_settings_handler.cc
@@ -41,7 +41,6 @@
 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/content_settings/core/browser/website_settings_registry.h"
 #include "components/content_settings/core/common/content_settings_types.h"
 #include "components/content_settings/core/common/content_settings_utils.h"
@@ -311,8 +310,6 @@
 
 SiteSettingsHandler::SiteSettingsHandler(Profile* profile)
     : profile_(profile),
-      observer_(this),
-      chooser_observer_(this),
       pref_change_registrar_(nullptr) {}
 
 SiteSettingsHandler::~SiteSettingsHandler() {
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler.h b/chrome/browser/ui/webui/settings/site_settings_handler.h
index 04848c7..ed0eafa7 100644
--- a/chrome/browser/ui/webui/settings/site_settings_handler.h
+++ b/chrome/browser/ui/webui/settings/site_settings_handler.h
@@ -15,12 +15,12 @@
 #include "chrome/browser/permissions/chooser_context_base.h"
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 #include "components/content_settings/core/browser/content_settings_observer.h"
+#include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "content/public/browser/host_zoom_map.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "ppapi/buildflags/buildflags.h"
 
-class HostContentSettingsMap;
 class Profile;
 
 class PrefChangeRegistrar;
@@ -254,11 +254,12 @@
   std::string clearing_origin_;
 
   // Change observer for content settings.
-  ScopedObserver<HostContentSettingsMap, content_settings::Observer> observer_;
+  ScopedObserver<HostContentSettingsMap, content_settings::Observer> observer_{
+      this};
 
   // Change observer for chooser permissions.
   ScopedObserver<ChooserContextBase, ChooserContextBase::PermissionObserver>
-      chooser_observer_;
+      chooser_observer_{this};
 
   // Change observer for prefs.
   std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
diff --git a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc
index 0086f6c69..2bdfb2af 100644
--- a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc
+++ b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
@@ -104,7 +105,6 @@
                              KeyedServiceShutdownNotifier* shutdown_notifier,
                              base::OnceClosure callback)
       : identity_manager_(identity_manager),
-        scoped_identity_manager_observer_(this),
         callback_(std::move(callback)),
         shutdown_subscription_(shutdown_notifier->Subscribe(
             base::Bind(&TokensLoadedCallbackRunner::OnShutdown,
@@ -122,11 +122,13 @@
   void OnShutdown() { delete this; }
 
   signin::IdentityManager* identity_manager_;
-  ScopedObserver<signin::IdentityManager, TokensLoadedCallbackRunner>
-      scoped_identity_manager_observer_;
+  ScopedObserver<signin::IdentityManager, signin::IdentityManager::Observer>
+      scoped_identity_manager_observer_{this};
   base::OnceClosure callback_;
   std::unique_ptr<KeyedServiceShutdownNotifier::Subscription>
       shutdown_subscription_;
+
+  DISALLOW_COPY_AND_ASSIGN(TokensLoadedCallbackRunner);
 };
 
 }  // namespace
@@ -490,7 +492,8 @@
     case LoginUIService::SYNC_WITH_DEFAULT_SETTINGS: {
       syncer::SyncService* sync_service = GetSyncService();
       if (sync_service)
-        sync_service->GetUserSettings()->SetFirstSetupComplete();
+        sync_service->GetUserSettings()->SetFirstSetupComplete(
+            syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
       if (consent_service)
         consent_service->SetUrlKeyedAnonymizedDataCollectionEnabled(true);
       break;
diff --git a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_delegate_impl.cc b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_delegate_impl.cc
index 471ba9a..ab43eb0 100644
--- a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_delegate_impl.cc
+++ b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_delegate_impl.cc
@@ -90,16 +90,15 @@
 
 DiceTurnSyncOnHelperDelegateImpl::DiceTurnSyncOnHelperDelegateImpl(
     Browser* browser)
-    : browser_(browser),
-      profile_(browser_->profile()),
-      scoped_browser_list_observer_(this),
-      scoped_login_ui_service_observer_(this) {
+    : browser_(browser), profile_(browser_->profile()) {
   DCHECK(browser);
   DCHECK(profile_);
-  scoped_browser_list_observer_.Add(BrowserList::GetInstance());
+  BrowserList::AddObserver(this);
 }
 
-DiceTurnSyncOnHelperDelegateImpl::~DiceTurnSyncOnHelperDelegateImpl() {}
+DiceTurnSyncOnHelperDelegateImpl::~DiceTurnSyncOnHelperDelegateImpl() {
+  BrowserList::RemoveObserver(this);
+}
 
 void DiceTurnSyncOnHelperDelegateImpl::ShowLoginError(
     const std::string& email,
diff --git a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_delegate_impl.h b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_delegate_impl.h
index cbbce5c..61406114 100644
--- a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_delegate_impl.h
+++ b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_delegate_impl.h
@@ -14,7 +14,6 @@
 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
 
 class Browser;
-class BrowserList;
 class Profile;
 
 // Default implementation for DiceTurnSyncOnHelper::Delegate.
@@ -69,10 +68,8 @@
   Profile* profile_;
   base::OnceCallback<void(LoginUIService::SyncConfirmationUIClosedResult)>
       sync_confirmation_callback_;
-  ScopedObserver<BrowserList, BrowserListObserver>
-      scoped_browser_list_observer_;
   ScopedObserver<LoginUIService, LoginUIService::Observer>
-      scoped_login_ui_service_observer_;
+      scoped_login_ui_service_observer_{this};
 
   DISALLOW_COPY_AND_ASSIGN(DiceTurnSyncOnHelperDelegateImpl);
 };
diff --git a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc
index b3d3914..ba4e132 100644
--- a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc
+++ b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc
@@ -654,8 +654,9 @@
   // Set expectations.
   expected_sync_confirmation_shown_ = true;
   SetExpectationsForSyncStartupCompleted();
-  EXPECT_CALL(*GetMockSyncService()->GetMockUserSettings(),
-              SetFirstSetupComplete())
+  EXPECT_CALL(
+      *GetMockSyncService()->GetMockUserSettings(),
+      SetFirstSetupComplete(syncer::SyncFirstSetupCompleteSource::BASIC_FLOW))
       .Times(0);
 
   // Signin flow.
@@ -674,8 +675,9 @@
   expected_sync_confirmation_shown_ = true;
   expected_sync_settings_shown_ = true;
   SetExpectationsForSyncStartupCompleted();
-  EXPECT_CALL(*GetMockSyncService()->GetMockUserSettings(),
-              SetFirstSetupComplete())
+  EXPECT_CALL(
+      *GetMockSyncService()->GetMockUserSettings(),
+      SetFirstSetupComplete(syncer::SyncFirstSetupCompleteSource::BASIC_FLOW))
       .Times(0);
 
   // Configure the test.
@@ -696,8 +698,9 @@
   // Set expectations.
   expected_sync_confirmation_shown_ = true;
   SetExpectationsForSyncStartupCompleted();
-  EXPECT_CALL(*GetMockSyncService()->GetMockUserSettings(),
-              SetFirstSetupComplete())
+  EXPECT_CALL(
+      *GetMockSyncService()->GetMockUserSettings(),
+      SetFirstSetupComplete(syncer::SyncFirstSetupCompleteSource::BASIC_FLOW))
       .Times(1);
   // Configure the test.
   sync_confirmation_result_ = LoginUIService::SyncConfirmationUIClosedResult::
@@ -720,8 +723,9 @@
   sync_confirmation_result_ = LoginUIService::SyncConfirmationUIClosedResult::
       SYNC_WITH_DEFAULT_SETTINGS;
   SetExpectationsForSyncStartupCompleted();
-  EXPECT_CALL(*GetMockSyncService()->GetMockUserSettings(),
-              SetFirstSetupComplete())
+  EXPECT_CALL(
+      *GetMockSyncService()->GetMockUserSettings(),
+      SetFirstSetupComplete(syncer::SyncFirstSetupCompleteSource::BASIC_FLOW))
       .Times(1);
 
   // Signin flow.
@@ -744,8 +748,9 @@
   sync_confirmation_result_ = LoginUIService::SyncConfirmationUIClosedResult::
       SYNC_WITH_DEFAULT_SETTINGS;
   SetExpectationsForSyncStartupCompleted();
-  EXPECT_CALL(*GetMockSyncService()->GetMockUserSettings(),
-              SetFirstSetupComplete())
+  EXPECT_CALL(
+      *GetMockSyncService()->GetMockUserSettings(),
+      SetFirstSetupComplete(syncer::SyncFirstSetupCompleteSource::BASIC_FLOW))
       .Times(1);
   PrefService* pref_service = profile()->GetPrefs();
   std::unique_ptr<UrlKeyedDataCollectionConsentHelper>
@@ -792,8 +797,9 @@
 
   // Simulate that sync startup has completed.
   expected_sync_confirmation_shown_ = true;
-  EXPECT_CALL(*GetMockSyncService()->GetMockUserSettings(),
-              SetFirstSetupComplete())
+  EXPECT_CALL(
+      *GetMockSyncService()->GetMockUserSettings(),
+      SetFirstSetupComplete(syncer::SyncFirstSetupCompleteSource::BASIC_FLOW))
       .Times(1);
   sync_confirmation_result_ = LoginUIService::SyncConfirmationUIClosedResult::
       SYNC_WITH_DEFAULT_SETTINGS;
@@ -826,8 +832,9 @@
 
   // Simulate that sync startup has failed.
   expected_sync_confirmation_shown_ = true;
-  EXPECT_CALL(*GetMockSyncService()->GetMockUserSettings(),
-              SetFirstSetupComplete())
+  EXPECT_CALL(
+      *GetMockSyncService()->GetMockUserSettings(),
+      SetFirstSetupComplete(syncer::SyncFirstSetupCompleteSource::BASIC_FLOW))
       .Times(1);
   sync_confirmation_result_ = LoginUIService::SyncConfirmationUIClosedResult::
       SYNC_WITH_DEFAULT_SETTINGS;
diff --git a/chrome/browser/ui/webui/sync_internals_message_handler.cc b/chrome/browser/ui/webui/sync_internals_message_handler.cc
index 69dc7e8..40880e73d 100644
--- a/chrome/browser/ui/webui/sync_internals_message_handler.cc
+++ b/chrome/browser/ui/webui/sync_internals_message_handler.cc
@@ -311,7 +311,8 @@
   // If the service was previously stopped via StopAndClear(), then the
   // "first-setup-complete" bit was also cleared, and now the service wouldn't
   // fully start up. So set that too.
-  service->GetUserSettings()->SetFirstSetupComplete();
+  service->GetUserSettings()->SetFirstSetupComplete(
+      syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
 }
 
 void SyncInternalsMessageHandler::HandleRequestStopKeepData(
diff --git a/chrome/browser/ui/webui/theme_handler.cc b/chrome/browser/ui/webui/theme_handler.cc
index 033a87d..9c52ec07 100644
--- a/chrome/browser/ui/webui/theme_handler.cc
+++ b/chrome/browser/ui/webui/theme_handler.cc
@@ -16,14 +16,12 @@
 #include "chrome/grit/theme_resources.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/web_ui.h"
-#include "ui/native_theme/native_theme.h"
 
 ///////////////////////////////////////////////////////////////////////////////
 // ThemeHandler
 
-ThemeHandler::ThemeHandler() : theme_observer_(this) {}
-
-ThemeHandler::~ThemeHandler() {}
+ThemeHandler::ThemeHandler() = default;
+ThemeHandler::~ThemeHandler() = default;
 
 void ThemeHandler::RegisterMessages() {
   // These are not actual message registrations, but can't be done in the
diff --git a/chrome/browser/ui/webui/theme_handler.h b/chrome/browser/ui/webui/theme_handler.h
index 5e52e81d1..5de9784 100644
--- a/chrome/browser/ui/webui/theme_handler.h
+++ b/chrome/browser/ui/webui/theme_handler.h
@@ -10,6 +10,7 @@
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/web_ui_message_handler.h"
+#include "ui/native_theme/native_theme.h"
 #include "ui/native_theme/native_theme_observer.h"
 
 class Profile;
@@ -53,7 +54,8 @@
 
   content::NotificationRegistrar registrar_;
 
-  ScopedObserver<ui::NativeTheme, ThemeHandler> theme_observer_;
+  ScopedObserver<ui::NativeTheme, ui::NativeThemeObserver> theme_observer_{
+      this};
 
   DISALLOW_COPY_AND_ASSIGN(ThemeHandler);
 };
diff --git a/chrome/browser/unified_consent/unified_consent_browsertest.cc b/chrome/browser/unified_consent/unified_consent_browsertest.cc
index 97d414e..2ad7499 100644
--- a/chrome/browser/unified_consent/unified_consent_browsertest.cc
+++ b/chrome/browser/unified_consent/unified_consent_browsertest.cc
@@ -46,7 +46,8 @@
   }
 
   void FinishSyncSetup(int client_id) {
-    GetSyncService(client_id)->GetUserSettings()->SetFirstSetupComplete();
+    GetSyncService(client_id)->GetUserSettings()->SetFirstSetupComplete(
+        syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
     sync_blocker_.reset();
     ASSERT_TRUE(GetClient(client_id)->AwaitSyncSetupCompletion());
   }
diff --git a/chrome/browser/upgrade_detector/upgrade_detector_chromeos.cc b/chrome/browser/upgrade_detector/upgrade_detector_chromeos.cc
index f44257b..c089e0b1 100644
--- a/chrome/browser/upgrade_detector/upgrade_detector_chromeos.cc
+++ b/chrome/browser/upgrade_detector/upgrade_detector_chromeos.cc
@@ -260,14 +260,15 @@
 }
 
 void UpgradeDetectorChromeos::UpdateStatusChanged(
-    const UpdateEngineClient::Status& status) {
-  if (status.status == UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT) {
+    const update_engine::StatusResult& status) {
+  if (status.current_operation() ==
+      update_engine::Operation::UPDATED_NEED_REBOOT) {
     if (upgrade_detected_time().is_null()) {
       set_upgrade_detected_time(clock()->Now());
       CalculateDeadlines();
     }
 
-    if (status.is_rollback) {
+    if (status.is_enterprise_rollback()) {
       // Powerwash will be required, determine what kind of notification to show
       // based on the channel.
       ChannelsRequester::Begin(
@@ -280,8 +281,8 @@
       set_is_factory_reset_required(false);
       NotifyOnUpgrade();
     }
-  } else if (status.status ==
-             UpdateEngineClient::UPDATE_STATUS_NEED_PERMISSION_TO_UPDATE) {
+  } else if (status.current_operation() ==
+             update_engine::Operation::NEED_PERMISSION_TO_UPDATE) {
     // Update engine broadcasts this state only when update is available but
     // downloading over cellular connection requires user's agreement.
     NotifyUpdateOverCellularAvailable();
diff --git a/chrome/browser/upgrade_detector/upgrade_detector_chromeos.h b/chrome/browser/upgrade_detector/upgrade_detector_chromeos.h
index 3b1508c..5daf70e5 100644
--- a/chrome/browser/upgrade_detector/upgrade_detector_chromeos.h
+++ b/chrome/browser/upgrade_detector/upgrade_detector_chromeos.h
@@ -76,8 +76,7 @@
   void OnRelaunchNotificationPeriodPrefChanged() override;
 
   // chromeos::UpdateEngineClient::Observer implementation.
-  void UpdateStatusChanged(
-      const chromeos::UpdateEngineClient::Status& status) override;
+  void UpdateStatusChanged(const update_engine::StatusResult& status) override;
   void OnUpdateOverCellularOneTimePermissionGranted() override;
 
   // Triggers NotifyOnUpgrade if thresholds have been changed.
diff --git a/chrome/browser/upgrade_detector/upgrade_detector_chromeos_unittest.cc b/chrome/browser/upgrade_detector/upgrade_detector_chromeos_unittest.cc
index 699072c..a1d2e10 100644
--- a/chrome/browser/upgrade_detector/upgrade_detector_chromeos_unittest.cc
+++ b/chrome/browser/upgrade_detector/upgrade_detector_chromeos_unittest.cc
@@ -96,9 +96,8 @@
   void RunUntilIdle() { task_environment_.RunUntilIdle(); }
 
   void NotifyUpdateReadyToInstall() {
-    chromeos::UpdateEngineClient::Status status;
-    status.status =
-        chromeos::UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT;
+    update_engine::StatusResult status;
+    status.set_current_operation(update_engine::Operation::UPDATED_NEED_REBOOT);
     fake_update_engine_client_->set_default_status(status);
     fake_update_engine_client_->NotifyObserversThatStatusChanged(status);
   }
diff --git a/chrome/browser/web_applications/components/web_app_shortcut_win.cc b/chrome/browser/web_applications/components/web_app_shortcut_win.cc
index ee104da..1a11ed6 100644
--- a/chrome/browser/web_applications/components/web_app_shortcut_win.cc
+++ b/chrome/browser/web_applications/components/web_app_shortcut_win.cc
@@ -44,12 +44,6 @@
 constexpr base::FilePath::CharType kChromeProxyExecutable[] =
     FILE_PATH_LITERAL("chrome_proxy.exe");
 
-base::FilePath GetChromeProxyPath() {
-  base::FilePath chrome_dir;
-  CHECK(base::PathService::Get(base::DIR_EXE, &chrome_dir));
-  return chrome_dir.Append(kChromeProxyExecutable);
-}
-
 // Calculates checksum of an icon family using MD5.
 // The checksum is derived from all of the icons in the family.
 void GetImageCheckSum(const gfx::ImageFamily& image, base::MD5Digest* digest) {
@@ -195,7 +189,7 @@
     return false;
   }
 
-  base::FilePath chrome_proxy_path = GetChromeProxyPath();
+  base::FilePath chrome_proxy_path = web_app::GetChromeProxyPath();
 
   // Working directory.
   base::FilePath working_dir(chrome_proxy_path.DirName());
@@ -342,7 +336,7 @@
                                                     shortcut_info.extension_id,
                                                     shortcut_info.profile_path);
 
-  command_line.SetProgram(GetChromeProxyPath());
+  command_line.SetProgram(web_app::GetChromeProxyPath());
   ui::win::SetRelaunchDetailsForWindow(command_line.GetCommandLineString(),
                                        shortcut_info.title, hwnd);
 
@@ -357,6 +351,12 @@
 
 namespace web_app {
 
+base::FilePath GetChromeProxyPath() {
+  base::FilePath chrome_dir;
+  CHECK(base::PathService::Get(base::DIR_EXE, &chrome_dir));
+  return chrome_dir.Append(kChromeProxyExecutable);
+}
+
 namespace internals {
 
 void OnShortcutInfoLoadedForSetRelaunchDetails(
diff --git a/chrome/browser/web_applications/components/web_app_shortcut_win.h b/chrome/browser/web_applications/components/web_app_shortcut_win.h
index 83622a1d..9c292e9 100644
--- a/chrome/browser/web_applications/components/web_app_shortcut_win.h
+++ b/chrome/browser/web_applications/components/web_app_shortcut_win.h
@@ -11,6 +11,8 @@
 
 namespace web_app {
 
+base::FilePath GetChromeProxyPath();
+
 namespace internals {
 
 // Returns the Windows user-level shortcut paths that are specified in
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.cc b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
index 9ab2fb2..efd9413 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model.cc
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
@@ -141,8 +141,7 @@
 
 void AuthenticatorRequestDialogModel::
     StartGuidedFlowForMostLikelyTransportOrShowTransportSelection() {
-  DCHECK(current_step() == Step::kWelcomeScreen ||
-         current_step() == Step::kNotStarted);
+  DCHECK(current_step() == Step::kNotStarted);
 
   // If no authenticator other than the one for the native Windows API is
   // available, don't show Chrome UI but proceed straight to the native
@@ -175,7 +174,6 @@
     AuthenticatorTransport transport,
     bool pair_with_new_device_for_bluetooth_low_energy) {
   DCHECK(current_step() == Step::kTransportSelection ||
-         current_step() == Step::kWelcomeScreen ||
          current_step() == Step::kUsbInsertAndActivate ||
          current_step() == Step::kBleActivate ||
          current_step() == Step::kCableActivate ||
@@ -234,7 +232,6 @@
 void AuthenticatorRequestDialogModel::
     EnsureBleAdapterIsPoweredBeforeContinuingWithStep(Step next_step) {
   DCHECK(current_step() == Step::kTransportSelection ||
-         current_step() == Step::kWelcomeScreen ||
          current_step() == Step::kUsbInsertAndActivate ||
          current_step() == Step::kBleActivate ||
          current_step() == Step::kCableActivate ||
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.h b/chrome/browser/webauthn/authenticator_request_dialog_model.h
index aed3a525..1e35120f 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model.h
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model.h
@@ -48,7 +48,6 @@
     // The UX flow has not started yet, the dialog should still be hidden.
     kNotStarted,
 
-    kWelcomeScreen,
     kTransportSelection,
 
     // The request errored out before completing. Error will only be sent
@@ -176,8 +175,8 @@
     return ephemeral_state_.selected_authenticator_id_;
   }
 
-  // Starts the UX flow, by either showing the welcome screen, the transport
-  // selection screen, or the guided flow for them most likely transport.
+  // Starts the UX flow, by either showing the transport selection screen or
+  // the guided flow for them most likely transport.
   //
   // Valid action when at step: kNotStarted.
   void StartFlow(
@@ -193,13 +192,13 @@
   // transport selection screen if the transport could not be uniquely
   // identified.
   //
-  // Valid action when at step: kNotStarted, kWelcomeScreen.
+  // Valid action when at step: kNotStarted.
   void StartGuidedFlowForMostLikelyTransportOrShowTransportSelection();
 
   // Requests that the step-by-step wizard flow commence, guiding the user
   // through using the Secutity Key with the given |transport|.
   //
-  // Valid action when at step: kNotStarted, kWelcomeScreen,
+  // Valid action when at step: kNotStarted.
   // kTransportSelection, and steps where the other transports menu is shown,
   // namely, kUsbInsertAndActivate, kBleActivate, kCableActivate.
   void StartGuidedFlowForTransport(
@@ -216,9 +215,9 @@
   //     then advanced to the flow to turn on Bluetooth automatically.
   //  -- Otherwise advanced to the manual Bluetooth power on flow.
   //
-  // Valid action when at step: kNotStarted, kWelcomeScreen,
-  // kTransportSelection, and steps where the other transports menu is shown,
-  // namely, kUsbInsertAndActivate, kBleActivate, kCableActivate.
+  // Valid action when at step: kNotStarted, kTransportSelection, and steps
+  // where the other transports menu is shown, namely, kUsbInsertAndActivate,
+  // kBleActivate, kCableActivate.
   void EnsureBleAdapterIsPoweredBeforeContinuingWithStep(Step step);
 
   // Continues with the BLE/caBLE flow now that the Bluetooth adapter is
diff --git a/chrome/installer/mini_installer/pe_resource.cc b/chrome/installer/mini_installer/pe_resource.cc
index ce63627d..4d9873e9 100644
--- a/chrome/installer/mini_installer/pe_resource.cc
+++ b/chrome/installer/mini_installer/pe_resource.cc
@@ -4,17 +4,19 @@
 
 #include "chrome/installer/mini_installer/pe_resource.h"
 
+#include <algorithm>
+
 PEResource::PEResource(HRSRC resource, HMODULE module)
     : resource_(resource), module_(module) {
 }
 
 PEResource::PEResource(const wchar_t* name, const wchar_t* type, HMODULE module)
-    : resource_(NULL), module_(module) {
+    : resource_(nullptr), module_(module) {
   resource_ = ::FindResource(module, name, type);
 }
 
 bool PEResource::IsValid() {
-  return (NULL != resource_);
+  return nullptr != resource_;
 }
 
 size_t PEResource::Size() {
@@ -23,26 +25,35 @@
 
 bool PEResource::WriteToDisk(const wchar_t* full_path) {
   // Resource handles are not real HGLOBALs so do not attempt to close them.
-  // Windows frees them whenever there is memory pressure.
+  // Resources are freed when the containing module is unloaded.
   HGLOBAL data_handle = ::LoadResource(module_, resource_);
-  if (NULL == data_handle) {
+  if (nullptr == data_handle)
     return false;
-  }
-  void* data = ::LockResource(data_handle);
-  if (NULL == data) {
+
+  const char* data = reinterpret_cast<const char*>(::LockResource(data_handle));
+  if (nullptr == data)
     return false;
-  }
-  size_t resource_size = Size();
-  HANDLE out_file = ::CreateFile(full_path, GENERIC_WRITE, 0, NULL,
-                                  CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
-  if (INVALID_HANDLE_VALUE == out_file) {
+
+  const size_t resource_size = Size();
+  HANDLE out_file = ::CreateFile(full_path, GENERIC_WRITE, 0, nullptr,
+                                 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
+  if (INVALID_HANDLE_VALUE == out_file)
     return false;
-  }
-  DWORD written = 0;
-  if (!::WriteFile(out_file, data, static_cast<DWORD>(resource_size),
-                   &written, NULL)) {
+
+  // Don't write all of the data at once because this can lead to kernel
+  // address-space exhaustion on 32-bit Windows (see https://crbug.com/1001022
+  // for details).
+  constexpr size_t kMaxWriteAmount = 8 * 1024 * 1024;
+  for (size_t total_written = 0; total_written < resource_size; /**/) {
+    const size_t write_amount =
+        std::min(kMaxWriteAmount, resource_size - total_written);
+    DWORD written = 0;
+    if (!::WriteFile(out_file, data + total_written,
+                     static_cast<DWORD>(write_amount), &written, nullptr)) {
       ::CloseHandle(out_file);
       return false;
+    }
+    total_written += write_amount;
   }
   return ::CloseHandle(out_file) ? true : false;
 }
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 3d78245..b1e76726 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -139,6 +139,7 @@
 #include "third_party/blink/public/web/web_plugin_container.h"
 #include "third_party/blink/public/web/web_plugin_params.h"
 #include "third_party/blink/public/web/web_security_policy.h"
+#include "third_party/blink/public/web/web_view.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/layout.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -713,12 +714,13 @@
     content::RenderFrame* render_frame,
     bool has_played_media_before,
     base::OnceClosure closure) {
-  // Don't allow autoplay/autoload of media resources in a RenderFrame that is
-  // hidden and has never played any media before.  We want to allow future
-  // loads even when hidden to allow playlist-like functionality.
+  // Don't allow autoplay/autoload of media resources in a page that is hidden
+  // and has never played any media before.  We want to allow future loads even
+  // when hidden to allow playlist-like functionality.
   //
   // NOTE: This is also used to defer media loading for prerender.
-  if ((render_frame->IsHidden() && !has_played_media_before) ||
+  if ((render_frame->GetRenderView()->GetWebView()->IsHidden() &&
+       !has_played_media_before) ||
       prerender::PrerenderHelper::IsPrerendering(render_frame)) {
     new MediaLoadDeferrer(render_frame, std::move(closure));
     return true;
diff --git a/chrome/services/cups_proxy/ipp_validator.cc b/chrome/services/cups_proxy/ipp_validator.cc
index 3eda616..748426f 100644
--- a/chrome/services/cups_proxy/ipp_validator.cc
+++ b/chrome/services/cups_proxy/ipp_validator.cc
@@ -80,6 +80,14 @@
   return 0;
 }
 
+// Returns true if |data| starts with the full |prefix|, false otherwise.
+bool StartsWith(base::span<uint8_t const> data,
+                base::span<uint8_t const> prefix) {
+  if (data.size() < prefix.size())
+    return false;
+  return std::equal(data.begin(), data.begin() + prefix.size(), prefix.begin());
+}
+
 }  // namespace
 
 // Verifies that |method|, |endpoint|, and |http_version| form a valid HTTP
@@ -257,24 +265,16 @@
   return ipp.release();
 }
 
-// Requires IPP data portion is either empty or looks like a pdf.
+// Requires |ipp_data| to be empty or look like a PDF or PostScript document.
 bool IppValidator::ValidateIppData(const std::vector<uint8_t>& ipp_data) {
-  const int pdf_magic_bytes_size = 4;
-  constexpr std::array<uint8_t, pdf_magic_bytes_size> pdf_magic_bytes = {
-      0x25, 0x50, 0x44, 0x46};  // { %PDF }
-
   // Empty IPP data portion.
   if (ipp_data.empty()) {
     return true;
   }
 
-  if (ipp_data.size() < pdf_magic_bytes_size) {
-    return false;
-  }
-
-  // Check that |ipp_data| starts with pdf_magic_bytes.
-  return std::equal(ipp_data.begin(), ipp_data.begin() + pdf_magic_bytes_size,
-                    pdf_magic_bytes.begin());
+  // Check if |ipp_data| looks like a PDF or PostScript document.
+  return StartsWith(ipp_data, pdf_magic_bytes) ||
+         StartsWith(ipp_data, ps_magic_bytes);
 }
 
 IppValidator::IppValidator(CupsProxyServiceDelegate* const delegate)
diff --git a/chrome/services/cups_proxy/ipp_validator_unittest.cc b/chrome/services/cups_proxy/ipp_validator_unittest.cc
index f954d9953..d27c4ff 100644
--- a/chrome/services/cups_proxy/ipp_validator_unittest.cc
+++ b/chrome/services/cups_proxy/ipp_validator_unittest.cc
@@ -11,6 +11,7 @@
 #include <utility>
 
 #include "chrome/services/cups_proxy/fake_cups_proxy_service_delegate.h"
+#include "chrome/services/cups_proxy/public/cpp/cups_util.h"
 #include "chrome/services/cups_proxy/public/cpp/ipp_messages.h"
 #include "printing/backend/cups_ipp_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -196,6 +197,22 @@
   EXPECT_FALSE(ippFindAttribute(ipp, fake_attr_name.c_str(), IPP_TAG_TEXT));
 }
 
+TEST_F(IppValidatorTest, IppDataVerification) {
+  auto request = GetBasicIppRequest();
+
+  // Should fail since the data too short to be a valid document.
+  request->data = {0x0};
+  EXPECT_FALSE(RunValidateIppRequest(request));
+
+  // Valid PDF.
+  request->data = {pdf_magic_bytes.begin(), pdf_magic_bytes.end()};
+  EXPECT_TRUE(RunValidateIppRequest(request));
+
+  // Valid PS.
+  request->data = {ps_magic_bytes.begin(), ps_magic_bytes.end()};
+  EXPECT_TRUE(RunValidateIppRequest(request));
+}
+
 // TODO(crbug.com/945409): Test IPP validation.
 
 }  // namespace
diff --git a/chrome/services/cups_proxy/public/cpp/cups_util.h b/chrome/services/cups_proxy/public/cpp/cups_util.h
index c33ad60..50444cc 100644
--- a/chrome/services/cups_proxy/public/cpp/cups_util.h
+++ b/chrome/services/cups_proxy/public/cpp/cups_util.h
@@ -27,6 +27,12 @@
 // Note: This is assumed to be stable.
 static const size_t kHttpMaxBufferSize = 2048;
 
+// PDF and PostScript document format identifiers.
+constexpr std::array<uint8_t, 5> pdf_magic_bytes = {0x25, 0x50, 0x44, 0x46,
+                                                    0x2d};  // { %PDF- }
+constexpr std::array<uint8_t, 4> ps_magic_bytes = {0x25, 0x21, 0x50,
+                                                   0x53};  // { %!PS }
+
 // Expects |request| to be an IPP_OP_GET_PRINTERS IPP request. This function
 // creates an appropriate IPP response referencing |printers|.
 // TODO(crbug.com/945409): Expand testing suite.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index fb9416040..ccb51e3 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -505,6 +505,10 @@
       "//testing/android/native_test:native_test_support",
     ]
 
+    data_deps = [
+      "//testing/buildbot/filters:android_browsertests_filters",
+    ]
+
     sources = [
       "../browser/engagement/important_sites_util_browsertest.cc",
       "../browser/payments/has_enrolled_instrument_browsertest.cc",
@@ -3073,10 +3077,10 @@
     "../browser/performance_manager/mechanisms/working_set_trimmer_win_unittest.cc",
     "../browser/performance_manager/observers/isolation_context_metrics_unittest.cc",
     "../browser/performance_manager/observers/metrics_collector_unittest.cc",
+    "../browser/performance_manager/performance_manager_impl_unittest.cc",
     "../browser/performance_manager/performance_manager_tab_helper_unittest.cc",
     "../browser/performance_manager/performance_manager_test_harness.cc",
     "../browser/performance_manager/performance_manager_test_harness.h",
-    "../browser/performance_manager/performance_manager_unittest.cc",
     "../browser/performance_manager/persistence/site_data/exponential_moving_average_unittest.cc",
     "../browser/performance_manager/persistence/site_data/leveldb_site_data_store_unittest.cc",
     "../browser/performance_manager/persistence/site_data/non_recording_site_data_cache_unittest.cc",
diff --git a/chrome/test/base/browser_with_test_window_test.h b/chrome/test/base/browser_with_test_window_test.h
index a287bb16..a8226f86 100644
--- a/chrome/test/base/browser_with_test_window_test.h
+++ b/chrome/test/base/browser_with_test_window_test.h
@@ -81,7 +81,7 @@
 
     // TODO(alexclarke): Make content::BrowserTaskEnvironment::ValidTraits
     // imply this.
-    explicit ValidTraits(base::test::TaskEnvironment::ValidTrait);
+    explicit ValidTraits(base::test::TaskEnvironment::ValidTraits);
   };
 
   // Creates a BrowserWithTestWindowTest with zero or more traits. By default
diff --git a/chrome/updater/win/installer/pe_resource.cc b/chrome/updater/win/installer/pe_resource.cc
index 248a133..c7b2a1b 100644
--- a/chrome/updater/win/installer/pe_resource.cc
+++ b/chrome/updater/win/installer/pe_resource.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/updater/win/installer/pe_resource.h"
 
+#include <algorithm>
+
 namespace updater {
 
 PEResource::PEResource(const wchar_t* name, const wchar_t* type, HMODULE module)
@@ -21,26 +23,35 @@
 
 bool PEResource::WriteToDisk(const wchar_t* full_path) {
   // Resource handles are not real HGLOBALs so do not attempt to close them.
-  // Windows frees them whenever there is memory pressure.
+  // Resources are freed when the containing module is unloaded.
   HGLOBAL data_handle = ::LoadResource(module_, resource_);
   if (nullptr == data_handle)
     return false;
 
-  void* data = ::LockResource(data_handle);
+  const char* data = reinterpret_cast<const char*>(::LockResource(data_handle));
   if (nullptr == data)
     return false;
 
-  size_t resource_size = Size();
+  const size_t resource_size = Size();
   HANDLE out_file = ::CreateFile(full_path, GENERIC_WRITE, 0, nullptr,
                                  CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
   if (INVALID_HANDLE_VALUE == out_file)
     return false;
 
-  DWORD written = 0;
-  if (!::WriteFile(out_file, data, static_cast<DWORD>(resource_size), &written,
-                   nullptr)) {
-    ::CloseHandle(out_file);
-    return false;
+  // Don't write all of the data at once because this can lead to kernel
+  // address-space exhaustion on 32-bit Windows (see https://crbug.com/1001022
+  // for details).
+  constexpr size_t kMaxWriteAmount = 8 * 1024 * 1024;
+  for (size_t total_written = 0; total_written < resource_size; /**/) {
+    const size_t write_amount =
+        std::min(kMaxWriteAmount, resource_size - total_written);
+    DWORD written = 0;
+    if (!::WriteFile(out_file, data + total_written,
+                     static_cast<DWORD>(write_amount), &written, nullptr)) {
+      ::CloseHandle(out_file);
+      return false;
+    }
+    total_written += write_amount;
   }
   return ::CloseHandle(out_file) ? true : false;
 }
diff --git a/chrome/utility/image_writer/image_writer_unittest.cc b/chrome/utility/image_writer/image_writer_unittest.cc
index 05ec705..bab93243 100644
--- a/chrome/utility/image_writer/image_writer_unittest.cc
+++ b/chrome/utility/image_writer/image_writer_unittest.cc
@@ -55,7 +55,7 @@
   base::FilePath device_path_;
 
  private:
-  base::test::TaskEnvironment task_environment_;
+  base::test::SingleThreadTaskEnvironment task_environment_;
   base::ScopedTempDir temp_dir_;
 };
 
diff --git a/chromecast/base/bind_to_task_runner_unittest.cc b/chromecast/base/bind_to_task_runner_unittest.cc
index 51cfb44..15bed7f 100644
--- a/chromecast/base/bind_to_task_runner_unittest.cc
+++ b/chromecast/base/bind_to_task_runner_unittest.cc
@@ -50,7 +50,7 @@
  public:
   ~BindToTaskRunnerTest() override { base::RunLoop().RunUntilIdle(); }
 
-  base::test::TaskEnvironment task_environment_;
+  base::test::SingleThreadTaskEnvironment task_environment_;
   MockCallbacks callbacks_;
 };
 
diff --git a/chromecast/external_mojo/external_service_support/BUILD.gn b/chromecast/external_mojo/external_service_support/BUILD.gn
index 8006a1d..a2da73ca 100644
--- a/chromecast/external_mojo/external_service_support/BUILD.gn
+++ b/chromecast/external_mojo/external_service_support/BUILD.gn
@@ -4,8 +4,9 @@
 
 source_set("external_service") {
   sources = [
-    "external_connector.cc",
     "external_connector.h",
+    "external_connector_impl.cc",
+    "external_connector_impl.h",
     "external_service.cc",
     "external_service.h",
   ]
diff --git a/chromecast/external_mojo/external_service_support/external_connector.h b/chromecast/external_mojo/external_service_support/external_connector.h
index ac41af79..94a3310 100644
--- a/chromecast/external_mojo/external_service_support/external_connector.h
+++ b/chromecast/external_mojo/external_service_support/external_connector.h
@@ -11,8 +11,6 @@
 #include <vector>
 
 #include "base/callback.h"
-#include "base/macros.h"
-#include "base/sequence_checker.h"
 #include "chromecast/external_mojo/public/mojom/connector.mojom.h"
 #include "mojo/public/cpp/bindings/interface_ptr.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
@@ -34,27 +32,22 @@
       const std::string& broker_path,
       base::OnceCallback<void(std::unique_ptr<ExternalConnector>)> callback);
 
-  explicit ExternalConnector(
-      external_mojo::mojom::ExternalConnectorPtr connector);
-  explicit ExternalConnector(
-      external_mojo::mojom::ExternalConnectorPtrInfo unbound_state);
-  ~ExternalConnector();
+  virtual ~ExternalConnector() = default;
 
   // Sets the callback that will be called if this class loses its connection to
   // the Mojo broker. Note that once the connection is lost, this instance
   // becomes nonfunctional (all public methods are no-ops); a new connection
   // must be made instead.
-  void set_connection_error_callback(base::OnceClosure callback) {
-    connection_error_callback_ = std::move(callback);
-  }
+  virtual void SetConnectionErrorCallback(base::OnceClosure callback) = 0;
 
   // Registers a service that other Mojo processes/services can bind to. Others
   // can call BindInterface(|service_name|, interface_name) to bind to this
   // |service|.
-  void RegisterService(const std::string& service_name,
-                       ExternalService* service);
-  void RegisterService(const std::string& service_name,
-                       external_mojo::mojom::ExternalServicePtr service_ptr);
+  virtual void RegisterService(const std::string& service_name,
+                               ExternalService* service) = 0;
+  virtual void RegisterService(
+      const std::string& service_name,
+      external_mojo::mojom::ExternalServicePtr service_ptr) = 0;
 
   // Asks the Mojo broker to bind to a matching interface on the service with
   // the given |service_name|. If the service does not yet exist, the binding
@@ -66,37 +59,26 @@
                   mojo::MakeRequest(ptr).PassMessagePipe());
   }
 
-  void BindInterface(const std::string& service_name,
-                     const std::string& interface_name,
-                     mojo::ScopedMessagePipeHandle interface_pipe);
+  virtual void BindInterface(const std::string& service_name,
+                             const std::string& interface_name,
+                             mojo::ScopedMessagePipeHandle interface_pipe) = 0;
 
   // Creates a new instance of this class which may be passed to another thread.
   // The returned object may be passed across sequences until any of its public
   // methods are called, at which point it becomes bound to the calling
   // sequence.
-  std::unique_ptr<ExternalConnector> Clone();
+  virtual std::unique_ptr<ExternalConnector> Clone() = 0;
 
   // Sends a request for a Chromium ServiceManager connector.
-  void SendChromiumConnectorRequest(mojo::ScopedMessagePipeHandle request);
+  virtual void SendChromiumConnectorRequest(
+      mojo::ScopedMessagePipeHandle request) = 0;
 
   // Query the list of available services from this connector.
-  void QueryServiceList(
+  virtual void QueryServiceList(
       base::OnceCallback<
           void(std::vector<
                chromecast::external_mojo::mojom::ExternalServiceInfoPtr>)>
-          callback);
-
- private:
-  void OnConnectionError();
-  bool BindConnectorIfNecessary();
-
-  external_mojo::mojom::ExternalConnectorPtr connector_;
-  external_mojo::mojom::ExternalConnectorPtrInfo unbound_state_;
-  base::OnceClosure connection_error_callback_;
-
-  SEQUENCE_CHECKER(sequence_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(ExternalConnector);
+          callback) = 0;
 };
 
 }  // namespace external_service_support
diff --git a/chromecast/external_mojo/external_service_support/external_connector.cc b/chromecast/external_mojo/external_service_support/external_connector_impl.cc
similarity index 78%
rename from chromecast/external_mojo/external_service_support/external_connector.cc
rename to chromecast/external_mojo/external_service_support/external_connector_impl.cc
index e92a3d1..844c244 100644
--- a/chromecast/external_mojo/external_service_support/external_connector.cc
+++ b/chromecast/external_mojo/external_service_support/external_connector_impl.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chromecast/external_mojo/external_service_support/external_connector.h"
+#include "chromecast/external_mojo/external_service_support/external_connector_impl.h"
 
 #include "base/bind.h"
 #include "base/location.h"
@@ -53,30 +53,35 @@
   external_mojo::mojom::ExternalConnectorPtr connector(
       external_mojo::mojom::ExternalConnectorPtrInfo(std::move(pipe), 0));
   std::move(callback).Run(
-      std::make_unique<ExternalConnector>(std::move(connector)));
+      std::make_unique<ExternalConnectorImpl>(std::move(connector)));
 }
 
-ExternalConnector::ExternalConnector(
+ExternalConnectorImpl::ExternalConnectorImpl(
     external_mojo::mojom::ExternalConnectorPtr connector)
     : connector_(std::move(connector)) {
   connector_.set_connection_error_handler(base::BindOnce(
-      &ExternalConnector::OnConnectionError, base::Unretained(this)));
+      &ExternalConnectorImpl::OnConnectionError, base::Unretained(this)));
 }
 
-ExternalConnector::ExternalConnector(
+ExternalConnectorImpl::ExternalConnectorImpl(
     external_mojo::mojom::ExternalConnectorPtrInfo unbound_state)
     : unbound_state_(std::move(unbound_state)) {
   DETACH_FROM_SEQUENCE(sequence_checker_);
 }
 
-ExternalConnector::~ExternalConnector() = default;
+ExternalConnectorImpl::~ExternalConnectorImpl() = default;
 
-void ExternalConnector::RegisterService(const std::string& service_name,
-                                        ExternalService* service) {
+void ExternalConnectorImpl::SetConnectionErrorCallback(
+    base::OnceClosure callback) {
+  connection_error_callback_ = std::move(callback);
+}
+
+void ExternalConnectorImpl::RegisterService(const std::string& service_name,
+                                            ExternalService* service) {
   RegisterService(service_name, service->GetBinding());
 }
 
-void ExternalConnector::RegisterService(
+void ExternalConnectorImpl::RegisterService(
     const std::string& service_name,
     external_mojo::mojom::ExternalServicePtr service_ptr) {
   if (BindConnectorIfNecessary()) {
@@ -84,7 +89,7 @@
   }
 }
 
-void ExternalConnector::QueryServiceList(
+void ExternalConnectorImpl::QueryServiceList(
     base::OnceCallback<void(
         std::vector<chromecast::external_mojo::mojom::ExternalServiceInfoPtr>)>
         callback) {
@@ -93,7 +98,7 @@
   }
 }
 
-void ExternalConnector::BindInterface(
+void ExternalConnectorImpl::BindInterface(
     const std::string& service_name,
     const std::string& interface_name,
     mojo::ScopedMessagePipeHandle interface_pipe) {
@@ -103,23 +108,23 @@
   }
 }
 
-std::unique_ptr<ExternalConnector> ExternalConnector::Clone() {
+std::unique_ptr<ExternalConnector> ExternalConnectorImpl::Clone() {
   external_mojo::mojom::ExternalConnectorPtrInfo connector_info;
   auto request = mojo::MakeRequest(&connector_info);
   if (BindConnectorIfNecessary()) {
     connector_->Clone(std::move(request));
   }
-  return std::make_unique<ExternalConnector>(std::move(connector_info));
+  return std::make_unique<ExternalConnectorImpl>(std::move(connector_info));
 }
 
-void ExternalConnector::SendChromiumConnectorRequest(
+void ExternalConnectorImpl::SendChromiumConnectorRequest(
     mojo::ScopedMessagePipeHandle request) {
   if (BindConnectorIfNecessary()) {
     connector_->BindChromiumConnector(std::move(request));
   }
 }
 
-void ExternalConnector::OnConnectionError() {
+void ExternalConnectorImpl::OnConnectionError() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   connector_.reset();
   if (connection_error_callback_) {
@@ -127,7 +132,7 @@
   }
 }
 
-bool ExternalConnector::BindConnectorIfNecessary() {
+bool ExternalConnectorImpl::BindConnectorIfNecessary() {
   // Bind the message pipe and SequenceChecker to the current thread the first
   // time it is used to connect.
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -142,7 +147,7 @@
 
   connector_.Bind(std::move(unbound_state_));
   connector_.set_connection_error_handler(base::BindOnce(
-      &ExternalConnector::OnConnectionError, base::Unretained(this)));
+      &ExternalConnectorImpl::OnConnectionError, base::Unretained(this)));
 
   return true;
 }
diff --git a/chromecast/external_mojo/external_service_support/external_connector_impl.h b/chromecast/external_mojo/external_service_support/external_connector_impl.h
new file mode 100644
index 0000000..8684934c
--- /dev/null
+++ b/chromecast/external_mojo/external_service_support/external_connector_impl.h
@@ -0,0 +1,63 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_EXTERNAL_MOJO_EXTERNAL_SERVICE_SUPPORT_EXTERNAL_CONNECTOR_IMPL_H_
+#define CHROMECAST_EXTERNAL_MOJO_EXTERNAL_SERVICE_SUPPORT_EXTERNAL_CONNECTOR_IMPL_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/sequence_checker.h"
+#include "chromecast/external_mojo/external_service_support/external_connector.h"
+
+namespace chromecast {
+namespace external_service_support {
+
+class ExternalConnectorImpl : public ExternalConnector {
+ public:
+  explicit ExternalConnectorImpl(
+      external_mojo::mojom::ExternalConnectorPtr connector);
+  explicit ExternalConnectorImpl(
+      external_mojo::mojom::ExternalConnectorPtrInfo unbound_state);
+  ~ExternalConnectorImpl() override;
+
+  // ExternalConnector implementation:
+  void SetConnectionErrorCallback(base::OnceClosure callback) override;
+  void RegisterService(const std::string& service_name,
+                       ExternalService* service) override;
+  void RegisterService(
+      const std::string& service_name,
+      external_mojo::mojom::ExternalServicePtr service_ptr) override;
+  void BindInterface(const std::string& service_name,
+                     const std::string& interface_name,
+                     mojo::ScopedMessagePipeHandle interface_pipe) override;
+  std::unique_ptr<ExternalConnector> Clone() override;
+  void SendChromiumConnectorRequest(
+      mojo::ScopedMessagePipeHandle request) override;
+  void QueryServiceList(
+      base::OnceCallback<
+          void(std::vector<
+               chromecast::external_mojo::mojom::ExternalServiceInfoPtr>)>
+          callback) override;
+
+ private:
+  void OnConnectionError();
+  bool BindConnectorIfNecessary();
+
+  external_mojo::mojom::ExternalConnectorPtr connector_;
+  external_mojo::mojom::ExternalConnectorPtrInfo unbound_state_;
+  base::OnceClosure connection_error_callback_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
+
+  DISALLOW_COPY_AND_ASSIGN(ExternalConnectorImpl);
+};
+
+}  // namespace external_service_support
+}  // namespace chromecast
+
+#endif  // CHROMECAST_EXTERNAL_MOJO_EXTERNAL_SERVICE_SUPPORT_EXTERNAL_CONNECTOR_IMPL_H_
diff --git a/chromeos/dbus/BUILD.gn b/chromeos/dbus/BUILD.gn
index 2deb98f1..15430db 100644
--- a/chromeos/dbus/BUILD.gn
+++ b/chromeos/dbus/BUILD.gn
@@ -30,6 +30,7 @@
     ":runtime_probe_proto",
     ":seneschal_proto",
     ":smbprovider_proto",
+    ":update_engine_proto",
     ":vm_applications_apps_proto",
     ":vm_plugin_dispatcher_proto",
     "//base",
@@ -309,6 +310,14 @@
   proto_out_dir = "chromeos/dbus/smbprovider"
 }
 
+proto_library("update_engine_proto") {
+  sources = [
+    "//third_party/cros_system_api/dbus/update_engine/update_engine.proto",
+  ]
+
+  proto_out_dir = "chromeos/dbus/update_engine"
+}
+
 proto_library("vm_applications_apps_proto") {
   sources = [
     "//third_party/cros_system_api/dbus/vm_applications/apps.proto",
diff --git a/chromeos/dbus/fake_update_engine_client.cc b/chromeos/dbus/fake_update_engine_client.cc
index d3d64342..3037b771 100644
--- a/chromeos/dbus/fake_update_engine_client.cc
+++ b/chromeos/dbus/fake_update_engine_client.cc
@@ -54,17 +54,17 @@
   reboot_after_update_call_count_++;
 }
 
-UpdateEngineClient::Status FakeUpdateEngineClient::GetLastStatus() {
+update_engine::StatusResult FakeUpdateEngineClient::GetLastStatus() {
   if (status_queue_.empty())
     return default_status_;
 
-  UpdateEngineClient::Status last_status = status_queue_.front();
+  update_engine::StatusResult last_status = status_queue_.front();
   status_queue_.pop();
   return last_status;
 }
 
 void FakeUpdateEngineClient::NotifyObserversThatStatusChanged(
-    const UpdateEngineClient::Status& status) {
+    const update_engine::StatusResult& status) {
   for (auto& observer : observers_)
     observer.UpdateStatusChanged(status);
 }
@@ -107,7 +107,7 @@
 }
 
 void FakeUpdateEngineClient::set_default_status(
-    const UpdateEngineClient::Status& status) {
+    const update_engine::StatusResult& status) {
   default_status_ = status;
 }
 
diff --git a/chromeos/dbus/fake_update_engine_client.h b/chromeos/dbus/fake_update_engine_client.h
index e60a1b4..40a379d 100644
--- a/chromeos/dbus/fake_update_engine_client.h
+++ b/chromeos/dbus/fake_update_engine_client.h
@@ -32,7 +32,7 @@
   void RebootAfterUpdate() override;
   void Rollback() override;
   void CanRollbackCheck(const RollbackCheckCallback& callback) override;
-  Status GetLastStatus() override;
+  update_engine::StatusResult GetLastStatus() override;
   void SetChannel(const std::string& target_channel,
                   bool is_powerwash_allowed) override;
   void GetChannel(bool get_current_channel,
@@ -44,23 +44,24 @@
       const std::string& target_version,
       int64_t target_size,
       const UpdateOverCellularOneTimePermissionCallback& callback) override;
-  // Pushes UpdateEngineClient::Status in the queue to test changing status.
+  // Pushes update_engine::StatusResult in the queue to test changing status.
   // GetLastStatus() returns the status set by this method in FIFO order.
   // See set_default_status().
-  void PushLastStatus(const UpdateEngineClient::Status& status) {
+  void PushLastStatus(const update_engine::StatusResult& status) {
     status_queue_.push(status);
   }
 
   // Sends status change notification.
   void NotifyObserversThatStatusChanged(
-      const UpdateEngineClient::Status& status);
+      const update_engine::StatusResult& status);
 
   // Notifies observers that the user's one time permission is granted.
   void NotifyUpdateOverCellularOneTimePermissionGranted();
 
-  // Sets the default UpdateEngineClient::Status. GetLastStatus() returns the
+  // Sets the default update_engine::StatusResult. GetLastStatus() returns the
   // value set here if |status_queue_| is empty.
-  void set_default_status(const UpdateEngineClient::Status& status);
+
+  void set_default_status(const update_engine::StatusResult& status);
 
   // Sets a value returned by RequestUpdateCheck().
   void set_update_check_result(
@@ -88,8 +89,8 @@
 
  private:
   base::ObserverList<Observer>::Unchecked observers_;
-  base::queue<UpdateEngineClient::Status> status_queue_;
-  UpdateEngineClient::Status default_status_;
+  base::queue<update_engine::StatusResult> status_queue_;
+  update_engine::StatusResult default_status_;
   UpdateEngineClient::UpdateCheckResult update_check_result_;
   bool can_rollback_stub_result_;
   int reboot_after_update_call_count_;
diff --git a/chromeos/dbus/update_engine_client.cc b/chromeos/dbus/update_engine_client.cc
index 910872d..5425ea62 100644
--- a/chromeos/dbus/update_engine_client.cc
+++ b/chromeos/dbus/update_engine_client.cc
@@ -56,33 +56,6 @@
 // Version number of the image being installed during fake AU.
 const char kStubVersion[] = "1234.0.0.0";
 
-// Returns UPDATE_STATUS_ERROR on error.
-UpdateEngineClient::UpdateStatusOperation UpdateStatusFromString(
-    const std::string& str) {
-  VLOG(1) << "UpdateStatusFromString got " << str << " as input.";
-  if (str == update_engine::kUpdateStatusIdle)
-    return UpdateEngineClient::UPDATE_STATUS_IDLE;
-  if (str == update_engine::kUpdateStatusCheckingForUpdate)
-    return UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE;
-  if (str == update_engine::kUpdateStatusUpdateAvailable)
-    return UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE;
-  if (str == update_engine::kUpdateStatusDownloading)
-    return UpdateEngineClient::UPDATE_STATUS_DOWNLOADING;
-  if (str == update_engine::kUpdateStatusVerifying)
-    return UpdateEngineClient::UPDATE_STATUS_VERIFYING;
-  if (str == update_engine::kUpdateStatusFinalizing)
-    return UpdateEngineClient::UPDATE_STATUS_FINALIZING;
-  if (str == update_engine::kUpdateStatusUpdatedNeedReboot)
-    return UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT;
-  if (str == update_engine::kUpdateStatusReportingErrorEvent)
-    return UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT;
-  if (str == update_engine::kUpdateStatusAttemptingRollback)
-    return UpdateEngineClient::UPDATE_STATUS_ATTEMPTING_ROLLBACK;
-  if (str == update_engine::kUpdateStatusNeedPermissionToUpdate)
-    return UpdateEngineClient::UPDATE_STATUS_NEED_PERMISSION_TO_UPDATE;
-  return UpdateEngineClient::UPDATE_STATUS_ERROR;
-}
-
 bool IsValidChannel(const std::string& channel) {
   return channel == kReleaseChannelDev || channel == kReleaseChannelBeta ||
          channel == kReleaseChannelStable;
@@ -175,7 +148,7 @@
                        weak_ptr_factory_.GetWeakPtr(), callback));
   }
 
-  Status GetLastStatus() override { return last_status_; }
+  update_engine::StatusResult GetLastStatus() override { return last_status_; }
 
   void SetChannel(const std::string& target_channel,
                   bool is_powerwash_allowed) override {
@@ -274,7 +247,8 @@
         update_engine::kUpdateEngineServiceName,
         dbus::ObjectPath(update_engine::kUpdateEngineServicePath));
     update_engine_proxy_->ConnectToSignal(
-        update_engine::kUpdateEngineInterface, update_engine::kStatusUpdate,
+        update_engine::kUpdateEngineInterface,
+        update_engine::kStatusUpdateAdvanced,
         base::Bind(&UpdateEngineClientImpl::StatusUpdateReceived,
                    weak_ptr_factory_.GetWeakPtr()),
         base::BindOnce(&UpdateEngineClientImpl::StatusUpdateConnected,
@@ -296,8 +270,8 @@
 
       // Get update engine status for the initial status. Update engine won't
       // send StatusUpdate signal unless there is a status change. If chrome
-      // crashes after UPDATE_STATUS_UPDATED_NEED_REBOOT status is set,
-      // restarted chrome would not get this status. See crbug.com/154104.
+      // crashes after UPDATED_NEED_REBOOT status is set, restarted chrome would
+      // not get this status. See crbug.com/154104.
       GetUpdateEngineStatus();
     } else {
       LOG(ERROR) << "Failed to wait for D-Bus service to become available";
@@ -306,9 +280,10 @@
   }
 
   void GetUpdateEngineStatus() {
-    dbus::MethodCall method_call(
-        update_engine::kUpdateEngineInterface,
-        update_engine::kGetStatus);
+    // TODO(crbug.com/977320): Rename the method call back to GetStatus() after
+    // the interface changed.
+    dbus::MethodCall method_call(update_engine::kUpdateEngineInterface,
+                                 update_engine::kGetStatusAdvanced);
     update_engine_proxy_->CallMethodWithErrorCallback(
         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::BindOnce(&UpdateEngineClientImpl::OnGetStatus,
@@ -371,27 +346,21 @@
     }
 
     dbus::MessageReader reader(response);
-    std::string current_operation;
-    Status status;
-    if (!(reader.PopInt64(&status.last_checked_time) &&
-          reader.PopDouble(&status.download_progress) &&
-          reader.PopString(&current_operation) &&
-          reader.PopString(&status.new_version) &&
-          reader.PopInt64(&status.new_size))) {
-      LOG(ERROR) << "GetStatus had incorrect response: "
-                 << response->ToString();
+    update_engine::StatusResult status;
+    if (!reader.PopArrayOfBytesAsProto(&status)) {
+      LOG(ERROR) << "Failed to parse proto from DBus Response.";
       return;
     }
-    status.status = UpdateStatusFromString(current_operation);
-    // TODO(hunyadym, https://crbug.com/864672): Add a new DBus call to
-    // determine this based on the Omaha response, and not version comparison.
+
+    // TODO(https://crbug.com/864672): Use GetStatus to determine this based on
+    // the Omaha response, and not version comparison.
     const std::string current_version =
         version_loader::GetVersion(version_loader::VERSION_SHORT);
-    status.is_rollback =
-        version_loader::IsRollback(current_version, status.new_version);
-    if (status.is_rollback) {
+    status.set_is_enterprise_rollback(
+        version_loader::IsRollback(current_version, status.new_version()));
+    if (status.is_enterprise_rollback()) {
       LOG(WARNING) << "New image is a rollback from " << current_version
-                   << " to " << status.new_version << ".";
+                   << " to " << status.new_version() << ".";
     }
 
     last_status_ = status;
@@ -513,38 +482,23 @@
   void StatusUpdateReceived(dbus::Signal* signal) {
     VLOG(1) << "Status update signal received: " << signal->ToString();
     dbus::MessageReader reader(signal);
-    int64_t last_checked_time = 0;
-    double progress = 0.0;
-    std::string current_operation;
-    std::string new_version;
-    int64_t new_size = 0;
-    if (!(reader.PopInt64(&last_checked_time) &&
-          reader.PopDouble(&progress) &&
-          reader.PopString(&current_operation) &&
-          reader.PopString(&new_version) &&
-          reader.PopInt64(&new_size))) {
-      LOG(ERROR) << "Status changed signal had incorrect parameters: "
-                 << signal->ToString();
+    update_engine::StatusResult status;
+    if (!reader.PopArrayOfBytesAsProto(&status)) {
+      LOG(ERROR) << "Failed to parse proto from DBus Response.";
       return;
     }
-    Status status;
-    status.last_checked_time = last_checked_time;
-    status.download_progress = progress;
-    status.status = UpdateStatusFromString(current_operation);
-    status.new_version = new_version;
-    // TODO(hunyadym, https://crbug.com/864672): Add a new DBus call to
-    // determine this based on the Omaha response, and not version comparison.
+
+    // TODO(https://crbug.com/864672): Use GetStatus to determine this based on
+    // the Omaha response, and not version comparison.
     const std::string current_version =
         version_loader::GetVersion(version_loader::VERSION_SHORT);
-    status.is_rollback =
-        version_loader::IsRollback(current_version, status.new_version);
-    if (status.is_rollback) {
+    status.set_is_enterprise_rollback(
+        version_loader::IsRollback(current_version, status.new_version()));
+    if (status.is_enterprise_rollback()) {
       LOG(WARNING) << "New image is a rollback from " << current_version
-                   << " to " << new_version << ".";
+                   << " to " << status.new_version() << ".";
     }
 
-    status.new_size = new_size;
-
     last_status_ = status;
     for (auto& observer : observers_)
       observer.UpdateStatusChanged(status);
@@ -560,7 +514,7 @@
 
   dbus::ObjectProxy* update_engine_proxy_;
   base::ObserverList<Observer>::Unchecked observers_;
-  Status last_status_;
+  update_engine::StatusResult last_status_;
 
   // True after update_engine's D-Bus service has become available.
   bool service_available_ = false;
@@ -600,17 +554,18 @@
   }
 
   void RequestUpdateCheck(const UpdateCheckCallback& callback) override {
-    if (last_status_.status != UPDATE_STATUS_IDLE) {
+    if (last_status_.current_operation() != update_engine::Operation::IDLE) {
       callback.Run(UPDATE_RESULT_FAILED);
       return;
     }
     callback.Run(UPDATE_RESULT_SUCCESS);
-    last_status_.status = UPDATE_STATUS_CHECKING_FOR_UPDATE;
-    last_status_.download_progress = 0.0;
-    last_status_.last_checked_time = 0;
-    last_status_.new_version = "0.0.0.0";
-    last_status_.new_size = 0;
-    last_status_.is_rollback = false;
+    last_status_.set_current_operation(
+        update_engine::Operation::CHECKING_FOR_UPDATE);
+    last_status_.set_progress(0.0);
+    last_status_.set_last_checked_time(0);
+    last_status_.set_new_version("0.0.0.0");
+    last_status_.set_new_size(0);
+    last_status_.set_is_enterprise_rollback(false);
     base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
         FROM_HERE,
         base::BindOnce(&UpdateEngineClientStubImpl::StateTransition,
@@ -626,7 +581,7 @@
     callback.Run(true);
   }
 
-  Status GetLastStatus() override { return last_status_; }
+  update_engine::StatusResult GetLastStatus() override { return last_status_; }
 
   void SetChannel(const std::string& target_channel,
                   bool is_powerwash_allowed) override {
@@ -662,44 +617,47 @@
 
  private:
   void StateTransition() {
-    UpdateStatusOperation next_status = UPDATE_STATUS_ERROR;
+    update_engine::Operation next_operation = update_engine::Operation::ERROR;
     int delay_ms = kStateTransitionDefaultDelayMs;
-    switch (last_status_.status) {
-      case UPDATE_STATUS_ERROR:
-      case UPDATE_STATUS_IDLE:
-      case UPDATE_STATUS_UPDATED_NEED_REBOOT:
-      case UPDATE_STATUS_REPORTING_ERROR_EVENT:
-      case UPDATE_STATUS_ATTEMPTING_ROLLBACK:
-      case UPDATE_STATUS_NEED_PERMISSION_TO_UPDATE:
+    switch (last_status_.current_operation()) {
+      case update_engine::Operation::ERROR:
+      case update_engine::Operation::IDLE:
+      case update_engine::Operation::UPDATED_NEED_REBOOT:
+      case update_engine::Operation::REPORTING_ERROR_EVENT:
+      case update_engine::Operation::ATTEMPTING_ROLLBACK:
+      case update_engine::Operation::NEED_PERMISSION_TO_UPDATE:
+      case update_engine::Operation::DISABLED:
         return;
-      case UPDATE_STATUS_CHECKING_FOR_UPDATE:
-        next_status = UPDATE_STATUS_UPDATE_AVAILABLE;
+      case update_engine::Operation::CHECKING_FOR_UPDATE:
+        next_operation = update_engine::Operation::UPDATE_AVAILABLE;
         break;
-      case UPDATE_STATUS_UPDATE_AVAILABLE:
-        next_status = UPDATE_STATUS_DOWNLOADING;
+      case update_engine::Operation::UPDATE_AVAILABLE:
+        next_operation = update_engine::Operation::DOWNLOADING;
         break;
-      case UPDATE_STATUS_DOWNLOADING:
-        if (last_status_.download_progress >= 1.0) {
-          next_status = UPDATE_STATUS_VERIFYING;
+      case update_engine::Operation::DOWNLOADING:
+        if (last_status_.progress() >= 1.0) {
+          next_operation = update_engine::Operation::VERIFYING;
         } else {
-          next_status = UPDATE_STATUS_DOWNLOADING;
-          last_status_.download_progress += 0.01;
-          last_status_.new_version = kStubVersion;
-          last_status_.new_size = kDownloadSizeDelta;
+          next_operation = update_engine::Operation::DOWNLOADING;
+          last_status_.set_progress(last_status_.progress() + 0.01);
+          last_status_.set_new_version(kStubVersion);
+          last_status_.set_new_size(kDownloadSizeDelta);
           delay_ms = kStateTransitionDownloadingDelayMs;
         }
         break;
-      case UPDATE_STATUS_VERIFYING:
-        next_status = UPDATE_STATUS_FINALIZING;
+      case update_engine::Operation::VERIFYING:
+        next_operation = update_engine::Operation::FINALIZING;
         break;
-      case UPDATE_STATUS_FINALIZING:
-        next_status = UPDATE_STATUS_UPDATED_NEED_REBOOT;
+      case update_engine::Operation::FINALIZING:
+        next_operation = update_engine::Operation::UPDATED_NEED_REBOOT;
         break;
+      default:
+        NOTREACHED();
     }
-    last_status_.status = next_status;
+    last_status_.set_current_operation(next_operation);
     for (auto& observer : observers_)
       observer.UpdateStatusChanged(last_status_);
-    if (last_status_.status != UPDATE_STATUS_IDLE) {
+    if (last_status_.current_operation() != update_engine::Operation::IDLE) {
       base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
           FROM_HERE,
           base::BindOnce(&UpdateEngineClientStubImpl::StateTransition,
@@ -713,7 +671,7 @@
   std::string current_channel_;
   std::string target_channel_;
 
-  Status last_status_;
+  update_engine::StatusResult last_status_;
 
   base::WeakPtrFactory<UpdateEngineClientStubImpl> weak_factory_{this};
 
diff --git a/chromeos/dbus/update_engine_client.h b/chromeos/dbus/update_engine_client.h
index d1641a3..32bc056 100644
--- a/chromeos/dbus/update_engine_client.h
+++ b/chromeos/dbus/update_engine_client.h
@@ -16,6 +16,7 @@
 #include "base/optional.h"
 #include "chromeos/dbus/dbus_client.h"
 #include "chromeos/dbus/dbus_client_implementation_type.h"
+#include "chromeos/dbus/update_engine/update_engine.pb.h"
 #include "dbus/message.h"
 #include "third_party/cros_system_api/dbus/update_engine/dbus-constants.h"
 
@@ -24,44 +25,6 @@
 // UpdateEngineClient is used to communicate with the update engine.
 class COMPONENT_EXPORT(CHROMEOS_DBUS) UpdateEngineClient : public DBusClient {
  public:
-  // Edges for state machine
-  //    IDLE->CHECKING_FOR_UPDATE
-  //    CHECKING_FOR_UPDATE->IDLE
-  //    CHECKING_FOR_UPDATE->UPDATE_AVAILABLE
-  //    CHECKING_FOR_UPDATE->NEED_PERMISSION_TO_UPDATE
-  //    ...
-  //    FINALIZING->UPDATE_NEED_REBOOT
-  // Any state can transition to REPORTING_ERROR_EVENT and then on to IDLE.
-  enum UpdateStatusOperation {
-    UPDATE_STATUS_ERROR = -1,
-    UPDATE_STATUS_IDLE = 0,
-    UPDATE_STATUS_CHECKING_FOR_UPDATE,
-    UPDATE_STATUS_UPDATE_AVAILABLE,
-    // User permission is needed to download an update on a cellular connection.
-    UPDATE_STATUS_NEED_PERMISSION_TO_UPDATE,
-    UPDATE_STATUS_DOWNLOADING,
-    UPDATE_STATUS_VERIFYING,
-    UPDATE_STATUS_FINALIZING,
-    UPDATE_STATUS_UPDATED_NEED_REBOOT,
-    UPDATE_STATUS_REPORTING_ERROR_EVENT,
-    UPDATE_STATUS_ATTEMPTING_ROLLBACK,
-  };
-
-  // The status of the ongoing update attempt.
-  struct Status {
-    UpdateStatusOperation status = UPDATE_STATUS_IDLE;
-    // 0.0 - 1.0
-    double download_progress = 0.0;
-    // As reported by std::time().
-    int64_t last_checked_time = 0;
-    std::string new_version;
-    // Valid during DOWNLOADING, in bytes.
-    int64_t new_size = 0;
-    // True if the update is actually a rollback and the device will be wiped
-    // when rebooted.
-    bool is_rollback = false;
-  };
-
   // The result code used for RequestUpdateCheck().
   enum UpdateCheckResult {
     UPDATE_RESULT_SUCCESS,
@@ -75,7 +38,8 @@
     virtual ~Observer() {}
 
     // Called when the status is updated.
-    virtual void UpdateStatusChanged(const Status& status) {}
+    virtual void UpdateStatusChanged(
+        const update_engine::StatusResult& status) {}
 
     // Called when the user's one time permission on update over cellular
     // connection has been granted.
@@ -120,7 +84,7 @@
   //
   // Ideally, the D-Bus client should be state-less, but there are clients
   // that need this information.
-  virtual Status GetLastStatus() = 0;
+  virtual update_engine::StatusResult GetLastStatus() = 0;
 
   // Changes the current channel of the device to the target
   // channel. If the target channel is a less stable channel than the
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.cc b/chromeos/services/assistant/assistant_manager_service_impl.cc
index add6520..4c0ae1f 100644
--- a/chromeos/services/assistant/assistant_manager_service_impl.cc
+++ b/chromeos/services/assistant/assistant_manager_service_impl.cc
@@ -127,7 +127,7 @@
 
 AssistantManagerServiceImpl::AssistantManagerServiceImpl(
     mojom::Client* client,
-    device::mojom::BatteryMonitorPtr battery_monitor,
+    mojo::PendingRemote<device::mojom::BatteryMonitor> battery_monitor,
     Service* service,
     std::unique_ptr<network::SharedURLLoaderFactoryInfo>
         url_loader_factory_info)
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.h b/chromeos/services/assistant/assistant_manager_service_impl.h
index f7a56ab..50f18ce 100644
--- a/chromeos/services/assistant/assistant_manager_service_impl.h
+++ b/chromeos/services/assistant/assistant_manager_service_impl.h
@@ -26,6 +26,7 @@
 #include "libassistant/shared/public/device_state_listener.h"
 #include "libassistant/shared/public/media_manager.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote_set.h"
 #include "services/device/public/mojom/battery_monitor.mojom.h"
@@ -91,7 +92,7 @@
   // |service| owns this class and must outlive this class.
   AssistantManagerServiceImpl(
       mojom::Client* client,
-      device::mojom::BatteryMonitorPtr battery_monitor,
+      mojo::PendingRemote<device::mojom::BatteryMonitor> battery_monitor,
       Service* service,
       std::unique_ptr<network::SharedURLLoaderFactoryInfo>
           url_loader_factory_info);
diff --git a/chromeos/services/assistant/chromium_http_connection.cc b/chromeos/services/assistant/chromium_http_connection.cc
index 0e2d07f..cfde911e 100644
--- a/chromeos/services/assistant/chromium_http_connection.cc
+++ b/chromeos/services/assistant/chromium_http_connection.cc
@@ -12,6 +12,7 @@
 
 #include "base/logging.h"
 #include "base/task/post_task.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
 #include "net/base/load_flags.h"
 #include "services/network/public/cpp/header_util.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -167,10 +168,11 @@
       !chunked_upload_content_type_.empty() && method_ == Method::POST;
   if (chunked_upload) {
     // Attach a chunked upload body.
-    network::mojom::ChunkedDataPipeGetterPtr data_pipe;
-    binding_set_.AddBinding(this, mojo::MakeRequest(&data_pipe));
+    mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter> data_remote;
+    receiver_set_.Add(this, data_remote.InitWithNewPipeAndPassReceiver());
     resource_request->request_body = new network::ResourceRequestBody();
-    resource_request->request_body->SetToChunkedDataPipe(std::move(data_pipe));
+    resource_request->request_body->SetToChunkedDataPipe(
+        std::move(data_remote));
   }
 
   url_loader_ = network::SimpleURLLoader::Create(std::move(resource_request),
diff --git a/chromeos/services/assistant/chromium_http_connection.h b/chromeos/services/assistant/chromium_http_connection.h
index 0abf0ce..dd904dc 100644
--- a/chromeos/services/assistant/chromium_http_connection.h
+++ b/chromeos/services/assistant/chromium_http_connection.h
@@ -15,7 +15,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/sequenced_task_runner.h"
 #include "libassistant/shared/internal_api/http_connection.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
 #include "net/http/http_request_headers.h"
 #include "services/network/public/cpp/resource_response.h"
 #include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
@@ -107,7 +107,7 @@
   std::unique_ptr<mojo::SimpleWatcher> upload_pipe_watcher_;
   // If non-null, invoked once the size of the upload is known.
   network::mojom::ChunkedDataPipeGetter::GetSizeCallback get_size_callback_;
-  mojo::BindingSet<network::mojom::ChunkedDataPipeGetter> binding_set_;
+  mojo::ReceiverSet<network::mojom::ChunkedDataPipeGetter> receiver_set_;
 
   // Parameters to be set before Start() call.
   GURL url_;
diff --git a/chromeos/services/assistant/platform/system_provider_impl.cc b/chromeos/services/assistant/platform/system_provider_impl.cc
index 02606ae..2051c53 100644
--- a/chromeos/services/assistant/platform/system_provider_impl.cc
+++ b/chromeos/services/assistant/platform/system_provider_impl.cc
@@ -18,7 +18,7 @@
 
 SystemProviderImpl::SystemProviderImpl(
     std::unique_ptr<PowerManagerProviderImpl> power_manager_provider,
-    device::mojom::BatteryMonitorPtr battery_monitor)
+    mojo::PendingRemote<device::mojom::BatteryMonitor> battery_monitor)
     : power_manager_provider_(std::move(power_manager_provider)),
       battery_monitor_(std::move(battery_monitor)) {
   battery_monitor_->QueryNextStatus(base::BindOnce(
diff --git a/chromeos/services/assistant/platform/system_provider_impl.h b/chromeos/services/assistant/platform/system_provider_impl.h
index c5e16aa..6e43a240 100644
--- a/chromeos/services/assistant/platform/system_provider_impl.h
+++ b/chromeos/services/assistant/platform/system_provider_impl.h
@@ -11,6 +11,8 @@
 #include "base/component_export.h"
 #include "base/macros.h"
 #include "libassistant/shared/public/platform_system.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "services/device/public/mojom/battery_monitor.mojom.h"
 #include "services/device/public/mojom/battery_status.mojom.h"
 
@@ -26,7 +28,7 @@
   // platform power manager provider is available.
   SystemProviderImpl(
       std::unique_ptr<PowerManagerProviderImpl> power_manager_provider,
-      device::mojom::BatteryMonitorPtr battery_monitor);
+      mojo::PendingRemote<device::mojom::BatteryMonitor> battery_monitor);
   ~SystemProviderImpl() override;
 
   // assistant_client::SystemProvider implementation:
@@ -45,7 +47,7 @@
 
   std::unique_ptr<PowerManagerProviderImpl> power_manager_provider_;
 
-  device::mojom::BatteryMonitorPtr battery_monitor_;
+  mojo::Remote<device::mojom::BatteryMonitor> battery_monitor_;
   device::mojom::BatteryStatusPtr current_battery_status_;
 
   DISALLOW_COPY_AND_ASSIGN(SystemProviderImpl);
diff --git a/chromeos/services/assistant/platform/system_provider_impl_unittest.cc b/chromeos/services/assistant/platform/system_provider_impl_unittest.cc
index 412c670..f883e4b 100644
--- a/chromeos/services/assistant/platform/system_provider_impl_unittest.cc
+++ b/chromeos/services/assistant/platform/system_provider_impl_unittest.cc
@@ -11,7 +11,7 @@
 #include "base/test/task_environment.h"
 #include "chromeos/services/assistant/fake_client.h"
 #include "chromeos/services/assistant/platform/power_manager_provider_impl.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 #include "services/device/public/mojom/battery_monitor.mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -20,12 +20,10 @@
 
 class FakeBatteryMonitor : device::mojom::BatteryMonitor {
  public:
-  FakeBatteryMonitor() : binding_(this) {}
+  FakeBatteryMonitor() = default;
 
-  device::mojom::BatteryMonitorPtr CreateInterfacePtrAndBind() {
-    device::mojom::BatteryMonitorPtr ptr;
-    binding_.Bind(mojo::MakeRequest(&ptr));
-    return ptr;
+  mojo::PendingRemote<device::mojom::BatteryMonitor> CreateRemoteAndBind() {
+    return receiver_.BindNewPipeAndPassRemote();
   }
 
   void QueryNextStatus(QueryNextStatusCallback callback) override {
@@ -53,7 +51,7 @@
   device::mojom::BatteryStatusPtr battery_status_;
   QueryNextStatusCallback callback_;
 
-  mojo::Binding<device::mojom::BatteryMonitor> binding_;
+  mojo::Receiver<device::mojom::BatteryMonitor> receiver_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeBatteryMonitor);
 };
@@ -69,7 +67,7 @@
     system_provider_impl_ = std::make_unique<SystemProviderImpl>(
         std::make_unique<PowerManagerProviderImpl>(
             &fake_client_, task_environment_.GetMainThreadTaskRunner()),
-        battery_monitor_.CreateInterfacePtrAndBind());
+        battery_monitor_.CreateRemoteAndBind());
     FlushForTesting();
   }
 
diff --git a/chromeos/services/assistant/platform_api_impl.cc b/chromeos/services/assistant/platform_api_impl.cc
index 5b33b49..d0d7924 100644
--- a/chromeos/services/assistant/platform_api_impl.cc
+++ b/chromeos/services/assistant/platform_api_impl.cc
@@ -79,7 +79,7 @@
 PlatformApiImpl::PlatformApiImpl(
     mojom::Client* client,
     AssistantMediaSession* media_session,
-    device::mojom::BatteryMonitorPtr battery_monitor,
+    mojo::PendingRemote<device::mojom::BatteryMonitor> battery_monitor,
     scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> background_task_runner,
     std::string pref_locale)
diff --git a/chromeos/services/assistant/platform_api_impl.h b/chromeos/services/assistant/platform_api_impl.h
index f0dfd3b5..b019aab 100644
--- a/chromeos/services/assistant/platform_api_impl.h
+++ b/chromeos/services/assistant/platform_api_impl.h
@@ -19,6 +19,7 @@
 #include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
 #include "libassistant/shared/public/platform_api.h"
 #include "libassistant/shared/public/platform_auth.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
 #include "services/device/public/mojom/battery_monitor.mojom.h"
 
 namespace chromeos {
@@ -33,7 +34,7 @@
   PlatformApiImpl(
       mojom::Client* client,
       AssistantMediaSession* media_session,
-      device::mojom::BatteryMonitorPtr battery_monitor,
+      mojo::PendingRemote<device::mojom::BatteryMonitor> battery_monitor,
       scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> background_task_runner,
       std::string pref_locale);
diff --git a/chromeos/services/assistant/service.cc b/chromeos/services/assistant/service.cc
index 828bcb3..74595ae 100644
--- a/chromeos/services/assistant/service.cc
+++ b/chromeos/services/assistant/service.cc
@@ -387,8 +387,9 @@
 
   DCHECK(client_);
 
-  device::mojom::BatteryMonitorPtr battery_monitor;
-  client_->RequestBatteryMonitor(mojo::MakeRequest(&battery_monitor));
+  mojo::PendingRemote<device::mojom::BatteryMonitor> battery_monitor;
+  client_->RequestBatteryMonitor(
+      battery_monitor.InitWithNewPipeAndPassReceiver());
 
   // |assistant_manager_service_| is only created once.
   DCHECK(url_loader_factory_info_);
diff --git a/components/autofill/content/browser/risk/fingerprint.cc b/components/autofill/content/browser/risk/fingerprint.cc
index 925fd90..7da8a13 100644
--- a/components/autofill/content/browser/risk/fingerprint.cc
+++ b/components/autofill/content/browser/risk/fingerprint.cc
@@ -40,6 +40,7 @@
 #include "content/public/common/webplugininfo.h"
 #include "gpu/config/gpu_info.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "ppapi/buildflags/buildflags.h"
 #include "services/device/public/cpp/geolocation/geoposition.h"
 #include "services/device/public/mojom/constants.mojom.h"
@@ -241,7 +242,7 @@
   std::vector<content::WebPluginInfo> plugins_;
   bool waiting_on_plugins_;
   device::mojom::Geoposition geoposition_;
-  device::mojom::GeolocationPtr geolocation_;
+  mojo::Remote<device::mojom::Geolocation> geolocation_;
   device::mojom::GeolocationContextPtr geolocation_context_;
 
   // Timer to enforce a maximum timeout before the |callback_| is called, even
@@ -315,7 +316,8 @@
   DCHECK(connector);
   connector->BindInterface(device::mojom::kServiceName,
                            mojo::MakeRequest(&geolocation_context_));
-  geolocation_context_->BindGeolocation(mojo::MakeRequest(&geolocation_));
+  geolocation_context_->BindGeolocation(
+      geolocation_.BindNewPipeAndPassReceiver());
   geolocation_->SetHighAccuracy(false);
   geolocation_->QueryNextPosition(
       base::BindOnce(&FingerprintDataLoader::OnGotGeoposition,
diff --git a/components/exo/layer_tree_frame_sink_holder.cc b/components/exo/layer_tree_frame_sink_holder.cc
index 1288443..ad8437f6 100644
--- a/components/exo/layer_tree_frame_sink_holder.cc
+++ b/components/exo/layer_tree_frame_sink_holder.cc
@@ -8,6 +8,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "cc/trees/layer_tree_frame_sink.h"
 #include "components/exo/surface_tree_host.h"
+#include "components/viz/common/frame_timing_details.h"
 #include "components/viz/common/hit_test/hit_test_region_list.h"
 #include "components/viz/common/resources/returned_resource.h"
 
@@ -134,10 +135,12 @@
 }
 
 void LayerTreeFrameSinkHolder::DidPresentCompositorFrame(
-    uint32_t presentation_token,
-    const gfx::PresentationFeedback& feedback) {
-  if (surface_tree_host_)
-    surface_tree_host_->DidPresentCompositorFrame(presentation_token, feedback);
+    uint32_t frame_token,
+    const viz::FrameTimingDetails& details) {
+  if (surface_tree_host_) {
+    surface_tree_host_->DidPresentCompositorFrame(
+        frame_token, details.presentation_feedback);
+  }
 }
 
 void LayerTreeFrameSinkHolder::DidLoseLayerTreeFrameSink() {
diff --git a/components/exo/layer_tree_frame_sink_holder.h b/components/exo/layer_tree_frame_sink_holder.h
index a6932db..83c6a51 100644
--- a/components/exo/layer_tree_frame_sink_holder.h
+++ b/components/exo/layer_tree_frame_sink_holder.h
@@ -14,6 +14,10 @@
 #include "components/viz/common/quads/compositor_frame.h"
 #include "components/viz/common/resources/release_callback.h"
 
+namespace viz {
+struct FrameTimingDetails;
+}
+
 namespace cc {
 class LayerTreeFrameSink;
 }
@@ -54,8 +58,8 @@
   void SetTreeActivationCallback(base::RepeatingClosure callback) override {}
   void DidReceiveCompositorFrameAck() override;
   void DidPresentCompositorFrame(
-      uint32_t presentation_token,
-      const gfx::PresentationFeedback& feedback) override;
+      uint32_t frame_token,
+      const viz::FrameTimingDetails& details) override;
   void DidLoseLayerTreeFrameSink() override;
   void OnDraw(const gfx::Transform& transform,
               const gfx::Rect& viewport,
diff --git a/components/language/content/browser/geo_language_provider.cc b/components/language/content/browser/geo_language_provider.cc
index f0d3fb9..ae04f165 100644
--- a/components/language/content/browser/geo_language_provider.cc
+++ b/components/language/content/browser/geo_language_provider.cc
@@ -133,7 +133,7 @@
   ip_geolocation_provider->CreateGeolocation(
       static_cast<net::MutablePartialNetworkTrafficAnnotationTag>(
           partial_traffic_annotation),
-      mojo::MakeRequest(&geolocation_provider_));
+      geolocation_provider_.BindNewPipeAndPassReceiver());
   // No error handler required: If the connection is broken, QueryNextPosition
   // will bind it again.
 }
@@ -141,7 +141,7 @@
 void GeoLanguageProvider::QueryNextPosition() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(background_sequence_checker_);
 
-  if (geolocation_provider_.encountered_error())
+  if (geolocation_provider_.is_bound() && !geolocation_provider_.is_connected())
     geolocation_provider_.reset();
   if (!geolocation_provider_.is_bound())
     BindIpGeolocationService();
diff --git a/components/language/content/browser/geo_language_provider.h b/components/language/content/browser/geo_language_provider.h
index 2166e0d..e4c51732 100644
--- a/components/language/content/browser/geo_language_provider.h
+++ b/components/language/content/browser/geo_language_provider.h
@@ -12,6 +12,7 @@
 #include "base/sequence_checker.h"
 #include "base/sequenced_task_runner.h"
 #include "components/language/content/browser/language_code_locator.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "services/device/public/mojom/geolocation.mojom.h"
 
 namespace base {
@@ -102,7 +103,7 @@
   std::unique_ptr<service_manager::Connector> service_manager_connector_;
 
   // Connection to the IP geolocation service.
-  device::mojom::GeolocationPtr geolocation_provider_;
+  mojo::Remote<device::mojom::Geolocation> geolocation_provider_;
 
   // Location -> Language lookup library.
   std::unique_ptr<language::LanguageCodeLocator> language_code_locator_;
diff --git a/components/language/core/common/language_experiments.cc b/components/language/core/common/language_experiments.cc
index cccf6a2..817ced8 100644
--- a/components/language/core/common/language_experiments.cc
+++ b/components/language/core/common/language_experiments.cc
@@ -20,8 +20,6 @@
     "OverrideTranslateTriggerInIndia", base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kExplicitLanguageAsk{"ExplicitLanguageAsk",
                                          base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kImprovedGeoLanguageData{"ImprovedGeoLanguageData",
-                                             base::FEATURE_ENABLED_BY_DEFAULT};
 const base::Feature kUseFluentLanguageModel {
   "UseFluentLanguageModel",
 #if defined(OS_IOS)
diff --git a/components/language/core/common/language_experiments.h b/components/language/core/common/language_experiments.h
index dd600dd..d428f32a 100644
--- a/components/language/core/common/language_experiments.h
+++ b/components/language/core/common/language_experiments.h
@@ -17,9 +17,6 @@
 // Android.
 extern const base::Feature kExplicitLanguageAsk;
 
-// The feature that enables the use of improved geo-language data from ULP.
-extern const base::Feature kImprovedGeoLanguageData;
-
 // This feature controls the activation of the experiment to trigger Translate
 // in India on English pages independent of the user's UI language. The params
 // associated with the experiment dictate which model is used to determine the
diff --git a/components/media_message_center/media_notification_container.h b/components/media_message_center/media_notification_container.h
index 154c9ba2..0c31203f 100644
--- a/components/media_message_center/media_notification_container.h
+++ b/components/media_message_center/media_notification_container.h
@@ -24,6 +24,9 @@
 
   // Called when MediaNotificationView's foreground color changes.
   virtual void OnForegoundColorChanged(SkColor color) = 0;
+
+ protected:
+  virtual ~MediaNotificationContainer() = default;
 };
 
 }  // namespace media_message_center
diff --git a/components/media_message_center/media_notification_controller.h b/components/media_message_center/media_notification_controller.h
index 86467d6..7fdbcdb 100644
--- a/components/media_message_center/media_notification_controller.h
+++ b/components/media_message_center/media_notification_controller.h
@@ -38,6 +38,9 @@
   // Notifies the MediaNotificationController that a media button was pressed on
   // the MediaNotificationView.
   virtual void LogMediaSessionActionButtonPressed(const std::string& id) = 0;
+
+ protected:
+  virtual ~MediaNotificationController() = default;
 };
 
 }  // namespace media_message_center
diff --git a/components/metrics/metrics_service_client.cc b/components/metrics/metrics_service_client.cc
index a4e7bc0..1e105ef 100644
--- a/components/metrics/metrics_service_client.cc
+++ b/components/metrics/metrics_service_client.cc
@@ -69,7 +69,7 @@
     update_running_services_.Run();
 }
 
-bool MetricsServiceClient::IsMetricsReportingForceEnabled() {
+bool MetricsServiceClient::IsMetricsReportingForceEnabled() const {
   return base::CommandLine::ForCurrentProcess()->HasSwitch(
       switches::kForceEnableMetricsReporting);
 }
diff --git a/components/metrics/metrics_service_client.h b/components/metrics/metrics_service_client.h
index 91e11c7..6c611a5b 100644
--- a/components/metrics/metrics_service_client.h
+++ b/components/metrics/metrics_service_client.h
@@ -146,7 +146,7 @@
   void UpdateRunningServices();
 
   // Checks if the user has forced metrics collection on via the override flag.
-  bool IsMetricsReportingForceEnabled();
+  bool IsMetricsReportingForceEnabled() const;
 
  private:
   base::Closure update_running_services_;
diff --git a/components/module_installer/android/java/src/org/chromium/components/module_installer/PlayCoreModuleInstallerBackend.java b/components/module_installer/android/java/src/org/chromium/components/module_installer/PlayCoreModuleInstallerBackend.java
index b6bf7e2..501314c8 100644
--- a/components/module_installer/android/java/src/org/chromium/components/module_installer/PlayCoreModuleInstallerBackend.java
+++ b/components/module_installer/android/java/src/org/chromium/components/module_installer/PlayCoreModuleInstallerBackend.java
@@ -5,6 +5,7 @@
 package org.chromium.components.module_installer;
 
 import android.content.SharedPreferences;
+import android.os.SystemClock;
 import android.util.SparseLongArray;
 
 import com.google.android.play.core.splitinstall.SplitInstallException;
@@ -40,7 +41,7 @@
 
         public InstallTimes(boolean isCached) {
             mIsCached = isCached;
-            mInstallTimes.put(SplitInstallSessionStatus.UNKNOWN, System.currentTimeMillis());
+            mInstallTimes.put(SplitInstallSessionStatus.UNKNOWN, SystemClock.uptimeMillis());
         }
     }
 
@@ -190,7 +191,7 @@
             case SplitInstallSessionStatus.INSTALLED:
                 for (String name : state.moduleNames()) {
                     mInstallTimesMap.get(name).mInstallTimes.put(
-                            state.status(), System.currentTimeMillis());
+                            state.status(), SystemClock.uptimeMillis());
                 }
                 if (state.status() == SplitInstallSessionStatus.INSTALLED) {
                     finish(true, state.moduleNames(), INSTALL_STATUS_SUCCESS);
@@ -310,7 +311,7 @@
             return;
         }
         RecordHistogram.recordLongTimesHistogram(
-                String.format("Android.FeatureModules.%sInstallDuration%s.%s",
+                String.format("Android.FeatureModules.%sAwakeInstallDuration%s.%s",
                         installTimes.mIsCached ? "Cached" : "Uncached", histogramSubname,
                         moduleName),
                 installTimes.mInstallTimes.get(endKey) - installTimes.mInstallTimes.get(startKey));
diff --git a/components/network_time/network_time_tracker_unittest.cc b/components/network_time/network_time_tracker_unittest.cc
index e1c844e..b71a3fb 100644
--- a/components/network_time/network_time_tracker_unittest.cc
+++ b/components/network_time/network_time_tracker_unittest.cc
@@ -48,7 +48,8 @@
   ~NetworkTimeTrackerTest() override {}
 
   NetworkTimeTrackerTest()
-      : task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
+      : task_environment_(
+            base::test::SingleThreadTaskEnvironment::MainThreadType::IO),
         field_trial_test_(new FieldTrialTest()),
         clock_(new base::SimpleTestClock),
         tick_clock_(new base::SimpleTestTickClock),
@@ -155,7 +156,7 @@
   }
 
  protected:
-  base::test::TaskEnvironment task_environment_;
+  base::test::SingleThreadTaskEnvironment task_environment_;
   std::unique_ptr<FieldTrialTest> field_trial_test_;
   base::TimeDelta resolution_;
   base::TimeDelta latency_;
diff --git a/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/OfflineItem.java b/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/OfflineItem.java
index 20d67a1..9590cbc1 100644
--- a/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/OfflineItem.java
+++ b/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/OfflineItem.java
@@ -76,6 +76,7 @@
     public boolean isAccelerated;
     public boolean promoteOrigin;
     public boolean canRename;
+    public boolean ignoreVisuals;
 
     // Content Metadata.
     public long totalSizeBytes;
@@ -132,6 +133,7 @@
         clone.filePath = filePath;
         clone.mimeType = mimeType;
         clone.canRename = canRename;
+        clone.ignoreVisuals = ignoreVisuals;
         clone.pageUrl = pageUrl;
         clone.originalUrl = originalUrl;
         clone.isOffTheRecord = isOffTheRecord;
diff --git a/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/bridges/OfflineItemBridge.java b/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/bridges/OfflineItemBridge.java
index e3582ff..d01179d 100644
--- a/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/bridges/OfflineItemBridge.java
+++ b/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/bridges/OfflineItemBridge.java
@@ -53,7 +53,7 @@
             @PendingState int pendingState, boolean isResumable, boolean allowMetered,
             long receivedBytes, long progressValue, long progressMax,
             @OfflineItemProgressUnit int progressUnit, long timeRemainingMs, boolean isDangerous,
-            boolean canRename) {
+            boolean canRename, boolean ignoreVisuals) {
         OfflineItem item = new OfflineItem();
         item.id.namespace = nameSpace;
         item.id.id = id;
@@ -85,6 +85,7 @@
         item.timeRemainingMs = timeRemainingMs;
         item.isDangerous = isDangerous;
         item.canRename = canRename;
+        item.ignoreVisuals = ignoreVisuals;
         if (list != null) list.add(item);
         return item;
     }
diff --git a/components/offline_items_collection/core/android/offline_item_bridge.cc b/components/offline_items_collection/core/android/offline_item_bridge.cc
index b2181622..b108c14 100644
--- a/components/offline_items_collection/core/android/offline_item_bridge.cc
+++ b/components/offline_items_collection/core/android/offline_item_bridge.cc
@@ -44,7 +44,8 @@
       static_cast<jint>(item.pending_state), item.is_resumable,
       item.allow_metered, item.received_bytes, item.progress.value,
       item.progress.max.value_or(-1), static_cast<jint>(item.progress.unit),
-      item.time_remaining_ms, item.is_dangerous, item.can_rename);
+      item.time_remaining_ms, item.is_dangerous, item.can_rename,
+      item.ignore_visuals);
 }
 
 }  // namespace
diff --git a/components/offline_items_collection/core/offline_item.cc b/components/offline_items_collection/core/offline_item.cc
index 59410f8..a779105 100644
--- a/components/offline_items_collection/core/offline_item.cc
+++ b/components/offline_items_collection/core/offline_item.cc
@@ -45,6 +45,7 @@
       is_accelerated(false),
       promote_origin(false),
       can_rename(false),
+      ignore_visuals(false),
       total_size_bytes(0),
       externally_removed(false),
       is_openable(false),
@@ -75,6 +76,7 @@
          is_accelerated == offline_item.is_accelerated &&
          promote_origin == offline_item.promote_origin &&
          can_rename == offline_item.can_rename &&
+         ignore_visuals == offline_item.ignore_visuals &&
          total_size_bytes == offline_item.total_size_bytes &&
          externally_removed == offline_item.externally_removed &&
          creation_time == offline_item.creation_time &&
diff --git a/components/offline_items_collection/core/offline_item.h b/components/offline_items_collection/core/offline_item.h
index c4ea0e30..d7d08166 100644
--- a/components/offline_items_collection/core/offline_item.h
+++ b/components/offline_items_collection/core/offline_item.h
@@ -122,6 +122,12 @@
   // Whether or not this item can be renamed.
   bool can_rename;
 
+  // Whether or not to bother querying for visuals.  Querying is not guaranteed
+  // to return anything, but if this is |true| the UI layers can make
+  // optimizations without waiting for the asynchronous query for visual
+  // information.
+  bool ignore_visuals;
+
   // TODO(dtrainor): Build out custom per-item icon support.
 
   // Content Metadata.
diff --git a/components/offline_pages/core/downloads/offline_item_conversions.cc b/components/offline_pages/core/downloads/offline_item_conversions.cc
index 20da8401..8dcc3ea 100644
--- a/components/offline_pages/core/downloads/offline_item_conversions.cc
+++ b/components/offline_pages/core/downloads/offline_item_conversions.cc
@@ -67,6 +67,7 @@
   item.description = page.snippet;
   item.attribution = page.attribution;
 
+  // TODO(carlosk): Set item.ignore_visuals here to the right thing.
   return item;
 }
 
diff --git a/components/omnibox/browser/autocomplete_match.cc b/components/omnibox/browser/autocomplete_match.cc
index 9134006..39ceb355 100644
--- a/components/omnibox/browser/autocomplete_match.cc
+++ b/components/omnibox/browser/autocomplete_match.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/feature_list.h"
+#include "base/i18n/case_conversion.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/stl_util.h"
@@ -129,6 +130,7 @@
       fill_into_edit(match.fill_into_edit),
       inline_autocompletion(match.inline_autocompletion),
       allowed_to_be_default_match(match.allowed_to_be_default_match),
+      is_navigational_title_match(match.is_navigational_title_match),
       destination_url(match.destination_url),
       stripped_destination_url(match.stripped_destination_url),
       image_dominant_color(match.image_dominant_color),
@@ -182,6 +184,7 @@
   fill_into_edit = match.fill_into_edit;
   inline_autocompletion = match.inline_autocompletion;
   allowed_to_be_default_match = match.allowed_to_be_default_match;
+  is_navigational_title_match = match.is_navigational_title_match;
   destination_url = match.destination_url;
   stripped_destination_url = match.stripped_destination_url;
   image_dominant_color = match.image_dominant_color;
@@ -1142,8 +1145,10 @@
       fill_into_edit == duplicate_match.fill_into_edit &&
       duplicate_match.allowed_to_be_default_match) {
     allowed_to_be_default_match = true;
-    if (inline_autocompletion.empty())
+    if (inline_autocompletion.empty()) {
       inline_autocompletion = duplicate_match.inline_autocompletion;
+      is_navigational_title_match = duplicate_match.is_navigational_title_match;
+    }
   }
 
   // And always absorb the higher relevance score of duplicates.
@@ -1153,6 +1158,36 @@
   }
 }
 
+void AutocompleteMatch::TryAutocompleteWithTitle(
+    const base::string16& title,
+    const AutocompleteInput& input) {
+  if (!base::FeatureList::IsEnabled(omnibox::kAutocompleteTitles))
+    return;
+
+  const base::string16 lower_text{base::i18n::ToLower(title)};
+  const base::string16 lower_input_text{base::i18n::ToLower(input.text())};
+
+  if (!base::StartsWith(lower_text, lower_input_text,
+                        base::CompareCase::SENSITIVE)) {
+    return;
+  }
+
+  // For exact matches, promote the relevance to out-score verbatim
+  // search-what-you-typed matches.
+  if (lower_text == lower_input_text) {
+    relevance =
+        std::max(relevance, SearchProvider::kNonURLVerbatimRelevance + 10);
+    RecordAdditionalInfo("title match", "full");
+  } else
+    RecordAdditionalInfo("title match", "prefix");
+
+  fill_into_edit = title;
+  inline_autocompletion = fill_into_edit.substr(lower_input_text.length());
+  allowed_to_be_default_match =
+      inline_autocompletion.empty() || !input.prevent_inline_autocomplete();
+  is_navigational_title_match = true;
+}
+
 #if DCHECK_IS_ON()
 void AutocompleteMatch::Validate() const {
   ValidateClassifications(contents, contents_class);
diff --git a/components/omnibox/browser/autocomplete_match.h b/components/omnibox/browser/autocomplete_match.h
index aadb876a..a756136 100644
--- a/components/omnibox/browser/autocomplete_match.h
+++ b/components/omnibox/browser/autocomplete_match.h
@@ -457,6 +457,12 @@
   // relevance score, this match's own relevance score will be upgraded.
   void UpgradeMatchWithPropertiesFrom(const AutocompleteMatch& duplicate_match);
 
+  // Called for navigation suggestions whose URLs cannot be inline autocompleted
+  // (e.g. because the input is not a prefix of the URL), to check if |title|
+  // can be inline autocompleted instead.
+  void TryAutocompleteWithTitle(const base::string16& title,
+                                const AutocompleteInput& input);
+
   // The provider of this match, used to remember which provider the user had
   // selected when the input changes. This may be NULL, in which case there is
   // no provider (or memory of the user's selection).
@@ -505,6 +511,15 @@
   // should set this flag.
   bool allowed_to_be_default_match = false;
 
+  // Set by |TryAutocompleteWithTitle|. If |type| is navigational, then this
+  // field indicates |fill_into_edit| is not the URL but instead looks like
+  // search terms (e.g. `title - URL`). If |type| is non-navigational, then this
+  // is true regardless; i.e., |fill_into_edit| is not a URL. This allows
+  // callees of AutocompleteClassifier::Classify, such as
+  // OmniboxEditModel::AdjustTextForCopy, to treat such navigational matches
+  // differently than typical navigational matches with URL text.
+  bool is_navigational_title_match = false;
+
   // The URL to actually load when the autocomplete item is selected. This URL
   // should be canonical so we can compare URLs with strcmp to avoid dupes.
   // It may be empty if there is no possible navigation.
@@ -536,6 +551,8 @@
 
   // If true, UI-level code should swap the contents and description fields
   // before displaying.
+  // This field is set when matches are appended to autocomplete results via
+  // |AutocompleteResult::AppendMatches| rather than when matches are created.
   bool swap_contents_and_description = false;
 
   // A rich-format version of the display for the dropdown.
diff --git a/components/omnibox/browser/autocomplete_result.cc b/components/omnibox/browser/autocomplete_result.cc
index 06dc991..926f8e9 100644
--- a/components/omnibox/browser/autocomplete_result.cc
+++ b/components/omnibox/browser/autocomplete_result.cc
@@ -400,7 +400,7 @@
   for (auto& match : matches_) {
     // We do not want to deal with pedals of pedals, or pedals among
     // exclusive tail suggestions.
-    if (match.pedal || match.type == AutocompleteMatchType::SEARCH_SUGGEST_TAIL)
+    if (match.pedal || match.type == ACMatchType::SEARCH_SUGGEST_TAIL)
       continue;
     OmniboxPedal* const pedal = provider->FindPedalMatch(match.contents);
     if (pedal)
diff --git a/components/omnibox/browser/bookmark_provider.cc b/components/omnibox/browser/bookmark_provider.cc
index 4ab89dc7..5a57908 100644
--- a/components/omnibox/browser/bookmark_provider.cc
+++ b/components/omnibox/browser/bookmark_provider.cc
@@ -67,9 +67,9 @@
   //  - Terms must be at least three characters in length in order to perform
   //    partial word matches. Any term of lesser length will only be used as an
   //    exact match. 'def' will match against 'define' but 'de' will not match.
-  //    (The flag below changes this behavior.)
+  //    (Unless IsShortBookmarkSuggestionsEnabled is true.)
   //  - A search containing multiple terms will return results with those words
-  //    occuring in any order.
+  //    occurring in any order.
   //  - Terms enclosed in quotes comprises a phrase that must match exactly.
   //  - Multiple terms enclosed in quotes will require those exact words in that
   //    exact order to match.
diff --git a/components/omnibox/browser/document_provider.cc b/components/omnibox/browser/document_provider.cc
index 594b17c..fe60814 100644
--- a/components/omnibox/browser/document_provider.cc
+++ b/components/omnibox/browser/document_provider.cc
@@ -334,6 +334,11 @@
   return std::string();
 }
 
+base::string16 TitleForAutocompletion(AutocompleteMatch match) {
+  return match.contents +
+         base::UTF8ToUTF16(" - " + match.destination_url.spec());
+}
+
 }  // namespace
 
 // static
@@ -767,6 +772,7 @@
       AutocompleteMatch::AddLastClassificationIfNecessary(
           &match.description_class, 0, ACMatchClassification::DIM);
     }
+    match.TryAutocompleteWithTitle(TitleForAutocompletion(match), input_);
     match.transition = ui::PAGE_TRANSITION_GENERATED;
     match.RecordAdditionalInfo("client score", client_score);
     match.RecordAdditionalInfo("server score", server_score);
@@ -788,6 +794,9 @@
                 matches_cache_.end(), [this](const auto& cache_key_match_pair) {
                   auto match = cache_key_match_pair.second;
                   match.relevance = 0;
+                  match.allowed_to_be_default_match = false;
+                  match.TryAutocompleteWithTitle(TitleForAutocompletion(match),
+                                                 input_);
                   match.contents_class =
                       DocumentProvider::Classify(match.contents, input_.text());
                   match.RecordAdditionalInfo("from cache", "true");
diff --git a/components/omnibox/browser/history_quick_provider.cc b/components/omnibox/browser/history_quick_provider.cc
index 45bf4ee2..8b69ef7e 100644
--- a/components/omnibox/browser/history_quick_provider.cc
+++ b/components/omnibox/browser/history_quick_provider.cc
@@ -229,14 +229,6 @@
                                    &inline_autocomplete_offset),
           client()->GetSchemeClassifier(), &inline_autocomplete_offset);
 
-  // Set |inline_autocompletion| and |allowed_to_be_default_match| if possible.
-  if (inline_autocomplete_offset != base::string16::npos) {
-    match.inline_autocompletion =
-        match.fill_into_edit.substr(inline_autocomplete_offset);
-    match.allowed_to_be_default_match =
-        AutocompleteMatch::AllowedToBeDefault(autocomplete_input_, match);
-  }
-
   // HistoryQuick classification diverges from relevance scoring. Specifically,
   // 1) All occurrences of the input contribute to relevance; e.g. for the input
   // 'pre', the suggestion 'pre prefix' will be scored higher than 'pre suffix'.
@@ -276,6 +268,17 @@
       description_terms, match.description.size(), ACMatchClassification::MATCH,
       ACMatchClassification::NONE);
 
+  // Set |inline_autocompletion| and |allowed_to_be_default_match| if possible.
+  if (inline_autocomplete_offset != base::string16::npos) {
+    match.inline_autocompletion =
+        match.fill_into_edit.substr(inline_autocomplete_offset);
+    match.allowed_to_be_default_match =
+        AutocompleteMatch::AllowedToBeDefault(autocomplete_input_, match);
+  } else {
+    auto title = match.description + base::UTF8ToUTF16(" - ") + match.contents;
+    match.TryAutocompleteWithTitle(title, autocomplete_input_);
+  }
+
   match.RecordAdditionalInfo("typed count", info.typed_count());
   match.RecordAdditionalInfo("visit count", info.visit_count());
   match.RecordAdditionalInfo("last visit", info.last_visit());
diff --git a/components/omnibox/browser/omnibox_edit_model.cc b/components/omnibox/browser/omnibox_edit_model.cc
index 6438e7fc..c55d2a71 100644
--- a/components/omnibox/browser/omnibox_edit_model.cc
+++ b/components/omnibox/browser/omnibox_edit_model.cc
@@ -405,7 +405,8 @@
   client_->GetAutocompleteClassifier()->Classify(*text, is_keyword_selected(),
                                                  true, GetPageClassification(),
                                                  &match_from_text, nullptr);
-  if (AutocompleteMatch::IsSearchType(match_from_text.type))
+  if (AutocompleteMatch::IsSearchType(match_from_text.type) ||
+      match_from_text.is_navigational_title_match)
     return;
 
   // Make our best GURL interpretation of |text|.
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc
index d6e55a3a..cb252cef 100644
--- a/components/omnibox/browser/omnibox_field_trial.cc
+++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -644,7 +644,8 @@
 
 bool OmniboxFieldTrial::IsShortBookmarkSuggestionsEnabled() {
   return base::FeatureList::IsEnabled(
-      omnibox::kOmniboxShortBookmarkSuggestions);
+             omnibox::kOmniboxShortBookmarkSuggestions) ||
+         base::FeatureList::IsEnabled(omnibox::kAutocompleteTitles);
 }
 
 bool OmniboxFieldTrial::IsTabSwitchSuggestionsEnabled() {
diff --git a/components/omnibox/browser/search_provider.cc b/components/omnibox/browser/search_provider.cc
index 736b5368..c7cb336 100644
--- a/components/omnibox/browser/search_provider.cc
+++ b/components/omnibox/browser/search_provider.cc
@@ -72,9 +72,6 @@
   MAX_SUGGEST_REQUEST_HISTOGRAM_VALUE
 };
 
-// The verbatim score for an input which is not an URL.
-const int kNonURLVerbatimRelevance = 1300;
-
 // Increments the appropriate value in the histogram by one.
 void LogOmniboxSuggestRequest(
     SuggestRequestsHistogramValue request_value) {
diff --git a/components/omnibox/browser/search_provider.h b/components/omnibox/browser/search_provider.h
index 3f8a679..f374dc0 100644
--- a/components/omnibox/browser/search_provider.h
+++ b/components/omnibox/browser/search_provider.h
@@ -77,6 +77,9 @@
   // AutocompleteProvider:
   void ResetSession() override;
 
+  // The verbatim score for an input which is not an URL.
+  static const int kNonURLVerbatimRelevance = 1300;
+
  protected:
   ~SearchProvider() override;
 
diff --git a/components/omnibox/browser/titled_url_match_utils.cc b/components/omnibox/browser/titled_url_match_utils.cc
index b930eef..a848a09 100644
--- a/components/omnibox/browser/titled_url_match_utils.cc
+++ b/components/omnibox/browser/titled_url_match_utils.cc
@@ -63,6 +63,14 @@
       ACMatchClassification::MATCH | ACMatchClassification::URL,
       ACMatchClassification::URL);
 
+  match.description = titled_url_match.node->GetTitledUrlNodeTitle();
+  base::TrimWhitespace(match.description, base::TRIM_LEADING,
+                       &match.description);
+  auto description_terms = FindTermMatches(input.text(), match.description);
+  match.description_class = ClassifyTermMatches(
+      description_terms, match.description.length(),
+      ACMatchClassification::MATCH, ACMatchClassification::NONE);
+
   // The inline_autocomplete_offset should be adjusted based on the formatting
   // applied to |fill_into_edit|.
   size_t inline_autocomplete_offset = URLPrefix::GetInlineAutocompleteOffset(
@@ -82,14 +90,10 @@
         match.fill_into_edit.substr(inline_autocomplete_offset);
     match.allowed_to_be_default_match =
         AutocompleteMatch::AllowedToBeDefault(input, match);
+  } else {
+    auto title = match.description + base::UTF8ToUTF16(" - ") + match.contents;
+    match.TryAutocompleteWithTitle(title, input);
   }
-  match.description = titled_url_match.node->GetTitledUrlNodeTitle();
-  base::TrimWhitespace(match.description, base::TRIM_LEADING,
-                       &match.description);
-  auto description_terms = FindTermMatches(input.text(), match.description);
-  match.description_class = ClassifyTermMatches(
-      description_terms, match.description.length(),
-      ACMatchClassification::MATCH, ACMatchClassification::NONE);
 
   return match;
 }
diff --git a/components/omnibox/common/omnibox_features.cc b/components/omnibox/common/omnibox_features.cc
index e4c6de1f..4f66936 100644
--- a/components/omnibox/common/omnibox_features.cc
+++ b/components/omnibox/common/omnibox_features.cc
@@ -257,6 +257,11 @@
 const base::Feature kDocumentProvider{"OmniboxDocumentProvider",
                                       base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Feature used to autocomplete bookmark, history, and document suggestions when
+// the user input is a prefix of their titles, as opposed to their URLs.
+const base::Feature kAutocompleteTitles{"OmniboxAutocompleteTitles",
+                                        base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Feature to replace the standard ZeroSuggest with icons for most visited sites
 // and collections (bookmarks, history, recent tabs, reading list). Only
 // available on iOS.
diff --git a/components/omnibox/common/omnibox_features.h b/components/omnibox/common/omnibox_features.h
index 1b5da5d..59dbcc6 100644
--- a/components/omnibox/common/omnibox_features.h
+++ b/components/omnibox/common/omnibox_features.h
@@ -44,6 +44,7 @@
 extern const base::Feature kSpeculativeServiceWorkerStartOnQueryInput;
 extern const base::Feature kDocumentProvider;
 extern const base::Feature kOnDeviceHeadProvider;
+extern const base::Feature kAutocompleteTitles;
 extern const base::Feature kOmniboxPopupShortcutIconsInZeroState;
 extern const base::Feature kOmniboxMaterialDesignWeatherIcons;
 extern const base::Feature kOmniboxDisableInstantExtendedLimit;
diff --git a/components/password_manager/core/browser/form_fetcher_impl.cc b/components/password_manager/core/browser/form_fetcher_impl.cc
index fbf8b126..8a744c9 100644
--- a/components/password_manager/core/browser/form_fetcher_impl.cc
+++ b/components/password_manager/core/browser/form_fetcher_impl.cc
@@ -29,39 +29,6 @@
 
 namespace {
 
-struct SplitMatches {
-  std::vector<std::unique_ptr<PasswordForm>> non_federated;
-  std::vector<std::unique_ptr<PasswordForm>> federated;
-  std::vector<std::unique_ptr<PasswordForm>> blacklisted;
-};
-
-// Partitions |results| into |-- non federated -|- federated -|- blacklisted --|
-// and returns result.
-SplitMatches SplitResults(std::vector<std::unique_ptr<PasswordForm>> results) {
-  const auto first_blacklisted = std::partition(
-      results.begin(), results.end(),
-      [](const auto& form) { return !form->blacklisted_by_user; });
-
-  const auto first_federated =
-      std::partition(results.begin(), first_blacklisted, [](const auto& form) {
-        return form->federation_origin.opaque();  // False means federated.
-      });
-
-  // Ignore PSL matches for blacklisted entries.
-  const auto first_blacklisted_psl = std::partition(
-      first_blacklisted, results.end(),
-      [](const auto& form) { return !form->is_public_suffix_match; });
-
-  SplitMatches matches;
-  matches.non_federated.assign(std::make_move_iterator(results.begin()),
-                               std::make_move_iterator(first_federated));
-  matches.federated.assign(std::make_move_iterator(first_federated),
-                           std::make_move_iterator(first_blacklisted));
-  matches.blacklisted.assign(std::make_move_iterator(first_blacklisted),
-                             std::make_move_iterator(first_blacklisted_psl));
-  return matches;
-}
-
 // Create a vector of const PasswordForm from a vector of
 // unique_ptr<PasswordForm> by applying get() item-wise.
 std::vector<const PasswordForm*> MakeWeakCopies(
@@ -252,10 +219,7 @@
     std::vector<std::unique_ptr<PasswordForm>> results) {
   DCHECK_EQ(State::WAITING, state_);
   state_ = State::NOT_WAITING;
-  SplitMatches matches = SplitResults(std::move(results));
-  federated_ = std::move(matches.federated);
-  non_federated_ = std::move(matches.non_federated);
-  blacklisted_ = std::move(matches.blacklisted);
+  SplitResults(std::move(results));
 
   password_manager_util::FindBestMatches(
       MakeWeakCopies(non_federated_), form_digest_.scheme,
@@ -265,4 +229,23 @@
     consumer->OnFetchCompleted();
 }
 
+void FormFetcherImpl::SplitResults(
+    std::vector<std::unique_ptr<PasswordForm>> forms) {
+  blacklisted_.clear();
+  non_federated_.clear();
+  federated_.clear();
+  for (auto& form : forms) {
+    if (form->blacklisted_by_user) {
+      // Ignore PSL matches for blacklisted entries.
+      if (!form->is_public_suffix_match) {
+        blacklisted_.push_back(std::move(form));
+      }
+    } else if (form->IsFederatedCredential()) {
+      federated_.push_back(std::move(form));
+    } else {
+      non_federated_.push_back(std::move(form));
+    }
+  }
+}
+
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/form_fetcher_impl.h b/components/password_manager/core/browser/form_fetcher_impl.h
index 96df83af..3589684 100644
--- a/components/password_manager/core/browser/form_fetcher_impl.h
+++ b/components/password_manager/core/browser/form_fetcher_impl.h
@@ -68,6 +68,10 @@
       std::vector<std::unique_ptr<autofill::PasswordForm>> forms) override;
 
  private:
+  // Splits |results| into |federated_|, |non_federated_| and |blacklisted_|.
+  void SplitResults(
+      std::vector<std::unique_ptr<autofill::PasswordForm>> results);
+
   // Processes password form results and forwards them to the |consumers_|.
   void ProcessPasswordStoreResults(
       std::vector<std::unique_ptr<autofill::PasswordForm>> results);
diff --git a/components/password_manager/core/browser/password_manager_client.h b/components/password_manager/core/browser/password_manager_client.h
index 1a7e5a6b..f1ee20ba 100644
--- a/components/password_manager/core/browser/password_manager_client.h
+++ b/components/password_manager/core/browser/password_manager_client.h
@@ -227,6 +227,9 @@
   // Returns the profile PasswordStore associated with this instance.
   virtual PasswordStore* GetProfilePasswordStore() const = 0;
 
+  // Returns the account PasswordStore associated with this instance.
+  virtual PasswordStore* GetAccountPasswordStore() const = 0;
+
   // Reports whether and how passwords are synced in the embedder. The default
   // implementation always returns NOT_SYNCING.
   virtual SyncState GetPasswordSyncState() const;
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.cc b/components/password_manager/core/browser/password_manager_metrics_util.cc
index 4b69530..1725ba6 100644
--- a/components/password_manager/core/browser/password_manager_metrics_util.cc
+++ b/components/password_manager/core/browser/password_manager_metrics_util.cc
@@ -85,6 +85,16 @@
                                 reason);
 }
 
+void LogResultOfSavingFlow(OnboardingResultOfSavingFlow result) {
+  base::UmaHistogramEnumeration("PasswordManager.Onboarding.ResultOfSavingFlow",
+                                result);
+}
+
+void LogResultOfOnboardingSavingFlow(OnboardingResultOfSavingFlow result) {
+  base::UmaHistogramEnumeration(
+      "PasswordManager.Onboarding.ResultOfSavingFlowAfterOnboarding", result);
+}
+
 void LogUIDisplayDisposition(UIDisplayDisposition disposition) {
   base::UmaHistogramEnumeration("PasswordBubble.DisplayDisposition",
                                 disposition, NUM_DISPLAY_DISPOSITIONS);
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.h b/components/password_manager/core/browser/password_manager_metrics_util.h
index b2a51db8..396cdcd 100644
--- a/components/password_manager/core/browser/password_manager_metrics_util.h
+++ b/components/password_manager/core/browser/password_manager_metrics_util.h
@@ -117,6 +117,29 @@
   kMaxValue = kDismissed,
 };
 
+// Metrics: "PasswordManager.Onboarding.ResultOfSavingFlow"
+// Metrics: "PasswordManager.Onboarding.ResultOfSavingFlowAfterOnboarding"
+// Enum recording the result of the combined saving flow consisting of the
+// potentially shown onboarding dialog and the save infobar.
+// Needs to stay in sync with the PasswordManagerOnboardingResultOfSavingFlow
+// enum in enums.xml.
+//
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class OnboardingResultOfSavingFlow {
+  // Possible infobar responses from the |UIDismissalReason| enum.
+  kInfobarNoDirectInteraction = 0,
+  kInfobarClickedSave = 1,
+  kInfobarClickedCancel = 2,
+  kInfobarClickedNever = 3,
+  // The rejecting button on the onboarding dialog was pressed, e.g. "Cancel".
+  kOnboardingRejected = 4,
+  // The onboarding dialog was dismissed, e.g. by pressing the back button, or
+  // opening a new tab.
+  kOnboardingDismissed = 5,
+  kMaxValue = kOnboardingDismissed,
+};
+
 enum FormDeserializationStatus {
   LOGIN_DATABASE_SUCCESS,
   LOGIN_DATABASE_FAILURE,
@@ -448,6 +471,13 @@
 // Log the |reason| a user dismissed the onboarding UI.
 void LogOnboardingUIDismissalReason(OnboardingUIDismissalReason reason);
 
+// Log the |result| of the password saving flow.
+void LogResultOfSavingFlow(OnboardingResultOfSavingFlow result);
+
+// Log the |result| of the password saving flow if the onboarding was shown in
+// the process.
+void LogResultOfOnboardingSavingFlow(OnboardingResultOfSavingFlow result);
+
 // Log the appropriate display disposition.
 void LogUIDisplayDisposition(UIDisplayDisposition disposition);
 
diff --git a/components/password_manager/core/browser/password_manager_onboarding.cc b/components/password_manager/core/browser/password_manager_onboarding.cc
index f7c8bfd..4e977bcb 100644
--- a/components/password_manager/core/browser/password_manager_onboarding.cc
+++ b/components/password_manager/core/browser/password_manager_onboarding.cc
@@ -5,13 +5,50 @@
 #include "components/password_manager/core/browser/password_manager_onboarding.h"
 
 #include "base/feature_list.h"
-#include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/password_manager/core/common/password_manager_pref_names.h"
 #include "components/prefs/pref_service.h"
 
 namespace password_manager {
 
+namespace {
+// Functions converting UIDismissalReasons for the save password
+// infobar and the onboarding dialog into values of the
+// |OnboardingResultOfSavingFlow| enum.
+metrics_util::OnboardingResultOfSavingFlow FlowResultFromInfobarDismissalReason(
+    const metrics_util::UIDismissalReason reason) {
+  switch (reason) {
+    case metrics_util::UIDismissalReason::NO_DIRECT_INTERACTION:
+      return metrics_util::OnboardingResultOfSavingFlow::
+          kInfobarNoDirectInteraction;
+    case metrics_util::UIDismissalReason::CLICKED_SAVE:
+      return metrics_util::OnboardingResultOfSavingFlow::kInfobarClickedSave;
+    case metrics_util::UIDismissalReason::CLICKED_CANCEL:
+      return metrics_util::OnboardingResultOfSavingFlow::kInfobarClickedCancel;
+    case metrics_util::UIDismissalReason::CLICKED_NEVER:
+      return metrics_util::OnboardingResultOfSavingFlow::kInfobarClickedNever;
+    default:
+      NOTREACHED();
+      return metrics_util::OnboardingResultOfSavingFlow::
+          kInfobarNoDirectInteraction;
+  }
+}
+
+metrics_util::OnboardingResultOfSavingFlow
+FlowResultFromOnboardingDismissalReason(
+    const metrics_util::OnboardingUIDismissalReason reason) {
+  switch (reason) {
+    case metrics_util::OnboardingUIDismissalReason::kRejected:
+      return metrics_util::OnboardingResultOfSavingFlow::kOnboardingRejected;
+    case metrics_util::OnboardingUIDismissalReason::kDismissed:
+      return metrics_util::OnboardingResultOfSavingFlow::kOnboardingDismissed;
+    default:
+      NOTREACHED();
+      return metrics_util::OnboardingResultOfSavingFlow::kOnboardingRejected;
+  }
+}
+}  // namespace
+
 using OnboardingState = password_manager::metrics_util::OnboardingState;
 
 OnboardingStateUpdate::OnboardingStateUpdate(
@@ -94,4 +131,27 @@
   return false;
 }
 
+SavingFlowMetricsRecorder::SavingFlowMetricsRecorder() = default;
+
+SavingFlowMetricsRecorder::~SavingFlowMetricsRecorder() {
+  metrics_util::LogResultOfSavingFlow(flow_result_);
+  if (onboarding_shown_) {
+    metrics_util::LogResultOfOnboardingSavingFlow(flow_result_);
+  }
+}
+
+void SavingFlowMetricsRecorder::SetOnboardingShown() {
+  onboarding_shown_ = true;
+}
+
+void SavingFlowMetricsRecorder::SetFlowResult(
+    metrics_util::UIDismissalReason reason) {
+  flow_result_ = FlowResultFromInfobarDismissalReason(reason);
+}
+
+void SavingFlowMetricsRecorder::SetFlowResult(
+    metrics_util::OnboardingUIDismissalReason reason) {
+  flow_result_ = FlowResultFromOnboardingDismissalReason(reason);
+}
+
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/password_manager_onboarding.h b/components/password_manager/core/browser/password_manager_onboarding.h
index 6f8cfab..1e2ad436 100644
--- a/components/password_manager/core/browser/password_manager_onboarding.h
+++ b/components/password_manager/core/browser/password_manager_onboarding.h
@@ -7,6 +7,7 @@
 
 #include "base/util/type_safety/strong_alias.h"
 #include "components/password_manager/core/browser/password_manager_client.h"
+#include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/password_manager/core/browser/password_store.h"
 #include "components/password_manager/core/browser/password_store_consumer.h"
 
@@ -81,6 +82,41 @@
                           BlacklistedBool is_blacklisted,
                           SyncState sync_state);
 
+// This utility class is responsible for recording the result of the
+// saving flow into the following metrics:
+//     - "PasswordManager.Onboarding.ResultOfSavingFlow"
+//     - "PasswordManager.Onboarding.ResultOfSavingFlowAfterOnboarding"
+// They are recorded upon deletion of this class.
+// The second metric is only recorded if the onboarding was shown
+// during the flow, which is indicated by |onboarding_shown_|.
+class SavingFlowMetricsRecorder {
+ public:
+  SavingFlowMetricsRecorder();
+
+  // Records the metrics before destruction.
+  ~SavingFlowMetricsRecorder();
+
+  // This is called to indicate that the onboarding was shown.
+  void SetOnboardingShown();
+
+  // Functions called to store the outcome of the saving flow.
+  // Accepts the following reasons for dismissing the infobar:
+  // NO_DIRECT_INTERACTION, CLICKED_SAVE, CLICKED_CANCEL and CLICKED_NEVER.
+  void SetFlowResult(metrics_util::UIDismissalReason reason);
+  // Accepts the following reasons for dismissing the onboarding dialog:
+  // kRejected and kDismissed.
+  void SetFlowResult(metrics_util::OnboardingUIDismissalReason reason);
+
+ private:
+  // Boolean indicating if the onboarding was shown in the flow.
+  bool onboarding_shown_ = false;
+  // Enum indicating the outcome of the password saving flow.
+  metrics_util::OnboardingResultOfSavingFlow flow_result_ =
+      metrics_util::OnboardingResultOfSavingFlow::kInfobarNoDirectInteraction;
+
+  DISALLOW_COPY_AND_ASSIGN(SavingFlowMetricsRecorder);
+};
+
 }  // namespace password_manager
 
 #endif  // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_MANAGER_ONBOARDING_H_
diff --git a/components/password_manager/core/browser/password_manager_onboarding_unittest.cc b/components/password_manager/core/browser/password_manager_onboarding_unittest.cc
index 29ccf76..4341da3 100644
--- a/components/password_manager/core/browser/password_manager_onboarding_unittest.cc
+++ b/components/password_manager/core/browser/password_manager_onboarding_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "components/autofill/core/common/password_form.h"
@@ -254,4 +255,135 @@
                                     SyncState::NOT_SYNCING));
 }
 
+TEST_F(PasswordManagerOnboardingTest,
+       SavingFlowMetricsRecorderInfobarNoDirectInteraction) {
+  base::HistogramTester histogram_tester;
+  {
+    SavingFlowMetricsRecorder recorder;
+    recorder.SetFlowResult(password_manager::metrics_util::UIDismissalReason::
+                               NO_DIRECT_INTERACTION);
+  }
+  histogram_tester.ExpectUniqueSample(
+      "PasswordManager.Onboarding.ResultOfSavingFlow",
+      password_manager::metrics_util::OnboardingResultOfSavingFlow::
+          kInfobarNoDirectInteraction,
+      1);
+  histogram_tester.ExpectTotalCount(
+      "PasswordManager.Onboarding.ResultOfSavingFlowAfterOnboarding", 0);
+}
+
+TEST_F(PasswordManagerOnboardingTest,
+       SavingFlowMetricsRecorderInfobarClickedSave) {
+  base::HistogramTester histogram_tester;
+  {
+    SavingFlowMetricsRecorder recorder;
+    recorder.SetFlowResult(
+        password_manager::metrics_util::UIDismissalReason::CLICKED_SAVE);
+  }
+  histogram_tester.ExpectUniqueSample(
+      "PasswordManager.Onboarding.ResultOfSavingFlow",
+      password_manager::metrics_util::OnboardingResultOfSavingFlow::
+          kInfobarClickedSave,
+      1);
+  histogram_tester.ExpectTotalCount(
+      "PasswordManager.Onboarding.ResultOfSavingFlowAfterOnboarding", 0);
+}
+
+TEST_F(PasswordManagerOnboardingTest,
+       SavingFlowMetricsRecorderInfobarClickedCancel) {
+  base::HistogramTester histogram_tester;
+  {
+    SavingFlowMetricsRecorder recorder;
+    recorder.SetFlowResult(
+        password_manager::metrics_util::UIDismissalReason::CLICKED_CANCEL);
+  }
+  histogram_tester.ExpectUniqueSample(
+      "PasswordManager.Onboarding.ResultOfSavingFlow",
+      password_manager::metrics_util::OnboardingResultOfSavingFlow::
+          kInfobarClickedCancel,
+      1);
+  histogram_tester.ExpectTotalCount(
+      "PasswordManager.Onboarding.ResultOfSavingFlowAfterOnboarding", 0);
+}
+
+TEST_F(PasswordManagerOnboardingTest,
+       SavingFlowMetricsRecorderInfobarClickedNever) {
+  base::HistogramTester histogram_tester;
+  {
+    SavingFlowMetricsRecorder recorder;
+    recorder.SetFlowResult(
+        password_manager::metrics_util::UIDismissalReason::CLICKED_NEVER);
+  }
+  histogram_tester.ExpectUniqueSample(
+      "PasswordManager.Onboarding.ResultOfSavingFlow",
+      password_manager::metrics_util::OnboardingResultOfSavingFlow::
+          kInfobarClickedNever,
+      1);
+  histogram_tester.ExpectTotalCount(
+      "PasswordManager.Onboarding.ResultOfSavingFlowAfterOnboarding", 0);
+}
+
+TEST_F(PasswordManagerOnboardingTest,
+       SavingFlowMetricsRecorderOnboardingRejected) {
+  base::HistogramTester histogram_tester;
+  {
+    SavingFlowMetricsRecorder recorder;
+    recorder.SetOnboardingShown();
+    recorder.SetFlowResult(
+        password_manager::metrics_util::OnboardingUIDismissalReason::kRejected);
+  }
+  histogram_tester.ExpectUniqueSample(
+      "PasswordManager.Onboarding.ResultOfSavingFlow",
+      password_manager::metrics_util::OnboardingResultOfSavingFlow::
+          kOnboardingRejected,
+      1);
+  histogram_tester.ExpectUniqueSample(
+      "PasswordManager.Onboarding.ResultOfSavingFlowAfterOnboarding",
+      password_manager::metrics_util::OnboardingResultOfSavingFlow::
+          kOnboardingRejected,
+      1);
+}
+
+TEST_F(PasswordManagerOnboardingTest,
+       SavingFlowMetricsRecorderOnboardingDismissed) {
+  base::HistogramTester histogram_tester;
+  {
+    SavingFlowMetricsRecorder recorder;
+    recorder.SetOnboardingShown();
+    recorder.SetFlowResult(password_manager::metrics_util::
+                               OnboardingUIDismissalReason::kDismissed);
+  }
+  histogram_tester.ExpectUniqueSample(
+      "PasswordManager.Onboarding.ResultOfSavingFlow",
+      password_manager::metrics_util::OnboardingResultOfSavingFlow::
+          kOnboardingDismissed,
+      1);
+  histogram_tester.ExpectUniqueSample(
+      "PasswordManager.Onboarding.ResultOfSavingFlowAfterOnboarding",
+      password_manager::metrics_util::OnboardingResultOfSavingFlow::
+          kOnboardingDismissed,
+      1);
+}
+
+TEST_F(PasswordManagerOnboardingTest,
+       SavingFlowMetricsRecorderAfterOnboarding) {
+  base::HistogramTester histogram_tester;
+  {
+    SavingFlowMetricsRecorder recorder;
+    recorder.SetOnboardingShown();
+    recorder.SetFlowResult(
+        password_manager::metrics_util::UIDismissalReason::CLICKED_SAVE);
+  }
+  histogram_tester.ExpectUniqueSample(
+      "PasswordManager.Onboarding.ResultOfSavingFlow",
+      password_manager::metrics_util::OnboardingResultOfSavingFlow::
+          kInfobarClickedSave,
+      1);
+  histogram_tester.ExpectUniqueSample(
+      "PasswordManager.Onboarding.ResultOfSavingFlowAfterOnboarding",
+      password_manager::metrics_util::OnboardingResultOfSavingFlow::
+          kInfobarClickedSave,
+      1);
+}
+
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/stub_password_manager_client.cc b/components/password_manager/core/browser/stub_password_manager_client.cc
index d36a3f1..bb65638 100644
--- a/components/password_manager/core/browser/stub_password_manager_client.cc
+++ b/components/password_manager/core/browser/stub_password_manager_client.cc
@@ -69,6 +69,10 @@
   return nullptr;
 }
 
+PasswordStore* StubPasswordManagerClient::GetAccountPasswordStore() const {
+  return nullptr;
+}
+
 const GURL& StubPasswordManagerClient::GetLastCommittedEntryURL() const {
   return GURL::EmptyGURL();
 }
diff --git a/components/password_manager/core/browser/stub_password_manager_client.h b/components/password_manager/core/browser/stub_password_manager_client.h
index a6a6824..f391977 100644
--- a/components/password_manager/core/browser/stub_password_manager_client.h
+++ b/components/password_manager/core/browser/stub_password_manager_client.h
@@ -55,6 +55,7 @@
       std::unique_ptr<PasswordFormManagerForUI> saved_manager) override;
   PrefService* GetPrefs() const override;
   PasswordStore* GetProfilePasswordStore() const override;
+  PasswordStore* GetAccountPasswordStore() const override;
   const GURL& GetLastCommittedEntryURL() const override;
   const CredentialsFilter* GetStoreResultFilter() const override;
   const autofill::LogManager* GetLogManager() const override;
diff --git a/components/policy/core/common/cloud/cloud_policy_client_unittest.cc b/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
index c673919..108a755 100644
--- a/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
+++ b/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
@@ -1465,10 +1465,10 @@
                  base::Unretained(&callback_observer_));
 
   base::Value context(base::Value::Type::DICTIONARY);
-  context.SetStringPath("gaiaEmail", "name@gmail.com");
-  context.SetStringPath("userAgent", "User-Agent");
-  context.SetStringPath("profileName", "Profile 1");
-  context.SetStringPath("profilePath", "C:\\User Data\\Profile 1");
+  context.SetStringPath("profile.gaiaEmail", "name@gmail.com");
+  context.SetStringPath("browser.userAgent", "User-Agent");
+  context.SetStringPath("profile.profileName", "Profile 1");
+  context.SetStringPath("profile.profilePath", "C:\\User Data\\Profile 1");
 
   base::Value event;
   event.SetStringPath("time", "2019-05-22T13:01:45Z");
@@ -1512,6 +1512,80 @@
   base::span<const base::Value> list = events->GetList();
   EXPECT_EQ(1u, list.size());
 }
+
+TEST_F(CloudPolicyClientTest, RealtimeReportMerge) {
+  auto config = std::make_unique<RealtimeReportingJobConfiguration>(
+      client_.get(), DMAuth::FromDMToken(kDMToken),
+      RealtimeReportingJobConfiguration::Callback());
+
+  // Add one report to the config.
+  {
+    base::Value context(base::Value::Type::DICTIONARY);
+    context.SetStringPath("profile.gaiaEmail", "name@gmail.com");
+    context.SetStringPath("browser.userAgent", "User-Agent");
+    context.SetStringPath("profile.profileName", "Profile 1");
+    context.SetStringPath("profile.profilePath", "C:\\User Data\\Profile 1");
+
+    base::Value event;
+    event.SetStringPath("time", "2019-09-10T20:01:45Z");
+    event.SetStringPath("foo.prop1", "value1");
+    event.SetStringPath("foo.prop2", "value2");
+    event.SetStringPath("foo.prop3", "value3");
+
+    base::Value events(base::Value::Type::LIST);
+    events.GetList().push_back(std::move(event));
+
+    base::Value report(base::Value::Type::DICTIONARY);
+    report.SetPath(RealtimeReportingJobConfiguration::kEventListKey,
+                   std::move(events));
+    report.SetPath(RealtimeReportingJobConfiguration::kContextKey,
+                   std::move(context));
+
+    ASSERT_TRUE(config->AddReport(std::move(report)));
+  }
+
+  // Add a second report to the config with a different context.
+  {
+    base::Value context(base::Value::Type::DICTIONARY);
+    context.SetStringPath("profile.gaiaEmail", "name2@gmail.com");
+    context.SetStringPath("browser.userAgent", "User-Agent2");
+    context.SetStringPath("browser.version", "1.0.0.0");
+
+    base::Value event;
+    event.SetStringPath("time", "2019-09-10T20:02:45Z");
+    event.SetStringPath("foo.prop1", "value1");
+    event.SetStringPath("foo.prop2", "value2");
+    event.SetStringPath("foo.prop3", "value3");
+
+    base::Value events(base::Value::Type::LIST);
+    events.GetList().push_back(std::move(event));
+
+    base::Value report(base::Value::Type::DICTIONARY);
+    report.SetPath(RealtimeReportingJobConfiguration::kEventListKey,
+                   std::move(events));
+    report.SetPath(RealtimeReportingJobConfiguration::kContextKey,
+                   std::move(context));
+
+    ASSERT_TRUE(config->AddReport(std::move(report)));
+  }
+
+  // The second config should trump the first.
+  DeviceManagementService::JobConfiguration* job_config = config.get();
+  base::Optional<base::Value> payload =
+      base::JSONReader::Read(job_config->GetPayload());
+  ASSERT_TRUE(payload);
+
+  ASSERT_EQ("name2@gmail.com", *payload->FindStringPath("profile.gaiaEmail"));
+  ASSERT_EQ("User-Agent2", *payload->FindStringPath("browser.userAgent"));
+  ASSERT_EQ("Profile 1", *payload->FindStringPath("profile.profileName"));
+  ASSERT_EQ("C:\\User Data\\Profile 1",
+            *payload->FindStringPath("profile.profilePath"));
+  ASSERT_EQ("1.0.0.0", *payload->FindStringPath("browser.version"));
+  ASSERT_EQ(2u,
+            payload->FindListPath(RealtimeReportingJobConfiguration::kEventsKey)
+                ->GetList()
+                .size());
+}
 #endif
 
 TEST_F(CloudPolicyClientTest, MultipleActiveRequests) {
diff --git a/components/policy/core/common/cloud/realtime_reporting_job_configuration.cc b/components/policy/core/common/cloud/realtime_reporting_job_configuration.cc
index 1519ace..52c08126 100644
--- a/components/policy/core/common/cloud/realtime_reporting_job_configuration.cc
+++ b/components/policy/core/common/cloud/realtime_reporting_job_configuration.cc
@@ -73,12 +73,8 @@
     return false;
 
   // Move context keys to the payload.  It is possible to add multiple reports
-  // to the payload in which case the context values are the same.  Only add
-  // any new values not already present.
-  for (const auto& item : context->DictItems()) {
-    if (!payload_.FindKey(item.first))
-      payload_.SetKey(item.first, item.second.Clone());
-  }
+  // to the payload in which case the context values are the same.
+  payload_.MergeDictionary(&*context);
 
   // Append event_list to the payload.
   base::Value::ListStorage& to = payload_.FindListKey(kEventsKey)->GetList();
diff --git a/components/services/pdf_compositor/pdf_compositor_impl.cc b/components/services/pdf_compositor/pdf_compositor_impl.cc
index b4fd83e3e2..a116efc 100644
--- a/components/services/pdf_compositor/pdf_compositor_impl.cc
+++ b/components/services/pdf_compositor/pdf_compositor_impl.cc
@@ -46,6 +46,9 @@
   if (receiver)
     receiver_.Bind(std::move(receiver));
 
+  if (!initialize_environment)
+    return;
+
 #if defined(OS_WIN)
   // Initialize direct write font proxy so skia can use it.
   content::InitializeDWriteFontProxy();
@@ -55,9 +58,6 @@
   SkGraphics::SetImageGeneratorFromEncodedDataFactory(
       blink::WebImageGenerator::CreateAsSkImageGenerator);
 
-  if (!initialize_environment)
-    return;
-
 #if defined(OS_POSIX) && !defined(OS_ANDROID)
   content::UtilityThread::Get()->EnsureBlinkInitializedWithSandboxSupport();
   // Check that we have sandbox support on this platform.
diff --git a/components/spellcheck/browser/spellcheck_host_metrics_unittest.cc b/components/spellcheck/browser/spellcheck_host_metrics_unittest.cc
index df64b605..b5cb625 100644
--- a/components/spellcheck/browser/spellcheck_host_metrics_unittest.cc
+++ b/components/spellcheck/browser/spellcheck_host_metrics_unittest.cc
@@ -27,7 +27,7 @@
   void RecordWordCountsForTesting() { metrics_->RecordWordCounts(); }
 
  private:
-  base::test::TaskEnvironment task_environment_;
+  base::test::SingleThreadTaskEnvironment task_environment_;
   std::unique_ptr<SpellCheckHostMetrics> metrics_;
 };
 
diff --git a/components/spellcheck/browser/spellcheck_platform_mac_unittest.cc b/components/spellcheck/browser/spellcheck_platform_mac_unittest.cc
index c671f3b..24ddcd14 100644
--- a/components/spellcheck/browser/spellcheck_platform_mac_unittest.cc
+++ b/components/spellcheck/browser/spellcheck_platform_mac_unittest.cc
@@ -49,8 +49,8 @@
                                   base::Unretained(this)));
   }
 
-  base::test::TaskEnvironment task_environment_{
-      base::test::TaskEnvironment::MainThreadType::UI};
+  base::test::SingleThreadTaskEnvironment task_environment_{
+      base::test::SingleThreadTaskEnvironment::MainThreadType::UI};
   spellcheck_platform::ScopedEnglishLanguageForTest scoped_language_;
 };
 
diff --git a/components/spellcheck/renderer/spellcheck_unittest.cc b/components/spellcheck/renderer/spellcheck_unittest.cc
index 69f05ff..cf56067 100644
--- a/components/spellcheck/renderer/spellcheck_unittest.cc
+++ b/components/spellcheck/renderer/spellcheck_unittest.cc
@@ -130,7 +130,7 @@
  private:
   spellcheck::EmptyLocalInterfaceProvider embedder_provider_;
   std::unique_ptr<SpellCheck> spell_check_;
-  base::test::TaskEnvironment task_environment_;
+  base::test::SingleThreadTaskEnvironment task_environment_;
 };
 
 struct MockTextCheckingResult {
diff --git a/components/sync/driver/profile_sync_service.cc b/components/sync/driver/profile_sync_service.cc
index dafc3840..558194c 100644
--- a/components/sync/driver/profile_sync_service.cc
+++ b/components/sync/driver/profile_sync_service.cc
@@ -865,7 +865,8 @@
   if (start_behavior_ == AUTO_START &&
       !user_settings_->IsFirstSetupComplete()) {
     // This will trigger a configure if it completes setup.
-    user_settings_->SetFirstSetupComplete();
+    user_settings_->SetFirstSetupComplete(
+        SyncFirstSetupCompleteSource::ENGINE_INITIALIZED_WITH_AUTO_START);
   } else if (CanConfigureDataTypes(/*bypass_setup_in_progress_check=*/false)) {
     // Datatype downloads on restart are generally due to newly supported
     // datatypes (although it's also possible we're picking up where a failed
diff --git a/components/sync/driver/profile_sync_service_startup_unittest.cc b/components/sync/driver/profile_sync_service_startup_unittest.cc
index 7b63954..4d60102 100644
--- a/components/sync/driver/profile_sync_service_startup_unittest.cc
+++ b/components/sync/driver/profile_sync_service_startup_unittest.cc
@@ -217,7 +217,8 @@
   EXPECT_CALL(*data_type_manager, Configure(_, _));
   ON_CALL(*data_type_manager, state())
       .WillByDefault(Return(DataTypeManager::CONFIGURED));
-  sync_service()->GetUserSettings()->SetFirstSetupComplete();
+  sync_service()->GetUserSettings()->SetFirstSetupComplete(
+      syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
 
   // This should have fully enabled sync.
   EXPECT_TRUE(sync_service()->IsSyncFeatureEnabled());
@@ -645,7 +646,8 @@
   // configuring the data types. Just marking the initial setup as complete
   // isn't enough though, because setup is still considered in progress (we
   // haven't released the setup-in-progress handle).
-  sync_service()->GetUserSettings()->SetFirstSetupComplete();
+  sync_service()->GetUserSettings()->SetFirstSetupComplete(
+      syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
   EXPECT_EQ(SyncService::TransportState::PENDING_DESIRED_CONFIGURATION,
             sync_service()->GetTransportState());
   EXPECT_TRUE(sync_service()->IsSyncFeatureEnabled());
diff --git a/components/sync/driver/profile_sync_service_unittest.cc b/components/sync/driver/profile_sync_service_unittest.cc
index 6c50207..d650ef7d 100644
--- a/components/sync/driver/profile_sync_service_unittest.cc
+++ b/components/sync/driver/profile_sync_service_unittest.cc
@@ -448,7 +448,8 @@
 
   // Once we mark first setup complete again (it was cleared by the policy) and
   // sign in, sync starts up.
-  service()->GetUserSettings()->SetFirstSetupComplete();
+  service()->GetUserSettings()->SetFirstSetupComplete(
+      syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
   SignIn();
   EXPECT_EQ(SyncService::TransportState::ACTIVE,
             service()->GetTransportState());
diff --git a/components/sync/driver/sync_user_settings.h b/components/sync/driver/sync_user_settings.h
index 3bfca3c..d099c4d 100644
--- a/components/sync/driver/sync_user_settings.h
+++ b/components/sync/driver/sync_user_settings.h
@@ -16,6 +16,18 @@
 
 namespace syncer {
 
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class SyncFirstSetupCompleteSource {
+  BASIC_FLOW = 0,
+  ADVANCED_FLOW_CONFIRM = 1,
+  ADVANCED_FLOW_INTERRUPTED_TURN_SYNC_ON = 2,
+  ADVANCED_FLOW_INTERRUPTED_LEAVE_SYNC_OFF = 3,
+  ENGINE_INITIALIZED_WITH_AUTO_START = 4,
+  kMaxValue = ENGINE_INITIALIZED_WITH_AUTO_START,
+};
+
 // This class encapsulates all the user-configurable bits of Sync.
 class SyncUserSettings : public syncer::DataTypeEncryptionHandler {
  public:
@@ -40,7 +52,7 @@
   // NOTE: On Android and ChromeOS, this gets set automatically, so it doesn't
   // really mean anything. See |browser_defaults::kSyncAutoStarts|.
   virtual bool IsFirstSetupComplete() const = 0;
-  virtual void SetFirstSetupComplete() = 0;
+  virtual void SetFirstSetupComplete(SyncFirstSetupCompleteSource source) = 0;
 
   // The user's selected types. The "sync everything" flag means to sync all
   // current and future data types. If it is set, then GetSelectedTypes() will
diff --git a/components/sync/driver/sync_user_settings_impl.cc b/components/sync/driver/sync_user_settings_impl.cc
index 7782c57..c7a8fd11 100644
--- a/components/sync/driver/sync_user_settings_impl.cc
+++ b/components/sync/driver/sync_user_settings_impl.cc
@@ -65,7 +65,11 @@
   return prefs_->IsFirstSetupComplete();
 }
 
-void SyncUserSettingsImpl::SetFirstSetupComplete() {
+void SyncUserSettingsImpl::SetFirstSetupComplete(
+    SyncFirstSetupCompleteSource source) {
+  if (IsFirstSetupComplete())
+    return;
+  UMA_HISTOGRAM_ENUMERATION("Signin.SyncFirstSetupCompleteSource", source);
   prefs_->SetFirstSetupComplete();
 }
 
diff --git a/components/sync/driver/sync_user_settings_impl.h b/components/sync/driver/sync_user_settings_impl.h
index 29e5b219..56252b4 100644
--- a/components/sync/driver/sync_user_settings_impl.h
+++ b/components/sync/driver/sync_user_settings_impl.h
@@ -38,7 +38,7 @@
   void SetSyncAllowedByPlatform(bool allowed) override;
 
   bool IsFirstSetupComplete() const override;
-  void SetFirstSetupComplete() override;
+  void SetFirstSetupComplete(SyncFirstSetupCompleteSource source) override;
 
   bool IsSyncEverythingEnabled() const override;
   UserSelectableTypeSet GetSelectedTypes() const override;
diff --git a/components/sync/driver/sync_user_settings_mock.h b/components/sync/driver/sync_user_settings_mock.h
index 980c67e..fd72dd3 100644
--- a/components/sync/driver/sync_user_settings_mock.h
+++ b/components/sync/driver/sync_user_settings_mock.h
@@ -24,7 +24,7 @@
   MOCK_METHOD1(SetSyncAllowedByPlatform, void(bool));
 
   MOCK_CONST_METHOD0(IsFirstSetupComplete, bool());
-  MOCK_METHOD0(SetFirstSetupComplete, void());
+  MOCK_METHOD1(SetFirstSetupComplete, void(SyncFirstSetupCompleteSource));
 
   MOCK_CONST_METHOD0(IsSyncEverythingEnabled, bool());
   MOCK_CONST_METHOD0(GetSelectedTypes, UserSelectableTypeSet());
diff --git a/components/sync/driver/test_sync_service.cc b/components/sync/driver/test_sync_service.cc
index 974e1d6..6f1c802 100644
--- a/components/sync/driver/test_sync_service.cc
+++ b/components/sync/driver/test_sync_service.cc
@@ -74,7 +74,10 @@
 }
 
 void TestSyncService::SetFirstSetupComplete(bool first_setup_complete) {
-  user_settings_.SetFirstSetupComplete(first_setup_complete);
+  if (first_setup_complete)
+    user_settings_.SetFirstSetupComplete();
+  else
+    user_settings_.ClearFirstSetupComplete();
 }
 
 void TestSyncService::SetPreferredDataTypes(const ModelTypeSet& types) {
diff --git a/components/sync/driver/test_sync_user_settings.cc b/components/sync/driver/test_sync_user_settings.cc
index 65cac6e..ce94b10 100644
--- a/components/sync/driver/test_sync_user_settings.cc
+++ b/components/sync/driver/test_sync_user_settings.cc
@@ -50,8 +50,9 @@
   return first_setup_complete_;
 }
 
-void TestSyncUserSettings::SetFirstSetupComplete() {
-  SetFirstSetupComplete(true);
+void TestSyncUserSettings::SetFirstSetupComplete(
+    SyncFirstSetupCompleteSource source) {
+  SetFirstSetupComplete();
 }
 
 bool TestSyncUserSettings::IsSyncEverythingEnabled() const {
@@ -146,8 +147,12 @@
   return false;
 }
 
-void TestSyncUserSettings::SetFirstSetupComplete(bool first_setup_complete) {
-  first_setup_complete_ = first_setup_complete;
+void TestSyncUserSettings::SetFirstSetupComplete() {
+  first_setup_complete_ = true;
+}
+
+void TestSyncUserSettings::ClearFirstSetupComplete() {
+  first_setup_complete_ = false;
 }
 
 void TestSyncUserSettings::SetPassphraseRequired(bool required) {
diff --git a/components/sync/driver/test_sync_user_settings.h b/components/sync/driver/test_sync_user_settings.h
index ef3bf5a4..ba387ae 100644
--- a/components/sync/driver/test_sync_user_settings.h
+++ b/components/sync/driver/test_sync_user_settings.h
@@ -27,7 +27,7 @@
   void SetSyncAllowedByPlatform(bool allowed) override;
 
   bool IsFirstSetupComplete() const override;
-  void SetFirstSetupComplete() override;
+  void SetFirstSetupComplete(SyncFirstSetupCompleteSource source) override;
 
   bool IsSyncEverythingEnabled() const override;
   UserSelectableTypeSet GetSelectedTypes() const override;
@@ -50,7 +50,8 @@
   void SetEncryptionPassphrase(const std::string& passphrase) override;
   bool SetDecryptionPassphrase(const std::string& passphrase) override;
 
-  void SetFirstSetupComplete(bool first_setup_complete);
+  void SetFirstSetupComplete();
+  void ClearFirstSetupComplete();
   void SetEncryptEverythingAllowed(bool allowed);
   void SetPassphraseRequired(bool required);
   void SetPassphraseRequiredForDecryption(bool required);
diff --git a/components/sync/engine_impl/model_type_worker.cc b/components/sync/engine_impl/model_type_worker.cc
index fb01ab2..a4acbb9 100644
--- a/components/sync/engine_impl/model_type_worker.cc
+++ b/components/sync/engine_impl/model_type_worker.cc
@@ -15,7 +15,6 @@
 #include "base/format_macros.h"
 #include "base/guid.h"
 #include "base/logging.h"
-#include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/stringprintf.h"
 #include "base/trace_event/memory_usage_estimator.h"
@@ -198,7 +197,6 @@
     }
   }
 
-  std::vector<std::string> client_tag_hashes;
   for (const sync_pb::SyncEntity* update_entity : applicable_updates) {
     if (update_entity->deleted()) {
       status->increment_num_tombstone_updates_downloaded_by(1);
@@ -211,9 +209,6 @@
     switch (PopulateUpdateResponseData(cryptographer_.get(), type_,
                                        *update_entity, response_data.get())) {
       case SUCCESS:
-        if (!response_data->entity->client_tag_hash.empty()) {
-          client_tag_hashes.push_back(response_data->entity->client_tag_hash);
-        }
         pending_updates_.push_back(std::move(response_data));
         break;
       case DECRYPTION_PENDING:
@@ -225,10 +220,6 @@
         break;
     }
   }
-  std::string suffix = ModelTypeToHistogramSuffix(type_);
-  base::UmaHistogramBoolean(
-      "Sync.DuplicateClientTagHashInGetUpdatesResponse." + suffix,
-      ContainsDuplicate(std::move(client_tag_hashes)));
 
   debug_info_emitter_->EmitUpdateCountersUpdate();
   return SyncerError(SyncerError::SYNCER_OK);
@@ -407,42 +398,20 @@
            << base::StringPrintf("Delivering %" PRIuS " applicable updates.",
                                  pending_updates_.size());
 
-  const bool contains_duplicate_server_ids =
-      ContainsDuplicateServerID(pending_updates_);
-  const bool contains_duplicate_client_tag_hashes =
-      ContainsDuplicateClientTagHash(pending_updates_);
-
   // Having duplicates should be rare, so only do the de-duping if
   // we've actually detected one.
 
   // Deduplicate updates first based on server ids.
-  if (contains_duplicate_server_ids) {
+  if (ContainsDuplicateServerID(pending_updates_)) {
     DeduplicatePendingUpdatesBasedOnServerId();
   }
 
   // Check for duplicate client tag hashes after removing duplicate server
-  // ids.
-  const bool contains_duplicate_client_tag_hashes_after_deduping_server_ids =
-      ContainsDuplicateClientTagHash(pending_updates_);
-
-  // Deduplicate updates based on client tag hashes.
-  if (contains_duplicate_client_tag_hashes_after_deduping_server_ids) {
+  // ids, and deduplicate updates based on client tag hashes if necessary.
+  if (ContainsDuplicateClientTagHash(pending_updates_)) {
     DeduplicatePendingUpdatesBasedOnClientTagHash();
   }
 
-  std::string suffix = ModelTypeToHistogramSuffix(type_);
-  base::UmaHistogramBoolean(
-      "Sync.DuplicateClientTagHashInApplyPendingUpdates." + suffix,
-      contains_duplicate_client_tag_hashes);
-  base::UmaHistogramBoolean(
-      "Sync.DuplicateServerIdInApplyPendingUpdates." + suffix,
-      contains_duplicate_server_ids);
-  base::UmaHistogramBoolean(
-      "Sync."
-      "DuplicateClientTagHashWithDifferentServerIdsInApplyPendingUpdates." +
-          suffix,
-      contains_duplicate_client_tag_hashes_after_deduping_server_ids);
-
   int num_updates_applied = pending_updates_.size();
   model_type_processor_->OnUpdateReceived(model_type_state_,
                                           std::move(pending_updates_));
diff --git a/components/sync/engine_impl/model_type_worker_unittest.cc b/components/sync/engine_impl/model_type_worker_unittest.cc
index 4a9964a0..c8467eae 100644
--- a/components/sync/engine_impl/model_type_worker_unittest.cc
+++ b/components/sync/engine_impl/model_type_worker_unittest.cc
@@ -745,30 +745,11 @@
 TEST_F(ModelTypeWorkerTest, ReceiveUpdates_NoDuplicateHash) {
   NormalInitialize();
 
-  base::HistogramTester histograms;
-
   TriggerPartialUpdateFromServer(10, kTag1, kValue1, kTag2, kValue2);
   TriggerPartialUpdateFromServer(10, kTag3, kValue3);
 
-  // No duplicates in either of the partial updates.
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateClientTagHashInGetUpdatesResponse.PREFERENCE",
-      /*sample=*/false, /*count=*/2);
-
   ApplyUpdates();
 
-  // No duplicate across the partial updates either.
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateClientTagHashInApplyPendingUpdates.PREFERENCE",
-      /*sample=*/false, /*count=*/1);
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateServerIdInApplyPendingUpdates.PREFERENCE",
-      /*sample=*/false, /*count=*/1);
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateClientTagHashWithDifferentServerIdsInApplyPendingUpdates."
-      "PREFERENCE",
-      /*sample=*/false, /*count=*/1);
-
   // Make sure all the updates arrived, in order.
   ASSERT_EQ(1u, processor()->GetNumUpdateResponses());
   std::vector<const UpdateResponseData*> result =
@@ -785,29 +766,11 @@
 TEST_F(ModelTypeWorkerTest, ReceiveUpdates_DuplicateHashWithinPartialUpdate) {
   NormalInitialize();
 
-  base::HistogramTester histograms;
-
   // Note that kTag1 appears twice.
   TriggerPartialUpdateFromServer(10, kTag1, kValue1, kTag1, kValue2);
 
-  // There was a duplicate.
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateClientTagHashInGetUpdatesResponse.PREFERENCE",
-      /*sample=*/true, /*count=*/1);
-
   ApplyUpdates();
 
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateClientTagHashInApplyPendingUpdates.PREFERENCE",
-      /*sample=*/true, /*count=*/1);
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateServerIdInApplyPendingUpdates.PREFERENCE",
-      /*sample=*/true, /*count=*/1);
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateClientTagHashWithDifferentServerIdsInApplyPendingUpdates."
-      "PREFERENCE",
-      /*sample=*/false, /*count=*/1);
-
   // Make sure the duplicate entry got de-duped, and the last one won.
   ASSERT_EQ(1u, processor()->GetNumUpdateResponses());
   std::vector<const UpdateResponseData*> result =
@@ -821,31 +784,12 @@
 TEST_F(ModelTypeWorkerTest, ReceiveUpdates_DuplicateHashAcrossPartialUpdates) {
   NormalInitialize();
 
-  base::HistogramTester histograms;
-
   // Note that kTag1 appears in both partial updates.
   TriggerPartialUpdateFromServer(10, kTag1, kValue1);
   TriggerPartialUpdateFromServer(10, kTag1, kValue2);
 
-  // Neither of the two partial updates contained duplicates.
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateClientTagHashInGetUpdatesResponse.PREFERENCE",
-      /*sample=*/false, /*count=*/2);
-
   ApplyUpdates();
 
-  // But there was a duplicate across the two partial updates.
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateClientTagHashInApplyPendingUpdates.PREFERENCE",
-      /*sample=*/true, /*count=*/1);
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateServerIdInApplyPendingUpdates.PREFERENCE",
-      /*sample=*/true, /*count=*/1);
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateClientTagHashWithDifferentServerIdsInApplyPendingUpdates."
-      "PREFERENCE",
-      /*sample=*/false, /*count=*/1);
-
   // Make sure the duplicate entry got de-duped, and the last one won.
   ASSERT_EQ(1u, processor()->GetNumUpdateResponses());
   std::vector<const UpdateResponseData*> result =
@@ -859,7 +803,6 @@
 TEST_F(ModelTypeWorkerTest,
        ReceiveUpdates_EmptyHashNotConsideredDuplicateIfForDistinctServerIds) {
   NormalInitialize();
-  base::HistogramTester histograms;
   // First create two entities with different tags, so they get assigned
   // different server ids.
   SyncEntity entity1 = server()->UpdateFromServer(
@@ -877,25 +820,8 @@
       server()->GetProgress(), server()->GetContext(), {&entity1, &entity2},
       status_controller());
 
-  // No duplicates in either of the partial updates.
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateClientTagHashInGetUpdatesResponse.PREFERENCE",
-      /*sample=*/false, /*count=*/1);
-
   ApplyUpdates();
 
-  // No duplicate server ids, but duplicate client tag hashes.
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateClientTagHashInApplyPendingUpdates.PREFERENCE",
-      /*sample=*/false, /*count=*/1);
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateServerIdInApplyPendingUpdates.PREFERENCE",
-      /*sample=*/false, /*count=*/1);
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateClientTagHashWithDifferentServerIdsInApplyPendingUpdates."
-      "PREFERENCE",
-      /*sample=*/false, /*count=*/1);
-
   // Make sure the empty client tag hashes did *not* get de-duped.
   ASSERT_EQ(1u, processor()->GetNumUpdateResponses());
   std::vector<const UpdateResponseData*> result =
@@ -910,8 +836,6 @@
 TEST_F(ModelTypeWorkerTest, ReceiveUpdates_MultipleDuplicateHashes) {
   NormalInitialize();
 
-  base::HistogramTester histograms;
-
   TriggerPartialUpdateFromServer(10, kTag1, kValue3);
   TriggerPartialUpdateFromServer(10, kTag2, kValue3);
   TriggerPartialUpdateFromServer(10, kTag3, kValue3);
@@ -921,24 +845,8 @@
 
   TriggerPartialUpdateFromServer(10, kTag1, kValue1);
 
-  // None of the partial updates contained duplicates.
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateClientTagHashInGetUpdatesResponse.PREFERENCE",
-      /*sample=*/false, /*count=*/6);
-
   ApplyUpdates();
 
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateClientTagHashInApplyPendingUpdates.PREFERENCE",
-      /*sample=*/true, /*count=*/1);
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateServerIdInApplyPendingUpdates.PREFERENCE",
-      /*sample=*/true, /*count=*/1);
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateClientTagHashWithDifferentServerIdsInApplyPendingUpdates."
-      "PREFERENCE",
-      /*sample=*/false, /*count=*/1);
-
   // Make sure the duplicate entries got de-duped, and the last one won.
   ASSERT_EQ(1u, processor()->GetNumUpdateResponses());
   std::vector<const UpdateResponseData*> result =
@@ -962,8 +870,6 @@
   // emitted. This scenario is considered a bug on the server.
   NormalInitialize();
 
-  base::HistogramTester histograms;
-
   // First create two entities with different tags, so they get assigned
   // different server ids.
   SyncEntity entity1 = server()->UpdateFromServer(
@@ -979,25 +885,8 @@
       server()->GetProgress(), server()->GetContext(), {&entity1, &entity2},
       status_controller());
 
-  // No duplicates in either of the partial updates.
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateClientTagHashInGetUpdatesResponse.PREFERENCE",
-      /*sample=*/true, /*count=*/1);
-
   ApplyUpdates();
 
-  // No duplicate server ids, but duplicate client tag hashes.
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateClientTagHashInApplyPendingUpdates.PREFERENCE",
-      /*sample=*/true, /*count=*/1);
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateServerIdInApplyPendingUpdates.PREFERENCE",
-      /*sample=*/false, /*count=*/1);
-  histograms.ExpectUniqueSample(
-      "Sync.DuplicateClientTagHashWithDifferentServerIdsInApplyPendingUpdates."
-      "PREFERENCE",
-      /*sample=*/true, /*count=*/1);
-
   // Make sure the first update has been discarded.
   ASSERT_EQ(1u, processor()->GetNumUpdateResponses());
   std::vector<const UpdateResponseData*> result =
diff --git a/components/ukm/ukm_service.cc b/components/ukm/ukm_service.cc
index 581cbf7..614281b 100644
--- a/components/ukm/ukm_service.cc
+++ b/components/ukm/ukm_service.cc
@@ -225,6 +225,9 @@
   DVLOG(1) << "UkmService::FinishedInitTask";
   initialize_complete_ = true;
   scheduler_->InitTaskComplete();
+  if (initialization_complete_callback_) {
+    std::move(initialization_complete_callback_).Run();
+  }
 }
 
 void UkmService::RotateLog() {
@@ -268,4 +271,13 @@
   return restrict_to_whitelist_entries_;
 }
 
+void UkmService::SetInitializationCompleteCallbackForTesting(base::OnceClosure callback) {
+  if (initialize_complete_) {
+    std::move(callback).Run();
+  } else {
+    // Store the callback to be invoked when initialization is complete later.
+    initialization_complete_callback_ = std::move(callback);
+  }
+}
+
 }  // namespace ukm
diff --git a/components/ukm/ukm_service.h b/components/ukm/ukm_service.h
index a510c285..6076c6a 100644
--- a/components/ukm/ukm_service.h
+++ b/components/ukm/ukm_service.h
@@ -121,6 +121,8 @@
   // ukm::UkmRecorderImpl:
   bool ShouldRestrictToWhitelistedEntries() const override;
 
+  void SetInitializationCompleteCallbackForTesting(base::OnceClosure callback);
+
   // A weak pointer to the PrefService used to read and write preferences.
   PrefService* pref_service_;
 
@@ -154,6 +156,9 @@
   bool initialize_started_ = false;
   bool initialize_complete_ = false;
 
+  // A callback invoked when initialization of the service is complete.
+  base::OnceClosure initialization_complete_callback_;
+
   SEQUENCE_CHECKER(sequence_checker_);
 
   // Weak pointers factory used to post task on different threads. All weak
diff --git a/components/url_formatter/spoof_checks/idn_spoof_checker.cc b/components/url_formatter/spoof_checks/idn_spoof_checker.cc
index 6394179..98152532 100644
--- a/components/url_formatter/spoof_checks/idn_spoof_checker.cc
+++ b/components/url_formatter/spoof_checks/idn_spoof_checker.cc
@@ -193,7 +193,7 @@
   //     TODO: see https://crbug.com/843352 for further work on
   //     U+0525 and U+0153.
   //   - {U+0167 (ŧ), U+0442 (т), U+04AD (ҭ), U+050F (ԏ), U+4E03 (七),
-  //     U+4E05 (丅), U+4E06 (丆)} => t
+  //     U+4E05 (丅), U+4E06 (丆), U+4E01 (丁)} => t
   //   - {U+0185 (ƅ), U+044C (ь), U+048D (ҍ), U+0432 (в)} => b
   //   - {U+03C9 (ω), U+0448 (ш), U+0449 (щ), U+0E1E (พ),
   //      U+0E1F (ฟ), U+0E9E (ພ), U+0E9F (ຟ)} => w
@@ -230,7 +230,7 @@
       icu::UnicodeString::fromUTF8(
           "[æӕ] > ae; [þϼҏ] > p; [ħнћңҥӈӊԋԧԩ] > h;"
           "[ĸκкқҝҟҡӄԟ] > k; [ŋпԥกח] > n; œ > ce;"
-          "[ŧтҭԏ七丅丆] > t; [ƅьҍв] > b;  [ωшщพฟພຟ] > w;"
+          "[ŧтҭԏ七丅丆丁] > t; [ƅьҍв] > b;  [ωшщพฟພຟ] > w;"
           "[мӎ] > m; [єҽҿၔ] > e; ґ > r; [ғӻ] > f;"
           "[ҫင] > c; [ұ丫] > y; [χҳӽӿ乂] > x;"
           "[ԃძ]  > d; [ԍဌ] > g; [ടรຣຮ] > s; ၂ > j;"
diff --git a/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc b/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc
index e6494ea..e6ed4a0 100644
--- a/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc
+++ b/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc
@@ -1077,6 +1077,7 @@
     {"xn--est-118d.net", L"七est.net", false},
     {"xn--est-918d.net", L"丅est.net", false},
     {"xn--est-e28d.net", L"丆est.net", false},
+    {"xn--est-t18d.net", L"丁est.net", false},
     {"xn--3-cq6a.com", L"丩3.com", false},
     {"xn--cxe-n68d.com", L"c丫xe.com", false},
     {"xn--cye-b98d.com", L"cy乂e.com", false},
diff --git a/components/viz/host/hit_test/hit_test_query.cc b/components/viz/host/hit_test/hit_test_query.cc
index 0112362..959b9a985 100644
--- a/components/viz/host/hit_test/hit_test_query.cc
+++ b/components/viz/host/hit_test/hit_test_query.cc
@@ -6,6 +6,7 @@
 
 #include "base/containers/stack.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/strings/string_util.h"
 #include "base/timer/elapsed_timer.h"
 #include "components/viz/common/features.h"
 #include "components/viz/common/hit_test/hit_test_region_list.h"
@@ -32,48 +33,43 @@
 }
 
 const std::string GetFlagNames(uint32_t flag) {
-  std::string names = "";
-  uint32_t mask = 1;
+  std::vector<base::StringPiece> names;
 
-  while (flag) {
-    std::string name = "";
-    switch (flag & mask) {
-      case kHitTestMine:
-        name = "Mine";
-        break;
-      case kHitTestIgnore:
-        name = "Ignore";
-        break;
-      case kHitTestChildSurface:
-        name = "ChildSurface";
-        break;
-      case kHitTestAsk:
-        name = "Ask";
-        break;
-      case kHitTestMouse:
-        name = "Mouse";
-        break;
-      case kHitTestTouch:
-        name = "Touch";
-        break;
-      case kHitTestNotActive:
-        name = "NotActive";
-        break;
-      case kHitTestDebug:
-        name = "Debug";
-        break;
-      case 0:
-        break;
-    }
-    if (!name.empty()) {
-      names += names.empty() ? name : ", " + name;
-    }
+  if (flag & kHitTestMine)
+    names.emplace_back("Mine");
+  if (flag & kHitTestIgnore)
+    names.emplace_back("Ignore");
+  if (flag & kHitTestChildSurface)
+    names.emplace_back("ChildSurface");
+  if (flag & kHitTestAsk)
+    names.emplace_back("Ask");
+  if (flag & kHitTestMouse)
+    names.emplace_back("Mouse");
+  if (flag & kHitTestTouch)
+    names.emplace_back("Touch");
+  if (flag & kHitTestNotActive)
+    names.emplace_back("NotActive");
+  if (flag & kHitTestDebug)
+    names.emplace_back("Debug");
 
-    flag &= ~mask;
-    mask <<= 1;
-  }
+  return base::JoinString(std::move(names), ", ");
+}
 
-  return names;
+const std::string GetAsyncHitTestReasons(uint32_t async_hit_test_reasons) {
+  std::vector<base::StringPiece> reasons;
+
+  if (async_hit_test_reasons & kOverlappedRegion)
+    reasons.emplace_back("OverlappedRegion");
+  if (async_hit_test_reasons & kIrregularClip)
+    reasons.emplace_back("IrregularClip");
+  if (async_hit_test_reasons & kRegionNotActive)
+    reasons.emplace_back("RegionNotActive");
+  if (async_hit_test_reasons & kPerspectiveTransform)
+    reasons.emplace_back("PerspectiveTransform");
+  if (async_hit_test_reasons & kUseDrawQuadData)
+    reasons.emplace_back("UseDrawQuadData");
+
+  return reasons.empty() ? "None" : base::JoinString(std::move(reasons), ", ");
 }
 
 }  // namespace
@@ -398,6 +394,8 @@
     oss << tabs << "Index: " << i << '\n';
     oss << tabs << "Children: " << htr.child_count << '\n';
     oss << tabs << "Flags: " << GetFlagNames(htr.flags) << '\n';
+    oss << tabs << "AsyncHitTestReasons: "
+        << GetAsyncHitTestReasons(htr.async_hit_test_reasons) << '\n';
     oss << tabs << "Frame Sink Id: " << htr.frame_sink_id.ToString() << '\n';
     oss << tabs << "Rect: " << htr.rect.ToString() << '\n';
     oss << tabs << "Transform:" << '\n';
diff --git a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc
index 38be463..9116f9c 100644
--- a/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc
+++ b/components/viz/service/compositor_frame_fuzzer/compositor_frame_fuzzer_util.cc
@@ -153,12 +153,14 @@
 
 FuzzedData FuzzedCompositorFrameBuilder::Build(
     const proto::RenderPass& render_pass_spec) {
+  static FrameTokenGenerator next_frame_token;
+
   data_.frame.metadata.begin_frame_ack.source_id =
       BeginFrameArgs::kManualSourceId;
   data_.frame.metadata.begin_frame_ack.sequence_number =
       BeginFrameArgs::kStartingFrameNumber;
   data_.frame.metadata.begin_frame_ack.has_damage = true;
-  data_.frame.metadata.frame_token = 1;
+  data_.frame.metadata.frame_token = ++next_frame_token;
   data_.frame.metadata.device_scale_factor = 1;
   data_.frame.metadata.local_surface_id_allocation_time =
       base::TimeTicks::Now();
diff --git a/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc b/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc
index be0cb34..25fb1bd 100644
--- a/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc
+++ b/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.cc
@@ -113,7 +113,7 @@
     SurfaceId renderer_surface_id) {
   CompositorFrame frame;
 
-  frame.metadata.frame_token = 1;
+  frame.metadata.frame_token = ++next_frame_token_;
   frame.metadata.begin_frame_ack.source_id = BeginFrameArgs::kManualSourceId;
   frame.metadata.begin_frame_ack.sequence_number =
       BeginFrameArgs::kStartingFrameNumber;
diff --git a/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.h b/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.h
index f27762f..68088e0 100644
--- a/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.h
+++ b/components/viz/service/compositor_frame_fuzzer/fuzzer_browser_process.h
@@ -58,6 +58,8 @@
 
   ParentLocalSurfaceIdAllocator lsi_allocator_;
 
+  FrameTokenGenerator next_frame_token_;
+
   DISALLOW_COPY_AND_ASSIGN(FuzzerBrowserProcess);
 };
 
diff --git a/components/viz/service/display/renderer_perftest.cc b/components/viz/service/display/renderer_perftest.cc
index f6ad154d..d05ff198 100644
--- a/components/viz/service/display/renderer_perftest.cc
+++ b/components/viz/service/display/renderer_perftest.cc
@@ -11,7 +11,8 @@
 //
 // $ out/release/viz_perftests --gtest_filter="*RendererPerfTest*" \
 //    --use-gpu-in-tests --test-launcher-timeout=300000 \
-//    --perf-test-time-ms=240000
+//    --perf-test-time-ms=240000 --disable_discard_framebuffer=1 \
+//    --use_virtualized_gl_contexts=1
 
 #include "base/bind.h"
 #include "base/command_line.h"
@@ -115,6 +116,7 @@
   const gfx::Transform transform_to_root_target;
   std::unique_ptr<RenderPass> pass = RenderPass::Create();
   pass->SetNew(id, output_rect, damage_rect, transform_to_root_target);
+  pass->has_transparent_background = false;
   return pass;
 }
 
diff --git a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
index 6a1979c..5cdf328 100644
--- a/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
+++ b/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
@@ -293,8 +293,7 @@
     const BeginFrameArgs& args,
     const FrameTimingDetailsMap& timing_details) {
   for (const auto& pair : timing_details)
-    client_->DidPresentCompositorFrame(pair.first,
-                                       pair.second.presentation_feedback);
+    client_->DidPresentCompositorFrame(pair.first, pair.second);
 
   DCHECK_LE(pipeline_reporting_frame_times_.size(), 25u);
   if (args.trace_id != -1) {
diff --git a/content/browser/accessibility/accessibility_win_browsertest.cc b/content/browser/accessibility/accessibility_win_browsertest.cc
index 62580ccf..ecea63e 100644
--- a/content/browser/accessibility/accessibility_win_browsertest.cc
+++ b/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -3520,6 +3520,53 @@
   accessible_cell.Reset();
 }
 
+IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestTreegridIsIATable) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+                                         ui::kAXModeComplete,
+                                         ax::mojom::Event::kLoadComplete);
+  EXPECT_TRUE(
+      NavigateToURL(shell(), embedded_test_server()->GetURL(
+                                 "/accessibility/aria/aria-treegrid.html")));
+  waiter.WaitForNotification();
+
+  Microsoft::WRL::ComPtr<IAccessible> document(GetRendererAccessible());
+  std::vector<base::win::ScopedVariant> document_children =
+      GetAllAccessibleChildren(document.Get());
+  // There are two treegrids in this test file. Use only the first one.
+  ASSERT_EQ(2u, document_children.size());
+
+  Microsoft::WRL::ComPtr<IAccessible2> table;
+  ASSERT_HRESULT_SUCCEEDED(QueryIAccessible2(
+      GetAccessibleFromVariant(document.Get(), document_children[0].AsInput())
+          .Get(),
+      &table));
+  LONG role = 0;
+  ASSERT_HRESULT_SUCCEEDED(table->role(&role));
+  ASSERT_EQ(ROLE_SYSTEM_OUTLINE, role);
+
+  // Retrieve the first cell.
+  Microsoft::WRL::ComPtr<IAccessibleTable2> table2;
+  Microsoft::WRL::ComPtr<IUnknown> cell;
+  Microsoft::WRL::ComPtr<IAccessible2> cell1;
+  EXPECT_HRESULT_SUCCEEDED(table.CopyTo(IID_PPV_ARGS(&table2)));
+  EXPECT_HRESULT_SUCCEEDED(table2->get_cellAt(0, 0, &cell));
+  EXPECT_HRESULT_SUCCEEDED(cell.CopyTo(IID_PPV_ARGS(&cell1)));
+
+  base::win::ScopedVariant childid_self(CHILDID_SELF);
+  Microsoft::WRL::ComPtr<IAccessibleTableCell> accessible_cell;
+  LONG row_index = -1;
+  LONG column_index = -1;
+  EXPECT_HRESULT_SUCCEEDED(cell1->role(&role));
+  EXPECT_EQ(ROLE_SYSTEM_CELL, role);
+  EXPECT_HRESULT_SUCCEEDED(cell1.CopyTo(IID_PPV_ARGS(&accessible_cell)));
+  EXPECT_HRESULT_SUCCEEDED(accessible_cell->get_rowIndex(&row_index));
+  EXPECT_HRESULT_SUCCEEDED(accessible_cell->get_columnIndex(&column_index));
+  EXPECT_EQ(0, row_index);
+  EXPECT_EQ(0, column_index);
+  accessible_cell.Reset();
+}
+
 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestScrollTo) {
   LoadInitialAccessibilityTreeFromHtml(
       R"HTML(<!DOCTYPE html>
diff --git a/content/browser/accessibility/browser_accessibility_com_win.cc b/content/browser/accessibility/browser_accessibility_com_win.cc
index 8fba7b5..a09eddcc 100644
--- a/content/browser/accessibility/browser_accessibility_com_win.cc
+++ b/content/browser/accessibility/browser_accessibility_com_win.cc
@@ -1603,7 +1603,7 @@
       return E_NOINTERFACE;
     }
   } else if (iid == IID_IAccessibleTable || iid == IID_IAccessibleTable2) {
-    if (ia_role != ROLE_SYSTEM_TABLE) {
+    if (!ui::IsTableLike(accessibility->owner()->GetRole())) {
       *object = nullptr;
       return E_NOINTERFACE;
     }
diff --git a/content/browser/battery_monitor_browsertest.cc b/content/browser/battery_monitor_browsertest.cc
index f21ab47..508facb 100644
--- a/content/browser/battery_monitor_browsertest.cc
+++ b/content/browser/battery_monitor_browsertest.cc
@@ -13,6 +13,7 @@
 #include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "services/device/public/mojom/battery_monitor.mojom.h"
 #include "services/device/public/mojom/battery_status.mojom.h"
diff --git a/content/browser/bluetooth/frame_connected_bluetooth_devices.cc b/content/browser/bluetooth/frame_connected_bluetooth_devices.cc
index b53f58e9..b870c0cb 100644
--- a/content/browser/bluetooth/frame_connected_bluetooth_devices.cc
+++ b/content/browser/bluetooth/frame_connected_bluetooth_devices.cc
@@ -9,18 +9,20 @@
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/web_contents.h"
 #include "device/bluetooth/bluetooth_gatt_connection.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
 
 namespace content {
 
 struct GATTConnectionAndServerClient {
   GATTConnectionAndServerClient(
       std::unique_ptr<device::BluetoothGattConnection> connection,
-      blink::mojom::WebBluetoothServerClientAssociatedPtr client)
+      mojo::AssociatedRemote<blink::mojom::WebBluetoothServerClient> client)
       : gatt_connection(std::move(connection)),
         server_client(std::move(client)) {}
 
   std::unique_ptr<device::BluetoothGattConnection> gatt_connection;
-  blink::mojom::WebBluetoothServerClientAssociatedPtr server_client;
+  mojo::AssociatedRemote<blink::mojom::WebBluetoothServerClient> server_client;
 };
 
 FrameConnectedBluetoothDevices::FrameConnectedBluetoothDevices(
@@ -47,7 +49,7 @@
 void FrameConnectedBluetoothDevices::Insert(
     const blink::WebBluetoothDeviceId& device_id,
     std::unique_ptr<device::BluetoothGattConnection> connection,
-    blink::mojom::WebBluetoothServerClientAssociatedPtr client) {
+    mojo::AssociatedRemote<blink::mojom::WebBluetoothServerClient> client) {
   if (device_id_to_connection_map_.find(device_id) !=
       device_id_to_connection_map_.end()) {
     // It's possible for WebBluetoothServiceImpl to issue two successive
diff --git a/content/browser/bluetooth/frame_connected_bluetooth_devices.h b/content/browser/bluetooth/frame_connected_bluetooth_devices.h
index 2da3e3ca..f259b4d 100644
--- a/content/browser/bluetooth/frame_connected_bluetooth_devices.h
+++ b/content/browser/bluetooth/frame_connected_bluetooth_devices.h
@@ -11,6 +11,7 @@
 
 #include "base/optional.h"
 #include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
 #include "third_party/blink/public/common/bluetooth/web_bluetooth_device_id.h"
 #include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
 #include "url/origin.h"
@@ -43,9 +44,10 @@
 
   // If a connection doesn't exist already for |device_id|, adds a connection to
   // the map and increases the WebContents count of connected devices.
-  void Insert(const blink::WebBluetoothDeviceId& device_id,
-              std::unique_ptr<device::BluetoothGattConnection> connection,
-              blink::mojom::WebBluetoothServerClientAssociatedPtr client);
+  void Insert(
+      const blink::WebBluetoothDeviceId& device_id,
+      std::unique_ptr<device::BluetoothGattConnection> connection,
+      mojo::AssociatedRemote<blink::mojom::WebBluetoothServerClient> client);
 
   // Deletes the BluetoothGattConnection for |device_id| and decrements the
   // WebContents count of connected devices if |device_id| had a connection.
diff --git a/content/browser/bluetooth/frame_connected_bluetooth_devices_unittest.cc b/content/browser/bluetooth/frame_connected_bluetooth_devices_unittest.cc
index 6d89ce4b..e24ed2b 100644
--- a/content/browser/bluetooth/frame_connected_bluetooth_devices_unittest.cc
+++ b/content/browser/bluetooth/frame_connected_bluetooth_devices_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "content/browser/bluetooth/frame_connected_bluetooth_devices.h"
 
+#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "content/browser/bluetooth/web_bluetooth_service_impl.h"
 #include "content/test/test_render_view_host.h"
@@ -12,9 +13,10 @@
 #include "device/bluetooth/test/mock_bluetooth_adapter.h"
 #include "device/bluetooth/test/mock_bluetooth_device.h"
 #include "device/bluetooth/test/mock_bluetooth_gatt_connection.h"
-#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
 
 namespace content {
 
@@ -38,9 +40,10 @@
 constexpr char kDeviceAddress1[] = "1";
 constexpr char kDeviceName1[] = "Device1";
 
-blink::mojom::WebBluetoothServerClientAssociatedPtr CreateServerClient() {
-  blink::mojom::WebBluetoothServerClientAssociatedPtr client;
-  mojo::MakeRequestAssociatedWithDedicatedPipe(&client);
+mojo::AssociatedRemote<blink::mojom::WebBluetoothServerClient>
+CreateServerClient() {
+  mojo::AssociatedRemote<blink::mojom::WebBluetoothServerClient> client;
+  ignore_result(client.BindNewEndpointAndPassDedicatedReceiverForTesting());
   return client;
 }
 
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.cc b/content/browser/bluetooth/web_bluetooth_service_impl.cc
index 09be895..805ac88 100644
--- a/content/browser/bluetooth/web_bluetooth_service_impl.cc
+++ b/content/browser/bluetooth/web_bluetooth_service_impl.cc
@@ -11,6 +11,7 @@
 #include "content/browser/bluetooth/web_bluetooth_service_impl.h"
 
 #include <algorithm>
+#include <utility>
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
@@ -35,7 +36,12 @@
 #include "device/bluetooth/bluetooth_adapter_factory_wrapper.h"
 #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h"
 #include "device/bluetooth/bluetooth_remote_gatt_descriptor.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 #include "third_party/blink/public/common/bluetooth/web_bluetooth_device_id.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
 
 using device::BluetoothAdapterFactoryWrapper;
 using device::BluetoothUUID;
@@ -213,22 +219,23 @@
 struct GATTNotifySessionAndCharacteristicClient {
   GATTNotifySessionAndCharacteristicClient(
       std::unique_ptr<device::BluetoothGattNotifySession> session,
-      blink::mojom::WebBluetoothCharacteristicClientAssociatedPtr client)
+      mojo::AssociatedRemote<blink::mojom::WebBluetoothCharacteristicClient>
+          client)
       : gatt_notify_session(std::move(session)),
         characteristic_client(std::move(client)) {}
 
   std::unique_ptr<device::BluetoothGattNotifySession> gatt_notify_session;
-  blink::mojom::WebBluetoothCharacteristicClientAssociatedPtr
+  mojo::AssociatedRemote<blink::mojom::WebBluetoothCharacteristicClient>
       characteristic_client;
 };
 
 WebBluetoothServiceImpl::WebBluetoothServiceImpl(
     RenderFrameHost* render_frame_host,
-    blink::mojom::WebBluetoothServiceRequest request)
+    mojo::PendingReceiver<blink::mojom::WebBluetoothService> receiver)
     : WebContentsObserver(WebContents::FromRenderFrameHost(render_frame_host)),
       connected_devices_(new FrameConnectedBluetoothDevices(render_frame_host)),
       render_frame_host_(render_frame_host),
-      binding_(this, std::move(request)) {
+      receiver_(this, std::move(receiver)) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   CHECK(web_contents());
 }
@@ -240,7 +247,7 @@
 
 void WebBluetoothServiceImpl::SetClientConnectionErrorHandler(
     base::OnceClosure closure) {
-  binding_.set_connection_error_handler(std::move(closure));
+  receiver_.set_disconnect_handler(std::move(closure));
 }
 
 blink::mojom::WebBluetoothResult
@@ -332,7 +339,7 @@
 }
 
 WebBluetoothServiceImpl::ScanningClient::ScanningClient(
-    blink::mojom::WebBluetoothScanClientAssociatedPtr client,
+    mojo::AssociatedRemote<blink::mojom::WebBluetoothScanClient> client,
     blink::mojom::WebBluetoothRequestLEScanOptionsPtr options,
     RequestScanningStartCallback callback,
     BluetoothDeviceScanningPromptController* prompt_controller)
@@ -341,7 +348,7 @@
       callback_(std::move(callback)),
       prompt_controller_(prompt_controller) {
   DCHECK(options_->filters.has_value() || options_->accept_all_advertisements);
-  client_.set_connection_error_handler(base::BindRepeating(
+  client_.set_disconnect_handler(base::BindRepeating(
       &ScanningClient::DisconnectionHandler, base::Unretained(this)));
 }
 
@@ -676,7 +683,8 @@
 
 void WebBluetoothServiceImpl::RemoteServerConnect(
     const blink::WebBluetoothDeviceId& device_id,
-    blink::mojom::WebBluetoothServerClientAssociatedPtrInfo client,
+    mojo::PendingAssociatedRemote<blink::mojom::WebBluetoothServerClient>
+        client,
     RemoteServerConnectCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
@@ -710,9 +718,8 @@
   // abstraction allows to check for pending connections.
   // http://crbug.com/583544
   const base::TimeTicks start_time = base::TimeTicks::Now();
-  blink::mojom::WebBluetoothServerClientAssociatedPtr
-      web_bluetooth_server_client;
-  web_bluetooth_server_client.Bind(std::move(client));
+  mojo::AssociatedRemote<blink::mojom::WebBluetoothServerClient>
+      web_bluetooth_server_client(std::move(client));
 
   // TODO(crbug.com/730593): Remove AdaptCallbackForRepeating() by updating
   // the callee interface.
@@ -1034,7 +1041,8 @@
 
 void WebBluetoothServiceImpl::RemoteCharacteristicStartNotifications(
     const std::string& characteristic_instance_id,
-    blink::mojom::WebBluetoothCharacteristicClientAssociatedPtrInfo client,
+    mojo::PendingAssociatedRemote<
+        blink::mojom::WebBluetoothCharacteristicClient> client,
     RemoteCharacteristicStartNotificationsCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
@@ -1071,9 +1079,8 @@
     return;
   }
 
-  blink::mojom::WebBluetoothCharacteristicClientAssociatedPtr
-      characteristic_client;
-  characteristic_client.Bind(std::move(client));
+  mojo::AssociatedRemote<blink::mojom::WebBluetoothCharacteristicClient>
+      characteristic_client(std::move(client));
 
   // TODO(crbug.com/730593): Remove AdaptCallbackForRepeating() by updating
   // the callee interface.
@@ -1196,13 +1203,14 @@
 }
 
 void WebBluetoothServiceImpl::RequestScanningStart(
-    blink::mojom::WebBluetoothScanClientAssociatedPtrInfo client_info,
+    mojo::PendingAssociatedRemote<blink::mojom::WebBluetoothScanClient>
+        client_info,
     blink::mojom::WebBluetoothRequestLEScanOptionsPtr options,
     RequestScanningStartCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  blink::mojom::WebBluetoothScanClientAssociatedPtr client;
-  client.Bind(std::move(client_info));
+  mojo::AssociatedRemote<blink::mojom::WebBluetoothScanClient> client(
+      std::move(client_info));
 
   if (!GetAdapter()) {
     if (BluetoothAdapterFactoryWrapper::Get().IsLowEnergySupported()) {
@@ -1224,7 +1232,7 @@
 }
 
 void WebBluetoothServiceImpl::RequestScanningStartImpl(
-    blink::mojom::WebBluetoothScanClientAssociatedPtr client,
+    mojo::AssociatedRemote<blink::mojom::WebBluetoothScanClient> client,
     blink::mojom::WebBluetoothRequestLEScanOptionsPtr options,
     RequestScanningStartCallback callback,
     device::BluetoothAdapter* adapter) {
@@ -1303,7 +1311,7 @@
 }
 
 void WebBluetoothServiceImpl::OnStartDiscoverySession(
-    blink::mojom::WebBluetoothScanClientAssociatedPtr client,
+    mojo::AssociatedRemote<blink::mojom::WebBluetoothScanClient> client,
     blink::mojom::WebBluetoothRequestLEScanOptionsPtr options,
     std::unique_ptr<device::BluetoothDiscoverySession> session) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -1485,7 +1493,7 @@
 void WebBluetoothServiceImpl::OnCreateGATTConnectionSuccess(
     const blink::WebBluetoothDeviceId& device_id,
     base::TimeTicks start_time,
-    blink::mojom::WebBluetoothServerClientAssociatedPtr client,
+    mojo::AssociatedRemote<blink::mojom::WebBluetoothServerClient> client,
     RemoteServerConnectCallback callback,
     std::unique_ptr<device::BluetoothGattConnection> connection) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -1546,7 +1554,8 @@
 }
 
 void WebBluetoothServiceImpl::OnStartNotifySessionSuccess(
-    blink::mojom::WebBluetoothCharacteristicClientAssociatedPtr client,
+    mojo::AssociatedRemote<blink::mojom::WebBluetoothCharacteristicClient>
+        client,
     RemoteCharacteristicStartNotificationsCallback callback,
     std::unique_ptr<device::BluetoothGattNotifySession> notify_session) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -1753,7 +1762,7 @@
 void WebBluetoothServiceImpl::CrashRendererAndClosePipe(
     bad_message::BadMessageReason reason) {
   bad_message::ReceivedBadMessage(GetRenderProcessHost(), reason);
-  binding_.Close();
+  receiver_.reset();
 }
 
 url::Origin WebBluetoothServiceImpl::GetOrigin() {
@@ -1815,8 +1824,8 @@
 
 void WebBluetoothServiceImpl::ClearState() {
   // Releasing the adapter will drop references to callbacks that have not yet
-  // been executed. The binding must be closed first so that this is allowed.
-  binding_.Close();
+  // been executed. The receiver must be closed first so that this is allowed.
+  receiver_.reset();
 
   characteristic_id_to_notify_session_.clear();
   scanning_clients_.clear();
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.h b/content/browser/bluetooth/web_bluetooth_service_impl.h
index c45d8ec..232f9e2 100644
--- a/content/browser/bluetooth/web_bluetooth_service_impl.h
+++ b/content/browser/bluetooth/web_bluetooth_service_impl.h
@@ -24,8 +24,10 @@
 #include "device/bluetooth/bluetooth_gatt_notify_session.h"
 #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h"
 #include "device/bluetooth/bluetooth_remote_gatt_service.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "mojo/public/cpp/bindings/interface_ptr_set.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 #include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
 
 namespace url {
@@ -62,9 +64,10 @@
       public device::BluetoothAdapter::Observer {
  public:
   // |render_frame_host|: The RFH that owns this instance.
-  // |request|: The instance will be bound to this request's pipe.
-  WebBluetoothServiceImpl(RenderFrameHost* render_frame_host,
-                          blink::mojom::WebBluetoothServiceRequest request);
+  // |receiver|: The instance will be bound to this receiver's pipe.
+  WebBluetoothServiceImpl(
+      RenderFrameHost* render_frame_host,
+      mojo::PendingReceiver<blink::mojom::WebBluetoothService> receiver);
   ~WebBluetoothServiceImpl() override;
 
   void CrashRendererAndClosePipe(bad_message::BadMessageReason reason);
@@ -105,10 +108,11 @@
 
   class ScanningClient {
    public:
-    ScanningClient(blink::mojom::WebBluetoothScanClientAssociatedPtr client,
-                   blink::mojom::WebBluetoothRequestLEScanOptionsPtr options,
-                   RequestScanningStartCallback callback,
-                   BluetoothDeviceScanningPromptController* prompt_controller);
+    ScanningClient(
+        mojo::AssociatedRemote<blink::mojom::WebBluetoothScanClient> client,
+        blink::mojom::WebBluetoothRequestLEScanOptionsPtr options,
+        RequestScanningStartCallback callback,
+        BluetoothDeviceScanningPromptController* prompt_controller);
     ~ScanningClient();
     bool SendEvent(blink::mojom::WebBluetoothScanResultPtr result);
 
@@ -140,7 +144,7 @@
 
     bool disconnected_ = false;
     bool allow_send_event_ = false;
-    mojo::AssociatedInterfacePtr<blink::mojom::WebBluetoothScanClient> client_;
+    mojo::AssociatedRemote<blink::mojom::WebBluetoothScanClient> client_;
     blink::mojom::WebBluetoothRequestLEScanOptionsPtr options_;
     RequestScanningStartCallback callback_;
     BluetoothDeviceScanningPromptController* prompt_controller_;
@@ -190,7 +194,8 @@
                      RequestDeviceCallback callback) override;
   void RemoteServerConnect(
       const blink::WebBluetoothDeviceId& device_id,
-      blink::mojom::WebBluetoothServerClientAssociatedPtrInfo client,
+      mojo::PendingAssociatedRemote<blink::mojom::WebBluetoothServerClient>
+          client,
       RemoteServerConnectCallback callback) override;
   void RemoteServerDisconnect(
       const blink::WebBluetoothDeviceId& device_id) override;
@@ -213,7 +218,8 @@
       RemoteCharacteristicWriteValueCallback callback) override;
   void RemoteCharacteristicStartNotifications(
       const std::string& characteristic_instance_id,
-      blink::mojom::WebBluetoothCharacteristicClientAssociatedPtrInfo client,
+      mojo::PendingAssociatedRemote<
+          blink::mojom::WebBluetoothCharacteristicClient> client,
       RemoteCharacteristicStartNotificationsCallback callback) override;
   void RemoteCharacteristicStopNotifications(
       const std::string& characteristic_instance_id,
@@ -231,7 +237,8 @@
       const std::vector<uint8_t>& value,
       RemoteDescriptorWriteValueCallback callback) override;
   void RequestScanningStart(
-      blink::mojom::WebBluetoothScanClientAssociatedPtrInfo client,
+      mojo::PendingAssociatedRemote<blink::mojom::WebBluetoothScanClient>
+          client,
       blink::mojom::WebBluetoothRequestLEScanOptionsPtr options,
       RequestScanningStartCallback callback) override;
 
@@ -241,13 +248,13 @@
       device::BluetoothAdapter* adapter);
 
   void RequestScanningStartImpl(
-      blink::mojom::WebBluetoothScanClientAssociatedPtr client,
+      mojo::AssociatedRemote<blink::mojom::WebBluetoothScanClient> client,
       blink::mojom::WebBluetoothRequestLEScanOptionsPtr options,
       RequestScanningStartCallback callback,
       device::BluetoothAdapter* adapter);
 
   void OnStartDiscoverySession(
-      blink::mojom::WebBluetoothScanClientAssociatedPtr client,
+      mojo::AssociatedRemote<blink::mojom::WebBluetoothScanClient> client,
       blink::mojom::WebBluetoothRequestLEScanOptionsPtr options,
       std::unique_ptr<device::BluetoothDiscoverySession> session);
 
@@ -274,7 +281,7 @@
   void OnCreateGATTConnectionSuccess(
       const blink::WebBluetoothDeviceId& device_id,
       base::TimeTicks start_time,
-      blink::mojom::WebBluetoothServerClientAssociatedPtr client,
+      mojo::AssociatedRemote<blink::mojom::WebBluetoothServerClient> client,
       RemoteServerConnectCallback callback,
       std::unique_ptr<device::BluetoothGattConnection> connection);
   void OnCreateGATTConnectionFailed(
@@ -299,7 +306,8 @@
 
   // Callbacks for BluetoothRemoteGattCharacteristic::StartNotifySession.
   void OnStartNotifySessionSuccess(
-      blink::mojom::WebBluetoothCharacteristicClientAssociatedPtr client,
+      mojo::AssociatedRemote<blink::mojom::WebBluetoothCharacteristicClient>
+          client,
       RemoteCharacteristicStartNotificationsCallback callback,
       std::unique_ptr<device::BluetoothGattNotifySession> notify_session);
   void OnStartNotifySessionFailed(
@@ -414,10 +422,10 @@
   // packets.
   bool accept_all_advertisements_ = false;
 
-  // The lifetime of this instance is exclusively managed by the RFH that
-  // owns it so we use a "Binding" as opposed to a "StrongBinding" which deletes
+  // The lifetime of this instance is exclusively managed by the RFH that owns
+  // it so we use a "Receiver" as opposed to a "SelfOwnedReceiver" which deletes
   // the service on pipe connection errors.
-  mojo::Binding<blink::mojom::WebBluetoothService> binding_;
+  mojo::Receiver<blink::mojom::WebBluetoothService> receiver_;
 
   base::WeakPtrFactory<WebBluetoothServiceImpl> weak_ptr_factory_{this};
 
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl_unittest.cc b/content/browser/bluetooth/web_bluetooth_service_impl_unittest.cc
index b39ea00..4a8c717 100644
--- a/content/browser/bluetooth/web_bluetooth_service_impl_unittest.cc
+++ b/content/browser/bluetooth/web_bluetooth_service_impl_unittest.cc
@@ -13,8 +13,11 @@
 #include "content/test/test_web_contents.h"
 #include "device/bluetooth/bluetooth_adapter_factory_wrapper.h"
 #include "device/bluetooth/test/mock_bluetooth_adapter.h"
-#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
 
 using testing::Return;
 
@@ -87,10 +90,11 @@
   // blink::mojom::WebBluetoothScanClient:
   void ScanEvent(blink::mojom::WebBluetoothScanResultPtr result) override {}
 
-  void BindRequest(
-      blink::mojom::WebBluetoothScanClientAssociatedRequest request) {
-    binding_.Bind(std::move(request));
-    binding_.set_connection_error_handler(
+  void BindReceiver(
+      mojo::PendingAssociatedReceiver<blink::mojom::WebBluetoothScanClient>
+          receiver) {
+    receiver_.Bind(std::move(receiver));
+    receiver_.set_disconnect_handler(
         base::BindOnce(&FakeWebBluetoothScanClientImpl::OnConnectionError,
                        base::Unretained(this)));
   }
@@ -100,7 +104,8 @@
   bool on_connection_error_called() { return on_connection_error_called_; }
 
  private:
-  mojo::AssociatedBinding<blink::mojom::WebBluetoothScanClient> binding_{this};
+  mojo::AssociatedReceiver<blink::mojom::WebBluetoothScanClient> receiver_{
+      this};
   bool on_connection_error_called_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(FakeWebBluetoothScanClientImpl);
@@ -149,8 +154,8 @@
   blink::mojom::RequestScanningStartResultPtr RequestScanningStart(
       const blink::mojom::WebBluetoothLeScanFilter& filter,
       FakeWebBluetoothScanClientImpl* client_impl) {
-    blink::mojom::WebBluetoothScanClientAssociatedPtrInfo client_info;
-    client_impl->BindRequest(mojo::MakeRequest(&client_info));
+    mojo::PendingAssociatedRemote<blink::mojom::WebBluetoothScanClient> client;
+    client_impl->BindReceiver(client.InitWithNewEndpointAndPassReceiver());
     auto options = blink::mojom::WebBluetoothRequestLEScanOptions::New();
     options->filters.emplace();
     auto filter_ptr = blink::mojom::WebBluetoothLeScanFilter::New(filter);
@@ -158,7 +163,7 @@
     base::RunLoop loop;
     blink::mojom::RequestScanningStartResultPtr result;
     service_->RequestScanningStart(
-        std::move(client_info), std::move(options),
+        std::move(client), std::move(options),
         base::BindLambdaForTesting(
             [&](blink::mojom::RequestScanningStartResultPtr p) {
               result = std::move(p);
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc
index 74b9007..557d30e 100644
--- a/content/browser/browser_interface_binders.cc
+++ b/content/browser/browser_interface_binders.cc
@@ -17,6 +17,7 @@
 #include "third_party/blink/public/mojom/background_fetch/background_fetch.mojom.h"
 #include "third_party/blink/public/mojom/filesystem/file_system.mojom.h"
 #include "third_party/blink/public/mojom/idle/idle_manager.mojom.h"
+#include "third_party/blink/public/mojom/locks/lock_manager.mojom.h"
 #include "third_party/blink/public/mojom/presentation/presentation.mojom.h"
 #include "third_party/blink/public/mojom/speech/speech_synthesis.mojom.h"
 #include "third_party/blink/public/mojom/webaudio/audio_context_manager.mojom.h"
@@ -47,6 +48,9 @@
 
   map->Add<blink::mojom::ScreenEnumeration>(
       base::BindRepeating(&ScreenEnumerationImpl::Create));
+
+  map->Add<blink::mojom::LockManager>(base::BindRepeating(
+      &RenderFrameHostImpl::CreateLockManager, base::Unretained(host)));
 }
 
 void PopulateBinderMapWithContext(
@@ -86,6 +90,9 @@
 void PopulateBinderMapWithContext(
     DedicatedWorkerHost* host,
     service_manager::BinderMapWithContext<const url::Origin&>* map) {
+  map->Add<blink::mojom::LockManager>(
+      base::BindRepeating(&RenderProcessHost::CreateLockManager,
+                          base::Unretained(host->GetProcessHost())));
 }
 
 void PopulateBinderMap(DedicatedWorkerHost* host,
@@ -115,6 +122,9 @@
   map->Add<blink::mojom::FileSystemManager>(
       base::BindRepeating(&RenderProcessHost::BindFileSystemManager,
                           base::Unretained(host->GetProcessHost())));
+  map->Add<blink::mojom::LockManager>(
+      base::BindRepeating(&RenderProcessHost::CreateLockManager,
+                          base::Unretained(host->GetProcessHost())));
 }
 
 void PopulateBinderMap(SharedWorkerHost* host,
@@ -134,6 +144,9 @@
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
   map->Add<blink::mojom::ScreenEnumeration>(
       base::BindRepeating(&ScreenEnumerationImpl::Create));
+
+  map->Add<blink::mojom::LockManager>(base::BindRepeating(
+      &ServiceWorkerProviderHost::CreateLockManager, base::Unretained(host)));
 }
 
 void PopulateBinderMapWithContext(
diff --git a/content/browser/devtools/devtools_instrumentation.cc b/content/browser/devtools/devtools_instrumentation.cc
index 9eab8df..87f23d7 100644
--- a/content/browser/devtools/devtools_instrumentation.cc
+++ b/content/browser/devtools/devtools_instrumentation.cc
@@ -130,16 +130,34 @@
                    envelope, certificate, ssl_info, errors);
 }
 
+namespace inspector_will_send_navigation_request_event {
+std::unique_ptr<base::trace_event::TracedValue> Data(
+    const base::UnguessableToken& request_id) {
+  auto value = std::make_unique<base::trace_event::TracedValue>();
+  value->SetString("requestId", request_id.ToString());
+  return value;
+}
+}  // namespace inspector_will_send_navigation_request_event
+
 void OnSignedExchangeCertificateRequestSent(
     FrameTreeNode* frame_tree_node,
     const base::UnguessableToken& request_id,
     const base::UnguessableToken& loader_id,
     const network::ResourceRequest& request,
     const GURL& signed_exchange_url) {
+  // Make sure both back-ends yield the same timestamp.
+  auto timestamp = base::TimeTicks::Now();
   DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::RequestSent,
                    request_id.ToString(), loader_id.ToString(), request,
                    protocol::Network::Initiator::TypeEnum::SignedExchange,
-                   signed_exchange_url);
+                   signed_exchange_url, timestamp);
+
+  auto value = std::make_unique<base::trace_event::TracedValue>();
+  value->SetString("requestId", request_id.ToString());
+  TRACE_EVENT_INSTANT_WITH_TIMESTAMP1(
+      "devtools.timeline", "ResourceWillSendRequest", TRACE_EVENT_SCOPE_PROCESS,
+      timestamp, "data",
+      inspector_will_send_navigation_request_event::Data(request_id));
 }
 
 void OnSignedExchangeCertificateResponseReceived(
@@ -356,9 +374,16 @@
 
 void OnNavigationRequestWillBeSent(
     const NavigationRequest& navigation_request) {
+  // Make sure both back-ends yield the same timestamp.
+  auto timestamp = base::TimeTicks::Now();
   DispatchToAgents(navigation_request.frame_tree_node(),
                    &protocol::NetworkHandler::NavigationRequestWillBeSent,
-                   navigation_request);
+                   navigation_request, timestamp);
+  TRACE_EVENT_INSTANT_WITH_TIMESTAMP1(
+      "devtools.timeline", "ResourceWillSendRequest", TRACE_EVENT_SCOPE_PROCESS,
+      timestamp, "data",
+      inspector_will_send_navigation_request_event::Data(
+          navigation_request.devtools_navigation_token()));
 }
 
 // Notify the provided agent host of a certificate error. Returns true if one of
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc
index e72f134..7f3fe38 100644
--- a/content/browser/devtools/protocol/network_handler.cc
+++ b/content/browser/devtools/protocol/network_handler.cc
@@ -1510,7 +1510,8 @@
 }  // namespace
 
 void NetworkHandler::NavigationRequestWillBeSent(
-    const NavigationRequest& nav_request) {
+    const NavigationRequest& nav_request,
+    base::TimeTicks timestamp) {
   if (!enabled_)
     return;
 
@@ -1571,8 +1572,7 @@
                     .Build();
   }
   std::string id = nav_request.devtools_navigation_token().ToString();
-  double current_ticks =
-      (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
+  double current_ticks = timestamp.since_origin().InSecondsF();
   double current_wall_time = base::Time::Now().ToDoubleT();
   std::string frame_token =
       nav_request.frame_tree_node()->devtools_frame_token().ToString();
@@ -1587,7 +1587,8 @@
                                  const std::string& loader_id,
                                  const network::ResourceRequest& request,
                                  const char* initiator_type,
-                                 const base::Optional<GURL>& initiator_url) {
+                                 const base::Optional<GURL>& initiator_url,
+                                 base::TimeTicks timestamp) {
   if (!enabled_)
     return;
   std::unique_ptr<DictionaryValue> headers_dict(DictionaryValue::create());
@@ -1612,10 +1613,8 @@
     request_object->SetUrlFragment(url_fragment);
   frontend_->RequestWillBeSent(
       request_id, loader_id, url_without_fragment, std::move(request_object),
-      base::TimeTicks::Now().ToInternalValue() /
-          static_cast<double>(base::Time::kMicrosecondsPerSecond),
-      base::Time::Now().ToDoubleT(), std::move(initiator),
-      std::unique_ptr<Network::Response>(),
+      timestamp.since_origin().InSecondsF(), base::Time::Now().ToDoubleT(),
+      std::move(initiator), std::unique_ptr<Network::Response>(),
       std::string(Network::ResourceTypeEnum::Other),
       Maybe<std::string>() /* frame_id */, request.has_user_gesture);
 }
diff --git a/content/browser/devtools/protocol/network_handler.h b/content/browser/devtools/protocol/network_handler.h
index 6c0d4f8..6d0108bd 100644
--- a/content/browser/devtools/protocol/network_handler.h
+++ b/content/browser/devtools/protocol/network_handler.h
@@ -157,12 +157,14 @@
   void ApplyOverrides(net::HttpRequestHeaders* headers,
                       bool* skip_service_worker,
                       bool* disable_cache);
-  void NavigationRequestWillBeSent(const NavigationRequest& nav_request);
+  void NavigationRequestWillBeSent(const NavigationRequest& nav_request,
+                                   base::TimeTicks timestamp);
   void RequestSent(const std::string& request_id,
                    const std::string& loader_id,
                    const network::ResourceRequest& request,
                    const char* initiator_type,
-                   const base::Optional<GURL>& initiator_url);
+                   const base::Optional<GURL>& initiator_url,
+                   base::TimeTicks timestamp);
   void ResponseReceived(const std::string& request_id,
                         const std::string& loader_id,
                         const GURL& url,
diff --git a/content/browser/devtools/service_worker_devtools_manager.cc b/content/browser/devtools/service_worker_devtools_manager.cc
index 678fa85..5acc20c7 100644
--- a/content/browser/devtools/service_worker_devtools_manager.cc
+++ b/content/browser/devtools/service_worker_devtools_manager.cc
@@ -188,11 +188,12 @@
   auto it = live_hosts_.find(worker_id);
   if (it == live_hosts_.end())
     return;
+  auto timestamp = base::TimeTicks::Now();
   for (auto* network :
        protocol::NetworkHandler::ForAgentHost(it->second.get())) {
     network->RequestSent(request_id, std::string(), request,
                          protocol::Network::Initiator::TypeEnum::Preload,
-                         base::nullopt /* initiator_url */);
+                         base::nullopt /* initiator_url */, timestamp);
   }
 }
 
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 4d1c3fd..e26fe6c 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -5,6 +5,7 @@
 #include "content/browser/frame_host/render_frame_host_impl.h"
 
 #include <algorithm>
+#include <memory>
 #include <unordered_map>
 #include <utility>
 
@@ -202,6 +203,7 @@
 #include "third_party/blink/public/common/frame/frame_policy.h"
 #include "third_party/blink/public/common/messaging/transferable_message.h"
 #include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
 #include "third_party/blink/public/mojom/frame/frame_host_test_interface.mojom.h"
 #include "third_party/blink/public/mojom/loader/pause_subresource_loading_handle.mojom.h"
 #include "third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom.h"
@@ -6169,12 +6171,13 @@
 }
 
 WebBluetoothServiceImpl* RenderFrameHostImpl::CreateWebBluetoothService(
-    blink::mojom::WebBluetoothServiceRequest request) {
+    mojo::PendingReceiver<blink::mojom::WebBluetoothService> receiver) {
   // RFHI owns |web_bluetooth_services_| and |web_bluetooth_service| owns the
-  // |binding_| which may run the error handler. |binding_| can't run the error
-  // handler after it's destroyed so it can't run after the RFHI is destroyed.
+  // |receiver_| which may run the error handler. |receiver_| can't run the
+  // error handler after it's destroyed so it can't run after the RFHI is
+  // destroyed.
   auto web_bluetooth_service =
-      std::make_unique<WebBluetoothServiceImpl>(this, std::move(request));
+      std::make_unique<WebBluetoothServiceImpl>(this, std::move(receiver));
   web_bluetooth_service->SetClientConnectionErrorHandler(
       base::BindOnce(&RenderFrameHostImpl::DeleteWebBluetoothService,
                      base::Unretained(this), web_bluetooth_service.get()));
@@ -6426,6 +6429,12 @@
                                 std::move(receiver)));
 }
 
+void RenderFrameHostImpl::CreateLockManager(
+    mojo::PendingReceiver<blink::mojom::LockManager> receiver) {
+  GetProcess()->CreateLockManager(GetLastCommittedOrigin(),
+                                  std::move(receiver));
+}
+
 void RenderFrameHostImpl::GetAuthenticator(
     mojo::PendingReceiver<blink::mojom::Authenticator> receiver) {
 #if !defined(OS_ANDROID)
@@ -7029,11 +7038,6 @@
     mojo::PendingRemote<network::mojom::URLLoaderFactory>
         prefetch_loader_factory,
     const base::UnguessableToken& devtools_navigation_token) {
-  // TODO(lfg): Temporary to debug https://crbug.com/996337.
-  if (common_params->url.SchemeIsCryptographic() &&
-      response_head.ssl_info.has_value() && !response_head.ssl_info->cert) {
-    base::debug::DumpWithoutCrashing();
-  }
   if (navigation_client) {
     navigation_client->CommitNavigation(
         std::move(common_params), std::move(commit_params), response_head,
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index adbdb61..2ddbd6d 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -1037,6 +1037,9 @@
   void GetSpeechSynthesis(
       mojo::PendingReceiver<blink::mojom::SpeechSynthesis> receiver);
 
+  void CreateLockManager(
+      mojo::PendingReceiver<blink::mojom::LockManager> receiver);
+
   // https://mikewest.github.io/corpp/#initialize-embedder-policy-for-global
   network::mojom::CrossOriginEmbedderPolicy cross_origin_embedder_policy()
       const {
@@ -1498,7 +1501,7 @@
   // Creates Web Bluetooth Service owned by the frame. Returns a raw pointer
   // to it.
   WebBluetoothServiceImpl* CreateWebBluetoothService(
-      blink::mojom::WebBluetoothServiceRequest request);
+      mojo::PendingReceiver<blink::mojom::WebBluetoothService> receiver);
 
   // Deletes the Web Bluetooth Service owned by the frame.
   void DeleteWebBluetoothService(
diff --git a/content/browser/geolocation/geolocation_service_impl_unittest.cc b/content/browser/geolocation/geolocation_service_impl_unittest.cc
index 9f29a84c..ff64e32 100644
--- a/content/browser/geolocation/geolocation_service_impl_unittest.cc
+++ b/content/browser/geolocation/geolocation_service_impl_unittest.cc
@@ -16,6 +16,7 @@
 #include "content/public/test/test_browser_context.h"
 #include "content/public/test/test_service_manager_context.h"
 #include "content/test/test_render_frame_host.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "services/device/public/cpp/test/scoped_geolocation_overrider.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/device/public/mojom/geolocation.mojom.h"
@@ -26,11 +27,11 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom.h"
 
-using blink::mojom::PermissionStatus;
-using device::mojom::GeolocationPtr;
-using device::mojom::GeopositionPtr;
 using blink::mojom::GeolocationService;
 using blink::mojom::GeolocationServicePtr;
+using blink::mojom::PermissionStatus;
+using device::mojom::Geolocation;
+using device::mojom::GeopositionPtr;
 
 namespace content {
 namespace {
@@ -157,15 +158,15 @@
       base::BindRepeating([](PermissionCallback callback) {
         ADD_FAILURE() << "Permissions checked unexpectedly.";
       }));
-  GeolocationPtr geolocation;
+  mojo::Remote<Geolocation> geolocation;
   service()->CreateGeolocation(
-      mojo::MakeRequest(&geolocation), true,
+      geolocation.BindNewPipeAndPassReceiver(), true,
       base::BindRepeating([](blink::mojom::PermissionStatus status) {
         EXPECT_EQ(blink::mojom::PermissionStatus::DENIED, status);
       }));
 
   base::RunLoop loop;
-  geolocation.set_connection_error_handler(loop.QuitClosure());
+  geolocation.set_disconnect_handler(loop.QuitClosure());
 
   geolocation->QueryNextPosition(base::BindOnce([](GeopositionPtr geoposition) {
     ADD_FAILURE() << "Position updated unexpectedly";
@@ -181,15 +182,15 @@
       base::BindRepeating([](PermissionCallback callback) {
         std::move(callback).Run(PermissionStatus::GRANTED);
       }));
-  GeolocationPtr geolocation;
+  mojo::Remote<Geolocation> geolocation;
   service()->CreateGeolocation(
-      mojo::MakeRequest(&geolocation), true,
+      geolocation.BindNewPipeAndPassReceiver(), true,
       base::BindRepeating([](blink::mojom::PermissionStatus status) {
         EXPECT_EQ(blink::mojom::PermissionStatus::GRANTED, status);
       }));
 
   base::RunLoop loop;
-  geolocation.set_connection_error_handler(base::BindOnce(
+  geolocation.set_disconnect_handler(base::BindOnce(
       [] { ADD_FAILURE() << "Connection error handler called unexpectedly"; }));
 
   geolocation->QueryNextPosition(base::BindOnce(
@@ -208,15 +209,15 @@
       base::BindRepeating([](PermissionCallback callback) {
         std::move(callback).Run(PermissionStatus::GRANTED);
       }));
-  GeolocationPtr geolocation;
+  mojo::Remote<Geolocation> geolocation;
   service()->CreateGeolocation(
-      mojo::MakeRequest(&geolocation), true,
+      geolocation.BindNewPipeAndPassReceiver(), true,
       base::BindRepeating([](blink::mojom::PermissionStatus status) {
         EXPECT_EQ(blink::mojom::PermissionStatus::GRANTED, status);
       }));
 
   base::RunLoop loop;
-  geolocation.set_connection_error_handler(base::BindOnce(
+  geolocation.set_disconnect_handler(base::BindOnce(
       [] { ADD_FAILURE() << "Connection error handler called unexpectedly"; }));
 
   geolocation->QueryNextPosition(base::BindOnce(
@@ -235,15 +236,15 @@
       base::BindRepeating([](PermissionCallback callback) {
         std::move(callback).Run(PermissionStatus::DENIED);
       }));
-  GeolocationPtr geolocation;
+  mojo::Remote<Geolocation> geolocation;
   service()->CreateGeolocation(
-      mojo::MakeRequest(&geolocation), true,
+      geolocation.BindNewPipeAndPassReceiver(), true,
       base::BindRepeating([](blink::mojom::PermissionStatus status) {
         EXPECT_EQ(blink::mojom::PermissionStatus::DENIED, status);
       }));
 
   base::RunLoop loop;
-  geolocation.set_connection_error_handler(loop.QuitClosure());
+  geolocation.set_disconnect_handler(loop.QuitClosure());
 
   geolocation->QueryNextPosition(base::BindOnce([](GeopositionPtr geoposition) {
     ADD_FAILURE() << "Position updated unexpectedly";
@@ -260,15 +261,15 @@
             FROM_HERE, base::BindOnce(std::move(permission_callback),
                                       PermissionStatus::GRANTED));
       }));
-  GeolocationPtr geolocation;
+  mojo::Remote<Geolocation> geolocation;
   service()->CreateGeolocation(
-      mojo::MakeRequest(&geolocation), true,
+      geolocation.BindNewPipeAndPassReceiver(), true,
       base::BindRepeating([](blink::mojom::PermissionStatus status) {
         EXPECT_EQ(blink::mojom::PermissionStatus::GRANTED, status);
       }));
 
   base::RunLoop loop;
-  geolocation.set_connection_error_handler(base::BindOnce(
+  geolocation.set_disconnect_handler(base::BindOnce(
       [] { ADD_FAILURE() << "Connection error handler called unexpectedly"; }));
 
   geolocation->QueryNextPosition(base::BindOnce(
@@ -290,15 +291,15 @@
             FROM_HERE, base::BindOnce(std::move(permission_callback),
                                       PermissionStatus::DENIED));
       }));
-  GeolocationPtr geolocation;
+  mojo::Remote<Geolocation> geolocation;
   service()->CreateGeolocation(
-      mojo::MakeRequest(&geolocation), true,
+      geolocation.BindNewPipeAndPassReceiver(), true,
       base::BindRepeating([](blink::mojom::PermissionStatus status) {
         EXPECT_EQ(blink::mojom::PermissionStatus::DENIED, status);
       }));
 
   base::RunLoop loop;
-  geolocation.set_connection_error_handler(loop.QuitClosure());
+  geolocation.set_disconnect_handler(loop.QuitClosure());
 
   geolocation->QueryNextPosition(base::BindOnce([](GeopositionPtr geoposition) {
     ADD_FAILURE() << "Position updated unexpectedly";
@@ -309,9 +310,9 @@
 TEST_F(GeolocationServiceTest, ServiceClosedBeforePermissionResponse) {
   CreateEmbeddedFrameAndGeolocationService(/*allow_via_feature_policy=*/true);
   permission_manager()->SetRequestId(42);
-  GeolocationPtr geolocation;
+  mojo::Remote<Geolocation> geolocation;
   service()->CreateGeolocation(
-      mojo::MakeRequest(&geolocation), true,
+      geolocation.BindNewPipeAndPassReceiver(), true,
       base::BindRepeating([](blink::mojom::PermissionStatus) {
         ADD_FAILURE() << "PositionStatus received unexpectedly.";
       }));
diff --git a/content/browser/histograms_internals_ui.cc b/content/browser/histograms_internals_ui.cc
index 276cc6834..4b9a018 100644
--- a/content/browser/histograms_internals_ui.cc
+++ b/content/browser/histograms_internals_ui.cc
@@ -80,7 +80,7 @@
     std::string ascii_output;
     histogram->WriteHTMLGraph(&ascii_output);
     ascii_output += "<br><hr><br>";
-    histograms_list.GetList().emplace_back(std::move(ascii_output));
+    histograms_list.Append(std::move(ascii_output));
   }
 
   ResolveJavascriptCallback(base::Value(callback_id),
diff --git a/content/browser/locks/lock_manager.cc b/content/browser/locks/lock_manager.cc
index 03a8a583..a927af3 100644
--- a/content/browser/locks/lock_manager.cc
+++ b/content/browser/locks/lock_manager.cc
@@ -308,8 +308,8 @@
 };
 
 void LockManager::CreateService(
-    mojo::PendingReceiver<blink::mojom::LockManager> receiver,
-    const url::Origin& origin) {
+    const url::Origin& origin,
+    mojo::PendingReceiver<blink::mojom::LockManager> receiver) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // TODO(jsbell): This should reflect the 'environment id' from HTML,
diff --git a/content/browser/locks/lock_manager.h b/content/browser/locks/lock_manager.h
index 7b023df..af713df47 100644
--- a/content/browser/locks/lock_manager.h
+++ b/content/browser/locks/lock_manager.h
@@ -26,8 +26,8 @@
  public:
   LockManager();
 
-  void CreateService(mojo::PendingReceiver<blink::mojom::LockManager> receiver,
-                     const url::Origin& origin);
+  void CreateService(const url::Origin& origin,
+                     mojo::PendingReceiver<blink::mojom::LockManager> receiver);
 
   // Request a lock. When the lock is acquired, |callback| will be invoked with
   // a LockHandle.
diff --git a/content/browser/media/media_internals_audio_focus_helper.cc b/content/browser/media/media_internals_audio_focus_helper.cc
index 7ba13c0..9c5e1b9 100644
--- a/content/browser/media/media_internals_audio_focus_helper.cc
+++ b/content/browser/media/media_internals_audio_focus_helper.cc
@@ -167,7 +167,7 @@
     std::string id_string = session->request_id.value().ToString();
     base::DictionaryValue media_session_data;
     media_session_data.SetKey(kAudioFocusIdKey, base::Value(id_string));
-    stack_data.GetList().push_back(std::move(media_session_data));
+    stack_data.Append(std::move(media_session_data));
 
     request_state_.emplace(id_string, session.Clone());
 
diff --git a/content/browser/payments/payment_app_database.cc b/content/browser/payments/payment_app_database.cc
index b13f19e..f86adc3 100644
--- a/content/browser/payments/payment_app_database.cc
+++ b/content/browser/payments/payment_app_database.cc
@@ -411,7 +411,7 @@
     EnableDelegationsCallback callback,
     blink::ServiceWorkerStatusCode status,
     scoped_refptr<ServiceWorkerRegistration> registration) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
   if (status != blink::ServiceWorkerStatusCode::kOk) {
     std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
     return;
@@ -432,7 +432,7 @@
     const GURL& pattern,
     const std::vector<std::string>& data,
     blink::ServiceWorkerStatusCode status) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
   if (status != blink::ServiceWorkerStatusCode::kOk) {
     std::move(callback).Run(PaymentHandlerStatus::NOT_FOUND);
     return;
@@ -479,7 +479,7 @@
 void PaymentAppDatabase::DidEnablePaymentAppDelegations(
     EnableDelegationsCallback callback,
     blink::ServiceWorkerStatusCode status) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
   return std::move(callback).Run(
       status == blink::ServiceWorkerStatusCode::kOk
           ? PaymentHandlerStatus::SUCCESS
diff --git a/content/browser/payments/payment_manager.cc b/content/browser/payments/payment_manager.cc
index cc640d8..9ffb7b6a 100644
--- a/content/browser/payments/payment_manager.cc
+++ b/content/browser/payments/payment_manager.cc
@@ -14,6 +14,7 @@
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/browser/service_worker/service_worker_registration.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/service_worker_context.h"
 #include "url/origin.h"
 
 namespace content {
@@ -141,7 +142,7 @@
 void PaymentManager::EnableDelegations(
     const std::vector<payments::mojom::PaymentDelegation>& delegations,
     PaymentManager::EnableDelegationsCallback callback) {
-  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
 
   payment_app_context_->payment_app_database()->EnablePaymentAppDelegations(
       scope_, delegations, std::move(callback));
diff --git a/content/browser/portal/OWNERS b/content/browser/portal/OWNERS
new file mode 100644
index 0000000..bf4f802
--- /dev/null
+++ b/content/browser/portal/OWNERS
@@ -0,0 +1,3 @@
+file://third_party/blink/renderer/core/html/portal/OWNERS
+
+# COMPONENT: Blink>HTML>Portal
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index b6f89d4..25fd6ca6 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -101,6 +101,7 @@
 #include "content/browser/histogram_controller.h"
 #include "content/browser/indexed_db/indexed_db_context_impl.h"
 #include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
+#include "content/browser/locks/lock_manager.h"
 #include "content/browser/media/capture/audio_mirroring_manager.h"
 #include "content/browser/media/media_internals.h"
 #include "content/browser/media/midi_host.h"
@@ -1909,6 +1910,14 @@
                      std::move(receiver)));
 }
 
+void RenderProcessHostImpl::CreateLockManager(
+    const url::Origin& origin,
+    mojo::PendingReceiver<blink::mojom::LockManager> receiver) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  storage_partition_impl_->GetLockManager()->CreateService(origin,
+                                                           std::move(receiver));
+}
+
 void RenderProcessHostImpl::CancelProcessShutdownDelayForUnload() {
   if (IsKeepAliveRefCountDisabled())
     return;
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index 790327e..48a5266 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -494,7 +494,7 @@
   void DelayProcessShutdownForUnload(const base::TimeDelta& timeout);
 
   // Binds |receiver| to the FileSystemManager instance owned by the render
-  // process host, and is used by workers via RendererInterfaceBinders.
+  // process host, and is used by workers via BrowserInterfaceBroker.
   void BindFileSystemManager(
       const url::Origin& origin,
       mojo::PendingReceiver<blink::mojom::FileSystemManager> receiver) override;
@@ -503,6 +503,13 @@
     return file_system_manager_impl_.get();
   }
 
+  // Binds |receiver| to the LockManager instance owned by
+  // |storage_partition_impl_|, and is used by frames and workers via
+  // BrowserInterfaceBroker.
+  void CreateLockManager(
+      const url::Origin& origin,
+      mojo::PendingReceiver<blink::mojom::LockManager> receiver) override;
+
   // Adds a CORB (Cross-Origin Read Blocking) exception for |process_id|.  The
   // exception will be removed when the corresponding RenderProcessHostImpl is
   // destroyed (see |cleanup_corb_exception_for_plugin_upon_destruction_|).
diff --git a/content/browser/renderer_interface_binders.cc b/content/browser/renderer_interface_binders.cc
index 13f48e7..cf4be3849 100644
--- a/content/browser/renderer_interface_binders.cc
+++ b/content/browser/renderer_interface_binders.cc
@@ -15,7 +15,6 @@
 #include "content/browser/content_index/content_index_service_impl.h"
 #include "content/browser/cookie_store/cookie_store_context.h"
 #include "content/browser/gpu/gpu_process_host.h"
-#include "content/browser/locks/lock_manager.h"
 #include "content/browser/native_file_system/native_file_system_manager_impl.h"
 #include "content/browser/notifications/platform_notification_context_impl.h"
 #include "content/browser/payments/payment_manager.h"
@@ -199,13 +198,6 @@
         static_cast<RenderProcessHostImpl*>(host)->BindIndexedDB(
             std::move(receiver), origin);
       }));
-  // TODO(https://crbug.com/873661): Pass origin to FileSystemMananger.
-  parameterized_binder_registry_.AddInterface(base::BindRepeating(
-      [](mojo::PendingReceiver<blink::mojom::FileSystemManager> receiver,
-         RenderProcessHost* host, const url::Origin& origin) {
-        static_cast<RenderProcessHostImpl*>(host)->BindFileSystemManager(
-            origin, std::move(receiver));
-      }));
   if (base::FeatureList::IsEnabled(blink::features::kNativeFileSystemAPI)) {
     parameterized_binder_registry_.AddInterface(base::BindRepeating(
         [](mojo::PendingReceiver<blink::mojom::NativeFileSystemManager>
@@ -233,13 +225,6 @@
             ->permission_service_context()
             .CreateServiceForWorker(std::move(receiver), origin);
       }));
-  parameterized_binder_registry_.AddInterface(base::BindRepeating(
-      [](blink::mojom::LockManagerRequest request, RenderProcessHost* host,
-         const url::Origin& origin) {
-        static_cast<StoragePartitionImpl*>(host->GetStoragePartition())
-            ->GetLockManager()
-            ->CreateService(std::move(request), origin);
-      }));
 
   parameterized_binder_registry_.AddInterface(base::BindRepeating(
       [](blink::mojom::NotificationServiceRequest request,
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
index 58d77940..9656a1427 100644
--- a/content/browser/service_worker/service_worker_browsertest.cc
+++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -3911,7 +3911,7 @@
   // Ensure the service worker did not see a fetch event for the PlzRedirect
   // URL, since throttles should have redirected before interception.
   base::Value list(base::Value::Type::LIST);
-  list.GetList().emplace_back(redirect_url.spec());
+  list.Append(redirect_url.spec());
   EXPECT_EQ(list, EvalJs(shell()->web_contents()->GetMainFrame(), script));
 
   SetBrowserClientForTesting(old_content_browser_client);
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc
index af113105..9653221 100644
--- a/content/browser/service_worker/service_worker_provider_host.cc
+++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -86,6 +86,18 @@
                       origin);
 }
 
+void CreateLockManagerImpl(
+    const url::Origin& origin,
+    int process_id,
+    mojo::PendingReceiver<blink::mojom::LockManager> receiver) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  auto* process = RenderProcessHost::FromID(process_id);
+  if (!process)
+    return;
+
+  process->CreateLockManager(origin, std::move(receiver));
+}
+
 ServiceWorkerMetrics::EventType PurposeToEventType(
     blink::mojom::ControllerServiceWorkerPurpose purpose) {
   switch (purpose) {
@@ -1352,6 +1364,17 @@
   return client_phase_ == ClientPhase::kExecutionReady;
 }
 
+void ServiceWorkerProviderHost::CreateLockManager(
+    mojo::PendingReceiver<blink::mojom::LockManager> receiver) {
+  DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
+  DCHECK(IsProviderForServiceWorker());
+  RunOrPostTaskOnThread(
+      FROM_HERE, BrowserThread::UI,
+      base::BindOnce(&CreateLockManagerImpl,
+                     running_hosted_version_->script_origin(),
+                     render_process_id_, std::move(receiver)));
+}
+
 void ServiceWorkerProviderHost::SetExecutionReady() {
   DCHECK(!is_execution_ready());
   TransitionToClientPhase(ClientPhase::kExecutionReady);
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h
index f229fac5..d4f4d49 100644
--- a/content/browser/service_worker/service_worker_provider_host.h
+++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -35,6 +35,7 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/network/public/mojom/fetch_api.mojom.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
+#include "third_party/blink/public/mojom/locks/lock_manager.mojom-forward.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_container.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_provider_type.mojom.h"
@@ -407,6 +408,11 @@
   // https://html.spec.whatwg.org/multipage/webappapis.html#concept-environment-execution-ready-flag
   bool is_execution_ready() const;
 
+  // For service worker execution contexts. Forwards |receiver| to the process
+  // host on the UI thread.
+  void CreateLockManager(
+      mojo::PendingReceiver<blink::mojom::LockManager> receiver);
+
  private:
   // For service worker clients. The flow is kInitial -> kResponseCommitted ->
   // kExecutionReady.
diff --git a/content/browser/snapshot_browsertest.cc b/content/browser/snapshot_browsertest.cc
index 1ed8faf..bc87539 100644
--- a/content/browser/snapshot_browsertest.cc
+++ b/content/browser/snapshot_browsertest.cc
@@ -253,9 +253,10 @@
 //   Windows Debug
 //   Linux Chromium OS ASAN LSAN Tests (1)
 //   Linux TSAN Tests
+//   Linux FYI SkiaRenderer Vulkan (Intel HD 630)
 // See crbug.com/771119
 #if (defined(OS_WIN) && !defined(NDEBUG)) || (defined(OS_CHROMEOS)) || \
-    (defined(OS_LINUX) && defined(THREAD_SANITIZER))
+    defined(OS_LINUX)
 #define MAYBE_SyncMultiWindowTest DISABLED_SyncMultiWindowTest
 #define MAYBE_AsyncMultiWindowTest DISABLED_AsyncMultiWindowTest
 #else
diff --git a/content/browser/speech/speech_recognition_engine.cc b/content/browser/speech/speech_recognition_engine.cc
index 8cf67c6..e55a430 100644
--- a/content/browser/speech/speech_recognition_engine.cc
+++ b/content/browser/speech/speech_recognition_engine.cc
@@ -18,7 +18,7 @@
 #include "content/browser/speech/proto/google_streaming_api.pb.h"
 #include "google_apis/google_api_keys.h"
 #include "mojo/public/c/system/types.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
 #include "net/base/escape.h"
 #include "net/base/load_flags.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
@@ -91,10 +91,11 @@
                  SpeechRecognitionEngine* speech_recognition_engine)
       : speech_recognition_engine_(speech_recognition_engine) {
     // Attach a chunked upload body.
-    network::mojom::ChunkedDataPipeGetterPtr data_pipe;
-    binding_set_.AddBinding(this, mojo::MakeRequest(&data_pipe));
+    mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter> data_remote;
+    receiver_set_.Add(this, data_remote.InitWithNewPipeAndPassReceiver());
     resource_request->request_body = new network::ResourceRequestBody();
-    resource_request->request_body->SetToChunkedDataPipe(std::move(data_pipe));
+    resource_request->request_body->SetToChunkedDataPipe(
+        std::move(data_remote));
     simple_url_loader_ = network::SimpleURLLoader::Create(
         std::move(resource_request), upstream_traffic_annotation);
     simple_url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
@@ -219,7 +220,7 @@
 
   SpeechRecognitionEngine* const speech_recognition_engine_;
   std::unique_ptr<network::SimpleURLLoader> simple_url_loader_;
-  mojo::BindingSet<network::mojom::ChunkedDataPipeGetter> binding_set_;
+  mojo::ReceiverSet<network::mojom::ChunkedDataPipeGetter> receiver_set_;
 
   DISALLOW_COPY_AND_ASSIGN(UpstreamLoader);
 };
diff --git a/content/browser/speech/speech_recognition_engine_unittest.cc b/content/browser/speech/speech_recognition_engine_unittest.cc
index 8465c9b..889760af 100644
--- a/content/browser/speech/speech_recognition_engine_unittest.cc
+++ b/content/browser/speech/speech_recognition_engine_unittest.cc
@@ -18,6 +18,7 @@
 #include "base/test/task_environment.h"
 #include "content/browser/speech/audio_buffer.h"
 #include "content/browser/speech/proto/google_streaming_api.pb.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "net/base/net_errors.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_util.h"
@@ -104,7 +105,7 @@
 
   network::TestURLLoaderFactory url_loader_factory_;
   mojo::ScopedDataPipeProducerHandle downstream_data_pipe_;
-  network::mojom::ChunkedDataPipeGetterPtr chunked_data_pipe_getter_;
+  mojo::Remote<network::mojom::ChunkedDataPipeGetter> chunked_data_pipe_getter_;
   mojo::ScopedDataPipeConsumerHandle upstream_data_pipe_;
 
   std::unique_ptr<SpeechRecognitionEngine> engine_under_test_;
diff --git a/content/browser/speech/speech_recognizer_impl_unittest.cc b/content/browser/speech/speech_recognizer_impl_unittest.cc
index 8bceb16c..45e8eb7 100644
--- a/content/browser/speech/speech_recognizer_impl_unittest.cc
+++ b/content/browser/speech/speech_recognizer_impl_unittest.cc
@@ -30,6 +30,7 @@
 #include "media/audio/test_audio_thread.h"
 #include "media/base/audio_bus.h"
 #include "media/base/test_helpers.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "mojo/public/cpp/system/data_pipe.h"
 #include "mojo/public/cpp/system/data_pipe_utils.h"
 #include "net/base/net_errors.h"
@@ -411,7 +412,7 @@
   // that we are streaming out encoded data as chunks without waiting for the
   // full recording to complete.
   const size_t kNumChunks = 5;
-  network::mojom::ChunkedDataPipeGetterPtr chunked_data_pipe_getter;
+  mojo::Remote<network::mojom::ChunkedDataPipeGetter> chunked_data_pipe_getter;
   mojo::DataPipe data_pipe;
   for (size_t i = 0; i < kNumChunks; ++i) {
     Capture(audio_bus_.get());
diff --git a/content/public/app/content_browser_manifest.cc b/content/public/app/content_browser_manifest.cc
index 57f83798..aba4a94d 100644
--- a/content/public/app/content_browser_manifest.cc
+++ b/content/public/app/content_browser_manifest.cc
@@ -168,7 +168,6 @@
               "navigation:shared_worker", "renderer",
               std::set<const char*>{
                   "blink.mojom.CacheStorage", "blink.mojom.IDBFactory",
-                  "blink.mojom.LockManager",
                   "blink.mojom.NativeFileSystemManager",
                   "blink.mojom.NotificationService",
                   "blink.mojom.PermissionService",
@@ -185,7 +184,6 @@
                   "blink.mojom.CacheStorage",
                   "blink.mojom.DedicatedWorkerHostFactory",
                   "blink.mojom.IDBFactory",
-                  "blink.mojom.LockManager",
                   "blink.mojom.NativeFileSystemManager",
                   "blink.mojom.NotificationService",
                   "blink.mojom.PermissionService",
@@ -203,7 +201,6 @@
               std::set<const char*>{
                   "blink.mojom.CacheStorage", "blink.mojom.CookieStore",
                   "blink.mojom.ContentIndexService", "blink.mojom.IDBFactory",
-                  "blink.mojom.LockManager",
                   "blink.mojom.NativeFileSystemManager",
                   "blink.mojom.NotificationService",
                   "blink.mojom.PermissionService",
@@ -234,7 +231,6 @@
                   "blink.mojom.IDBFactory",
                   "blink.mojom.InsecureInputService",
                   "blink.mojom.KeyboardLockService",
-                  "blink.mojom.LockManager",
                   "blink.mojom.MediaDevicesDispatcherHost",
                   "blink.mojom.MediaStreamDispatcherHost",
                   "blink.mojom.MediaSessionService",
diff --git a/content/public/browser/render_process_host.h b/content/public/browser/render_process_host.h
index ad966f5..d51832b 100644
--- a/content/public/browser/render_process_host.h
+++ b/content/public/browser/render_process_host.h
@@ -34,6 +34,7 @@
 #include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-forward.h"
 #include "third_party/blink/public/mojom/filesystem/file_system.mojom-forward.h"
 #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-forward.h"
+#include "third_party/blink/public/mojom/locks/lock_manager.mojom-forward.h"
 #include "ui/gfx/native_widget_types.h"
 
 #if defined(OS_ANDROID)
@@ -496,6 +497,13 @@
       mojo::PendingReceiver<blink::mojom::IDBFactory> receiver,
       const url::Origin& origin) = 0;
 
+  // Binds |receiver| to an instance of LockManager. This is for internal use
+  // only, and is only exposed here to support MockRenderProcessHost usage in
+  // tests.
+  virtual void CreateLockManager(
+      const url::Origin& origin,
+      mojo::PendingReceiver<blink::mojom::LockManager> receiver) = 0;
+
   // Returns the current number of active views in this process.  Excludes
   // any RenderViewHosts that are swapped out.
   size_t GetActiveViewCount();
diff --git a/content/public/test/browser_task_environment.h b/content/public/test/browser_task_environment.h
index a921eed3..00d18ed 100644
--- a/content/public/test/browser_task_environment.h
+++ b/content/public/test/browser_task_environment.h
@@ -142,7 +142,7 @@
   static constexpr MainThreadType IO_MAINLOOP = MainThreadType::IO;
 
   struct ValidTraits {
-    ValidTraits(TaskEnvironment::ValidTrait);
+    ValidTraits(TaskEnvironment::ValidTraits);
     ValidTraits(Options);
   };
 
diff --git a/content/public/test/mock_render_process_host.h b/content/public/test/mock_render_process_host.h
index 0f1c488c..10c42ed8 100644
--- a/content/public/test/mock_render_process_host.h
+++ b/content/public/test/mock_render_process_host.h
@@ -178,6 +178,9 @@
       override {}
   void BindIndexedDB(mojo::PendingReceiver<blink::mojom::IDBFactory> receiver,
                      const url::Origin& origin) override;
+  void CreateLockManager(
+      const url::Origin& origin,
+      mojo::PendingReceiver<blink::mojom::LockManager> receiver) override {}
   void CleanupCorbExceptionForPluginUponDestruction() override;
 
   // IPC::Sender via RenderProcessHost.
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 1995097..720e7ef 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -250,6 +250,8 @@
     "p2p/socket_client_impl.h",
     "p2p/socket_dispatcher.cc",
     "p2p/socket_dispatcher.h",
+    "page_properties.cc",
+    "page_properties.h",
     "peripheral_content_heuristic.cc",
     "peripheral_content_heuristic.h",
     "queue_message_swap_promise.cc",
diff --git a/content/renderer/android/synchronous_layer_tree_frame_sink.cc b/content/renderer/android/synchronous_layer_tree_frame_sink.cc
index ce56f14..b833fa1 100644
--- a/content/renderer/android/synchronous_layer_tree_frame_sink.cc
+++ b/content/renderer/android/synchronous_layer_tree_frame_sink.cc
@@ -562,10 +562,8 @@
     const viz::FrameTimingDetailsMap& timing_details) {
   if (!client_)
     return;
-  for (const auto& pair : timing_details) {
-    client_->DidPresentCompositorFrame(pair.first,
-                                       pair.second.presentation_feedback);
-  }
+  for (const auto& pair : timing_details)
+    client_->DidPresentCompositorFrame(pair.first, pair.second);
 }
 
 void SynchronousLayerTreeFrameSink::BeginFrame(
diff --git a/content/renderer/page_properties.cc b/content/renderer/page_properties.cc
new file mode 100644
index 0000000..a71ce9a
--- /dev/null
+++ b/content/renderer/page_properties.cc
@@ -0,0 +1,11 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/page_properties.h"
+
+namespace content {
+PageProperties::PageProperties() = default;
+PageProperties::~PageProperties() = default;
+
+}  // namespace content
diff --git a/content/renderer/page_properties.h b/content/renderer/page_properties.h
new file mode 100644
index 0000000..43398b0
--- /dev/null
+++ b/content/renderer/page_properties.h
@@ -0,0 +1,28 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_PAGE_PROPERTIES_H_
+#define CONTENT_RENDERER_PAGE_PROPERTIES_H_
+
+#include "content/common/content_export.h"
+
+namespace content {
+
+// This interface exposes "page global" concepts to child frames. Historically
+// such state was managed by the RenderView API. However RenderView also has
+// to be have as the WebViewClient as well as the IPC anchor for content. As
+// such it is hard to separate what APIs are needed by blink, IPC, and other
+// content renderer objects.
+//
+// Splitting out an explicit concept aligned with a "page" better fits the
+// abstractions and clarifies which APIs can be coupled.
+class CONTENT_EXPORT PageProperties {
+ public:
+  PageProperties();
+  ~PageProperties();
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_PAGE_PROPERTIES_H_
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 4e17b17..527b0e0c 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -1466,7 +1466,7 @@
   // RenderFrame.
   render_view->render_widget_ = RenderWidget::CreateForFrame(
       params->main_frame_widget_routing_id, compositor_deps,
-      params->visual_properties.screen_info,
+      render_view->page_properties(), params->visual_properties.screen_info,
       params->visual_properties.display_mode,
       /*is_undead=*/params->main_frame_routing_id == MSG_ROUTING_NONE,
       params->never_visible);
@@ -1686,7 +1686,8 @@
     // local root with a new compositing, painting, and input coordinate
     // space/context.
     std::unique_ptr<RenderWidget> render_widget = RenderWidget::CreateForFrame(
-        widget_params.routing_id, compositor_deps, screen_info_from_main_frame,
+        widget_params.routing_id, compositor_deps,
+        render_view->page_properties(), screen_info_from_main_frame,
         blink::kWebDisplayModeUndefined,
         /*is_undead=*/false, /*never_visible=*/false);
 
@@ -2146,8 +2147,9 @@
   // web ScreenInfo or the original ScreenInfo here.
   RenderWidgetFullscreenPepper* widget = RenderWidgetFullscreenPepper::Create(
       fullscreen_widget_routing_id, std::move(show_callback),
-      GetLocalRootRenderWidget()->compositor_deps(), plugin,
-      std::move(main_frame_url), GetLocalRootRenderWidget()->GetWebScreenInfo(),
+      GetLocalRootRenderWidget()->compositor_deps(),
+      render_view()->page_properties(), plugin, std::move(main_frame_url),
+      GetLocalRootRenderWidget()->GetWebScreenInfo(),
       std::move(widget_channel_request));
   // TODO(nick): The show() handshake seems like unnecessary complexity here,
   // since there's no real delay between CreateFullscreenWidget and
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index d76b5b9..312ae58 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -508,7 +508,7 @@
     // RenderWidget for a remote main frame.
     render_widget_ = RenderWidget::CreateForFrame(
         params->main_frame_widget_routing_id, compositor_deps,
-        params->visual_properties.screen_info,
+        page_properties(), params->visual_properties.screen_info,
         params->visual_properties.display_mode,
         /*is_undead=*/params->main_frame_routing_id == MSG_ROUTING_NONE,
         params->never_visible);
@@ -1452,7 +1452,8 @@
 
   RenderWidget* popup_widget = RenderWidget::CreateForPopup(
       widget_routing_id, view_render_widget->compositor_deps(),
-      view_render_widget->screen_info(), blink::kWebDisplayModeUndefined,
+      page_properties(), view_render_widget->screen_info(),
+      blink::kWebDisplayModeUndefined,
       /*hidden=*/false,
       /*never_visible=*/false, std::move(widget_channel_request));
 
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index d27c0b3..518f67fd 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -144,6 +144,11 @@
   RenderWidget* GetWidget();
   const RenderWidget* GetWidget() const;
 
+  // Returns a |page_properties| interface. The lifetime is scoped to
+  // the RenderViewImpl.
+  PageProperties* page_properties() { return &page_properties_; }
+  const PageProperties* page_properties() const { return &page_properties_; }
+
   const WebPreferences& webkit_preferences() const {
     return webkit_preferences_;
   }
@@ -564,6 +569,10 @@
   // to be called.
   bool needs_preferred_size_update_ = true;
 
+  // Properties about the page that are of interest to subframes. These persist
+  // across main-frame navigations.
+  PageProperties page_properties_;
+
   // Loading state -------------------------------------------------------------
 
   // Timer used to delay the updating of nav state (see
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 074a065..bef3446 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -419,36 +419,40 @@
 std::unique_ptr<RenderWidget> RenderWidget::CreateForFrame(
     int32_t widget_routing_id,
     CompositorDependencies* compositor_deps,
+    PageProperties* page_properties,
     const ScreenInfo& screen_info,
     blink::WebDisplayMode display_mode,
     bool is_undead,
     bool never_visible) {
   if (g_create_render_widget_for_frame) {
     return g_create_render_widget_for_frame(
-        widget_routing_id, compositor_deps, screen_info, display_mode,
-        is_undead, never_visible, mojo::NullReceiver());
+        widget_routing_id, compositor_deps, page_properties, screen_info,
+        display_mode, is_undead, never_visible, mojo::NullReceiver());
   }
 
   return std::make_unique<RenderWidget>(
-      widget_routing_id, compositor_deps, screen_info, display_mode, is_undead,
+      widget_routing_id, compositor_deps, page_properties, screen_info,
+      display_mode, is_undead,
       /*hidden=*/true, never_visible, mojo::NullReceiver());
 }
 
 RenderWidget* RenderWidget::CreateForPopup(
     int32_t widget_routing_id,
     CompositorDependencies* compositor_deps,
+    PageProperties* page_properties,
     const ScreenInfo& screen_info,
     blink::WebDisplayMode display_mode,
     bool hidden,
     bool never_visible,
     mojo::PendingReceiver<mojom::Widget> widget_receiver) {
-  return new RenderWidget(widget_routing_id, compositor_deps, screen_info,
-                          display_mode, /*is_undead=*/false, hidden,
-                          never_visible, std::move(widget_receiver));
+  return new RenderWidget(widget_routing_id, compositor_deps, page_properties,
+                          screen_info, display_mode, /*is_undead=*/false,
+                          hidden, never_visible, std::move(widget_receiver));
 }
 
 RenderWidget::RenderWidget(int32_t widget_routing_id,
                            CompositorDependencies* compositor_deps,
+                           PageProperties* page_properties,
                            const ScreenInfo& screen_info,
                            blink::WebDisplayMode display_mode,
                            bool is_undead,
@@ -457,6 +461,7 @@
                            mojo::PendingReceiver<mojom::Widget> widget_receiver)
     : routing_id_(widget_routing_id),
       compositor_deps_(compositor_deps),
+      page_properties_(page_properties),
       is_hidden_(hidden),
       compositor_never_visible_(never_visible),
       display_mode_(display_mode),
@@ -467,6 +472,7 @@
       widget_receiver_(this, std::move(widget_receiver)) {
   DCHECK_NE(routing_id_, MSG_ROUTING_NONE);
   DCHECK(RenderThread::IsMainThread());
+  DCHECK(page_properties);
 
   // In tests there may not be a RenderThreadImpl.
   if (RenderThreadImpl::current()) {
@@ -810,8 +816,6 @@
       delegate()->ApplyAutoResizeLimitsForWidget(min_auto_size, max_auto_size);
     } else if (auto_resize_mode_changed) {
       delegate()->DisableAutoResizeForWidget();
-      if (visual_properties.new_size.IsEmpty())
-        return;
     }
 
     browser_controls_shrink_blink_size_ =
@@ -3811,6 +3815,15 @@
   visual_properties.visible_viewport_size = visible_viewport_size_;
   visual_properties.is_fullscreen_granted = is_fullscreen_granted_;
   visual_properties.display_mode = display_mode_;
+
+  if (new_size.IsEmpty()) {
+    // The |new_size| is empty when resetting auto resize in between tests. In
+    // this case the current size should just be preserved.
+    visual_properties.new_size = size_;
+  } else {
+    visual_properties.new_size = new_size;
+  }
+
   OnSynchronizeVisualProperties(visual_properties);
 }
 
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index 053214e..82b2c2d 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -43,6 +43,7 @@
 #include "content/renderer/input/render_widget_input_handler.h"
 #include "content/renderer/input/render_widget_input_handler_delegate.h"
 #include "content/renderer/mouse_lock_dispatcher.h"
+#include "content/renderer/page_properties.h"
 #include "content/renderer/render_widget_delegate.h"
 #include "content/renderer/render_widget_mouse_lock_dispatcher.h"
 #include "content/renderer/render_widget_screen_metrics_emulator_delegate.h"
@@ -160,6 +161,7 @@
  public:
   RenderWidget(int32_t widget_routing_id,
                CompositorDependencies* compositor_deps,
+               PageProperties* page_properties,
                const ScreenInfo& screen_info,
                blink::WebDisplayMode display_mode,
                bool is_undead,
@@ -185,6 +187,7 @@
   using CreateRenderWidgetFunction = std::unique_ptr<RenderWidget> (*)(
       int32_t,
       CompositorDependencies*,
+      PageProperties*,
       const ScreenInfo&,
       blink::WebDisplayMode display_mode,
       bool is_undead,
@@ -201,6 +204,7 @@
   static std::unique_ptr<RenderWidget> CreateForFrame(
       int32_t widget_routing_id,
       CompositorDependencies* compositor_deps,
+      PageProperties* page_properties,
       const ScreenInfo& screen_info,
       blink::WebDisplayMode display_mode,
       bool is_undead,
@@ -214,6 +218,7 @@
   static RenderWidget* CreateForPopup(
       int32_t widget_routing_id,
       CompositorDependencies* compositor_deps,
+      PageProperties* page_properties,
       const ScreenInfo& screen_info,
       blink::WebDisplayMode display_mode,
       bool hidden,
@@ -957,6 +962,11 @@
   // a RenderViewImpl.
   RenderWidgetDelegate* delegate_ = nullptr;
 
+  // Contains properties that are global to a whole page. This is populated in
+  // all RenderWidgets regardless of whether they are main frame or child
+  // frame widgets.
+  PageProperties* const page_properties_;
+
   // This is lazily constructed and must not outlive webwidget_.
   std::unique_ptr<LayerTreeView> layer_tree_view_;
 
diff --git a/content/renderer/render_widget_fullscreen_pepper.cc b/content/renderer/render_widget_fullscreen_pepper.cc
index 5db5b666..38f342da 100644
--- a/content/renderer/render_widget_fullscreen_pepper.cc
+++ b/content/renderer/render_widget_fullscreen_pepper.cc
@@ -275,15 +275,16 @@
     int32_t routing_id,
     RenderWidget::ShowCallback show_callback,
     CompositorDependencies* compositor_deps,
+    PageProperties* page_properties,
     PepperPluginInstanceImpl* plugin,
     const blink::WebURL& local_main_frame_url,
     const ScreenInfo& screen_info,
     mojo::PendingReceiver<mojom::Widget> widget_receiver) {
   DCHECK_NE(MSG_ROUTING_NONE, routing_id);
   DCHECK(show_callback);
-  RenderWidgetFullscreenPepper* widget =
-      new RenderWidgetFullscreenPepper(routing_id, compositor_deps, plugin,
-                                       screen_info, std::move(widget_receiver));
+  RenderWidgetFullscreenPepper* widget = new RenderWidgetFullscreenPepper(
+      routing_id, compositor_deps, page_properties, plugin, screen_info,
+      std::move(widget_receiver));
   widget->Init(std::move(show_callback),
                new PepperWidget(widget, local_main_frame_url));
   return widget;
@@ -292,11 +293,13 @@
 RenderWidgetFullscreenPepper::RenderWidgetFullscreenPepper(
     int32_t routing_id,
     CompositorDependencies* compositor_deps,
+    PageProperties* page_properties,
     PepperPluginInstanceImpl* plugin,
     const ScreenInfo& screen_info,
     mojo::PendingReceiver<mojom::Widget> widget_receiver)
     : RenderWidget(routing_id,
                    compositor_deps,
+                   page_properties,
                    screen_info,
                    blink::kWebDisplayModeUndefined,
                    false,
diff --git a/content/renderer/render_widget_fullscreen_pepper.h b/content/renderer/render_widget_fullscreen_pepper.h
index 0c1dc33..89b060d 100644
--- a/content/renderer/render_widget_fullscreen_pepper.h
+++ b/content/renderer/render_widget_fullscreen_pepper.h
@@ -37,6 +37,7 @@
       int32_t routing_id,
       RenderWidget::ShowCallback show_callback,
       CompositorDependencies* compositor_deps,
+      PageProperties* page_properties,
       PepperPluginInstanceImpl* plugin,
       const blink::WebURL& local_main_frame_url,
       const ScreenInfo& screen_info,
@@ -62,6 +63,7 @@
   RenderWidgetFullscreenPepper(
       int32_t routing_id,
       CompositorDependencies* compositor_deps,
+      PageProperties* page_properties,
       PepperPluginInstanceImpl* plugin,
       const ScreenInfo& screen_info,
       mojo::PendingReceiver<mojom::Widget> widget_receiver);
diff --git a/content/renderer/render_widget_unittest.cc b/content/renderer/render_widget_unittest.cc
index 8acd0ad..54e63b3d 100644
--- a/content/renderer/render_widget_unittest.cc
+++ b/content/renderer/render_widget_unittest.cc
@@ -179,9 +179,11 @@
 
 class InteractiveRenderWidget : public RenderWidget {
  public:
-  explicit InteractiveRenderWidget(CompositorDependencies* compositor_deps)
+  InteractiveRenderWidget(CompositorDependencies* compositor_deps,
+                          PageProperties* page_properties)
       : RenderWidget(++next_routing_id_,
                      compositor_deps,
+                     page_properties,
                      ScreenInfo(),
                      blink::kWebDisplayModeUndefined,
                      false,
@@ -264,7 +266,8 @@
  public:
   // testing::Test implementation.
   void SetUp() override {
-    widget_ = std::make_unique<InteractiveRenderWidget>(&compositor_deps_);
+    widget_ = std::make_unique<InteractiveRenderWidget>(&compositor_deps_,
+                                                        &page_properties_);
   }
 
   void DestroyWidget() {
@@ -289,6 +292,7 @@
   MockRenderProcess render_process_;
   MockRenderThread render_thread_;
   FakeCompositorDependencies compositor_deps_;
+  PageProperties page_properties_;
   std::unique_ptr<InteractiveRenderWidget> widget_;
   base::HistogramTester histogram_tester_;
 };
@@ -448,9 +452,11 @@
 
 class PopupRenderWidget : public RenderWidget {
  public:
-  explicit PopupRenderWidget(CompositorDependencies* compositor_deps)
+  PopupRenderWidget(CompositorDependencies* compositor_deps,
+                    PageProperties* page_properties)
       : RenderWidget(routing_id_++,
                      compositor_deps,
+                     page_properties,
                      ScreenInfo(),
                      blink::kWebDisplayModeUndefined,
                      false,
@@ -503,11 +509,13 @@
 
   // testing::Test implementation.
   void SetUp() override {
-    widget_ = std::make_unique<PopupRenderWidget>(&compositor_deps_);
+    widget_ = std::make_unique<PopupRenderWidget>(&compositor_deps_,
+                                                  &page_properties_);
   }
 
   PopupRenderWidget* widget() const { return widget_.get(); }
   FakeCompositorDependencies compositor_deps_;
+  PageProperties page_properties_;
 
  protected:
   base::test::TaskEnvironment task_environment_;
@@ -596,7 +604,7 @@
   visual_properties.new_size = parent_window_rect.size();
 
   std::unique_ptr<PopupRenderWidget> parent_widget(
-      new PopupRenderWidget(&compositor_deps_));
+      new PopupRenderWidget(&compositor_deps_, &page_properties_));
 
   // Setup emulation on the |parent_widget|.
   parent_widget->OnSynchronizeVisualProperties(visual_properties);
diff --git a/content/shell/android/BUILD.gn b/content/shell/android/BUILD.gn
index c42bba7..6547898 100644
--- a/content/shell/android/BUILD.gn
+++ b/content/shell/android/BUILD.gn
@@ -230,10 +230,12 @@
   shared_libraries = [ ":libcontent_native_test" ]
   android_manifest = "javatests/AndroidManifest.xml"
 
+  data_deps = [
+    "//testing/buildbot/filters:content_shell_test_apk_filters",
+  ]
+
   if (enable_chrome_android_internal) {
-    data_deps = [
-      "//clank/build/bot/filters:content_shell_test_apk_filters",
-    ]
+    data_deps += [ "//clank/build/bot/filters:content_shell_test_apk_filters" ]
   }
 }
 
diff --git a/content/shell/renderer/web_test/blink_test_runner.cc b/content/shell/renderer/web_test/blink_test_runner.cc
index 2a7515a..5a58803 100644
--- a/content/shell/renderer/web_test/blink_test_runner.cc
+++ b/content/shell/renderer/web_test/blink_test_runner.cc
@@ -277,8 +277,16 @@
 
 void BlinkTestRunner::DisableAutoResizeMode(const WebSize& new_size) {
   content::DisableAutoResizeMode(render_view(), new_size);
-  if (!new_size.IsEmpty())
-    ForceResizeRenderView(render_view(), new_size);
+  ForceResizeRenderView(render_view(), new_size);
+}
+
+void BlinkTestRunner::ResetAutoResizeMode() {
+  // An empty size indicates to keep the size as is. Resetting races with the
+  // browser setting up the new test (one is a mojo IPC (OnSetTestConfiguration)
+  // and one is legacy (OnReset)) so we can not clobber the size here.
+  content::DisableAutoResizeMode(render_view(), gfx::Size());
+  // Does not call ForceResizeRenderView() here intentionally. This is between
+  // tests, and the next test will set up a size.
 }
 
 void BlinkTestRunner::NavigateSecondaryWindow(const GURL& url) {
diff --git a/content/shell/renderer/web_test/blink_test_runner.h b/content/shell/renderer/web_test/blink_test_runner.h
index 6fe5214..d7764be 100644
--- a/content/shell/renderer/web_test/blink_test_runner.h
+++ b/content/shell/renderer/web_test/blink_test_runner.h
@@ -76,6 +76,7 @@
   void EnableAutoResizeMode(const blink::WebSize& min_size,
                             const blink::WebSize& max_size) override;
   void DisableAutoResizeMode(const blink::WebSize& new_size) override;
+  void ResetAutoResizeMode() override;
   void NavigateSecondaryWindow(const GURL& url) override;
   void InspectSecondaryWindow() override;
   void ClearAllDatabases() override;
diff --git a/content/shell/test_runner/spell_check_client.cc b/content/shell/test_runner/spell_check_client.cc
index 802f470..d6b3b81 100644
--- a/content/shell/test_runner/spell_check_client.cc
+++ b/content/shell/test_runner/spell_check_client.cc
@@ -122,7 +122,7 @@
   last_requested_text_checking_completion_.reset();
   RequestResolved();
 
-  if (test_runner_->shouldDumpSpellCheckCallbacks())
+  if (test_runner_->ShouldDumpSpellCheckCallbacks())
     delegate_->PrintMessage("SpellCheckEvent: FinishLastTextCheck\n");
 }
 
diff --git a/content/shell/test_runner/test_interfaces.cc b/content/shell/test_runner/test_interfaces.cc
index 7ceea1f1..102a5ea 100644
--- a/content/shell/test_runner/test_interfaces.cc
+++ b/content/shell/test_runner/test_interfaces.cc
@@ -102,21 +102,21 @@
   // execute the same code regardless of the protocol mode, e.g. for ease of
   // debugging a web test issue.
   if (!protocol_mode)
-    test_runner_->setShouldDumpAsLayout(true);
+    test_runner_->SetShouldDumpAsLayout(true);
 
   // For http/tests/loading/, which is served via httpd and becomes /loading/.
   if (spec.find("/loading/") != std::string::npos)
-    test_runner_->setShouldDumpFrameLoadCallbacks(true);
+    test_runner_->SetShouldDumpFrameLoadCallbacks(true);
   if (spec.find("/dumpAsText/") != std::string::npos) {
-    test_runner_->setShouldDumpAsText(true);
-    test_runner_->setShouldGeneratePixelResults(false);
+    test_runner_->SetShouldDumpAsText(true);
+    test_runner_->SetShouldGeneratePixelResults(false);
   }
   test_runner_->SetV8CacheDisabled(is_devtools_test);
 
   if (spec.find("/viewsource/") != std::string::npos) {
-    test_runner_->setShouldEnableViewSource(true);
-    test_runner_->setShouldGeneratePixelResults(false);
-    test_runner_->setShouldDumpAsMarkup(true);
+    test_runner_->SetShouldEnableViewSource(true);
+    test_runner_->SetShouldGeneratePixelResults(false);
+    test_runner_->SetShouldDumpAsMarkup(true);
   }
   if (spec.find("/external/wpt/") != std::string::npos ||
       spec.find("/external/csswg-test/") != std::string::npos ||
diff --git a/content/shell/test_runner/test_runner.cc b/content/shell/test_runner/test_runner.cc
index e699c78..ed0b140 100644
--- a/content/shell/test_runner/test_runner.cc
+++ b/content/shell/test_runner/test_runner.cc
@@ -277,8 +277,8 @@
   void WaitForPolicyDelegate();
   void WaitUntilDone();
   void WaitUntilExternalURLLoad();
-  bool DisableAutoResizeMode(int new_width, int new_height);
-  bool EnableAutoResizeMode(int min_width,
+  void DisableAutoResizeMode(int new_width, int new_height);
+  void EnableAutoResizeMode(int min_width,
                             int min_height,
                             int max_width,
                             int max_height);
@@ -873,21 +873,17 @@
     runner_->UseUnfortunateSynchronousResizeMode();
 }
 
-bool TestRunnerBindings::EnableAutoResizeMode(int min_width,
+void TestRunnerBindings::EnableAutoResizeMode(int min_width,
                                               int min_height,
                                               int max_width,
                                               int max_height) {
-  if (runner_) {
-    return runner_->EnableAutoResizeMode(min_width, min_height, max_width,
-                                         max_height);
-  }
-  return false;
+  if (runner_)
+    runner_->EnableAutoResizeMode(min_width, min_height, max_width, max_height);
 }
 
-bool TestRunnerBindings::DisableAutoResizeMode(int new_width, int new_height) {
+void TestRunnerBindings::DisableAutoResizeMode(int new_width, int new_height) {
   if (runner_)
     return runner_->DisableAutoResizeMode(new_width, new_height);
-  return false;
 }
 
 void TestRunnerBindings::SetMockScreenOrientation(
@@ -1115,7 +1111,7 @@
 
 void TestRunnerBindings::SetShouldGeneratePixelResults(bool value) {
   if (runner_)
-    runner_->setShouldGeneratePixelResults(value);
+    runner_->SetShouldGeneratePixelResults(value);
 }
 
 void TestRunnerBindings::SetShouldStayOnPageAfterHandlingBeforeUnload(
@@ -1352,7 +1348,7 @@
 
 void TestRunnerBindings::SetCustomTextOutput(const std::string& output) {
   if (runner_)
-    runner_->setCustomTextOutput(output);
+    runner_->SetCustomTextOutput(output);
 }
 
 void TestRunnerBindings::SetViewSourceForFrame(const std::string& name,
@@ -1545,7 +1541,7 @@
     delegate_->SetBlockThirdPartyCookies(false);
     delegate_->SetLocale("");
     delegate_->UseUnfortunateSynchronousResizeMode(false);
-    delegate_->DisableAutoResizeMode(blink::WebSize());
+    delegate_->ResetAutoResizeMode();
     delegate_->DeleteAllCookies();
     delegate_->SetBluetoothManualChooser(false);
     delegate_->ResetPermissions();
@@ -1588,34 +1584,34 @@
   return web_test_runtime_flags_.dump_selection_rect();
 }
 
-bool TestRunner::shouldDumpEditingCallbacks() const {
+bool TestRunner::ShouldDumpEditingCallbacks() const {
   return web_test_runtime_flags_.dump_editting_callbacks();
 }
 
-void TestRunner::setShouldDumpAsText(bool value) {
+void TestRunner::SetShouldDumpAsText(bool value) {
   web_test_runtime_flags_.set_dump_as_text(value);
   OnWebTestRuntimeFlagsChanged();
 }
 
-void TestRunner::setShouldDumpAsMarkup(bool value) {
+void TestRunner::SetShouldDumpAsMarkup(bool value) {
   web_test_runtime_flags_.set_dump_as_markup(value);
   OnWebTestRuntimeFlagsChanged();
 }
 
-void TestRunner::setShouldDumpAsLayout(bool value) {
+void TestRunner::SetShouldDumpAsLayout(bool value) {
   web_test_runtime_flags_.set_dump_as_layout(value);
   OnWebTestRuntimeFlagsChanged();
 }
 
-bool TestRunner::shouldDumpAsCustomText() const {
+bool TestRunner::ShouldDumpAsCustomText() const {
   return web_test_runtime_flags_.has_custom_text_output();
 }
 
-std::string TestRunner::customDumpText() const {
+std::string TestRunner::CustomDumpText() const {
   return web_test_runtime_flags_.custom_text_output();
 }
 
-void TestRunner::setCustomTextOutput(const std::string& text) {
+void TestRunner::SetCustomTextOutput(const std::string& text) {
   web_test_runtime_flags_.set_custom_text_output(text);
   web_test_runtime_flags_.set_has_custom_text_output(true);
   OnWebTestRuntimeFlagsChanged();
@@ -1626,11 +1622,11 @@
   return web_test_runtime_flags_.generate_pixel_results();
 }
 
-bool TestRunner::shouldStayOnPageAfterHandlingBeforeUnload() const {
+bool TestRunner::ShouldStayOnPageAfterHandlingBeforeUnload() const {
   return web_test_runtime_flags_.stay_on_page_after_handling_before_unload();
 }
 
-void TestRunner::setShouldGeneratePixelResults(bool value) {
+void TestRunner::SetShouldGeneratePixelResults(bool value) {
   web_test_runtime_flags_.set_generate_pixel_results(value);
   OnWebTestRuntimeFlagsChanged();
 }
@@ -1705,30 +1701,30 @@
 }
 
 bool TestRunner::HasCustomTextDump(std::string* custom_text_dump) const {
-  if (shouldDumpAsCustomText()) {
-    *custom_text_dump = customDumpText();
+  if (ShouldDumpAsCustomText()) {
+    *custom_text_dump = CustomDumpText();
     return true;
   }
 
   return false;
 }
 
-bool TestRunner::shouldDumpFrameLoadCallbacks() const {
+bool TestRunner::ShouldDumpFrameLoadCallbacks() const {
   return test_is_running_ &&
          web_test_runtime_flags_.dump_frame_load_callbacks();
 }
 
-void TestRunner::setShouldDumpFrameLoadCallbacks(bool value) {
+void TestRunner::SetShouldDumpFrameLoadCallbacks(bool value) {
   web_test_runtime_flags_.set_dump_frame_load_callbacks(value);
   OnWebTestRuntimeFlagsChanged();
 }
 
-bool TestRunner::shouldDumpPingLoaderCallbacks() const {
+bool TestRunner::ShouldDumpPingLoaderCallbacks() const {
   return test_is_running_ &&
          web_test_runtime_flags_.dump_ping_loader_callbacks();
 }
 
-void TestRunner::setShouldEnableViewSource(bool value) {
+void TestRunner::SetShouldEnableViewSource(bool value) {
   // TODO(lukasza): This flag should be 1) replicated across OOPIFs and
   // 2) applied to all views, not just the main window view.
 
@@ -1741,28 +1737,28 @@
   main_view_->MainFrame()->ToWebLocalFrame()->EnableViewSourceMode(value);
 }
 
-bool TestRunner::shouldDumpUserGestureInFrameLoadCallbacks() const {
+bool TestRunner::ShouldDumpUserGestureInFrameLoadCallbacks() const {
   return test_is_running_ &&
          web_test_runtime_flags_.dump_user_gesture_in_frame_load_callbacks();
 }
 
-bool TestRunner::shouldDumpTitleChanges() const {
+bool TestRunner::ShouldDumpTitleChanges() const {
   return web_test_runtime_flags_.dump_title_changes();
 }
 
-bool TestRunner::shouldDumpIconChanges() const {
+bool TestRunner::ShouldDumpIconChanges() const {
   return web_test_runtime_flags_.dump_icon_changes();
 }
 
-bool TestRunner::shouldDumpCreateView() const {
+bool TestRunner::ShouldDumpCreateView() const {
   return web_test_runtime_flags_.dump_create_view();
 }
 
-bool TestRunner::canOpenWindows() const {
+bool TestRunner::CanOpenWindows() const {
   return web_test_runtime_flags_.can_open_windows();
 }
 
-bool TestRunner::shouldDumpResourceLoadCallbacks() const {
+bool TestRunner::ShouldDumpResourceLoadCallbacks() const {
   return test_is_running_ &&
          web_test_runtime_flags_.dump_resource_load_callbacks();
 }
@@ -1775,7 +1771,7 @@
   return spellcheck_.get();
 }
 
-bool TestRunner::shouldDumpSpellCheckCallbacks() const {
+bool TestRunner::ShouldDumpSpellCheckCallbacks() const {
   return web_test_runtime_flags_.dump_spell_check_callbacks();
 }
 
@@ -1783,15 +1779,11 @@
   return dump_back_forward_list_;
 }
 
-bool TestRunner::isPrinting() const {
-  return web_test_runtime_flags_.is_printing();
-}
-
-bool TestRunner::shouldWaitUntilExternalURLLoad() const {
+bool TestRunner::ShouldWaitUntilExternalURLLoad() const {
   return web_test_runtime_flags_.wait_until_external_url_load();
 }
 
-const std::set<std::string>* TestRunner::httpHeadersToClear() const {
+const std::set<std::string>* TestRunner::HttpHeadersToClear() const {
   return &http_headers_to_clear_;
 }
 
@@ -1892,37 +1884,37 @@
   return main_view_->MainFrame();
 }
 
-void TestRunner::policyDelegateDone() {
+void TestRunner::PolicyDelegateDone() {
   DCHECK(web_test_runtime_flags_.wait_until_done());
   delegate_->TestFinished();
   web_test_runtime_flags_.set_wait_until_done(false);
   OnWebTestRuntimeFlagsChanged();
 }
 
-bool TestRunner::policyDelegateEnabled() const {
+bool TestRunner::PolicyDelegateEnabled() const {
   return web_test_runtime_flags_.policy_delegate_enabled();
 }
 
-bool TestRunner::policyDelegateIsPermissive() const {
+bool TestRunner::PolicyDelegateIsPermissive() const {
   return web_test_runtime_flags_.policy_delegate_is_permissive();
 }
 
-bool TestRunner::policyDelegateShouldNotifyDone() const {
+bool TestRunner::PolicyDelegateShouldNotifyDone() const {
   return web_test_runtime_flags_.policy_delegate_should_notify_done();
 }
 
-void TestRunner::setToolTipText(const blink::WebString& text) {
+void TestRunner::SetToolTipText(const blink::WebString& text) {
   tooltip_text_ = text.Utf8();
 }
 
-void TestRunner::setDragImage(const SkBitmap& drag_image) {
+void TestRunner::SetDragImage(const SkBitmap& drag_image) {
   if (web_test_runtime_flags_.dump_drag_image()) {
     if (drag_image_.isNull())
       drag_image_ = drag_image;
   }
 }
 
-bool TestRunner::shouldDumpNavigationPolicy() const {
+bool TestRunner::ShouldDumpNavigationPolicy() const {
   return web_test_runtime_flags_.dump_navigation_policy();
 }
 
@@ -2129,23 +2121,25 @@
   delegate_->UseUnfortunateSynchronousResizeMode(true);
 }
 
-bool TestRunner::EnableAutoResizeMode(int min_width,
+void TestRunner::EnableAutoResizeMode(int min_width,
                                       int min_height,
                                       int max_width,
                                       int max_height) {
+  if (max_width <= 0 || max_height <= 0)
+    return;
   blink::WebSize min_size(min_width, min_height);
   blink::WebSize max_size(max_width, max_height);
   delegate_->EnableAutoResizeMode(min_size, max_size);
-  return true;
 }
 
-bool TestRunner::DisableAutoResizeMode(int new_width, int new_height) {
+void TestRunner::DisableAutoResizeMode(int new_width, int new_height) {
+  if (new_width <= 0 || new_height <= 0)
+    return;
   blink::WebSize new_size(new_width, new_height);
   delegate_->DisableAutoResizeMode(new_size);
-  return true;
 }
 
-MockScreenOrientationClient* TestRunner::getMockScreenOrientationClient() {
+MockScreenOrientationClient* TestRunner::GetMockScreenOrientationClient() {
   return &mock_screen_orientation_client_;
 }
 
diff --git a/content/shell/test_runner/test_runner.h b/content/shell/test_runner/test_runner.h
index 7ec7ca59..2f86f3a 100644
--- a/content/shell/test_runner/test_runner.h
+++ b/content/shell/test_runner/test_runner.h
@@ -50,12 +50,12 @@
 class WebTestDelegate;
 
 // TestRunner class currently has dual purpose:
-// 1. It implements |testRunner| javascript bindings for "global" / "ambient".
+// 1. It implements TestRunner javascript bindings for "global" / "ambient".
 //    Examples:
-//    - testRunner.dumpAsText (test flag affecting test behavior)
-//    - testRunner.setAllowRunningOfInsecureContent (test flag affecting product
+//    - TestRunner.DumpAsText (test flag affecting test behavior)
+//    - TestRunner.SetAllowRunningOfInsecureContent (test flag affecting product
 //      behavior)
-//    - testRunner.setTextSubpixelPositioning (directly interacts with product).
+//    - TestRunner.SetTextSubpixelPositioning (directly interacts with product).
 //    Note that "per-view" (non-"global") bindings are handled by
 //    instances of TestRunnerForSpecificView class.
 // 2. It manages global test state.  Example:
@@ -109,33 +109,32 @@
 
   // Methods used by WebViewTestClient and WebFrameTestClient.
   std::string GetAcceptLanguages() const;
-  bool shouldStayOnPageAfterHandlingBeforeUnload() const;
-  MockScreenOrientationClient* getMockScreenOrientationClient();
-  bool isPrinting() const;
-  bool shouldDumpAsCustomText() const;
-  std::string customDumpText() const;
+  bool ShouldStayOnPageAfterHandlingBeforeUnload() const;
+  MockScreenOrientationClient* GetMockScreenOrientationClient();
+  bool ShouldDumpAsCustomText() const;
+  std::string CustomDumpText() const;
   void ShowDevTools(const std::string& settings,
                     const std::string& frontend_url);
   void SetV8CacheDisabled(bool);
-  void setShouldDumpAsText(bool);
-  void setShouldDumpAsMarkup(bool);
-  void setShouldDumpAsLayout(bool);
-  void setCustomTextOutput(const std::string& text);
-  void setShouldGeneratePixelResults(bool);
-  void setShouldDumpFrameLoadCallbacks(bool);
-  void setShouldEnableViewSource(bool);
-  bool shouldDumpEditingCallbacks() const;
-  bool shouldDumpFrameLoadCallbacks() const;
-  bool shouldDumpPingLoaderCallbacks() const;
-  bool shouldDumpUserGestureInFrameLoadCallbacks() const;
-  bool shouldDumpTitleChanges() const;
-  bool shouldDumpIconChanges() const;
-  bool shouldDumpCreateView() const;
-  bool canOpenWindows() const;
-  bool shouldDumpResourceLoadCallbacks() const;
-  bool shouldDumpSpellCheckCallbacks() const;
-  bool shouldWaitUntilExternalURLLoad() const;
-  const std::set<std::string>* httpHeadersToClear() const;
+  void SetShouldDumpAsText(bool);
+  void SetShouldDumpAsMarkup(bool);
+  void SetShouldDumpAsLayout(bool);
+  void SetCustomTextOutput(const std::string& text);
+  void SetShouldGeneratePixelResults(bool);
+  void SetShouldDumpFrameLoadCallbacks(bool);
+  void SetShouldEnableViewSource(bool);
+  bool ShouldDumpEditingCallbacks() const;
+  bool ShouldDumpFrameLoadCallbacks() const;
+  bool ShouldDumpPingLoaderCallbacks() const;
+  bool ShouldDumpUserGestureInFrameLoadCallbacks() const;
+  bool ShouldDumpTitleChanges() const;
+  bool ShouldDumpIconChanges() const;
+  bool ShouldDumpCreateView() const;
+  bool CanOpenWindows() const;
+  bool ShouldDumpResourceLoadCallbacks() const;
+  bool ShouldDumpSpellCheckCallbacks() const;
+  bool ShouldWaitUntilExternalURLLoad() const;
+  const std::set<std::string>* HttpHeadersToClear() const;
   bool is_web_platform_tests_mode() const {
     return is_web_platform_tests_mode_;
   }
@@ -153,18 +152,18 @@
   // Remove |frame| from the set of loading frames.
   //
   // When there are no more loading frames, this potentially finishes the test,
-  // unless testRunner.waitUntilDone() was called and/or there are pending load
+  // unless TestRunner.WaitUntilDone() was called and/or there are pending load
   // requests in WorkQueue.
   void RemoveLoadingFrame(blink::WebFrame* frame);
 
   blink::WebFrame* MainFrame() const;
-  void policyDelegateDone();
-  bool policyDelegateEnabled() const;
-  bool policyDelegateIsPermissive() const;
-  bool policyDelegateShouldNotifyDone() const;
-  void setToolTipText(const blink::WebString&);
-  void setDragImage(const SkBitmap& drag_image);
-  bool shouldDumpNavigationPolicy() const;
+  void PolicyDelegateDone();
+  bool PolicyDelegateEnabled() const;
+  bool PolicyDelegateIsPermissive() const;
+  bool PolicyDelegateShouldNotifyDone() const;
+  void SetToolTipText(const blink::WebString&);
+  void SetDragImage(const SkBitmap& drag_image);
+  bool ShouldDumpNavigationPolicy() const;
 
   bool ShouldDumpConsoleMessages() const;
   // Controls whether console messages produced by the page are dumped
@@ -190,8 +189,8 @@
   friend class TestRunnerBindings;
   friend class WorkQueue;
 
-  // Helper class for managing events queued by methods like queueLoad or
-  // queueScript.
+  // Helper class for managing events queued by methods like QueueLoad or
+  // QueueScript.
   class WorkQueue {
    public:
     explicit WorkQueue(TestRunner* controller);
@@ -223,12 +222,12 @@
   // Methods dealing with the test logic
 
   // By default, tests end when page load is complete. These methods are used
-  // to delay the completion of the test until notifyDone is called.
+  // to delay the completion of the test until NotifyDone is called.
   void NotifyDone();
   void WaitUntilDone();
 
   // Methods for adding actions to the work queue. Used in conjunction with
-  // waitUntilDone/notifyDone above.
+  // WaitUntilDone/NotifyDone above.
   void QueueBackNavigation(int how_far_back);
   void QueueForwardNavigation(int how_far_forward);
   void QueueReload();
@@ -275,11 +274,11 @@
   // http://crbug.com/309760 for the plan.
   void UseUnfortunateSynchronousResizeMode();
 
-  bool EnableAutoResizeMode(int min_width,
+  void EnableAutoResizeMode(int min_width,
                             int min_height,
                             int max_width,
                             int max_height);
-  bool DisableAutoResizeMode(int new_width, int new_height);
+  void DisableAutoResizeMode(int new_width, int new_height);
 
   void SetMockScreenOrientation(const std::string& orientation);
   void DisableMockScreenOrientation();
@@ -424,7 +423,7 @@
   void SetUseMockTheme(bool use);
 
   // Sets a flag that causes the test to be marked as completed when the
-  // WebLocalFrameClient receives a loadURLExternally() call.
+  // WebLocalFrameClient receives a LoadURLExternally() call.
   void WaitUntilExternalURLLoad();
 
   // This function sets a flag to dump the drag image when the next drag&drop is
@@ -433,7 +432,7 @@
   void DumpDragImage();
 
   // Sets a flag that tells the WebViewTestProxy to dump the default navigation
-  // policy passed to the decidePolicyForNavigation callback.
+  // policy passed to the DecidePolicyForNavigation callback.
   void DumpNavigationPolicy();
 
   // Controls whether JavaScript dialogs such as alert() are dumped to test
@@ -523,7 +522,7 @@
 
   // When reset is called, go through and close all but the main test shell
   // window. By default, set to true but toggled to false using
-  // setCloseRemainingWindowsWhenComplete().
+  // SetCloseRemainingWindowsWhenComplete().
   bool close_remaining_windows_ = false;
 
   WorkQueue work_queue_;
diff --git a/content/shell/test_runner/web_frame_test_client.cc b/content/shell/test_runner/web_frame_test_client.cc
index 11c4c19..5e7b0b9 100644
--- a/content/shell/test_runner/web_frame_test_client.cc
+++ b/content/shell/test_runner/web_frame_test_client.cc
@@ -189,7 +189,7 @@
 bool WebFrameTestClient::RunModalBeforeUnloadDialog(bool is_reload) {
   if (test_runner()->ShouldDumpJavaScriptDialogs())
     delegate_->PrintMessage(std::string("CONFIRM NAVIGATION\n"));
-  return !test_runner()->shouldStayOnPageAfterHandlingBeforeUnload();
+  return !test_runner()->ShouldStayOnPageAfterHandlingBeforeUnload();
 }
 
 void WebFrameTestClient::PostAccessibilityEvent(
@@ -325,14 +325,14 @@
 }
 
 void WebFrameTestClient::DidChangeSelection(bool is_empty_callback) {
-  if (test_runner()->shouldDumpEditingCallbacks())
+  if (test_runner()->ShouldDumpEditingCallbacks())
     delegate_->PrintMessage(
         "EDITING DELEGATE: "
         "webViewDidChangeSelection:WebViewDidChangeSelectionNotification\n");
 }
 
 void WebFrameTestClient::DidChangeContents() {
-  if (test_runner()->shouldDumpEditingCallbacks())
+  if (test_runner()->ShouldDumpEditingCallbacks())
     delegate_->PrintMessage(
         "EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification\n");
 }
@@ -357,7 +357,7 @@
     blink::WebLocalFrameClient::CrossOriginRedirects
         cross_origin_redirect_behavior,
     mojo::ScopedMessagePipeHandle blob_url_token) {
-  if (test_runner()->shouldWaitUntilExternalURLLoad()) {
+  if (test_runner()->ShouldWaitUntilExternalURLLoad()) {
     delegate_->PrintMessage(std::string("Download started\n"));
     delegate_->TestFinished();
   }
@@ -365,20 +365,20 @@
 
 void WebFrameTestClient::DidReceiveTitle(const blink::WebString& title,
                                          blink::WebTextDirection direction) {
-  if (test_runner()->shouldDumpFrameLoadCallbacks() &&
+  if (test_runner()->ShouldDumpFrameLoadCallbacks() &&
       web_frame_test_proxy_->GetWebFrame()) {
     PrintFrameDescription(delegate_, web_frame_test_proxy_->GetWebFrame());
     delegate_->PrintMessage(std::string(" - didReceiveTitle: ") + title.Utf8() +
                             "\n");
   }
 
-  if (test_runner()->shouldDumpTitleChanges())
+  if (test_runner()->ShouldDumpTitleChanges())
     delegate_->PrintMessage(std::string("TITLE CHANGED: '") + title.Utf8() +
                             "'\n");
 }
 
 void WebFrameTestClient::DidChangeIcon(blink::WebIconURL::Type icon_type) {
-  if (test_runner()->shouldDumpIconChanges()) {
+  if (test_runner()->ShouldDumpIconChanges()) {
     PrintFrameDescription(delegate_, web_frame_test_proxy_->GetWebFrame());
     delegate_->PrintMessage(std::string(" - didChangeIcons\n"));
   }
@@ -386,7 +386,7 @@
 
 void WebFrameTestClient::DidFailLoad(const blink::WebURLError& error,
                                      blink::WebHistoryCommitType commit_type) {
-  if (test_runner()->shouldDumpFrameLoadCallbacks()) {
+  if (test_runner()->ShouldDumpFrameLoadCallbacks()) {
     PrintFrameDescription(delegate_, web_frame_test_proxy_->GetWebFrame());
     delegate_->PrintMessage(" - didFailLoadWithError\n");
   }
@@ -401,7 +401,7 @@
 }
 
 void WebFrameTestClient::DidDispatchPingLoader(const blink::WebURL& url) {
-  if (test_runner()->shouldDumpPingLoaderCallbacks())
+  if (test_runner()->ShouldDumpPingLoaderCallbacks())
     delegate_->PrintMessage(std::string("PingLoader dispatched to '") +
                             URLDescription(url).c_str() + "'.\n");
 }
@@ -413,7 +413,7 @@
 
   GURL main_document_url = request.SiteForCookies();
 
-  if (test_runner()->shouldDumpResourceLoadCallbacks()) {
+  if (test_runner()->ShouldDumpResourceLoadCallbacks()) {
     delegate_->PrintMessage(DescriptionSuitableForTestResult(request_url));
     delegate_->PrintMessage(" - willSendRequest <NSURLRequest URL ");
     delegate_->PrintMessage(
@@ -425,8 +425,8 @@
     delegate_->PrintMessage(">\n");
   }
 
-  if (test_runner()->httpHeadersToClear()) {
-    for (const std::string& header : *test_runner()->httpHeadersToClear())
+  if (test_runner()->HttpHeadersToClear()) {
+    for (const std::string& header : *test_runner()->HttpHeadersToClear())
       request.ClearHttpHeaderField(blink::WebString::FromUTF8(header));
   }
 
@@ -509,14 +509,14 @@
 
 bool WebFrameTestClient::ShouldContinueNavigation(
     blink::WebNavigationInfo* info) {
-  if (test_runner()->shouldDumpNavigationPolicy()) {
+  if (test_runner()->ShouldDumpNavigationPolicy()) {
     delegate_->PrintMessage(
         "Default policy for navigation to '" +
         URLDescription(info->url_request.Url()) + "' is '" +
         WebNavigationPolicyToString(info->navigation_policy) + "'\n");
   }
 
-  if (test_runner()->shouldDumpFrameLoadCallbacks()) {
+  if (test_runner()->ShouldDumpFrameLoadCallbacks()) {
     GURL url = info->url_request.Url();
     WebFrameTestClient::PrintFrameDescription(
         delegate_, web_frame_test_proxy_->GetWebFrame());
@@ -529,20 +529,20 @@
   }
 
   bool should_continue = true;
-  if (test_runner()->policyDelegateEnabled()) {
+  if (test_runner()->PolicyDelegateEnabled()) {
     delegate_->PrintMessage(
         std::string("Policy delegate: attempt to load ") +
         URLDescription(info->url_request.Url()) + " with navigation type '" +
         WebNavigationTypeToString(info->navigation_type) + "'\n");
-    should_continue = test_runner()->policyDelegateIsPermissive();
-    if (test_runner()->policyDelegateShouldNotifyDone()) {
-      test_runner()->policyDelegateDone();
+    should_continue = test_runner()->PolicyDelegateIsPermissive();
+    if (test_runner()->PolicyDelegateShouldNotifyDone()) {
+      test_runner()->PolicyDelegateDone();
       should_continue = false;
     }
   }
 
-  if (test_runner()->httpHeadersToClear()) {
-    for (const std::string& header : *test_runner()->httpHeadersToClear()) {
+  if (test_runner()->HttpHeadersToClear()) {
+    for (const std::string& header : *test_runner()->HttpHeadersToClear()) {
       info->url_request.ClearHttpHeaderField(
           blink::WebString::FromUTF8(header));
     }
diff --git a/content/shell/test_runner/web_frame_test_proxy.cc b/content/shell/test_runner/web_frame_test_proxy.cc
index a0cc0fc..afa9efd 100644
--- a/content/shell/test_runner/web_frame_test_proxy.cc
+++ b/content/shell/test_runner/web_frame_test_proxy.cc
@@ -46,13 +46,13 @@
   void DidStartNavigation(
       const GURL& url,
       base::Optional<blink::WebNavigationType> navigation_type) override {
-    if (test_runner()->shouldDumpFrameLoadCallbacks()) {
+    if (test_runner()->ShouldDumpFrameLoadCallbacks()) {
       WebFrameTestClient::PrintFrameDescription(delegate(),
                                                 render_frame()->GetWebFrame());
       delegate()->PrintMessage(" - DidStartNavigation\n");
     }
 
-    if (test_runner()->shouldDumpUserGestureInFrameLoadCallbacks()) {
+    if (test_runner()->ShouldDumpUserGestureInFrameLoadCallbacks()) {
       PrintFrameUserGestureStatus(delegate(), render_frame()->GetWebFrame(),
                                   " - in DidStartNavigation\n");
     }
@@ -60,7 +60,7 @@
 
   void ReadyToCommitNavigation(
       blink::WebDocumentLoader* document_loader) override {
-    if (test_runner()->shouldDumpFrameLoadCallbacks()) {
+    if (test_runner()->ShouldDumpFrameLoadCallbacks()) {
       WebFrameTestClient::PrintFrameDescription(delegate(),
                                                 render_frame()->GetWebFrame());
       delegate()->PrintMessage(" - ReadyToCommitNavigation\n");
@@ -68,7 +68,7 @@
   }
 
   void DidFailProvisionalLoad(const blink::WebURLError& error) override {
-    if (test_runner()->shouldDumpFrameLoadCallbacks()) {
+    if (test_runner()->ShouldDumpFrameLoadCallbacks()) {
       WebFrameTestClient::PrintFrameDescription(delegate(),
                                                 render_frame()->GetWebFrame());
       delegate()->PrintMessage(" - didFailProvisionalLoadWithError\n");
@@ -77,7 +77,7 @@
 
   void DidCommitProvisionalLoad(bool is_same_document_navigation,
                                 ui::PageTransition transition) override {
-    if (test_runner()->shouldDumpFrameLoadCallbacks()) {
+    if (test_runner()->ShouldDumpFrameLoadCallbacks()) {
       WebFrameTestClient::PrintFrameDescription(delegate(),
                                                 render_frame()->GetWebFrame());
       delegate()->PrintMessage(" - didCommitLoadForFrame\n");
@@ -85,7 +85,7 @@
   }
 
   void DidFinishDocumentLoad() override {
-    if (test_runner()->shouldDumpFrameLoadCallbacks()) {
+    if (test_runner()->ShouldDumpFrameLoadCallbacks()) {
       WebFrameTestClient::PrintFrameDescription(delegate(),
                                                 render_frame()->GetWebFrame());
       delegate()->PrintMessage(" - didFinishDocumentLoadForFrame\n");
@@ -93,7 +93,7 @@
   }
 
   void DidFinishLoad() override {
-    if (test_runner()->shouldDumpFrameLoadCallbacks()) {
+    if (test_runner()->ShouldDumpFrameLoadCallbacks()) {
       WebFrameTestClient::PrintFrameDescription(delegate(),
                                                 render_frame()->GetWebFrame());
       delegate()->PrintMessage(" - didFinishLoadForFrame\n");
@@ -101,7 +101,7 @@
   }
 
   void DidHandleOnloadEvents() override {
-    if (test_runner()->shouldDumpFrameLoadCallbacks()) {
+    if (test_runner()->ShouldDumpFrameLoadCallbacks()) {
       WebFrameTestClient::PrintFrameDescription(delegate(),
                                                 render_frame()->GetWebFrame());
       delegate()->PrintMessage(" - didHandleOnloadEventsForFrame\n");
diff --git a/content/shell/test_runner/web_test_delegate.h b/content/shell/test_runner/web_test_delegate.h
index e9763440..5b41ade 100644
--- a/content/shell/test_runner/web_test_delegate.h
+++ b/content/shell/test_runner/web_test_delegate.h
@@ -104,6 +104,8 @@
   virtual void EnableAutoResizeMode(const blink::WebSize& min_size,
                                     const blink::WebSize& max_size) = 0;
   virtual void DisableAutoResizeMode(const blink::WebSize& new_size) = 0;
+  // Resets auto resize mode off in between tests, without requiring a size.
+  virtual void ResetAutoResizeMode() = 0;
 
   virtual void NavigateSecondaryWindow(const GURL& url) = 0;
   virtual void InspectSecondaryWindow() = 0;
diff --git a/content/shell/test_runner/web_view_test_proxy.cc b/content/shell/test_runner/web_view_test_proxy.cc
index 8b291bf..1a376b9 100644
--- a/content/shell/test_runner/web_view_test_proxy.cc
+++ b/content/shell/test_runner/web_view_test_proxy.cc
@@ -39,16 +39,16 @@
     blink::WebSandboxFlags sandbox_flags,
     const blink::FeaturePolicy::FeatureState& opener_feature_state,
     const blink::SessionStorageNamespaceId& session_storage_namespace_id) {
-  if (GetTestRunner()->shouldDumpNavigationPolicy()) {
+  if (GetTestRunner()->ShouldDumpNavigationPolicy()) {
     delegate()->PrintMessage("Default policy for createView for '" +
                              URLDescription(request.Url()) + "' is '" +
                              WebNavigationPolicyToString(policy) + "'\n");
   }
 
-  if (!GetTestRunner()->canOpenWindows())
+  if (!GetTestRunner()->CanOpenWindows())
     return nullptr;
 
-  if (GetTestRunner()->shouldDumpCreateView()) {
+  if (GetTestRunner()->ShouldDumpCreateView()) {
     delegate()->PrintMessage(std::string("createView(") +
                              URLDescription(request.Url()) + ")\n");
   }
@@ -79,7 +79,7 @@
   blink::WebScreenInfo info = RenderViewImpl::GetScreenInfo();
 
   MockScreenOrientationClient* mock_client =
-      GetTestRunner()->getMockScreenOrientationClient();
+      GetTestRunner()->GetMockScreenOrientationClient();
 
   if (!mock_client->IsDisabled()) {
     // Override screen orientation information with mock data.
diff --git a/content/shell/test_runner/web_widget_test_proxy.cc b/content/shell/test_runner/web_widget_test_proxy.cc
index 45a371d..7e5acf22 100644
--- a/content/shell/test_runner/web_widget_test_proxy.cc
+++ b/content/shell/test_runner/web_widget_test_proxy.cc
@@ -104,7 +104,7 @@
 void WebWidgetTestProxy::SetToolTipText(const blink::WebString& text,
                                         blink::WebTextDirection hint) {
   RenderWidget::SetToolTipText(text, hint);
-  GetTestRunner()->setToolTipText(text);
+  GetTestRunner()->SetToolTipText(text);
 }
 
 void WebWidgetTestProxy::StartDragging(network::mojom::ReferrerPolicy policy,
@@ -112,7 +112,7 @@
                                        blink::WebDragOperationsMask mask,
                                        const SkBitmap& drag_image,
                                        const gfx::Point& image_offset) {
-  GetTestRunner()->setDragImage(drag_image);
+  GetTestRunner()->SetDragImage(drag_image);
 
   // When running a test, we need to fake a drag drop operation otherwise
   // Windows waits for real mouse events to know when the drag is over.
diff --git a/content/test/gpu/gpu_tests/pixel_test_pages.py b/content/test/gpu/gpu_tests/pixel_test_pages.py
index e83c176..fbbbdb8 100644
--- a/content/test/gpu/gpu_tests/pixel_test_pages.py
+++ b/content/test/gpu/gpu_tests/pixel_test_pages.py
@@ -1169,6 +1169,7 @@
       '--disable-features=D3D11VideoDecoder']
 
     tolerance_dc = 5
+    tolerance_dc_vp9 = 15
 
     return [
       PixelTestPage(
@@ -1412,7 +1413,7 @@
         test_rect=[0, 0, 240, 135],
         revision=0, # Golden image revision is not used
         browser_args=browser_args,
-        tolerance=tolerance_dc,
+        tolerance=tolerance_dc_vp9,
         expected_colors=_FOUR_COLOR_VIDEO_240x135_EXPECTED_COLORS),
 
       PixelTestPage(
@@ -1421,7 +1422,7 @@
         browser_args=browser_args_DXVA,
         test_rect=[0, 0, 240, 135],
         revision=0, # Golden image revision is not used
-        tolerance=tolerance_dc,
+        tolerance=tolerance_dc_vp9,
         expected_colors=_FOUR_COLOR_VIDEO_240x135_EXPECTED_COLORS),
 
       PixelTestPage(
@@ -1431,7 +1432,7 @@
         revision=0, # Golden image revision is not used
         browser_args=browser_args,
         other_args={'zero_copy': True},
-        tolerance=tolerance_dc,
+        tolerance=tolerance_dc_vp9,
         expected_colors=[
           {
             'comment': 'top left video, yellow',
@@ -1466,7 +1467,7 @@
         revision=0, # Golden image revision is not used
         browser_args=browser_args_YUY2,
         other_args={'expect_yuy2': True},
-        tolerance=tolerance_dc,
+        tolerance=tolerance_dc_vp9,
         expected_colors=_FOUR_COLOR_VIDEO_240x135_EXPECTED_COLORS),
 
       PixelTestPage(
diff --git a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
index 03d6c98b..fbb084d 100644
--- a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
@@ -1,4 +1,4 @@
-# tags: [ android linux lion mac mountainlion win win7 win8 ]
+# tags: [ android linux lion mac mountainlion win win7 win8 win10]
 # tags: [ debug ]
 # tags: [ amd-0x6779 nvidia qualcomm-adreno-(tm)-418 qualcomm-adreno-(tm)-420 ]
 # tags: [ asan no-asan ]
@@ -13,6 +13,9 @@
 # Win8 Release and Debug NVIDIA bots.
 crbug.com/524808 [ win8 nvidia ] ContextLost_WebGLContextLostFromSelectElement [ Skip ]
 
+# Win10 NVIDIA
+crbug.com/965268 [ win10 nvidia ] ContextLost_WebGLBlockedAfterJSNavigation [ RetryOnFailure ]
+
 # Flakily timing out on Win x64 Debug bot. Unfortunately we can't identify this
 # separately from the 32-bit bots. Also unfortunately, the flaky retry mechanism
 # doesn't work well in this harness if the test times out. Skip it on this
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
index 13f972e..12b45126 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -509,6 +509,7 @@
 crbug.com/611945 [ qualcomm-adreno-(tm)-420 android ] conformance/glsl/bugs/sampler-struct-function-arg.html [ Failure ]
 crbug.com/611945 [ qualcomm-adreno-(tm)-430 android ] conformance/glsl/bugs/sampler-struct-function-arg.html [ Failure ]
 crbug.com/951628 [ android qualcomm-adreno-(tm)-420 no-passthrough ] conformance/rendering/blending.html [ Failure ]
+crbug.com/1002997 [ android qualcomm-adreno-(tm)-430 no-passthrough ] conformance/rendering/blending.html [ Failure ]
 
 # This test is skipped because running it causes a future test to fail.
 # The list of tests which may be that future test is very long. It is
diff --git a/content/test/gpu/gpu_tests/test_expectations_unittest.py b/content/test/gpu/gpu_tests/test_expectations_unittest.py
index a71103aa..e8fa1e1 100644
--- a/content/test/gpu/gpu_tests/test_expectations_unittest.py
+++ b/content/test/gpu/gpu_tests/test_expectations_unittest.py
@@ -28,7 +28,6 @@
 WIN_CONDITIONS = ['xp', 'vista', 'win7', 'win8', 'win10']
 MAC_CONDITIONS = ['leopard', 'snowleopard', 'lion', 'mountainlion',
                   'mavericks', 'yosemite', 'sierra', 'highsierra', 'mojave']
-# These aren't expanded out into "lollipop", "marshmallow", etc.
 ANDROID_CONDITIONS = ['android-lollipop', 'android-marshmallow',
                       'anroid-nougat', 'android-oreo', 'android-pie',
                       'android-10', 'android-kitkat']
@@ -203,6 +202,25 @@
                 os.path.basename(f.name))
     assert not errors, errors
 
+  def testExpectationsFilesCanBeParsed(self):
+    webgl_conformance_test_class = (
+        webgl_conformance_integration_test.WebGLConformanceIntegrationTest)
+    for test_case in _FindTestCases():
+      if 'gpu_tests.gpu_integration_test_unittest' not in test_case.__module__:
+        for webgl_version in xrange(
+            1, 2 + (test_case == webgl_conformance_test_class)):
+          _ = list(
+              test_case.GenerateGpuTests(
+                  gpu_helper.GetMockArgs(
+                      webgl_version=('%d.0.0' % webgl_version))))
+          if test_case.ExpectationsFiles():
+            with open(test_case.ExpectationsFiles()[0]) as f:
+              test_expectations = expectations_parser.TestExpectations()
+              ret, err = test_expectations.parse_tagged_list(f.read(), f.name)
+              assert not ret, (
+                  'There was an error parsing %s, the error is:\n\t%s' %
+                  (os.path.basename(f.name), err))
+
   def testWebglTestPathsExist(self):
     webgl_test_class = (
         webgl_conformance_integration_test.WebGLConformanceIntegrationTest)
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc
index f684882..6251bd5 100644
--- a/content/test/test_render_frame_host.cc
+++ b/content/test/test_render_frame_host.cc
@@ -525,7 +525,7 @@
 TestRenderFrameHost::CreateWebBluetoothServiceForTesting() {
   WebBluetoothServiceImpl* service =
       RenderFrameHostImpl::CreateWebBluetoothService(
-          blink::mojom::WebBluetoothServiceRequest());
+          dummy_web_bluetooth_service_remote_.InitWithNewPipeAndPassReceiver());
   return service;
 }
 
diff --git a/content/test/test_render_frame_host.h b/content/test/test_render_frame_host.h
index 2b39c895..b327b95 100644
--- a/content/test/test_render_frame_host.h
+++ b/content/test/test_render_frame_host.h
@@ -22,6 +22,8 @@
 #include "content/test/test_render_view_host.h"
 #include "content/test/test_render_widget_host.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
 #include "ui/base/page_transition_types.h"
 
 namespace net {
@@ -287,6 +289,9 @@
            mojom::NavigationClient::CommitFailedNavigationCallback>
       navigation_client_commit_failed_callback_;
 
+  mojo::PendingRemote<blink::mojom::WebBluetoothService>
+      dummy_web_bluetooth_service_remote_;
+
   DISALLOW_COPY_AND_ASSIGN(TestRenderFrameHost);
 };
 
diff --git a/content/test/web_test_support.cc b/content/test/web_test_support.cc
index ccbd88b..e58baa2 100644
--- a/content/test/web_test_support.cc
+++ b/content/test/web_test_support.cc
@@ -93,13 +93,15 @@
 std::unique_ptr<RenderWidget> CreateRenderWidgetForFrame(
     int32_t routing_id,
     CompositorDependencies* compositor_deps,
+    PageProperties* page_properties,
     const ScreenInfo& screen_info,
     blink::WebDisplayMode display_mode,
     bool swapped_out,
     bool never_visible,
     mojo::PendingReceiver<mojom::Widget> widget_receiver) {
   return std::make_unique<test_runner::WebWidgetTestProxy>(
-      routing_id, compositor_deps, screen_info, display_mode, swapped_out,
+      routing_id, compositor_deps, page_properties, screen_info, display_mode,
+      swapped_out,
       /*hidden=*/true, never_visible, std::move(widget_receiver));
 }
 
diff --git a/device/bluetooth/bluetooth_adapter_factory.h b/device/bluetooth/bluetooth_adapter_factory.h
index d33b22a..e80a0d1 100644
--- a/device/bluetooth/bluetooth_adapter_factory.h
+++ b/device/bluetooth/bluetooth_adapter_factory.h
@@ -86,7 +86,7 @@
   static bool HasSharedInstanceForTesting();
 
 #if defined(OS_CHROMEOS)
-  // Sets the BleScanParserPtr callback used in Get*() below.
+  // Sets the mojo::Remote<BleScanParser> callback used in Get*() below.
   static void SetBleScanParserCallback(BleScanParserCallback callback);
   // Returns a reference to a parser for BLE advertisement packets.
   // This will be an empty callback until something calls Set*() above.
diff --git a/extensions/browser/api/declarative/rules_registry.cc b/extensions/browser/api/declarative/rules_registry.cc
index ab59b6b..30b767c 100644
--- a/extensions/browser/api/declarative/rules_registry.cc
+++ b/extensions/browser/api/declarative/rules_registry.cc
@@ -42,7 +42,7 @@
 base::Value RulesToValue(const std::vector<const api::events::Rule*>& rules) {
   base::Value value(base::Value::Type::LIST);
   for (const auto* rule : rules)
-    value.GetList().push_back(std::move(*rule->ToValue()));
+    value.Append(std::move(*rule->ToValue()));
   return value;
 }
 
diff --git a/extensions/browser/api/declarative_net_request/filter_list_converter/converter.cc b/extensions/browser/api/declarative_net_request/filter_list_converter/converter.cc
index cae7606..e00e034 100644
--- a/extensions/browser/api/declarative_net_request/filter_list_converter/converter.cc
+++ b/extensions/browser/api/declarative_net_request/filter_list_converter/converter.cc
@@ -241,7 +241,7 @@
 
     for (const proto::DomainListItem& item : input_rule_.domains()) {
       if (item.exclude() == exclude_value)
-        domains.GetList().emplace_back(item.domain());
+        domains.Append(item.domain());
     }
 
     // Omit empty domain list.
@@ -344,7 +344,7 @@
           break;
       }
 
-      resource_types.GetList().emplace_back(dnr_api::ToString(resource_type));
+      resource_types.Append(dnr_api::ToString(resource_type));
     }
 
     CHECK(json_rule_.SetPath({kRuleConditionKey, kResourceTypesKey},
@@ -449,7 +449,7 @@
 
     CHECK(error.empty());
     CHECK(json_rule_value.is_dict());
-    output_rules_list_.GetList().push_back(std::move(json_rule_value));
+    output_rules_list_.Append(std::move(json_rule_value));
     ++rule_id_;
     return true;
   }
diff --git a/extensions/browser/api/declarative_webrequest/webrequest_condition_attribute_unittest.cc b/extensions/browser/api/declarative_webrequest/webrequest_condition_attribute_unittest.cc
index f69e81d..56cae27 100644
--- a/extensions/browser/api/declarative_webrequest/webrequest_condition_attribute_unittest.cc
+++ b/extensions/browser/api/declarative_webrequest/webrequest_condition_attribute_unittest.cc
@@ -336,7 +336,7 @@
           break;
         }
         case base::Value::Type::LIST:  // Just append to the list.
-          entry->GetList().emplace_back(*value);
+          entry->Append(*value);
           break;
         default:
           NOTREACHED();  // We never put other Values here.
diff --git a/extensions/browser/api/storage/storage_frontend.cc b/extensions/browser/api/storage/storage_frontend.cc
index 229787d..57918cc 100644
--- a/extensions/browser/api/storage/storage_frontend.cc
+++ b/extensions/browser/api/storage/storage_frontend.cc
@@ -91,7 +91,7 @@
     // Event for StorageArea.
     {
       auto args = std::make_unique<base::ListValue>();
-      args->GetList().push_back(changes->Clone());
+      args->Append(changes->Clone());
       auto event = std::make_unique<Event>(
           NamespaceToEventHistogram(settings_namespace),
           base::StringPrintf("storage.%s.onChanged", namespace_string.c_str()),
diff --git a/extensions/browser/api/web_request/upload_data_presenter.cc b/extensions/browser/api/web_request/upload_data_presenter.cc
index 022abc0..a4b28fb 100644
--- a/extensions/browser/api/web_request/upload_data_presenter.cc
+++ b/extensions/browser/api/web_request/upload_data_presenter.cc
@@ -114,7 +114,7 @@
   FormDataParser::Result result;
   while (parser_->GetNextNameValue(&result)) {
     base::Value* list = GetOrCreateList(dictionary_.get(), result.name());
-    list->GetList().emplace_back(result.take_value());
+    list->Append(result.take_value());
   }
 }
 
diff --git a/extensions/browser/computed_hashes.cc b/extensions/browser/computed_hashes.cc
index 263eaa6..1533306b 100644
--- a/extensions/browser/computed_hashes.cc
+++ b/extensions/browser/computed_hashes.cc
@@ -159,7 +159,7 @@
   for (const auto& hash : hashes) {
     std::string encoded;
     base::Base64Encode(hash, &encoded);
-    block_hashes->GetList().emplace_back(std::move(encoded));
+    block_hashes->Append(std::move(encoded));
   }
 
   auto dict = std::make_unique<base::DictionaryValue>();
diff --git a/extensions/common/extension_l10n_util_unittest.cc b/extensions/common/extension_l10n_util_unittest.cc
index 7262332..22b63f5f 100644
--- a/extensions/common/extension_l10n_util_unittest.cc
+++ b/extensions/common/extension_l10n_util_unittest.cc
@@ -439,7 +439,7 @@
   base::DictionaryValue handler;
   handler.SetString(keys::kActionDefaultTitle, "__MSG_file_handler_title__");
   auto handlers = std::make_unique<base::ListValue>();
-  handlers->GetList().push_back(std::move(handler));
+  handlers->Append(std::move(handler));
   manifest.Set(keys::kFileBrowserHandlers, std::move(handlers));
 
   std::string error;
diff --git a/extensions/common/manifest_handlers/oauth2_manifest_unittest.cc b/extensions/common/manifest_handlers/oauth2_manifest_unittest.cc
index 81f9d42..b57bf54 100644
--- a/extensions/common/manifest_handlers/oauth2_manifest_unittest.cc
+++ b/extensions/common/manifest_handlers/oauth2_manifest_unittest.cc
@@ -106,8 +106,8 @@
   base_manifest.SetPath(TokenizeDictionaryPath(keys::kOAuth2ClientId),
                         base::Value("client1"));
   base::Value scopes(base::Value::Type::LIST);
-  scopes.GetList().push_back(base::Value("scope1"));
-  scopes.GetList().push_back(base::Value("scope2"));
+  scopes.Append(base::Value("scope1"));
+  scopes.Append(base::Value("scope2"));
   base_manifest.SetPath(TokenizeDictionaryPath(keys::kOAuth2Scopes),
                         std::move(scopes));
 
diff --git a/extensions/common/value_builder.h b/extensions/common/value_builder.h
index a75f0d5..1e5c084 100644
--- a/extensions/common/value_builder.h
+++ b/extensions/common/value_builder.h
@@ -81,14 +81,14 @@
 
   template <typename T>
   ListBuilder& Append(T in_value) {
-    list_->GetList().emplace_back(in_value);
+    list_->Append(in_value);
     return *this;
   }
 
   // See note on DictionaryBuilder::Set().
   template <typename T>
   ListBuilder& Append(std::unique_ptr<T> in_value) {
-    list_->GetList().push_back(std::move(*in_value));
+    list_->Append(std::move(*in_value));
     return *this;
   }
 
diff --git a/fuchsia/base/BUILD.gn b/fuchsia/base/BUILD.gn
index e8ba2b60..4a024db7 100644
--- a/fuchsia/base/BUILD.gn
+++ b/fuchsia/base/BUILD.gn
@@ -73,6 +73,8 @@
     "test_devtools_list_fetcher.h",
     "test_navigation_listener.cc",
     "test_navigation_listener.h",
+    "url_request_rewrite_test_util.cc",
+    "url_request_rewrite_test_util.h",
   ]
   public_deps = [
     ":base",
diff --git a/fuchsia/base/url_request_rewrite_test_util.cc b/fuchsia/base/url_request_rewrite_test_util.cc
new file mode 100644
index 0000000..6f2eac0c
--- /dev/null
+++ b/fuchsia/base/url_request_rewrite_test_util.cc
@@ -0,0 +1,67 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "fuchsia/base/url_request_rewrite_test_util.h"
+
+#include "fuchsia/base/string_util.h"
+
+namespace cr_fuchsia {
+
+fuchsia::web::UrlRequestRewrite CreateRewriteAddHeaders(
+    base::StringPiece header_name,
+    base::StringPiece header_value) {
+  fuchsia::net::http::Header header;
+  header.name = cr_fuchsia::StringToBytes(header_name);
+  header.value = cr_fuchsia::StringToBytes(header_value);
+
+  std::vector<fuchsia::net::http::Header> response_headers;
+  response_headers.push_back(std::move(header));
+
+  fuchsia::web::UrlRequestRewriteAddHeaders add_headers;
+  add_headers.set_headers(std::move(response_headers));
+  fuchsia::web::UrlRequestRewrite rewrite;
+  rewrite.set_add_headers(std::move(add_headers));
+
+  return rewrite;
+}
+
+fuchsia::web::UrlRequestRewrite CreateRewriteRemoveHeader(
+    base::Optional<base::StringPiece> query_pattern,
+    base::StringPiece header_name) {
+  fuchsia::web::UrlRequestRewriteRemoveHeader remove_header;
+  if (query_pattern)
+    remove_header.set_query_pattern(query_pattern.value().as_string());
+  remove_header.set_header_name(cr_fuchsia::StringToBytes(header_name));
+  fuchsia::web::UrlRequestRewrite rewrite;
+  rewrite.set_remove_header(std::move(remove_header));
+
+  return rewrite;
+}
+
+fuchsia::web::UrlRequestRewrite CreateRewriteSubstituteQueryPattern(
+    base::StringPiece pattern,
+    base::StringPiece substitution) {
+  fuchsia::web::UrlRequestRewriteSubstituteQueryPattern
+      substitute_query_pattern;
+  substitute_query_pattern.set_pattern(pattern.as_string());
+  substitute_query_pattern.set_substitution(substitution.as_string());
+  fuchsia::web::UrlRequestRewrite rewrite;
+  rewrite.set_substitute_query_pattern(std::move(substitute_query_pattern));
+
+  return rewrite;
+}
+
+fuchsia::web::UrlRequestRewrite CreateRewriteReplaceUrl(
+    base::StringPiece url_ends_with,
+    base::StringPiece new_url) {
+  fuchsia::web::UrlRequestRewriteReplaceUrl replace_url;
+  replace_url.set_url_ends_with(url_ends_with.as_string());
+  replace_url.set_new_url(new_url.as_string());
+  fuchsia::web::UrlRequestRewrite rewrite;
+  rewrite.set_replace_url(std::move(replace_url));
+
+  return rewrite;
+}
+
+}  // namespace cr_fuchsia
diff --git a/fuchsia/base/url_request_rewrite_test_util.h b/fuchsia/base/url_request_rewrite_test_util.h
new file mode 100644
index 0000000..00e08f8
--- /dev/null
+++ b/fuchsia/base/url_request_rewrite_test_util.h
@@ -0,0 +1,35 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FUCHSIA_BASE_URL_REQUEST_REWRITE_TEST_UTIL_H_
+#define FUCHSIA_BASE_URL_REQUEST_REWRITE_TEST_UTIL_H_
+
+#include <fuchsia/web/cpp/fidl.h>
+
+#include "base/optional.h"
+#include "base/strings/string_piece.h"
+
+namespace cr_fuchsia {
+
+// Utility functions to create a fuchsia.web.UrlRequestRewrite in one line.
+
+fuchsia::web::UrlRequestRewrite CreateRewriteAddHeaders(
+    base::StringPiece header_name,
+    base::StringPiece header_value);
+
+fuchsia::web::UrlRequestRewrite CreateRewriteRemoveHeader(
+    base::Optional<base::StringPiece> query_pattern,
+    base::StringPiece header_name);
+
+fuchsia::web::UrlRequestRewrite CreateRewriteSubstituteQueryPattern(
+    base::StringPiece pattern,
+    base::StringPiece substitution);
+
+fuchsia::web::UrlRequestRewrite CreateRewriteReplaceUrl(
+    base::StringPiece url_ends_with,
+    base::StringPiece new_url);
+
+}  // namespace cr_fuchsia
+
+#endif  // FUCHSIA_BASE_URL_REQUEST_REWRITE_TEST_UTIL_H_
diff --git a/fuchsia/engine/BUILD.gn b/fuchsia/engine/BUILD.gn
index 6457eeb0..a33b60c 100644
--- a/fuchsia/engine/BUILD.gn
+++ b/fuchsia/engine/BUILD.gn
@@ -17,9 +17,11 @@
 mojom("mojom") {
   sources = [
     "on_load_script_injector.mojom",
+    "url_request_rewrite.mojom",
   ]
   public_deps = [
     "//mojo/public/mojom/base",
+    "//services/network/public/mojom",
   ]
   visibility = [ ":*" ]
 }
@@ -127,6 +129,8 @@
     "browser/frame_impl.h",
     "browser/navigation_controller_impl.cc",
     "browser/navigation_controller_impl.h",
+    "browser/url_request_rewrite_rules_manager.cc",
+    "browser/url_request_rewrite_rules_manager.h",
     "browser/web_engine_browser_context.cc",
     "browser/web_engine_browser_context.h",
     "browser/web_engine_browser_main.cc",
@@ -149,14 +153,22 @@
     "browser/web_engine_screen.h",
     "common.cc",
     "common.h",
+    "common/web_engine_url_loader_throttle.cc",
+    "common/web_engine_url_loader_throttle.h",
     "context_provider_impl.cc",
     "context_provider_impl.h",
     "context_provider_main.cc",
     "context_provider_main.h",
     "renderer/on_load_script_injector.cc",
     "renderer/on_load_script_injector.h",
+    "renderer/url_request_rules_receiver.cc",
+    "renderer/url_request_rules_receiver.h",
     "renderer/web_engine_content_renderer_client.cc",
     "renderer/web_engine_content_renderer_client.h",
+    "renderer/web_engine_url_loader_throttle_provider.cc",
+    "renderer/web_engine_url_loader_throttle_provider.h",
+    "url_request_rewrite_type_converters.cc",
+    "url_request_rewrite_type_converters.h",
     "web_engine_content_client.cc",
     "web_engine_content_client.h",
     "web_engine_export.h",
@@ -258,12 +270,14 @@
     "browser/accessibility_bridge_unittest.cc",
     "browser/cookie_manager_impl_unittest.cc",
     "browser/frame_impl_unittest.cc",
+    "browser/url_request_rewrite_rules_manager_unittest.cc",
     "context_provider_impl_unittest.cc",
     "fake_context.cc",
     "fake_context.h",
     "test/run_all_unittests.cc",
   ]
   deps = [
+    ":mojom",
     ":web_engine_core",
     "//base/test:test_support",
     "//fuchsia/base:test_support",
diff --git a/fuchsia/engine/DEPS b/fuchsia/engine/DEPS
index a1f6ab61..ef204be 100644
--- a/fuchsia/engine/DEPS
+++ b/fuchsia/engine/DEPS
@@ -3,6 +3,7 @@
   "+content/public/app",
   "+gpu/command_buffer/service",
   "+media/base",
+  "+mojo/public",
   "+services/service_manager",
   "+third_party/widevine/cdm/widevine_cdm_common.h",
   "+ui/base",
diff --git a/fuchsia/engine/OWNERS b/fuchsia/engine/OWNERS
index 08850f4..7daaf52 100644
--- a/fuchsia/engine/OWNERS
+++ b/fuchsia/engine/OWNERS
@@ -1,2 +1,4 @@
 per-file *.mojom=set noparent
 per-file *.mojom=file://ipc/SECURITY_OWNERS
+per-file *_type_converter*.*=set noparent
+per-file *_type_converter*.*=file://ipc/SECURITY_OWNERS
diff --git a/fuchsia/engine/browser/frame_impl.cc b/fuchsia/engine/browser/frame_impl.cc
index 7a87169..38af00d 100644
--- a/fuchsia/engine/browser/frame_impl.cc
+++ b/fuchsia/engine/browser/frame_impl.cc
@@ -184,6 +184,7 @@
       context_(context),
       navigation_controller_(web_contents_.get()),
       log_level_(kLogSeverityNone),
+      url_request_rewrite_rules_manager_(web_contents_.get()),
       binding_(this, std::move(frame_request)) {
   web_contents_->SetDelegate(this);
   Observe(web_contents_.get());
@@ -344,6 +345,12 @@
     case WindowOpenDisposition::NEW_BACKGROUND_TAB:
     case WindowOpenDisposition::NEW_POPUP:
     case WindowOpenDisposition::NEW_WINDOW: {
+      if (url_request_rewrite_rules_manager_.GetCachedRules()) {
+        // There is no support for URL request rules rewriting with popups.
+        *was_blocked = true;
+        return;
+      }
+
       PopupFrameCreationInfoUserData* popup_creation_info =
           reinterpret_cast<PopupFrameCreationInfoUserData*>(
               new_contents->GetUserData(kPopupCreationInfo));
@@ -620,6 +627,15 @@
       fit::bind_member(this, &FrameImpl::OnPopupListenerDisconnected));
 }
 
+void FrameImpl::SetUrlRequestRewriteRules(
+    std::vector<fuchsia::web::UrlRequestRewriteRule> rules,
+    SetUrlRequestRewriteRulesCallback callback) {
+  zx_status_t error = url_request_rewrite_rules_manager_.OnRulesUpdated(
+      std::move(rules), std::move(callback));
+  if (error != ZX_OK)
+    binding_.Close(error);
+}
+
 void FrameImpl::CloseContents(content::WebContents* source) {
   DCHECK_EQ(source, web_contents_.get());
   context_->DestroyFrame(this);
diff --git a/fuchsia/engine/browser/frame_impl.h b/fuchsia/engine/browser/frame_impl.h
index dbd85f6..d905a12c 100644
--- a/fuchsia/engine/browser/frame_impl.h
+++ b/fuchsia/engine/browser/frame_impl.h
@@ -8,6 +8,7 @@
 #include <fuchsia/web/cpp/fidl.h>
 #include <lib/fidl/cpp/binding_set.h>
 #include <lib/zx/channel.h>
+
 #include <list>
 #include <map>
 #include <memory>
@@ -21,6 +22,7 @@
 #include "content/public/browser/web_contents_observer.h"
 #include "fuchsia/engine/browser/discarding_event_filter.h"
 #include "fuchsia/engine/browser/navigation_controller_impl.h"
+#include "fuchsia/engine/browser/url_request_rewrite_rules_manager.h"
 #include "fuchsia/engine/on_load_script_injector.mojom.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/wm/core/focus_controller.h"
@@ -126,6 +128,9 @@
   void SetPopupFrameCreationListener(
       fidl::InterfaceHandle<fuchsia::web::PopupFrameCreationListener> listener)
       override;
+  void SetUrlRequestRewriteRules(
+      std::vector<fuchsia::web::UrlRequestRewriteRule> rules,
+      SetUrlRequestRewriteRulesCallback callback) override;
 
   // content::WebContentsDelegate implementation.
   void CloseContents(content::WebContents* source) override;
@@ -177,6 +182,7 @@
   std::map<uint64_t, OriginScopedScript> before_load_scripts_;
   std::vector<uint64_t> before_load_scripts_order_;
   base::RepeatingCallback<void(base::StringPiece)> console_log_message_hook_;
+  UrlRequestRewriteRulesManager url_request_rewrite_rules_manager_;
 
   // Used for receiving and dispatching popup created by this Frame.
   fuchsia::web::PopupFrameCreationListenerPtr popup_listener_;
@@ -188,5 +194,4 @@
   DISALLOW_COPY_AND_ASSIGN(FrameImpl);
 };
 
-
 #endif  // FUCHSIA_ENGINE_BROWSER_FRAME_IMPL_H_
diff --git a/fuchsia/engine/browser/frame_impl_browsertest.cc b/fuchsia/engine/browser/frame_impl_browsertest.cc
index 50bd253..90db309 100644
--- a/fuchsia/engine/browser/frame_impl_browsertest.cc
+++ b/fuchsia/engine/browser/frame_impl_browsertest.cc
@@ -6,6 +6,7 @@
 #include <lib/ui/scenic/cpp/view_token_pair.h>
 
 #include "base/bind.h"
+#include "base/containers/span.h"
 #include "base/fuchsia/fuchsia_logging.h"
 #include "base/macros.h"
 #include "base/strings/stringprintf.h"
@@ -21,6 +22,7 @@
 #include "fuchsia/base/result_receiver.h"
 #include "fuchsia/base/string_util.h"
 #include "fuchsia/base/test_navigation_listener.h"
+#include "fuchsia/base/url_request_rewrite_test_util.h"
 #include "fuchsia/engine/browser/frame_impl.h"
 #include "fuchsia/engine/common.h"
 #include "fuchsia/engine/test/web_engine_browser_test.h"
@@ -50,6 +52,8 @@
 const char kPage1Path[] = "/title1.html";
 const char kPage2Path[] = "/title2.html";
 const char kPage3Path[] = "/websql.html";
+const char kPage4Path[] = "/image.html";
+const char kPage4ImgPath[] = "/img.png";
 const char kDynamicTitlePath[] = "/dynamic_title.html";
 const char kPopupPath[] = "/popup_parent.html";
 const char kPopupRedirectPath[] = "/popup_child.html";
@@ -1620,6 +1624,286 @@
               testing::Contains(testing::Key("X-2ExtraHeaders")));
 }
 
+// Tests the URLRequestRewrite API properly adds headers on every requests.
+IN_PROC_BROWSER_TEST_F(RequestMonitoringFrameImplBrowserTest,
+                       UrlRequestRewriteAddHeaders) {
+  fuchsia::web::FramePtr frame = CreateFrame();
+
+  std::vector<fuchsia::web::UrlRequestRewrite> rewrites;
+  rewrites.push_back(cr_fuchsia::CreateRewriteAddHeaders("Test", "Value"));
+  fuchsia::web::UrlRequestRewriteRule rule;
+  rule.set_rewrites(std::move(rewrites));
+  std::vector<fuchsia::web::UrlRequestRewriteRule> rules;
+  rules.push_back(std::move(rule));
+  frame->SetUrlRequestRewriteRules(std::move(rules), []() {});
+
+  fuchsia::web::NavigationControllerPtr controller;
+  frame->GetNavigationController(controller.NewRequest());
+
+  // Navigate, we should get the additional header on the main request and the
+  // image request.
+  const GURL page_url(embedded_test_server()->GetURL(kPage4Path));
+  const GURL img_url(embedded_test_server()->GetURL(kPage4ImgPath));
+  EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
+      controller.get(), fuchsia::web::LoadUrlParams(), page_url.spec()));
+  navigation_listener_.RunUntilUrlEquals(page_url);
+
+  {
+    const auto iter = accumulated_requests_.find(page_url);
+    ASSERT_NE(iter, accumulated_requests_.end());
+    EXPECT_THAT(iter->second.headers, testing::Contains(testing::Key("Test")));
+  }
+  {
+    const auto iter = accumulated_requests_.find(img_url);
+    ASSERT_NE(iter, accumulated_requests_.end());
+    EXPECT_THAT(iter->second.headers, testing::Contains(testing::Key("Test")));
+  }
+}
+
+// Tests the URLRequestRewrite API properly removes headers on every requests.
+// Also tests that rewrites are applied properly in succession.
+IN_PROC_BROWSER_TEST_F(RequestMonitoringFrameImplBrowserTest,
+                       UrlRequestRewriteRemoveHeader) {
+  fuchsia::web::FramePtr frame = CreateFrame();
+
+  std::vector<fuchsia::web::UrlRequestRewrite> rewrites;
+  rewrites.push_back(cr_fuchsia::CreateRewriteAddHeaders("Test", "Value"));
+  rewrites.push_back(
+      cr_fuchsia::CreateRewriteRemoveHeader(base::nullopt, "Test"));
+  fuchsia::web::UrlRequestRewriteRule rule;
+  rule.set_rewrites(std::move(rewrites));
+  std::vector<fuchsia::web::UrlRequestRewriteRule> rules;
+  rules.push_back(std::move(rule));
+  frame->SetUrlRequestRewriteRules(std::move(rules), []() {});
+
+  fuchsia::web::NavigationControllerPtr controller;
+  frame->GetNavigationController(controller.NewRequest());
+
+  // Navigate, we should get no "Test" header.
+  const GURL page_url(embedded_test_server()->GetURL(kPage4Path));
+  const GURL img_url(embedded_test_server()->GetURL(kPage4ImgPath));
+  EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
+      controller.get(), fuchsia::web::LoadUrlParams(), page_url.spec()));
+  navigation_listener_.RunUntilUrlEquals(page_url);
+
+  {
+    const auto iter = accumulated_requests_.find(page_url);
+    ASSERT_NE(iter, accumulated_requests_.end());
+    EXPECT_THAT(iter->second.headers,
+                testing::Not(testing::Contains(testing::Key("Test"))));
+  }
+  {
+    const auto iter = accumulated_requests_.find(img_url);
+    ASSERT_NE(iter, accumulated_requests_.end());
+    EXPECT_THAT(iter->second.headers,
+                testing::Not(testing::Contains(testing::Key("Test"))));
+  }
+}
+
+// Tests the URLRequestRewrite API properly removes headers, based on the
+// presence of a string in the query.
+IN_PROC_BROWSER_TEST_F(RequestMonitoringFrameImplBrowserTest,
+                       UrlRequestRewriteRemoveHeaderWithQuery) {
+  fuchsia::web::FramePtr frame = CreateFrame();
+
+  const GURL page_url(embedded_test_server()->GetURL("/page?stuff=[pattern]"));
+
+  std::vector<fuchsia::web::UrlRequestRewrite> rewrites;
+  rewrites.push_back(cr_fuchsia::CreateRewriteAddHeaders("Test", "Value"));
+  rewrites.push_back(cr_fuchsia::CreateRewriteRemoveHeader(
+      base::make_optional("[pattern]"), "Test"));
+  fuchsia::web::UrlRequestRewriteRule rule;
+  rule.set_rewrites(std::move(rewrites));
+  std::vector<fuchsia::web::UrlRequestRewriteRule> rules;
+  rules.push_back(std::move(rule));
+  frame->SetUrlRequestRewriteRules(std::move(rules), []() {});
+
+  fuchsia::web::NavigationControllerPtr controller;
+  frame->GetNavigationController(controller.NewRequest());
+
+  // Navigate, we should get no "Test" header.
+  EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
+      controller.get(), fuchsia::web::LoadUrlParams(), page_url.spec()));
+  navigation_listener_.RunUntilUrlEquals(page_url);
+
+  const auto iter = accumulated_requests_.find(page_url);
+  ASSERT_NE(iter, accumulated_requests_.end());
+  EXPECT_THAT(iter->second.headers,
+              testing::Not(testing::Contains(testing::Key("Test"))));
+}
+
+// Tests the URLRequestRewrite API properly handles query substitution.
+IN_PROC_BROWSER_TEST_F(RequestMonitoringFrameImplBrowserTest,
+                       UrlRequestRewriteSubstituteQueryPattern) {
+  fuchsia::web::FramePtr frame = CreateFrame();
+
+  std::vector<fuchsia::web::UrlRequestRewrite> rewrites;
+  rewrites.push_back(cr_fuchsia::CreateRewriteSubstituteQueryPattern(
+      "[pattern]", "substitution"));
+  fuchsia::web::UrlRequestRewriteRule rule;
+  rule.set_rewrites(std::move(rewrites));
+  std::vector<fuchsia::web::UrlRequestRewriteRule> rules;
+  rules.push_back(std::move(rule));
+  frame->SetUrlRequestRewriteRules(std::move(rules), []() {});
+
+  fuchsia::web::NavigationControllerPtr controller;
+  frame->GetNavigationController(controller.NewRequest());
+
+  // Navigate, we should get to the URL with the modified request.
+  const GURL page_url(embedded_test_server()->GetURL("/page?[pattern]"));
+  const GURL final_url(embedded_test_server()->GetURL("/page?substitution"));
+  EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
+      controller.get(), fuchsia::web::LoadUrlParams(), page_url.spec()));
+  navigation_listener_.RunUntilUrlEquals(final_url);
+
+  EXPECT_THAT(accumulated_requests_,
+              testing::Contains(testing::Key(final_url)));
+}
+
+// Tests the URLRequestRewrite API properly handles URL replacement.
+IN_PROC_BROWSER_TEST_F(RequestMonitoringFrameImplBrowserTest,
+                       UrlRequestRewriteReplaceUrl) {
+  fuchsia::web::FramePtr frame = CreateFrame();
+
+  const GURL page_url(embedded_test_server()->GetURL(kPage1Path));
+  const GURL final_url(embedded_test_server()->GetURL(kPage2Path));
+
+  std::vector<fuchsia::web::UrlRequestRewrite> rewrites;
+  rewrites.push_back(
+      cr_fuchsia::CreateRewriteReplaceUrl(kPage1Path, final_url.spec()));
+  fuchsia::web::UrlRequestRewriteRule rule;
+  rule.set_rewrites(std::move(rewrites));
+  std::vector<fuchsia::web::UrlRequestRewriteRule> rules;
+  rules.push_back(std::move(rule));
+  frame->SetUrlRequestRewriteRules(std::move(rules), []() {});
+
+  fuchsia::web::NavigationControllerPtr controller;
+  frame->GetNavigationController(controller.NewRequest());
+
+  // Navigate, we should get to the replaced URL.
+  EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
+      controller.get(), fuchsia::web::LoadUrlParams(), page_url.spec()));
+  navigation_listener_.RunUntilUrlEquals(final_url);
+
+  EXPECT_THAT(accumulated_requests_,
+              testing::Contains(testing::Key(final_url)));
+}
+
+// Tests the URLRequestRewrite API properly handles URL replacement when the
+// original request URL contains a query and a fragment string.
+IN_PROC_BROWSER_TEST_F(RequestMonitoringFrameImplBrowserTest,
+                       UrlRequestRewriteReplaceUrlQueryRef) {
+  fuchsia::web::FramePtr frame = CreateFrame();
+
+  const GURL page_url(
+      embedded_test_server()->GetURL(std::string(kPage1Path) + "?query#ref"));
+  const GURL replacement_url(embedded_test_server()->GetURL(kPage2Path));
+  const GURL final_url_with_ref(
+      embedded_test_server()->GetURL(std::string(kPage2Path) + "?query#ref"));
+  const GURL final_url(
+      embedded_test_server()->GetURL(std::string(kPage2Path) + "?query"));
+
+  std::vector<fuchsia::web::UrlRequestRewrite> rewrites;
+  rewrites.push_back(
+      cr_fuchsia::CreateRewriteReplaceUrl(kPage1Path, replacement_url.spec()));
+  fuchsia::web::UrlRequestRewriteRule rule;
+  rule.set_rewrites(std::move(rewrites));
+  std::vector<fuchsia::web::UrlRequestRewriteRule> rules;
+  rules.push_back(std::move(rule));
+  frame->SetUrlRequestRewriteRules(std::move(rules), []() {});
+
+  fuchsia::web::NavigationControllerPtr controller;
+  frame->GetNavigationController(controller.NewRequest());
+
+  // Navigate, we should get to the replaced URL.
+  EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
+      controller.get(), fuchsia::web::LoadUrlParams(), page_url.spec()));
+  navigation_listener_.RunUntilUrlEquals(final_url_with_ref);
+
+  EXPECT_THAT(accumulated_requests_,
+              testing::Contains(testing::Key(final_url)));
+}
+
+// Tests the URLRequestRewrite API properly handles scheme and host filtering in
+// rules.
+IN_PROC_BROWSER_TEST_F(RequestMonitoringFrameImplBrowserTest,
+                       UrlRequestRewriteSchemeHostFilter) {
+  fuchsia::web::FramePtr frame = CreateFrame();
+
+  std::vector<fuchsia::web::UrlRequestRewrite> rewrites1;
+  rewrites1.push_back(cr_fuchsia::CreateRewriteAddHeaders("Test1", "Value"));
+  fuchsia::web::UrlRequestRewriteRule rule1;
+  rule1.set_rewrites(std::move(rewrites1));
+  rule1.set_hosts_filter({"127.0.0.1"});
+
+  std::vector<fuchsia::web::UrlRequestRewrite> rewrites2;
+  rewrites2.push_back(cr_fuchsia::CreateRewriteAddHeaders("Test2", "Value"));
+  fuchsia::web::UrlRequestRewriteRule rule2;
+  rule2.set_rewrites(std::move(rewrites2));
+  rule2.set_hosts_filter({"test.xyz"});
+
+  std::vector<fuchsia::web::UrlRequestRewrite> rewrites3;
+  rewrites3.push_back(cr_fuchsia::CreateRewriteAddHeaders("Test3", "Value"));
+  fuchsia::web::UrlRequestRewriteRule rule3;
+  rule3.set_rewrites(std::move(rewrites3));
+  rule3.set_schemes_filter({"http"});
+
+  std::vector<fuchsia::web::UrlRequestRewrite> rewrites4;
+  rewrites4.push_back(cr_fuchsia::CreateRewriteAddHeaders("Test4", "Value"));
+  fuchsia::web::UrlRequestRewriteRule rule4;
+  rule4.set_rewrites(std::move(rewrites4));
+  rule4.set_schemes_filter({"https"});
+
+  std::vector<fuchsia::web::UrlRequestRewriteRule> rules;
+  rules.push_back(std::move(rule1));
+  rules.push_back(std::move(rule2));
+  rules.push_back(std::move(rule3));
+  rules.push_back(std::move(rule4));
+
+  frame->SetUrlRequestRewriteRules(std::move(rules), []() {});
+
+  fuchsia::web::NavigationControllerPtr controller;
+  frame->GetNavigationController(controller.NewRequest());
+
+  // Navigate, we should get the "Test1" and "Test3" headers, but not "Test2"
+  // and "Test4".
+  const GURL page_url(embedded_test_server()->GetURL("/default"));
+  EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
+      controller.get(), fuchsia::web::LoadUrlParams(), page_url.spec()));
+  navigation_listener_.RunUntilUrlEquals(page_url);
+
+  const auto iter = accumulated_requests_.find(page_url);
+  ASSERT_NE(iter, accumulated_requests_.end());
+  EXPECT_THAT(iter->second.headers, testing::Contains(testing::Key("Test1")));
+  EXPECT_THAT(iter->second.headers, testing::Contains(testing::Key("Test3")));
+  EXPECT_THAT(iter->second.headers,
+              testing::Not(testing::Contains(testing::Key("Test2"))));
+  EXPECT_THAT(iter->second.headers,
+              testing::Not(testing::Contains(testing::Key("Test4"))));
+}
+
+// Tests the URLRequestRewrite API properly closes the Frame channel if the
+// rules are invalid.
+IN_PROC_BROWSER_TEST_F(RequestMonitoringFrameImplBrowserTest,
+                       UrlRequestRewriteInvalidRules) {
+  fuchsia::web::FramePtr frame = CreateFrame();
+  base::RunLoop run_loop;
+  frame.set_error_handler([&run_loop](zx_status_t status) {
+    EXPECT_EQ(status, ZX_ERR_INVALID_ARGS);
+    run_loop.Quit();
+  });
+
+  std::vector<fuchsia::web::UrlRequestRewrite> rewrites;
+  rewrites.push_back(cr_fuchsia::CreateRewriteAddHeaders("Te\nst1", "Value"));
+  fuchsia::web::UrlRequestRewriteRule rule;
+  rule.set_rewrites(std::move(rewrites));
+  std::vector<fuchsia::web::UrlRequestRewriteRule> rules;
+  rules.push_back(std::move(rule));
+
+  frame->SetUrlRequestRewriteRules(std::move(rules), []() {});
+  run_loop.Run();
+}
+
 class TestPopupListener : public fuchsia::web::PopupFrameCreationListener {
  public:
   TestPopupListener() = default;
diff --git a/fuchsia/engine/browser/url_request_rewrite_rules_manager.cc b/fuchsia/engine/browser/url_request_rewrite_rules_manager.cc
new file mode 100644
index 0000000..69e6e98
--- /dev/null
+++ b/fuchsia/engine/browser/url_request_rewrite_rules_manager.cc
@@ -0,0 +1,200 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "fuchsia/engine/browser/url_request_rewrite_rules_manager.h"
+
+#include "fuchsia/base/string_util.h"
+#include "fuchsia/engine/url_request_rewrite_type_converters.h"
+#include "net/http/http_util.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+
+namespace {
+
+using RoutingIdRewriterMap =
+    std::unordered_map<int, UrlRequestRewriteRulesManager*>;
+RoutingIdRewriterMap& GetRewriterMap() {
+  static base::NoDestructor<RoutingIdRewriterMap> rewriter_map;
+  return *rewriter_map;
+}
+
+bool ValidateAddHeaders(
+    const fuchsia::web::UrlRequestRewriteAddHeaders& add_headers) {
+  if (!add_headers.has_headers())
+    return false;
+  for (const auto& header : add_headers.headers()) {
+    base::StringPiece header_name = cr_fuchsia::BytesAsString(header.name);
+    base::StringPiece header_value = cr_fuchsia::BytesAsString(header.value);
+    if (!net::HttpUtil::IsValidHeaderName(header_name) ||
+        !net::HttpUtil::IsValidHeaderValue(header_value))
+      return false;
+  }
+  return true;
+}
+
+bool ValidateRemoveHeader(
+    const fuchsia::web::UrlRequestRewriteRemoveHeader& remove_header) {
+  if (!remove_header.has_header_name())
+    return false;
+  if (!net::HttpUtil::IsValidHeaderName(
+          cr_fuchsia::BytesAsString(remove_header.header_name())))
+    return false;
+  return true;
+}
+
+bool ValidateSubstituteQueryPattern(
+    const fuchsia::web::UrlRequestRewriteSubstituteQueryPattern&
+        substitute_query_pattern) {
+  if (!substitute_query_pattern.has_pattern() ||
+      !substitute_query_pattern.has_substitution())
+    return false;
+  return true;
+}
+
+bool ValidateReplaceUrl(
+    const fuchsia::web::UrlRequestRewriteReplaceUrl& replace_url) {
+  if (!replace_url.has_url_ends_with() || !replace_url.has_new_url())
+    return false;
+  if (!GURL("http://site.com/" + replace_url.url_ends_with()).is_valid())
+    return false;
+  if (!GURL(replace_url.new_url()).is_valid())
+    return false;
+  return true;
+}
+
+bool ValidateRewrite(const fuchsia::web::UrlRequestRewrite& rewrite) {
+  switch (rewrite.Which()) {
+    case fuchsia::web::UrlRequestRewrite::Tag::kAddHeaders:
+      return ValidateAddHeaders(rewrite.add_headers());
+    case fuchsia::web::UrlRequestRewrite::Tag::kRemoveHeader:
+      return ValidateRemoveHeader(rewrite.remove_header());
+    case fuchsia::web::UrlRequestRewrite::Tag::kSubstituteQueryPattern:
+      return ValidateSubstituteQueryPattern(rewrite.substitute_query_pattern());
+    case fuchsia::web::UrlRequestRewrite::Tag::kReplaceUrl:
+      return ValidateReplaceUrl(rewrite.replace_url());
+    default:
+      // This is to prevent build breakage when adding new rewrites to the FIDL
+      // definition. This can also happen if the client sends an empty rewrite,
+      // which is invalid.
+      return false;
+  }
+}
+
+bool ValidateRules(
+    const std::vector<fuchsia::web::UrlRequestRewriteRule>& rules) {
+  for (const auto& rule : rules) {
+    if (rule.has_hosts_filter() && rule.hosts_filter().empty())
+      return false;
+    if (rule.has_schemes_filter() && rule.schemes_filter().empty())
+      return false;
+    if (!rule.has_rewrites())
+      return false;
+    for (const auto& rewrite : rule.rewrites()) {
+      if (!ValidateRewrite(rewrite))
+        return false;
+    }
+  }
+  return true;
+}
+
+}  // namespace
+
+// static
+UrlRequestRewriteRulesManager*
+UrlRequestRewriteRulesManager::ForFrameTreeNodeId(int frame_tree_node_id) {
+  auto iter = GetRewriterMap().find(frame_tree_node_id);
+  if (iter == GetRewriterMap().end())
+    return nullptr;
+  return iter->second;
+}
+
+// static
+std::unique_ptr<UrlRequestRewriteRulesManager>
+UrlRequestRewriteRulesManager::CreateForTesting() {
+  return base::WrapUnique(new UrlRequestRewriteRulesManager());
+}
+
+UrlRequestRewriteRulesManager::UrlRequestRewriteRulesManager(
+    content::WebContents* web_contents)
+    : content::WebContentsObserver(web_contents) {}
+
+UrlRequestRewriteRulesManager::~UrlRequestRewriteRulesManager() = default;
+
+zx_status_t UrlRequestRewriteRulesManager::OnRulesUpdated(
+    std::vector<fuchsia::web::UrlRequestRewriteRule> rules,
+    fuchsia::web::Frame::SetUrlRequestRewriteRulesCallback callback) {
+  if (!ValidateRules(rules)) {
+    base::AutoLock auto_lock(lock_);
+    cached_rules_ = nullptr;
+    return ZX_ERR_INVALID_ARGS;
+  }
+
+  base::AutoLock auto_lock(lock_);
+  cached_rules_ =
+      base::MakeRefCounted<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>(
+          mojo::ConvertTo<std::vector<mojom::UrlRequestRewriteRulePtr>>(
+              std::move(rules)));
+
+  // Send the updated rules to the receivers.
+  for (const auto& receiver_pair : rules_receivers_per_frame_id_) {
+    receiver_pair.second->OnRulesUpdated(mojo::Clone(cached_rules_->data));
+  }
+
+  // TODO(crbug.com/976975): Only call the callback when there are pending
+  // throttles.
+  std::move(callback)();
+  return ZX_OK;
+}
+
+scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
+UrlRequestRewriteRulesManager::GetCachedRules() {
+  base::AutoLock auto_lock(lock_);
+  return cached_rules_;
+}
+
+UrlRequestRewriteRulesManager::UrlRequestRewriteRulesManager() {}
+
+void UrlRequestRewriteRulesManager::RenderFrameCreated(
+    content::RenderFrameHost* render_frame_host) {
+  int frame_tree_node_id = render_frame_host->GetFrameTreeNodeId();
+
+  if (rules_receivers_per_frame_id_.find(frame_tree_node_id) !=
+      rules_receivers_per_frame_id_.end()) {
+    // This happens on cross-process navigations. It is not necessary to refresh
+    // the global map in this case as RenderFrameDeleted will not have been
+    // called for this RenderFrameHost.
+    size_t deleted = rules_receivers_per_frame_id_.erase(frame_tree_node_id);
+    DCHECK(deleted == 1);
+  } else {
+    // Register this instance of UrlRequestRewriteRulesManager as the URL
+    // request rewriter handler for this RenderFrameHost ID.
+    auto iter =
+        GetRewriterMap().emplace(std::make_pair(frame_tree_node_id, this));
+    DCHECK(iter.second);
+  }
+
+  // Register the frame rules receiver.
+  mojom::UrlRequestRulesReceiverAssociatedPtr rules_receiver;
+  render_frame_host->GetRemoteAssociatedInterfaces()->GetInterface(
+      &rules_receiver);
+  auto iter = rules_receivers_per_frame_id_.emplace(frame_tree_node_id,
+                                                    std::move(rules_receiver));
+  DCHECK(iter.second);
+
+  base::AutoLock auto_lock(lock_);
+  if (cached_rules_) {
+    // Send an initial set of rules.
+    iter.first->second->OnRulesUpdated(mojo::Clone(cached_rules_->data));
+  }
+}
+
+void UrlRequestRewriteRulesManager::RenderFrameDeleted(
+    content::RenderFrameHost* render_frame_host) {
+  int frame_tree_node_id = render_frame_host->GetFrameTreeNodeId();
+
+  size_t deleted = GetRewriterMap().erase(frame_tree_node_id);
+  DCHECK(deleted == 1);
+
+  deleted = rules_receivers_per_frame_id_.erase(frame_tree_node_id);
+  DCHECK(deleted == 1);
+}
diff --git a/fuchsia/engine/browser/url_request_rewrite_rules_manager.h b/fuchsia/engine/browser/url_request_rewrite_rules_manager.h
new file mode 100644
index 0000000..8f2f05a
--- /dev/null
+++ b/fuchsia/engine/browser/url_request_rewrite_rules_manager.h
@@ -0,0 +1,65 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FUCHSIA_ENGINE_BROWSER_URL_REQUEST_REWRITE_RULES_MANAGER_H_
+#define FUCHSIA_ENGINE_BROWSER_URL_REQUEST_REWRITE_RULES_MANAGER_H_
+
+#include <fuchsia/web/cpp/fidl.h>
+
+#include "base/synchronization/lock.h"
+#include "content/public/browser/web_contents_binding_set.h"
+#include "fuchsia/engine/common/web_engine_url_loader_throttle.h"
+#include "fuchsia/engine/url_request_rewrite.mojom.h"
+#include "fuchsia/engine/web_engine_export.h"
+
+namespace content {
+class RenderFrameHost;
+class WebContents;
+}  // namespace content
+
+// Adapts the UrlRequestRewrite FIDL API to be sent to the renderers over the
+// over the UrlRequestRewrite Mojo API.
+class WEB_ENGINE_EXPORT UrlRequestRewriteRulesManager
+    : public content::WebContentsObserver,
+      public WebEngineURLLoaderThrottle::CachedRulesProvider {
+ public:
+  static UrlRequestRewriteRulesManager* ForFrameTreeNodeId(
+      int frame_tree_node_id);
+
+  static std::unique_ptr<UrlRequestRewriteRulesManager> CreateForTesting();
+
+  explicit UrlRequestRewriteRulesManager(content::WebContents* web_contents);
+  ~UrlRequestRewriteRulesManager() final;
+
+  // Signals |rules| have been updated. Actual implementation for
+  // fuchsia.web.Frame/SetUrlRequestRewriteRules.
+  // Return ZX_OK on success and an error code otherwise.
+  zx_status_t OnRulesUpdated(
+      std::vector<fuchsia::web::UrlRequestRewriteRule> rules,
+      fuchsia::web::Frame::SetUrlRequestRewriteRulesCallback callback);
+
+  // WebEngineURLLoaderThrottle::CachedRulesProvider implementation.
+  scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
+  GetCachedRules() override;
+
+ private:
+  // Test-only constructor.
+  explicit UrlRequestRewriteRulesManager();
+
+  // content::WebContentsObserver implementation.
+  void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override;
+  void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
+
+  base::Lock lock_;
+  scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
+      cached_rules_ GUARDED_BY(lock_);
+
+  // Map of frames rules receivers per FrameTreeNode ID.
+  std::map<int, mojom::UrlRequestRulesReceiverAssociatedPtr>
+      rules_receivers_per_frame_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(UrlRequestRewriteRulesManager);
+};
+
+#endif  // FUCHSIA_ENGINE_BROWSER_URL_REQUEST_REWRITE_RULES_MANAGER_H_
diff --git a/fuchsia/engine/browser/url_request_rewrite_rules_manager_unittest.cc b/fuchsia/engine/browser/url_request_rewrite_rules_manager_unittest.cc
new file mode 100644
index 0000000..952ec1335
--- /dev/null
+++ b/fuchsia/engine/browser/url_request_rewrite_rules_manager_unittest.cc
@@ -0,0 +1,231 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "fuchsia/engine/browser/url_request_rewrite_rules_manager.h"
+
+#include <lib/fidl/cpp/binding.h>
+
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "fuchsia/base/url_request_rewrite_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class UrlRequestRewriteRulesManagerTest : public testing::Test {
+ public:
+  UrlRequestRewriteRulesManagerTest()
+      : task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
+        url_request_rewrite_rules_manager_(
+            UrlRequestRewriteRulesManager::CreateForTesting()) {}
+  ~UrlRequestRewriteRulesManagerTest() override = default;
+
+ protected:
+  zx_status_t UpdateRulesFromRewrite(fuchsia::web::UrlRequestRewrite rewrite) {
+    std::vector<fuchsia::web::UrlRequestRewrite> rewrites;
+    rewrites.push_back(std::move(rewrite));
+
+    fuchsia::web::UrlRequestRewriteRule rule;
+    rule.set_rewrites(std::move(rewrites));
+
+    std::vector<fuchsia::web::UrlRequestRewriteRule> rules;
+    rules.push_back(std::move(rule));
+    return url_request_rewrite_rules_manager_->OnRulesUpdated(std::move(rules),
+                                                              []() {});
+  }
+
+  base::test::SingleThreadTaskEnvironment task_environment_;
+  std::unique_ptr<UrlRequestRewriteRulesManager>
+      url_request_rewrite_rules_manager_;
+
+  DISALLOW_COPY_AND_ASSIGN(UrlRequestRewriteRulesManagerTest);
+};
+
+// Tests AddHeaders rewrites are properly converted to their Mojo equivalent.
+TEST_F(UrlRequestRewriteRulesManagerTest, ConvertAddHeader) {
+  EXPECT_EQ(UpdateRulesFromRewrite(
+                cr_fuchsia::CreateRewriteAddHeaders("Test", "Value")),
+            ZX_OK);
+  scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
+      cached_rules = url_request_rewrite_rules_manager_->GetCachedRules();
+  ASSERT_EQ(cached_rules->data.size(), 1u);
+  ASSERT_FALSE(cached_rules->data[0]->hosts_filter);
+  ASSERT_FALSE(cached_rules->data[0]->schemes_filter);
+  ASSERT_EQ(cached_rules->data[0]->rewrites.size(), 1u);
+  ASSERT_TRUE(cached_rules->data[0]->rewrites[0]->is_add_headers());
+
+  const net::HttpRequestHeaders& headers =
+      cached_rules->data[0]->rewrites[0]->get_add_headers()->headers;
+  ASSERT_EQ(headers.GetHeaderVector().size(), 1u);
+
+  std::string value;
+  ASSERT_TRUE(headers.GetHeader("Test", &value));
+  ASSERT_EQ(value.compare("Value"), 0);
+}
+
+// Tests RemoveHeader rewrites are properly converted to their Mojo equivalent.
+TEST_F(UrlRequestRewriteRulesManagerTest, ConvertRemoveHeader) {
+  EXPECT_EQ(UpdateRulesFromRewrite(cr_fuchsia::CreateRewriteRemoveHeader(
+                base::make_optional("Test"), "Header")),
+            ZX_OK);
+  scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
+      cached_rules = url_request_rewrite_rules_manager_->GetCachedRules();
+  ASSERT_EQ(cached_rules->data.size(), 1u);
+  ASSERT_FALSE(cached_rules->data[0]->hosts_filter);
+  ASSERT_FALSE(cached_rules->data[0]->schemes_filter);
+  ASSERT_EQ(cached_rules->data[0]->rewrites.size(), 1u);
+  ASSERT_TRUE(cached_rules->data[0]->rewrites[0]->is_remove_header());
+
+  const mojom::UrlRequestRewriteRemoveHeaderPtr& remove_header1 =
+      cached_rules->data[0]->rewrites[0]->get_remove_header();
+  ASSERT_TRUE(remove_header1->query_pattern);
+  ASSERT_EQ(remove_header1->query_pattern.value().compare("Test"), 0);
+  ASSERT_EQ(remove_header1->header_name.compare("Header"), 0);
+
+  // Create a RemoveHeader rewrite with no pattern.
+  EXPECT_EQ(UpdateRulesFromRewrite(
+                cr_fuchsia::CreateRewriteRemoveHeader(base::nullopt, "Header")),
+            ZX_OK);
+  cached_rules = url_request_rewrite_rules_manager_->GetCachedRules();
+  ASSERT_EQ(cached_rules->data.size(), 1u);
+  ASSERT_FALSE(cached_rules->data[0]->hosts_filter);
+  ASSERT_FALSE(cached_rules->data[0]->schemes_filter);
+  ASSERT_EQ(cached_rules->data[0]->rewrites.size(), 1u);
+  ASSERT_TRUE(cached_rules->data[0]->rewrites[0]->is_remove_header());
+
+  const mojom::UrlRequestRewriteRemoveHeaderPtr& remove_header2 =
+      cached_rules->data[0]->rewrites[0]->get_remove_header();
+  ASSERT_FALSE(remove_header2->query_pattern);
+  ASSERT_EQ(remove_header2->header_name.compare("Header"), 0);
+}
+
+// Tests SubstituteQueryPattern rewrites are properly converted to their Mojo
+// equivalent.
+TEST_F(UrlRequestRewriteRulesManagerTest, ConvertSubstituteQueryPattern) {
+  EXPECT_EQ(
+      UpdateRulesFromRewrite(cr_fuchsia::CreateRewriteSubstituteQueryPattern(
+          "Pattern", "Substitution")),
+      ZX_OK);
+  scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
+      cached_rules = url_request_rewrite_rules_manager_->GetCachedRules();
+  ASSERT_EQ(cached_rules->data.size(), 1u);
+  ASSERT_FALSE(cached_rules->data[0]->hosts_filter);
+  ASSERT_FALSE(cached_rules->data[0]->schemes_filter);
+  ASSERT_EQ(cached_rules->data[0]->rewrites.size(), 1u);
+  ASSERT_TRUE(
+      cached_rules->data[0]->rewrites[0]->is_substitute_query_pattern());
+
+  const mojom::UrlRequestRewriteSubstituteQueryPatternPtr&
+      substitute_query_pattern =
+          cached_rules->data[0]->rewrites[0]->get_substitute_query_pattern();
+  ASSERT_EQ(substitute_query_pattern->pattern.compare("Pattern"), 0);
+  ASSERT_EQ(substitute_query_pattern->substitution.compare("Substitution"), 0);
+}
+
+// Tests ReplaceUrl rewrites are properly converted to their Mojo equivalent.
+TEST_F(UrlRequestRewriteRulesManagerTest, ConvertReplaceUrl) {
+  GURL url("http://site.xyz");
+  EXPECT_EQ(UpdateRulesFromRewrite(
+                cr_fuchsia::CreateRewriteReplaceUrl("/something", url.spec())),
+            ZX_OK);
+  scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
+      cached_rules = url_request_rewrite_rules_manager_->GetCachedRules();
+  ASSERT_EQ(cached_rules->data.size(), 1u);
+  ASSERT_FALSE(cached_rules->data[0]->hosts_filter);
+  ASSERT_FALSE(cached_rules->data[0]->schemes_filter);
+  ASSERT_EQ(cached_rules->data[0]->rewrites.size(), 1u);
+  ASSERT_TRUE(cached_rules->data[0]->rewrites[0]->is_replace_url());
+
+  const mojom::UrlRequestRewriteReplaceUrlPtr& replace_url =
+      cached_rules->data[0]->rewrites[0]->get_replace_url();
+  ASSERT_EQ(replace_url->url_ends_with.compare("/something"), 0);
+  ASSERT_EQ(replace_url->new_url.spec().compare(url.spec()), 0);
+}
+
+// Tests validation is working as expected.
+TEST_F(UrlRequestRewriteRulesManagerTest, Validation) {
+  // Empty rewrite.
+  EXPECT_EQ(UpdateRulesFromRewrite(fuchsia::web::UrlRequestRewrite()),
+            ZX_ERR_INVALID_ARGS);
+
+  // Invalid AddHeaders header name.
+  EXPECT_EQ(UpdateRulesFromRewrite(
+                cr_fuchsia::CreateRewriteAddHeaders("Te\nst1", "Value")),
+            ZX_ERR_INVALID_ARGS);
+
+  // Invalid AddHeaders header value.
+  EXPECT_EQ(UpdateRulesFromRewrite(
+                cr_fuchsia::CreateRewriteAddHeaders("Test1", "Val\nue")),
+            ZX_ERR_INVALID_ARGS);
+
+  // Empty AddHeaders.
+  {
+    fuchsia::web::UrlRequestRewrite rewrite;
+    rewrite.set_add_headers(fuchsia::web::UrlRequestRewriteAddHeaders());
+    EXPECT_EQ(UpdateRulesFromRewrite(std::move(rewrite)), ZX_ERR_INVALID_ARGS);
+  }
+
+  // Invalid RemoveHeader header name.
+  EXPECT_EQ(UpdateRulesFromRewrite(
+                cr_fuchsia::CreateRewriteRemoveHeader("Query", "Head\ner")),
+            ZX_ERR_INVALID_ARGS);
+
+  // Empty RemoveHeader.
+  {
+    fuchsia::web::UrlRequestRewrite rewrite;
+    rewrite.set_add_headers(fuchsia::web::UrlRequestRewriteAddHeaders());
+    EXPECT_EQ(UpdateRulesFromRewrite(std::move(rewrite)), ZX_ERR_INVALID_ARGS);
+  }
+
+  // Empty SubstituteQueryPattern.
+  {
+    fuchsia::web::UrlRequestRewrite rewrite;
+    rewrite.set_substitute_query_pattern(
+        fuchsia::web::UrlRequestRewriteSubstituteQueryPattern());
+    EXPECT_EQ(UpdateRulesFromRewrite(std::move(rewrite)), ZX_ERR_INVALID_ARGS);
+  }
+
+  // Invalid ReplaceUrl url_ends_with.
+  EXPECT_EQ(UpdateRulesFromRewrite(cr_fuchsia::CreateRewriteReplaceUrl(
+                "some%00thing", GURL("http://site.xyz").spec())),
+            ZX_ERR_INVALID_ARGS);
+
+  // Invalid ReplaceUrl new_url.
+  EXPECT_EQ(UpdateRulesFromRewrite(cr_fuchsia::CreateRewriteReplaceUrl(
+                "/something", "http:site:xyz")),
+            ZX_ERR_INVALID_ARGS);
+
+  // Empty ReplaceUrl.
+  {
+    fuchsia::web::UrlRequestRewrite rewrite;
+    rewrite.set_replace_url(fuchsia::web::UrlRequestRewriteReplaceUrl());
+    EXPECT_EQ(UpdateRulesFromRewrite(std::move(rewrite)), ZX_ERR_INVALID_ARGS);
+  }
+}
+
+// Tests rules are properly renewed after new rules are sent.
+TEST_F(UrlRequestRewriteRulesManagerTest, RuleRenewal) {
+  EXPECT_EQ(UpdateRulesFromRewrite(
+                cr_fuchsia::CreateRewriteAddHeaders("Test1", "Value")),
+            ZX_OK);
+  scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
+      cached_rules = url_request_rewrite_rules_manager_->GetCachedRules();
+  ASSERT_EQ(cached_rules->data.size(), 1u);
+  ASSERT_EQ(cached_rules->data[0]->rewrites.size(), 1u);
+  ASSERT_TRUE(cached_rules->data[0]->rewrites[0]->is_add_headers());
+  ASSERT_TRUE(
+      cached_rules->data[0]->rewrites[0]->get_add_headers()->headers.HasHeader(
+          "Test1"));
+
+  EXPECT_EQ(UpdateRulesFromRewrite(
+                cr_fuchsia::CreateRewriteAddHeaders("Test2", "Value")),
+            ZX_OK);
+
+  // We should have the new rules.
+  cached_rules = url_request_rewrite_rules_manager_->GetCachedRules();
+  ASSERT_EQ(cached_rules->data.size(), 1u);
+  ASSERT_EQ(cached_rules->data[0]->rewrites.size(), 1u);
+  ASSERT_TRUE(cached_rules->data[0]->rewrites[0]->is_add_headers());
+  ASSERT_TRUE(
+      cached_rules->data[0]->rewrites[0]->get_add_headers()->headers.HasHeader(
+          "Test2"));
+}
diff --git a/fuchsia/engine/browser/web_engine_content_browser_client.cc b/fuchsia/engine/browser/web_engine_content_browser_client.cc
index 08453ea5..051b3ea6 100644
--- a/fuchsia/engine/browser/web_engine_content_browser_client.cc
+++ b/fuchsia/engine/browser/web_engine_content_browser_client.cc
@@ -11,10 +11,12 @@
 #include "components/version_info/version_info.h"
 #include "content/public/common/user_agent.h"
 #include "content/public/common/web_preferences.h"
+#include "fuchsia/engine/browser/url_request_rewrite_rules_manager.h"
 #include "fuchsia/engine/browser/web_engine_browser_context.h"
 #include "fuchsia/engine/browser/web_engine_browser_main_parts.h"
 #include "fuchsia/engine/browser/web_engine_devtools_manager_delegate.h"
 #include "fuchsia/engine/common.h"
+#include "fuchsia/engine/common/web_engine_url_loader_throttle.h"
 #include "fuchsia/engine/switches.h"
 
 WebEngineContentBrowserClient::WebEngineContentBrowserClient(
@@ -104,3 +106,28 @@
     command_line->AppendSwitch(switches::kDisableSoftwareVideoDecoders);
   }
 }
+
+std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
+WebEngineContentBrowserClient::CreateURLLoaderThrottles(
+    const network::ResourceRequest& request,
+    content::BrowserContext* browser_context,
+    const base::RepeatingCallback<content::WebContents*()>& wc_getter,
+    content::NavigationUIData* navigation_ui_data,
+    int frame_tree_node_id) {
+  if (frame_tree_node_id == content::RenderFrameHost::kNoFrameTreeNodeId) {
+    // TODO(crbug.com/976975): Add support for service workers.
+    return {};
+  }
+
+  UrlRequestRewriteRulesManager* adapter =
+      UrlRequestRewriteRulesManager::ForFrameTreeNodeId(frame_tree_node_id);
+  if (!adapter) {
+    // No popup support for rules rewriter.
+    return {};
+  }
+
+  std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles;
+  throttles.emplace_back(std::make_unique<WebEngineURLLoaderThrottle>(
+      UrlRequestRewriteRulesManager::ForFrameTreeNodeId(frame_tree_node_id)));
+  return throttles;
+}
diff --git a/fuchsia/engine/browser/web_engine_content_browser_client.h b/fuchsia/engine/browser/web_engine_content_browser_client.h
index 560ed6c7..46b25b1 100644
--- a/fuchsia/engine/browser/web_engine_content_browser_client.h
+++ b/fuchsia/engine/browser/web_engine_content_browser_client.h
@@ -48,6 +48,13 @@
       NonNetworkURLLoaderFactoryMap* factories) final;
   void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
                                       int child_process_id) final;
+  std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
+  CreateURLLoaderThrottles(
+      const network::ResourceRequest& request,
+      content::BrowserContext* browser_context,
+      const base::RepeatingCallback<content::WebContents*()>& wc_getter,
+      content::NavigationUIData* navigation_ui_data,
+      int frame_tree_node_id) final;
 
  private:
   fidl::InterfaceRequest<fuchsia::web::Context> request_;
diff --git a/fuchsia/engine/common/DEPS b/fuchsia/engine/common/DEPS
new file mode 100644
index 0000000..34940ca7
--- /dev/null
+++ b/fuchsia/engine/common/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+third_party/blink/public/common/loader",
+]
diff --git a/fuchsia/engine/common/web_engine_url_loader_throttle.cc b/fuchsia/engine/common/web_engine_url_loader_throttle.cc
new file mode 100644
index 0000000..151ca415
--- /dev/null
+++ b/fuchsia/engine/common/web_engine_url_loader_throttle.cc
@@ -0,0 +1,160 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "fuchsia/engine/common/web_engine_url_loader_throttle.h"
+
+#include "base/strings/string_util.h"
+
+namespace {
+
+// Returnns a string representing the URL stripped of query and ref.
+std::string ClearUrlQueryRef(const GURL& url) {
+  GURL::Replacements replacements;
+  replacements.ClearQuery();
+  replacements.ClearRef();
+  return url.ReplaceComponents(replacements).spec();
+}
+
+void ApplyAddHeaders(network::ResourceRequest* request,
+                     const mojom::UrlRequestRewriteAddHeadersPtr& add_headers) {
+  request->headers.MergeFrom(add_headers->headers);
+}
+
+void ApplyRemoveHeader(
+    network::ResourceRequest* request,
+    const mojom::UrlRequestRewriteRemoveHeaderPtr& remove_header) {
+  base::Optional<std::string> query_pattern = remove_header->query_pattern;
+  if (query_pattern &&
+      request->url.query().find(query_pattern.value()) == std::string::npos) {
+    return;
+  }
+
+  request->headers.RemoveHeader(remove_header->header_name);
+}
+
+void ApplySubstituteQueryPattern(
+    network::ResourceRequest* request,
+    const mojom::UrlRequestRewriteSubstituteQueryPatternPtr&
+        substitute_query_pattern) {
+  std::string url_query = request->url.query();
+
+  base::ReplaceSubstringsAfterOffset(&url_query, 0,
+                                     substitute_query_pattern->pattern,
+                                     substitute_query_pattern->substitution);
+
+  GURL::Replacements replacements;
+  replacements.SetQueryStr(url_query);
+  request->url = request->url.ReplaceComponents(replacements);
+}
+
+void ApplyReplaceUrl(network::ResourceRequest* request,
+                     const mojom::UrlRequestRewriteReplaceUrlPtr& replace_url) {
+  if (!base::EndsWith(ClearUrlQueryRef(request->url),
+                      replace_url->url_ends_with, base::CompareCase::SENSITIVE))
+    return;
+
+  GURL new_url = replace_url->new_url;
+  if (new_url.has_scheme() &&
+      new_url.scheme().compare(request->url.scheme()) != 0) {
+    // No cross-scheme redirect allowed.
+    return;
+  }
+
+  GURL::Replacements replacements;
+  std::string host = new_url.host();
+  replacements.SetHostStr(host);
+  std::string port = new_url.port();
+  replacements.SetPortStr(port);
+  std::string path = new_url.path();
+  replacements.SetPathStr(path);
+
+  request->url = request->url.ReplaceComponents(replacements);
+}
+
+void ApplyRewrite(network::ResourceRequest* request,
+                  const mojom::UrlRequestRewritePtr& rewrite) {
+  switch (rewrite->which()) {
+    case mojom::UrlRequestRewrite::Tag::ADD_HEADERS:
+      ApplyAddHeaders(request, rewrite->get_add_headers());
+      break;
+    case mojom::UrlRequestRewrite::Tag::REMOVE_HEADER:
+      ApplyRemoveHeader(request, rewrite->get_remove_header());
+      break;
+    case mojom::UrlRequestRewrite::Tag::SUBSTITUTE_QUERY_PATTERN:
+      ApplySubstituteQueryPattern(request,
+                                  rewrite->get_substitute_query_pattern());
+      break;
+    case mojom::UrlRequestRewrite::Tag::REPLACE_URL:
+      ApplyReplaceUrl(request, rewrite->get_replace_url());
+      break;
+  }
+}
+
+void ApplyRule(network::ResourceRequest* request,
+               const mojom::UrlRequestRewriteRulePtr& rule) {
+  const GURL& url = request->url;
+
+  if (rule->hosts_filter) {
+    bool found = false;
+    for (const auto& host : rule->hosts_filter.value()) {
+      if (url.host().compare(host) == 0) {
+        found = true;
+        break;
+      }
+    }
+    if (!found)
+      return;
+  }
+
+  if (rule->schemes_filter) {
+    bool found = false;
+    for (const auto& scheme : rule->schemes_filter.value()) {
+      if (url.scheme().compare(scheme) == 0) {
+        found = true;
+        break;
+      }
+    }
+    if (!found)
+      return;
+  }
+
+  for (const auto& rewrite : rule->rewrites) {
+    ApplyRewrite(request, rewrite);
+  }
+}
+
+void ApplyRules(network::ResourceRequest* request,
+                const std::vector<mojom::UrlRequestRewriteRulePtr>& rules) {
+  for (const auto& rule : rules) {
+    ApplyRule(request, rule);
+  }
+}
+
+}  // namespace
+
+WebEngineURLLoaderThrottle::WebEngineURLLoaderThrottle(
+    CachedRulesProvider* cached_rules_provider)
+    : cached_rules_provider_(cached_rules_provider) {
+  DCHECK(cached_rules_provider);
+}
+
+WebEngineURLLoaderThrottle::~WebEngineURLLoaderThrottle() = default;
+
+void WebEngineURLLoaderThrottle::DetachFromCurrentSequence() {}
+
+void WebEngineURLLoaderThrottle::WillStartRequest(
+    network::ResourceRequest* request,
+    bool* defer) {
+  scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
+      cached_rules = cached_rules_provider_->GetCachedRules();
+  // |cached_rules| may be empty if no rule was ever sent to WebEngine.
+  if (cached_rules)
+    ApplyRules(request, cached_rules->data);
+  *defer = false;
+}
+
+bool WebEngineURLLoaderThrottle::makes_unsafe_redirect() {
+  // WillStartRequest() does not make cross-scheme redirects.
+  return false;
+}
diff --git a/fuchsia/engine/common/web_engine_url_loader_throttle.h b/fuchsia/engine/common/web_engine_url_loader_throttle.h
new file mode 100644
index 0000000..f9ffdcf3
--- /dev/null
+++ b/fuchsia/engine/common/web_engine_url_loader_throttle.h
@@ -0,0 +1,48 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FUCHSIA_ENGINE_COMMON_WEB_ENGINE_URL_LOADER_THROTTLE_H_
+#define FUCHSIA_ENGINE_COMMON_WEB_ENGINE_URL_LOADER_THROTTLE_H_
+
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "fuchsia/engine/url_request_rewrite.mojom.h"
+#include "third_party/blink/public/common/loader/url_loader_throttle.h"
+
+// Implements a URLLoaderThrottle for the WebEngine. Applies network request
+// rewrites provided through the fuchsia.web.SetUrlRequestRewriteRules FIDL API.
+class WebEngineURLLoaderThrottle : public blink::URLLoaderThrottle {
+ public:
+  using UrlRequestRewriteRules =
+      base::RefCountedData<std::vector<mojom::UrlRequestRewriteRulePtr>>;
+
+  // An interface to provide rewrite rules to the throttle. Its
+  // implementation must outlive the WebEngineURLLoaderThrottle.
+  class CachedRulesProvider {
+   public:
+    virtual ~CachedRulesProvider() = default;
+
+    // Gets cached rules. This call can be made on any sequence, as
+    // URLLoaderThrottles are not guaranteed to stay on the same sequence.
+    virtual scoped_refptr<UrlRequestRewriteRules> GetCachedRules() = 0;
+  };
+
+  explicit WebEngineURLLoaderThrottle(
+      CachedRulesProvider* cached_rules_provider);
+  ~WebEngineURLLoaderThrottle() override;
+
+ private:
+  // blink::URLLoaderThrottle implementation.
+  void DetachFromCurrentSequence() override;
+  void WillStartRequest(network::ResourceRequest* request,
+                        bool* defer) override;
+  bool makes_unsafe_redirect() override;
+
+  CachedRulesProvider* const cached_rules_provider_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebEngineURLLoaderThrottle);
+};
+
+#endif  // FUCHSIA_ENGINE_COMMON_WEB_ENGINE_URL_LOADER_THROTTLE_H_
diff --git a/fuchsia/engine/renderer/url_request_rules_receiver.cc b/fuchsia/engine/renderer/url_request_rules_receiver.cc
new file mode 100644
index 0000000..7381ec93b
--- /dev/null
+++ b/fuchsia/engine/renderer/url_request_rules_receiver.cc
@@ -0,0 +1,66 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "fuchsia/engine/renderer/url_request_rules_receiver.h"
+
+#include "content/public/renderer/render_frame.h"
+#include "fuchsia/engine/renderer/web_engine_content_renderer_client.h"
+#include "fuchsia/engine/url_request_rewrite.mojom.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
+
+UrlRequestRulesReceiver::UrlRequestRulesReceiver(
+    content::RenderFrame* render_frame,
+    base::OnceCallback<void(int)> on_render_frame_deleted_callback)
+    : content::RenderFrameObserver(render_frame),
+      associated_binding_(this),
+      on_render_frame_deleted_callback_(
+          std::move(on_render_frame_deleted_callback)) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(on_render_frame_deleted_callback_);
+  DCHECK(render_frame);
+
+  // It is fine to use an unretained pointer to |this| here as the
+  // AssociatedInterfaceRegistry, owned by |render_frame| will be torn-down at
+  // the same time as |this|.
+  render_frame->GetAssociatedInterfaceRegistry()->AddInterface(
+      base::BindRepeating(
+          &UrlRequestRulesReceiver::OnUrlRequestRulesReceiverAssociatedRequest,
+          base::Unretained(this)));
+}
+
+UrlRequestRulesReceiver::~UrlRequestRulesReceiver() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+void UrlRequestRulesReceiver::OnUrlRequestRulesReceiverAssociatedRequest(
+    mojom::UrlRequestRulesReceiverAssociatedRequest request) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(!associated_binding_.is_bound());
+  associated_binding_.Bind(std::move(request));
+}
+
+void UrlRequestRulesReceiver::OnRulesUpdated(
+    std::vector<mojom::UrlRequestRewriteRulePtr> rules) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  base::AutoLock auto_lock(lock_);
+  cached_rules_ =
+      base::MakeRefCounted<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>(
+          std::move(rules));
+}
+
+scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
+UrlRequestRulesReceiver::GetCachedRules() {
+  base::AutoLock auto_lock(lock_);
+  return cached_rules_;
+}
+
+void UrlRequestRulesReceiver::OnDestruct() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  // The RenderFrame corresponding to this object was destroyed, which means
+  // the AssociatedInterfaceRegsitry is also gone. It is expected that
+  // |on_render_frame_deleted_callback_| will delete |this|.
+  std::move(on_render_frame_deleted_callback_).Run(routing_id());
+}
diff --git a/fuchsia/engine/renderer/url_request_rules_receiver.h b/fuchsia/engine/renderer/url_request_rules_receiver.h
new file mode 100644
index 0000000..4ca5c10f
--- /dev/null
+++ b/fuchsia/engine/renderer/url_request_rules_receiver.h
@@ -0,0 +1,68 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FUCHSIA_ENGINE_RENDERER_URL_REQUEST_RULES_RECEIVER_H_
+#define FUCHSIA_ENGINE_RENDERER_URL_REQUEST_RULES_RECEIVER_H_
+
+#include "base/sequence_checker.h"
+#include "base/synchronization/lock.h"
+#include "base/thread_annotations.h"
+#include "content/public/renderer/render_frame_observer.h"
+#include "fuchsia/engine/common/web_engine_url_loader_throttle.h"
+#include "fuchsia/engine/url_request_rewrite.mojom.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
+
+namespace content {
+class RenderFrame;
+}  // namespace content
+
+// Provides rewriting rules for network requests. UrlRequestRulesReceiver
+// objects are owned by their respective WebEngineContentRendererClient and they
+// will be destroyed on RenderFrame destruction. This is guaranteed to outlive
+// any WebEngineURLLoaderThrottle that uses it as the RenderFrame destruction
+// will have triggered the destruction of all pending
+// WebEngineURLLoaderThrottles.
+// This class should only be used on the IO thread, with the exception of the
+// GetCachedRules() implementation, which can be called from any sequence.
+class UrlRequestRulesReceiver
+    : public mojom::UrlRequestRulesReceiver,
+      public WebEngineURLLoaderThrottle::CachedRulesProvider,
+      public content::RenderFrameObserver {
+ public:
+  UrlRequestRulesReceiver(
+      content::RenderFrame* render_frame,
+      base::OnceCallback<void(int)> on_render_frame_deleted_callback);
+  ~UrlRequestRulesReceiver() override;
+
+ private:
+  void OnUrlRequestRulesReceiverAssociatedRequest(
+      mojom::UrlRequestRulesReceiverAssociatedRequest request);
+
+  // mojom::UrlRequestRulesReceiver implementation.
+  void OnRulesUpdated(
+      std::vector<mojom::UrlRequestRewriteRulePtr> rules) override;
+
+  // WebEngineURLLoaderThrottle::CachedRulesProvider implementation.
+  scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
+  GetCachedRules() override;
+
+  // content::RenderFrameObserver implementation.
+  void OnDestruct() override;
+
+  base::Lock lock_;
+
+  // This is accessed by WebEngineURLLoaderThrottles, which can be off-sequence
+  // in the case of synchronous network requests.
+  scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
+      cached_rules_ GUARDED_BY(lock_);
+
+  mojo::AssociatedBinding<mojom::UrlRequestRulesReceiver> associated_binding_;
+  base::OnceCallback<void(int)> on_render_frame_deleted_callback_;
+  SEQUENCE_CHECKER(sequence_checker_);
+
+  DISALLOW_COPY_AND_ASSIGN(UrlRequestRulesReceiver);
+};
+
+#endif  // FUCHSIA_ENGINE_RENDERER_URL_REQUEST_RULES_RECEIVER_H_
diff --git a/fuchsia/engine/renderer/web_engine_content_renderer_client.cc b/fuchsia/engine/renderer/web_engine_content_renderer_client.cc
index 6ef7367f..28ea905 100644
--- a/fuchsia/engine/renderer/web_engine_content_renderer_client.cc
+++ b/fuchsia/engine/renderer/web_engine_content_renderer_client.cc
@@ -4,13 +4,16 @@
 
 #include "fuchsia/engine/renderer/web_engine_content_renderer_client.h"
 
+#include "base/feature_list.h"
 #include "base/macros.h"
 #include "components/cdm/renderer/widevine_key_system_properties.h"
 #include "content/public/renderer/render_frame.h"
 #include "fuchsia/engine/renderer/on_load_script_injector.h"
+#include "fuchsia/engine/renderer/web_engine_url_loader_throttle_provider.h"
 #include "fuchsia/engine/switches.h"
 #include "media/base/eme_constants.h"
 #include "media/base/video_codecs.h"
+#include "services/network/public/cpp/features.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
 #include "third_party/widevine/cdm/widevine_cdm_common.h"
@@ -19,11 +22,45 @@
 
 WebEngineContentRendererClient::~WebEngineContentRendererClient() = default;
 
+UrlRequestRulesReceiver*
+WebEngineContentRendererClient::GetUrlRequestRulesReceiverForRenderFrameId(
+    int render_frame_id) const {
+  auto iter = url_request_receivers_by_id_.find(render_frame_id);
+  DCHECK(iter != url_request_receivers_by_id_.end());
+  return iter->second.get();
+}
+
+void WebEngineContentRendererClient::OnRenderFrameDeleted(int render_frame_id) {
+  size_t count = url_request_receivers_by_id_.erase(render_frame_id);
+  DCHECK_EQ(count, 1u);
+}
+
 void WebEngineContentRendererClient::RenderFrameCreated(
     content::RenderFrame* render_frame) {
   // Add WebEngine services to the new RenderFrame.
   // The objects' lifetimes are bound to the RenderFrame's lifetime.
   new OnLoadScriptInjector(render_frame);
+
+  int render_frame_id = render_frame->GetRoutingID();
+  auto rules_receiver = std::make_unique<UrlRequestRulesReceiver>(
+      content::RenderFrame::FromRoutingID(render_frame_id),
+      base::BindOnce(&WebEngineContentRendererClient::OnRenderFrameDeleted,
+                     base::Unretained(this)));
+  auto iter = url_request_receivers_by_id_.emplace(render_frame_id,
+                                                   std::move(rules_receiver));
+  DCHECK(iter.second);
+}
+
+std::unique_ptr<content::URLLoaderThrottleProvider>
+WebEngineContentRendererClient::CreateURLLoaderThrottleProvider(
+    content::URLLoaderThrottleProviderType type) {
+  DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
+
+  // TODO(crbug.com/976975): Add support for service workers.
+  if (type == content::URLLoaderThrottleProviderType::kWorker)
+    return nullptr;
+
+  return std::make_unique<WebEngineURLLoaderThrottleProvider>(this);
 }
 
 void WebEngineContentRendererClient::AddSupportedKeySystems(
diff --git a/fuchsia/engine/renderer/web_engine_content_renderer_client.h b/fuchsia/engine/renderer/web_engine_content_renderer_client.h
index 0e196cc5..ecf45c8 100644
--- a/fuchsia/engine/renderer/web_engine_content_renderer_client.h
+++ b/fuchsia/engine/renderer/web_engine_content_renderer_client.h
@@ -7,20 +7,36 @@
 
 #include "base/macros.h"
 #include "content/public/renderer/content_renderer_client.h"
+#include "fuchsia/engine/renderer/url_request_rules_receiver.h"
 
 class WebEngineContentRendererClient : public content::ContentRendererClient {
  public:
   WebEngineContentRendererClient();
   ~WebEngineContentRendererClient() override;
 
+  // Returns the UrlRequestRulesReceiver corresponding to |render_frame_id|.
+  UrlRequestRulesReceiver* GetUrlRequestRulesReceiverForRenderFrameId(
+      int render_frame_id) const;
+
+ private:
+  // Called by UrlRequestRulesReceivers when their corresponding RenderFrame is
+  // in the process of being deleted.
+  void OnRenderFrameDeleted(int render_frame_id);
+
   // content::ContentRendererClient overrides.
   void RenderFrameCreated(content::RenderFrame* render_frame) override;
   void AddSupportedKeySystems(
       std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems)
       override;
   bool IsSupportedVideoType(const media::VideoType& type) override;
+  std::unique_ptr<content::URLLoaderThrottleProvider>
+  CreateURLLoaderThrottleProvider(
+      content::URLLoaderThrottleProviderType type) override;
 
- private:
+  // Map of rules receivers per RenderFrame ID.
+  std::map<int, std::unique_ptr<UrlRequestRulesReceiver>>
+      url_request_receivers_by_id_;
+
   DISALLOW_COPY_AND_ASSIGN(WebEngineContentRendererClient);
 };
 
diff --git a/fuchsia/engine/renderer/web_engine_url_loader_throttle_provider.cc b/fuchsia/engine/renderer/web_engine_url_loader_throttle_provider.cc
new file mode 100644
index 0000000..be620f8
--- /dev/null
+++ b/fuchsia/engine/renderer/web_engine_url_loader_throttle_provider.cc
@@ -0,0 +1,42 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "fuchsia/engine/renderer/web_engine_url_loader_throttle_provider.h"
+
+#include "content/public/renderer/render_frame.h"
+#include "fuchsia/engine/common/web_engine_url_loader_throttle.h"
+#include "fuchsia/engine/renderer/web_engine_content_renderer_client.h"
+
+WebEngineURLLoaderThrottleProvider::WebEngineURLLoaderThrottleProvider(
+    WebEngineContentRendererClient* content_renderer_client)
+    : content_renderer_client_(content_renderer_client) {
+  DETACH_FROM_SEQUENCE(sequence_checker_);
+}
+
+WebEngineURLLoaderThrottleProvider::~WebEngineURLLoaderThrottleProvider() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
+
+std::unique_ptr<content::URLLoaderThrottleProvider>
+WebEngineURLLoaderThrottleProvider::Clone() {
+  // This should only happen for service workers, which we do not support here.
+  NOTREACHED();
+  return nullptr;
+}
+
+std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
+WebEngineURLLoaderThrottleProvider::CreateThrottles(
+    int render_frame_id,
+    const blink::WebURLRequest& request,
+    content::ResourceType resource_type) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles;
+  throttles.emplace_back(std::make_unique<WebEngineURLLoaderThrottle>(
+      content_renderer_client_->GetUrlRequestRulesReceiverForRenderFrameId(
+          render_frame_id)));
+  return throttles;
+}
+
+void WebEngineURLLoaderThrottleProvider::SetOnline(bool is_online) {}
diff --git a/fuchsia/engine/renderer/web_engine_url_loader_throttle_provider.h b/fuchsia/engine/renderer/web_engine_url_loader_throttle_provider.h
new file mode 100644
index 0000000..2370fbe2
--- /dev/null
+++ b/fuchsia/engine/renderer/web_engine_url_loader_throttle_provider.h
@@ -0,0 +1,39 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FUCHSIA_ENGINE_RENDERER_WEB_ENGINE_URL_LOADER_THROTTLE_PROVIDER_H_
+#define FUCHSIA_ENGINE_RENDERER_WEB_ENGINE_URL_LOADER_THROTTLE_PROVIDER_H_
+
+#include "base/macros.h"
+#include "base/sequence_checker.h"
+#include "content/public/renderer/url_loader_throttle_provider.h"
+
+class WebEngineContentRendererClient;
+
+// Implements a URLLoaderThrottleProvider for the WebEngine. Creates
+// URLLoaderThrottles, implemented as WebEngineURLLoaderThrottles for network
+// requests.
+class WebEngineURLLoaderThrottleProvider
+    : public content::URLLoaderThrottleProvider {
+ public:
+  explicit WebEngineURLLoaderThrottleProvider(
+      WebEngineContentRendererClient* content_renderer_client);
+  ~WebEngineURLLoaderThrottleProvider() override;
+
+  // content::URLLoaderThrottleProvider implementation.
+  std::unique_ptr<content::URLLoaderThrottleProvider> Clone() override;
+  std::vector<std::unique_ptr<blink::URLLoaderThrottle>> CreateThrottles(
+      int render_frame_id,
+      const blink::WebURLRequest& request,
+      content::ResourceType resource_type) override;
+  void SetOnline(bool is_online) override;
+
+ private:
+  const WebEngineContentRendererClient* const content_renderer_client_;
+  SEQUENCE_CHECKER(sequence_checker_);
+
+  DISALLOW_COPY_AND_ASSIGN(WebEngineURLLoaderThrottleProvider);
+};
+
+#endif  // FUCHSIA_ENGINE_RENDERER_WEB_ENGINE_URL_LOADER_THROTTLE_PROVIDER_H_
diff --git a/fuchsia/engine/test/data/image.html b/fuchsia/engine/test/data/image.html
new file mode 100644
index 0000000..55025a1
--- /dev/null
+++ b/fuchsia/engine/test/data/image.html
@@ -0,0 +1,4 @@
+<html>
+  <head><title>Image</title></head>
+  <body><img src="/img.png"></body>
+</html>
diff --git a/fuchsia/engine/url_request_rewrite.mojom b/fuchsia/engine/url_request_rewrite.mojom
new file mode 100644
index 0000000..a52f33c
--- /dev/null
+++ b/fuchsia/engine/url_request_rewrite.mojom
@@ -0,0 +1,83 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module mojom;
+
+import "mojo/public/mojom/base/time.mojom";
+import "services/network/public/mojom/http_request_headers.mojom";
+import "url/mojom/url.mojom";
+
+// Used by the browser to push URL rewrite rules to renderers. There will be
+// one receiver per web frame.
+// TODO(https://crbug.com/976975): Support URL rewriting for service workers.
+interface UrlRequestRulesReceiver {
+  // Receives a set of rules to apply to URL requests.
+  OnRulesUpdated(array<UrlRequestRewriteRule> rules);
+};
+
+// A URL request rewrite rule.
+struct UrlRequestRewriteRule {
+  // Set of hosts to apply the rewrites to. If empty, the rule will apply to
+  // every request, independent of host.
+  array<string>? hosts_filter;
+
+  // Set of schemes to apply the rewrites to. If empty, the rule will apply to
+  // every request, independent of scheme.
+  array<string>? schemes_filter;
+
+  // URL request rewrites to apply.
+  array<UrlRequestRewrite> rewrites;
+};
+
+union UrlRequestRewrite {
+  // Adds a set of headers to a URL request.
+  UrlRequestRewriteAddHeaders add_headers;
+
+  // Removes a header based on the presence of a pattern in the URL query.
+  UrlRequestRewriteRemoveHeader remove_header;
+
+  // Substitutes a pattern in the URL query.
+  UrlRequestRewriteSubstituteQueryPattern substitute_query_pattern;
+
+  // Replaces a URL if the original URL ends with a pattern.
+  UrlRequestRewriteReplaceUrl replace_url;
+};
+
+// Adds |headers| to the URL request. If a header is already present in the
+// original URL request, it will be overwritten.
+struct UrlRequestRewriteAddHeaders {
+  // The headers to add.
+  network.mojom.HttpRequestHeaders headers;
+};
+
+// If |query_pattern| in the URL query, removes |header_name| from the list of
+// headers. If |query_pattern| is empty, removes |header_name| from the list
+// of headers unconditionally
+struct UrlRequestRewriteRemoveHeader {
+  // The pattern to look for in the URL request.
+  string? query_pattern;
+
+  // The header to remove.
+  string header_name;
+};
+
+// If |pattern| is found in the URL request query, replaces it with
+// |substitution|.
+struct UrlRequestRewriteSubstituteQueryPattern {
+  // The pattern to look for in the URL request.
+  string pattern;
+
+  // The string to repalce |pattern| with.
+  string substitution;
+};
+
+// If the URL in the URL request ends with |url_ends_with|, rewrites the URL to
+// |new_url|.
+struct UrlRequestRewriteReplaceUrl {
+  // The pattern to look for in the URL.
+  string url_ends_with;
+
+  // The replacement URL.
+  url.mojom.Url new_url;
+};
diff --git a/fuchsia/engine/url_request_rewrite_type_converters.cc b/fuchsia/engine/url_request_rewrite_type_converters.cc
new file mode 100644
index 0000000..bd4a4bd2
--- /dev/null
+++ b/fuchsia/engine/url_request_rewrite_type_converters.cc
@@ -0,0 +1,109 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "fuchsia/engine/url_request_rewrite_type_converters.h"
+
+namespace mojo {
+
+mojom::UrlRequestRewriteAddHeadersPtr
+TypeConverter<mojom::UrlRequestRewriteAddHeadersPtr,
+              fuchsia::web::UrlRequestRewriteAddHeaders>::
+    Convert(const fuchsia::web::UrlRequestRewriteAddHeaders& input) {
+  mojom::UrlRequestRewriteAddHeadersPtr add_headers =
+      mojom::UrlRequestRewriteAddHeaders::New();
+  if (input.has_headers()) {
+    for (const auto& header : input.headers()) {
+      base::StringPiece header_name = cr_fuchsia::BytesAsString(header.name);
+      base::StringPiece header_value = cr_fuchsia::BytesAsString(header.value);
+      add_headers->headers.SetHeader(header_name, header_value);
+    }
+  }
+  return add_headers;
+}
+
+mojom::UrlRequestRewriteRemoveHeaderPtr
+TypeConverter<mojom::UrlRequestRewriteRemoveHeaderPtr,
+              fuchsia::web::UrlRequestRewriteRemoveHeader>::
+    Convert(const fuchsia::web::UrlRequestRewriteRemoveHeader& input) {
+  mojom::UrlRequestRewriteRemoveHeaderPtr remove_header =
+      mojom::UrlRequestRewriteRemoveHeader::New();
+  if (input.has_query_pattern())
+    remove_header->query_pattern = base::make_optional(input.query_pattern());
+  if (input.has_header_name())
+    remove_header->header_name =
+        cr_fuchsia::BytesAsString(input.header_name()).as_string();
+  return remove_header;
+}
+
+mojom::UrlRequestRewriteSubstituteQueryPatternPtr
+TypeConverter<mojom::UrlRequestRewriteSubstituteQueryPatternPtr,
+              fuchsia::web::UrlRequestRewriteSubstituteQueryPattern>::
+    Convert(
+        const fuchsia::web::UrlRequestRewriteSubstituteQueryPattern& input) {
+  mojom::UrlRequestRewriteSubstituteQueryPatternPtr substitute_query_pattern =
+      mojom::UrlRequestRewriteSubstituteQueryPattern::New();
+  if (input.has_pattern())
+    substitute_query_pattern->pattern = input.pattern();
+  if (input.has_substitution())
+    substitute_query_pattern->substitution = input.substitution();
+  return substitute_query_pattern;
+}
+
+mojom::UrlRequestRewriteReplaceUrlPtr
+TypeConverter<mojom::UrlRequestRewriteReplaceUrlPtr,
+              fuchsia::web::UrlRequestRewriteReplaceUrl>::
+    Convert(const fuchsia::web::UrlRequestRewriteReplaceUrl& input) {
+  mojom::UrlRequestRewriteReplaceUrlPtr replace_url =
+      mojom::UrlRequestRewriteReplaceUrl::New();
+  if (input.has_url_ends_with())
+    replace_url->url_ends_with = input.url_ends_with();
+  if (input.has_new_url())
+    replace_url->new_url = GURL(input.new_url());
+  return replace_url;
+}
+
+mojom::UrlRequestRewritePtr
+TypeConverter<mojom::UrlRequestRewritePtr, fuchsia::web::UrlRequestRewrite>::
+    Convert(const fuchsia::web::UrlRequestRewrite& input) {
+  switch (input.Which()) {
+    case fuchsia::web::UrlRequestRewrite::Tag::kAddHeaders:
+      return mojom::UrlRequestRewrite::NewAddHeaders(
+          mojo::ConvertTo<mojom::UrlRequestRewriteAddHeadersPtr>(
+              input.add_headers()));
+    case fuchsia::web::UrlRequestRewrite::Tag::kRemoveHeader:
+      return mojom::UrlRequestRewrite::NewRemoveHeader(
+          mojo::ConvertTo<mojom::UrlRequestRewriteRemoveHeaderPtr>(
+              input.remove_header()));
+    case fuchsia::web::UrlRequestRewrite::Tag::kSubstituteQueryPattern:
+      return mojom::UrlRequestRewrite::NewSubstituteQueryPattern(
+          mojo::ConvertTo<mojom::UrlRequestRewriteSubstituteQueryPatternPtr>(
+              input.substitute_query_pattern()));
+    case fuchsia::web::UrlRequestRewrite::Tag::kReplaceUrl:
+      return mojom::UrlRequestRewrite::NewReplaceUrl(
+          mojo::ConvertTo<mojom::UrlRequestRewriteReplaceUrlPtr>(
+              input.replace_url()));
+    default:
+      // This is to prevent build breakage when adding new rewrites to the FIDL
+      // definition.
+      NOTREACHED();
+      return nullptr;
+  }
+}
+
+mojom::UrlRequestRewriteRulePtr
+TypeConverter<mojom::UrlRequestRewriteRulePtr,
+              fuchsia::web::UrlRequestRewriteRule>::
+    Convert(const fuchsia::web::UrlRequestRewriteRule& input) {
+  mojom::UrlRequestRewriteRulePtr rule = mojom::UrlRequestRewriteRule::New();
+  if (input.has_hosts_filter())
+    rule->hosts_filter = base::make_optional(input.hosts_filter());
+  if (input.has_schemes_filter())
+    rule->schemes_filter = base::make_optional(input.schemes_filter());
+  if (input.has_rewrites())
+    rule->rewrites = mojo::ConvertTo<std::vector<mojom::UrlRequestRewritePtr>>(
+        input.rewrites());
+  return rule;
+}
+
+}  // namespace mojo
diff --git a/fuchsia/engine/url_request_rewrite_type_converters.h b/fuchsia/engine/url_request_rewrite_type_converters.h
new file mode 100644
index 0000000..559ef7d
--- /dev/null
+++ b/fuchsia/engine/url_request_rewrite_type_converters.h
@@ -0,0 +1,60 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FUCHSIA_ENGINE_URL_REQUEST_REWRITE_TYPE_CONVERTERS_H_
+#define FUCHSIA_ENGINE_URL_REQUEST_REWRITE_TYPE_CONVERTERS_H_
+
+#include <fuchsia/web/cpp/fidl.h>
+
+#include "fuchsia/base/string_util.h"
+#include "fuchsia/engine/url_request_rewrite.mojom.h"
+#include "mojo/public/cpp/bindings/type_converter.h"
+
+namespace mojo {
+
+template <>
+struct TypeConverter<mojom::UrlRequestRewriteAddHeadersPtr,
+                     fuchsia::web::UrlRequestRewriteAddHeaders> {
+  static mojom::UrlRequestRewriteAddHeadersPtr Convert(
+      const fuchsia::web::UrlRequestRewriteAddHeaders& input);
+};
+
+template <>
+struct TypeConverter<mojom::UrlRequestRewriteRemoveHeaderPtr,
+                     fuchsia::web::UrlRequestRewriteRemoveHeader> {
+  static mojom::UrlRequestRewriteRemoveHeaderPtr Convert(
+      const fuchsia::web::UrlRequestRewriteRemoveHeader& input);
+};
+
+template <>
+struct TypeConverter<mojom::UrlRequestRewriteSubstituteQueryPatternPtr,
+                     fuchsia::web::UrlRequestRewriteSubstituteQueryPattern> {
+  static mojom::UrlRequestRewriteSubstituteQueryPatternPtr Convert(
+      const fuchsia::web::UrlRequestRewriteSubstituteQueryPattern& input);
+};
+
+template <>
+struct TypeConverter<mojom::UrlRequestRewriteReplaceUrlPtr,
+                     fuchsia::web::UrlRequestRewriteReplaceUrl> {
+  static mojom::UrlRequestRewriteReplaceUrlPtr Convert(
+      const fuchsia::web::UrlRequestRewriteReplaceUrl& input);
+};
+
+template <>
+struct TypeConverter<mojom::UrlRequestRewritePtr,
+                     fuchsia::web::UrlRequestRewrite> {
+  static mojom::UrlRequestRewritePtr Convert(
+      const fuchsia::web::UrlRequestRewrite& input);
+};
+
+template <>
+struct TypeConverter<mojom::UrlRequestRewriteRulePtr,
+                     fuchsia::web::UrlRequestRewriteRule> {
+  static mojom::UrlRequestRewriteRulePtr Convert(
+      const fuchsia::web::UrlRequestRewriteRule& input);
+};
+
+}  // namespace mojo
+
+#endif  // FUCHSIA_ENGINE_URL_REQUEST_REWRITE_TYPE_CONVERTERS_H_
diff --git a/gpu/ipc/service/shared_image_stub.cc b/gpu/ipc/service/shared_image_stub.cc
index 15fccd35..09d8f4f69 100644
--- a/gpu/ipc/service/shared_image_stub.cc
+++ b/gpu/ipc/service/shared_image_stub.cc
@@ -491,19 +491,15 @@
                                          const SyncToken& sync_token) {
   // If there is no sync token, we don't need to wait.
   if (!sync_token.HasData()) {
-    OnSyncTokenReleased(mailbox);
+    OnDestroySharedImage(mailbox);
     return;
   }
 
-  auto done_cb = base::BindOnce(&SharedImageStub::OnSyncTokenReleased,
+  auto done_cb = base::BindOnce(&SharedImageStub::OnDestroySharedImage,
                                 weak_factory_.GetWeakPtr(), mailbox);
   channel_->scheduler()->ScheduleTask(
       gpu::Scheduler::Task(sequence_, std::move(done_cb),
                            std::vector<gpu::SyncToken>({sync_token})));
 }
 
-void SharedImageStub::OnSyncTokenReleased(const Mailbox& mailbox) {
-  factory_->DestroySharedImage(mailbox);
-}
-
 }  // namespace gpu
diff --git a/gpu/ipc/service/shared_image_stub.h b/gpu/ipc/service/shared_image_stub.h
index f719135..e7587b8 100644
--- a/gpu/ipc/service/shared_image_stub.h
+++ b/gpu/ipc/service/shared_image_stub.h
@@ -93,7 +93,6 @@
   bool MakeContextCurrent();
   ContextResult MakeContextCurrentAndCreateFactory();
   void OnError();
-  void OnSyncTokenReleased(const Mailbox& mailbox);
 
   // Wait on the sync token if any and destroy the shared image.
   void DestroySharedImage(const Mailbox& mailbox, const SyncToken& sync_token);
diff --git a/gpu/vulkan/generate_bindings.py b/gpu/vulkan/generate_bindings.py
index 679e6c9..47c2f26 100755
--- a/gpu/vulkan/generate_bindings.py
+++ b/gpu/vulkan/generate_bindings.py
@@ -71,9 +71,15 @@
     ]
   },
   {
+  'min_api_version': 'VK_API_VERSION_1_1',
+    'functions': [
+      'vkGetPhysicalDeviceImageFormatProperties2',
+    ]
+  },
+  {
     # vkGetPhysicalDeviceFeatures2() is defined in Vulkan 1.1 or suffixed in the
     # VK_KHR_get_physical_device_properties2 extension.
-    'min_api_version': 'VK_VERSION_1_1',
+    'min_api_version': 'VK_API_VERSION_1_1',
     'extension': 'VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME',
     'extension_suffix': 'KHR',
     'functions': [
@@ -142,6 +148,12 @@
     ]
   },
   {
+    'min_api_version': 'VK_API_VERSION_1_1',
+    'functions': [
+      'vkGetImageMemoryRequirements2',
+    ]
+  },
+  {
     'ifdef': 'defined(OS_ANDROID)',
     'extension':
         'VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME',
@@ -161,7 +173,8 @@
     'ifdef': 'defined(OS_LINUX)',
     'extension': 'VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME',
     'functions': [
-      'vkGetMemoryFdKHR'
+      'vkGetMemoryFdKHR',
+      'vkGetMemoryFdPropertiesKHR',
     ]
   },
   {
diff --git a/gpu/vulkan/vulkan_function_pointers.cc b/gpu/vulkan/vulkan_function_pointers.cc
index f772a8f..928afb492 100644
--- a/gpu/vulkan/vulkan_function_pointers.cc
+++ b/gpu/vulkan/vulkan_function_pointers.cc
@@ -246,7 +246,19 @@
   }
 #endif  // defined(OS_FUCHSIA)
 
-  if (api_version >= VK_VERSION_1_1) {
+  if (api_version >= VK_API_VERSION_1_1) {
+    vkGetPhysicalDeviceImageFormatProperties2Fn =
+        reinterpret_cast<PFN_vkGetPhysicalDeviceImageFormatProperties2>(
+            vkGetInstanceProcAddrFn(
+                vk_instance, "vkGetPhysicalDeviceImageFormatProperties2"));
+    if (!vkGetPhysicalDeviceImageFormatProperties2Fn) {
+      DLOG(WARNING) << "Failed to bind vulkan entrypoint: "
+                    << "vkGetPhysicalDeviceImageFormatProperties2";
+      return false;
+    }
+  }
+
+  if (api_version >= VK_API_VERSION_1_1) {
     vkGetPhysicalDeviceFeatures2Fn =
         reinterpret_cast<PFN_vkGetPhysicalDeviceFeatures2>(
             vkGetInstanceProcAddrFn(vk_instance,
@@ -715,6 +727,17 @@
     return false;
   }
 
+  if (api_version >= VK_API_VERSION_1_1) {
+    vkGetImageMemoryRequirements2Fn =
+        reinterpret_cast<PFN_vkGetImageMemoryRequirements2>(
+            vkGetDeviceProcAddrFn(vk_device, "vkGetImageMemoryRequirements2"));
+    if (!vkGetImageMemoryRequirements2Fn) {
+      DLOG(WARNING) << "Failed to bind vulkan entrypoint: "
+                    << "vkGetImageMemoryRequirements2";
+      return false;
+    }
+  }
+
 #if defined(OS_ANDROID)
   if (gfx::HasExtension(
           enabled_extensions,
@@ -762,6 +785,15 @@
                     << "vkGetMemoryFdKHR";
       return false;
     }
+
+    vkGetMemoryFdPropertiesKHRFn =
+        reinterpret_cast<PFN_vkGetMemoryFdPropertiesKHR>(
+            vkGetDeviceProcAddrFn(vk_device, "vkGetMemoryFdPropertiesKHR"));
+    if (!vkGetMemoryFdPropertiesKHRFn) {
+      DLOG(WARNING) << "Failed to bind vulkan entrypoint: "
+                    << "vkGetMemoryFdPropertiesKHR";
+      return false;
+    }
   }
 #endif  // defined(OS_LINUX)
 
diff --git a/gpu/vulkan/vulkan_function_pointers.h b/gpu/vulkan/vulkan_function_pointers.h
index f27e00d..95ae21c1 100644
--- a/gpu/vulkan/vulkan_function_pointers.h
+++ b/gpu/vulkan/vulkan_function_pointers.h
@@ -107,6 +107,9 @@
       nullptr;
 #endif  // defined(OS_FUCHSIA)
 
+  PFN_vkGetPhysicalDeviceImageFormatProperties2
+      vkGetPhysicalDeviceImageFormatProperties2Fn = nullptr;
+
   PFN_vkGetPhysicalDeviceFeatures2 vkGetPhysicalDeviceFeatures2Fn = nullptr;
 
   // Device functions
@@ -165,6 +168,8 @@
   PFN_vkUpdateDescriptorSets vkUpdateDescriptorSetsFn = nullptr;
   PFN_vkWaitForFences vkWaitForFencesFn = nullptr;
 
+  PFN_vkGetImageMemoryRequirements2 vkGetImageMemoryRequirements2Fn = nullptr;
+
 #if defined(OS_ANDROID)
   PFN_vkGetAndroidHardwareBufferPropertiesANDROID
       vkGetAndroidHardwareBufferPropertiesANDROIDFn = nullptr;
@@ -177,6 +182,7 @@
 
 #if defined(OS_LINUX)
   PFN_vkGetMemoryFdKHR vkGetMemoryFdKHRFn = nullptr;
+  PFN_vkGetMemoryFdPropertiesKHR vkGetMemoryFdPropertiesKHRFn = nullptr;
 #endif  // defined(OS_LINUX)
 
 #if defined(OS_FUCHSIA)
@@ -261,6 +267,9 @@
   gpu::GetVulkanFunctionPointers()->vkCreateImagePipeSurfaceFUCHSIAFn
 #endif  // defined(OS_FUCHSIA)
 
+#define vkGetPhysicalDeviceImageFormatProperties2 \
+  gpu::GetVulkanFunctionPointers()->vkGetPhysicalDeviceImageFormatProperties2Fn
+
 #define vkGetPhysicalDeviceFeatures2 \
   gpu::GetVulkanFunctionPointers()->vkGetPhysicalDeviceFeatures2Fn
 
@@ -350,6 +359,9 @@
   gpu::GetVulkanFunctionPointers()->vkUpdateDescriptorSetsFn
 #define vkWaitForFences gpu::GetVulkanFunctionPointers()->vkWaitForFencesFn
 
+#define vkGetImageMemoryRequirements2 \
+  gpu::GetVulkanFunctionPointers()->vkGetImageMemoryRequirements2Fn
+
 #if defined(OS_ANDROID)
 #define vkGetAndroidHardwareBufferPropertiesANDROID \
   gpu::GetVulkanFunctionPointers()                  \
@@ -365,6 +377,8 @@
 
 #if defined(OS_LINUX)
 #define vkGetMemoryFdKHR gpu::GetVulkanFunctionPointers()->vkGetMemoryFdKHRFn
+#define vkGetMemoryFdPropertiesKHR \
+  gpu::GetVulkanFunctionPointers()->vkGetMemoryFdPropertiesKHRFn
 #endif  // defined(OS_LINUX)
 
 #if defined(OS_FUCHSIA)
diff --git a/infra/config/cr-buildbucket.cfg b/infra/config/cr-buildbucket.cfg
index 12478c3..3ea9872 100644
--- a/infra/config/cr-buildbucket.cfg
+++ b/infra/config/cr-buildbucket.cfg
@@ -810,9 +810,9 @@
 builder_mixins {
   name: "xcode-caches"
   caches: {
-    # Cache for Xcode 11 (build version 11m392r) needed for iOS builds.
-    name: "xcode_ios_11m392r"
-    path: "xcode_ios_11m392r.app"
+    # Cache for Xcode 11 (build version 11a419c) needed for iOS builds.
+    name: "xcode_ios_11a419c"
+    path: "xcode_ios_11a419c.app"
   }
 }
 
diff --git a/ios/build/bots/chromium.clang/ToTiOS.json b/ios/build/bots/chromium.clang/ToTiOS.json
index 911b727..59457819 100644
--- a/ios/build/bots/chromium.clang/ToTiOS.json
+++ b/ios/build/bots/chromium.clang/ToTiOS.json
@@ -2,7 +2,7 @@
   "comments": [
     "Clang tip-of-tree builder for iOS."
   ],
-  "xcode build version": "11m392r",
+  "xcode build version": "11a419c",
   "gn_args": [
     "ios_enable_code_signing=false",
     "is_component_build=false",
diff --git a/ios/build/bots/chromium.clang/ToTiOSDevice.json b/ios/build/bots/chromium.clang/ToTiOSDevice.json
index b14dca2b..2b73f84 100644
--- a/ios/build/bots/chromium.clang/ToTiOSDevice.json
+++ b/ios/build/bots/chromium.clang/ToTiOSDevice.json
@@ -2,7 +2,7 @@
   "comments": [
     "Clang tip-of-tree builder for iOS device."
   ],
-  "xcode build version": "11m392r",
+  "xcode build version": "11a419c",
   "gn_args": [
     "is_debug=false",
     "llvm_force_head_revision=true",
diff --git a/ios/build/bots/chromium.fyi/ios-device-goma-canary-clobber.json b/ios/build/bots/chromium.fyi/ios-device-goma-canary-clobber.json
index 0f7ed42..f924ec4f 100644
--- a/ios/build/bots/chromium.fyi/ios-device-goma-canary-clobber.json
+++ b/ios/build/bots/chromium.fyi/ios-device-goma-canary-clobber.json
@@ -3,7 +3,7 @@
     "Goma canary builder for iOS.",
     "It is chromium.mac/ios-device.json + use_goma_canary, clobber."
   ],
-  "xcode build version": "11m392r",
+  "xcode build version": "11a419c",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
     "ios_enable_code_signing=false",
diff --git a/ios/build/bots/chromium.fyi/ios-device-goma-latest-clobber.json b/ios/build/bots/chromium.fyi/ios-device-goma-latest-clobber.json
index a9e07d9..ea69174 100644
--- a/ios/build/bots/chromium.fyi/ios-device-goma-latest-clobber.json
+++ b/ios/build/bots/chromium.fyi/ios-device-goma-latest-clobber.json
@@ -3,7 +3,7 @@
     "Goma latest builder for iOS.",
     "It is chromium.mac/ios-device.json + use_goma_canary, clobber."
   ],
-  "xcode build version": "11m392r",
+  "xcode build version": "11a419c",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
     "ios_enable_code_signing=false",
diff --git a/ios/build/bots/chromium.fyi/ios-simulator-cronet.json b/ios/build/bots/chromium.fyi/ios-simulator-cronet.json
index 1a4e588..4c0fa28e 100644
--- a/ios/build/bots/chromium.fyi/ios-simulator-cronet.json
+++ b/ios/build/bots/chromium.fyi/ios-simulator-cronet.json
@@ -3,7 +3,7 @@
     "Cronet tests 64-bit iOS 12 and 13 simulators.",
     "Tests run on iPhone X."
   ],
-  "xcode build version": "11m392r",
+  "xcode build version": "11a419c",
   "gn_args": [
     "additional_target_cpus=[\"x86\"]",
     "disable_brotli_filter=false",
diff --git a/ios/build/bots/chromium.fyi/ios-simulator.json b/ios/build/bots/chromium.fyi/ios-simulator.json
index cf06bfc..953bc3a 100644
--- a/ios/build/bots/chromium.fyi/ios-simulator.json
+++ b/ios/build/bots/chromium.fyi/ios-simulator.json
@@ -2,7 +2,7 @@
   "comments": [
     "Runs tests on FYI on the latest simulators."
   ],
-  "xcode build version": "11m392r",
+  "xcode build version": "11a419c",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
     "is_component_build=false",
diff --git a/ios/build/bots/chromium.fyi/ios12-beta-simulator.json b/ios/build/bots/chromium.fyi/ios12-beta-simulator.json
index 49c56c75..11c021e1 100644
--- a/ios/build/bots/chromium.fyi/ios12-beta-simulator.json
+++ b/ios/build/bots/chromium.fyi/ios12-beta-simulator.json
@@ -3,7 +3,7 @@
     "Run tests on iOS12beta track on 64-bit iOS 12 simulators.",
     "Note: Xcode 11 requires OSX 10.14.3 hence 'host os'"
   ],
-  "xcode build version": "11m392r",
+  "xcode build version": "11a419c",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
     "is_component_build=false",
diff --git a/ios/build/bots/chromium.fyi/ios13-beta-simulator.json b/ios/build/bots/chromium.fyi/ios13-beta-simulator.json
index 46263b38..97b53419 100644
--- a/ios/build/bots/chromium.fyi/ios13-beta-simulator.json
+++ b/ios/build/bots/chromium.fyi/ios13-beta-simulator.json
@@ -3,7 +3,7 @@
     "Run tests on iOS13beta track on 64-bit iOS 13 simulators.",
     "Note: Xcode 11 requires OSX 10.14.4 and up"
   ],
-  "xcode build version": "11m392r",
+  "xcode build version": "11a419c",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
     "is_component_build=false",
@@ -22,7 +22,7 @@
       "include": "eg2_tests.json",
       "device type": "iPhone X",
       "os": "13.0",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "pool":"Chrome",
       "host os": "Mac-10.14.4",
       "optional_dimensions": {
@@ -36,7 +36,7 @@
       "include": "eg2_tests.json",
       "device type": "iPad (6th generation)",
       "os": "13.0",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "pool":"Chrome",
       "host os": "Mac-10.14.4",
       "optional_dimensions": {
@@ -50,7 +50,7 @@
       "include": "eg2_tests.json",
       "device type": "iPhone X",
       "os": "12.2",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "pool":"Chrome",
       "host os": "Mac-10.14.4",
       "optional_dimensions": {
@@ -64,7 +64,7 @@
       "include": "eg2_tests.json",
       "device type": "iPad (6th generation)",
       "os": "12.2",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "pool":"Chrome",
       "host os": "Mac-10.14.4",
       "optional_dimensions": {
@@ -77,7 +77,7 @@
       "include": "common_tests.json",
       "device type": "iPhone X",
       "os": "13.0",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "host os": "Mac-10.14.4",
       "pool":"Chrome",
       "optional_dimensions": {
@@ -90,7 +90,7 @@
       "include": "eg_cq_tests.json",
       "device type": "iPhone X",
       "os": "13.0",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "host os": "Mac-10.14.4",
       "pool":"Chrome",
       "optional_dimensions": {
@@ -103,7 +103,7 @@
       "include": "eg_cq_tests.json",
       "device type": "iPad Pro (12.9-inch)",
       "os": "13.0",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "host os": "Mac-10.14.4",
       "pool":"Chrome",
       "optional_dimensions": {
@@ -116,7 +116,7 @@
       "include": "eg_tests.json",
       "device type": "iPhone X",
       "os": "13.0",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "host os": "Mac-10.14.4",
       "pool":"Chrome",
       "optional_dimensions": {
@@ -129,7 +129,7 @@
       "include": "eg_tests.json",
       "device type": "iPad Air (3rd generation)",
       "os": "13.0",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "host os": "Mac-10.14.4",
       "pool":"Chrome",
       "optional_dimensions": {
@@ -142,7 +142,7 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone 6s Plus",
       "os": "13.0",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "host os": "Mac-10.14.4",
       "pool":"Chrome",
       "optional_dimensions": {
@@ -155,7 +155,7 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone X",
       "os": "13.0",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "host os": "Mac-10.14.4",
       "pool":"Chrome",
       "optional_dimensions": {
@@ -168,7 +168,7 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPad Air 2",
       "os": "13.0",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "host os": "Mac-10.14.4",
       "pool":"Chrome",
       "optional_dimensions": {
diff --git a/ios/build/bots/chromium.fyi/ios13-sdk-device.json b/ios/build/bots/chromium.fyi/ios13-sdk-device.json
index 5a62879..2f2ac7d 100644
--- a/ios/build/bots/chromium.fyi/ios13-sdk-device.json
+++ b/ios/build/bots/chromium.fyi/ios13-sdk-device.json
@@ -3,7 +3,7 @@
     "Builder for Xcode 11 iOS 13 SDK",
     "Build is performed with gn+ninja."
   ],
-  "xcode build version": "11m392r",
+  "xcode build version": "11a419c",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
     "ios_enable_code_signing=false",
diff --git a/ios/build/bots/chromium.fyi/ios13-sdk-simulator.json b/ios/build/bots/chromium.fyi/ios13-sdk-simulator.json
index 13fb004..574b3ac 100644
--- a/ios/build/bots/chromium.fyi/ios13-sdk-simulator.json
+++ b/ios/build/bots/chromium.fyi/ios13-sdk-simulator.json
@@ -2,7 +2,7 @@
   "comments": [
     "Runs tests on 64-bit iOS 11.4 and 12.2 and 13.0 tests"
   ],
-  "xcode build version": "11m392r",
+  "xcode build version": "11a419c",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
     "is_component_build=false",
diff --git a/ios/build/bots/chromium.mac/ios-simulator-cronet.json b/ios/build/bots/chromium.mac/ios-simulator-cronet.json
index e60f6110..b0123b3 100644
--- a/ios/build/bots/chromium.mac/ios-simulator-cronet.json
+++ b/ios/build/bots/chromium.mac/ios-simulator-cronet.json
@@ -2,7 +2,7 @@
   "comments": [
     "Cronet tests 64-bit iOS 12 and 13 simulators."
   ],
-  "xcode build version": "11m392r",
+  "xcode build version": "11a419c",
   "gn_args": [
     "additional_target_cpus=[\"x86\"]",
     "disable_brotli_filter=false",
diff --git a/ios/build/bots/chromium.mac/ios-simulator-full-configs.json b/ios/build/bots/chromium.mac/ios-simulator-full-configs.json
index 0dd3fc43..6d41796 100644
--- a/ios/build/bots/chromium.mac/ios-simulator-full-configs.json
+++ b/ios/build/bots/chromium.mac/ios-simulator-full-configs.json
@@ -3,7 +3,7 @@
     "Runs tests on 64-bit iOS 11 and 12 tests on iPad, iPhone,",
     "@3x, and @2x on main waterfall ios-simulator-full-configs."
   ],
-  "xcode build version": "11m392r",
+  "xcode build version": "11a419c",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
     "is_component_build=false",
diff --git a/ios/build/bots/chromium.mac/ios-simulator-xcode-clang.json b/ios/build/bots/chromium.mac/ios-simulator-xcode-clang.json
index 96eee82..d8a84b0a 100644
--- a/ios/build/bots/chromium.mac/ios-simulator-xcode-clang.json
+++ b/ios/build/bots/chromium.mac/ios-simulator-xcode-clang.json
@@ -4,7 +4,7 @@
     "This 'xcode build version' must exist in GOMA",
     "Build is performed with gn+ninja."
   ],
-  "xcode build version": "11m392r",
+  "xcode build version": "11a419c",
   "use xcode build version": true,
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
diff --git a/ios/build/bots/chromium.mac/ios-simulator.json b/ios/build/bots/chromium.mac/ios-simulator.json
index 420ab11..188d0bf9 100644
--- a/ios/build/bots/chromium.mac/ios-simulator.json
+++ b/ios/build/bots/chromium.mac/ios-simulator.json
@@ -4,7 +4,7 @@
     "main and CQ ios-simulator.",
     "Note: Xcode 10 requires Mac OS 10.13.4 or higher, hence 'host os'."
   ],
-  "xcode build version": "11m392r",
+  "xcode build version": "11a419c",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
     "is_component_build=false",
diff --git a/ios/build/bots/chromium.mac/ios-slimnav.json b/ios/build/bots/chromium.mac/ios-slimnav.json
index 79d9c66d..2e4333c 100644
--- a/ios/build/bots/chromium.mac/ios-slimnav.json
+++ b/ios/build/bots/chromium.mac/ios-slimnav.json
@@ -2,7 +2,7 @@
   "comments": [
     "Test the SlimNavigationManager feature."
   ],
-  "xcode build version": "11m392r",
+  "xcode build version": "11a419c",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
     "is_component_build=false",
diff --git a/ios/build/bots/chromium.mac/ios13-beta-simulator.json b/ios/build/bots/chromium.mac/ios13-beta-simulator.json
index f9843de..45a79d7 100644
--- a/ios/build/bots/chromium.mac/ios13-beta-simulator.json
+++ b/ios/build/bots/chromium.mac/ios13-beta-simulator.json
@@ -5,7 +5,7 @@
     "Note: This file exists only to support the trybot.",
     "It should be kept in sync with the CI configuration in ../chromium.fyi/."
   ],
-  "xcode build version": "11m392r",
+  "xcode build version": "11a419c",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
     "is_component_build=false",
@@ -24,7 +24,7 @@
       "include": "eg2_tests.json",
       "device type": "iPhone X",
       "os": "13.0",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "pool":"Chrome",
       "host os": "Mac-10.14.4",
       "optional_dimensions": {
@@ -38,7 +38,7 @@
       "include": "eg2_tests.json",
       "device type": "iPad (6th generation)",
       "os": "13.0",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "pool":"Chrome",
       "host os": "Mac-10.14.4",
       "optional_dimensions": {
@@ -52,7 +52,7 @@
       "include": "eg2_tests.json",
       "device type": "iPhone X",
       "os": "12.2",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "pool":"Chrome",
       "host os": "Mac-10.14.4",
       "optional_dimensions": {
@@ -66,7 +66,7 @@
       "include": "eg2_tests.json",
       "device type": "iPad (6th generation)",
       "os": "12.2",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "pool":"Chrome",
       "host os": "Mac-10.14.4",
       "optional_dimensions": {
@@ -79,7 +79,7 @@
       "include": "common_tests.json",
       "device type": "iPhone X",
       "os": "13.0",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "host os": "Mac-10.14.4",
       "pool":"Chrome",
       "optional_dimensions": {
@@ -92,7 +92,7 @@
       "include": "eg_cq_tests.json",
       "device type": "iPhone X",
       "os": "13.0",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "host os": "Mac-10.14.4",
       "pool":"Chrome",
       "optional_dimensions": {
@@ -105,7 +105,7 @@
       "include": "eg_cq_tests.json",
       "device type": "iPad Pro (12.9-inch)",
       "os": "13.0",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "host os": "Mac-10.14.4",
       "pool":"Chrome",
       "optional_dimensions": {
@@ -118,7 +118,7 @@
       "include": "eg_tests.json",
       "device type": "iPhone X",
       "os": "13.0",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "host os": "Mac-10.14.4",
       "pool":"Chrome",
       "optional_dimensions": {
@@ -131,7 +131,7 @@
       "include": "eg_tests.json",
       "device type": "iPad Air (3rd generation)",
       "os": "13.0",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "host os": "Mac-10.14.4",
       "pool":"Chrome",
       "optional_dimensions": {
@@ -144,7 +144,7 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone 6s Plus",
       "os": "13.0",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "host os": "Mac-10.14.4",
       "pool":"Chrome",
       "optional_dimensions": {
@@ -157,7 +157,7 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPhone X",
       "os": "13.0",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "host os": "Mac-10.14.4",
       "pool":"Chrome",
       "optional_dimensions": {
@@ -170,7 +170,7 @@
       "include": "screen_size_dependent_tests.json",
       "device type": "iPad Air 2",
       "os": "13.0",
-      "xcode build version": "11m392r",
+      "xcode build version": "11a419c",
       "host os": "Mac-10.14.4",
       "pool":"Chrome",
       "optional_dimensions": {
diff --git a/ios/build/bots/chromium.mac/ios13-sdk-simulator.json b/ios/build/bots/chromium.mac/ios13-sdk-simulator.json
index bfad9e84..9ab9ef3 100644
--- a/ios/build/bots/chromium.mac/ios13-sdk-simulator.json
+++ b/ios/build/bots/chromium.mac/ios13-sdk-simulator.json
@@ -5,7 +5,7 @@
     "Note: This file exists only to support the trybot.",
     "It should be kept in sync with the CI configuration in ../chromium.fyi/."
   ],
-  "xcode build version": "11m392r",
+  "xcode build version": "11a419c",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
     "is_component_build=false",
diff --git a/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-device.json b/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-device.json
index 3c61d7f1..79e6d21 100644
--- a/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-device.json
+++ b/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-device.json
@@ -3,7 +3,7 @@
     "Builder for 64-bit devices.",
     "Build is performed with gn+ninja."
   ],
-  "xcode build version": "11m392r",
+  "xcode build version": "11a419c",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
     "ios_enable_code_signing=false",
diff --git a/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json b/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json
index 3f5db0d..7a3cb59 100644
--- a/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json
+++ b/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json
@@ -2,7 +2,7 @@
   "comments": [
     "Runs tests on @3x, @2x, 64-bit phone, tablet, iOS 11."
   ],
-  "xcode build version": "11m392r",
+  "xcode build version": "11a419c",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
     "ios_enable_code_signing=false",
diff --git a/ios/chrome/app/chrome_overlay_window.mm b/ios/chrome/app/chrome_overlay_window.mm
index e79c7fd..d1d7ea0 100644
--- a/ios/chrome/app/chrome_overlay_window.mm
+++ b/ios/chrome/app/chrome_overlay_window.mm
@@ -1,4 +1,4 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2019 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -8,6 +8,7 @@
 #import "ios/chrome/browser/crash_report/breakpad_helper.h"
 #import "ios/chrome/browser/metrics/drag_and_drop_recorder.h"
 #import "ios/chrome/browser/metrics/size_class_recorder.h"
+#import "ios/chrome/browser/metrics/user_interface_style_recorder.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/ui/util/ui_util.h"
 
@@ -15,10 +16,12 @@
 #error "This file requires ARC support."
 #endif
 
-@interface ChromeOverlayWindow () {
-  SizeClassRecorder* _sizeClassRecorder;
-  DragAndDropRecorder* _dragAndDropRecorder;
-}
+@interface ChromeOverlayWindow ()
+@property(nonatomic, strong)
+    UserInterfaceStyleRecorder* userInterfaceStyleRecorder API_AVAILABLE(
+        ios(13.0));
+@property(nonatomic, strong) SizeClassRecorder* sizeClassRecorder;
+@property(nonatomic, strong) DragAndDropRecorder* dragAndDropRecorder;
 
 // Initializes the size class recorder. On iPad It starts tracking horizontal
 // size class changes.
@@ -38,6 +41,10 @@
     [self initializeSizeClassRecorder];
     [self updateBreakpad];
     _dragAndDropRecorder = [[DragAndDropRecorder alloc] initWithView:self];
+    if (@available(iOS 13, *)) {
+      _userInterfaceStyleRecorder = [[UserInterfaceStyleRecorder alloc]
+          initWithUserInterfaceStyle:self.traitCollection.userInterfaceStyle];
+    }
   }
   return self;
 }
@@ -73,6 +80,14 @@
         horizontalSizeClassDidChange:self.traitCollection.horizontalSizeClass];
     [self updateBreakpad];
   }
+  if (@available(iOS 13, *)) {
+    if ([self.traitCollection
+            hasDifferentColorAppearanceComparedToTraitCollection:
+                previousTraitCollection]) {
+      [self.userInterfaceStyleRecorder
+          userInterfaceStyleDidChange:self.traitCollection.userInterfaceStyle];
+    }
+  }
 }
 
 #pragma mark - Testing methods
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm
index 626a062..d98c659a 100644
--- a/ios/chrome/app/main_controller.mm
+++ b/ios/chrome/app/main_controller.mm
@@ -2153,10 +2153,18 @@
   // It is however unnecessary for off-the-record BrowserState (as the code
   // is not invoked) and has undesired side-effect (cause all regular tabs
   // to reload, see http://crbug.com/821753 for details).
-
-  const BOOL disableWebUsageDuringRemoval =
+  BOOL disableWebUsageDuringRemoval =
       !browserState->IsOffTheRecord() &&
       IsRemoveDataMaskSet(removeMask, BrowsingDataRemoveMask::REMOVE_SITE_DATA);
+  BOOL showActivityIndicator = NO;
+
+  if (@available(iOS 13, *)) {
+    // TODO(crbug.com/632772): Visited links don't clearing doesn't require
+    // disabling web usage with iOS 13. Stop disabling web usage once iOS 12
+    // is not supported.
+    showActivityIndicator = disableWebUsageDuringRemoval;
+    disableWebUsageDuringRemoval = NO;
+  }
 
   ProceduralBlock removeBrowsingDataBlock = ^{
     if (disableWebUsageDuringRemoval) {
@@ -2165,6 +2173,10 @@
       DCHECK([NSThread isMainThread]);
       self.interfaceProvider.mainInterface.userInteractionEnabled = NO;
       self.interfaceProvider.incognitoInterface.userInteractionEnabled = NO;
+    } else if (showActivityIndicator) {
+      // Show activity overlay so users know that clear browsing data is in
+      // progress.
+      [self.mainBVC.dispatcher showActivityOverlay:YES];
     }
 
     BrowsingDataRemoverFactory::GetForBrowserState(browserState)
@@ -2172,6 +2184,16 @@
                    // Activates browsing and enables web views.
                    // Must be called only on the main thread.
                    DCHECK([NSThread isMainThread]);
+                   if (showActivityIndicator) {
+                     // User interaction still needs to be disabled as a way to
+                     // force reload all the web states and to reset NTPs.
+                     self.interfaceProvider.mainInterface
+                         .userInteractionEnabled = NO;
+                     self.interfaceProvider.incognitoInterface
+                         .userInteractionEnabled = NO;
+
+                     [self.mainBVC.dispatcher showActivityOverlay:NO];
+                   }
                    self.interfaceProvider.mainInterface.userInteractionEnabled =
                        YES;
                    self.interfaceProvider.incognitoInterface
diff --git a/ios/chrome/browser/autofill/automation/automation_action_egtest.mm b/ios/chrome/browser/autofill/automation/automation_action_egtest.mm
index 678e49ec..2822d59c 100644
--- a/ios/chrome/browser/autofill/automation/automation_action_egtest.mm
+++ b/ios/chrome/browser/autofill/automation/automation_action_egtest.mm
@@ -70,7 +70,7 @@
   base::DictionaryValue waitForDict = base::DictionaryValue();
   waitForDict.SetKey("type", base::Value("waitFor"));
   base::Value assertions = base::Value(base::Value::Type::LIST);
-  assertions.GetList().emplace_back(base::Value(
+  assertions.Append(base::Value(
       "return document.getElementsByName(\"name_address\")[0].value == \"Jane "
       "Smith\";"));
   waitForDict.SetKey("assertions", std::move(assertions));
diff --git a/ios/chrome/browser/metrics/BUILD.gn b/ios/chrome/browser/metrics/BUILD.gn
index 9ac211bd..d457830 100644
--- a/ios/chrome/browser/metrics/BUILD.gn
+++ b/ios/chrome/browser/metrics/BUILD.gn
@@ -166,6 +166,8 @@
     "size_class_recorder_private.h",
     "tab_usage_recorder.h",
     "tab_usage_recorder.mm",
+    "user_interface_style_recorder.h",
+    "user_interface_style_recorder.mm",
   ]
   deps = [
     ":metrics",
diff --git a/ios/chrome/browser/metrics/user_interface_style_recorder.h b/ios/chrome/browser/metrics/user_interface_style_recorder.h
new file mode 100644
index 0000000..1accf692
--- /dev/null
+++ b/ios/chrome/browser/metrics/user_interface_style_recorder.h
@@ -0,0 +1,24 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_METRICS_USER_INTERFACE_STYLE_RECORDER_H_
+#define IOS_CHROME_BROWSER_METRICS_USER_INTERFACE_STYLE_RECORDER_H_
+
+#import <UIKit/UIKit.h>
+
+// Reports metrics for the user interface style on iOS 13+.
+API_AVAILABLE(ios(13.0))
+@interface UserInterfaceStyleRecorder : NSObject
+
+- (instancetype)initWithUserInterfaceStyle:(UIUserInterfaceStyle)style
+    NS_DESIGNATED_INITIALIZER;
+
+- (instancetype)init NS_UNAVAILABLE;
+
+// Call this method to report the new user interface to UMA.
+- (void)userInterfaceStyleDidChange:(UIUserInterfaceStyle)newUserInterfaceStyle;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_METRICS_USER_INTERFACE_STYLE_RECORDER_H_
diff --git a/ios/chrome/browser/metrics/user_interface_style_recorder.mm b/ios/chrome/browser/metrics/user_interface_style_recorder.mm
new file mode 100644
index 0000000..6ffebd8
--- /dev/null
+++ b/ios/chrome/browser/metrics/user_interface_style_recorder.mm
@@ -0,0 +1,126 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/metrics/user_interface_style_recorder.h"
+
+#include "base/logging.h"
+#include "base/metrics/histogram_functions.h"
+#import "ios/chrome/browser/ui/util/ui_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+
+// Interface Style enum to report UMA metrics. Must be in sync with
+// iOSInterfaceStyleForReporting in tools/metrics/histograms/enums.xml.
+enum class InterfaceStyleForReporting {
+  kUnspecified,
+  kLight,
+  kDark,
+  kMaxValue = kDark
+};
+
+// Converts a UIKit interface style to a interface style for reporting.
+InterfaceStyleForReporting InterfaceStyleForReportingForUIUserInterfaceStyle(
+    UIUserInterfaceStyle userInterfaceStyle) {
+  switch (userInterfaceStyle) {
+    case UIUserInterfaceStyleUnspecified:
+      return InterfaceStyleForReporting::kUnspecified;
+    case UIUserInterfaceStyleLight:
+      return InterfaceStyleForReporting::kLight;
+    case UIUserInterfaceStyleDark:
+      return InterfaceStyleForReporting::kDark;
+  }
+}
+
+// Reports the currently used interface style.
+void ReportUserInterfaceStyleUsed(UIUserInterfaceStyle userInterfaceStyle) {
+  InterfaceStyleForReporting userInterfaceStyleForReporting =
+      InterfaceStyleForReportingForUIUserInterfaceStyle(userInterfaceStyle);
+  base::UmaHistogramEnumeration("UserInterfaceStyle.CurrentlyUsed",
+                                userInterfaceStyleForReporting);
+}
+
+// Reports the interface style changed while Chrome is active.
+void ReportUserInterfaceStyleChangedWhileActive(
+    UIUserInterfaceStyle userInterfaceStyle) {
+  InterfaceStyleForReporting userInterfaceStyleForReporting =
+      InterfaceStyleForReportingForUIUserInterfaceStyle(userInterfaceStyle);
+  base::UmaHistogramEnumeration("UserInterfaceStyle.ChangedWhileActive",
+                                userInterfaceStyleForReporting);
+}
+
+}  // namespace
+
+@interface UserInterfaceStyleRecorder ()
+@property(nonatomic, assign) BOOL applicationInBackground;
+@property(nonatomic, assign) UIUserInterfaceStyle initialUserInterfaceStyle;
+@end
+
+@implementation UserInterfaceStyleRecorder
+
+- (instancetype)initWithUserInterfaceStyle:
+    (UIUserInterfaceStyle)userInterfaceStyle {
+  self = [super init];
+  if (self) {
+    // Store the initial user interface for reporting after the application did
+    // become active. Otherwise, if this initializer is called before the
+    // metrics service is started, reporting metrics will fail for the entire
+    // session.
+    _initialUserInterfaceStyle = userInterfaceStyle;
+    [[NSNotificationCenter defaultCenter]
+        addObserver:self
+           selector:@selector(applicationDidBecomeActive:)
+               name:UIApplicationDidBecomeActiveNotification
+             object:nil];
+    [[NSNotificationCenter defaultCenter]
+        addObserver:self
+           selector:@selector(applicationDidEnterBackground:)
+               name:UIApplicationDidEnterBackgroundNotification
+             object:nil];
+    [[NSNotificationCenter defaultCenter]
+        addObserver:self
+           selector:@selector(applicationWillEnterForeground:)
+               name:UIApplicationWillEnterForegroundNotification
+             object:nil];
+  }
+  return self;
+}
+
+- (void)userInterfaceStyleDidChange:
+    (UIUserInterfaceStyle)newUserInterfaceStyle {
+  // Record the new user interface style.
+  ReportUserInterfaceStyleUsed(newUserInterfaceStyle);
+
+  // Record if changed while in foreground.
+  if (!self.applicationInBackground) {
+    ReportUserInterfaceStyleChangedWhileActive(newUserInterfaceStyle);
+  }
+}
+
+#pragma mark - Application state notifications handlers
+
+- (void)applicationDidBecomeActive:(NSNotification*)notification {
+  // This is only needed to report the initial user interface. Deregister from
+  // this notification on the first time it is received.
+  [[NSNotificationCenter defaultCenter]
+      removeObserver:self
+                name:UIApplicationDidBecomeActiveNotification
+              object:nil];
+  ReportUserInterfaceStyleUsed(self.initialUserInterfaceStyle);
+  // For good measure, set the initial interface to unspecified.
+  self.initialUserInterfaceStyle = UIUserInterfaceStyleUnspecified;
+}
+
+- (void)applicationDidEnterBackground:(NSNotification*)notification {
+  self.applicationInBackground = YES;
+}
+
+- (void)applicationWillEnterForeground:(NSNotification*)notification {
+  self.applicationInBackground = NO;
+}
+
+@end
diff --git a/ios/chrome/browser/passwords/credential_manager_util_unittest.cc b/ios/chrome/browser/passwords/credential_manager_util_unittest.cc
index f4f17f23..afc8728 100644
--- a/ios/chrome/browser/passwords/credential_manager_util_unittest.cc
+++ b/ios/chrome/browser/passwords/credential_manager_util_unittest.cc
@@ -232,8 +232,8 @@
   // Build example valid |providers| list.
   std::unique_ptr<base::ListValue> list_ptr =
       std::make_unique<base::ListValue>();
-  list_ptr->GetList().emplace_back(kTestWebOrigin);
-  list_ptr->GetList().emplace_back("https://google.com");
+  list_ptr->Append(kTestWebOrigin);
+  list_ptr->Append("https://google.com");
   json.SetList(kCredentialRequestProvidersKey, std::move(list_ptr));
   std::vector<GURL> federations;
 
@@ -244,8 +244,8 @@
 
   // ParseFederations should skip invalid URLs.
   list_ptr = std::make_unique<base::ListValue>();
-  list_ptr->GetList().emplace_back(kTestWebOrigin);
-  list_ptr->GetList().emplace_back("not a valid url");
+  list_ptr->Append(kTestWebOrigin);
+  list_ptr->Append("not a valid url");
   json.SetList(kCredentialRequestProvidersKey, std::move(list_ptr));
   EXPECT_TRUE(ParseFederations(json, &federations));
   EXPECT_THAT(federations, testing::ElementsAre(GURL(kTestWebOrigin)));
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h
index 31d4bac9..3632981 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h
+++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.h
@@ -100,6 +100,7 @@
   bool IsMainFrameSecure() const override;
   PrefService* GetPrefs() const override;
   password_manager::PasswordStore* GetProfilePasswordStore() const override;
+  password_manager::PasswordStore* GetAccountPasswordStore() const override;
   void NotifyUserAutoSignin(
       std::vector<std::unique_ptr<autofill::PasswordForm>> local_forms,
       const GURL& origin) override;
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm
index 7d065ef..a173b710 100644
--- a/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm
+++ b/ios/chrome/browser/passwords/ios_chrome_password_manager_client.mm
@@ -161,6 +161,11 @@
       .get();
 }
 
+PasswordStore* IOSChromePasswordManagerClient::GetAccountPasswordStore() const {
+  // AccountPasswordStore is currenly not supported on iOS.
+  return nullptr;
+}
+
 void IOSChromePasswordManagerClient::NotifyUserAutoSignin(
     std::vector<std::unique_ptr<autofill::PasswordForm>> local_forms,
     const GURL& origin) {
diff --git a/ios/chrome/browser/payments/ios_payment_instrument_launcher.mm b/ios/chrome/browser/payments/ios_payment_instrument_launcher.mm
index 6a29a78..47d6215 100644
--- a/ios/chrome/browser/payments/ios_payment_instrument_launcher.mm
+++ b/ios/chrome/browser/payments/ios_payment_instrument_launcher.mm
@@ -78,7 +78,7 @@
   // implementation.
   base::Value method_names(base::Value::Type::LIST);
   for (auto const& pair : payment_request->stringified_method_data())
-    method_names.GetList().emplace_back(pair.first);
+    method_names.Append(pair.first);
 
   base::Value params_to_payment_app(base::Value::Type::DICTIONARY);
   params_to_payment_app.SetKey(kMethodNames, std::move(method_names));
@@ -188,7 +188,7 @@
       // We insert the stringified data, not the JSON object and only if the
       // corresponding JSON object is valid.
       if (base::JSONReader::Read(data_it))
-        data_list.GetList().emplace_back(data_it);
+        data_list.Append(data_it);
     }
     method_data.SetKey(map_it.first, std::move(data_list));
   }
@@ -216,11 +216,11 @@
     base::Value byte_array(base::Value::Type::LIST);
     byte_array.GetList().reserve(cert_string.size());
     for (const char byte : cert_string)
-      byte_array.GetList().emplace_back(byte);
+      byte_array.Append(byte);
 
     base::Value cert_chain_dict(base::Value::Type::DICTIONARY);
     cert_chain_dict.SetKey(kCertificate, std::move(byte_array));
-    cert_chain_list.GetList().push_back(std::move(cert_chain_dict));
+    cert_chain_list.Append(std::move(cert_chain_dict));
   }
 
   return cert_chain_list;
@@ -231,7 +231,7 @@
   base::Value modifiers(base::Value::Type::LIST);
   size_t numModifiers = details.modifiers.size();
   for (size_t i = 0; i < numModifiers; ++i) {
-    modifiers.GetList().push_back(base::Value::FromUniquePtrValue(
+    modifiers.Append(base::Value::FromUniquePtrValue(
         details.modifiers[i].ToDictionaryValue()));
   }
   return modifiers;
diff --git a/ios/chrome/browser/payments/ios_payment_instrument_launcher_unittest.mm b/ios/chrome/browser/payments/ios_payment_instrument_launcher_unittest.mm
index b7347a0..96fbc3c 100644
--- a/ios/chrome/browser/payments/ios_payment_instrument_launcher_unittest.mm
+++ b/ios/chrome/browser/payments/ios_payment_instrument_launcher_unittest.mm
@@ -153,7 +153,7 @@
   std::string jef_stringified_data;
   base::JSONWriter::Write(jef_data, &jef_stringified_data);
   base::Value jef_data_list(base::Value::Type::LIST);
-  jef_data_list.GetList().emplace_back(jef_stringified_data);
+  jef_data_list.Append(jef_stringified_data);
 
   // Bob data...
   base::Value bob_data(base::Value::Type::DICTIONARY);
@@ -161,7 +161,7 @@
   std::string bob_stringified_data;
   base::JSONWriter::Write(bob_data, &bob_stringified_data);
   base::Value bob_data_list(base::Value::Type::LIST);
-  bob_data_list.GetList().emplace_back(bob_stringified_data);
+  bob_data_list.Append(bob_stringified_data);
 
   // Alice data...
   base::Value alice_data_list(base::Value::Type::LIST);
diff --git a/ios/chrome/browser/sync/sync_setup_service.cc b/ios/chrome/browser/sync/sync_setup_service.cc
index 012a507..68c83f80 100644
--- a/ios/chrome/browser/sync/sync_setup_service.cc
+++ b/ios/chrome/browser/sync/sync_setup_service.cc
@@ -174,13 +174,14 @@
     sync_blocker_ = sync_service_->GetSetupInProgressHandle();
 }
 
-void SyncSetupService::SetFirstSetupComplete() {
+void SyncSetupService::SetFirstSetupComplete(
+    syncer::SyncFirstSetupCompleteSource source) {
   DCHECK(unified_consent::IsUnifiedConsentFeatureEnabled());
   DCHECK(sync_blocker_);
   // Turn on the sync setup completed flag only if the user did not turn sync
   // off.
   if (sync_service_->CanSyncFeatureStart()) {
-    sync_service_->GetUserSettings()->SetFirstSetupComplete();
+    sync_service_->GetUserSettings()->SetFirstSetupComplete(source);
   }
 }
 
@@ -195,7 +196,8 @@
   if (sync_service_->IsSetupInProgress() &&
       !sync_service_->GetUserSettings()->IsFirstSetupComplete() &&
       sync_service_->CanSyncFeatureStart()) {
-    sync_service_->GetUserSettings()->SetFirstSetupComplete();
+    sync_service_->GetUserSettings()->SetFirstSetupComplete(
+        syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
   }
 
   sync_blocker_.reset();
diff --git a/ios/chrome/browser/sync/sync_setup_service.h b/ios/chrome/browser/sync/sync_setup_service.h
index 18c2204e..03cbe31 100644
--- a/ios/chrome/browser/sync/sync_setup_service.h
+++ b/ios/chrome/browser/sync/sync_setup_service.h
@@ -10,6 +10,7 @@
 #include "base/macros.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/sync/base/model_type.h"
+#include "components/sync/driver/sync_user_settings.h"
 
 namespace syncer {
 class SyncService;
@@ -99,7 +100,7 @@
   // changes. PrepareForFirstSyncSetup() needs to be called before. This flag is
   // not set if the user didn't turn on sync.
   // This method should only be used with UnifiedConsent flag.
-  void SetFirstSetupComplete();
+  void SetFirstSetupComplete(syncer::SyncFirstSetupCompleteSource source);
 
   // Returns true if the user finished the Sync setup flow.
   bool IsFirstSetupComplete() const;
diff --git a/ios/chrome/browser/ui/authentication/BUILD.gn b/ios/chrome/browser/ui/authentication/BUILD.gn
index 60c2509..0bd4dcc 100644
--- a/ios/chrome/browser/ui/authentication/BUILD.gn
+++ b/ios/chrome/browser/ui/authentication/BUILD.gn
@@ -164,7 +164,9 @@
     "//ios/chrome/browser/ui/authentication/cells",
     "//ios/chrome/browser/ui/authentication/unified_consent:unified_consent_ui",
     "//ios/chrome/browser/ui/authentication/unified_consent/identity_chooser:identity_chooser_ui",
+    "//ios/chrome/browser/ui/signin_interaction:eg_test_support",
     "//ios/chrome/browser/ui/util",
+    "//ios/chrome/test:eg_test_support",
     "//ios/chrome/test/app:test_support",
     "//ios/chrome/test/earl_grey:test_support",
     "//ios/public/provider/chrome/browser/signin",
diff --git a/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.mm b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.mm
index 23273da..d303ad8 100644
--- a/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.mm
+++ b/ios/chrome/browser/ui/authentication/chrome_signin_view_controller.mm
@@ -300,7 +300,8 @@
     // to start Sync.
     SyncSetupService* syncSetupService =
         SyncSetupServiceFactory::GetForBrowserState(_browserState);
-    syncSetupService->SetFirstSetupComplete();
+    syncSetupService->SetFirstSetupComplete(
+        syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
     syncSetupService->CommitSyncChanges();
   }
   [self acceptSignInAndShowAccountsSettings:_unifiedConsentCoordinator
diff --git a/ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h b/ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h
index 9b6d3c9..66e9cde 100644
--- a/ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h
+++ b/ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h
@@ -14,9 +14,15 @@
 // Methods used for the EarlGrey tests, related to UI.
 @interface SigninEarlGreyUI : NSObject
 
-// Adds the identity (if not already added), and perform a sign-in.
+// Calls [SigninEarlGreyUI signinWithIdentity:identity isManagedAccount:NO].
 + (void)signinWithIdentity:(ChromeIdentity*)identity;
 
+// Adds the identity (if not already added), and perform a sign-in. if
+// |isManagedAccount| is true, |identity| needs to be a managed account and the
+// managed dialog is expected while signing in.
++ (void)signinWithIdentity:(ChromeIdentity*)identity
+          isManagedAccount:(BOOL)isManagedAccount;
+
 // Taps on the settings link in the sign-in view. The sign-in view has to be
 // opened before calling this method.
 + (void)tapSettingsLink;
@@ -25,6 +31,9 @@
 // is confirmed, but it doesn't validated the user consent page.
 + (void)selectIdentityWithEmail:(NSString*)userEmail;
 
+// Confirms the managed account dialog with signing in.
++ (void)confirmSigninWithManagedAccount;
+
 // Confirms the sign in confirmation page, scrolls first to make the OK button
 // visible on short devices (e.g. iPhone 5s).
 + (void)confirmSigninConfirmationDialog;
diff --git a/ios/chrome/browser/ui/authentication/signin_earl_grey_ui.mm b/ios/chrome/browser/ui/authentication/signin_earl_grey_ui.mm
index 00b312f..6fcc939 100644
--- a/ios/chrome/browser/ui/authentication/signin_earl_grey_ui.mm
+++ b/ios/chrome/browser/ui/authentication/signin_earl_grey_ui.mm
@@ -11,11 +11,13 @@
 #import "ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_cell.h"
 #import "ios/chrome/browser/ui/authentication/unified_consent/identity_picker_view.h"
 #import "ios/chrome/browser/ui/authentication/unified_consent/unified_consent_view_controller.h"
+#import "ios/chrome/browser/ui/signin_interaction/signin_interaction_controller_egtest_util.h"
 #import "ios/chrome/browser/ui/util/transparent_link_button.h"
 #include "ios/chrome/grit/ios_strings.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers_app_interface.h"
+#import "ios/chrome/test/scoped_eg_synchronization_disabler.h"
 #import "ios/public/provider/chrome/browser/signin/chrome_identity.h"
 #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h"
 
@@ -56,6 +58,11 @@
 @implementation SigninEarlGreyUI
 
 + (void)signinWithIdentity:(ChromeIdentity*)identity {
+  [self signinWithIdentity:(ChromeIdentity*)identity isManagedAccount:NO];
+}
+
++ (void)signinWithIdentity:(ChromeIdentity*)identity
+          isManagedAccount:(BOOL)isManagedAccount {
   ios::FakeChromeIdentityService::GetInstanceFromChromeProvider()->AddIdentity(
       identity);
 
@@ -64,6 +71,9 @@
       tapSettingsMenuButton:chrome_test_util::SecondarySignInButton()];
   [self selectIdentityWithEmail:identity.userEmail];
   [self confirmSigninConfirmationDialog];
+  if (isManagedAccount) {
+    [self confirmSigninWithManagedAccount];
+  }
   [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
       performAction:grey_tap()];
   [SigninEarlGreyUtils checkSignedInWithIdentity:identity];
@@ -90,6 +100,17 @@
       performAction:grey_tap()];
 }
 
++ (void)confirmSigninWithManagedAccount {
+  // Synchronization off due to an infinite spinner, in the user consent view,
+  // under the managed consent dialog. This spinner is started by the sign-in
+  // process.
+  ScopedSynchronizationDisabler disabler;
+  id<GREYMatcher> acceptButton = [ChromeMatchersAppInterface
+      buttonWithAccessibilityLabelID:IDS_IOS_MANAGED_SIGNIN_ACCEPT_BUTTON];
+  WaitForMatcher(acceptButton);
+  [[EarlGrey selectElementWithMatcher:acceptButton] performAction:grey_tap()];
+}
+
 + (void)confirmSigninConfirmationDialog {
   // To confirm the dialog, the scroll view content has to be scrolled to the
   // bottom to transform "MORE" button into the validation button.
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
index a193031..92e844e 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -1236,14 +1236,7 @@
   // prevent interaction with the web page.
   // TODO(crbug.com/637093): This coordinator should be managed by the
   // coordinator used to present BrowserViewController, when implemented.
-  if (active) {
-    [self.activityOverlayCoordinator stop];
-    self.activityOverlayCoordinator = nil;
-  } else if (!self.activityOverlayCoordinator) {
-    self.activityOverlayCoordinator =
-        [[ActivityOverlayCoordinator alloc] initWithBaseViewController:self];
-    [self.activityOverlayCoordinator start];
-  }
+  [self showActivityOverlay:!active];
 
   if (self.browserState) {
     ActiveStateManager* active_state_manager =
@@ -4387,6 +4380,17 @@
                    targetDeviceName:[command targetDeviceName]];
 }
 
+- (void)showActivityOverlay:(BOOL)shown {
+  if (!shown) {
+    [self.activityOverlayCoordinator stop];
+    self.activityOverlayCoordinator = nil;
+  } else if (!self.activityOverlayCoordinator) {
+    self.activityOverlayCoordinator =
+        [[ActivityOverlayCoordinator alloc] initWithBaseViewController:self];
+    [self.activityOverlayCoordinator start];
+  }
+}
+
 #pragma mark - FindInPageResponseDelegate
 
 - (void)findDidFinishWithUpdatedModel:(FindInPageModel*)model {
diff --git a/ios/chrome/browser/ui/commands/browser_commands.h b/ios/chrome/browser/ui/commands/browser_commands.h
index 8229f65..c2c3ae48 100644
--- a/ios/chrome/browser/ui/commands/browser_commands.h
+++ b/ios/chrome/browser/ui/commands/browser_commands.h
@@ -112,6 +112,10 @@
 // Sends the tab to another of the user's devices using the data in |command|.
 - (void)sendTabToSelf:(SendTabToSelfCommand*)command;
 
+// Show/Hide the activity indicator overlay that appears over the view to
+// prevent interaction with the web page.
+- (void)showActivityOverlay:(BOOL)shown;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_COMMANDS_BROWSER_COMMANDS_H_
diff --git a/ios/chrome/browser/ui/overlays/web_content_area/java_script_dialogs/java_script_dialog_overlay_coordinator.mm b/ios/chrome/browser/ui/overlays/web_content_area/java_script_dialogs/java_script_dialog_overlay_coordinator.mm
index 568e874..0d0113b 100644
--- a/ios/chrome/browser/ui/overlays/web_content_area/java_script_dialogs/java_script_dialog_overlay_coordinator.mm
+++ b/ios/chrome/browser/ui/overlays/web_content_area/java_script_dialogs/java_script_dialog_overlay_coordinator.mm
@@ -75,8 +75,11 @@
       presentViewController:self.alertViewController
                    animated:animated
                  completion:^{
-                   weakSelf.delegate->OverlayUIDidFinishPresentation(
-                       weakSelf.request);
+                   __typeof__(self) strongSelf = weakSelf;
+                   if (!strongSelf)
+                     return;
+                   strongSelf.delegate->OverlayUIDidFinishPresentation(
+                       strongSelf.request);
                  }];
   self.started = YES;
 }
diff --git a/ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_coordinator.mm b/ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_coordinator.mm
index 0047710..0318c97 100644
--- a/ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_coordinator.mm
+++ b/ios/chrome/browser/ui/settings/google_services/advanced_signin_settings_coordinator.mm
@@ -147,7 +147,8 @@
         // FirstSetupComplete flag should be only turned on when the user agrees
         // to start Sync.
         syncSetupService->PrepareForFirstSyncSetup();
-        syncSetupService->SetFirstSetupComplete();
+        syncSetupService->SetFirstSetupComplete(
+            syncer::SyncFirstSetupCompleteSource::ADVANCED_FLOW_CONFIRM);
       }
       break;
     }
diff --git a/ios/chrome/browser/ui/settings/google_services/google_services_settings_mediator.mm b/ios/chrome/browser/ui/settings/google_services/google_services_settings_mediator.mm
index 9649657..f4b113d 100644
--- a/ios/chrome/browser/ui/settings/google_services/google_services_settings_mediator.mm
+++ b/ios/chrome/browser/ui/settings/google_services/google_services_settings_mediator.mm
@@ -674,7 +674,8 @@
         // button.
         CHECK(value);
         self.syncSetupService->PrepareForFirstSyncSetup();
-        self.syncSetupService->SetFirstSetupComplete();
+        self.syncSetupService->SetFirstSetupComplete(
+            syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
       }
       break;
     case IdentityItemType:
diff --git a/ios/chrome/browser/ui/signin_interaction/signin_interaction_controller_egtest.mm b/ios/chrome/browser/ui/signin_interaction/signin_interaction_controller_egtest.mm
index f5be4bc..ce80d82b 100644
--- a/ios/chrome/browser/ui/signin_interaction/signin_interaction_controller_egtest.mm
+++ b/ios/chrome/browser/ui/signin_interaction/signin_interaction_controller_egtest.mm
@@ -29,7 +29,6 @@
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
-#import "ios/chrome/test/scoped_eg_synchronization_disabler.h"
 #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity.h"
 #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h"
 #import "ios/web/public/web_state.h"
@@ -139,23 +138,9 @@
 // correctly.
 - (void)testSignInDisconnectFromChromeManaged {
   ChromeIdentity* identity = [SigninEarlGreyUtils fakeManagedIdentity];
-  ios::FakeChromeIdentityService::GetInstanceFromChromeProvider()->AddIdentity(
-      identity);
 
-  [ChromeEarlGreyUI openSettingsMenu];
-  [ChromeEarlGreyUI tapSettingsMenuButton:SecondarySignInButton()];
-  [SigninEarlGreyUI selectIdentityWithEmail:identity.userEmail];
-  [SigninEarlGreyUI confirmSigninConfirmationDialog];
-  {
-    // Synchronization off due to an infinite spinner.
-    ScopedSynchronizationDisabler disabler;
-    WaitForMatcher(chrome_test_util::ButtonWithAccessibilityLabelId(
-        IDS_IOS_MANAGED_SIGNIN_ACCEPT_BUTTON));
-    TapButtonWithLabelId(IDS_IOS_MANAGED_SIGNIN_ACCEPT_BUTTON);
-  }
-  [SigninEarlGreyUtils checkSignedInWithIdentity:identity];
-  [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
-      performAction:grey_tap()];
+  // Sign-in with a managed account.
+  [SigninEarlGreyUI signinWithIdentity:identity isManagedAccount:YES];
 
   // Sign out.
   [SigninEarlGreyUI signOutWithManagedAccount:YES];
diff --git a/ios/chrome/browser/ui/webui/sync_internals/sync_internals_message_handler.cc b/ios/chrome/browser/ui/webui/sync_internals/sync_internals_message_handler.cc
index ba960f3..9d2cc71 100644
--- a/ios/chrome/browser/ui/webui/sync_internals/sync_internals_message_handler.cc
+++ b/ios/chrome/browser/ui/webui/sync_internals/sync_internals_message_handler.cc
@@ -222,7 +222,8 @@
   // If the service was previously stopped with CLEAR_DATA, then the
   // "first-setup-complete" bit was also cleared, and now the service wouldn't
   // fully start up. So set that too.
-  service->GetUserSettings()->SetFirstSetupComplete();
+  service->GetUserSettings()->SetFirstSetupComplete(
+      syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
 }
 
 void SyncInternalsMessageHandler::HandleRequestStopKeepData(
diff --git a/ios/chrome/browser/unified_consent/unified_consent_service_factory.cc b/ios/chrome/browser/unified_consent/unified_consent_service_factory.cc
index 1a38663..3fa21e3 100644
--- a/ios/chrome/browser/unified_consent/unified_consent_service_factory.cc
+++ b/ios/chrome/browser/unified_consent/unified_consent_service_factory.cc
@@ -10,7 +10,6 @@
 #include "components/keyed_service/ios/browser_state_dependency_manager.h"
 #include "components/sync/driver/sync_service.h"
 #include "components/sync_preferences/pref_service_syncable.h"
-#include "components/unified_consent/feature.h"
 #include "components/unified_consent/unified_consent_metrics.h"
 #include "components/unified_consent/unified_consent_service.h"
 #include "ios/chrome/browser/application_context.h"
@@ -67,12 +66,6 @@
   // Record settings for pre- and post-UnifiedConsent users.
   unified_consent::metrics::RecordSettingsHistogram(user_pref_service);
 
-  if (!unified_consent::IsUnifiedConsentFeatureEnabled()) {
-    unified_consent::UnifiedConsentService::RollbackIfNeeded(user_pref_service,
-                                                             sync_service);
-    return nullptr;
-  }
-
   // List of synced prefs that can be configured during the settings opt-in
   // flow.
   std::vector<std::string> synced_service_pref_names;
diff --git a/ios/chrome/test/wpt/cwt_request_handler.mm b/ios/chrome/test/wpt/cwt_request_handler.mm
index 0ed0a9d..82ad195f 100644
--- a/ios/chrome/test/wpt/cwt_request_handler.mm
+++ b/ios/chrome/test/wpt/cwt_request_handler.mm
@@ -331,7 +331,7 @@
   base::Value id_list(base::Value::Type::LIST);
   NSArray* tab_ids = [CWTWebDriverAppInterface tabIDs];
   for (NSString* tab_id in tab_ids) {
-    id_list.GetList().push_back(base::Value(base::SysNSStringToUTF8(tab_id)));
+    id_list.Append(base::Value(base::SysNSStringToUTF8(tab_id)));
   }
   return id_list;
 }
diff --git a/ios/web/favicon/favicon_util_unittest.mm b/ios/web/favicon/favicon_util_unittest.mm
index 1cb8cc6..44cdeb8 100644
--- a/ios/web/favicon/favicon_util_unittest.mm
+++ b/ios/web/favicon/favicon_util_unittest.mm
@@ -33,9 +33,9 @@
   favicon3.SetKey("sizes", base::Value("werfxw"));
   std::unique_ptr<base::ListValue> favicons =
       std::make_unique<base::ListValue>();
-  favicons->GetList().push_back(std::move(favicon));
-  favicons->GetList().push_back(std::move(favicon2));
-  favicons->GetList().push_back(std::move(favicon3));
+  favicons->Append(std::move(favicon));
+  favicons->Append(std::move(favicon2));
+  favicons->Append(std::move(favicon3));
   base::DictionaryValue dictionnary;
   dictionnary.Set({"favicons"}, std::move(favicons));
 
@@ -74,9 +74,9 @@
   favicon3.SetKey("rel", base::Value("apple-touch-icon-precomposed"));
   std::unique_ptr<base::ListValue> favicons =
       std::make_unique<base::ListValue>();
-  favicons->GetList().push_back(std::move(favicon));
-  favicons->GetList().push_back(std::move(favicon2));
-  favicons->GetList().push_back(std::move(favicon3));
+  favicons->Append(std::move(favicon));
+  favicons->Append(std::move(favicon2));
+  favicons->Append(std::move(favicon3));
   base::DictionaryValue dictionnary;
   dictionnary.Set({"favicons"}, std::move(favicons));
 
@@ -102,9 +102,9 @@
   favicon3.SetKey("rel", base::Value("apple-touch-icon-precomposed"));
   std::unique_ptr<base::ListValue> favicons =
       std::make_unique<base::ListValue>();
-  favicons->GetList().push_back(std::move(favicon));
-  favicons->GetList().push_back(std::move(favicon2));
-  favicons->GetList().push_back(std::move(favicon3));
+  favicons->Append(std::move(favicon));
+  favicons->Append(std::move(favicon2));
+  favicons->Append(std::move(favicon3));
   base::DictionaryValue dictionnary;
   dictionnary.Set({"favicons"}, std::move(favicons));
 
@@ -129,9 +129,9 @@
   favicon3.SetKey("rel", base::Value("apple-touch-icon-precomposed"));
   std::unique_ptr<base::ListValue> favicons =
       std::make_unique<base::ListValue>();
-  favicons->GetList().push_back(std::move(favicon));
-  favicons->GetList().push_back(std::move(favicon2));
-  favicons->GetList().push_back(std::move(favicon3));
+  favicons->Append(std::move(favicon));
+  favicons->Append(std::move(favicon2));
+  favicons->Append(std::move(favicon3));
   base::DictionaryValue dictionnary;
   dictionnary.Set({"favicons"}, std::move(favicons));
 
@@ -176,8 +176,8 @@
   favicon2.SetKey("sizes", base::Value("sgxer 30x40"));
   std::unique_ptr<base::ListValue> favicons =
       std::make_unique<base::ListValue>();
-  favicons->GetList().push_back(std::move(favicon));
-  favicons->GetList().push_back(std::move(favicon2));
+  favicons->Append(std::move(favicon));
+  favicons->Append(std::move(favicon2));
   base::DictionaryValue dictionnary;
   dictionnary.Set({"favicons"}, std::move(favicons));
 
@@ -214,8 +214,8 @@
   favicon2.SetKey("sizes", base::Value("x40"));
   std::unique_ptr<base::ListValue> favicons =
       std::make_unique<base::ListValue>();
-  favicons->GetList().push_back(std::move(favicon));
-  favicons->GetList().push_back(std::move(favicon2));
+  favicons->Append(std::move(favicon));
+  favicons->Append(std::move(favicon2));
   base::DictionaryValue dictionnary;
   dictionnary.Set({"favicons"}, std::move(favicons));
 
diff --git a/ios/web/js_messaging/web_frames_manager_impl.mm b/ios/web/js_messaging/web_frames_manager_impl.mm
index 0bc28a5..a3207b11 100644
--- a/ios/web/js_messaging/web_frames_manager_impl.mm
+++ b/ios/web/js_messaging/web_frames_manager_impl.mm
@@ -51,12 +51,12 @@
   DCHECK(old_web_view != new_web_view);
   if (old_web_view) {
     RemoveAllWebFrames();
-    [message_router
-        removeScriptMessageHandlerForName:kFrameBecameAvailableMessageName
-                                  webView:old_web_view];
-    [message_router
-        removeScriptMessageHandlerForName:kFrameBecameUnavailableMessageName
-                                  webView:old_web_view];
+    // TODO(crbug.com/956516): ScriptMessageHandlers should all be removed
+    // manually using |removeScriptMessageHandlerForName|, however this is not
+    // possible because of the cases where the webviewconfiguration is purged,
+    // in these cases the message router is deleted and it will not have
+    // message handlers for the web view.
+    [message_router removeAllScriptMessageHandlersForWebView:old_web_view];
   }
 
   // |this| is captured inside callbacks for JS messages, so the owner of
diff --git a/ios/web/navigation/wk_based_navigation_manager_impl.mm b/ios/web/navigation/wk_based_navigation_manager_impl.mm
index d846b9d..7a911e55 100644
--- a/ios/web/navigation/wk_based_navigation_manager_impl.mm
+++ b/ios/web/navigation/wk_based_navigation_manager_impl.mm
@@ -200,8 +200,9 @@
   // When reloading an target url redirect page, re-use the target url as the
   // current item url.
   GURL target_url;
-  if (ui::PageTransitionCoreTypeIs(navigation_type,
-                                   ui::PAGE_TRANSITION_RELOAD) &&
+  if (navigation_type & ui::PAGE_TRANSITION_RELOAD &&
+      !(navigation_type & ui::PAGE_TRANSITION_FORWARD_BACK) &&
+      initiation_type == NavigationInitiationType::BROWSER_INITIATED &&
       web::wk_navigation_util::IsRestoreSessionUrl(current_item_url) &&
       web::wk_navigation_util::ExtractTargetURL(current_item_url,
                                                 &target_url)) {
diff --git a/ios/web/navigation/wk_navigation_util.mm b/ios/web/navigation/wk_navigation_util.mm
index 7ed21f320..9412fc5 100644
--- a/ios/web/navigation/wk_navigation_util.mm
+++ b/ios/web/navigation/wk_navigation_util.mm
@@ -136,8 +136,8 @@
   restored_titles.GetList().reserve(new_size);
   for (auto it = begin; it != end; ++it) {
     NavigationItem* item = (*it).get();
-    restored_urls.GetList().push_back(base::Value(item->GetURL().spec()));
-    restored_titles.GetList().push_back(base::Value(item->GetTitle()));
+    restored_urls.Append(base::Value(item->GetURL().spec()));
+    restored_titles.Append(base::Value(item->GetTitle()));
   }
   base::Value session(base::Value::Type::DICTIONARY);
   int offset = new_last_committed_item_index + 1 - new_size;
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index 7bd63743..44cd194 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -431,11 +431,6 @@
       _webView, webView, messageRouter);
 
   if (_webView) {
-    // TODO(crbug.com/956516): Use removeScriptMessageHandlerForName:webView:
-    // for |kScriptMessageName| and let CRWContextMenuController unregister its
-    // own callback.
-    [messageRouter removeAllScriptMessageHandlersForWebView:_webView];
-
     [_webView stopLoading];
     [_webView removeFromSuperview];
   }
diff --git a/ios/web_view/internal/passwords/web_view_password_manager_client.h b/ios/web_view/internal/passwords/web_view_password_manager_client.h
index a7454432..267cee6 100644
--- a/ios/web_view/internal/passwords/web_view_password_manager_client.h
+++ b/ios/web_view/internal/passwords/web_view_password_manager_client.h
@@ -88,6 +88,7 @@
       const override;
   PrefService* GetPrefs() const override;
   password_manager::PasswordStore* GetProfilePasswordStore() const override;
+  password_manager::PasswordStore* GetAccountPasswordStore() const override;
   void NotifyUserAutoSignin(
       std::vector<std::unique_ptr<autofill::PasswordForm>> local_forms,
       const GURL& origin) override;
diff --git a/ios/web_view/internal/passwords/web_view_password_manager_client.mm b/ios/web_view/internal/passwords/web_view_password_manager_client.mm
index 33966d6..4dbd447 100644
--- a/ios/web_view/internal/passwords/web_view_password_manager_client.mm
+++ b/ios/web_view/internal/passwords/web_view_password_manager_client.mm
@@ -133,6 +133,11 @@
       .get();
 }
 
+PasswordStore* WebViewPasswordManagerClient::GetAccountPasswordStore() const {
+  // Account password stores aren't currently supported in iOS webviews.
+  return nullptr;
+}
+
 void WebViewPasswordManagerClient::NotifyUserAutoSignin(
     std::vector<std::unique_ptr<autofill::PasswordForm>> local_forms,
     const GURL& origin) {
diff --git a/media/capture/video/fake_video_capture_device_unittest.cc b/media/capture/video/fake_video_capture_device_unittest.cc
index f83fe157..c584ef5 100644
--- a/media/capture/video/fake_video_capture_device_unittest.cc
+++ b/media/capture/video/fake_video_capture_device_unittest.cc
@@ -200,7 +200,7 @@
 
   const VideoCaptureFormat& last_format() const { return last_format_; }
 
-  base::test::TaskEnvironment task_environment_;
+  base::test::SingleThreadTaskEnvironment task_environment_;
   std::unique_ptr<VideoCaptureDeviceDescriptors> descriptors_;
   std::unique_ptr<base::RunLoop> run_loop_;
   std::unique_ptr<MockVideoCaptureDeviceClient> client_;
diff --git a/media/capture/video/video_capture_device_unittest.cc b/media/capture/video/video_capture_device_unittest.cc
index a84bb11..012a7268 100644
--- a/media/capture/video/video_capture_device_unittest.cc
+++ b/media/capture/video/video_capture_device_unittest.cc
@@ -250,7 +250,8 @@
 #if defined(OS_MACOSX)
         // Video capture code on MacOSX must run on a CFRunLoop enabled thread
         // for interaction with AVFoundation.
-        task_environment_(base::test::TaskEnvironment::MainThreadType::UI),
+        task_environment_(
+            base::test::SingleThreadTaskEnvironment::MainThreadType::UI),
 #endif
         device_descriptors_(new VideoCaptureDeviceDescriptors()),
         main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
@@ -461,7 +462,7 @@
 #if defined(OS_WIN)
   base::win::ScopedCOMInitializer initialize_com_;
 #endif
-  base::test::TaskEnvironment task_environment_;
+  base::test::SingleThreadTaskEnvironment task_environment_;
   std::unique_ptr<VideoCaptureDeviceDescriptors> device_descriptors_;
   std::unique_ptr<base::RunLoop> run_loop_;
   scoped_refptr<base::TaskRunner> main_thread_task_runner_;
diff --git a/media/gpu/video_decode_accelerator_perf_tests.cc b/media/gpu/video_decode_accelerator_perf_tests.cc
index 989e2703..50549ce6e 100644
--- a/media/gpu/video_decode_accelerator_perf_tests.cc
+++ b/media/gpu/video_decode_accelerator_perf_tests.cc
@@ -258,14 +258,14 @@
   // Write frame delivery times to json.
   base::Value delivery_times(base::Value::Type::LIST);
   for (double frame_delivery_time : frame_delivery_times_) {
-    delivery_times.GetList().emplace_back(frame_delivery_time);
+    delivery_times.Append(frame_delivery_time);
   }
   metrics.SetKey("FrameDeliveryTimes", std::move(delivery_times));
 
   // Write frame decodes times to json.
   base::Value decode_times(base::Value::Type::LIST);
   for (double frame_decode_time : frame_decode_times_) {
-    decode_times.GetList().emplace_back(frame_decode_time);
+    decode_times.Append(frame_decode_time);
   }
   metrics.SetKey("FrameDecodeTimes", std::move(decode_times));
 
diff --git a/mojo/public/cpp/bindings/receiver_set.h b/mojo/public/cpp/bindings/receiver_set.h
index a368d9c..f312e20 100644
--- a/mojo/public/cpp/bindings/receiver_set.h
+++ b/mojo/public/cpp/bindings/receiver_set.h
@@ -14,6 +14,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/stl_util.h"
 #include "mojo/public/cpp/bindings/connection_error_callback.h"
 #include "mojo/public/cpp/bindings/message.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -164,6 +165,13 @@
   // disconnection notifications until a new receiver is added to the set.
   void Clear() { receivers_.clear(); }
 
+  // Predicate to test if a receiver exists in the set.
+  //
+  // Returns |true| if the receiver is in the set and |false| if not.
+  bool HasReceiver(ReceiverId id) const {
+    return base::Contains(receivers_, id);
+  }
+
   bool empty() const { return receivers_.empty(); }
 
   size_t size() const { return receivers_.size(); }
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 0cf712e..951d506 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1327,6 +1327,18 @@
       "third_party/quiche/src/http2/platform/api/http2_string_utils.h",
       "third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.cc",
       "third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h",
+      "third_party/quiche/src/quic/core/congestion_control/bbr2_drain.cc",
+      "third_party/quiche/src/quic/core/congestion_control/bbr2_drain.h",
+      "third_party/quiche/src/quic/core/congestion_control/bbr2_misc.cc",
+      "third_party/quiche/src/quic/core/congestion_control/bbr2_misc.h",
+      "third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.cc",
+      "third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.h",
+      "third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.cc",
+      "third_party/quiche/src/quic/core/congestion_control/bbr2_probe_rtt.h",
+      "third_party/quiche/src/quic/core/congestion_control/bbr2_sender.cc",
+      "third_party/quiche/src/quic/core/congestion_control/bbr2_sender.h",
+      "third_party/quiche/src/quic/core/congestion_control/bbr2_startup.cc",
+      "third_party/quiche/src/quic/core/congestion_control/bbr2_startup.h",
       "third_party/quiche/src/quic/core/congestion_control/bbr_sender.cc",
       "third_party/quiche/src/quic/core/congestion_control/bbr_sender.h",
       "third_party/quiche/src/quic/core/congestion_control/cubic_bytes.cc",
@@ -5474,6 +5486,7 @@
     "third_party/quiche/src/http2/tools/random_util.cc",
     "third_party/quiche/src/http2/tools/random_util.h",
     "third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler_test.cc",
+    "third_party/quiche/src/quic/core/congestion_control/bbr2_simulator_test.cc",
     "third_party/quiche/src/quic/core/congestion_control/bbr_sender_test.cc",
     "third_party/quiche/src/quic/core/congestion_control/cubic_bytes_test.cc",
     "third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm_test.cc",
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h
index f34fb2a1..ac9797a 100644
--- a/net/quic/quic_flags_list.h
+++ b/net/quic/quic_flags_list.h
@@ -49,6 +49,22 @@
 // Congestion window gain for QUIC BBR during PROBE_BW phase.
 QUIC_FLAG(double, FLAGS_quic_bbr_cwnd_gain, 2.0f)
 
+// The default minimum duration for BBRv2-native probes, in milliseconds.
+QUIC_FLAG(int32_t, FLAGS_quic_bbr2_default_probe_bw_base_duration_ms, 2000)
+
+// The default upper bound of the random amount of BBRv2-native probes, in
+// milliseconds.
+QUIC_FLAG(int32_t, FLAGS_quic_bbr2_default_probe_bw_max_rand_duration_ms, 1000)
+
+// The default period for entering PROBE_RTT, in milliseconds.
+QUIC_FLAG(int32_t, FLAGS_quic_bbr2_default_probe_rtt_period_ms, 10000)
+
+// The default loss threshold for QUIC BBRv2, should be a value between 0 and 1.
+QUIC_FLAG(double, FLAGS_quic_bbr2_default_loss_threshold, 0.02)
+
+// The default minimum number of loss marking events to exit STARTUP.
+QUIC_FLAG(int32_t, FLAGS_quic_bbr2_default_startup_full_loss_count, 8)
+
 // If true, adjust congestion window when doing bandwidth resumption in BBR.
 QUIC_FLAG(bool,
           FLAGS_quic_reloadable_flag_quic_fix_bbr_cwnd_in_bandwidth_resumption,
diff --git a/printing/backend/cups_connection.cc b/printing/backend/cups_connection.cc
index 24885c6..caa244c 100644
--- a/printing/backend/cups_connection.cc
+++ b/printing/backend/cups_connection.cc
@@ -47,12 +47,10 @@
   void store_dest(cups_dest_t* dest) { dests_.emplace_back(dest); }
 
   // Returns the collected destinations.
-  std::vector<std::unique_ptr<cups_dest_t, DestinationDeleter>>& get_dests() {
-    return dests_;
-  }
+  std::vector<ScopedDestination>& get_dests() { return dests_; }
 
  private:
-  std::vector<std::unique_ptr<cups_dest_t, DestinationDeleter>> dests_;
+  std::vector<ScopedDestination> dests_;
 
   DISALLOW_COPY_AND_ASSIGN(DestinationEnumerator);
 };
@@ -139,8 +137,8 @@
   if (!dest)
     return nullptr;
 
-  return std::make_unique<CupsPrinter>(
-      cups_http_.get(), std::unique_ptr<cups_dest_t, DestinationDeleter>(dest));
+  return std::make_unique<CupsPrinter>(cups_http_.get(),
+                                       ScopedDestination(dest));
 }
 
 bool CupsConnection::GetJobs(const std::vector<std::string>& printer_ids,
diff --git a/printing/backend/cups_connection.h b/printing/backend/cups_connection.h
index c7deb45..3fcb995 100644
--- a/printing/backend/cups_connection.h
+++ b/printing/backend/cups_connection.h
@@ -67,7 +67,7 @@
   http_encryption_t cups_encryption_;
   bool blocking_;
 
-  std::unique_ptr<http_t, HttpDeleter> cups_http_;
+  ScopedHttpPtr cups_http_;
 
   DISALLOW_COPY_AND_ASSIGN(CupsConnection);
 };
diff --git a/printing/backend/cups_deleters.cc b/printing/backend/cups_deleters.cc
index 6df4c4e..2dccc5b 100644
--- a/printing/backend/cups_deleters.cc
+++ b/printing/backend/cups_deleters.cc
@@ -23,10 +23,4 @@
   cupsFreeOptions(1, option);
 }
 
-JobsDeleter::JobsDeleter(int num_jobs) : num_jobs_(num_jobs) {}
-
-void JobsDeleter::operator()(cups_job_t* jobs) const {
-  cupsFreeJobs(num_jobs_, jobs);
-}
-
 }  // namespace printing
diff --git a/printing/backend/cups_deleters.h b/printing/backend/cups_deleters.h
index 6e7b198..aa905e8 100644
--- a/printing/backend/cups_deleters.h
+++ b/printing/backend/cups_deleters.h
@@ -6,8 +6,7 @@
 #define PRINTING_BACKEND_CUPS_DELETERS_H_
 
 #include <cups/cups.h>
-
-#include "base/macros.h"
+#include <memory>
 
 namespace printing {
 
@@ -27,16 +26,10 @@
   void operator()(cups_option_t* option) const;
 };
 
-class JobsDeleter {
- public:
-  explicit JobsDeleter(int num_jobs);
-  void operator()(cups_job_t* jobs) const;
-
- private:
-  int num_jobs_;
-
-  DISALLOW_COPY_AND_ASSIGN(JobsDeleter);
-};
+using ScopedHttpPtr = std::unique_ptr<http_t, HttpDeleter>;
+using ScopedDestination = std::unique_ptr<cups_dest_t, DestinationDeleter>;
+using ScopedDestInfo = std::unique_ptr<cups_dinfo_t, DestInfoDeleter>;
+using ScopedCupsOption = std::unique_ptr<cups_option_t, OptionDeleter>;
 
 }  // namespace printing
 
diff --git a/printing/backend/cups_jobs.cc b/printing/backend/cups_jobs.cc
index 7a08695..cad8294 100644
--- a/printing/backend/cups_jobs.cc
+++ b/printing/backend/cups_jobs.cc
@@ -114,8 +114,6 @@
     {kPrinterMakeAndModel, kIppVersionsSupported, kIppFeaturesSupported,
      kDocumentFormatSupported, kPwgRasterDocumentResolutionSupported}};
 
-using ScopedHttpPtr = std::unique_ptr<http_t, HttpDeleter>;
-
 // Converts an IPP attribute |attr| to the appropriate JobState enum.
 CupsJob::JobState ToJobState(ipp_attribute_t* attr) {
   DCHECK_EQ(IPP_TAG_ENUM, ippGetValueTag(attr));
diff --git a/printing/backend/cups_printer.cc b/printing/backend/cups_printer.cc
index c8c873e1..ce0d781 100644
--- a/printing/backend/cups_printer.cc
+++ b/printing/backend/cups_printer.cc
@@ -23,8 +23,7 @@
 
 namespace printing {
 
-CupsPrinter::CupsPrinter(http_t* http,
-                         std::unique_ptr<cups_dest_t, DestinationDeleter> dest)
+CupsPrinter::CupsPrinter(http_t* http, ScopedDestination dest)
     : cups_http_(http), destination_(std::move(dest)) {
   DCHECK(cups_http_);
   DCHECK(destination_);
diff --git a/printing/backend/cups_printer.h b/printing/backend/cups_printer.h
index 720aae74..c1310ac 100644
--- a/printing/backend/cups_printer.h
+++ b/printing/backend/cups_printer.h
@@ -51,8 +51,7 @@
 class PRINTING_EXPORT CupsPrinter : public CupsOptionProvider {
  public:
   // Create a printer with a connection defined by |http| and |dest|.
-  CupsPrinter(http_t* http,
-              std::unique_ptr<cups_dest_t, DestinationDeleter> dest);
+  CupsPrinter(http_t* http, ScopedDestination dest);
 
   CupsPrinter(CupsPrinter&& printer);
 
@@ -126,10 +125,10 @@
   http_t* const cups_http_;
 
   // information to identify a printer
-  std::unique_ptr<cups_dest_t, DestinationDeleter> destination_;
+  ScopedDestination destination_;
 
   // opaque object containing printer attributes and options
-  mutable std::unique_ptr<cups_dinfo_t, DestInfoDeleter> dest_info_;
+  mutable ScopedDestInfo dest_info_;
 
   DISALLOW_COPY_AND_ASSIGN(CupsPrinter);
 };
diff --git a/printing/printing_context_chromeos.cc b/printing/printing_context_chromeos.cc
index b48cbe1..17c79ba 100644
--- a/printing/printing_context_chromeos.cc
+++ b/printing/printing_context_chromeos.cc
@@ -29,8 +29,6 @@
 
 namespace {
 
-using ScopedCupsOption = std::unique_ptr<cups_option_t, OptionDeleter>;
-
 // convert from a ColorMode setting to a print-color-mode value from PWG 5100.13
 const char* GetColorModelForMode(int color_mode) {
   const char* mode_string;
diff --git a/printing/printing_context_chromeos.h b/printing/printing_context_chromeos.h
index 519c255..d814a4e 100644
--- a/printing/printing_context_chromeos.h
+++ b/printing/printing_context_chromeos.h
@@ -11,6 +11,7 @@
 
 #include "base/macros.h"
 #include "printing/backend/cups_connection.h"
+#include "printing/backend/cups_deleters.h"
 #include "printing/backend/cups_printer.h"
 #include "printing/printing_context.h"
 
@@ -42,8 +43,6 @@
   Result StreamData(const std::vector<char>& buffer);
 
  private:
-  using ScopedCupsOption = std::unique_ptr<cups_option_t, OptionDeleter>;
-
   // Lazily initializes |printer_|.
   Result InitializeDevice(const std::string& device);
 
diff --git a/remoting/host/installer/mac/do_signing.sh b/remoting/host/installer/mac/do_signing.sh
index 5dbbbe3..6513d2af 100755
--- a/remoting/host/installer/mac/do_signing.sh
+++ b/remoting/host/installer/mac/do_signing.sh
@@ -208,9 +208,6 @@
   echo "Usage: ${ME} -o output_dir -i input_dir "\
       "[-c codesign_id] [-p productsign_id] [-k keychain]" >&2
   echo >&2
-  echo "Usage (legacy): ${ME} output_dir input_dir [keychain codesign_id"\
-      "[productsign_id]]" >&2
-  echo >&2
   echo "  Sign the binaries using the specified <codesign_id>, build" >&2
   echo "  the installer, and then sign the installer using the given" >&2
   echo "  <productsign_id>." >&2
@@ -228,7 +225,6 @@
   local productsign_id=""
   local keychain=""
 
-  local opt_count=${#}
   local OPTNAME OPTIND OPTARG
   while getopts ":o:i:c:p:k:h" OPTNAME; do
     case ${OPTNAME} in
@@ -252,47 +248,12 @@
         exit 0
         ;;
       * )
-        err "Invalid command-line option: ${OPTARG}"
-        usage
-        exit 1
+        err "Ignoring invalid command-line option: ${OPTARG}"
         ;;
     esac
   done
   shift $(($OPTIND - 1))
 
-  # The opts need to be either all "flag-style" or all "position-style", not
-  # both. If there are any leftover opts at this point, it should be all the
-  # original ones (i.e. all positional).
-  # TODO(mmoss): The positional handling is legacy and can go away once the
-  # signing system has been migrated to using flags, which provides more
-  # flexibility for adding/removing opts if needed. b/31931170
-  if [[ ${#} -ne 0 ]]; then
-    if [[ ${opt_count} -ne ${#} ]]; then
-      err "Please use all flag opts, or all positional opts, not both."
-      usage
-      exit 1
-    fi
-    if [[ ${#} < 2 ]]; then
-      err "Too few positional opts."
-      usage
-      exit 1
-    fi
-    output_dir="$(shell_safe_path "${1}")"
-    input_dir="$(shell_safe_path "${2}")"
-    keychain=""
-    if [[ ${#} -ge 3 ]]; then
-      keychain="$(shell_safe_path "${3}")"
-    fi
-    codesign_id=""
-    if [[ ${#} -ge 4 ]]; then
-      codesign_id="${4}"
-    fi
-    productsign_id=""
-    if [[ ${#} -ge 5 ]]; then
-      productsign_id="${5}"
-    fi
-  fi
-
   if [[ -z "${output_dir}" || -z "${input_dir}" ]]; then
     err "output_dir and input_dir are required."
     usage
diff --git a/services/data_decoder/data_decoder_service.cc b/services/data_decoder/data_decoder_service.cc
index bcfbb394..f2250e7 100644
--- a/services/data_decoder/data_decoder_service.cc
+++ b/services/data_decoder/data_decoder_service.cc
@@ -70,10 +70,10 @@
 
 #ifdef OS_CHROMEOS
 void DataDecoderService::BindBleScanParser(
-    mojom::BleScanParserRequest request) {
-  mojo::MakeStrongBinding(
+    mojo::PendingReceiver<mojom::BleScanParser> receiver) {
+  mojo::MakeSelfOwnedReceiver(
       std::make_unique<BleScanParserImpl>(keepalive_.CreateRef()),
-      std::move(request));
+      std::move(receiver));
 }
 #endif  // OS_CHROMEOS
 
@@ -97,10 +97,10 @@
 }
 
 void DataDecoderService::BindBundledExchangesParserFactory(
-    mojom::BundledExchangesParserFactoryRequest request) {
-  mojo::MakeStrongBinding(
+    mojo::PendingReceiver<mojom::BundledExchangesParserFactory> receiver) {
+  mojo::MakeSelfOwnedReceiver(
       std::make_unique<BundledExchangesParserFactory>(keepalive_.CreateRef()),
-      std::move(request));
+      std::move(receiver));
 }
 
 }  // namespace data_decoder
diff --git a/services/data_decoder/data_decoder_service.h b/services/data_decoder/data_decoder_service.h
index 4aa4bda..1878b85 100644
--- a/services/data_decoder/data_decoder_service.h
+++ b/services/data_decoder/data_decoder_service.h
@@ -42,13 +42,13 @@
 
  private:
   void BindBundledExchangesParserFactory(
-      mojom::BundledExchangesParserFactoryRequest request);
+      mojo::PendingReceiver<mojom::BundledExchangesParserFactory> receiver);
   void BindImageDecoder(mojo::PendingReceiver<mojom::ImageDecoder> receiver);
   void BindJsonParser(mojo::PendingReceiver<mojom::JsonParser> receiver);
   void BindXmlParser(mojom::XmlParserRequest request);
 
 #ifdef OS_CHROMEOS
-  void BindBleScanParser(mojom::BleScanParserRequest request);
+  void BindBleScanParser(mojo::PendingReceiver<mojom::BleScanParser> receiver);
 #endif  // OS_CHROMEOS
 
   service_manager::ServiceBinding binding_{this};
diff --git a/services/data_decoder/xml_parser.cc b/services/data_decoder/xml_parser.cc
index 53254a6e..d2f81d78 100644
--- a/services/data_decoder/xml_parser.cc
+++ b/services/data_decoder/xml_parser.cc
@@ -69,7 +69,7 @@
   if (!children)
     children = element->SetKey(mojom::XmlParser::kChildrenKey,
                                base::Value(base::Value::Type::LIST));
-  children->GetList().push_back(std::move(child));
+  children->Append(std::move(child));
   return &children->GetList().back();
 }
 
diff --git a/services/device/battery/battery_monitor_impl.cc b/services/device/battery/battery_monitor_impl.cc
index f1f8dcb5..0fb7d8c 100644
--- a/services/device/battery/battery_monitor_impl.cc
+++ b/services/device/battery/battery_monitor_impl.cc
@@ -9,16 +9,16 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
 
 namespace device {
 
 // static
-void BatteryMonitorImpl::Create(mojom::BatteryMonitorRequest request) {
+void BatteryMonitorImpl::Create(
+    mojo::PendingReceiver<mojom::BatteryMonitor> receiver) {
   auto* impl = new BatteryMonitorImpl;
-  auto binding =
-      mojo::MakeStrongBinding(base::WrapUnique(impl), std::move(request));
-  impl->binding_ = binding;
+  impl->receiver_ =
+      mojo::MakeSelfOwnedReceiver(base::WrapUnique(impl), std::move(receiver));
 }
 
 BatteryMonitorImpl::BatteryMonitorImpl() : status_to_report_(false) {
@@ -33,7 +33,7 @@
 void BatteryMonitorImpl::QueryNextStatus(QueryNextStatusCallback callback) {
   if (!callback_.is_null()) {
     DVLOG(1) << "Overlapped call to QueryNextStatus!";
-    binding_->Close();
+    receiver_->Close();
     return;
   }
   callback_ = std::move(callback);
diff --git a/services/device/battery/battery_monitor_impl.h b/services/device/battery/battery_monitor_impl.h
index dd36546..b5b17776 100644
--- a/services/device/battery/battery_monitor_impl.h
+++ b/services/device/battery/battery_monitor_impl.h
@@ -8,7 +8,8 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
 #include "services/device/battery/battery_status_service.h"
 #include "services/device/public/mojom/battery_monitor.mojom.h"
 
@@ -16,7 +17,7 @@
 
 class BatteryMonitorImpl : public mojom::BatteryMonitor {
  public:
-  static void Create(mojom::BatteryMonitorRequest request);
+  static void Create(mojo::PendingReceiver<mojom::BatteryMonitor> receiver);
 
   BatteryMonitorImpl();
   ~BatteryMonitorImpl() override;
@@ -29,7 +30,7 @@
   void DidChange(const mojom::BatteryStatus& battery_status);
   void ReportStatus();
 
-  mojo::StrongBindingPtr<mojom::BatteryMonitor> binding_;
+  mojo::SelfOwnedReceiverRef<mojom::BatteryMonitor> receiver_;
   std::unique_ptr<BatteryStatusService::BatteryUpdateSubscription>
       subscription_;
   QueryNextStatusCallback callback_;
diff --git a/services/device/battery/battery_monitor_impl_unittest.cc b/services/device/battery/battery_monitor_impl_unittest.cc
index 16cbf2f..0527f3fc2 100644
--- a/services/device/battery/battery_monitor_impl_unittest.cc
+++ b/services/device/battery/battery_monitor_impl_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "services/device/battery/battery_status_manager.h"
 #include "services/device/battery/battery_status_service.h"
 #include "services/device/device_service_test_base.h"
@@ -96,7 +97,8 @@
     battery_manager_ = battery_manager.get();
     battery_service->SetBatteryManagerForTesting(std::move(battery_manager));
 
-    connector()->BindInterface(mojom::kServiceName, &battery_monitor_);
+    connector()->Connect(mojom::kServiceName,
+                         battery_monitor_.BindNewPipeAndPassReceiver());
   }
 
   void TearDown() override {
@@ -110,7 +112,7 @@
 
   FakeBatteryStatusManager* battery_manager() { return battery_manager_; }
 
-  mojom::BatteryMonitorPtr battery_monitor_;
+  mojo::Remote<mojom::BatteryMonitor> battery_monitor_;
 
  private:
   FakeBatteryStatusManager* battery_manager_;
diff --git a/services/device/device_service.cc b/services/device/device_service.cc
index a517c10..04c3aee 100644
--- a/services/device/device_service.cc
+++ b/services/device/device_service.cc
@@ -143,7 +143,7 @@
 
 void DeviceService::OnStart() {
   registry_.AddInterface<mojom::Fingerprint>(base::Bind(
-      &DeviceService::BindFingerprintRequest, base::Unretained(this)));
+      &DeviceService::BindFingerprintReceiver, base::Unretained(this)));
   registry_.AddInterface<mojom::GeolocationConfig>(base::BindRepeating(
       &DeviceService::BindGeolocationConfigRequest, base::Unretained(this)));
   registry_.AddInterface<mojom::GeolocationContext>(base::Bind(
@@ -180,7 +180,7 @@
           ->CreateInterfaceFactory<mojom::VibrationManager>());
 #else
   registry_.AddInterface<mojom::BatteryMonitor>(base::Bind(
-      &DeviceService::BindBatteryMonitorRequest, base::Unretained(this)));
+      &DeviceService::BindBatteryMonitorReceiver, base::Unretained(this)));
   registry_.AddInterface<mojom::HidManager>(base::Bind(
       &DeviceService::BindHidManagerRequest, base::Unretained(this)));
   registry_.AddInterface<mojom::NFCProvider>(base::Bind(
@@ -230,9 +230,9 @@
 }
 
 #if !defined(OS_ANDROID)
-void DeviceService::BindBatteryMonitorRequest(
-    mojom::BatteryMonitorRequest request) {
-  BatteryMonitorImpl::Create(std::move(request));
+void DeviceService::BindBatteryMonitorReceiver(
+    mojo::PendingReceiver<mojom::BatteryMonitor> receiver) {
+  BatteryMonitorImpl::Create(std::move(receiver));
 }
 
 void DeviceService::BindHidManagerRequest(mojom::HidManagerRequest request) {
@@ -275,8 +275,9 @@
 }
 #endif
 
-void DeviceService::BindFingerprintRequest(mojom::FingerprintRequest request) {
-  Fingerprint::Create(std::move(request));
+void DeviceService::BindFingerprintReceiver(
+    mojo::PendingReceiver<mojom::Fingerprint> receiver) {
+  Fingerprint::Create(std::move(receiver));
 }
 
 void DeviceService::BindGeolocationConfigRequest(
diff --git a/services/device/device_service.h b/services/device/device_service.h
index b77e5a9..06331f25 100644
--- a/services/device/device_service.h
+++ b/services/device/device_service.h
@@ -138,7 +138,8 @@
                        const std::string& interface_name,
                        mojo::ScopedMessagePipeHandle interface_pipe) override;
 
-  void BindFingerprintRequest(mojom::FingerprintRequest request);
+  void BindFingerprintReceiver(
+      mojo::PendingReceiver<mojom::Fingerprint> receiver);
   void BindGeolocationConfigRequest(mojom::GeolocationConfigRequest request);
   void BindGeolocationContextRequest(mojom::GeolocationContextRequest request);
   void BindGeolocationControlRequest(mojom::GeolocationControlRequest request);
@@ -148,7 +149,8 @@
 #endif
 
 #if !defined(OS_ANDROID)
-  void BindBatteryMonitorRequest(mojom::BatteryMonitorRequest request);
+  void BindBatteryMonitorReceiver(
+      mojo::PendingReceiver<mojom::BatteryMonitor> receiver);
   void BindHidManagerRequest(mojom::HidManagerRequest request);
   void BindNFCProviderReceiver(
       mojo::PendingReceiver<mojom::NFCProvider> receiver);
diff --git a/services/device/fingerprint/fingerprint.h b/services/device/fingerprint/fingerprint.h
index 83676e8..ee78e8cf 100644
--- a/services/device/fingerprint/fingerprint.h
+++ b/services/device/fingerprint/fingerprint.h
@@ -5,6 +5,7 @@
 #ifndef SERVICES_DEVICE_FINGERPRINT_FINGERPRINT_H_
 #define SERVICES_DEVICE_FINGERPRINT_FINGERPRINT_H_
 
+#include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "services/device/fingerprint/fingerprint_export.h"
 #include "services/device/public/mojom/fingerprint.mojom.h"
 
@@ -14,7 +15,7 @@
  public:
   // This function is implemented in platform-specific subclasses.
   SERVICES_DEVICE_FINGERPRINT_EXPORT static void Create(
-      device::mojom::FingerprintRequest request);
+      mojo::PendingReceiver<device::mojom::Fingerprint> receiver);
 };
 
 }  // namespace device
diff --git a/services/device/fingerprint/fingerprint_chromeos.cc b/services/device/fingerprint/fingerprint_chromeos.cc
index d3ff91d..c4a873b6 100644
--- a/services/device/fingerprint/fingerprint_chromeos.cc
+++ b/services/device/fingerprint/fingerprint_chromeos.cc
@@ -9,7 +9,8 @@
 #include "base/bind.h"
 #include "chromeos/dbus/biod/biod_client.h"
 #include "dbus/object_path.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
 #include "services/device/fingerprint/fingerprint.h"
 #include "services/device/public/mojom/fingerprint.mojom.h"
 
@@ -331,9 +332,10 @@
 }
 
 // static
-void Fingerprint::Create(device::mojom::FingerprintRequest request) {
-  mojo::MakeStrongBinding(std::make_unique<FingerprintChromeOS>(),
-                          std::move(request));
+void Fingerprint::Create(
+    mojo::PendingReceiver<device::mojom::Fingerprint> receiver) {
+  mojo::MakeSelfOwnedReceiver(std::make_unique<FingerprintChromeOS>(),
+                              std::move(receiver));
 }
 
 }  // namespace device
diff --git a/services/device/fingerprint/fingerprint_default.cc b/services/device/fingerprint/fingerprint_default.cc
index 8c0ae7ea..7b0798f1 100644
--- a/services/device/fingerprint/fingerprint_default.cc
+++ b/services/device/fingerprint/fingerprint_default.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 "mojo/public/cpp/bindings/pending_receiver.h"
 #include "services/device/fingerprint/fingerprint.h"
 #include "services/device/public/mojom/fingerprint.mojom.h"
 
@@ -20,7 +21,8 @@
 }  // namespace
 
 // static
-void Fingerprint::Create(device::mojom::FingerprintRequest request) {
+void Fingerprint::Create(
+    mojo::PendingReceiver<device::mojom::Fingerprint> receiver) {
   // Do nothing.
 }
 
diff --git a/services/device/geolocation/geolocation_service_unittest.cc b/services/device/geolocation/geolocation_service_unittest.cc
index d1cda12..ac9cace 100644
--- a/services/device/geolocation/geolocation_service_unittest.cc
+++ b/services/device/geolocation/geolocation_service_unittest.cc
@@ -11,6 +11,7 @@
 #include "chromeos/network/geolocation_handler.h"
 #endif
 #include "mojo/public/cpp/bindings/interface_ptr.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "net/base/network_change_notifier.h"
 #include "services/device/device_service_test_base.h"
 #include "services/device/geolocation/geolocation_provider_impl.h"
@@ -52,7 +53,8 @@
     geolocation_control_->UserDidOptIntoLocationServices();
 
     connector()->BindInterface(mojom::kServiceName, &geolocation_context_);
-    geolocation_context_->BindGeolocation(MakeRequest(&geolocation_));
+    geolocation_context_->BindGeolocation(
+        geolocation_.BindNewPipeAndPassReceiver());
   }
 
   void TearDown() override {
@@ -79,7 +81,7 @@
   std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_;
   mojom::GeolocationControlPtr geolocation_control_;
   mojom::GeolocationContextPtr geolocation_context_;
-  mojom::GeolocationPtr geolocation_;
+  mojo::Remote<mojom::Geolocation> geolocation_;
   mojom::GeolocationConfigPtr geolocation_config_;
 
   DISALLOW_COPY_AND_ASSIGN(GeolocationServiceUnitTest);
diff --git a/services/device/geolocation/public_ip_address_geolocator_unittest.cc b/services/device/geolocation/public_ip_address_geolocator_unittest.cc
index c5ccb23..51d412f9 100644
--- a/services/device/geolocation/public_ip_address_geolocator_unittest.cc
+++ b/services/device/geolocation/public_ip_address_geolocator_unittest.cc
@@ -9,7 +9,8 @@
 #include "base/strings/string_util.h"
 #include "base/test/task_environment.h"
 #include "mojo/core/embedder/embedder.h"
-#include "mojo/public/cpp/bindings/strong_binding_set.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/bindings/unique_receiver_set.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
 #include "services/network/test/test_network_connection_tracker.h"
@@ -44,12 +45,12 @@
         base::Bind(&PublicIpAddressGeolocatorTest::OnMojoBadMessage,
                    base::Unretained(this)));
 
-    binding_set_.AddBinding(
+    receiver_set_.Add(
         std::make_unique<PublicIpAddressGeolocator>(
             PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS, notifier_.get(),
             base::Bind(&PublicIpAddressGeolocatorTest::OnGeolocatorBadMessage,
                        base::Unretained(this))),
-        mojo::MakeRequest(&public_ip_address_geolocator_));
+        public_ip_address_geolocator_.BindNewPipeAndPassReceiver());
   }
 
   void TearDown() override {
@@ -65,7 +66,7 @@
 
   // Deal with PublicIpAddressGeolocator bad message.
   void OnGeolocatorBadMessage(const std::string& message) {
-    binding_set_.ReportBadMessage(message);
+    receiver_set_.ReportBadMessage(message);
   }
 
   // Invokes QueryNextPosition on |public_ip_address_geolocator_|, and runs
@@ -87,8 +88,8 @@
   // Result of the latest completed call to QueryNextPosition.
   mojom::GeopositionPtr position_;
 
-  // StrongBindingSet to mojom::Geolocation.
-  mojo::StrongBindingSet<mojom::Geolocation> binding_set_;
+  // UniqueReceiverSet to mojom::Geolocation.
+  mojo::UniqueReceiverSet<mojom::Geolocation> receiver_set_;
 
   // Test task runner.
   base::test::TaskEnvironment task_environment_;
@@ -104,7 +105,7 @@
   std::unique_ptr<PublicIpAddressLocationNotifier> notifier_;
 
   // The object under test.
-  mojom::GeolocationPtr public_ip_address_geolocator_;
+  mojo::Remote<mojom::Geolocation> public_ip_address_geolocator_;
 
   // Test URLLoaderFactory for handling requests to the geolocation API.
   network::TestURLLoaderFactory test_url_loader_factory_;
@@ -147,8 +148,7 @@
 // connection error and reports a bad message.
 TEST_F(PublicIpAddressGeolocatorTest, ProhibitedOverlappingCalls) {
   base::RunLoop loop;
-  public_ip_address_geolocator_.set_connection_error_handler(
-      loop.QuitClosure());
+  public_ip_address_geolocator_.set_disconnect_handler(loop.QuitClosure());
 
   // Issue two overlapping calls to QueryNextPosition.
   QueryNextPosition(base::Closure());
diff --git a/services/image_annotation/annotator.cc b/services/image_annotation/annotator.cc
index 863c318f..4b3f87a 100644
--- a/services/image_annotation/annotator.cc
+++ b/services/image_annotation/annotator.cc
@@ -454,7 +454,7 @@
                              base::Value(base::Value::Type::DICTIONARY));
 
     base::Value engine_params_list(base::Value::Type::LIST);
-    engine_params_list.GetList().push_back(std::move(ocr_engine_params));
+    engine_params_list.Append(std::move(ocr_engine_params));
 
     // Also add a description annotations request if the image is within model
     // policy.
@@ -464,7 +464,7 @@
       // Add preferred description language if it has been specified.
       if (!it->desc_lang_tag.empty()) {
         base::Value desc_lang_list(base::Value::Type::LIST);
-        desc_lang_list.GetList().push_back(base::Value(it->desc_lang_tag));
+        desc_lang_list.Append(base::Value(it->desc_lang_tag));
 
         desc_params.SetKey("preferredLanguages", std::move(desc_lang_list));
       }
@@ -472,7 +472,7 @@
       base::Value engine_params(base::Value::Type::DICTIONARY);
       engine_params.SetKey("descriptionParameters", std::move(desc_params));
 
-      engine_params_list.GetList().push_back(std::move(engine_params));
+      engine_params_list.Append(std::move(engine_params));
     }
     ReportImageRequestIncludesDesc(it->desc_requested);
 
@@ -482,7 +482,7 @@
     image_request.SetKey("imageBytes", base::Value(std::move(base64_data)));
     image_request.SetKey("engineParameters", std::move(engine_params_list));
 
-    image_request_list.GetList().push_back(std::move(image_request));
+    image_request_list.Append(std::move(image_request));
   }
 
   base::Value request(base::Value::Type::DICTIONARY);
diff --git a/services/network/chunked_data_pipe_upload_data_stream.cc b/services/network/chunked_data_pipe_upload_data_stream.cc
index 4f59ea5..2aab30f 100644
--- a/services/network/chunked_data_pipe_upload_data_stream.cc
+++ b/services/network/chunked_data_pipe_upload_data_stream.cc
@@ -15,7 +15,7 @@
 
 ChunkedDataPipeUploadDataStream::ChunkedDataPipeUploadDataStream(
     scoped_refptr<ResourceRequestBody> resource_request_body,
-    mojom::ChunkedDataPipeGetterPtr chunked_data_pipe_getter)
+    mojo::PendingRemote<mojom::ChunkedDataPipeGetter> chunked_data_pipe_getter)
     : net::UploadDataStream(true /* is_chunked */,
                             resource_request_body->identifier()),
       resource_request_body_(std::move(resource_request_body)),
@@ -23,7 +23,7 @@
       handle_watcher_(FROM_HERE,
                       mojo::SimpleWatcher::ArmingPolicy::MANUAL,
                       base::SequencedTaskRunnerHandle::Get()) {
-  chunked_data_pipe_getter_.set_connection_error_handler(
+  chunked_data_pipe_getter_.set_disconnect_handler(
       base::BindOnce(&ChunkedDataPipeUploadDataStream::OnDataPipeGetterClosed,
                      base::Unretained(this)));
   chunked_data_pipe_getter_->GetSize(
@@ -41,7 +41,7 @@
     return status_;
 
   // If the data pipe was closed, just fail initialization.
-  if (chunked_data_pipe_getter_.encountered_error())
+  if (!chunked_data_pipe_getter_.is_connected())
     return net::ERR_FAILED;
 
   // Get a new data pipe and start.
diff --git a/services/network/chunked_data_pipe_upload_data_stream.h b/services/network/chunked_data_pipe_upload_data_stream.h
index c9ec963..45f7c2b5 100644
--- a/services/network/chunked_data_pipe_upload_data_stream.h
+++ b/services/network/chunked_data_pipe_upload_data_stream.h
@@ -13,6 +13,8 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/optional.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "mojo/public/cpp/system/data_pipe.h"
 #include "mojo/public/cpp/system/simple_watcher.h"
 #include "net/base/completion_once_callback.h"
@@ -36,7 +38,8 @@
   // life of the UploadDataStream.
   ChunkedDataPipeUploadDataStream(
       scoped_refptr<ResourceRequestBody> resource_request_body,
-      mojom::ChunkedDataPipeGetterPtr chunked_data_pipe_getter);
+      mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
+          chunked_data_pipe_getter);
 
   ~ChunkedDataPipeUploadDataStream() override;
 
@@ -59,7 +62,7 @@
   void OnDataPipeGetterClosed();
 
   scoped_refptr<ResourceRequestBody> resource_request_body_;
-  mojom::ChunkedDataPipeGetterPtr chunked_data_pipe_getter_;
+  mojo::Remote<mojom::ChunkedDataPipeGetter> chunked_data_pipe_getter_;
   mojo::ScopedDataPipeConsumerHandle data_pipe_;
   // Watcher for |data_pipe_|. Only armed while there's a pending read.
   mojo::SimpleWatcher handle_watcher_;
diff --git a/services/network/chunked_data_pipe_upload_data_stream_unittest.cc b/services/network/chunked_data_pipe_upload_data_stream_unittest.cc
index 8ab8320..13f3bd7c 100644
--- a/services/network/chunked_data_pipe_upload_data_stream_unittest.cc
+++ b/services/network/chunked_data_pipe_upload_data_stream_unittest.cc
@@ -40,7 +40,7 @@
     chunked_data_pipe_getter_ = std::make_unique<TestChunkedDataPipeGetter>();
     chunked_upload_stream_ = std::make_unique<ChunkedDataPipeUploadDataStream>(
         base::MakeRefCounted<network::ResourceRequestBody>(),
-        chunked_data_pipe_getter_->GetDataPipeGetterPtr());
+        chunked_data_pipe_getter_->GetDataPipeGetterRemote());
     // Nothing interesting happens before Init, so always wait for it in the
     // test fixture.
     net::TestCompletionCallback callback;
@@ -319,7 +319,7 @@
   chunked_data_pipe_getter_ = std::make_unique<TestChunkedDataPipeGetter>();
   chunked_upload_stream_ = std::make_unique<ChunkedDataPipeUploadDataStream>(
       base::MakeRefCounted<network::ResourceRequestBody>(),
-      chunked_data_pipe_getter_->GetDataPipeGetterPtr());
+      chunked_data_pipe_getter_->GetDataPipeGetterRemote());
   get_size_callback_ = chunked_data_pipe_getter_->WaitForGetSize();
   std::move(get_size_callback_).Run(net::OK, kData.size());
   // Wait for the ChunkedUploadStream to receive the size.
@@ -408,7 +408,7 @@
   chunked_data_pipe_getter_ = std::make_unique<TestChunkedDataPipeGetter>();
   chunked_upload_stream_ = std::make_unique<ChunkedDataPipeUploadDataStream>(
       base::MakeRefCounted<network::ResourceRequestBody>(),
-      chunked_data_pipe_getter_->GetDataPipeGetterPtr());
+      chunked_data_pipe_getter_->GetDataPipeGetterRemote());
   get_size_callback_ = chunked_data_pipe_getter_->WaitForGetSize();
   std::move(get_size_callback_).Run(net::ERR_ACCESS_DENIED, 0);
   // Wait for the ChunkedUploadStream to receive the size.
@@ -712,7 +712,7 @@
   chunked_data_pipe_getter_ = std::make_unique<TestChunkedDataPipeGetter>();
   chunked_upload_stream_ = std::make_unique<ChunkedDataPipeUploadDataStream>(
       base::MakeRefCounted<network::ResourceRequestBody>(),
-      chunked_data_pipe_getter_->GetDataPipeGetterPtr());
+      chunked_data_pipe_getter_->GetDataPipeGetterRemote());
 
   // Destroy the DataPipeGetter pipe, which is the pipe used for
   // GetSizeCallback.
diff --git a/services/network/cors/cors_url_loader_unittest.cc b/services/network/cors/cors_url_loader_unittest.cc
index ecf4547..cc5642da 100644
--- a/services/network/cors/cors_url_loader_unittest.cc
+++ b/services/network/cors/cors_url_loader_unittest.cc
@@ -1220,6 +1220,92 @@
   EXPECT_EQ(net::OK, client().completion_status().error_code);
 }
 
+// Tests if CorsURLLoader takes into account
+// ResourceRequest::isolated_world_origin when consulting OriginAccessList.
+TEST_F(CorsURLLoaderTest, OriginAccessList_IsolatedWorldOrigin) {
+  const GURL main_world_origin("http://main-world.com");
+  const GURL isolated_world_origin("http://isolated-world.com");
+  const GURL url("http://other.com/foo.png");
+
+  AddAllowListEntryForOrigin(url::Origin::Create(isolated_world_origin),
+                             url.scheme(), url.host(),
+                             mojom::CorsDomainMatchMode::kDisallowSubdomains);
+
+  ResourceRequest request;
+  request.mode = mojom::RequestMode::kCors;
+  request.credentials_mode = mojom::CredentialsMode::kOmit;
+  request.method = net::HttpRequestHeaders::kGetMethod;
+  request.url = url;
+  request.request_initiator = url::Origin::Create(main_world_origin);
+  request.isolated_world_origin = url::Origin::Create(isolated_world_origin);
+  CreateLoaderAndStart(request);
+
+  NotifyLoaderClientOnReceiveResponse();
+  NotifyLoaderClientOnComplete(net::OK);
+
+  RunUntilComplete();
+
+  EXPECT_TRUE(IsNetworkLoaderStarted());
+  EXPECT_FALSE(client().has_received_redirect());
+  EXPECT_TRUE(client().has_received_response());
+  EXPECT_EQ(network::mojom::FetchResponseType::kBasic,
+            client().response_head().response_type);
+  EXPECT_TRUE(client().has_received_completion());
+  EXPECT_EQ(net::OK, client().completion_status().error_code);
+}
+
+// Tests if CorsURLLoader takes into account
+// ResourceRequest::isolated_world_origin when consulting OriginAccessList
+// after redirects.
+TEST_F(CorsURLLoaderTest, OriginAccessList_IsolatedWorldOrigin_Redirect) {
+  const GURL main_world_origin("http://main-world.com");
+  const GURL isolated_world_origin("http://isolated-world.com");
+  const GURL url("http://other.com/foo.png");
+  // |new_url| is same-origin as |url| to avoid tainting the response
+  // in CorsURLLoader::OnReceiveRedirect.
+  const GURL new_url("http://other.com/bar.png");
+
+  AddAllowListEntryForOrigin(url::Origin::Create(isolated_world_origin),
+                             url.scheme(), url.host(),
+                             mojom::CorsDomainMatchMode::kDisallowSubdomains);
+  AddAllowListEntryForOrigin(url::Origin::Create(isolated_world_origin),
+                             new_url.scheme(), new_url.host(),
+                             mojom::CorsDomainMatchMode::kDisallowSubdomains);
+
+  ResourceRequest request;
+  // Using no-cors to force opaque response (unless the allowlist entry added
+  // above is taken into account).
+  request.mode = mojom::RequestMode::kNoCors;
+  request.credentials_mode = mojom::CredentialsMode::kOmit;
+  request.method = net::HttpRequestHeaders::kGetMethod;
+  request.url = url;
+  request.request_initiator = url::Origin::Create(main_world_origin);
+  request.isolated_world_origin = url::Origin::Create(isolated_world_origin);
+  CreateLoaderAndStart(request);
+
+  NotifyLoaderClientOnReceiveRedirect(CreateRedirectInfo(301, "GET", new_url));
+  RunUntilRedirectReceived();
+
+  EXPECT_TRUE(IsNetworkLoaderStarted());
+  EXPECT_FALSE(client().has_received_completion());
+  EXPECT_FALSE(client().has_received_response());
+  EXPECT_TRUE(client().has_received_redirect());
+
+  FollowRedirect();
+  NotifyLoaderClientOnReceiveResponse();
+  NotifyLoaderClientOnComplete(net::OK);
+
+  RunUntilComplete();
+
+  EXPECT_TRUE(IsNetworkLoaderStarted());
+  EXPECT_TRUE(client().has_received_redirect());
+  EXPECT_TRUE(client().has_received_response());
+  EXPECT_EQ(network::mojom::FetchResponseType::kBasic,
+            client().response_head().response_type);
+  EXPECT_TRUE(client().has_received_completion());
+  EXPECT_EQ(net::OK, client().completion_status().error_code);
+}
+
 // Check if higher-priority block list wins.
 TEST_F(CorsURLLoaderTest, OriginAccessList_Blocked) {
   const GURL origin("http://example.com");
diff --git a/services/network/public/cpp/cors/origin_access_list_unittest.cc b/services/network/public/cpp/cors/origin_access_list_unittest.cc
index b59a5ee..72dae9a 100644
--- a/services/network/public/cpp/cors/origin_access_list_unittest.cc
+++ b/services/network/public/cpp/cors/origin_access_list_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "services/network/public/cpp/cors/origin_access_list.h"
+#include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/mojom/cors.mojom.h"
 #include "services/network/public/mojom/cors_origin_pattern.mojom.h"
 
@@ -59,6 +60,17 @@
   const url::Origin& https_google_origin() const {
     return https_google_origin_;
   }
+  const url::Origin& source_origin() const { return source_origin_; }
+  OriginAccessList::AccessState CheckAccess(
+      const url::Origin& request_initiator,
+      const base::Optional<url::Origin>& isolated_world_origin,
+      const GURL& url) {
+    ResourceRequest request;
+    request.url = url;
+    request.request_initiator = request_initiator;
+    request.isolated_world_origin = isolated_world_origin;
+    return list_.CheckAccessState(request);
+  }
   bool IsAllowed(const url::Origin& destination_origin) const {
     return list_.CheckAccessState(source_origin_,
                                   destination_origin.GetURL()) ==
@@ -140,6 +152,38 @@
   EXPECT_TRUE(IsAllowed(https_another_port_example_origin()));
 }
 
+TEST_F(OriginAccessListTest, IsAccessAllowedForIsolatedWorldOrigin) {
+  // By default, no access should be allowed.
+  EXPECT_FALSE(IsAllowed(https_example_origin()));
+
+  // Adding access for https://example.com should work, but should not grant
+  // access to different ports for the same scheme:host pair.
+  GURL target("https://example.com");
+  SetAllowListEntry(target.scheme(), target.host(), kHttpsPort,
+                    kDisallowSubdomains, kAllowOnlySpecifiedPort);
+
+  // When request is made by a Chrome Extension background page,
+  // request_initiator is the origin that should be used as a key for
+  // OriginAccessList.
+  EXPECT_EQ(OriginAccessList::AccessState::kAllowed,
+            CheckAccess(source_origin(), base::nullopt, target));
+
+  // When request is made by a Chrome Extension content script,
+  // isolated_world_origin is the origin that should be used as a key for
+  // OriginAccessList.
+  EXPECT_EQ(OriginAccessList::AccessState::kAllowed,
+            CheckAccess(https_another_port_example_origin(), source_origin(),
+                        target));
+
+  // Impossible situation with Chrome Extensions - the isolated_world_origin is
+  // non-empty, but request_intiator is the key in the OriginAccessList.  In
+  // this impossible situation it is okay to indicate that no entry is listed
+  // in the OriginAccessList.
+  EXPECT_EQ(OriginAccessList::AccessState::kNotListed,
+            CheckAccess(source_origin(), https_another_port_example_origin(),
+                        target));
+}
+
 TEST_F(OriginAccessListTest, IsAccessAllowed) {
   // By default, no access should be allowed.
   EXPECT_FALSE(IsAllowed(https_example_origin()));
diff --git a/services/network/public/cpp/data_element.cc b/services/network/public/cpp/data_element.cc
index f7d2553df..a75bb59 100644
--- a/services/network/public/cpp/data_element.cc
+++ b/services/network/public/cpp/data_element.cc
@@ -71,9 +71,10 @@
 }
 
 void DataElement::SetToChunkedDataPipe(
-    mojom::ChunkedDataPipeGetterPtr chunked_data_pipe_getter) {
+    mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
+        chunked_data_pipe_getter) {
   type_ = mojom::DataElementType::kChunkedDataPipe;
-  chunked_data_pipe_getter_ = chunked_data_pipe_getter.PassInterface();
+  chunked_data_pipe_getter_ = std::move(chunked_data_pipe_getter);
 }
 
 base::File DataElement::ReleaseFile() {
@@ -100,7 +101,7 @@
   return clone;
 }
 
-mojom::ChunkedDataPipeGetterPtrInfo
+mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
 DataElement::ReleaseChunkedDataPipeGetter() {
   DCHECK_EQ(mojom::DataElementType::kChunkedDataPipe, type_);
   return std::move(chunked_data_pipe_getter_);
diff --git a/services/network/public/cpp/data_element.h b/services/network/public/cpp/data_element.h
index 88bc820..c3bd96e 100644
--- a/services/network/public/cpp/data_element.h
+++ b/services/network/public/cpp/data_element.h
@@ -167,8 +167,8 @@
   // sent. This method triggers a chunked upload, which not all servers may
   // support, so SetToDataPipe should be used instead, unless talking with a
   // server known to support chunked uploads.
-  void SetToChunkedDataPipe(
-      mojom::ChunkedDataPipeGetterPtr chunked_data_pipe_getter);
+  void SetToChunkedDataPipe(mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
+                                chunked_data_pipe_getter);
 
   // Takes ownership of the File, if this is of TYPE_RAW_FILE. The file is open
   // for reading (asynchronous reading on Windows).
@@ -180,7 +180,8 @@
 
   // Takes ownership of the DataPipeGetter, if this is of
   // TYPE_CHUNKED_DATA_PIPE.
-  mojom::ChunkedDataPipeGetterPtrInfo ReleaseChunkedDataPipeGetter();
+  mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
+  ReleaseChunkedDataPipeGetter();
 
  private:
   FRIEND_TEST_ALL_PREFIXES(BlobAsyncTransportStrategyTest, TestInvalidParams);
@@ -203,7 +204,7 @@
   // For TYPE_DATA_PIPE.
   mojo::PendingRemote<mojom::DataPipeGetter> data_pipe_getter_;
   // For TYPE_CHUNKED_DATA_PIPE.
-  mojom::ChunkedDataPipeGetterPtrInfo chunked_data_pipe_getter_;
+  mojo::PendingRemote<mojom::ChunkedDataPipeGetter> chunked_data_pipe_getter_;
   uint64_t offset_;
   uint64_t length_;
   base::Time expected_modification_time_;
diff --git a/services/network/public/cpp/network_ipc_param_traits.cc b/services/network/public/cpp/network_ipc_param_traits.cc
index e396175..ad07a680 100644
--- a/services/network/public/cpp/network_ipc_param_traits.cc
+++ b/services/network/public/cpp/network_ipc_param_traits.cc
@@ -53,7 +53,7 @@
     case network::mojom::DataElementType::kChunkedDataPipe: {
       WriteParam(m, const_cast<network::DataElement&>(p)
                         .ReleaseChunkedDataPipeGetter()
-                        .PassHandle()
+                        .PassPipe()
                         .release());
       break;
     }
@@ -138,13 +138,13 @@
       return true;
     }
     case network::mojom::DataElementType::kChunkedDataPipe: {
-      network::mojom::ChunkedDataPipeGetterPtr chunked_data_pipe_getter;
       mojo::MessagePipeHandle message_pipe;
       if (!ReadParam(m, iter, &message_pipe))
         return false;
-      chunked_data_pipe_getter.Bind(
-          network::mojom::ChunkedDataPipeGetterPtrInfo(
-              mojo::ScopedMessagePipeHandle(message_pipe), 0u));
+      mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter>
+          chunked_data_pipe_getter(mojo::ScopedMessagePipeHandle(message_pipe),
+                                   0u);
+
       r->SetToChunkedDataPipe(std::move(chunked_data_pipe_getter));
       return true;
     }
diff --git a/services/network/public/cpp/resource_request_body.cc b/services/network/public/cpp/resource_request_body.cc
index debf2e0..a865aeb 100644
--- a/services/network/public/cpp/resource_request_body.cc
+++ b/services/network/public/cpp/resource_request_body.cc
@@ -88,7 +88,8 @@
 }
 
 void ResourceRequestBody::SetToChunkedDataPipe(
-    mojom::ChunkedDataPipeGetterPtr chunked_data_pipe_getter) {
+    mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
+        chunked_data_pipe_getter) {
   DCHECK(elements_.empty());
 
   elements_.push_back(DataElement());
diff --git a/services/network/public/cpp/resource_request_body.h b/services/network/public/cpp/resource_request_body.h
index 330e0852..6d4920d3 100644
--- a/services/network/public/cpp/resource_request_body.h
+++ b/services/network/public/cpp/resource_request_body.h
@@ -78,8 +78,8 @@
   // no web APIs that send uploads with unknown request body sizes, so this
   // method should only be used when talking to servers that are are known to
   // support chunked uploads.
-  void SetToChunkedDataPipe(
-      mojom::ChunkedDataPipeGetterPtr chunked_data_pipe_getter);
+  void SetToChunkedDataPipe(mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
+                                chunked_data_pipe_getter);
 
   const std::vector<DataElement>* elements() const { return &elements_; }
   std::vector<DataElement>* elements_mutable() { return &elements_; }
diff --git a/services/network/public/cpp/url_request_mojom_traits.h b/services/network/public/cpp/url_request_mojom_traits.h
index 578f76d..72b2809 100644
--- a/services/network/public/cpp/url_request_mojom_traits.h
+++ b/services/network/public/cpp/url_request_mojom_traits.h
@@ -311,10 +311,10 @@
       return mojo::NullRemote();
     return element.CloneDataPipeGetter();
   }
-  static network::mojom::ChunkedDataPipeGetterPtrInfo chunked_data_pipe_getter(
-      const network::DataElement& element) {
+  static mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter>
+  chunked_data_pipe_getter(const network::DataElement& element) {
     if (element.type_ != network::mojom::DataElementType::kChunkedDataPipe)
-      return nullptr;
+      return mojo::NullRemote();
     return const_cast<network::DataElement&>(element)
         .ReleaseChunkedDataPipeGetter();
   }
diff --git a/services/network/test_chunked_data_pipe_getter.cc b/services/network/test_chunked_data_pipe_getter.cc
index 4754463..8c11530 100644
--- a/services/network/test_chunked_data_pipe_getter.cc
+++ b/services/network/test_chunked_data_pipe_getter.cc
@@ -9,21 +9,18 @@
 
 namespace network {
 
-TestChunkedDataPipeGetter::TestChunkedDataPipeGetter() : binding_(this) {}
+TestChunkedDataPipeGetter::TestChunkedDataPipeGetter() = default;
 
-TestChunkedDataPipeGetter::~TestChunkedDataPipeGetter() {}
+TestChunkedDataPipeGetter::~TestChunkedDataPipeGetter() = default;
 
-mojom::ChunkedDataPipeGetterPtr
-TestChunkedDataPipeGetter::GetDataPipeGetterPtr() {
-  EXPECT_FALSE(binding_.is_bound());
-
-  mojom::ChunkedDataPipeGetterPtr data_pipe_getter_ptr;
-  binding_.Bind(mojo::MakeRequest(&data_pipe_getter_ptr));
-  return data_pipe_getter_ptr;
+mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
+TestChunkedDataPipeGetter::GetDataPipeGetterRemote() {
+  EXPECT_FALSE(receiver_.is_bound());
+  return receiver_.BindNewPipeAndPassRemote();
 }
 
 void TestChunkedDataPipeGetter::ClosePipe() {
-  binding_.Close();
+  receiver_.reset();
 }
 
 mojom::ChunkedDataPipeGetter::GetSizeCallback
diff --git a/services/network/test_chunked_data_pipe_getter.h b/services/network/test_chunked_data_pipe_getter.h
index 48e05e7e1..635513c 100644
--- a/services/network/test_chunked_data_pipe_getter.h
+++ b/services/network/test_chunked_data_pipe_getter.h
@@ -9,7 +9,8 @@
 
 #include "base/macros.h"
 #include "base/run_loop.h"
-#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/system/data_pipe.h"
 #include "services/network/public/mojom/chunked_data_pipe_getter.mojom.h"
 
@@ -23,9 +24,9 @@
   TestChunkedDataPipeGetter();
   ~TestChunkedDataPipeGetter() override;
 
-  // Returns the mojo::ChunkedDataPipeGetterPtr corresponding to |this|. May
-  // only be called once.
-  mojom::ChunkedDataPipeGetterPtr GetDataPipeGetterPtr();
+  // Returns the mojo::PendingRemote<mojom::ChunkedDataPipeGetter> corresponding
+  // to |this|. May only be called once.
+  mojo::PendingRemote<mojom::ChunkedDataPipeGetter> GetDataPipeGetterRemote();
 
   // Close the mojom::DataPipeGetter pipe.
   void ClosePipe();
@@ -41,7 +42,7 @@
   std::unique_ptr<base::RunLoop> get_size_run_loop_;
   std::unique_ptr<base::RunLoop> start_reading_run_loop_;
 
-  mojo::Binding<mojom::ChunkedDataPipeGetter> binding_;
+  mojo::Receiver<mojom::ChunkedDataPipeGetter> receiver_{this};
   mojo::ScopedDataPipeProducerHandle write_pipe_;
   GetSizeCallback get_size_callback_;
   bool received_size_callback_ = false;
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
index 69dbf99..67f6300 100644
--- a/services/network/url_loader.cc
+++ b/services/network/url_loader.cc
@@ -202,9 +202,8 @@
       body->elements()->begin()->type() ==
           network::mojom::DataElementType::kChunkedDataPipe) {
     return std::make_unique<ChunkedDataPipeUploadDataStream>(
-        body, mojom::ChunkedDataPipeGetterPtr(
-                  const_cast<DataElement&>(body->elements()->front())
-                      .ReleaseChunkedDataPipeGetter()));
+        body, const_cast<DataElement&>(body->elements()->front())
+                  .ReleaseChunkedDataPipeGetter());
   }
 
   auto opened_file = opened_files.begin();
diff --git a/services/network/url_loader_unittest.cc b/services/network/url_loader_unittest.cc
index bf3cd5b..46ff15b 100644
--- a/services/network/url_loader_unittest.cc
+++ b/services/network/url_loader_unittest.cc
@@ -1788,7 +1788,7 @@
       CreateResourceRequest("POST", test_server()->GetURL("/echo"));
   request.request_body = base::MakeRefCounted<ResourceRequestBody>();
   request.request_body->SetToChunkedDataPipe(
-      data_pipe_getter.GetDataPipeGetterPtr());
+      data_pipe_getter.GetDataPipeGetterRemote());
 
   base::RunLoop delete_run_loop;
   mojom::URLLoaderPtr loader;
diff --git a/services/tracing/OWNERS b/services/tracing/OWNERS
index 4eb41f25..816d0e2 100644
--- a/services/tracing/OWNERS
+++ b/services/tracing/OWNERS
@@ -1,5 +1,4 @@
 file://base/trace_event/OWNERS
-chiniforooshan@chromium.org
 
 per-file manifest.cc=set noparent
 per-file manifest.cc=file://ipc/SECURITY_OWNERS
diff --git a/services/tracing/perfetto/json_trace_exporter.cc b/services/tracing/perfetto/json_trace_exporter.cc
index b6ff849..c058b06 100644
--- a/services/tracing/perfetto/json_trace_exporter.cc
+++ b/services/tracing/perfetto/json_trace_exporter.cc
@@ -353,7 +353,7 @@
     buf_dict->SetInteger("abi_violations", buf_stats.abi_violations());
     buf_dict->SetInteger("trace_writer_packet_loss",
                          buf_stats.trace_writer_packet_loss());
-    buf_list->GetList().push_back(std::move(buf_value));
+    buf_list->Append(std::move(buf_value));
   }
   dict->SetList("buffer_stats", std::move(buf_list));
   metadata_->SetDictionary("perfetto_trace_stats", std::move(dict));
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index 1544356..897f5aca 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -2364,14 +2364,14 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "chrome.tests"
             }
           ],
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 5366f9b..8a5a4e5 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -98,7 +98,7 @@
       {
         "args": [
           "--enable-features=BackForwardCache",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.browser_tests.filter",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.android_browsertests.filter",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -146,7 +146,7 @@
       {
         "args": [
           "--enable-features=BackForwardCache",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.browser_tests.filter",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.chrome_public_test_apk.filter",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -242,7 +242,7 @@
       {
         "args": [
           "--enable-features=BackForwardCache",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.browser_tests.filter",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.content_shell_test_apk.filter",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index b3920f1..615fa15b 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -11841,7 +11841,7 @@
           "dimension_sets": [
             {
               "gpu": "1002:6821",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -11849,7 +11849,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -11878,7 +11878,7 @@
           "dimension_sets": [
             {
               "gpu": "1002:6821",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -11886,7 +11886,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -11916,7 +11916,7 @@
           "dimension_sets": [
             {
               "gpu": "1002:6821",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -11924,7 +11924,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -11951,7 +11951,7 @@
           "dimension_sets": [
             {
               "gpu": "1002:6821",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -11959,7 +11959,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -11985,7 +11985,7 @@
           "dimension_sets": [
             {
               "gpu": "1002:6821",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -11993,7 +11993,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12019,7 +12019,7 @@
           "dimension_sets": [
             {
               "gpu": "1002:6821",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12027,7 +12027,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12050,7 +12050,7 @@
           "dimension_sets": [
             {
               "gpu": "1002:6821",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12058,7 +12058,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12085,7 +12085,7 @@
           "dimension_sets": [
             {
               "gpu": "1002:6821",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12093,7 +12093,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12116,7 +12116,7 @@
           "dimension_sets": [
             {
               "gpu": "1002:6821",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12124,7 +12124,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12160,7 +12160,7 @@
           "dimension_sets": [
             {
               "gpu": "1002:6821",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12169,7 +12169,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12202,7 +12202,7 @@
           "dimension_sets": [
             {
               "gpu": "1002:6821",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12211,7 +12211,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12244,7 +12244,7 @@
           "dimension_sets": [
             {
               "gpu": "1002:6821",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12253,7 +12253,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12286,7 +12286,7 @@
           "dimension_sets": [
             {
               "gpu": "1002:6821",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12295,7 +12295,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12332,7 +12332,7 @@
           "dimension_sets": [
             {
               "gpu": "1002:6821",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12341,7 +12341,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12381,7 +12381,7 @@
           "dimension_sets": [
             {
               "gpu": "1002:6821",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12390,7 +12390,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12438,7 +12438,7 @@
           "dimension_sets": [
             {
               "gpu": "1002:6821",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12447,7 +12447,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12482,7 +12482,7 @@
           "dimension_sets": [
             {
               "gpu": "1002:6821",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12491,7 +12491,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12524,7 +12524,7 @@
           "dimension_sets": [
             {
               "gpu": "1002:6821",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12533,7 +12533,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12568,7 +12568,7 @@
           "dimension_sets": [
             {
               "gpu": "1002:6821",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12577,7 +12577,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12611,7 +12611,7 @@
           "dimension_sets": [
             {
               "gpu": "1002:6821",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12620,7 +12620,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12654,7 +12654,7 @@
           "dimension_sets": [
             {
               "gpu": "1002:6821",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12663,7 +12663,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12695,7 +12695,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12703,7 +12703,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12732,7 +12732,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12740,7 +12740,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12770,7 +12770,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12778,7 +12778,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12805,7 +12805,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12813,7 +12813,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12839,7 +12839,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12847,7 +12847,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12873,7 +12873,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12881,7 +12881,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12904,7 +12904,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12912,7 +12912,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12939,7 +12939,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12947,7 +12947,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -12970,7 +12970,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -12978,7 +12978,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13014,7 +13014,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13023,7 +13023,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13056,7 +13056,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13065,7 +13065,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13098,7 +13098,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13107,7 +13107,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13140,7 +13140,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13149,7 +13149,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13186,7 +13186,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13195,7 +13195,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13235,7 +13235,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13244,7 +13244,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13292,7 +13292,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13301,7 +13301,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13336,7 +13336,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13345,7 +13345,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13378,7 +13378,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13387,7 +13387,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13422,7 +13422,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13431,7 +13431,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13465,7 +13465,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13474,7 +13474,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13508,7 +13508,7 @@
           "dimension_sets": [
             {
               "gpu": "8086:0a2e",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13517,7 +13517,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13549,7 +13549,7 @@
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13557,7 +13557,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13586,7 +13586,7 @@
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13594,7 +13594,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13624,7 +13624,7 @@
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13632,7 +13632,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13659,7 +13659,7 @@
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13667,7 +13667,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13693,7 +13693,7 @@
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13701,7 +13701,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13727,7 +13727,7 @@
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13735,7 +13735,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13758,7 +13758,7 @@
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13766,7 +13766,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13793,7 +13793,7 @@
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13801,7 +13801,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13824,7 +13824,7 @@
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13832,7 +13832,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13868,7 +13868,7 @@
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13877,7 +13877,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13910,7 +13910,7 @@
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13919,7 +13919,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13952,7 +13952,7 @@
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -13961,7 +13961,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -13994,7 +13994,7 @@
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -14003,7 +14003,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -14040,7 +14040,7 @@
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -14049,7 +14049,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -14089,7 +14089,7 @@
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -14098,7 +14098,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -14146,7 +14146,7 @@
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -14155,7 +14155,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -14190,7 +14190,7 @@
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -14199,7 +14199,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -14232,7 +14232,7 @@
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -14241,7 +14241,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -14276,7 +14276,7 @@
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -14285,7 +14285,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -14319,7 +14319,7 @@
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -14328,7 +14328,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
@@ -14362,7 +14362,7 @@
           "dimension_sets": [
             {
               "gpu": "10de:0fe9",
-              "os": "Mac-10.14.4",
+              "os": "Mac-10.14.6",
               "pool": "Chrome-GPU"
             }
           ],
@@ -14371,7 +14371,7 @@
           "optional_dimensions": {
             "300": [
               {
-                "os": "Mac-10.14.3"
+                "os": "Mac-10.14.4"
               }
             ],
             "600": [
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn
index 66489ef..26931fb8 100644
--- a/testing/buildbot/filters/BUILD.gn
+++ b/testing/buildbot/filters/BUILD.gn
@@ -16,6 +16,14 @@
 # $ for i in $(ls -1 testing/buildbot/filters/*.browser_tests.*filter ); \
 #   do echo "    \"//$i\","; done | sort
 
+source_set("android_browsertests_filters") {
+  testonly = true
+
+  data = [
+    "//testing/buildbot/filters/bfcache.android_browsertests.filter",
+  ]
+}
+
 source_set("blink_web_tests_filter") {
   testonly = true
 
@@ -45,6 +53,14 @@
   ]
 }
 
+source_set("chrome_public_test_apk_filters") {
+  testonly = true
+
+  data = [
+    "//testing/buildbot/filters/bfcache.chrome_public_test_apk.filter",
+  ]
+}
+
 source_set("chromeos_filters") {
   data = [
     "//testing/buildbot/filters/chromeos.base_unittests.filter",
@@ -55,15 +71,6 @@
   ]
 }
 
-source_set("content_unittests_filters") {
-  testonly = true
-
-  data = [
-    "//testing/buildbot/filters/bfcache.content_unittests.filter",
-    "//testing/buildbot/filters/webrtc.content_unittests.filter",
-  ]
-}
-
 source_set("content_browsertests_filters") {
   testonly = true
 
@@ -78,6 +85,23 @@
   ]
 }
 
+source_set("content_shell_test_apk_filters") {
+  testonly = true
+
+  data = [
+    "//testing/buildbot/filters/bfcache.content_shell_test_apk.filter",
+  ]
+}
+
+source_set("content_unittests_filters") {
+  testonly = true
+
+  data = [
+    "//testing/buildbot/filters/bfcache.content_unittests.filter",
+    "//testing/buildbot/filters/webrtc.content_unittests.filter",
+  ]
+}
+
 source_set("fuchsia_filters") {
   data = [
     "//testing/buildbot/filters/fuchsia.base_perftests.filter",
diff --git a/testing/buildbot/filters/bfcache.android_browsertests.filter b/testing/buildbot/filters/bfcache.android_browsertests.filter
new file mode 100644
index 0000000..2d8f82a
--- /dev/null
+++ b/testing/buildbot/filters/bfcache.android_browsertests.filter
@@ -0,0 +1 @@
+# These tests currently fail when run with --enable-features=BackForwardCache
diff --git a/testing/buildbot/filters/bfcache.chrome_public_test_apk.filter b/testing/buildbot/filters/bfcache.chrome_public_test_apk.filter
new file mode 100644
index 0000000..2d8f82a
--- /dev/null
+++ b/testing/buildbot/filters/bfcache.chrome_public_test_apk.filter
@@ -0,0 +1 @@
+# These tests currently fail when run with --enable-features=BackForwardCache
diff --git a/testing/buildbot/filters/bfcache.content_shell_test_apk.filter b/testing/buildbot/filters/bfcache.content_shell_test_apk.filter
new file mode 100644
index 0000000..2d8f82a
--- /dev/null
+++ b/testing/buildbot/filters/bfcache.content_shell_test_apk.filter
@@ -0,0 +1 @@
+# These tests currently fail when run with --enable-features=BackForwardCache
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl
index 125b099..fdff756 100644
--- a/testing/buildbot/mixins.pyl
+++ b/testing/buildbot/mixins.pyl
@@ -364,14 +364,14 @@
   'mac_10.14': {
     'swarming': {
       'dimensions': {
-        'os': 'Mac-10.14.4',
+        'os': 'Mac-10.14.6',
       },
       'optional_dimensions': {
-        # Wait 5 minutes for 10.14.3, then 5 for .5, then fall back to 10.14.4
+        # Wait 5 minutes for 10.14.4, then 5 for .5, then fall back to 10.14.6
         # The format for optional dimensions is: expiration: [{key, value}, ..].
         300: [
           {
-            'os': 'Mac-10.14.3',
+            'os': 'Mac-10.14.4',
           },
         ],
         600: [
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index b614134..9765168e 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -208,7 +208,7 @@
       'bf_cache_android_browsertests': {
         'args': [
           '--enable-features=BackForwardCache',
-          '--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.browser_tests.filter'
+          '--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.android_browsertests.filter'
         ],
         'swarming': {
           'shards': 10,
@@ -218,7 +218,7 @@
       'bf_cache_content_shell_test_apk': {
         'args': [
           '--enable-features=BackForwardCache',
-          '--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.browser_tests.filter'
+          '--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.content_shell_test_apk.filter'
         ],
         'swarming': {
           'shards': 10,
@@ -228,7 +228,7 @@
       'bf_cache_chrome_public_test_apk': {
         'args': [
           '--enable-features=BackForwardCache',
-          '--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.browser_tests.filter'
+          '--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.chrome_public_test_apk.filter'
         ],
         'swarming': {
           'shards': 10,
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index e39d74a..3ee4d47 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -2854,21 +2854,6 @@
             ]
         }
     ],
-    "ImprovedGeolanguageReplacement": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "ImprovedGeoLanguageData"
-                    ]
-                }
-            ]
-        }
-    ],
     "ImprovedRecoveryComponent": [
         {
             "platforms": [
diff --git a/third_party/blink/common/fetch/fetch_api_request_body_mojom_traits.cc b/third_party/blink/common/fetch/fetch_api_request_body_mojom_traits.cc
index e744edb5..9ed7814 100644
--- a/third_party/blink/common/fetch/fetch_api_request_body_mojom_traits.cc
+++ b/third_party/blink/common/fetch/fetch_api_request_body_mojom_traits.cc
@@ -38,7 +38,7 @@
   out->data_pipe_getter_ =
       data.TakeDataPipeGetter<network::mojom::DataPipeGetterPtrInfo>();
   out->chunked_data_pipe_getter_ = data.TakeChunkedDataPipeGetter<
-      network::mojom::ChunkedDataPipeGetterPtrInfo>();
+      mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter>>();
   out->offset_ = data.offset();
   out->length_ = data.length();
   return true;
diff --git a/third_party/blink/public/common/fetch/fetch_api_request_body_mojom_traits.h b/third_party/blink/public/common/fetch/fetch_api_request_body_mojom_traits.h
index 8ab9c20..ecd5fce 100644
--- a/third_party/blink/public/common/fetch/fetch_api_request_body_mojom_traits.h
+++ b/third_party/blink/public/common/fetch/fetch_api_request_body_mojom_traits.h
@@ -74,10 +74,10 @@
       return mojo::NullRemote();
     return element.CloneDataPipeGetter();
   }
-  static network::mojom::ChunkedDataPipeGetterPtrInfo chunked_data_pipe_getter(
-      const network::DataElement& element) {
+  static mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter>
+  chunked_data_pipe_getter(const network::DataElement& element) {
     if (element.type_ != network::mojom::DataElementType::kChunkedDataPipe)
-      return nullptr;
+      return mojo::NullRemote();
     return const_cast<network::DataElement&>(element)
         .ReleaseChunkedDataPipeGetter();
   }
diff --git a/third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom b/third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom
index 65bf6c8f..c798d5e 100644
--- a/third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom
+++ b/third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom
@@ -191,7 +191,8 @@
   // Returns the result of the connection request.
   RemoteServerConnect(
     WebBluetoothDeviceId device_id,
-    associated WebBluetoothServerClient client) => (WebBluetoothResult result);
+    pending_associated_remote<WebBluetoothServerClient> client) => (
+    WebBluetoothResult result);
 
   // If a GATT connection exists for Device identified by |device_id| then
   // decreases the ref count for that connection.
@@ -245,7 +246,7 @@
   // Returns the result of the connection request.
   RemoteCharacteristicStartNotifications(
     string characteristic_instance_id,
-    associated WebBluetoothCharacteristicClient client) => (
+    pending_associated_remote<WebBluetoothCharacteristicClient> client) => (
       WebBluetoothResult result);
 
   // Stops notifications for the characteristic identified by
@@ -285,9 +286,10 @@
     array<uint8> value) => (WebBluetoothResult result);
 
   // Starts scanning for low energy devices.
-  RequestScanningStart(associated WebBluetoothScanClient client,
-                       WebBluetoothRequestLEScanOptions options) => (
-                       RequestScanningStartResult result);
+  RequestScanningStart(
+    pending_associated_remote<WebBluetoothScanClient> client,
+    WebBluetoothRequestLEScanOptions options) => (
+    RequestScanningStartResult result);
 };
 
 // Classes that implement this interface will be notified of device events.
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc b/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc
index 794d58d..bf4203e 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc
@@ -637,7 +637,7 @@
         std::unique_ptr<Graph::Node>(new EmbedderRootNode("Blink roots"))));
     EnsureRootState(root);
     ParentScope parent(this, root);
-    ThreadState::Current()->GetPersistentRegion()->TracePersistentNodes(this);
+    ThreadState::Current()->GetPersistentRegion()->TraceNodes(this);
   }
   {
     EmbedderNode* root =
@@ -646,7 +646,7 @@
     EnsureRootState(root);
     ParentScope parent(this, root);
     MutexLocker persistent_lock(ProcessHeap::CrossThreadPersistentMutex());
-    ProcessHeap::GetCrossThreadPersistentRegion().TracePersistentNodes(this);
+    ProcessHeap::GetCrossThreadPersistentRegion().TraceNodes(this);
   }
 }
 
diff --git a/third_party/blink/renderer/core/html/forms/resources/calendarPicker.js b/third_party/blink/renderer/core/html/forms/resources/calendarPicker.js
index 693ad30..d908743 100644
--- a/third_party/blink/renderer/core/html/forms/resources/calendarPicker.js
+++ b/third_party/blink/renderer/core/html/forms/resources/calendarPicker.js
@@ -2259,7 +2259,7 @@
 YearListView.prototype = Object.create(ListView.prototype);
 
 YearListView._Height = YearListCell._SelectedHeight - 1;
-YearListView._VisibleYearsRefresh = 3;
+YearListView._VisibleYearsRefresh = 4;
 YearListView._HeightRefresh = YearListCell._SelectedHeightRefresh - 1 + YearListView._VisibleYearsRefresh * YearListCell._HeightRefresh;
 YearListView.GetHeight = function() {
   if (global.params.isFormControlsRefreshEnabled) {
@@ -3842,7 +3842,11 @@
 CalendarPicker.prototype.onYearListViewDidHide = function(sender) {
   this.monthPopupView.hide();
   this.calendarHeaderView.setDisabled(false);
-  this.adjustHeight();
+  if (global.params.isFormControlsRefreshEnabled) {
+    this.calendarTableView.element.style.visibility = 'visible';
+  } else {
+    this.adjustHeight();
+  }
 };
 
 /**
@@ -3880,7 +3884,11 @@
       clientRect.height);
   this.monthPopupView.show(this.currentMonth(), calendarTableRect);
   this.calendarHeaderView.setDisabled(true);
-  this.adjustHeight();
+  if (global.params.isFormControlsRefreshEnabled) {
+    this.calendarTableView.element.style.visibility = 'hidden';
+  } else {
+    this.adjustHeight();
+  }
 };
 
 CalendarPicker.prototype._setConfig = function(config) {
@@ -3935,7 +3943,7 @@
   var numberOfRows = global.params.isFormControlsRefreshEnabled ? CalendarPicker.VisibleRowsRefresh : rowForLastDayInMonth - rowForFirstDayInMonth + 1;
   var calendarTableViewHeight =
       CalendarTableHeaderView.GetHeight() + numberOfRows * DayCell.GetHeight() + CalendarTableView.GetBorderWidth() * 2 + CalendarTableView.GetTodayButtonHeight();
-  var height = (this.monthPopupView.isVisible ? YearListView.GetHeight() : calendarTableViewHeight) +
+  var height = (this.monthPopupView.isVisible && !global.params.isFormControlsRefreshEnabled ? YearListView.GetHeight() : calendarTableViewHeight) +
       CalendarHeaderView.Height + CalendarHeaderView.BottomMargin + CalendarPicker.Padding * 2 +
       CalendarPicker.BorderWidth * 2;
   this.setHeight(height);
diff --git a/third_party/blink/renderer/core/html/portal/OWNERS b/third_party/blink/renderer/core/html/portal/OWNERS
new file mode 100644
index 0000000..4c925a2
--- /dev/null
+++ b/third_party/blink/renderer/core/html/portal/OWNERS
@@ -0,0 +1,6 @@
+adithyas@chromium.org
+jbroman@chromium.org
+lfg@chromium.org
+mcnee@chromium.org
+
+# COMPONENT: Blink>HTML>Portal
diff --git a/third_party/blink/renderer/core/layout/layout_shift_tracker.cc b/third_party/blink/renderer/core/layout/layout_shift_tracker.cc
index 56508ed..9d6b822e 100644
--- a/third_party/blink/renderer/core/layout/layout_shift_tracker.cc
+++ b/third_party/blink/renderer/core/layout/layout_shift_tracker.cc
@@ -28,8 +28,6 @@
 
 static constexpr base::TimeDelta kTimerDelay =
     base::TimeDelta::FromMilliseconds(500);
-// TODO(crbug.com/1000716): Remove granularity scaling logic.
-static const float kSweepLineRegionGranularity = 1.0;
 static const float kMovementThreshold = 3.0;  // CSS pixels.
 
 static FloatPoint LogicalStart(const FloatRect& rect,
@@ -50,11 +48,6 @@
   return std::max(fabs(location_delta.Width()), fabs(location_delta.Height()));
 }
 
-float LayoutShiftTracker::RegionGranularityScale(
-    const IntRect& viewport) const {
-  return kSweepLineRegionGranularity;
-}
-
 static bool EqualWithinMovementThreshold(const FloatPoint& a,
                                          const FloatPoint& b,
                                          const LayoutObject& object) {
@@ -64,10 +57,10 @@
          fabs(a.Y() - b.Y()) < threshold_physical_px;
 }
 
-static bool SmallerThanRegionGranularity(const FloatRect& rect,
-                                         float granularity_scale) {
-  return rect.Width() * granularity_scale < 0.5 ||
-         rect.Height() * granularity_scale < 0.5;
+static bool SmallerThanRegionGranularity(const FloatRect& rect) {
+  // The region uses integer coordinates, so the rects are snapped to
+  // pixel boundaries. Ignore rects smaller than half a pixel.
+  return rect.Width() < 0.5 || rect.Height() < 0.5;
 }
 
 static const PropertyTreeState PropertyTreeStateFor(
@@ -75,30 +68,24 @@
   return object.FirstFragment().LocalBorderBoxProperties();
 }
 
-static void RegionToTracedValue(const Region& region,
-                                double granularity_scale,
+static void RegionToTracedValue(const LayoutShiftRegion& region,
                                 TracedValue& value) {
+  Region blink_region;
+  for (IntRect rect : region.GetRects())
+    blink_region.Unite(Region(rect));
+
   value.BeginArray("region_rects");
-  for (const IntRect& rect : region.Rects()) {
+  for (const IntRect& rect : blink_region.Rects()) {
     value.BeginArray();
-    value.PushInteger(clampTo<int>(roundf(rect.X() / granularity_scale)));
-    value.PushInteger(clampTo<int>(roundf(rect.Y() / granularity_scale)));
-    value.PushInteger(clampTo<int>(roundf(rect.Width() / granularity_scale)));
-    value.PushInteger(clampTo<int>(roundf(rect.Height() / granularity_scale)));
+    value.PushInteger(rect.X());
+    value.PushInteger(rect.Y());
+    value.PushInteger(rect.Width());
+    value.PushInteger(rect.Height());
     value.EndArray();
   }
   value.EndArray();
 }
 
-static void RegionToTracedValue(const LayoutShiftRegion& region,
-                                double granularity_scale,
-                                TracedValue& value) {
-  Region old_region;
-  for (IntRect rect : region.GetRects())
-    old_region.Unite(Region(rect));
-  RegionToTracedValue(old_region, granularity_scale, value);
-}
-
 #if DCHECK_IS_ON()
 static bool ShouldLog(const LocalFrame& frame) {
   const String& url = frame.GetDocument()->Url().GetString();
@@ -133,13 +120,8 @@
                                    LogicalStart(new_rect, source), source))
     return;
 
-  IntRect viewport =
-      IntRect(IntPoint(),
-              frame_view_->GetScrollableArea()->VisibleContentRect().Size());
-  float scale = RegionGranularityScale(viewport);
-
-  if (SmallerThanRegionGranularity(old_rect, scale) &&
-      SmallerThanRegionGranularity(new_rect, scale))
+  if (SmallerThanRegionGranularity(old_rect) &&
+      SmallerThanRegionGranularity(new_rect))
     return;
 
   // Ignore layout objects that move (in the coordinate space of the paint
@@ -187,6 +169,10 @@
     clipped_new_rect.Intersect(clip_rect.Rect());
   }
 
+  IntRect viewport =
+      IntRect(IntPoint(),
+              frame_view_->GetScrollableArea()->VisibleContentRect().Size());
+
   IntRect visible_old_rect = RoundedIntRect(clipped_old_rect);
   visible_old_rect.Intersect(viewport);
   IntRect visible_new_rect = RoundedIntRect(clipped_new_rect);
@@ -212,12 +198,8 @@
   }
 #endif
 
-  visible_old_rect.Scale(scale);
-  visible_new_rect.Scale(scale);
-
-  // TODO(crbug.com/1000716): Rename region_experimental_.
-  region_experimental_.AddRect(visible_old_rect);
-  region_experimental_.AddRect(visible_new_rect);
+  region_.AddRect(visible_old_rect);
+  region_.AddRect(visible_new_rect);
 }
 
 void LayoutShiftTracker::NotifyObjectPrePaint(
@@ -260,25 +242,15 @@
 void LayoutShiftTracker::NotifyPrePaintFinished() {
   if (!IsActive())
     return;
-  bool use_sweep_line = true;
-  bool region_is_empty =
-      use_sweep_line ? region_experimental_.IsEmpty() : region_.IsEmpty();
-  if (region_is_empty)
+  if (region_.IsEmpty())
     return;
 
   IntRect viewport = frame_view_->GetScrollableArea()->VisibleContentRect();
   if (viewport.IsEmpty())
     return;
 
-  double granularity_scale = RegionGranularityScale(viewport);
-  IntRect scaled_viewport = viewport;
-  scaled_viewport.Scale(granularity_scale);
-
-  double viewport_area =
-      double(scaled_viewport.Width()) * double(scaled_viewport.Height());
-  uint64_t region_area =
-      use_sweep_line ? region_experimental_.Area() : region_.Area();
-  double impact_fraction = region_area / viewport_area;
+  double viewport_area = double(viewport.Width()) * double(viewport.Height());
+  double impact_fraction = region_.Area() / viewport_area;
   DCHECK_GT(impact_fraction, 0);
 
   DCHECK_GT(frame_max_distance_, 0.0);
@@ -309,17 +281,10 @@
     ReportShift(score_delta, weighted_score_delta);
   }
 
-  if (use_sweep_line) {
-    if (!region_experimental_.IsEmpty()) {
-      SetLayoutShiftRects(region_experimental_.GetRects(), 1, true);
-    }
-    region_experimental_.Reset();
-  } else {
-    if (!region_.IsEmpty()) {
-      SetLayoutShiftRects(region_.Rects(), granularity_scale, false);
-    }
-    region_ = Region();
-  }
+  if (!region_.IsEmpty())
+    SetLayoutShiftRects(region_.GetRects());
+  region_.Reset();
+
   frame_max_distance_ = 0.0;
   frame_scroll_delta_ = ScrollOffset();
 }
@@ -446,34 +411,13 @@
   value->SetDouble("cumulative_score", score_);
   value->SetDouble("overall_max_distance", overall_max_distance_);
   value->SetDouble("frame_max_distance", frame_max_distance_);
-
-  float granularity_scale = RegionGranularityScale(
-      IntRect(IntPoint(),
-              frame_view_->GetScrollableArea()->VisibleContentRect().Size()));
-
-  RegionToTracedValue(region_experimental_, granularity_scale, *value);
-
+  RegionToTracedValue(region_, *value);
   value->SetBoolean("is_main_frame", frame_view_->GetFrame().IsMainFrame());
   value->SetBoolean("had_recent_input", input_detected);
   return value;
 }
 
-WebVector<gfx::Rect> LayoutShiftTracker::ConvertIntRectsToGfxRects(
-    const Vector<IntRect>& int_rects,
-    double granularity_scale) {
-  WebVector<gfx::Rect> rects;
-  for (const IntRect& rect : int_rects) {
-    gfx::Rect r = gfx::Rect(
-        rect.X() / granularity_scale, rect.Y() / granularity_scale,
-        rect.Width() / granularity_scale, rect.Height() / granularity_scale);
-    rects.emplace_back(r);
-  }
-  return rects;
-}
-
-void LayoutShiftTracker::SetLayoutShiftRects(const Vector<IntRect>& int_rects,
-                                             double granularity_scale,
-                                             bool using_sweep_line) {
+void LayoutShiftTracker::SetLayoutShiftRects(const Vector<IntRect>& int_rects) {
   // Store the layout shift rects in the HUD layer.
   GraphicsLayer* root_graphics_layer =
       frame_view_->GetLayoutView()->Compositor()->RootGraphicsLayer();
@@ -488,15 +432,11 @@
       return;
     if (cc_layer->layer_tree_host()->hud_layer()) {
       WebVector<gfx::Rect> rects;
-      if (using_sweep_line) {
-        Region old_region;
-        for (IntRect rect : int_rects)
-          old_region.Unite(Region(rect));
-        rects =
-            ConvertIntRectsToGfxRects(old_region.Rects(), granularity_scale);
-      } else {
-        rects = ConvertIntRectsToGfxRects(int_rects, granularity_scale);
-      }
+      Region blink_region;
+      for (IntRect rect : int_rects)
+        blink_region.Unite(Region(rect));
+      for (const IntRect& rect : blink_region.Rects())
+        rects.emplace_back(rect);
       cc_layer->layer_tree_host()->hud_layer()->SetLayoutShiftRects(
           rects.ReleaseVector());
       cc_layer->layer_tree_host()->hud_layer()->SetNeedsPushProperties();
diff --git a/third_party/blink/renderer/core/layout/layout_shift_tracker.h b/third_party/blink/renderer/core/layout/layout_shift_tracker.h
index 7fabfb0..79185e2 100644
--- a/third_party/blink/renderer/core/layout/layout_shift_tracker.h
+++ b/third_party/blink/renderer/core/layout/layout_shift_tracker.h
@@ -70,14 +70,8 @@
   void TimerFired(TimerBase*) {}
   std::unique_ptr<TracedValue> PerFrameTraceData(double score_delta,
                                                  bool input_detected) const;
-  float RegionGranularityScale(const IntRect& viewport) const;
   double SubframeWeightingFactor() const;
-  WebVector<gfx::Rect> ConvertIntRectsToGfxRects(
-      const Vector<IntRect>& int_rects,
-      double granularity_scale);
-  void SetLayoutShiftRects(const Vector<IntRect>& int_rects,
-                           double granularity_scale,
-                           bool using_sweep_line);
+  void SetLayoutShiftRects(const Vector<IntRect>& int_rects);
   void UpdateInputTimestamp(base::TimeTicks timestamp);
 
   // This owns us.
@@ -110,10 +104,7 @@
   PointerdownPendingData pointerdown_pending_data_;
 
   // The per-animation-frame impact region.
-  Region region_;
-
-  // Experimental impact region implementation using sweep-line algorithm.
-  LayoutShiftRegion region_experimental_;
+  LayoutShiftRegion region_;
 
   // Tracks the short period after an input event during which we ignore shifts
   // for the purpose of cumulative scoring, and report them to the web perf API
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index cc21874e..2e7c2ad 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -983,7 +983,9 @@
   GetFrameLoader().DidFinishNavigation(
       FrameLoader::NavigationFinishState::kSuccess);
 
-  if (!frame_->GetPage())
+  // GetFrameLoader().DidFinishNavigation can lead to DetachFromFrame so need
+  // to check again if frame_ is null.
+  if (!frame_ || !frame_->GetPage())
     return;
   GetFrameLoader().SaveScrollState();
 
diff --git a/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.cc b/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.cc
index 87ca9fba..250faaf2 100644
--- a/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.cc
+++ b/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.cc
@@ -31,7 +31,7 @@
 
 namespace blink {
 
-SMILAnimationSandwich::SMILAnimationSandwich() {}
+SMILAnimationSandwich::SMILAnimationSandwich() = default;
 
 void SMILAnimationSandwich::Schedule(SVGSMILElement* animation) {
   DCHECK(!sandwich_.Contains(animation));
@@ -42,12 +42,15 @@
   auto* position = std::find(sandwich_.begin(), sandwich_.end(), animation);
   DCHECK(sandwich_.end() != position);
   sandwich_.erase(position);
+  if (animation == ResultElement())
+    animation->ClearAnimatedType();
 }
 
 void SMILAnimationSandwich::Reset() {
-  for (SVGSMILElement* animation : sandwich_) {
+  if (SVGSMILElement* result_element = ResultElement())
+    result_element->ClearAnimatedType();
+  for (SVGSMILElement* animation : sandwich_)
     animation->Reset();
-  }
 }
 
 void SMILAnimationSandwich::UpdateTiming(double elapsed) {
@@ -56,21 +59,13 @@
     std::sort(sandwich_.begin(), sandwich_.end(), PriorityCompare(elapsed));
   }
 
-  active_.Shrink(0);
-  active_.ReserveCapacity(sandwich_.size());
-  for (const auto& it_animation : sandwich_) {
-    SVGSMILElement* animation = it_animation.Get();
+  for (const auto& animation : sandwich_) {
     DCHECK(animation->HasValidTarget());
 
-    if (animation->NeedsToProgress(elapsed)) {
-      bool interval_restart = animation->CheckAndUpdateInterval(elapsed);
-      animation->UpdateActiveState(elapsed, interval_restart);
-      active_.push_back(animation);
-    } else if (animation->IsContributing(elapsed)) {
-      active_.push_back(animation);
-    } else {
-      animation->ClearAnimatedType();
-    }
+    if (!animation->NeedsToProgress(elapsed))
+      continue;
+    bool interval_restart = animation->CheckAndUpdateInterval(elapsed);
+    animation->UpdateActiveState(elapsed, interval_restart);
   }
 }
 
@@ -95,30 +90,38 @@
 }
 
 void SMILAnimationSandwich::UpdateSyncBases(double elapsed) {
-  for (auto& animation : active_)
+  for (auto& animation : sandwich_)
     animation->UpdateSyncBases();
+}
 
-  auto* it = active_.begin();
-  while (it != active_.end()) {
-    auto* scheduled = it->Get();
-    if (scheduled->IsContributing(elapsed)) {
-      it++;
+SVGSMILElement* SMILAnimationSandwich::ResultElement() const {
+  return !active_.IsEmpty() ? active_.front() : nullptr;
+}
+
+void SMILAnimationSandwich::UpdateActiveAnimationStack(
+    double presentation_time) {
+  SVGSMILElement* old_result_element = ResultElement();
+  active_.Shrink(0);
+  active_.ReserveCapacity(sandwich_.size());
+  // Build the contributing/active sandwich.
+  for (auto& animation : sandwich_) {
+    if (!animation->IsContributing(presentation_time))
       continue;
-    }
-    scheduled->ClearAnimatedType();
-    it = active_.erase(it);
+    active_.push_back(animation);
   }
+  // If we switched result element, clear the old one.
+  if (old_result_element && old_result_element != ResultElement())
+    old_result_element->ClearAnimatedType();
 }
 
 SVGSMILElement* SMILAnimationSandwich::ApplyAnimationValues() {
-  if (active_.IsEmpty())
+  SVGSMILElement* result_element = ResultElement();
+  if (!result_element)
     return nullptr;
-  // Results are accumulated to the first animation that animates and
-  // contributes to a particular element/attribute pair.
+
   // Only reset the animated type to the base value once for
   // the lowest priority animation that animates and
   // contributes to a particular element/attribute pair.
-  SVGSMILElement* result_element = active_.front();
   result_element->ResetAnimatedType();
 
   // Animations have to be applied lowest to highest prio.
@@ -137,10 +140,8 @@
        sandwich_it++) {
     (*sandwich_it)->UpdateAnimatedValue(result_element);
   }
-  active_.Shrink(0);
 
   result_element->ApplyResultsToTarget();
-
   return result_element;
 }
 
diff --git a/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.h b/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.h
index 0eed9c0..a07f745 100644
--- a/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.h
+++ b/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.h
@@ -48,10 +48,12 @@
   double elapsed_;
 };
 
+// This class implements/helps with implementing the "sandwich model" from SMIL.
+// https://www.w3.org/TR/SMIL3/smil-animation.html#animationNS-AnimationSandwichModel
 class SMILAnimationSandwich : public GarbageCollected<SMILAnimationSandwich> {
  public:
   using ScheduledVector = HeapVector<Member<SVGSMILElement>>;
-  explicit SMILAnimationSandwich();
+  SMILAnimationSandwich();
 
   void Schedule(SVGSMILElement* animation);
   void Unschedule(SVGSMILElement* animation);
@@ -59,6 +61,7 @@
 
   void UpdateTiming(double elapsed);
   void UpdateSyncBases(double elapsed);
+  void UpdateActiveAnimationStack(double elapsed);
   SVGSMILElement* ApplyAnimationValues();
 
   SMILTime NextInterestingTime(double presentation_time) const;
@@ -69,8 +72,17 @@
   void Trace(blink::Visitor*);
 
  private:
-  // The list stored here is always sorted.
+  // Results are accumulated to the first animation element that animates and
+  // contributes to a particular element/attribute pair. We refer to this as
+  // the "result element".
+  SVGSMILElement* ResultElement() const;
+
+  // All the animation (really: timed) elements that make up the sandwich,
+  // sorted according to priority.
   ScheduledVector sandwich_;
+  // The currently active animation elements in the sandwich. Retains the
+  // ordering of elements from |sandwich_| when created. This is the animation
+  // elements from which the animation value is computed.
   ScheduledVector active_;
 };
 
diff --git a/third_party/blink/renderer/core/svg/animation/smil_time_container.cc b/third_party/blink/renderer/core/svg/animation/smil_time_container.cc
index 2d681ce..1cc397e 100644
--- a/third_party/blink/renderer/core/svg/animation/smil_time_container.cc
+++ b/third_party/blink/renderer/core/svg/animation/smil_time_container.cc
@@ -518,6 +518,7 @@
 #endif
   HeapVector<Member<SVGSMILElement>> animations_to_apply;
   for (auto& sandwich : active_sandwiches_) {
+    sandwich->UpdateActiveAnimationStack(elapsed);
     if (SVGSMILElement* animation = sandwich->ApplyAnimationValues())
       animations_to_apply.push_back(animation);
   }
diff --git a/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc b/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc
index 431e646..021e0c3 100644
--- a/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc
+++ b/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc
@@ -270,8 +270,6 @@
 }
 
 void SVGSMILElement::Reset() {
-  ClearAnimatedType();
-
   active_state_ = kInactive;
   is_waiting_for_first_interval_ = true;
   interval_ = {SMILTime::Unresolved(), SMILTime::Unresolved()};
diff --git a/third_party/blink/renderer/core/svg/svg_animate_element.cc b/third_party/blink/renderer/core/svg/svg_animate_element.cc
index 8096b36..96239577 100644
--- a/third_party/blink/renderer/core/svg/svg_animate_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_animate_element.cc
@@ -556,8 +556,8 @@
 
 void SVGAnimateElement::WillChangeAnimationTarget() {
   SVGAnimationElement::WillChangeAnimationTarget();
-  if (targetElement())
-    ClearAnimatedType();
+  // Should be cleared by the above.
+  DCHECK(!animated_value_);
 }
 
 void SVGAnimateElement::DidChangeAnimationTarget() {
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 10f2de7..161a0bd 100644
--- a/third_party/blink/renderer/core/workers/worker_global_scope.cc
+++ b/third_party/blink/renderer/core/workers/worker_global_scope.cc
@@ -566,7 +566,7 @@
   auto* frame_callback =
       MakeGarbageCollected<FrameRequestCallbackCollection::V8FrameCallback>(
           callback);
-  frame_callback->SetUseLegacyTimeBase(true);
+  frame_callback->SetUseLegacyTimeBase(false);
 
   int ret = animation_frame_provider_->RegisterCallback(frame_callback);
 
diff --git a/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js b/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js
index a309861..0bba1a3 100644
--- a/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js
+++ b/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js
@@ -104,6 +104,7 @@
     eventStyles[type.TimeStamp] = new Timeline.TimelineRecordStyle(ls`Timestamp`, scripting);
     eventStyles[type.ConsoleTime] = new Timeline.TimelineRecordStyle(ls`Console Time`, scripting);
     eventStyles[type.UserTiming] = new Timeline.TimelineRecordStyle(ls`User Timing`, scripting);
+    eventStyles[type.ResourceWillSendRequest] = new Timeline.TimelineRecordStyle(ls`Will Send Request`, loading);
     eventStyles[type.ResourceSendRequest] = new Timeline.TimelineRecordStyle(ls`Send Request`, loading);
     eventStyles[type.ResourceReceiveResponse] = new Timeline.TimelineRecordStyle(ls`Receive Response`, loading);
     eventStyles[type.ResourceFinish] = new Timeline.TimelineRecordStyle(ls`Finish Loading`, loading);
@@ -523,6 +524,7 @@
       case recordType.WebSocketSendHandshakeRequest:
       case recordType.WebSocketReceiveHandshakeResponse:
       case recordType.WebSocketDestroy:
+      case recordType.ResourceWillSendRequest:
       case recordType.ResourceSendRequest:
       case recordType.ResourceReceivedData:
       case recordType.ResourceReceiveResponse:
@@ -630,6 +632,7 @@
       case recordType.DecodeLazyPixelRef:
       case recordType.XHRReadyStateChange:
       case recordType.XHRLoad:
+      case recordType.ResourceWillSendRequest:
       case recordType.ResourceSendRequest:
       case recordType.ResourceReceivedData:
       case recordType.ResourceReceiveResponse:
@@ -828,6 +831,7 @@
       case recordTypes.FireAnimationFrame:
         contentHelper.appendTextRow(ls`Callback ID`, eventData['id']);
         break;
+      case recordTypes.ResourceWillSendRequest:
       case recordTypes.ResourceSendRequest:
       case recordTypes.ResourceReceiveResponse:
       case recordTypes.ResourceReceivedData:
diff --git a/third_party/blink/renderer/devtools/front_end/timeline/timeline_strings.grdp b/third_party/blink/renderer/devtools/front_end/timeline/timeline_strings.grdp
index 4d860c4b..2124a43f 100644
--- a/third_party/blink/renderer/devtools/front_end/timeline/timeline_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/timeline/timeline_strings.grdp
@@ -160,6 +160,9 @@
   <message name="IDS_DEVTOOLS_24aa4117da86c41684ad25742832dfa6" desc="Text in Timeline UIUtils of the Performance panel">
     Async
   </message>
+  <message name="IDS_DEVTOOLS_24ed51e784c08847f2c1bafe1a6428a4" desc="Text in Timeline UIUtils of the Performance panel">
+    Will Send Request
+  </message>
   <message name="IDS_DEVTOOLS_25a5e1f05232eae2d3a9c1ff4cb83869" desc="Text in Timeline UIUtils of the Performance panel">
     Function Call
   </message>
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 1916764f..0bd19b5 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
@@ -951,6 +951,13 @@
       return;
     }
 
+    if (event.name === TimelineModel.TimelineModel.RecordType.ResourceWillSendRequest) {
+      const requestId = event.args['data']['requestId'];
+      if (typeof requestId === 'string')
+        this._requestsFromBrowser.set(requestId, event);
+      return;
+    }
+
     if (event.hasCategory(SDK.TracingModel.DevToolsMetadataEventCategory) && event.args['data']) {
       const data = event.args['data'];
       if (event.name === TimelineModel.TimelineModel.DevToolsMetadataEvent.TracingStartedInBrowser) {
@@ -1074,6 +1081,8 @@
     /** @type {!Map<string, !TimelineModel.TimelineModel.PageFrame>} */
     this._pageFrames = new Map();
     this._mainFrame = null;
+    /** @type {!Map<string, !SDK.TracingModel.Event>} */
+    this._requestsFromBrowser = new Map();
 
     this._minimumRecordTime = 0;
     this._maximumRecordTime = 0;
@@ -1171,8 +1180,8 @@
     const zeroStartRequestsList = [];
     const types = TimelineModel.TimelineModel.RecordType;
     const resourceTypes = new Set([
-      types.ResourceSendRequest, types.ResourceReceiveResponse, types.ResourceReceivedData, types.ResourceFinish,
-      types.ResourceMarkAsCached
+      types.ResourceWillSendRequest, types.ResourceSendRequest, types.ResourceReceiveResponse,
+      types.ResourceReceivedData, types.ResourceFinish, types.ResourceMarkAsCached
     ]);
     const events = this.inspectedTargetEvents();
     for (let i = 0; i < events.length; ++i) {
@@ -1180,6 +1189,11 @@
       if (!resourceTypes.has(e.name))
         continue;
       const id = TimelineModel.TimelineModel.globalEventId(e, 'requestId');
+      if (e.name === types.ResourceSendRequest && this._requestsFromBrowser.has(e.args.data.requestId))
+        addRequest(this._requestsFromBrowser.get(e.args.data.requestId), id);
+      addRequest(e, id);
+    }
+    function addRequest(e, id) {
       let request = requests.get(id);
       if (request) {
         request.addEvent(e);
@@ -1267,6 +1281,7 @@
   ConsoleTime: 'ConsoleTime',
   UserTiming: 'UserTiming',
 
+  ResourceWillSendRequest: 'ResourceWillSendRequest',
   ResourceSendRequest: 'ResourceSendRequest',
   ResourceReceiveResponse: 'ResourceReceiveResponse',
   ResourceReceivedData: 'ResourceReceivedData',
@@ -1522,7 +1537,10 @@
    * @param {!SDK.TracingModel.Event} event
    */
   constructor(event) {
-    this.startTime = event.name === TimelineModel.TimelineModel.RecordType.ResourceSendRequest ? event.startTime : 0;
+    const recordType = TimelineModel.TimelineModel.RecordType;
+    const isInitial =
+        event.name === recordType.ResourceSendRequest || event.name === recordType.ResourceWillSendRequest;
+    this.startTime = isInitial ? event.startTime : 0;
     this.endTime = Infinity;
     this.encodedDataLength = 0;
     this.decodedBodyLength = 0;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_selection.cc b/third_party/blink/renderer/modules/accessibility/ax_selection.cc
index 7532b8cc..b7166cb 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_selection.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_selection.cc
@@ -214,6 +214,9 @@
   const auto ax_extent =
       AXPosition::FromPosition(dom_extent, extent_affinity, extent_adjustment);
 
+  if (!ax_base.IsValid() || !ax_extent.IsValid())
+    return {};
+
   AXSelection::Builder selection_builder;
   selection_builder.SetBase(ax_base).SetExtent(ax_extent);
   return selection_builder.Build();
diff --git a/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc b/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc
index 4a10b2c..0f27d24 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc
@@ -1615,6 +1615,33 @@
       builder.SetBase(ax_position).SetExtent(ax_position).Build();
 }
 
+TEST_F(AccessibilitySelectionTest, InvalidSelectionOnAShadowRoot) {
+  GetPage().GetSettings().SetScriptEnabled(true);
+  SetBodyInnerHTML(R"HTML(
+		<div id="container">
+		</div>	
+	)HTML");
+  Element* const script_element =
+      GetDocument().CreateRawElement(html_names::kScriptTag);
+  script_element->setTextContent(R"SCRIPT(
+      var container = document.getElementById("container");
+			var shadow = container.attachShadow({mode: 'open'});
+			var button = document.createElement("button");
+			button.id = "button";
+			shadow.appendChild(button);
+      )SCRIPT");
+  GetDocument().body()->AppendChild(script_element);
+  UpdateAllLifecyclePhasesForTest();
+
+  Node* shadow_root = GetElementById("container")->GetShadowRoot();
+  const Position base = Position::EditingPositionOf(shadow_root, 0);
+  const Position extent = Position::EditingPositionOf(shadow_root, 1);
+
+  const auto selection =
+      SelectionInDOMTree::Builder().SetBaseAndExtent(base, extent).Build();
+  EXPECT_FALSE(AXSelection::FromSelection(selection).IsValid());
+}
+
 //
 // Declarative tests.
 //
diff --git a/third_party/blink/renderer/modules/battery/battery_dispatcher.cc b/third_party/blink/renderer/modules/battery/battery_dispatcher.cc
index 9f0dc99..83c54701 100644
--- a/third_party/blink/renderer/modules/battery/battery_dispatcher.cc
+++ b/third_party/blink/renderer/modules/battery/battery_dispatcher.cc
@@ -47,8 +47,9 @@
 void BatteryDispatcher::StartListening(LocalFrame* frame) {
   DCHECK(!monitor_.is_bound());
   // See https://bit.ly/2S0zRAS for task types.
-  Platform::Current()->GetInterfaceProvider()->GetInterface(mojo::MakeRequest(
-      &monitor_, frame->GetTaskRunner(TaskType::kMiscPlatformAPI)));
+  Platform::Current()->GetInterfaceProvider()->GetInterface(
+      monitor_.BindNewPipeAndPassReceiver(
+          frame->GetTaskRunner(TaskType::kMiscPlatformAPI)));
   QueryNextStatus();
 }
 
diff --git a/third_party/blink/renderer/modules/battery/battery_dispatcher.h b/third_party/blink/renderer/modules/battery/battery_dispatcher.h
index 3d6a057..e1b4965e 100644
--- a/third_party/blink/renderer/modules/battery/battery_dispatcher.h
+++ b/third_party/blink/renderer/modules/battery/battery_dispatcher.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_BATTERY_BATTERY_DISPATCHER_H_
 
 #include "base/macros.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "services/device/public/mojom/battery_monitor.mojom-blink.h"
 #include "third_party/blink/renderer/core/frame/platform_event_dispatcher.h"
 #include "third_party/blink/renderer/modules/battery/battery_manager.h"
@@ -37,7 +38,7 @@
   void StartListening(LocalFrame* frame) override;
   void StopListening() override;
 
-  device::mojom::blink::BatteryMonitorPtr monitor_;
+  mojo::Remote<device::mojom::blink::BatteryMonitor> monitor_;
   BatteryStatus battery_status_;
   bool has_latest_data_;
 
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth.cc
index e85d4961..bfe0afa4 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth.cc
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth.cc
@@ -6,7 +6,12 @@
 
 #include <utility>
 
+#include "mojo/public/cpp/bindings/associated_receiver_set.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-blink.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
@@ -283,7 +288,7 @@
 
 void Bluetooth::RequestScanningCallback(
     ScriptPromiseResolver* resolver,
-    mojo::BindingId id,
+    mojo::ReceiverId id,
     mojom::blink::RequestScanningStartResultPtr result) {
   if (!resolver->GetExecutionContext() ||
       resolver->GetExecutionContext()->IsContextDestroyed()) {
@@ -356,11 +361,11 @@
   auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
   ScriptPromise promise = resolver->Promise();
 
-  mojom::blink::WebBluetoothScanClientAssociatedPtrInfo client;
+  mojo::PendingAssociatedRemote<mojom::blink::WebBluetoothScanClient> client;
   // See https://bit.ly/2S0zRAS for task types.
-  mojo::BindingId id = client_bindings_.AddBinding(
-      this, mojo::MakeRequest(&client),
-      context->GetTaskRunner(TaskType::kMiscPlatformAPI));
+  mojo::ReceiverId id =
+      client_receivers_.Add(this, client.InitWithNewEndpointAndPassReceiver(),
+                            context->GetTaskRunner(TaskType::kMiscPlatformAPI));
 
   service_->RequestScanningStart(
       std::move(client), std::move(scan_options),
@@ -408,15 +413,15 @@
 }
 
 void Bluetooth::PageVisibilityChanged() {
-  client_bindings_.CloseAllBindings();
+  client_receivers_.Clear();
 }
 
-void Bluetooth::CancelScan(mojo::BindingId id) {
-  client_bindings_.RemoveBinding(id);
+void Bluetooth::CancelScan(mojo::ReceiverId id) {
+  client_receivers_.Remove(id);
 }
 
-bool Bluetooth::IsScanActive(mojo::BindingId id) const {
-  return client_bindings_.HasBinding(id);
+bool Bluetooth::IsScanActive(mojo::ReceiverId id) const {
+  return client_receivers_.HasReceiver(id);
 }
 
 const WTF::AtomicString& Bluetooth::InterfaceName() const {
@@ -428,7 +433,7 @@
 }
 
 void Bluetooth::ContextDestroyed(ExecutionContext*) {
-  client_bindings_.CloseAllBindings();
+  client_receivers_.Clear();
 }
 
 void Bluetooth::Trace(blink::Visitor* visitor) {
@@ -443,7 +448,7 @@
       PageVisibilityObserver(To<Document>(context)->GetPage()) {}
 
 Bluetooth::~Bluetooth() {
-  DCHECK(client_bindings_.empty());
+  DCHECK(client_receivers_.empty());
 }
 
 BluetoothDevice* Bluetooth::GetBluetoothDeviceRepresentingDevice(
@@ -465,7 +470,7 @@
     // See https://bit.ly/2S0zRAS for task types.
     auto task_runner = context->GetTaskRunner(TaskType::kMiscPlatformAPI);
     context->GetInterfaceProvider()->GetInterface(
-        mojo::MakeRequest(&service_, task_runner));
+        service_.BindNewPipeAndPassReceiver(task_runner));
   }
 }
 
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth.h b/third_party/blink/renderer/modules/bluetooth/bluetooth.h
index 5a499b7e..237111f 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth.h
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth.h
@@ -5,7 +5,9 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_H_
 
-#include <memory>
+#include "mojo/public/cpp/bindings/associated_receiver_set.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/core/page/page_visibility_observer.h"
@@ -61,8 +63,8 @@
   // PageVisibilityObserver
   void PageVisibilityChanged() override;
 
-  void CancelScan(mojo::BindingId);
-  bool IsScanActive(mojo::BindingId) const;
+  void CancelScan(mojo::ReceiverId);
+  bool IsScanActive(mojo::ReceiverId) const;
 
  private:
   BluetoothDevice* GetBluetoothDeviceRepresentingDevice(
@@ -74,7 +76,7 @@
                              mojom::blink::WebBluetoothDevicePtr);
 
   void RequestScanningCallback(ScriptPromiseResolver*,
-                               mojo::BindingId id,
+                               mojo::ReceiverId id,
                                mojom::blink::RequestScanningStartResultPtr);
 
   void EnsureServiceConnection(ExecutionContext*);
@@ -84,10 +86,10 @@
   // Bluetooth device inside a single global object.
   HeapHashMap<String, Member<BluetoothDevice>> device_instance_map_;
 
-  mojo::AssociatedBindingSet<mojom::blink::WebBluetoothScanClient>
-      client_bindings_;
+  mojo::AssociatedReceiverSet<mojom::blink::WebBluetoothScanClient>
+      client_receivers_;
 
-  mojom::blink::WebBluetoothServicePtr service_;
+  mojo::Remote<mojom::blink::WebBluetoothService> service_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.cc
index 8f3edbb..017c0d3e 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.cc
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.cc
@@ -4,10 +4,12 @@
 
 #include "third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.h"
 
+#include "mojo/public/cpp/bindings/receiver_set.h"
+
 namespace blink {
 
 BluetoothLEScan::BluetoothLEScan(
-    mojo::BindingId id,
+    mojo::ReceiverId id,
     Bluetooth* bluetooth,
     mojom::blink::WebBluetoothRequestLEScanOptionsPtr options)
     : id_(id),
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.h b/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.h
index 94362714..0fb2bf26 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.h
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_LE_SCAN_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_LE_SCAN_H_
 
+#include "mojo/public/cpp/bindings/receiver_set.h"
 #include "third_party/blink/renderer/modules/bluetooth/bluetooth.h"
 #include "third_party/blink/renderer/modules/bluetooth/bluetooth_le_scan_filter_init.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -16,7 +17,7 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  BluetoothLEScan(mojo::BindingId,
+  BluetoothLEScan(mojo::ReceiverId,
                   Bluetooth*,
                   mojom::blink::WebBluetoothRequestLEScanOptionsPtr);
 
@@ -31,7 +32,7 @@
   void Trace(blink::Visitor*) override;
 
  private:
-  mojo::BindingId id_;
+  mojo::ReceiverId id_;
   HeapVector<Member<BluetoothLEScanFilterInit>> filters_;
   Member<Bluetooth> bluetooth_;
   const bool keep_repeated_devices_;
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.cc
index e73dc5f8..0eb99595 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.cc
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.cc
@@ -6,7 +6,9 @@
 
 #include <utility>
 
-#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
+#include "mojo/public/cpp/bindings/associated_receiver_set.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
@@ -55,7 +57,7 @@
 }
 
 void BluetoothRemoteGATTCharacteristic::Dispose() {
-  client_bindings_.CloseAllBindings();
+  receivers_.Clear();
 }
 
 const WTF::AtomicString& BluetoothRemoteGATTCharacteristic::InterfaceName()
@@ -255,15 +257,15 @@
 
   mojom::blink::WebBluetoothService* service =
       device_->GetBluetooth()->Service();
-  mojom::blink::WebBluetoothCharacteristicClientAssociatedPtrInfo ptr_info;
-  auto request = mojo::MakeRequest(&ptr_info);
+  mojo::PendingAssociatedRemote<mojom::blink::WebBluetoothCharacteristicClient>
+      client;
   // See https://bit.ly/2S0zRAS for task types.
-  client_bindings_.AddBinding(
-      this, std::move(request),
+  receivers_.Add(
+      this, client.InitWithNewEndpointAndPassReceiver(),
       GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI));
 
   service->RemoteCharacteristicStartNotifications(
-      characteristic_->instance_id, std::move(ptr_info),
+      characteristic_->instance_id, std::move(client),
       WTF::Bind(&BluetoothRemoteGATTCharacteristic::NotificationsCallback,
                 WrapPersistent(this), WrapPersistent(resolver)));
 
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.h b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.h
index ef53c8cc..7bd75f2 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.h
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.h
@@ -5,7 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_REMOTE_GATT_CHARACTERISTIC_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_REMOTE_GATT_CHARACTERISTIC_H_
 
-#include "mojo/public/cpp/bindings/associated_binding_set.h"
+#include "mojo/public/cpp/bindings/associated_receiver_set.h"
 #include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
 #include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
@@ -133,8 +133,8 @@
   Member<BluetoothCharacteristicProperties> properties_;
   Member<DOMDataView> value_;
   Member<BluetoothDevice> device_;
-  mojo::AssociatedBindingSet<mojom::blink::WebBluetoothCharacteristicClient>
-      client_bindings_;
+  mojo::AssociatedReceiverSet<mojom::blink::WebBluetoothCharacteristicClient>
+      receivers_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.cc
index dc80911..a74a5746 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.cc
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.cc
@@ -5,7 +5,10 @@
 #include "third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.h"
 
 #include <utility>
-#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
+
+#include "mojo/public/cpp/bindings/associated_receiver_set.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
+#include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
@@ -75,7 +78,7 @@
   DisconnectIfConnected();
   // The pipe to this object must be closed when is marked unreachable to
   // prevent messages from being dispatched before lazy sweeping.
-  client_bindings_.CloseAllBindings();
+  client_receivers_.Clear();
 }
 
 void BluetoothRemoteGATTServer::Trace(blink::Visitor* visitor) {
@@ -106,15 +109,15 @@
 
   mojom::blink::WebBluetoothService* service =
       device_->GetBluetooth()->Service();
-  mojom::blink::WebBluetoothServerClientAssociatedPtrInfo ptr_info;
+  mojo::PendingAssociatedRemote<mojom::blink::WebBluetoothServerClient> client;
   // See https://bit.ly/2S0zRAS for task types.
   scoped_refptr<base::SingleThreadTaskRunner> task_runner =
       GetExecutionContext()->GetTaskRunner(TaskType::kMiscPlatformAPI);
-  auto request = mojo::MakeRequest(&ptr_info);
-  client_bindings_.AddBinding(this, std::move(request), std::move(task_runner));
+  client_receivers_.Add(this, client.InitWithNewEndpointAndPassReceiver(),
+                        std::move(task_runner));
 
   service->RemoteServerConnect(
-      device_->id(), std::move(ptr_info),
+      device_->id(), std::move(client),
       WTF::Bind(&BluetoothRemoteGATTServer::ConnectCallback,
                 WrapPersistent(this), WrapPersistent(resolver)));
 
@@ -125,7 +128,7 @@
   if (!connected_)
     return;
   CleanupDisconnectedDeviceAndFireEvent();
-  client_bindings_.CloseAllBindings();
+  client_receivers_.Clear();
   mojom::blink::WebBluetoothService* service =
       device_->GetBluetooth()->Service();
   service->RemoteServerDisconnect(device_->id());
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.h b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.h
index 62d24b3..73c60c1 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.h
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.h
@@ -5,7 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_REMOTE_GATT_SERVER_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_REMOTE_GATT_SERVER_H_
 
-#include "mojo/public/cpp/bindings/associated_binding_set.h"
+#include "mojo/public/cpp/bindings/associated_receiver_set.h"
 #include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/modules/v8/string_or_unsigned_long.h"
 #include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
@@ -108,8 +108,8 @@
   // using this server’s connection.
   HeapHashSet<Member<ScriptPromiseResolver>> active_algorithms_;
 
-  mojo::AssociatedBindingSet<mojom::blink::WebBluetoothServerClient>
-      client_bindings_;
+  mojo::AssociatedReceiverSet<mojom::blink::WebBluetoothServerClient>
+      client_receivers_;
 
   Member<BluetoothDevice> device_;
   bool connected_;
@@ -117,4 +117,4 @@
 
 }  // namespace blink
 
-#endif  // BluetoothDevice_h
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_BLUETOOTH_BLUETOOTH_REMOTE_GATT_SERVER_H_
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 801b914..f43ed0d 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
@@ -63,7 +63,7 @@
 
   SkBitmap black_bitmap;
   black_bitmap.allocN32Pixels(copy_image->width(), copy_image->height());
-  black_bitmap.eraseColor(SkColorSetRGB(0, 0, 0));
+  black_bitmap.eraseARGB(0, 0, 0, 0);
   image_layer_bridge_->SetImage(
       StaticBitmapImage::Create(SkImage::MakeFromBitmap(black_bitmap)));
 
diff --git a/third_party/blink/renderer/modules/locks/lock_manager.cc b/third_party/blink/renderer/modules/locks/lock_manager.cc
index 2f6acc8..6790c7da 100644
--- a/third_party/blink/renderer/modules/locks/lock_manager.cc
+++ b/third_party/blink/renderer/modules/locks/lock_manager.cc
@@ -7,7 +7,7 @@
 #include <algorithm>
 
 #include "mojo/public/cpp/bindings/associated_receiver.h"
-#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_lock_granted_callback.h"
@@ -227,10 +227,10 @@
   }
 
   if (!service_.is_bound()) {
-    if (auto* provider = context->GetInterfaceProvider()) {
-      provider->GetInterface(service_.BindNewPipeAndPassReceiver(
-          context->GetTaskRunner(TaskType::kMiscPlatformAPI)));
-    }
+    context->GetBrowserInterfaceBroker().GetInterface(
+        service_.BindNewPipeAndPassReceiver(
+            context->GetTaskRunner(TaskType::kMiscPlatformAPI)));
+
     if (!service_.is_bound()) {
       exception_state.ThrowTypeError("Service not available.");
       return ScriptPromise();
@@ -347,10 +347,10 @@
   }
 
   if (!service_.is_bound()) {
-    if (auto* provider = context->GetInterfaceProvider()) {
-      provider->GetInterface(service_.BindNewPipeAndPassReceiver(
-          context->GetTaskRunner(TaskType::kMiscPlatformAPI)));
-    }
+    context->GetBrowserInterfaceBroker().GetInterface(
+        service_.BindNewPipeAndPassReceiver(
+            context->GetTaskRunner(TaskType::kMiscPlatformAPI)));
+
     if (!service_.is_bound()) {
       exception_state.ThrowTypeError("Service not available.");
       return ScriptPromise();
diff --git a/third_party/blink/renderer/platform/graphics/OWNERS b/third_party/blink/renderer/platform/graphics/OWNERS
index 28d1c109..73a6535 100644
--- a/third_party/blink/renderer/platform/graphics/OWNERS
+++ b/third_party/blink/renderer/platform/graphics/OWNERS
@@ -17,6 +17,9 @@
 # lowLatency canvas
 mcasas@chromium.org
 
+# canvas resources and images
+khushalsagar@chromium.org
+
 # TEAM: paint-dev@chromium.org
 # COMPONENT: Blink>Paint
 
diff --git a/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc b/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc
index 0d7ea36..e134ad7 100644
--- a/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc
+++ b/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc
@@ -59,6 +59,10 @@
   if (compositor_frame_sink_.is_bound())
     return;
 
+  // Once we are using RAF, this thread is driving Display updates. Update
+  // priority accordingly.
+  base::PlatformThread::SetCurrentThreadPriority(base::ThreadPriority::DISPLAY);
+
   mojo::Remote<mojom::blink::EmbeddedFrameSinkProvider> provider;
   Platform::Current()->GetInterfaceProvider()->GetInterface(
       provider.BindNewPipeAndPassReceiver());
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
index d670a59..fa7b124 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
@@ -559,7 +559,7 @@
     // space.
     SkBitmap black_bitmap;
     black_bitmap.allocN32Pixels(size_.Width(), size_.Height());
-    black_bitmap.eraseARGB(0, 255, 255, 255);
+    black_bitmap.eraseARGB(0, 0, 0, 0);
     return StaticBitmapImage::Create(SkImage::MakeFromBitmap(black_bitmap));
   }
 
diff --git a/third_party/blink/renderer/platform/heap/persistent.h b/third_party/blink/renderer/platform/heap/persistent.h
index 7a0e9636..a2e9ed6 100644
--- a/third_party/blink/renderer/platform/heap/persistent.h
+++ b/third_party/blink/renderer/platform/heap/persistent.h
@@ -64,7 +64,10 @@
     return result;
   }
 
-  void Clear() { AssignSafe(nullptr); }
+  void Clear() {
+    // Note that this also frees up related data in the backend.
+    AssignSafe(nullptr);
+  }
 
   T* Get() const {
     CheckPointer();
diff --git a/third_party/blink/renderer/platform/heap/persistent_node.cc b/third_party/blink/renderer/platform/heap/persistent_node.cc
index 5edbdc75..a0a6bb8c 100644
--- a/third_party/blink/renderer/platform/heap/persistent_node.cc
+++ b/third_party/blink/renderer/platform/heap/persistent_node.cc
@@ -19,59 +19,44 @@
 };
 }
 
-PersistentRegion::~PersistentRegion() {
+PersistentRegionBase::~PersistentRegionBase() {
   PersistentNodeSlots* slots = slots_;
   while (slots) {
     PersistentNodeSlots* dead_slots = slots;
-    slots = slots->next_;
+    slots = slots->next;
     delete dead_slots;
   }
 }
 
-int PersistentRegion::NumberOfPersistents() {
+int PersistentRegionBase::NodesInUse() const {
   size_t persistent_count = 0;
-  for (PersistentNodeSlots* slots = slots_; slots; slots = slots->next_) {
+  for (PersistentNodeSlots* slots = slots_; slots; slots = slots->next) {
     for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) {
-      if (!slots->slot_[i].IsUnused())
+      if (!slots->slot[i].IsUnused())
         ++persistent_count;
     }
   }
 #if DCHECK_IS_ON()
-  DCHECK_EQ(persistent_count, persistent_count_);
+  DCHECK_EQ(persistent_count, used_node_count_);
 #endif
   return persistent_count;
 }
 
-void PersistentRegion::EnsurePersistentNodeSlots(void* self,
-                                                 TraceCallback trace) {
+void PersistentRegionBase::EnsureNodeSlots() {
   DCHECK(!free_list_head_);
   PersistentNodeSlots* slots = new PersistentNodeSlots;
   for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) {
-    PersistentNode* node = &slots->slot_[i];
+    PersistentNode* node = &slots->slot[i];
     node->SetFreeListNext(free_list_head_);
     free_list_head_ = node;
     DCHECK(node->IsUnused());
   }
-  slots->next_ = slots_;
+  slots->next = slots_;
   slots_ = slots;
 }
 
-void PersistentRegion::ReleasePersistentNode(PersistentNode* persistent_node) {
-  DCHECK(!persistent_node->IsUnused());
-  // 'self' is in use, containing the persistent wrapper object.
-  void* self = persistent_node->Self();
-  Persistent<DummyGCBase>* persistent =
-      reinterpret_cast<Persistent<DummyGCBase>*>(self);
-  persistent->Clear();
-  DCHECK(persistent_node->IsUnused());
-}
-
-// This function traces all PersistentNodes. If we encounter
-// a PersistentNodeSlot that contains only freed PersistentNodes,
-// we delete the PersistentNodeSlot. This function rebuilds the free
-// list of PersistentNodes.
-void PersistentRegion::TracePersistentNodes(Visitor* visitor,
-                                            ShouldTraceCallback should_trace) {
+void PersistentRegionBase::TraceNodesImpl(Visitor* visitor,
+                                          ShouldTraceCallback should_trace) {
   free_list_head_ = nullptr;
   size_t persistent_count = 0;
   PersistentNodeSlots** prev_next = &slots_;
@@ -81,7 +66,7 @@
     PersistentNode* free_list_last = nullptr;
     int free_count = 0;
     for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) {
-      PersistentNode* node = &slots->slot_[i];
+      PersistentNode* node = &slots->slot[i];
       if (node->IsUnused()) {
         if (!free_list_next)
           free_list_last = node;
@@ -97,8 +82,8 @@
     }
     if (free_count == PersistentNodeSlots::kSlotCount) {
       PersistentNodeSlots* dead_slots = slots;
-      *prev_next = slots->next_;
-      slots = slots->next_;
+      *prev_next = slots->next;
+      slots = slots->next;
       delete dead_slots;
     } else {
       if (free_list_last) {
@@ -107,21 +92,32 @@
         free_list_last->SetFreeListNext(free_list_head_);
         free_list_head_ = free_list_next;
       }
-      prev_next = &slots->next_;
-      slots = slots->next_;
+      prev_next = &slots->next;
+      slots = slots->next;
     }
   }
 #if DCHECK_IS_ON()
-  DCHECK_EQ(persistent_count, persistent_count_);
+  DCHECK_EQ(persistent_count, used_node_count_);
 #endif
 }
 
-void PersistentRegion::PrepareForThreadStateTermination() {
+void PersistentRegion::ReleaseNode(PersistentNode* persistent_node) {
+  DCHECK(!persistent_node->IsUnused());
+  // 'self' is in use, containing the persistent wrapper object.
+  void* self = persistent_node->Self();
+  Persistent<DummyGCBase>* persistent =
+      reinterpret_cast<Persistent<DummyGCBase>*>(self);
+  persistent->Clear();
+  DCHECK(persistent_node->IsUnused());
+}
+
+void PersistentRegion::PrepareForThreadStateTermination(ThreadState* state) {
+  DCHECK_EQ(state, ThreadState::Current());
   DCHECK(!IsMainThread());
   PersistentNodeSlots* slots = slots_;
   while (slots) {
     for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) {
-      PersistentNode* node = &slots->slot_[i];
+      PersistentNode* node = &slots->slot[i];
       if (node->IsUnused())
         continue;
       // It is safe to cast to Persistent<DummyGCBase> because persistent heap
@@ -132,10 +128,10 @@
       persistent->Clear();
       DCHECK(node->IsUnused());
     }
-    slots = slots->next_;
+    slots = slots->next;
   }
 #if DCHECK_IS_ON()
-  DCHECK_EQ(persistent_count_, 0u);
+  DCHECK_EQ(used_node_count_, 0u);
 #endif
 }
 
@@ -159,17 +155,17 @@
   // out the underlying heap reference.
   MutexLocker lock(ProcessHeap::CrossThreadPersistentMutex());
 
-  PersistentNodeSlots* slots = persistent_region_.slots_;
+  PersistentNodeSlots* slots = slots_;
   while (slots) {
     for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) {
-      if (slots->slot_[i].IsUnused())
+      if (slots->slot[i].IsUnused())
         continue;
 
       // 'self' is in use, containing the cross-thread persistent wrapper
       // object.
       CrossThreadPersistent<DummyGCBase>* persistent =
           reinterpret_cast<CrossThreadPersistent<DummyGCBase>*>(
-              slots->slot_[i].Self());
+              slots->slot[i].Self());
       DCHECK(persistent);
       void* raw_object = persistent->Get();
       if (!raw_object)
@@ -178,10 +174,10 @@
       DCHECK(page);
       if (page->Arena()->GetThreadState() == thread_state) {
         persistent->ClearWithLockHeld();
-        DCHECK(slots->slot_[i].IsUnused());
+        DCHECK(slots->slot[i].IsUnused());
       }
     }
-    slots = slots->next_;
+    slots = slots->next;
   }
 }
 
@@ -191,10 +187,9 @@
   ProcessHeap::CrossThreadPersistentMutex().AssertAcquired();
 #endif
   size_t persistent_count = 0;
-  for (PersistentNodeSlots* slots = persistent_region_.slots_; slots;
-       slots = slots->next_) {
+  for (PersistentNodeSlots* slots = slots_; slots; slots = slots->next) {
     for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) {
-      const PersistentNode& node = slots->slot_[i];
+      const PersistentNode& node = slots->slot[i];
       if (!node.IsUnused()) {
         ASAN_UNPOISON_MEMORY_REGION(node.Self(),
                                     sizeof(CrossThreadPersistent<void*>));
@@ -203,7 +198,7 @@
     }
   }
 #if DCHECK_IS_ON()
-  DCHECK_EQ(persistent_count, persistent_region_.persistent_count_);
+  DCHECK_EQ(persistent_count, used_node_count_);
 #endif
 }
 #endif
diff --git a/third_party/blink/renderer/platform/heap/persistent_node.h b/third_party/blink/renderer/platform/heap/persistent_node.h
index fcd7142..70bc04a8 100644
--- a/third_party/blink/renderer/platform/heap/persistent_node.h
+++ b/third_party/blink/renderer/platform/heap/persistent_node.h
@@ -123,12 +123,11 @@
 struct PersistentNodeSlots final {
   USING_FAST_MALLOC(PersistentNodeSlots);
 
- private:
-  static const int kSlotCount = 256;
-  PersistentNodeSlots* next_;
-  PersistentNode slot_[kSlotCount];
-  friend class PersistentRegion;
-  friend class CrossThreadPersistentRegion;
+ public:
+  static constexpr int kSlotCount = 256;
+
+  PersistentNodeSlots* next;
+  PersistentNode slot[kSlotCount];
 };
 
 // Used by PersistentBase to manage a pointer to a thread heap persistent node.
@@ -196,118 +195,111 @@
   std::atomic<PersistentNode*> ptr_{nullptr};
 };
 
-// PersistentRegion provides a region of PersistentNodes. PersistentRegion
-// holds a linked list of PersistentNodeSlots, each of which stores
-// a predefined number of PersistentNodes. You can call allocatePersistentNode/
-// freePersistentNode to allocate/free a PersistentNode on the region.
-class PLATFORM_EXPORT PersistentRegion final {
-  USING_FAST_MALLOC(PersistentRegion);
-
+class PLATFORM_EXPORT PersistentRegionBase {
  public:
-  PersistentRegion() = default;
-  ~PersistentRegion();
+  ~PersistentRegionBase();
 
-  PersistentNode* AllocatePersistentNode(void* self, TraceCallback trace) {
-#if DCHECK_IS_ON()
-    ++persistent_count_;
-#endif
-    if (UNLIKELY(!free_list_head_))
-      EnsurePersistentNodeSlots(self, trace);
-    DCHECK(free_list_head_);
-    PersistentNode* node = free_list_head_;
-    free_list_head_ = free_list_head_->FreeListNext();
-    node->Initialize(self, trace);
-    DCHECK(!node->IsUnused());
-    return node;
-  }
+  inline PersistentNode* AllocateNode(void* self, TraceCallback trace);
+  inline void FreeNode(PersistentNode* persistent_node);
+  int NodesInUse() const;
 
-  void FreePersistentNode(PersistentNode* persistent_node) {
-#if DCHECK_IS_ON()
-    DCHECK_GT(persistent_count_, 0u);
-#endif
-    persistent_node->SetFreeListNext(free_list_head_);
-    free_list_head_ = persistent_node;
-#if DCHECK_IS_ON()
-    --persistent_count_;
-#endif
-  }
-
-  static bool ShouldTracePersistentNode(Visitor*, PersistentNode*) {
-    return true;
-  }
-
-  void ReleasePersistentNode(PersistentNode*);
+ protected:
   using ShouldTraceCallback = bool (*)(Visitor*, PersistentNode*);
-  void TracePersistentNodes(
-      Visitor*,
-      ShouldTraceCallback = PersistentRegion::ShouldTracePersistentNode);
-  int NumberOfPersistents();
-  void PrepareForThreadStateTermination();
 
- private:
-  friend CrossThreadPersistentRegion;
+  void TraceNodesImpl(Visitor*, ShouldTraceCallback);
 
-  void EnsurePersistentNodeSlots(void*, TraceCallback);
+  void EnsureNodeSlots();
 
   PersistentNode* free_list_head_ = nullptr;
   PersistentNodeSlots* slots_ = nullptr;
 #if DCHECK_IS_ON()
-  size_t persistent_count_ = 0;
+  size_t used_node_count_ = 0;
 #endif
 };
 
-// Protected by ProcessHeap::CrossThreadPersistentMutex.
-class PLATFORM_EXPORT CrossThreadPersistentRegion final {
-  USING_FAST_MALLOC(CrossThreadPersistentRegion);
+inline PersistentNode* PersistentRegionBase::AllocateNode(void* self,
+                                                          TraceCallback trace) {
+#if DCHECK_IS_ON()
+  ++used_node_count_;
+#endif
+  if (UNLIKELY(!free_list_head_))
+    EnsureNodeSlots();
+  DCHECK(free_list_head_);
+  PersistentNode* node = free_list_head_;
+  free_list_head_ = free_list_head_->FreeListNext();
+  node->Initialize(self, trace);
+  DCHECK(!node->IsUnused());
+  return node;
+}
+
+void PersistentRegionBase::FreeNode(PersistentNode* persistent_node) {
+#if DCHECK_IS_ON()
+  DCHECK_GT(used_node_count_, 0u);
+#endif
+  persistent_node->SetFreeListNext(free_list_head_);
+  free_list_head_ = persistent_node;
+#if DCHECK_IS_ON()
+  --used_node_count_;
+#endif
+}
+
+class PLATFORM_EXPORT PersistentRegion final : public PersistentRegionBase {
+  USING_FAST_MALLOC(PersistentRegion);
 
  public:
-  PersistentNode* AllocatePersistentNode(void* self, TraceCallback trace) {
-    PersistentMutexTraits<
-        kCrossThreadPersistentConfiguration>::AssertAcquired();
-    return persistent_region_.AllocatePersistentNode(self, trace);
-  }
+  inline void TraceNodes(Visitor*);
 
-  void FreePersistentNode(PersistentNode* node) {
-    PersistentMutexTraits<
-        kCrossThreadPersistentConfiguration>::AssertAcquired();
-    // When the thread that holds the heap object that the cross-thread
-    // persistent shuts down, prepareForThreadStateTermination() will clear out
-    // the associated CrossThreadPersistent<> and PersistentNode so as to avoid
-    // unsafe access. This can overlap with a holder of the
-    // CrossThreadPersistent<> also clearing the persistent and freeing the
-    // PersistentNode.
-    //
-    // The lock ensures the updating is ordered, but by the time lock has been
-    // acquired the PersistentNode reference may have been cleared out already;
-    // check for this.
-    if (!node)
-      return;
-    persistent_region_.FreePersistentNode(node);
-  }
-
-  void TracePersistentNodes(Visitor* visitor) {
-    PersistentMutexTraits<
-        kCrossThreadPersistentConfiguration>::AssertAcquired();
-    persistent_region_.TracePersistentNodes(
-        visitor, CrossThreadPersistentRegion::ShouldTracePersistentNode);
-  }
+  // Clears the Persistent and then frees the node.
+  void ReleaseNode(PersistentNode*);
 
   void PrepareForThreadStateTermination(ThreadState*);
 
-  NO_SANITIZE_ADDRESS
-  static bool ShouldTracePersistentNode(Visitor*, PersistentNode*);
+ private:
+  static constexpr bool ShouldTracePersistentNode(Visitor*, PersistentNode*) {
+    return true;
+  }
+};
+
+inline void PersistentRegion::TraceNodes(Visitor* visitor) {
+  PersistentRegionBase::TraceNodesImpl(visitor, ShouldTracePersistentNode);
+}
+
+class PLATFORM_EXPORT CrossThreadPersistentRegion final
+    : public PersistentRegionBase {
+  USING_FAST_MALLOC(CrossThreadPersistentRegion);
+
+ public:
+  inline PersistentNode* AllocateNode(void* self, TraceCallback trace);
+  inline void FreeNode(PersistentNode*);
+  inline void TraceNodes(Visitor*);
+
+  void PrepareForThreadStateTermination(ThreadState*);
 
 #if defined(ADDRESS_SANITIZER)
   void UnpoisonCrossThreadPersistents();
 #endif
 
  private:
-  // We don't make CrossThreadPersistentRegion inherit from PersistentRegion
-  // because we don't want to virtualize performance-sensitive methods
-  // such as PersistentRegion::allocate/freePersistentNode.
-  PersistentRegion persistent_region_;
+  NO_SANITIZE_ADDRESS
+  static bool ShouldTracePersistentNode(Visitor*, PersistentNode*);
 };
 
+inline PersistentNode* CrossThreadPersistentRegion::AllocateNode(
+    void* self,
+    TraceCallback trace) {
+  PersistentMutexTraits<kCrossThreadPersistentConfiguration>::AssertAcquired();
+  return PersistentRegionBase::AllocateNode(self, trace);
+}
+
+inline void CrossThreadPersistentRegion::FreeNode(PersistentNode* node) {
+  PersistentMutexTraits<kCrossThreadPersistentConfiguration>::AssertAcquired();
+  PersistentRegionBase::FreeNode(node);
+}
+
+inline void CrossThreadPersistentRegion::TraceNodes(Visitor* visitor) {
+  PersistentRegionBase::TraceNodesImpl(visitor, ShouldTracePersistentNode);
+}
+
 template <ThreadAffinity affinity,
           WeaknessPersistentConfiguration weakness_configuration>
 void PersistentNodePtr<affinity, weakness_configuration>::Initialize(
@@ -319,7 +311,7 @@
       weakness_configuration == kWeakPersistentConfiguration
           ? state->GetWeakPersistentRegion()
           : state->GetPersistentRegion();
-  ptr_ = region->AllocatePersistentNode(owner, trace_callback);
+  ptr_ = region->AllocateNode(owner, trace_callback);
 #if DCHECK_IS_ON()
   state_ = state;
 #endif
@@ -354,7 +346,7 @@
       weakness_configuration == kWeakPersistentConfiguration
           ? ProcessHeap::GetCrossThreadWeakPersistentRegion()
           : ProcessHeap::GetCrossThreadPersistentRegion();
-  PersistentNode* node = region.AllocatePersistentNode(owner, trace_callback);
+  PersistentNode* node = region.AllocateNode(owner, trace_callback);
   ptr_.store(node, std::memory_order_release);
 }
 
@@ -365,7 +357,7 @@
       weakness_configuration == kWeakPersistentConfiguration
           ? ProcessHeap::GetCrossThreadWeakPersistentRegion()
           : ProcessHeap::GetCrossThreadPersistentRegion();
-  region.FreePersistentNode(ptr_.load(std::memory_order_relaxed));
+  region.FreeNode(ptr_.load(std::memory_order_relaxed));
   ptr_.store(nullptr, std::memory_order_release);
 }
 
@@ -376,7 +368,7 @@
       weakness_configuration == kWeakPersistentConfiguration
           ? ProcessHeap::GetCrossThreadWeakPersistentRegion()
           : ProcessHeap::GetCrossThreadPersistentRegion();
-  region.FreePersistentNode(ptr_.load(std::memory_order_relaxed));
+  region.FreeNode(ptr_.load(std::memory_order_relaxed));
   ptr_.store(nullptr, std::memory_order_release);
 }
 
diff --git a/third_party/blink/renderer/platform/heap/thread_state.cc b/third_party/blink/renderer/platform/heap/thread_state.cc
index 27bf1f2..505b261 100644
--- a/third_party/blink/renderer/platform/heap/thread_state.cc
+++ b/third_party/blink/renderer/platform/heap/thread_state.cc
@@ -217,7 +217,7 @@
   // Do thread local GC's as long as the count of thread local Persistents
   // changes and is above zero.
   int old_count = -1;
-  int current_count = GetPersistentRegion()->NumberOfPersistents();
+  int current_count = GetPersistentRegion()->NodesInUse();
   DCHECK_GE(current_count, 0);
   while (current_count != old_count) {
     CollectGarbage(BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
@@ -227,7 +227,7 @@
     // instantiated while running the termination GC.
     ReleaseStaticPersistentNodes();
     old_count = current_count;
-    current_count = GetPersistentRegion()->NumberOfPersistents();
+    current_count = GetPersistentRegion()->NodesInUse();
   }
 
   // We should not have any persistents left when getting to this point,
@@ -235,17 +235,17 @@
   // RegisterAsStaticReference. Clearing out all the Persistents will avoid
   // stale pointers and gets them reported as nullptr dereferences.
   if (current_count) {
-    for (size_t i = 0; i < kMaxTerminationGCLoops &&
-                       GetPersistentRegion()->NumberOfPersistents();
+    for (size_t i = 0;
+         i < kMaxTerminationGCLoops && GetPersistentRegion()->NodesInUse();
          i++) {
-      GetPersistentRegion()->PrepareForThreadStateTermination();
+      GetPersistentRegion()->PrepareForThreadStateTermination(this);
       CollectGarbage(BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
                      BlinkGC::kEagerSweeping,
                      BlinkGC::GCReason::kThreadTerminationGC);
     }
   }
 
-  CHECK(!GetPersistentRegion()->NumberOfPersistents());
+  CHECK(!GetPersistentRegion()->NodesInUse());
 
   // All of pre-finalizers should be consumed.
   DCHECK(ordered_pre_finalizers_.empty());
@@ -326,19 +326,18 @@
         Heap().stats_collector(),
         ThreadHeapStatsCollector::kVisitCrossThreadPersistents);
     ProcessHeap::CrossThreadPersistentMutex().AssertAcquired();
-    ProcessHeap::GetCrossThreadPersistentRegion().TracePersistentNodes(visitor);
+    ProcessHeap::GetCrossThreadPersistentRegion().TraceNodes(visitor);
   }
   {
     ThreadHeapStatsCollector::Scope inner_stats_scope(
         Heap().stats_collector(), ThreadHeapStatsCollector::kVisitPersistents);
-    persistent_region_->TracePersistentNodes(visitor);
+    persistent_region_->TraceNodes(visitor);
   }
 }
 
 void ThreadState::VisitWeakPersistents(Visitor* visitor) {
-  ProcessHeap::GetCrossThreadWeakPersistentRegion().TracePersistentNodes(
-      visitor);
-  weak_persistent_region_->TracePersistentNodes(visitor);
+  ProcessHeap::GetCrossThreadWeakPersistentRegion().TraceNodes(visitor);
+  weak_persistent_region_->TraceNodes(visitor);
 }
 
 ThreadState::GCSnapshotInfo::GCSnapshotInfo(wtf_size_t num_object_types)
@@ -981,12 +980,12 @@
 
   PersistentRegion* persistent_region = GetPersistentRegion();
   for (PersistentNode* it : static_persistents)
-    persistent_region->ReleasePersistentNode(it);
+    persistent_region->ReleaseNode(it);
 }
 
 void ThreadState::FreePersistentNode(PersistentRegion* persistent_region,
                                      PersistentNode* persistent_node) {
-  persistent_region->FreePersistentNode(persistent_node);
+  persistent_region->FreeNode(persistent_node);
   // Do not allow static persistents to be freed before
   // they're all released in releaseStaticPersistentNodes().
   //
diff --git a/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.h b/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.h
index dff0c8c..e5e8cef 100644
--- a/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.h
+++ b/third_party/blink/renderer/platform/network/encoded_form_data_element_mojom_traits.h
@@ -31,9 +31,9 @@
   static mojo::PendingRemote<network::mojom::blink::DataPipeGetter>
   data_pipe_getter(const blink::FormDataElement& data);
 
-  static network::mojom::blink::ChunkedDataPipeGetterPtrInfo
+  static mojo::PendingRemote<network::mojom::blink::ChunkedDataPipeGetter>
   chunked_data_pipe_getter(const blink::FormDataElement& data) {
-    return nullptr;
+    return mojo::NullRemote();
   }
 
   static uint64_t offset(const blink::FormDataElement& data) {
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index b6505d0..8c94d197 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -6229,3 +6229,8 @@
 
 # Sheriff 2019-09-11
 crbug.com/1002828 [ Linux ] virtual/compositor_threaded_scrollbar_scrolling/fast/scrolling/scrollbars/scrollbar-button-gesture-target.html [ Pass Failure Crash ]
+
+crbug.com/913887 fast/dom/Window/window-postmessage-args.html [ Skip ]
+crbug.com/913887 fast/dom/Window/window-postmessage-clone.html [ Skip ]
+crbug.com/913887 fast/events/message-port-clone.html [ Skip ]
+crbug.com/913887 virtual/mouseevent_fractional/fast/events/message-port-clone.html [ Skip ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
index 9e24d7b9..90a643d9 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
@@ -156010,9 +156010,6 @@
    "geolocation-API/getCurrentPosition_permission_allow.https-expected.txt": [
     []
    ],
-   "geolocation-API/idlharness.https.window-expected.txt": [
-    []
-   ],
    "geolocation-API/support.js": [
     []
    ],
@@ -164833,6 +164830,9 @@
    "mathml/support/box-comparison.js": [
     []
    ],
+   "mathml/support/box-navigation.js": [
+    []
+   ],
    "mathml/support/feature-detection.js": [
     []
    ],
@@ -169057,6 +169057,9 @@
    "resource-timing/resources/self_navigation.html": [
     []
    ],
+   "resource-timing/resources/status-code.py": [
+    []
+   ],
    "resource-timing/resources/webperftestharness.js": [
     []
    ],
@@ -177010,9 +177013,6 @@
    "web-animations/testcommon.js": [
     []
    ],
-   "web-animations/timing-model/animations/canceling-an-animation-expected.txt": [
-    []
-   ],
    "web-animations/timing-model/animations/pausing-an-animation-expected.txt": [
     []
    ],
@@ -284731,12 +284731,6 @@
      {}
     ]
    ],
-   "resource-timing/resource_ignore_failures.html": [
-    [
-     "resource-timing/resource_ignore_failures.html",
-     {}
-    ]
-   ],
    "resource-timing/resource_initiator_types.html": [
     [
      "resource-timing/resource_initiator_types.html",
@@ -284823,6 +284817,12 @@
      }
     ]
    ],
+   "resource-timing/status-codes-create-entry.html": [
+    [
+     "resource-timing/status-codes-create-entry.html",
+     {}
+    ]
+   ],
    "resource-timing/supported_resource_type.any.js": [
     [
      "resource-timing/supported_resource_type.any.html",
@@ -372034,11 +372034,11 @@
    "testharness"
   ],
   "css/css-grid/alignment/grid-inline-axis-alignment-auto-margins-005.html": [
-   "dc8a2e96f0231f33d1647a1583ea2504e8a857b3",
+   "fd9e696a55e17dc12079df698860b30b192d149d",
    "testharness"
   ],
   "css/css-grid/alignment/grid-inline-axis-alignment-auto-margins-006.html": [
-   "ab933844e9c2f1bec3b766c74578cfb1ae7ba940",
+   "4492f9b1ebbe7cbc6eadecd9cde2c1de1afd6192",
    "testharness"
   ],
   "css/css-grid/alignment/grid-inline-axis-alignment-auto-margins-007.html": [
@@ -428206,7 +428206,7 @@
    "support"
   ],
   "feature-policy/reporting/geolocation-report-only.https-expected.txt": [
-   "93220611ee3618ea05ef73671e21cc39227bf024",
+   "c7c46f13a8af49acc190e0d0225c264115cb3cf8",
    "support"
   ],
   "feature-policy/reporting/geolocation-report-only.https.html": [
@@ -431594,11 +431594,11 @@
    "testharness"
   ],
   "geolocation-API/getCurrentPosition_IDL.https-expected.txt": [
-   "cacf8e368bdeb1d0ef36970e9f7c560a45f8d131",
+   "a399a8b221b34d125de1a94be778d3c915382eed",
    "support"
   ],
   "geolocation-API/getCurrentPosition_IDL.https.html": [
-   "75426fc3b99d8663243e58ab9bbf0336a02a346c",
+   "1688c86278966552066235a514853e8b1064bb34",
    "testharness"
   ],
   "geolocation-API/getCurrentPosition_TypeError.html": [
@@ -431629,10 +431629,6 @@
    "50129608ac7e6e8d64e6dd966eda1172b5929a70",
    "testharness"
   ],
-  "geolocation-API/idlharness.https.window-expected.txt": [
-   "5f60ebaf31a337874f940db5963fee823f2cd241",
-   "support"
-  ],
   "geolocation-API/idlharness.https.window.js": [
    "fe4ac8895dfb6e889eded7d694e3c87905868b4f",
    "testharness"
@@ -452258,7 +452254,7 @@
    "testharness"
   ],
   "imagebitmap-renderingcontext/tranferFromImageBitmap-TransferToImageBitmap-offscreen.html": [
-   "9f9c3395733a8a39de61ce8a616c3871e20e7e4f",
+   "7e04da63ddb1f1132c53ab49e6bda713ace55ea1",
    "testharness"
   ],
   "imagebitmap-renderingcontext/tranferFromImageBitmap-null-offscreen.html": [
@@ -453358,7 +453354,7 @@
    "support"
   ],
   "interfaces/FileAPI.idl": [
-   "0ae43bbe38cf6cfd78d2f8f468d45ee3aea8ee2b",
+   "a630226c3df3d3dd09cb5ef85435319fdd8ef632",
    "support"
   ],
   "interfaces/IndexedDB.idl": [
@@ -453414,7 +453410,7 @@
    "support"
   ],
   "interfaces/background-fetch.idl": [
-   "0dbe3fbad3cf343c36977380653c73144c6659d8",
+   "cf3d75125402197f7b1a52b4a38fe9acc168643f",
    "support"
   ],
   "interfaces/battery-status.idl": [
@@ -453798,7 +453794,7 @@
    "support"
   ],
   "interfaces/service-workers.idl": [
-   "0feabd389cf556a6ff6d3978fd23e2e288624054",
+   "c01fcab7f2d92491899907bc3c0505e8a4d4ba63",
    "support"
   ],
   "interfaces/shape-detection-api.idl": [
@@ -455038,11 +455034,11 @@
    "testharness"
   ],
   "mathml/presentation-markup/operators/embellished-operator-001.html": [
-   "b7d9b4945558440edbba2cb5fd3d7629b7f22087",
+   "31bdff2fd7c2c4e463adfba2c3768d678c5c7424",
    "testharness"
   ],
   "mathml/presentation-markup/operators/embellished-operator-002.html": [
-   "b7b7f51d75bbad3140f9affe11262b7c69ceadea",
+   "1bbed4e229ef3cc010c9fab7b9541911abd310f6",
    "testharness"
   ],
   "mathml/presentation-markup/operators/mo-axis-height-1.html": [
@@ -455198,7 +455194,7 @@
    "testharness"
   ],
   "mathml/presentation-markup/spaces/space-like-004.html": [
-   "091a3ea0a628c9b18b4b262aef737d7a7c9dac0a",
+   "2ad6b0b772c39cad147604523409d85bee999564",
    "testharness"
   ],
   "mathml/presentation-markup/tables/table-axis-height.html": [
@@ -455801,6 +455797,10 @@
    "a574b01706b5fecc232d62735ef7e89938594769",
    "support"
   ],
+  "mathml/support/box-navigation.js": [
+   "362648771202bdc94d1355385ccf9515f7983200",
+   "support"
+  ],
   "mathml/support/feature-detection.js": [
    "50ca926d25ea810177068a5f5de29f39749db7e6",
    "support"
@@ -479917,10 +479917,6 @@
    "f8ca2f1187e934fc9b07b5dbc31769f887528b51",
    "testharness"
   ],
-  "resource-timing/resource_ignore_failures.html": [
-   "fa9e411ea989218489adf02224b15aa46bcfbd9a",
-   "testharness"
-  ],
   "resource-timing/resource_initiator_types.html": [
    "9912da7c3400138d73245acc372463ca174e6f58",
    "testharness"
@@ -480201,6 +480197,10 @@
    "beb12f5da551780fcb4378bef4661b9699a5d009",
    "support"
   ],
+  "resource-timing/resources/status-code.py": [
+   "6ddad159524db2870acd4a56115af6d74c460387",
+   "support"
+  ],
   "resource-timing/resources/webperftestharness.js": [
    "203eb0d16b4f3ad8d22877ff7afc7064fe252892",
    "support"
@@ -480217,6 +480217,10 @@
    "c7f777a174a6a307c81fba3d6082fb152be99b1f",
    "testharness"
   ],
+  "resource-timing/status-codes-create-entry.html": [
+   "fb4236e6bbe856be21e5af577a3fea03d774b8e1",
+   "testharness"
+  ],
   "resource-timing/supported_resource_type.any.js": [
    "31e40096ddb2c3a8e38ddbeec00a67ca7a91ce59",
    "testharness"
@@ -483006,7 +483010,7 @@
    "testharness"
   ],
   "service-workers/service-worker/resource-timing.sub.https.html": [
-   "f0502cac727896ce674f3b93a9dd4cfcbf54b41b",
+   "2a366087cd35e793a9544e97327bb3f5ed7b3091",
    "testharness"
   ],
   "service-workers/service-worker/resources/404.py": [
@@ -496689,12 +496693,8 @@
    "3c42f79a7101e44195938137414d05cf6ff503ef",
    "testharness"
   ],
-  "web-animations/timing-model/animations/canceling-an-animation-expected.txt": [
-   "f58af1789613675bf6a9b2363cd5f6112101948e",
-   "support"
-  ],
   "web-animations/timing-model/animations/canceling-an-animation.html": [
-   "b0ef0b1bf96b64ddd052a8ad91401e9fb97f8388",
+   "b2a7a33e6e67e5d88ba2df5f91244860c7120d0f",
    "testharness"
   ],
   "web-animations/timing-model/animations/finishing-an-animation.html": [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-inline-axis-alignment-auto-margins-005.html b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-inline-axis-alignment-auto-margins-005.html
index dc8a2e9..fd9e696 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-inline-axis-alignment-auto-margins-005.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-inline-axis-alignment-auto-margins-005.html
@@ -39,12 +39,14 @@
 document.fonts.ready.then(() => {
     item1.setAttribute("data-offset-x", "50");
     item2.setAttribute("data-offset-x", "325");
-    checkLayout('#grid');
+    checkLayout('#grid', false);
 
     item2.style.fontSize = "30px";
 
     item1.setAttribute("data-offset-x", "50");
     item2.setAttribute("data-offset-x", "275");
-    checkLayout('#grid');
+    checkLayout('#grid', false);
+
+    done();
 });
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-inline-axis-alignment-auto-margins-006.html b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-inline-axis-alignment-auto-margins-006.html
index ab93384..4492f9b1e 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-inline-axis-alignment-auto-margins-006.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-inline-axis-alignment-auto-margins-006.html
@@ -38,12 +38,14 @@
 document.fonts.ready.then(() => {
     item1.setAttribute("data-offset-x", "80");
     item2.setAttribute("data-offset-x", "340");
-    checkLayout('#grid');
+    checkLayout('#grid', false);
 
     grid.style.fontSize = "25px";
 
     item1.setAttribute("data-offset-x", "50");
     item2.setAttribute("data-offset-x", "325");
-    checkLayout('#grid');
+    checkLayout('#grid', false);
+
+    done();
 });
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/imagebitmap-renderingcontext/tranferFromImageBitmap-TransferToImageBitmap-offscreen.html b/third_party/blink/web_tests/external/wpt/imagebitmap-renderingcontext/tranferFromImageBitmap-TransferToImageBitmap-offscreen.html
index 9f9c339..7e04da6 100644
--- a/third_party/blink/web_tests/external/wpt/imagebitmap-renderingcontext/tranferFromImageBitmap-TransferToImageBitmap-offscreen.html
+++ b/third_party/blink/web_tests/external/wpt/imagebitmap-renderingcontext/tranferFromImageBitmap-TransferToImageBitmap-offscreen.html
@@ -36,7 +36,7 @@
         var myCanvas2 = document.createElement('canvas');
         var myCtx2 = myCanvas2.getContext('bitmaprenderer');
         myCtx2.transferFromImageBitmap(bitmapCanvas.transferToImageBitmap());
-        testCanvas(myCanvas2, 0, 0, 0, 255);
+        testCanvas(myCanvas2, 0, 0, 0, 0);
     }
 
     var greenCanvas = document.createElement('canvas');
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/FileAPI.idl b/third_party/blink/web_tests/external/wpt/interfaces/FileAPI.idl
index 0ae43bb..a630226c 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/FileAPI.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/FileAPI.idl
@@ -3,10 +3,10 @@
 // (https://github.com/tidoust/reffy-reports)
 // Source: File API (https://w3c.github.io/FileAPI/)
 
-[Constructor(optional sequence<BlobPart> blobParts,
-             optional BlobPropertyBag options = {}),
- Exposed=(Window,Worker), Serializable]
+[Exposed=(Window,Worker), Serializable]
 interface Blob {
+  constructor(optional sequence<BlobPart> blobParts,
+              optional BlobPropertyBag options = {});
 
   readonly attribute unsigned long long size;
   readonly attribute DOMString type;
@@ -31,11 +31,11 @@
 
 typedef (BufferSource or Blob or USVString) BlobPart;
 
-[Constructor(sequence<BlobPart> fileBits,
-             USVString fileName,
-             optional FilePropertyBag options = {}),
- Exposed=(Window,Worker), Serializable]
+[Exposed=(Window,Worker), Serializable]
 interface File : Blob {
+  constructor(sequence<BlobPart> fileBits,
+              USVString fileName,
+              optional FilePropertyBag options = {});
   readonly attribute DOMString name;
   readonly attribute long long lastModified;
 };
@@ -50,9 +50,9 @@
   readonly attribute unsigned long length;
 };
 
-[Constructor, Exposed=(Window,Worker)]
+[Exposed=(Window,Worker)]
 interface FileReader: EventTarget {
-
+  constructor();
   // async read methods
   void readAsArrayBuffer(Blob blob);
   void readAsBinaryString(Blob blob);
@@ -82,8 +82,9 @@
   attribute EventHandler onloadend;
 };
 
-[Constructor, Exposed=(DedicatedWorker,SharedWorker)]
+[Exposed=(DedicatedWorker,SharedWorker)]
 interface FileReaderSync {
+  constructor();
   // Synchronously return strings
 
   ArrayBuffer readAsArrayBuffer(Blob blob);
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/background-fetch.idl b/third_party/blink/web_tests/external/wpt/interfaces/background-fetch.idl
index 0dbe3fba..cf3d751 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/background-fetch.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/background-fetch.idl
@@ -16,7 +16,7 @@
 
 [Exposed=(Window,Worker)]
 interface BackgroundFetchManager {
-  Promise<BackgroundFetchRegistration> fetch(DOMString id, (RequestInfo or sequence<RequestInfo>) requests, optional BackgroundFetchOptions options);
+  Promise<BackgroundFetchRegistration> fetch(DOMString id, (RequestInfo or sequence<RequestInfo>) requests, optional BackgroundFetchOptions options = {});
   Promise<BackgroundFetchRegistration?> get(DOMString id);
   Promise<sequence<DOMString>> getIds();
 };
@@ -44,8 +44,8 @@
   attribute EventHandler onprogress;
 
   Promise<boolean> abort();
-  Promise<BackgroundFetchRecord> match(RequestInfo request, optional CacheQueryOptions options);
-  Promise<sequence<BackgroundFetchRecord>> matchAll(optional RequestInfo request, optional CacheQueryOptions options);
+  Promise<BackgroundFetchRecord> match(RequestInfo request, optional CacheQueryOptions options = {});
+  Promise<sequence<BackgroundFetchRecord>> matchAll(optional RequestInfo request, optional CacheQueryOptions options = {});
 };
 
 enum BackgroundFetchResult { "", "success", "failure" };
@@ -72,8 +72,9 @@
   readonly attribute Promise<Response> responseReady;
 };
 
-[Constructor(DOMString type, BackgroundFetchEventInit init), Exposed=ServiceWorker]
+[Exposed=ServiceWorker]
 interface BackgroundFetchEvent : ExtendableEvent {
+  constructor(DOMString type, BackgroundFetchEventInit init);
   readonly attribute BackgroundFetchRegistration registration;
 };
 
@@ -81,7 +82,8 @@
   required BackgroundFetchRegistration registration;
 };
 
-[Constructor(DOMString type, BackgroundFetchEventInit init), Exposed=ServiceWorker]
+[Exposed=ServiceWorker]
 interface BackgroundFetchUpdateUIEvent : BackgroundFetchEvent {
-  Promise<void> updateUI(optional BackgroundFetchUIOptions options);
+  constructor(DOMString type, BackgroundFetchEventInit init);
+  Promise<void> updateUI(optional BackgroundFetchUIOptions options = {});
 };
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/service-workers.idl b/third_party/blink/web_tests/external/wpt/interfaces/service-workers.idl
index 0feabd3..c01fcab7 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/service-workers.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/service-workers.idl
@@ -155,8 +155,9 @@
   "all"
 };
 
-[Constructor(DOMString type, optional ExtendableEventInit eventInitDict = {}), Exposed=ServiceWorker]
+[Exposed=ServiceWorker]
 interface ExtendableEvent : Event {
+  constructor(DOMString type, optional ExtendableEventInit eventInitDict = {});
   void waitUntil(Promise<any> f);
 };
 
@@ -164,8 +165,9 @@
   // Defined for the forward compatibility across the derived events
 };
 
-[Constructor(DOMString type, FetchEventInit eventInitDict), Exposed=ServiceWorker]
+[Exposed=ServiceWorker]
 interface FetchEvent : ExtendableEvent {
+  constructor(DOMString type, FetchEventInit eventInitDict);
   [SameObject] readonly attribute Request request;
   readonly attribute Promise<any> preloadResponse;
   readonly attribute DOMString clientId;
@@ -183,8 +185,9 @@
   DOMString replacesClientId = "";
 };
 
-[Constructor(DOMString type, optional ExtendableMessageEventInit eventInitDict = {}), Exposed=ServiceWorker]
+[Exposed=ServiceWorker]
 interface ExtendableMessageEvent : ExtendableEvent {
+  constructor(DOMString type, optional ExtendableMessageEventInit eventInitDict = {});
   readonly attribute any data;
   readonly attribute USVString origin;
   readonly attribute DOMString lastEventId;
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/embellished-operator-001.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/embellished-operator-001.html
index b7d9b4945..31bdff2 100644
--- a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/embellished-operator-001.html
+++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/embellished-operator-001.html
@@ -11,6 +11,7 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/mathml/support/feature-detection.js"></script>
+<script src="/mathml/support/box-navigation.js"></script>
 <style>
   /* Default spacing of operator 'X' is 0.2777777777777778em so quite different
      from the measured/specified 0em and 1em. */
@@ -40,7 +41,7 @@
 <script>
   function spaceBeforeElement(id) {
       var element = document.getElementById(id);
-      var mnBefore = element.previousElementSibling;
+      var mnBefore = previousInFlowSibling(element);
       return element.getBoundingClientRect().left - mnBefore.getBoundingClientRect().right;
   }
 
@@ -116,7 +117,7 @@
       <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
       <mn>X</mn>
       <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
-      <mrow id="mrow-op-1" class="testedElement">
+      <mrow id="mrow-op-2" class="testedElement">
         <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
         <mo lspace="2em" rspace="0em">X</mo>
         <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/embellished-operator-002.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/embellished-operator-002.html
index b7b7f51..1bbed4e 100644
--- a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/embellished-operator-002.html
+++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/operators/embellished-operator-002.html
@@ -11,6 +11,7 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/mathml/support/feature-detection.js"></script>
+<script src="/mathml/support/box-navigation.js"></script>
 <style>
   /* Default spacing of operator 'X' is 0.2777777777777778em so quite different
      from the measured/specified 0em and 1em. */
@@ -42,7 +43,7 @@
 </style>
 <script>
   function spaceBeforeElement(element) {
-      var mnBefore = element.previousElementSibling;
+      var mnBefore = previousInFlowSibling(element);
       return element.getBoundingClientRect().left - mnBefore.getBoundingClientRect().right;
   }
 
@@ -346,7 +347,6 @@
       <mn>X</mn>
       <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
       <maction class="testedElement" actiontype="statusline">
-        <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
         <mo lspace="2em" rspace="0em">X</mo>
         <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
         <mn>STATUS MESSAGE</mn>
@@ -363,7 +363,6 @@
       <mn>X</mn>
       <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
       <semantics class="testedElement">
-        <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
         <mo lspace="2em" rspace="0em">X</mo>
         <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
         <annotation>TEXT ANNOTATION</annotation>
@@ -639,7 +638,6 @@
       <mn>X</mn>
       <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
       <maction class="testedElement" actiontype="statusline">
-        <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
         <mn>X</mn>
         <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
         <mo lspace="2em" rspace="0em">STATUS MESSAGE</mo>
@@ -656,7 +654,6 @@
       <mn>X</mn>
       <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
       <semantics class="testedElement">
-        <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
         <mrow>
           <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
           <mn>X</mn>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/spaces/space-like-004.html b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/spaces/space-like-004.html
index 091a3ea0..2ad6b0b 100644
--- a/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/spaces/space-like-004.html
+++ b/third_party/blink/web_tests/external/wpt/mathml/presentation-markup/spaces/space-like-004.html
@@ -11,6 +11,7 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/mathml/support/feature-detection.js"></script>
+<script src="/mathml/support/box-navigation.js"></script>
 <style>
   /* Default spacing of operator 'X' is 0.2777777777777778em so quite different
      from the measured/specified 0em and 1em. */
@@ -27,17 +28,26 @@
       color: blue !important;
       background: blue !important;
   }
+  .oof1 {
+      position: absolute;
+  }
+  .oof2 {
+      position: fixed;
+  }
+  .nobox {
+      display: none;
+  }
 </style>
 <script>
   function spaceBefore(id) {
       var element = document.getElementById(id);
-      var mnBeforeParent = element.parentNode.previousElementSibling;
+      var mnBeforeParent = previousInFlowSibling(element.parentNode);
       return element.getBoundingClientRect().left - mnBeforeParent.getBoundingClientRect().right;
   }
 
   function spaceAfter(id) {
       var element = document.getElementById(id);
-      var mnAfterParent = element.parentNode.nextElementSibling;
+      var mnAfterParent = nextInFlowSibling(element.parentNode);
       return mnAfterParent.getBoundingClientRect().left - element.getBoundingClientRect().right;
   }
 
@@ -56,10 +66,22 @@
 
       test(function() {
           assert_true(MathMLFeatureDetection.has_operator_spacing());
+          assert_approx_equals(spaceBefore("complex1-bis"), emToPx, epsilon);
+          assert_approx_equals(spaceAfter("complex1-bis"), emToPx, epsilon);
+      }, "complex space-like subtree, from in-flow children");
+
+      test(function() {
+          assert_true(MathMLFeatureDetection.has_operator_spacing());
           assert_approx_equals(spaceBefore("complex2"), 0, epsilon);
           assert_approx_equals(spaceAfter("complex2"), 2 * emToPx, epsilon);
       }, "complex non-space-like subtree");
 
+      test(function() {
+          assert_true(MathMLFeatureDetection.has_operator_spacing());
+          assert_approx_equals(spaceBefore("complex2-bis"), 0, epsilon);
+          assert_approx_equals(spaceAfter("complex2-bis"), 2 * emToPx, epsilon);
+      }, "complex non-space-like subtree, from in-flow children");
+
       done();
   }
 </script>
@@ -129,6 +151,121 @@
   </p>
   <p>
     <math>
+      <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+      <mn>X</mn>
+      <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+      <mrow>
+        <!-- This element is space-like because it is made of nested
+             mrow, mstyle, mpadded, mphantom, mtext, mspace
+          -->
+        <mrow class="testedElement" id="complex1-bis">
+          <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+          <mtext>X</mtext>
+          <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+          <mstyle>
+            <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            <mstyle>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mtext>X</mtext>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mtext>X</mtext>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            </mstyle>
+            <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            <mtext>X</mtext>
+            <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            <mspace width="25px"></mspace>
+            <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            <mpadded>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mtext>X</mtext>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mrow></mrow>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mtext>X</mtext>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mspace width="25px"></mspace>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mphantom>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+                <mtext>X</mtext>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+                <mspace width="25px"></mspace>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              </mphantom>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mrow>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+                <mtext>X</mtext>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+                <mtext>X</mtext>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              </mrow>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mspace width="25px"></mspace>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            </mpadded>
+            <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            <mspace width="25px"></mspace>
+            <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            <mtext>X</mtext>
+            <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            <mspace width="25px"></mspace>
+            <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            <mpadded>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mphantom>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+                <mtext>X</mtext>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+                <mspace width="25px"></mspace>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              </mphantom>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mtext>X</mtext>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mtext>X</mtext>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mspace width="25px"></mspace>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mtext>X</mtext>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mtext>X</mtext>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mspace width="25px"></mspace>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mphantom>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+                <mtext>X</mtext>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+                <mspace width="25px"></mspace>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              </mphantom>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mtext>X</mtext>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mtext>X</mtext>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mspace width="25px"></mspace>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            </mpadded>
+            <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+          </mstyle>
+          <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+          <mspace width="25px"></mspace>
+          <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+        </mrow>
+        <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+        <mo lspace="1em" rspace="0em">X</mo>
+        <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+      </mrow>
+      <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+      <mn>X</mn>
+      <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+    </math>
+  </p>
+  <p>
+    <math>
       <mn>X</mn>
       <mrow>
         <!-- This element is not space-like. It is made of nested
@@ -189,5 +326,121 @@
       <mn>X</mn>
     </math>
   </p>
+  <p>
+    <math>
+      <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+      <mn>X</mn>
+      <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+      <mrow>
+        <!-- This element is not space-like. It is made of nested
+             mrow, mstyle, mpadded, mphantom, mtext, mspace but contains
+             one non-space like descendant (an mn element).
+          -->
+        <mrow class="testedElement" id="complex2-bis">
+          <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+          <mtext>X</mtext>
+          <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+          <mstyle>
+            <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            <mstyle>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mtext>X</mtext>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mtext>X</mtext>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            </mstyle>
+            <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            <mtext>X</mtext>
+            <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            <mspace width="25px"></mspace>
+            <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            <mpadded>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mtext>X</mtext>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mrow></mrow>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mtext>X</mtext>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mspace width="25px"></mspace>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mphantom>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+                <mtext>X</mtext>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+                <mspace width="25px"></mspace>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              </mphantom>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mrow>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+                <mtext>X</mtext>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+                <mtext>X</mtext>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              </mrow>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mspace width="25px"></mspace>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            </mpadded>
+            <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            <mspace width="25px"></mspace>
+            <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            <mtext>X</mtext>
+            <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            <mspace width="25px"></mspace>
+            <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            <mpadded>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mphantom>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+                <mn>X</mn> <!-- mn is not space-like -->
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+                <mspace width="25px"></mspace>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              </mphantom>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mtext>X</mtext>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mtext>X</mtext>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mspace width="25px"></mspace>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mtext>X</mtext>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mtext>X</mtext>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mspace width="25px"></mspace>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mphantom>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+                <mtext>X</mtext>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+                <mspace width="25px"></mspace>
+                <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              </mphantom>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mtext>X</mtext>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mtext>X</mtext>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+              <mspace width="25px"></mspace>
+              <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+            </mpadded>
+            <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+          </mstyle>
+          <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+          <mspace width="25px"></mspace>
+          <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+        </mrow>
+        <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+        <mo lspace="1em" rspace="0em">X</mo>
+        <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+      </mrow>
+      <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+      <mn>X</mn>
+      <mn class="oof1">0</mn><mn class="oof2">1</mn><mn class="nobox">2</mn>
+    </math>
+  </p>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/mathml/support/box-navigation.js b/third_party/blink/web_tests/external/wpt/mathml/support/box-navigation.js
new file mode 100644
index 0000000..36264877
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/mathml/support/box-navigation.js
@@ -0,0 +1,22 @@
+function IsInFlow(element) {
+    var style = window.getComputedStyle(element);
+    return style.getPropertyValue("display") !== "none" &&
+        style.getPropertyValue("position") !== "absolute" &&
+        style.getPropertyValue("position") !== "fixed";
+}
+
+function nextInFlowSibling(element) {
+    var child = element;
+    do {
+        child = child.nextElementSibling;
+    } while (child && !IsInFlow(child));
+    return child;
+}
+
+function previousInFlowSibling(element) {
+    var child = element;
+    do {
+        child = child.previousElementSibling;
+    } while (child && !IsInFlow(child));
+    return child;
+}
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animations/canceling-an-animation-expected.txt b/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animations/canceling-an-animation-expected.txt
deleted file mode 100644
index f58af17..0000000
--- a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animations/canceling-an-animation-expected.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = The user aborted a request.
-PASS Canceling an animation should cause its start time and hold time to be unresolved
-PASS A play-pending ready promise should be rejected when the animation is canceled
-PASS A pause-pending ready promise should be rejected when the animation is canceled
-PASS When an animation is canceled, it should create a resolved Promise
-PASS The ready promise should be replaced when the animation is canceled
-PASS The finished promise should NOT be rejected if the animation is already idle
-PASS The cancel event should NOT be fired if the animation is already idle
-PASS Canceling an animation should fire cancel event on orphaned element
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animations/canceling-an-animation.html b/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animations/canceling-an-animation.html
index b0ef0b1..b2a7a33e 100644
--- a/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animations/canceling-an-animation.html
+++ b/third_party/blink/web_tests/external/wpt/web-animations/timing-model/animations/canceling-an-animation.html
@@ -66,6 +66,7 @@
   const promise = animation.ready;
   animation.cancel();
   assert_not_equals(animation.ready, promise);
+  promise_rejects(t, 'AbortError', promise, 'Cancel should abort ready promise');
 }, 'The ready promise should be replaced when the animation is canceled');
 
 promise_test(t => {
diff --git a/third_party/blink/web_tests/fast/canvas/OffscreenCanvas-Bitmaprenderer-TransferToImageBitmapResetsToBlack-expected.html b/third_party/blink/web_tests/fast/canvas/OffscreenCanvas-Bitmaprenderer-TransferToImageBitmapResetsToBlack-expected.html
index b5fb912..01c9425 100644
--- a/third_party/blink/web_tests/fast/canvas/OffscreenCanvas-Bitmaprenderer-TransferToImageBitmapResetsToBlack-expected.html
+++ b/third_party/blink/web_tests/fast/canvas/OffscreenCanvas-Bitmaprenderer-TransferToImageBitmapResetsToBlack-expected.html
@@ -29,7 +29,7 @@
 htmlCanvas2.width = 60;
 htmlCanvas2.height = 60;
 var htmlCanvasCtx2 = htmlCanvas2.getContext("2d");
-htmlCanvasCtx2.fillStyle = "black";
+htmlCanvasCtx2.fillStyle = "rgba(0, 0, 0, 0)";
 htmlCanvasCtx2.fillRect(0, 0, 60, 60);
 
 DrawCanvas(htmlCanvas2, "can2");
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-year-view-resize.html b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-year-view-resize.html
new file mode 100644
index 0000000..9fc6622
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/calendar-picker/date-picker-year-view-resize.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../../../resources/testharness.js"></script>
+<script src="../../../../resources/testharnessreport.js"></script>
+<script src="../../../forms/resources/common.js"></script>
+<script src="../../../forms/resources/picker-common.js"></script>
+<script src="../../../forms/calendar-picker/resources/calendar-picker-common.js"></script>
+</head>
+<body>
+
+<input type=date id=date value="2019-09-10">
+
+<script>
+let t = async_test('Test year list view size');
+
+function test1() {
+  var dateViewHeight = popupWindow.global.picker.height();
+  clickMonthPopupButton();
+  if (popupWindow.global.params.isFormControlsRefreshEnabled) {
+    assert_equals(dateViewHeight, popupWindow.global.picker.height());
+  } else {
+    assert_not_equals(dateViewHeight, popupWindow.global.picker.height());
+  }
+}
+
+t.step(() => {
+  openPicker(document.getElementById('date'), t.step_func_done(test1));
+});
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource-navigation-expected.txt b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource-navigation-expected.txt
new file mode 100644
index 0000000..b7191318
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource-navigation-expected.txt
@@ -0,0 +1,11 @@
+Tests presence and order of tracing events for a browser navigation.
+
+Page reloaded.
+Recording stopped
+Number of events in request: 5
+ResourceWillSendRequest from thread CrBrowserMain
+ResourceSendRequest from thread CrRendererMain
+ResourceReceiveResponse from thread CrRendererMain
+ResourceReceivedData from thread CrRendererMain
+ResourceFinish from thread CrRendererMain
+
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource-navigation-sgx-expected.txt b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource-navigation-sgx-expected.txt
new file mode 100644
index 0000000..b7191318
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource-navigation-sgx-expected.txt
@@ -0,0 +1,11 @@
+Tests presence and order of tracing events for a browser navigation.
+
+Page reloaded.
+Recording stopped
+Number of events in request: 5
+ResourceWillSendRequest from thread CrBrowserMain
+ResourceSendRequest from thread CrRendererMain
+ResourceReceiveResponse from thread CrRendererMain
+ResourceReceivedData from thread CrRendererMain
+ResourceFinish from thread CrRendererMain
+
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource-navigation-sgx.js b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource-navigation-sgx.js
new file mode 100644
index 0000000..8ad093f
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource-navigation-sgx.js
@@ -0,0 +1,36 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(async function() {
+  TestRunner.addResult(`Tests presence and order of tracing events for a browser navigation.\n`);
+  await TestRunner.loadModule(`performance_test_runner`);
+  await TestRunner.showPanel(`timeline`);
+  await TestRunner.NetworkAgent.setCacheDisabled(true);
+  await TestRunner.navigatePromise('/loading/sxg/resources/sxg-location.sxg');
+
+  TestRunner.resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.Load, TestRunner.pageLoaded);
+
+  const panel = UI.panels.timeline;
+  PerformanceTestRunner.runWhenTimelineIsReady(recordingStopped);
+  panel._millisecondsToRecordAfterLoadEvent = 1;
+  panel._recordReload();
+
+  async function recordingStopped() {
+    TestRunner.addResult('Recording stopped');
+    const sendRequests = PerformanceTestRunner.timelineModel().networkRequests();
+    for (const request of sendRequests) {
+      TestRunner.addResult(`Number of events in request: ${request.children && request.children.length}`);
+      let requestId = null;
+      for (const event of request.children.sort((a,b) => a.startTime - b.startTime)) {
+        if (requestId === null) {
+          requestId = event.args.data.requestId;
+        } else if (requestId !== event.args.data.requestId) {
+          TestRunner.addResult(`Events did not have the same request id.`)
+        }
+        TestRunner.addResult(`${event.name} from thread ${event.thread._name}`);
+      }
+    }
+    TestRunner.completeTest();
+}
+})();
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource-navigation.js b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource-navigation.js
new file mode 100644
index 0000000..0f1d317b
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-network/timeline-network-resource-navigation.js
@@ -0,0 +1,35 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(async function() {
+  TestRunner.addResult(`Tests presence and order of tracing events for a browser navigation.\n`);
+  await TestRunner.loadModule(`performance_test_runner`);
+  await TestRunner.showPanel(`timeline`);
+  await TestRunner.NetworkAgent.setCacheDisabled(true);
+
+  TestRunner.resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.Load, TestRunner.pageLoaded);
+
+  const panel = UI.panels.timeline;
+  PerformanceTestRunner.runWhenTimelineIsReady(recordingStopped);
+  panel._millisecondsToRecordAfterLoadEvent = 1;
+  panel._recordReload();
+
+  async function recordingStopped() {
+    TestRunner.addResult('Recording stopped');
+    const sendRequests = PerformanceTestRunner.timelineModel().networkRequests();
+    for (const request of sendRequests) {
+      TestRunner.addResult(`Number of events in request: ${request.children && request.children.length}`);
+      let requestId = null;
+      for (const event of request.children.sort((a,b) => a.startTime - b.startTime)) {
+        if (requestId === null) {
+          requestId = event.args.data.requestId;
+        } else if (requestId !== event.args.data.requestId) {
+          TestRunner.addResult(`Events did not have the same request id.`)
+        }
+        TestRunner.addResult(`${event.name} from thread ${event.thread._name}`);
+      }
+    }
+    TestRunner.completeTest();
+}
+})();
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-domain-mismatch-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-domain-mismatch-expected.txt
new file mode 100644
index 0000000..2c08fdf
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-domain-mismatch-expected.txt
@@ -0,0 +1,19 @@
+Verifies that cookies blocked for a request of a subdomain of the cookie's domain are included in the blocked cookies of Network.RequestWillBeSentExtraInfo events.
+
+requestWillBeSentExtraInfo blocked cookies: [
+  {
+    "blockedReason": "DomainMismatch",
+    "cookie": {
+      "name": "name",
+      "value": "value",
+      "domain": "cookie.test",
+      "path": "/inspector-protocol/network/resources",
+      "expires": -1,
+      "size": 9,
+      "httpOnly": false,
+      "secure": false,
+      "session": true
+    }
+  }
+]
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-domain-mismatch.js b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-domain-mismatch.js
new file mode 100644
index 0000000..906117a
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-domain-mismatch.js
@@ -0,0 +1,20 @@
+(async function(testRunner) {
+  const {page, session, dp} = await testRunner.startBlank(
+      `Verifies that cookies blocked for a request of a subdomain of the cookie's domain are included in the blocked cookies of Network.RequestWillBeSentExtraInfo events.\n`);
+  await dp.Network.enable();
+
+  const setCookieUrl = 'https://cookie.test:8443/inspector-protocol/network/resources/set-cookie.php?cookie='
+      + encodeURIComponent('name=value');
+  const subdomainUrl = 'https://subdomain.cookie.test:8443/inspector-protocol/network/resources/hello-world.html';
+
+  const helper = (await testRunner.loadScript('resources/extra-info-helper.js'))(dp, session);
+
+  // set a cookie in a domain
+  await helper.navigateWithExtraInfo(setCookieUrl);
+
+  // navigate to a subdomain to see that the cookie was blocked
+  const {requestExtraInfo, responseExtraInfo} = await helper.navigateWithExtraInfo(subdomainUrl);
+  testRunner.log(`requestWillBeSentExtraInfo blocked cookies: ${JSON.stringify(requestExtraInfo.params.blockedCookies, null, 2)}`);
+
+  testRunner.completeTest();
+})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-not-on-path-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-not-on-path-expected.txt
new file mode 100644
index 0000000..30ee474
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-not-on-path-expected.txt
@@ -0,0 +1,19 @@
+Verifies that cookies not within the current path of the request to a domain send Network.*ExtraInfo events with corresponding blocked cookies.
+
+requestWillBeSentExtraInfo blocked cookies: [
+  {
+    "blockedReason": "NotOnPath",
+    "cookie": {
+      "name": "name",
+      "value": "value",
+      "domain": "cookie.test",
+      "path": "/inspector-protocol/network/resources/set-cookie.php",
+      "expires": -1,
+      "size": 9,
+      "httpOnly": false,
+      "secure": false,
+      "session": true
+    }
+  }
+]
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-not-on-path.js b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-not-on-path.js
new file mode 100644
index 0000000..3972c4d6
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-not-on-path.js
@@ -0,0 +1,20 @@
+(async function(testRunner) {
+  const {page, session, dp} = await testRunner.startBlank(
+      `Verifies that cookies not within the current path of the request to a domain send Network.*ExtraInfo events with corresponding blocked cookies.\n`);
+  await dp.Network.enable();
+
+  const setCookieUrl = 'https://cookie.test:8443/inspector-protocol/network/resources/set-cookie.php?cookie='
+      + encodeURIComponent('name=value; Path=/inspector-protocol/network/resources/set-cookie.php');
+  const differentPathUrl = 'https://cookie.test:8443/inspector-protocol/network/resources/hello-world.php';
+
+  const helper = (await testRunner.loadScript('resources/extra-info-helper.js'))(dp, session);
+
+  // set a cookie with a path
+  await helper.navigateWithExtraInfo(setCookieUrl);
+
+  // navigate to a different path to see that the cookie was blocked
+  const {requestExtraInfo, responseExtraInfo} = await helper.navigateWithExtraInfo(differentPathUrl);
+  testRunner.log(`requestWillBeSentExtraInfo blocked cookies: ${JSON.stringify(requestExtraInfo.params.blockedCookies, null, 2)}`);
+
+  testRunner.completeTest();
+})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-same-site-lax-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-same-site-lax-expected.txt
new file mode 100644
index 0000000..832d49a
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-same-site-lax-expected.txt
@@ -0,0 +1,24 @@
+Verifies that making cross origin requests with SameSite=Lax cookies sends us Network.RequestWillBeSentExtraInfo events with corresponding blocked cookies.
+
+Browser initiated navigation blocked cookies: []
+
+Javascript initiated navigation blocked cookies: []
+
+Javascript initiated subresource blocked cookies: [
+  {
+    "blockedReason": "SameSiteLax",
+    "cookie": {
+      "name": "name",
+      "value": "value",
+      "domain": "cookie.test",
+      "path": "/inspector-protocol/network/resources",
+      "expires": -1,
+      "size": 9,
+      "httpOnly": false,
+      "secure": false,
+      "session": true,
+      "sameSite": "Lax"
+    }
+  }
+]
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-same-site-lax.js b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-same-site-lax.js
new file mode 100644
index 0000000..e05d5a4a
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-same-site-lax.js
@@ -0,0 +1,32 @@
+(async function(testRunner) {
+  const {page, session, dp} = await testRunner.startBlank(
+      `Verifies that making cross origin requests with SameSite=Lax cookies sends us Network.RequestWillBeSentExtraInfo events with corresponding blocked cookies.\n`);
+  await dp.Network.enable();
+
+  const setCookieUrl = 'https://cookie.test:8443/inspector-protocol/network/resources/set-cookie.php?cookie='
+      + encodeURIComponent('name=value; SameSite=Lax');
+  const firstPartyUrl = 'https://cookie.test:8443/inspector-protocol/network/resources/hello-world.html';
+  const thirdPartyUrl = 'https://thirdparty.test:8443/inspector-protocol/network/resources/hello-world.html';
+
+  const helper = (await testRunner.loadScript('resources/extra-info-helper.js'))(dp, session);
+
+  // set the SameSite=Lax cookie
+  await helper.navigateWithExtraInfo(setCookieUrl);
+
+  // navigate to a different domain and back from the browser and see that the cookie is not blocked
+  await helper.navigateWithExtraInfo(thirdPartyUrl);
+  var {requestExtraInfo} = await helper.navigateWithExtraInfo(firstPartyUrl);
+  testRunner.log(`Browser initiated navigation blocked cookies: ${JSON.stringify(requestExtraInfo.params.blockedCookies, null, 2)}\n`);
+
+  // navigate to a different domain and back from javascript and see that the cookie is not blocked
+  await helper.navigateWithExtraInfo(thirdPartyUrl);
+  var {requestExtraInfo} = await helper.jsNavigateWithExtraInfo(firstPartyUrl);
+  testRunner.log(`Javascript initiated navigation blocked cookies: ${JSON.stringify(requestExtraInfo.params.blockedCookies, null, 2)}\n`);
+
+  // navigate away and make a subresource request from javascript, see that the cookie is blocked
+  await helper.navigateWithExtraInfo(thirdPartyUrl);
+  var {requestExtraInfo} = await helper.fetchWithExtraInfo(firstPartyUrl);
+  testRunner.log(`Javascript initiated subresource blocked cookies: ${JSON.stringify(requestExtraInfo.params.blockedCookies, null, 2)}`);
+
+  testRunner.completeTest();
+})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-same-site-strict-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-same-site-strict-expected.txt
new file mode 100644
index 0000000..227f359
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-same-site-strict-expected.txt
@@ -0,0 +1,40 @@
+Verifies that making cross origin requests with SameSite=Strict cookies sends us Network.RequestWillBeSentExtraInfo events with corresponding blocked cookies.
+
+Browser initiated navigation blocked cookies: []
+
+Javascript initiated navigation blocked cookies: [
+  {
+    "blockedReason": "SameSiteStrict",
+    "cookie": {
+      "name": "name",
+      "value": "value",
+      "domain": "cookie.test",
+      "path": "/inspector-protocol/network/resources",
+      "expires": -1,
+      "size": 9,
+      "httpOnly": false,
+      "secure": false,
+      "session": true,
+      "sameSite": "Strict"
+    }
+  }
+]
+
+Javascript initiated subresource blocked cookies: [
+  {
+    "blockedReason": "SameSiteStrict",
+    "cookie": {
+      "name": "name",
+      "value": "value",
+      "domain": "cookie.test",
+      "path": "/inspector-protocol/network/resources",
+      "expires": -1,
+      "size": 9,
+      "httpOnly": false,
+      "secure": false,
+      "session": true,
+      "sameSite": "Strict"
+    }
+  }
+]
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-same-site-strict.js b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-same-site-strict.js
new file mode 100644
index 0000000..870b7f6
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-same-site-strict.js
@@ -0,0 +1,32 @@
+(async function(testRunner) {
+  const {page, session, dp} = await testRunner.startBlank(
+      `Verifies that making cross origin requests with SameSite=Strict cookies sends us Network.RequestWillBeSentExtraInfo events with corresponding blocked cookies.\n`);
+  await dp.Network.enable();
+
+  const setCookieUrl = 'https://cookie.test:8443/inspector-protocol/network/resources/set-cookie.php?cookie='
+      + encodeURIComponent('name=value; SameSite=Strict');
+  const firstPartyUrl = 'https://cookie.test:8443/inspector-protocol/network/resources/hello-world.html';
+  const thirdPartyUrl = 'https://thirdparty.test:8443/inspector-protocol/network/resources/hello-world.html';
+
+  const helper = (await testRunner.loadScript('resources/extra-info-helper.js'))(dp, session);
+
+  // set the SameSite=Strict cookie
+  await helper.navigateWithExtraInfo(setCookieUrl);
+
+  // navigate to a different domain and back from the browser and see that the cookie is not blocked
+  await helper.navigateWithExtraInfo(thirdPartyUrl);
+  var {requestExtraInfo, responseExtraInfo} = await helper.navigateWithExtraInfo(firstPartyUrl);
+  testRunner.log(`Browser initiated navigation blocked cookies: ${JSON.stringify(requestExtraInfo.params.blockedCookies, null, 2)}\n`);
+
+  // navigate to a different domain and back from javascript and see that the cookie is blocked
+  await helper.navigateWithExtraInfo(thirdPartyUrl);
+  var {requestExtraInfo, responseExtraInfo} = await helper.jsNavigateWithExtraInfo(firstPartyUrl);
+  testRunner.log(`Javascript initiated navigation blocked cookies: ${JSON.stringify(requestExtraInfo.params.blockedCookies, null, 2)}\n`);
+
+  // navigate away and make a subresource request from javascript, see that the cookie is blocked
+  await helper.navigateWithExtraInfo(thirdPartyUrl);
+  await helper.fetchWithExtraInfo(firstPartyUrl);
+  testRunner.log(`Javascript initiated subresource blocked cookies: ${JSON.stringify(requestExtraInfo.params.blockedCookies, null, 2)}`);
+
+  testRunner.completeTest();
+})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-secure-only-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-secure-only-expected.txt
new file mode 100644
index 0000000..ddfa0310
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-secure-only-expected.txt
@@ -0,0 +1,38 @@
+Verifies that storing and sending Secure cookies over http sends Network.*ExtraInfo events with corresponding blocked cookies.
+
+ResponseReceivedExtraInfo blocked cookies: [
+  {
+    "blockedReason": "SecureOnly",
+    "cookieLine": "name=value; Secure",
+    "cookie": {
+      "name": "name",
+      "value": "value",
+      "domain": "cookie.test",
+      "path": "/inspector-protocol/network/resources",
+      "expires": -1,
+      "size": 9,
+      "httpOnly": false,
+      "secure": true,
+      "session": true
+    }
+  }
+]
+
+RequestWillBeSentExtraInfo blocked cookies: [
+  {
+    "blockedReason": "SecureOnly",
+    "cookie": {
+      "name": "name",
+      "value": "value",
+      "domain": "cookie.test",
+      "path": "/inspector-protocol/network/resources",
+      "expires": -1,
+      "size": 9,
+      "httpOnly": false,
+      "secure": true,
+      "session": true
+    }
+  }
+]
+
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-secure-only.js b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-secure-only.js
new file mode 100644
index 0000000..c4b90224
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-cookie-secure-only.js
@@ -0,0 +1,25 @@
+(async function(testRunner) {
+  const {page, session, dp} = await testRunner.startBlank(
+      `Verifies that storing and sending Secure cookies over http sends Network.*ExtraInfo events with corresponding blocked cookies.\n`);
+  await dp.Network.enable();
+
+  const setCookieInsecureUrl = 'http://cookie.test:8000/inspector-protocol/network/resources/set-cookie.php?cookie='
+      + encodeURIComponent('name=value; Secure');
+  const setCookieSecureUrl = 'https://cookie.test:8443/inspector-protocol/network/resources/set-cookie.php?cookie='
+      + encodeURIComponent('name=value; Secure');
+
+  const helper = (await testRunner.loadScript('resources/extra-info-helper.js'))(dp, session);
+
+  // navigate to the set-cookie over http and see that the cookie gets blocked
+  var {requestExtraInfo, responseExtraInfo} = await helper.navigateWithExtraInfo(setCookieInsecureUrl);
+  testRunner.log(`ResponseReceivedExtraInfo blocked cookies: ${JSON.stringify(responseExtraInfo.params.blockedCookies, null, 2)}\n`);
+
+  // navigate to the set-cookie over https to actually set the cookie
+  await helper.navigateWithExtraInfo(setCookieSecureUrl);
+
+  // navigate there again over http to see that the cookie was not sent
+  var {requestExtraInfo, responseExtraInfo} = await helper.navigateWithExtraInfo(setCookieInsecureUrl);
+  testRunner.log(`RequestWillBeSentExtraInfo blocked cookies: ${JSON.stringify(requestExtraInfo.params.blockedCookies, null, 2)}\n`);
+
+  testRunner.completeTest();
+})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-invalid-domain-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-invalid-domain-expected.txt
new file mode 100644
index 0000000..a3c4216
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-invalid-domain-expected.txt
@@ -0,0 +1,9 @@
+Verifies that setting a cookie with a domain attribute which does not match the current domain sends a Network.ResponseReceivedExtraInfo event with the corresponding blocked cookie.
+
+Bad domain attribute blocked set-cookies: [
+  {
+    "blockedReason": "InvalidDomain",
+    "cookieLine": "name=value; Domain=cookie.test"
+  }
+]
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-invalid-domain.js b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-invalid-domain.js
new file mode 100644
index 0000000..88cdb93
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-invalid-domain.js
@@ -0,0 +1,16 @@
+(async function(testRunner) {
+  const {page, session, dp} = await testRunner.startBlank(
+      `Verifies that setting a cookie with a domain attribute which does not match the current domain sends a Network.ResponseReceivedExtraInfo event with the corresponding blocked cookie.\n`);
+  await dp.Network.enable();
+
+  const setCookieUrlBadDomain = 'https://thirdparty.test:8443/inspector-protocol/network/resources/set-cookie.php?cookie='
+      + encodeURIComponent('name=value; Domain=cookie.test');
+
+  const helper = (await testRunner.loadScript('resources/extra-info-helper.js'))(dp, session);
+
+  // try to set the cookie from a different domain than the one it specifies, see that it is blocked
+  const {requestExtraInfo, responseExtraInfo} = await helper.navigateWithExtraInfo(setCookieUrlBadDomain);
+  testRunner.log(`Bad domain attribute blocked set-cookies: ${JSON.stringify(responseExtraInfo.params.blockedCookies, null, 2)}`);
+
+  testRunner.completeTest();
+})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-invalid-prefix-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-invalid-prefix-expected.txt
new file mode 100644
index 0000000..453fd00
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-invalid-prefix-expected.txt
@@ -0,0 +1,15 @@
+Verifies that setting a cookie with an invalid __Secure- or __Host- prefix sends us Network.ResponseReceivedExtraInfo events with corresponding blocked cookies.
+
+Bad __Secure- prefix blocked set-cookies: [
+  {
+    "blockedReason": "InvalidPrefix",
+    "cookieLine": "__Secure-name=value"
+  }
+]
+Bad __Host- prefix blocked set-cookies: [
+  {
+    "blockedReason": "InvalidPrefix",
+    "cookieLine": "__Host-name=value; Secure"
+  }
+]
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-invalid-prefix.js b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-invalid-prefix.js
new file mode 100644
index 0000000..aa94aa26
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-invalid-prefix.js
@@ -0,0 +1,20 @@
+(async function(testRunner) {
+  const {page, session, dp} = await testRunner.startBlank(
+      `Verifies that setting a cookie with an invalid __Secure- or __Host- prefix sends us Network.ResponseReceivedExtraInfo events with corresponding blocked cookies.\n`);
+  await dp.Network.enable();
+
+  const setCookieUrlBadSecure = 'https://cookie.test:8443/inspector-protocol/network/resources/set-cookie.php?cookie='
+      + encodeURIComponent('__Secure-name=value');
+  const setCookieUrlBadHost = 'https://cookie.test:8443/inspector-protocol/network/resources/set-cookie.php?cookie='
+      + encodeURIComponent('__Host-name=value; Secure');
+
+  const helper = (await testRunner.loadScript('resources/extra-info-helper.js'))(dp, session);
+
+  var {requestExtraInfo, responseExtraInfo} = await helper.navigateWithExtraInfo(setCookieUrlBadSecure);
+  testRunner.log(`Bad __Secure- prefix blocked set-cookies: ${JSON.stringify(responseExtraInfo.params.blockedCookies, null, 2)}`);
+
+  var {requestExtraInfo, responseExtraInfo} = await helper.navigateWithExtraInfo(setCookieUrlBadHost);
+  testRunner.log(`Bad __Host- prefix blocked set-cookies: ${JSON.stringify(responseExtraInfo.params.blockedCookies, null, 2)}`);
+
+  testRunner.completeTest();
+})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-overwrite-secure-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-overwrite-secure-expected.txt
new file mode 100644
index 0000000..09ae19a
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-overwrite-secure-expected.txt
@@ -0,0 +1,19 @@
+Verifies that when we get a non-secure set-cookie header that would overwrite a secure one, we get a Network.ResponseReceivedExtraInfo event with the blocked cookie.
+set-cookie that would overwrite secure cookie blocked set-cookies: [
+  {
+    "blockedReason": "OverwriteSecure",
+    "cookieLine": "name=value",
+    "cookie": {
+      "name": "name",
+      "value": "value",
+      "domain": "cookie.test",
+      "path": "/inspector-protocol/network/resources",
+      "expires": -1,
+      "size": 9,
+      "httpOnly": false,
+      "secure": false,
+      "session": true
+    }
+  }
+]
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-overwrite-secure.js b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-overwrite-secure.js
new file mode 100644
index 0000000..a95f754
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-overwrite-secure.js
@@ -0,0 +1,20 @@
+(async function(testRunner) {
+  const {page, session, dp} = await testRunner.startBlank(
+      `Verifies that when we get a non-secure set-cookie header that would overwrite a secure one, we get a Network.ResponseReceivedExtraInfo event with the blocked cookie.`);
+  await dp.Network.enable();
+
+  const setCookieSecure = 'https://cookie.test:8443/inspector-protocol/network/resources/set-cookie-secure.php';
+  const setCookieInsecure = 'http://cookie.test:8000/inspector-protocol/network/resources/set-cookie.php?cookie='
+      + encodeURIComponent('name=value');
+
+  const helper = (await testRunner.loadScript('resources/extra-info-helper.js'))(dp, session);
+
+  // set a secure cookie
+  await helper.navigateWithExtraInfo(setCookieSecure);
+
+  // try to overwrite it with an insecure cookie
+  const {requestExtraInfo, responseExtraInfo} = await helper.navigateWithExtraInfo(setCookieInsecure);
+  testRunner.log(`set-cookie that would overwrite secure cookie blocked set-cookies: ${JSON.stringify(responseExtraInfo.params.blockedCookies, null, 2)}`);
+
+  testRunner.completeTest();
+})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-same-site-lax-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-same-site-lax-expected.txt
new file mode 100644
index 0000000..3a0c84bd
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-same-site-lax-expected.txt
@@ -0,0 +1,25 @@
+Verifies that making cross origin requests which set SameSite=Lax cookies send us Network.ResponseReceivedExtraInfo events with corresponding blocked set-cookies.
+
+Javascript initiated subresource blocked set-cookies: [
+  {
+    "blockedReason": "SameSiteLax",
+    "cookieLine": "name=value; SameSite=Lax",
+    "cookie": {
+      "name": "name",
+      "value": "value",
+      "domain": "cookie.test",
+      "path": "/inspector-protocol/network/resources",
+      "expires": -1,
+      "size": 9,
+      "httpOnly": false,
+      "secure": false,
+      "session": true,
+      "sameSite": "Lax"
+    }
+  }
+]
+
+Javascript initiated navigation blocked set-cookies: []
+
+Browser initiated navigation blocked set-cookies: []
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-same-site-lax.js b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-same-site-lax.js
new file mode 100644
index 0000000..55436983
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-same-site-lax.js
@@ -0,0 +1,28 @@
+(async function(testRunner) {
+  const {page, session, dp} = await testRunner.startBlank(
+      `Verifies that making cross origin requests which set SameSite=Lax cookies send us Network.ResponseReceivedExtraInfo events with corresponding blocked set-cookies.\n`);
+  await dp.Network.enable();
+
+  const thirdPartyUrl = 'https://thirdparty.test:8443/inspector-protocol/network/resources/hello-world.html';
+  const setCookieUrl = 'https://cookie.test:8443/inspector-protocol/network/resources/set-cookie.php?cookie='
+      + encodeURIComponent('name=value; SameSite=Lax');
+
+  const helper = (await testRunner.loadScript('resources/extra-info-helper.js'))(dp, session);
+
+  // make a cross origin request to set the cookie, see that it gets blocked
+  await helper.navigateWithExtraInfo(thirdPartyUrl);
+  var {responseExtraInfo} = await helper.fetchWithExtraInfo(setCookieUrl);
+  testRunner.log(`Javascript initiated subresource blocked set-cookies: ${JSON.stringify(responseExtraInfo.params.blockedCookies, null, 2)}\n`);
+
+  // make a cross origin navigation via javascript to set the cookie, see that it is not blocked
+  await helper.navigateWithExtraInfo(thirdPartyUrl);
+  var {responseExtraInfo} = await helper.jsNavigateWithExtraInfo(setCookieUrl);
+  testRunner.log(`Javascript initiated navigation blocked set-cookies: ${JSON.stringify(responseExtraInfo.params.blockedCookies, null, 2)}\n`);
+
+  // make a cross origin navigation via browser to set the cookie, see that it is not blocked
+  await helper.navigateWithExtraInfo(thirdPartyUrl);
+  var {responseExtraInfo} = await helper.navigateWithExtraInfo(setCookieUrl);
+  testRunner.log(`Browser initiated navigation blocked set-cookies: ${JSON.stringify(responseExtraInfo.params.blockedCookies, null, 2)}`);
+
+  testRunner.completeTest();
+})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-same-site-strict-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-same-site-strict-expected.txt
new file mode 100644
index 0000000..a91d5d9
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-same-site-strict-expected.txt
@@ -0,0 +1,25 @@
+Verifies that making cross origin requests which set SameSite=Strict cookies send us Network.ResponseReceivedExtraInfo events with corresponding blocked set-cookies.
+
+Javascript initiated subresource blocked set-cookies: [
+  {
+    "blockedReason": "SameSiteStrict",
+    "cookieLine": "name=value; SameSite=Strict",
+    "cookie": {
+      "name": "name",
+      "value": "value",
+      "domain": "cookie.test",
+      "path": "/inspector-protocol/network/resources",
+      "expires": -1,
+      "size": 9,
+      "httpOnly": false,
+      "secure": false,
+      "session": true,
+      "sameSite": "Strict"
+    }
+  }
+]
+
+Javascript initiated navigation blocked set-cookies: []
+
+Browser initiated navigation blocked set-cookies: []
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-same-site-strict.js b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-same-site-strict.js
new file mode 100644
index 0000000..1d181cd
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-same-site-strict.js
@@ -0,0 +1,28 @@
+(async function(testRunner) {
+  const {page, session, dp} = await testRunner.startBlank(
+      `Verifies that making cross origin requests which set SameSite=Strict cookies send us Network.ResponseReceivedExtraInfo events with corresponding blocked set-cookies.\n`);
+  await dp.Network.enable();
+
+  const thirdPartyUrl = 'https://thirdparty.test:8443/inspector-protocol/network/resources/hello-world.html';
+  const setCookieUrl = 'https://cookie.test:8443/inspector-protocol/network/resources/set-cookie.php?cookie='
+      + encodeURIComponent('name=value; SameSite=Strict');
+
+  const helper = (await testRunner.loadScript('resources/extra-info-helper.js'))(dp, session);
+
+  // make a cross origin request to set the cookie, see that it gets blocked
+  await helper.navigateWithExtraInfo(thirdPartyUrl);
+  var {responseExtraInfo} = await helper.fetchWithExtraInfo(setCookieUrl);
+  testRunner.log(`Javascript initiated subresource blocked set-cookies: ${JSON.stringify(responseExtraInfo.params.blockedCookies, null, 2)}\n`);
+
+  // make a cross origin navigation via javascript to set the cookie, see that it gets blocked
+  await helper.navigateWithExtraInfo(thirdPartyUrl);
+  var {responseExtraInfo} = await helper.jsNavigateWithExtraInfo(setCookieUrl);
+  testRunner.log(`Javascript initiated navigation blocked set-cookies: ${JSON.stringify(responseExtraInfo.params.blockedCookies, null, 2)}\n`);
+
+  // make a cross origin navigation via browser to set the cookie, see that it is not blocked
+  await helper.navigateWithExtraInfo(thirdPartyUrl);
+  var {responseExtraInfo} = await helper.navigateWithExtraInfo(setCookieUrl);
+  testRunner.log(`Browser initiated navigation blocked set-cookies: ${JSON.stringify(responseExtraInfo.params.blockedCookies, null, 2)}`);
+
+  testRunner.completeTest();
+})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-syntax-error-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-syntax-error-expected.txt
new file mode 100644
index 0000000..ce2e6a0
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-syntax-error-expected.txt
@@ -0,0 +1,9 @@
+Verifies that receiving a set-cookie header with invalid syntax sends a Network.ResponseReceivedExtraInfo event with the blocked cookie.
+
+Invalid syntax blocked set-cookies: [
+  {
+    "blockedReason": "SyntaxError",
+    "cookieLine": "name=val\tue"
+  }
+]
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-syntax-error.js b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-syntax-error.js
new file mode 100644
index 0000000..8d59e7d
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/blocked-setcookie-syntax-error.js
@@ -0,0 +1,14 @@
+(async function(testRunner) {
+  const {page, session, dp} = await testRunner.startBlank(
+      `Verifies that receiving a set-cookie header with invalid syntax sends a Network.ResponseReceivedExtraInfo event with the blocked cookie.\n`);
+  await dp.Network.enable();
+
+  const setCookieInvalidSyntax = 'https://cookie.test:8443/inspector-protocol/network/resources/set-cookie-invalid-syntax.php';
+
+  const helper = (await testRunner.loadScript('resources/extra-info-helper.js'))(dp, session);
+
+  const {requestExtraInfo, responseExtraInfo} = await helper.navigateWithExtraInfo(setCookieInvalidSyntax);
+  testRunner.log(`Invalid syntax blocked set-cookies: ${JSON.stringify(responseExtraInfo.params.blockedCookies, null, 2)}`);
+
+  testRunner.completeTest();
+})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/extra-info-raw-headers-navigation.js b/third_party/blink/web_tests/http/tests/inspector-protocol/network/extra-info-raw-headers-navigation.js
index 78134a8..06654dde 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/network/extra-info-raw-headers-navigation.js
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/extra-info-raw-headers-navigation.js
@@ -4,7 +4,8 @@
 
   await dp.Network.enable();
 
-  const setCookieUrl = 'https://cookie.test:8443/inspector-protocol/network/resources/set-cookie-samesitenone.php';
+  const setCookieUrl = 'https://cookie.test:8443/inspector-protocol/network/resources/set-cookie.php?cookie='
+      + encodeURIComponent('name=value; Secure; SameSite=None; HttpOnly');
   const helloWorldUrl = 'https://cookie.test:8443/inspector-protocol/network/resources/hello-world.html';
   const otherDomainUrl = 'https://thirdparty.test:8443/inspector-protocol/network/resources/hello-world.html';
 
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/extra-info-raw-headers-subresource.js b/third_party/blink/web_tests/http/tests/inspector-protocol/network/extra-info-raw-headers-subresource.js
index 5913bc6..a7491cb 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/network/extra-info-raw-headers-subresource.js
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/extra-info-raw-headers-subresource.js
@@ -4,7 +4,8 @@
 
   await dp.Network.enable();
 
-  const setCookieUrl = 'https://cookie.test:8443/inspector-protocol/network/resources/set-cookie-samesitenone.php';
+  const setCookieUrl = 'https://cookie.test:8443/inspector-protocol/network/resources/set-cookie.php?cookie='
+      + encodeURIComponent('name=value; Secure; SameSite=None; HttpOnly');
   const firstPartyUrl = 'https://cookie.test:8443/inspector-protocol/network/resources/hello-world.html';
   const thirdPartyUrl = 'https://thirdparty.test:8443/inspector-protocol/network/resources/hello-world.html';
 
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/extra-info-helper.js b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/extra-info-helper.js
index 1e5b3ec..8c667f0 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/extra-info-helper.js
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/extra-info-helper.js
@@ -14,6 +14,15 @@
       return {requestExtraInfo, responseExtraInfo};
     }
 
+    async jsNavigateWithExtraInfo(url) {
+      const requestExtraInfoPromise = this._dp.Network.onceRequestWillBeSentExtraInfo();
+      const responseExtraInfoPromise = this._dp.Network.onceResponseReceivedExtraInfo();
+      await this._session.evaluate(`window.location.href = '${url}'`);
+      const requestExtraInfo = await requestExtraInfoPromise;
+      const responseExtraInfo = await responseExtraInfoPromise;
+      return {requestExtraInfo, responseExtraInfo};
+    }
+
     async fetchWithExtraInfo(url) {
       const requestExtraInfoPromise = this._dp.Network.onceRequestWillBeSentExtraInfo();
       const responseExtraInfoPromise = this._dp.Network.onceResponseReceivedExtraInfo();
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/set-cookie-invalid-syntax.php b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/set-cookie-invalid-syntax.php
new file mode 100644
index 0000000..b393e96
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/set-cookie-invalid-syntax.php
@@ -0,0 +1,3 @@
+<?php
+header("set-cookie: name=val\x09ue");
+?>
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/set-cookie-samesitenone.php b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/set-cookie-samesitenone.php
deleted file mode 100644
index 6500c19..0000000
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/set-cookie-samesitenone.php
+++ /dev/null
@@ -1,3 +0,0 @@
-<?php
-header('set-cookie: name=value; Secure; SameSite=None; HttpOnly')
-?>
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/set-cookie-secure.php b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/set-cookie-secure.php
new file mode 100644
index 0000000..e31db8e
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/set-cookie-secure.php
@@ -0,0 +1,3 @@
+<?php
+header("set-cookie: name=value; Secure");
+?>
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/set-cookie.php b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/set-cookie.php
new file mode 100644
index 0000000..e9c4569
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/set-cookie.php
@@ -0,0 +1,4 @@
+<?php
+header("set-cookie: " . $_GET["cookie"]);
+echo "set-cookie: " . $_GET["cookie"];
+?>
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
index 4b54f753..37f240f5 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
index a3245a6f..64ad5a4 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
index a493585..f8c2545 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
index eee865ce..bf664e3a 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
index eee865ce..bf664e3a 100644
--- a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
index eee865ce..bf664e3a 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
new file mode 100644
index 0000000..4b945793
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
index ae79609..d3595685 100644
--- a/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
+++ b/third_party/blink/web_tests/platform/win7/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
index cefd647..4b945793 100644
--- a/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
+++ b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/calendar-picker/date-picker-month-appearance-expected.png
Binary files differ
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium
index d38a393..7f00920 100644
--- a/third_party/crashpad/README.chromium
+++ b/third_party/crashpad/README.chromium
@@ -2,7 +2,7 @@
 Short Name: crashpad
 URL: https://crashpad.chromium.org/
 Version: unknown
-Revision: e1e55e224627a5e74d524f6395a3d1617368a564
+Revision: 06fdbdecdc5d94989543bcec197752fdea2fbd9d
 License: Apache 2.0
 License File: crashpad/LICENSE
 Security Critical: yes
diff --git a/third_party/crashpad/crashpad/DEPS b/third_party/crashpad/crashpad/DEPS
index 46c3424..ec17347 100644
--- a/third_party/crashpad/crashpad/DEPS
+++ b/third_party/crashpad/crashpad/DEPS
@@ -33,7 +33,7 @@
       '8048ece6c16c91acfe0d36d1d3cc0890ab6e945c',
   'crashpad/third_party/mini_chromium/mini_chromium':
       Var('chromium_git') + '/chromium/mini_chromium@' +
-      '5889767521eed1483b5858b12c54893f21d72fd0',
+      '660b43a779892e7fdb74d490b54cf37ffe8a978d',
   'crashpad/third_party/libfuzzer/src':
       Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git@' +
       'fda403cf93ecb8792cb1d061564d89a6553ca020',
diff --git a/third_party/crashpad/crashpad/client/crashpad_client.h b/third_party/crashpad/crashpad/client/crashpad_client.h
index 36c9d1f8..dfe13538 100644
--- a/third_party/crashpad/crashpad/client/crashpad_client.h
+++ b/third_party/crashpad/crashpad/client/crashpad_client.h
@@ -16,6 +16,7 @@
 #define CRASHPAD_CLIENT_CRASHPAD_CLIENT_H_
 
 #include <map>
+#include <set>
 #include <string>
 #include <vector>
 
@@ -138,7 +139,7 @@
   //!     this process' ptracer. 0 indicates it is not necessary to set the
   //!     handler as this process' ptracer. -1 indicates that the handler's
   //!     process ID should be determined by communicating over the socket.
-  static bool SetHandlerSocket(ScopedFileHandle sock, pid_t pid);
+  bool SetHandlerSocket(ScopedFileHandle sock, pid_t pid);
 #endif  // OS_ANDROID || OS_LINUX || DOXYGEN
 
 #if defined(OS_ANDROID) || DOXYGEN
@@ -170,7 +171,7 @@
   //!     specified in this parameter.
   //!
   //! \return `true` on success, `false` on failure with a message logged.
-  static bool StartJavaHandlerAtCrash(
+  bool StartJavaHandlerAtCrash(
       const std::string& class_name,
       const std::vector<std::string>* env,
       const base::FilePath& database,
@@ -251,7 +252,7 @@
   //!     specified in this parameter.
   //!
   //! \return `true` on success, `false` on failure with a message logged.
-  static bool StartHandlerWithLinkerAtCrash(
+  bool StartHandlerWithLinkerAtCrash(
       const std::string& handler_trampoline,
       const std::string& handler_library,
       bool is_64_bit,
@@ -333,7 +334,7 @@
   //!     specified in this parameter.
   //!
   //! \return `true` on success, `false` on failure with a message logged.
-  static bool StartHandlerAtCrash(
+  bool StartHandlerAtCrash(
       const base::FilePath& handler,
       const base::FilePath& database,
       const base::FilePath& metrics_dir,
@@ -413,6 +414,16 @@
   //! \param[in] handler The custom crash signal handler to install.
   static void SetFirstChanceExceptionHandler(FirstChanceHandler handler);
 
+  //! \brief Configures a set of signals that shouldn't have Crashpad signal
+  //!     handlers installed.
+  //!
+  //! This method should be called before calling StartHandler(),
+  //! SetHandlerSocket(), or other methods that install Crashpad signal
+  //! handlers.
+  //!
+  //! \param[in] unhandled_signals The set of unhandled signals
+  void SetUnhandledSignals(const std::set<int>& unhandled_signals);
+
 #endif  // OS_LINUX || OS_ANDROID || DOXYGEN
 
 #if defined(OS_MACOSX) || DOXYGEN
@@ -604,6 +615,8 @@
 #elif defined(OS_WIN)
   std::wstring ipc_pipe_;
   ScopedKernelHANDLE handler_start_thread_;
+#elif defined(OS_LINUX) || defined(OS_ANDROID)
+  std::set<int> unhandled_signals_;
 #endif  // OS_MACOSX
 
   DISALLOW_COPY_AND_ASSIGN(CrashpadClient);
diff --git a/third_party/crashpad/crashpad/client/crashpad_client_linux.cc b/third_party/crashpad/crashpad/client/crashpad_client_linux.cc
index eb210a2..c3ebbd4c 100644
--- a/third_party/crashpad/crashpad/client/crashpad_client_linux.cc
+++ b/third_party/crashpad/crashpad/client/crashpad_client_linux.cc
@@ -155,11 +155,11 @@
  protected:
   SignalHandler() = default;
 
-  bool Install() {
+  bool Install(const std::set<int>* unhandled_signals) {
     DCHECK(!handler_);
     handler_ = this;
     return Signals::InstallCrashHandlers(
-        HandleOrReraiseSignal, 0, &old_actions_);
+        HandleOrReraiseSignal, 0, &old_actions_, unhandled_signals);
   }
 
   const ExceptionInformation& GetExceptionInfo() {
@@ -202,7 +202,8 @@
   }
 
   bool Initialize(std::vector<std::string>* argv_in,
-                  const std::vector<std::string>* envp) {
+                  const std::vector<std::string>* envp,
+                  const std::set<int>* unhandled_signals) {
     argv_strings_.swap(*argv_in);
 
     if (envp) {
@@ -215,7 +216,7 @@
                                                   &GetExceptionInfo()));
 
     StringVectorToCStringVector(argv_strings_, &argv_);
-    return Install();
+    return Install(unhandled_signals);
   }
 
   void HandleCrashImpl() override {
@@ -270,7 +271,9 @@
   // created the namespace.
   // pid > 0 directly indicates what the handler's pid is expected to be, so
   // retrieving this information from the handler is not necessary.
-  bool Initialize(ScopedFileHandle sock, pid_t pid) {
+  bool Initialize(ScopedFileHandle sock,
+                  pid_t pid,
+                  const std::set<int>* unhandled_signals) {
     ExceptionHandlerClient client(sock.get(), true);
     if (pid < 0) {
       ucred creds;
@@ -285,7 +288,7 @@
     }
     sock_to_handler_.reset(sock.release());
     handler_pid_ = pid;
-    return Install();
+    return Install(unhandled_signals);
   }
 
   bool GetHandlerSocket(int* sock, pid_t* pid) {
@@ -368,7 +371,8 @@
   }
 
   auto signal_handler = RequestCrashDumpHandler::Get();
-  return signal_handler->Initialize(std::move(client_sock), -1);
+  return signal_handler->Initialize(
+      std::move(client_sock), -1, &unhandled_signals_);
 }
 
 #if defined(OS_ANDROID) || defined(OS_LINUX)
@@ -378,16 +382,14 @@
   return signal_handler->GetHandlerSocket(sock, pid);
 }
 
-// static
 bool CrashpadClient::SetHandlerSocket(ScopedFileHandle sock, pid_t pid) {
   auto signal_handler = RequestCrashDumpHandler::Get();
-  return signal_handler->Initialize(std::move(sock), pid);
+  return signal_handler->Initialize(std::move(sock), pid, &unhandled_signals_);
 }
 #endif  // OS_ANDROID || OS_LINUX
 
 #if defined(OS_ANDROID)
 
-// static
 bool CrashpadClient::StartJavaHandlerAtCrash(
     const std::string& class_name,
     const std::vector<std::string>* env,
@@ -405,7 +407,7 @@
                                                       kInvalidFileHandle);
 
   auto signal_handler = LaunchAtCrashHandler::Get();
-  return signal_handler->Initialize(&argv, env);
+  return signal_handler->Initialize(&argv, env, &unhandled_signals_);
 }
 
 // static
@@ -423,7 +425,6 @@
   return DoubleForkAndExec(argv, env, socket, false, nullptr);
 }
 
-// static
 bool CrashpadClient::StartHandlerWithLinkerAtCrash(
     const std::string& handler_trampoline,
     const std::string& handler_library,
@@ -445,7 +446,7 @@
                                   arguments,
                                   kInvalidFileHandle);
   auto signal_handler = LaunchAtCrashHandler::Get();
-  return signal_handler->Initialize(&argv, env);
+  return signal_handler->Initialize(&argv, env, &unhandled_signals_);
 }
 
 // static
@@ -475,7 +476,6 @@
 
 #endif
 
-// static
 bool CrashpadClient::StartHandlerAtCrash(
     const base::FilePath& handler,
     const base::FilePath& database,
@@ -487,7 +487,7 @@
       handler, database, metrics_dir, url, annotations, arguments);
 
   auto signal_handler = LaunchAtCrashHandler::Get();
-  return signal_handler->Initialize(&argv, nullptr);
+  return signal_handler->Initialize(&argv, nullptr, &unhandled_signals_);
 }
 
 // static
@@ -543,6 +543,11 @@
   SignalHandler::Get()->SetFirstChanceHandler(handler);
 }
 
+void CrashpadClient::SetUnhandledSignals(const std::set<int>& signals) {
+  DCHECK(!SignalHandler::Get());
+  unhandled_signals_ = signals;
+}
+
 #if defined(OS_CHROMEOS)
 // static
 void CrashpadClient::SetCrashLoopBefore(uint64_t crash_loop_before_time) {
diff --git a/third_party/crashpad/crashpad/handler/crashpad_handler.md b/third_party/crashpad/crashpad/handler/crashpad_handler.md
index c4126b6..f7e63a50 100644
--- a/third_party/crashpad/crashpad/handler/crashpad_handler.md
+++ b/third_party/crashpad/crashpad/handler/crashpad_handler.md
@@ -279,6 +279,13 @@
    library, typically in response to a user requesting this behavior. If this
    option is not specified, this program will behave as if uploads are disabled.
 
+ * **--use-cros-crash-reporter**
+
+   Causes crash reports to be passed via an in-memory file to
+   `/sbin/crash_reporter` instead of storing them in the database. The database
+   is still used for Crashpad settings. This option is only valid on Chromium
+   OS.
+
  * **--help**
 
    Display help and exit.
diff --git a/third_party/crashpad/crashpad/handler/handler_main.cc b/third_party/crashpad/crashpad/handler/handler_main.cc
index 7b69e84..d5a9e609 100644
--- a/third_party/crashpad/crashpad/handler/handler_main.cc
+++ b/third_party/crashpad/crashpad/handler/handler_main.cc
@@ -163,6 +163,11 @@
 "                              only if uploads are enabled for the database\n"
 #if defined(OS_CHROMEOS)
 "      --use-cros-crash-reporter\n"
+"                              pass crash reports to /sbin/crash_reporter\n"
+"                              instead of storing them in the database\n"
+"      --minidump-dir-for-tests=TEST_MINIDUMP_DIR\n"
+"                              causes /sbin/crash_reporter to leave dumps in\n"
+"                              this directory instead of the normal location\n"
 #endif  // OS_CHROMEOS
 "      --help                  display this help and exit\n"
 "      --version               output version information and exit\n",
@@ -197,6 +202,7 @@
   bool upload_gzip;
 #if defined(OS_CHROMEOS)
   bool use_cros_crash_reporter;
+  base::FilePath minidump_dir_for_tests;
 #endif  // OS_CHROMEOS
 };
 
@@ -571,6 +577,7 @@
     kOptionURL,
 #if defined(OS_CHROMEOS)
     kOptionUseCrosCrashReporter,
+    kOptionMinidumpDirForTests,
 #endif  // OS_CHROMEOS
 
     // Standard options.
@@ -642,6 +649,10 @@
       no_argument,
       nullptr,
       kOptionUseCrosCrashReporter},
+    {"minidump_dir_for_tests",
+      required_argument,
+      nullptr,
+      kOptionMinidumpDirForTests},
 #endif  // OS_CHROMEOS
     {"help", no_argument, nullptr, kOptionHelp},
     {"version", no_argument, nullptr, kOptionVersion},
@@ -789,6 +800,11 @@
         options.use_cros_crash_reporter = true;
         break;
       }
+      case kOptionMinidumpDirForTests: {
+        options.minidump_dir_for_tests = base::FilePath(
+            ToolSupport::CommandLineArgumentToFilePathStringType(optarg));
+        break;
+      }
 #endif  // OS_CHROMEOS
       case kOptionHelp: {
         Usage(me);
@@ -923,10 +939,16 @@
 
 #if defined(OS_CHROMEOS)
   if (options.use_cros_crash_reporter) {
-    exception_handler = std::make_unique<CrosCrashReportExceptionHandler>(
+    auto cros_handler = std::make_unique<CrosCrashReportExceptionHandler>(
         database.get(),
         &options.annotations,
         user_stream_sources);
+
+    if (!options.minidump_dir_for_tests.empty()) {
+      cros_handler->SetDumpDir(options.minidump_dir_for_tests);
+    }
+
+    exception_handler = std::move(cros_handler);
   } else {
     exception_handler = std::make_unique<CrashReportExceptionHandler>(
         database.get(),
diff --git a/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.cc b/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.cc
index a24b17f6..f54cc07 100644
--- a/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.cc
+++ b/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.cc
@@ -255,6 +255,9 @@
     argv.push_back("--crash_loop_before=" +
                    std::to_string(info.crash_loop_before_time));
   }
+  if (!dump_dir_.empty()) {
+    argv.push_back("--chrome_dump_dir=" + dump_dir_.value());
+  }
 
   if (!DoubleForkAndExec(argv,
                          nullptr /* envp */,
@@ -270,6 +273,7 @@
   if (local_report_id != nullptr) {
     *local_report_id = uuid;
   }
+  LOG(INFO) << "Successfully wrote report " << uuid.ToString();
 
   Metrics::ExceptionCaptureResult(Metrics::CaptureResult::kSuccess);
   return true;
diff --git a/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.h b/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.h
index f6ca445b..def1c82b 100644
--- a/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.h
+++ b/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.h
@@ -76,6 +76,7 @@
       int broker_sock,
       UUID* local_report_id = nullptr) override;
 
+  void SetDumpDir(const base::FilePath& dump_dir) { dump_dir_ = dump_dir; }
  private:
   bool HandleExceptionWithConnection(
       PtraceConnection* connection,
@@ -88,6 +89,7 @@
   CrashReportDatabase* database_;  // weak
   const std::map<std::string, std::string>* process_annotations_;  // weak
   const UserStreamDataSources* user_stream_data_sources_;  // weak
+  base::FilePath dump_dir_;
 
   DISALLOW_COPY_AND_ASSIGN(CrosCrashReportExceptionHandler);
 };
diff --git a/third_party/crashpad/crashpad/util/BUILD.gn b/third_party/crashpad/crashpad/util/BUILD.gn
index 3819b15..dec7d5c4 100644
--- a/third_party/crashpad/crashpad/util/BUILD.gn
+++ b/third_party/crashpad/crashpad/util/BUILD.gn
@@ -49,7 +49,8 @@
       if (!use_system_xcode) {
         import("//build/config/clang/clang.gni")
         import("//build/config/mac/mac_sdk.gni")
-        clang_path = rebase_path("$clang_base_path/bin/", root_build_dir) + "clang"
+        clang_path =
+            rebase_path("$clang_base_path/bin/", root_build_dir) + "clang"
         mig_path = "$mac_bin_path" + "mig"
         migcom_path = "$mac_bin_path" + "../libexec/migcom"
 
@@ -165,6 +166,9 @@
     "stdlib/strnlen.cc",
     "stdlib/strnlen.h",
     "stdlib/thread_safe_vector.h",
+    "stream/output_stream_interface.h",
+    "stream/zlib_output_stream.cc",
+    "stream/zlib_output_stream.h",
     "string/split_string.cc",
     "string/split_string.h",
     "synchronization/semaphore.h",
@@ -177,6 +181,8 @@
     "thread/worker_thread.h",
   ]
 
+  defines = [ "ZLIB_CONST" ]
+
   if (crashpad_is_posix || crashpad_is_fuchsia) {
     sources += [
       "file/directory_reader_posix.cc",
@@ -273,7 +279,7 @@
   if (crashpad_is_linux || crashpad_is_fuchsia || crashpad_is_android) {
     sources += [ "net/http_transport_socket.cc" ]
     if (crashpad_use_boringssl_for_http_transport_socket) {
-      defines = [ "CRASHPAD_USE_BORINGSSL" ]
+      defines += [ "CRASHPAD_USE_BORINGSSL" ]
 
       if (crashpad_is_in_fuchsia) {
         deps += [ "//third_party/boringssl" ]
@@ -593,6 +599,9 @@
     "stdlib/strlcpy_test.cc",
     "stdlib/strnlen_test.cc",
     "stdlib/thread_safe_vector_test.cc",
+    "stream/test_output_stream.cc",
+    "stream/test_output_stream.h",
+    "stream/zlib_output_stream_test.cc",
     "string/split_string_test.cc",
     "synchronization/semaphore_test.cc",
     "thread/thread_log_messages_test.cc",
diff --git a/third_party/crashpad/crashpad/util/posix/signals.cc b/third_party/crashpad/crashpad/util/posix/signals.cc
index 1384de1..53c1038 100644
--- a/third_party/crashpad/crashpad/util/posix/signals.cc
+++ b/third_party/crashpad/crashpad/util/posix/signals.cc
@@ -93,9 +93,14 @@
 bool InstallHandlers(const std::vector<int>& signals,
                      Signals::Handler handler,
                      int flags,
-                     Signals::OldActions* old_actions) {
+                     Signals::OldActions* old_actions,
+                     const std::set<int>* unhandled_signals) {
   bool success = true;
   for (int sig : signals) {
+    if (unhandled_signals &&
+        unhandled_signals->find(sig) != unhandled_signals->end()) {
+      continue;
+    }
     success &= Signals::InstallHandler(
         sig,
         handler,
@@ -151,13 +156,15 @@
 // static
 bool Signals::InstallCrashHandlers(Handler handler,
                                    int flags,
-                                   OldActions* old_actions) {
+                                   OldActions* old_actions,
+                                   const std::set<int>* unhandled_signals) {
   return InstallHandlers(
       std::vector<int>(kCrashSignals,
                        kCrashSignals + base::size(kCrashSignals)),
       handler,
       flags,
-      old_actions);
+      old_actions,
+      unhandled_signals);
 }
 
 // static
@@ -169,7 +176,8 @@
                        kTerminateSignals + base::size(kTerminateSignals)),
       handler,
       flags,
-      old_actions);
+      old_actions,
+      nullptr);
 }
 
 // static
diff --git a/third_party/crashpad/crashpad/util/posix/signals.h b/third_party/crashpad/crashpad/util/posix/signals.h
index dc55059..368161bf 100644
--- a/third_party/crashpad/crashpad/util/posix/signals.h
+++ b/third_party/crashpad/crashpad/util/posix/signals.h
@@ -17,6 +17,8 @@
 
 #include <signal.h>
 
+#include <set>
+
 #include "base/macros.h"
 
 namespace crashpad {
@@ -114,15 +116,19 @@
   //!     the new action. May be `nullptr` if not needed. The same \a
   //!     old_actions object may be used for calls to both this function and
   //!     InstallTerminateHandlers().
+  //! \param[in] unhandled_signals Signal handlers will not be installed for
+  //!     signal numbers in this set. Optional.
   //!
   //! \return `true` on success. `false` on failure with a message logged.
   //!
   //! \warning This function may not be called from a signal handler because of
   //!     its use of logging. See RestoreHandlerAndReraiseSignalOnReturn()
   //!     instead.
-  static bool InstallCrashHandlers(Handler handler,
-                                   int flags,
-                                   OldActions* old_actions);
+  static bool InstallCrashHandlers(
+      Handler handler,
+      int flags,
+      OldActions* old_actions,
+      const std::set<int>* unhandled_signals = nullptr);
 
   //! \brief Installs a new signal handler for all signals associated with
   //!     termination.
diff --git a/third_party/crashpad/crashpad/util/posix/signals_test.cc b/third_party/crashpad/crashpad/util/posix/signals_test.cc
index d91e3cc..f46e331 100644
--- a/third_party/crashpad/crashpad/util/posix/signals_test.cc
+++ b/third_party/crashpad/crashpad/util/posix/signals_test.cc
@@ -258,7 +258,12 @@
   void MultiprocessChild() override {
     bool (*install_handlers)(Signals::Handler, int, Signals::OldActions*);
     if (Signals::IsCrashSignal(sig_)) {
-      install_handlers = Signals::InstallCrashHandlers;
+      install_handlers = [](Signals::Handler handler,
+                            int sig,
+                            Signals::OldActions* old_actions) {
+        return Signals::InstallCrashHandlers(
+            handler, sig, old_actions, nullptr);
+      };
     } else if (Signals::IsTerminateSignal(sig_)) {
       install_handlers = Signals::InstallTerminateHandlers;
     } else {
diff --git a/third_party/crashpad/crashpad/util/stream/output_stream_interface.h b/third_party/crashpad/crashpad/util/stream/output_stream_interface.h
new file mode 100644
index 0000000..397860e
--- /dev/null
+++ b/third_party/crashpad/crashpad/util/stream/output_stream_interface.h
@@ -0,0 +1,64 @@
+// Copyright 2019 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CRASHPAD_UTIL_STREAM_OUTPUT_STREAM_INTERFACE_H_
+#define CRASHPAD_UTIL_STREAM_OUTPUT_STREAM_INTERFACE_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace crashpad {
+
+//! \brief The interface for an output stream pipeline.
+//!
+//! Example:
+//! <code>
+//!   class OutputStreamInterfaceImpl : public OutputStreamInterface {
+//!     ...
+//!   };
+//!
+//!   // Create a OutputStream.
+//!   OutputStreamInterfaceImpl impl(...);
+//!   // Write the data multiple times.
+//!   while (has_data) {
+//!     impl.Write(data, size);
+//!     ...
+//!   }
+//!   // Flush internal buffer to indicate all data has been written.
+//!   impl.Flush();
+//! </code>
+//!
+class OutputStreamInterface {
+ public:
+  virtual ~OutputStreamInterface() = default;
+
+  //! \brief Writes \a data to this stream. This method may be called multiple
+  //! times for streaming.
+  //!
+  //! \param[in] data The data that should be written.
+  //! \param[in] size The size of \a data.
+  //!
+  //! \return `true` on success.
+  virtual bool Write(const uint8_t* data, size_t size) = 0;
+
+  //! \brief Flush the internal buffer after all data has been written.
+  //!
+  //! Write() can't be called afterwards.
+  //! \return `true` on success.
+  virtual bool Flush() = 0;
+};
+
+}  // namespace crashpad
+
+#endif  // CRASHPAD_UTIL_STREAM_OUTPUT_STREAM_INTERFACE_H_
diff --git a/third_party/crashpad/crashpad/util/stream/test_output_stream.cc b/third_party/crashpad/crashpad/util/stream/test_output_stream.cc
new file mode 100644
index 0000000..04ef7007
--- /dev/null
+++ b/third_party/crashpad/crashpad/util/stream/test_output_stream.cc
@@ -0,0 +1,48 @@
+// Copyright 2019 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "util/stream/test_output_stream.h"
+#include "base/logging.h"
+
+namespace crashpad {
+namespace test {
+
+TestOutputStream::TestOutputStream()
+    : last_written_data_(),
+      all_data_(),
+      write_count_(0),
+      flush_count_(0),
+      flush_needed_(false) {}
+
+TestOutputStream::~TestOutputStream() {
+  DCHECK(!flush_needed_);
+}
+
+bool TestOutputStream::Write(const uint8_t* data, size_t size) {
+  last_written_data_.assign(data, data + size);
+  all_data_.insert(all_data_.end(), data, data + size);
+
+  flush_needed_ = true;
+  write_count_++;
+  return true;
+}
+
+bool TestOutputStream::Flush() {
+  flush_needed_ = false;
+  flush_count_++;
+  return true;
+}
+
+}  // namespace test
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/stream/test_output_stream.h b/third_party/crashpad/crashpad/util/stream/test_output_stream.h
new file mode 100644
index 0000000..dcd0d45
--- /dev/null
+++ b/third_party/crashpad/crashpad/util/stream/test_output_stream.h
@@ -0,0 +1,66 @@
+// Copyright 2019 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CRASHPAD_UTIL_STREAM_TEST_OUTPUT_STREAM_H_
+#define CRASHPAD_UTIL_STREAM_TEST_OUTPUT_STREAM_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <vector>
+
+#include "base/macros.h"
+#include "util/stream/output_stream_interface.h"
+
+namespace crashpad {
+namespace test {
+
+//! \brief The help class for \a OutputStreamInterface related tests.
+class TestOutputStream : public OutputStreamInterface {
+ public:
+  TestOutputStream();
+  ~TestOutputStream() override;
+
+  // OutputStreamInterface:
+  bool Write(const uint8_t* data, size_t size) override;
+  bool Flush() override;
+
+  //! \return the data that has been received by the last call of Write().
+  const std::vector<uint8_t>& last_written_data() const {
+    return last_written_data_;
+  }
+
+  //! \return all data that has been received.
+  const std::vector<uint8_t>& all_data() const { return all_data_; }
+
+  //! \return the number of times Write() has been called.
+  size_t write_count() const { return write_count_; }
+
+  //! \return the number of times Flush() has been called.
+  size_t flush_count() const { return flush_count_; }
+
+ private:
+  std::vector<uint8_t> last_written_data_;
+  std::vector<uint8_t> all_data_;
+  size_t write_count_;
+  size_t flush_count_;
+  bool flush_needed_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestOutputStream);
+};
+
+}  // namespace test
+}  // namespace crashpad
+
+#endif  // CRASHPAD_UTIL_STREAM_TEST_OUTPUT_STREAM_H_
diff --git a/third_party/crashpad/crashpad/util/stream/zlib_output_stream.cc b/third_party/crashpad/crashpad/util/stream/zlib_output_stream.cc
new file mode 100644
index 0000000..88861db
--- /dev/null
+++ b/third_party/crashpad/crashpad/util/stream/zlib_output_stream.cc
@@ -0,0 +1,139 @@
+// Copyright 2019 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "util/stream/zlib_output_stream.h"
+
+#include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/stl_util.h"
+#include "util/misc/zlib.h"
+
+namespace crashpad {
+
+ZlibOutputStream::ZlibOutputStream(
+    Mode mode,
+    std::unique_ptr<OutputStreamInterface> output_stream)
+    : output_stream_(std::move(output_stream)),
+      mode_(mode),
+      initialized_(),
+      flush_needed_(false) {}
+
+ZlibOutputStream::~ZlibOutputStream() {
+  if (!initialized_.is_valid())
+    return;
+  DCHECK(!flush_needed_);
+  if (mode_ == Mode::kCompress) {
+    if (deflateEnd(&zlib_stream_) != Z_OK)
+      LOG(ERROR) << "deflateEnd: " << zlib_stream_.msg;
+  } else if (mode_ == Mode::kDecompress) {
+    if (inflateEnd(&zlib_stream_) != Z_OK)
+      LOG(ERROR) << "inflateEnd: " << zlib_stream_.msg;
+  }
+}
+
+bool ZlibOutputStream::Write(const uint8_t* data, size_t size) {
+  if (initialized_.is_uninitialized()) {
+    initialized_.set_invalid();
+
+    zlib_stream_.zalloc = Z_NULL;
+    zlib_stream_.zfree = Z_NULL;
+    zlib_stream_.opaque = Z_NULL;
+
+    if (mode_ == Mode::kDecompress) {
+      int result = inflateInit(&zlib_stream_);
+      if (result != Z_OK) {
+        LOG(ERROR) << "inflateInit: " << ZlibErrorString(result);
+        return false;
+      }
+    } else if (mode_ == Mode::kCompress) {
+      int result = deflateInit(&zlib_stream_, Z_BEST_COMPRESSION);
+      if (result != Z_OK) {
+        LOG(ERROR) << "deflateInit: " << ZlibErrorString(result);
+        return false;
+      }
+    }
+    zlib_stream_.next_out = buffer_;
+    zlib_stream_.avail_out = base::saturated_cast<uInt>(base::size(buffer_));
+    initialized_.set_valid();
+  }
+
+  if (!initialized_.is_valid())
+    return false;
+
+  zlib_stream_.next_in = data;
+  zlib_stream_.avail_in = base::saturated_cast<uInt>(size);
+  flush_needed_ = false;
+  while (zlib_stream_.avail_in > 0) {
+    if (mode_ == Mode::kCompress) {
+      if (deflate(&zlib_stream_, Z_NO_FLUSH) != Z_OK) {
+        LOG(ERROR) << "deflate: " << zlib_stream_.msg;
+        return false;
+      }
+    } else if (mode_ == Mode::kDecompress) {
+      int result = inflate(&zlib_stream_, Z_NO_FLUSH);
+      if (result == Z_STREAM_END) {
+        if (zlib_stream_.avail_in > 0) {
+          LOG(ERROR) << "inflate: unconsumed input";
+          return false;
+        }
+      } else if (result != Z_OK) {
+        LOG(ERROR) << "inflate: " << zlib_stream_.msg;
+        return false;
+      }
+    }
+
+    if (!WriteOutputStream())
+      return false;
+  }
+  flush_needed_ = true;
+  return true;
+}
+
+bool ZlibOutputStream::Flush() {
+  if (initialized_.is_valid() && flush_needed_) {
+    flush_needed_ = false;
+    int result = Z_OK;
+    do {
+      if (mode_ == Mode::kCompress) {
+        result = deflate(&zlib_stream_, Z_FINISH);
+        if (result != Z_STREAM_END && result != Z_BUF_ERROR && result != Z_OK) {
+          LOG(ERROR) << "deflate: " << zlib_stream_.msg;
+          return false;
+        }
+      } else if (mode_ == Mode::kDecompress) {
+        result = inflate(&zlib_stream_, Z_FINISH);
+        if (result != Z_STREAM_END && result != Z_BUF_ERROR && result != Z_OK) {
+          LOG(ERROR) << "inflate: " << zlib_stream_.msg;
+          return false;
+        }
+      }
+      if (!WriteOutputStream())
+        return false;
+    } while (result != Z_STREAM_END);
+  }
+  return output_stream_->Flush();
+}
+
+bool ZlibOutputStream::WriteOutputStream() {
+  auto valid_size = base::size(buffer_) - zlib_stream_.avail_out;
+  if (valid_size > 0 && !output_stream_->Write(buffer_, valid_size))
+    return false;
+
+  zlib_stream_.next_out = buffer_;
+  zlib_stream_.avail_out = base::saturated_cast<uInt>(base::size(buffer_));
+
+  return true;
+}
+
+}  // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/stream/zlib_output_stream.h b/third_party/crashpad/crashpad/util/stream/zlib_output_stream.h
new file mode 100644
index 0000000..d8e62a6
--- /dev/null
+++ b/third_party/crashpad/crashpad/util/stream/zlib_output_stream.h
@@ -0,0 +1,82 @@
+// Copyright 2019 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CRASHPAD_UTIL_STREAM_ZLIB_OUTPUT_STREAM_H_
+#define CRASHPAD_UTIL_STREAM_ZLIB_OUTPUT_STREAM_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+
+#include "base/macros.h"
+#include "third_party/zlib/zlib_crashpad.h"
+#include "util/misc/initialization_state.h"
+#include "util/stream/output_stream_interface.h"
+
+namespace crashpad {
+
+//! \brief The class wraps zlib into \a OutputStreamInterface.
+class ZlibOutputStream : public OutputStreamInterface {
+ public:
+  //! \brief Whether this object is configured to compress or decompress data.
+  enum class Mode : bool {
+    //! \brief Data passed through this object is compressed.
+    kCompress = false,
+    //! \brief Data passed through this object is decompressed.
+    kDecompress = true
+  };
+
+  //! \param[in] mode The work mode of this object.
+  //! \param[in] output_stream The output_stream that this object writes to.
+  //!
+  //! To construct an output pipeline, the output stream needs an output stream
+  //! to write the result to. For example, the code below constructs a
+  //! compress->base94-encoding->log output stream pipline.
+  //!
+  //! <code>
+  //!   ZlibOutputStream zlib_output_stream(
+  //!        ZlibOutputStream::Mode::kDeflate,
+  //!        std::make_unique<Base94OutputStream>(
+  //!            Base94OutputStream::Mode::kEncode,
+  //!            std::make_unique<LogOutputStream>()));
+  //! </code>
+  //!
+  //!
+  ZlibOutputStream(Mode mode,
+                   std::unique_ptr<OutputStreamInterface> output_stream);
+  ~ZlibOutputStream() override;
+
+  // OutputStreamInterface:
+  bool Write(const uint8_t* data, size_t size) override;
+  bool Flush() override;
+
+ private:
+  // Write compressed/decompressed data to |output_stream_| and empty the output
+  // buffer in |zlib_stream_|.
+  bool WriteOutputStream();
+
+  uint8_t buffer_[4096];
+  z_stream zlib_stream_;
+  std::unique_ptr<OutputStreamInterface> output_stream_;
+  Mode mode_;
+  InitializationState initialized_;  // protects zlib_stream_
+  bool flush_needed_;
+
+  DISALLOW_COPY_AND_ASSIGN(ZlibOutputStream);
+};
+
+}  // namespace crashpad
+
+#endif  // CRASHPAD_UTIL_STREAM_ZLIB_OUTPUT_STREAM_H_
diff --git a/third_party/crashpad/crashpad/util/stream/zlib_output_stream_test.cc b/third_party/crashpad/crashpad/util/stream/zlib_output_stream_test.cc
new file mode 100644
index 0000000..dfa935b6
--- /dev/null
+++ b/third_party/crashpad/crashpad/util/stream/zlib_output_stream_test.cc
@@ -0,0 +1,186 @@
+// Copyright 2019 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "util/stream/zlib_output_stream.h"
+
+#include <string.h>
+
+#include <algorithm>
+
+#include "base/rand_util.h"
+#include "base/stl_util.h"
+#include "base/strings/stringprintf.h"
+#include "gtest/gtest.h"
+#include "util/stream/test_output_stream.h"
+
+namespace crashpad {
+namespace test {
+namespace {
+
+constexpr size_t kShortDataLength = 10;
+constexpr size_t kLongDataLength = 4096 * 10;
+
+class ZlibOutputStreamTest : public testing::Test {
+ public:
+  ZlibOutputStreamTest() : input_(), deterministic_input_() {
+    auto test_output_stream = std::make_unique<TestOutputStream>();
+    test_output_stream_ = test_output_stream.get();
+    zlib_output_stream_ = std::make_unique<ZlibOutputStream>(
+        ZlibOutputStream::Mode::kCompress,
+        std::make_unique<ZlibOutputStream>(ZlibOutputStream::Mode::kDecompress,
+                                           std::move(test_output_stream)));
+  }
+
+  const uint8_t* BuildDeterministicInput(size_t size) {
+    deterministic_input_ = std::make_unique<uint8_t[]>(size);
+    uint8_t* deterministic_input_base = deterministic_input_.get();
+    while (size-- > 0)
+      deterministic_input_base[size] = static_cast<uint8_t>(size);
+    return deterministic_input_base;
+  }
+
+  const uint8_t* BuildRandomInput(size_t size) {
+    input_ = std::make_unique<uint8_t[]>(size);
+    base::RandBytes(&input_[0], size);
+    return input_.get();
+  }
+
+  const TestOutputStream& test_output_stream() const {
+    return *test_output_stream_;
+  }
+
+  ZlibOutputStream* zlib_output_stream() const {
+    return zlib_output_stream_.get();
+  }
+
+ private:
+  std::unique_ptr<ZlibOutputStream> zlib_output_stream_;
+  std::unique_ptr<uint8_t[]> input_;
+  std::unique_ptr<uint8_t[]> deterministic_input_;
+  TestOutputStream* test_output_stream_;  // weak, owned by zlib_output_stream_
+
+  DISALLOW_COPY_AND_ASSIGN(ZlibOutputStreamTest);
+};
+
+TEST_F(ZlibOutputStreamTest, WriteDeterministicShortData) {
+  const uint8_t* input = BuildDeterministicInput(kShortDataLength);
+  EXPECT_TRUE(zlib_output_stream()->Write(input, kShortDataLength));
+  EXPECT_TRUE(zlib_output_stream()->Flush());
+  EXPECT_EQ(test_output_stream().last_written_data().size(), kShortDataLength);
+  EXPECT_EQ(memcmp(test_output_stream().last_written_data().data(),
+                   input,
+                   kShortDataLength),
+            0);
+}
+
+TEST_F(ZlibOutputStreamTest, WriteDeterministicLongDataOneTime) {
+  const uint8_t* input = BuildDeterministicInput(kLongDataLength);
+  EXPECT_TRUE(zlib_output_stream()->Write(input, kLongDataLength));
+  EXPECT_TRUE(zlib_output_stream()->Flush());
+  EXPECT_EQ(test_output_stream().all_data().size(), kLongDataLength);
+  EXPECT_EQ(
+      memcmp(test_output_stream().all_data().data(), input, kLongDataLength),
+      0);
+}
+
+TEST_F(ZlibOutputStreamTest, WriteDeterministicLongDataMultipleTimes) {
+  const uint8_t* input = BuildDeterministicInput(kLongDataLength);
+
+  static constexpr size_t kWriteLengths[] = {
+      4, 96, 40, kLongDataLength - 4 - 96 - 40};
+
+  size_t offset = 0;
+  for (size_t index = 0; index < base::size(kWriteLengths); ++index) {
+    const size_t write_length = kWriteLengths[index];
+    SCOPED_TRACE(base::StringPrintf(
+        "offset %zu, write_length %zu", offset, write_length));
+    EXPECT_TRUE(zlib_output_stream()->Write(input + offset, write_length));
+    offset += write_length;
+  }
+  EXPECT_TRUE(zlib_output_stream()->Flush());
+  EXPECT_EQ(test_output_stream().all_data().size(), kLongDataLength);
+  EXPECT_EQ(
+      memcmp(test_output_stream().all_data().data(), input, kLongDataLength),
+      0);
+}
+
+TEST_F(ZlibOutputStreamTest, WriteShortData) {
+  const uint8_t* input = BuildRandomInput(kShortDataLength);
+  EXPECT_TRUE(zlib_output_stream()->Write(input, kShortDataLength));
+  EXPECT_TRUE(zlib_output_stream()->Flush());
+  EXPECT_EQ(memcmp(test_output_stream().last_written_data().data(),
+                   input,
+                   kShortDataLength),
+            0);
+  EXPECT_EQ(test_output_stream().last_written_data().size(), kShortDataLength);
+}
+
+TEST_F(ZlibOutputStreamTest, WriteLongDataOneTime) {
+  const uint8_t* input = BuildRandomInput(kLongDataLength);
+  EXPECT_TRUE(zlib_output_stream()->Write(input, kLongDataLength));
+  EXPECT_TRUE(zlib_output_stream()->Flush());
+  EXPECT_EQ(test_output_stream().all_data().size(), kLongDataLength);
+  EXPECT_EQ(
+      memcmp(test_output_stream().all_data().data(), input, kLongDataLength),
+      0);
+}
+
+TEST_F(ZlibOutputStreamTest, WriteLongDataMultipleTimes) {
+  const uint8_t* input = BuildRandomInput(kLongDataLength);
+
+  // Call Write() a random number of times.
+  size_t index = 0;
+  while (index < kLongDataLength) {
+    size_t write_length =
+        std::min(static_cast<size_t>(base::RandInt(0, 4096 * 2)),
+                 kLongDataLength - index);
+    SCOPED_TRACE(
+        base::StringPrintf("index %zu, write_length %zu", index, write_length));
+    EXPECT_TRUE(zlib_output_stream()->Write(input + index, write_length));
+    index += write_length;
+  }
+  EXPECT_TRUE(zlib_output_stream()->Flush());
+  EXPECT_EQ(test_output_stream().all_data().size(), kLongDataLength);
+  EXPECT_EQ(
+      memcmp(test_output_stream().all_data().data(), input, kLongDataLength),
+      0);
+}
+
+TEST_F(ZlibOutputStreamTest, NoWriteOrFlush) {
+  EXPECT_EQ(test_output_stream().write_count(), 0u);
+  EXPECT_EQ(test_output_stream().flush_count(), 0u);
+  EXPECT_TRUE(test_output_stream().all_data().empty());
+}
+
+TEST_F(ZlibOutputStreamTest, FlushWithoutWrite) {
+  EXPECT_TRUE(zlib_output_stream()->Flush());
+  EXPECT_EQ(test_output_stream().write_count(), 0u);
+  EXPECT_EQ(test_output_stream().flush_count(), 1u);
+  EXPECT_TRUE(test_output_stream().all_data().empty());
+}
+
+TEST_F(ZlibOutputStreamTest, WriteEmptyData) {
+  std::vector<uint8_t> empty_data;
+  EXPECT_TRUE(zlib_output_stream()->Write(
+      static_cast<const uint8_t*>(empty_data.data()), empty_data.size()));
+  EXPECT_TRUE(zlib_output_stream()->Flush());
+  EXPECT_TRUE(zlib_output_stream()->Flush());
+  EXPECT_EQ(test_output_stream().write_count(), 0u);
+  EXPECT_EQ(test_output_stream().flush_count(), 2u);
+  EXPECT_TRUE(test_output_stream().all_data().empty());
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace crashpad
diff --git a/tools/ipc_fuzzer/get_accessible_interfaces/get_accessible_interfaces.cc b/tools/ipc_fuzzer/get_accessible_interfaces/get_accessible_interfaces.cc
index dc1617e..f372cc5 100644
--- a/tools/ipc_fuzzer/get_accessible_interfaces/get_accessible_interfaces.cc
+++ b/tools/ipc_fuzzer/get_accessible_interfaces/get_accessible_interfaces.cc
@@ -25,7 +25,7 @@
 
   base::ListValue interface_names;
   for (const auto& interface_name : it->second) {
-    interface_names.GetList().emplace_back(base::Value(interface_name));
+    interface_names.Append(base::Value(interface_name));
   }
 
   return interface_names;
diff --git a/tools/json_schema_compiler/util.cc b/tools/json_schema_compiler/util.cc
index bda985c..b83e4a6 100644
--- a/tools/json_schema_compiler/util.cc
+++ b/tools/json_schema_compiler/util.cc
@@ -132,7 +132,7 @@
 }
 
 void AddItemToList(const std::vector<uint8_t>& from, base::ListValue* out) {
-  out->GetList().emplace_back(from);
+  out->Append(base::Value(from));
 }
 
 void AddItemToList(const std::unique_ptr<base::Value>& from,
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index da200ee..29d5855 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -19293,6 +19293,14 @@
   </description>
 </action>
 
+<action name="Signin_Signin_ShowAdvancedSyncSettings">
+  <owner>triploblastic@chromium.org</owner>
+  <owner>bsazonov@chromium.org</owner>
+  <description>
+    Recorded when advanced turn on sync flow is started.
+  </description>
+</action>
+
 <action name="Signin_Signin_Succeed">
   <owner>gogerald@chromium.org</owner>
   <description>Recorded when user sign in was successful.</description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 5e617a20..81e3377 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -32450,6 +32450,12 @@
   <int value="3" label="Page Control Drag"/>
 </enum>
 
+<enum name="IOSUserInterfaceStyle">
+  <int value="0" label="Unspecified"/>
+  <int value="1" label="Light"/>
+  <int value="2" label="Dark"/>
+</enum>
+
 <enum name="IOSWKWebViewLinkPreviewAction">
   <summary>
     This enum is used to track the user actions that occur when previewing links
@@ -37234,6 +37240,7 @@
   <int value="1421620678" label="simple-clear-browsing-data-support-string"/>
   <int value="1427905064" label="CreditCardAutofillTouchBar:enabled"/>
   <int value="1431050645" label="PayWithGoogleV1:disabled"/>
+  <int value="1431934725" label="OmniboxAutocompleteTitles:disabled"/>
   <int value="1434515920" label="ReaderModeInCCT:enabled"/>
   <int value="1435251818" label="AutofillNoLocalSaveOnUploadSuccess:enabled"/>
   <int value="1437413720" label="CooperativeScheduling:disabled"/>
@@ -37517,6 +37524,7 @@
   <int value="1831593339" label="stop-in-background:disabled"/>
   <int value="1831835753" label="MaterialDesignIncognitoNTP:enabled"/>
   <int value="1832552562" label="EnableVirtualKeyboardUkm:enabled"/>
+  <int value="1834968807" label="OmniboxAutocompleteTitles:enabled"/>
   <int value="1835523483" label="OmniboxUIExperimentSwapTitleAndUrl:enabled"/>
   <int value="1838990777" label="V8Future:enabled"/>
   <int value="1839740266" label="LocationHardReload:disabled"/>
@@ -46989,6 +46997,15 @@
   <int value="1" label="1+ from Android"/>
 </enum>
 
+<enum name="PasswordManagerOnboardingResultOfSavingFlow">
+  <int value="0" label="Infobar: No direct interaction"/>
+  <int value="1" label="Infobar: Clicked 'Save'"/>
+  <int value="2" label="Infobar: Clicked 'X'"/>
+  <int value="3" label="Infobar: Clicked 'Never'"/>
+  <int value="4" label="Onboarding: Rejected"/>
+  <int value="5" label="Onboarding: Dismissed"/>
+</enum>
+
 <enum name="PasswordManagerOnboardingState">
   <int value="0" label="Not shown"/>
   <int value="1" label="Should be shown"/>
@@ -58458,6 +58475,15 @@
   <int value="1" label="Sync transport only."/>
 </enum>
 
+<enum name="SyncFirstSetupCompleteSource">
+  <summary>Possible flows where the FirstSetupComplete bit was set.</summary>
+  <int value="0" label="Basic Flow"/>
+  <int value="1" label="Confirm Clicked In Advanced Flow"/>
+  <int value="2" label="Sync Turned On After Interrupted Advanced Flow"/>
+  <int value="3" label="Sync Left Off After Interrupted Advanced Flow"/>
+  <int value="4" label="Engine Initialized With Auto Start"/>
+</enum>
+
 <enum name="SyncFSConflictResolutionPolicy">
   <int value="0" label="Unknown"/>
   <int value="1" label="LastWriteWin"/>
@@ -58779,7 +58805,8 @@
   <int value="7" label="Web app action share"/>
   <int value="8" label="Web app action open in Chrome"/>
   <int value="9" label="Offline content suggestion settings"/>
-  <int value="10" label="Sharing notification dismiss button"/>
+  <int value="10"
+      label="[Deprecated in M79] Sharing notification dismiss button"/>
   <int value="11" label="Sharing error notification try again button"/>
 </enum>
 
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 379f6e3..38c6b13 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -2585,12 +2585,33 @@
   </summary>
 </histogram>
 
-<histogram base="true" name="Android.FeatureModules.CachedInstallDuration"
+<histogram base="true" name="Android.FeatureModules.CachedAwakeInstallDuration"
     units="ms" expires_after="2020-01-01">
 <!-- Name completed by histogram_suffixes
        name="AndroidFeatureModuleName" -->
 
   <owner>tiborg@chromium.org</owner>
+  <owner>wnwen@chromium.org</owner>
+  <owner>agrieve@chromium.org</owner>
+  <summary>
+    Duration of successful installs for each dynamic feature module. Only
+    contains install durations for modules first requested *before* Chrome
+    started last and may therefore be installed from cache. Omits deep sleep
+    time.
+  </summary>
+</histogram>
+
+<histogram base="true" name="Android.FeatureModules.CachedInstallDuration"
+    units="ms" expires_after="2020-01-01">
+  <obsolete>
+    Deprecated 2019-09 in favour of
+    Android.FeatureModules.CachedAwakeInstallDuration.
+  </obsolete>
+<!-- Name completed by histogram_suffixes
+       name="AndroidFeatureModuleName" -->
+
+  <owner>tiborg@chromium.org</owner>
+  <owner>wnwen@chromium.org</owner>
   <owner>agrieve@chromium.org</owner>
   <summary>
     Duration of successful installs for each dynamic feature module. Only
@@ -2623,12 +2644,34 @@
   </summary>
 </histogram>
 
-<histogram base="true" name="Android.FeatureModules.UncachedInstallDuration"
-    units="ms" expires_after="2020-01-01">
+<histogram base="true"
+    name="Android.FeatureModules.UncachedAwakeInstallDuration" units="ms"
+    expires_after="2020-01-01">
 <!-- Name completed by histogram_suffixes
        name="AndroidFeatureModuleName" -->
 
   <owner>tiborg@chromium.org</owner>
+  <owner>wnwen@chromium.org</owner>
+  <owner>agrieve@chromium.org</owner>
+  <summary>
+    Duration of successful installs for each dynamic feature module. Only
+    contains install durations of modules first requested *after* Chrome started
+    last and are therefore unlikely to be installed from cache. Omits deep sleep
+    time.
+  </summary>
+</histogram>
+
+<histogram base="true" name="Android.FeatureModules.UncachedInstallDuration"
+    units="ms" expires_after="2020-01-01">
+  <obsolete>
+    Deprecated 2019-09 in favour of
+    Android.FeatureModules.UncachedAwakeInstallDuration.
+  </obsolete>
+<!-- Name completed by histogram_suffixes
+       name="AndroidFeatureModuleName" -->
+
+  <owner>tiborg@chromium.org</owner>
+  <owner>wnwen@chromium.org</owner>
   <owner>agrieve@chromium.org</owner>
   <summary>
     Duration of successful installs for each dynamic feature module. Only
@@ -48439,7 +48482,7 @@
 </histogram>
 
 <histogram name="Geolocation.PositionCache.CacheHit" units="BooleanCacheHit"
-    expires_after="2019-09-20">
+    expires_after="2020-03-10">
   <owner>mattreynolds@chromium.org</owner>
   <owner>deviceapi-team@google.com</owner>
   <summary>
@@ -48449,7 +48492,7 @@
 </histogram>
 
 <histogram name="Geolocation.PositionCache.CacheSize" units="count"
-    expires_after="2019-09-20">
+    expires_after="2020-03-10">
   <owner>mattreynolds@chromium.org</owner>
   <owner>deviceapi-team@google.com</owner>
   <summary>
@@ -57590,6 +57633,15 @@
   </summary>
 </histogram>
 
+<histogram name="Login.BrowserShutdownTime" units="ms" expires_after="2020-9-9">
+  <owner>xiyuan@chromium.org</owner>
+  <summary>
+    Tracks the browser process shutdown time from when SIGTERM is sent to the
+    browser process to when the browser process group exits (or gets killed by
+    SIGABRT).
+  </summary>
+</histogram>
+
 <histogram name="Login.ConsumerNewUsersAllowed" enum="LoginConsumerWhitelist"
     expires_after="M77">
   <owner>cmasone@chromium.org</owner>
@@ -100352,6 +100404,30 @@
   </summary>
 </histogram>
 
+<histogram name="PasswordManager.Onboarding.ResultOfSavingFlow"
+    enum="PasswordManagerOnboardingResultOfSavingFlow"
+    expires_after="2020-01-31">
+  <owner>achulkov@google.com</owner>
+  <owner>ioanap@chromium.org</owner>
+  <summary>
+    Result of the combined saving flow consisting of the potentially shown
+    onboarding dialog and the save infobar. Recorded when the user is prompted
+    to save their password.
+  </summary>
+</histogram>
+
+<histogram name="PasswordManager.Onboarding.ResultOfSavingFlowAfterOnboarding"
+    enum="PasswordManagerOnboardingResultOfSavingFlow"
+    expires_after="2020-01-31">
+  <owner>achulkov@google.com</owner>
+  <owner>ioanap@chromium.org</owner>
+  <summary>
+    Result of the combined saving flow consisting of the shown onboarding dialog
+    and the save infobar. Recorded when the user is propmpted to save their
+    password only if the onboarding was actually shown.
+  </summary>
+</histogram>
+
 <histogram name="PasswordManager.Onboarding.State"
     enum="PasswordManagerOnboardingState" expires_after="2020-01-31">
   <owner>achulkov@google.com</owner>
@@ -131706,6 +131782,13 @@
   </summary>
 </histogram>
 
+<histogram name="Signin.SyncFirstSetupCompleteSource"
+    enum="SyncFirstSetupCompleteSource" expires_after="M85">
+  <owner>triploblastic@chromium.org</owner>
+  <owner>bsazonov@chromium.org</owner>
+  <summary>Tracks where FirstSetupComplete bit is set from.</summary>
+</histogram>
+
 <histogram name="Signin.TokenServiceDiceCompatible" enum="Boolean"
     expires_after="2019-11-01">
   <owner>msalama@chromium.org</owner>
@@ -140043,6 +140126,9 @@
 
 <histogram base="true" name="Sync.DuplicateClientTagHashInApplyPendingUpdates"
     enum="BooleanPresent" expires_after="2019-09-30">
+  <obsolete>
+    Removed 2019-09 - we collected sufficient data, see crbug.com/995534.
+  </obsolete>
   <owner>treib@chromium.org</owner>
   <owner>jkrcal@chromium.org</owner>
   <summary>
@@ -140054,6 +140140,9 @@
 
 <histogram base="true" name="Sync.DuplicateClientTagHashInGetUpdatesResponse"
     enum="BooleanPresent" expires_after="2019-09-30">
+  <obsolete>
+    Removed 2019-09 - we collected sufficient data, see crbug.com/995531.
+  </obsolete>
   <owner>treib@chromium.org</owner>
   <owner>jkrcal@chromium.org</owner>
   <summary>
@@ -140066,6 +140155,9 @@
 <histogram base="true"
     name="Sync.DuplicateClientTagHashWithDifferentServerIdsInApplyPendingUpdates"
     enum="BooleanPresent" expires_after="2019-09-30">
+  <obsolete>
+    Removed 2019-09 - we collected sufficient data, see crbug.com/995528.
+  </obsolete>
   <owner>mamir@chromium.org</owner>
   <owner>treib@chromium.org</owner>
   <summary>
@@ -140078,6 +140170,9 @@
 
 <histogram base="true" name="Sync.DuplicateServerIdInApplyPendingUpdates"
     enum="BooleanPresent" expires_after="2019-09-30">
+  <obsolete>
+    Removed 2019-09 - we collected sufficient data, see crbug.com/995529.
+  </obsolete>
   <owner>mamir@chromium.org</owner>
   <owner>treib@chromium.org</owner>
   <summary>
@@ -149486,6 +149581,29 @@
   </summary>
 </histogram>
 
+<histogram name="UserInterfaceStyle.ChangedWhileActive"
+    enum="IOSUserInterfaceStyle" expires_after="M81">
+  <owner>javierrobles@chromium.org</owner>
+  <owner>rkgibson@google.com</owner>
+  <owner>bling-team@google.com</owner>
+  <summary>
+    [iOS] Used on iOS 13+ to report the changes to Light and Dark mode. This is
+    logged when the interface style changes and Chrome is active. Can be caused
+    by the system automatic switch or by the user manually schanging the style.
+  </summary>
+</histogram>
+
+<histogram name="UserInterfaceStyle.CurrentlyUsed" enum="IOSUserInterfaceStyle"
+    expires_after="M81">
+  <owner>javierrobles@chromium.org</owner>
+  <owner>rkgibson@google.com</owner>
+  <owner>bling-team@google.com</owner>
+  <summary>
+    [iOS] Used on iOS 13+ to report the usage of Light and Dark mode. This is
+    logged at startup and on each user interface style change.
+  </summary>
+</histogram>
+
 <histogram name="UserManager.LoginUserType" enum="UserType"
     expires_after="2020-01-20">
   <owner>achuith@chromium.org</owner>
@@ -161069,7 +161187,10 @@
       State does not exist
     </obsolete>
   </suffix>
+  <affected-histogram name="Android.FeatureModules.CachedAwakeInstallDuration"/>
   <affected-histogram name="Android.FeatureModules.CachedInstallDuration"/>
+  <affected-histogram
+      name="Android.FeatureModules.UncachedAwakeInstallDuration"/>
   <affected-histogram name="Android.FeatureModules.UncachedInstallDuration"/>
 </histogram_suffixes>
 
@@ -161081,6 +161202,17 @@
   <suffix name="test_dummy" label="Test Dummy Module"/>
   <suffix name="vr" label="Virtual Reality Module"/>
   <affected-histogram name="Android.FeatureModules.AvailabilityStatus"/>
+  <affected-histogram name="Android.FeatureModules.CachedAwakeInstallDuration"/>
+  <affected-histogram
+      name="Android.FeatureModules.CachedAwakeInstallDuration.Download"/>
+  <affected-histogram
+      name="Android.FeatureModules.CachedAwakeInstallDuration.Downloading"/>
+  <affected-histogram
+      name="Android.FeatureModules.CachedAwakeInstallDuration.Installing"/>
+  <affected-histogram
+      name="Android.FeatureModules.CachedAwakeInstallDuration.PendingDownload"/>
+  <affected-histogram
+      name="Android.FeatureModules.CachedAwakeInstallDuration.PendingInstall"/>
   <affected-histogram name="Android.FeatureModules.CachedInstallDuration"/>
   <affected-histogram
       name="Android.FeatureModules.CachedInstallDuration.Download"/>
@@ -161093,6 +161225,18 @@
   <affected-histogram
       name="Android.FeatureModules.CachedInstallDuration.PendingInstall"/>
   <affected-histogram name="Android.FeatureModules.InstallStatus"/>
+  <affected-histogram
+      name="Android.FeatureModules.UncachedAwakeInstallDuration"/>
+  <affected-histogram
+      name="Android.FeatureModules.UncachedAwakeInstallDuration.Download"/>
+  <affected-histogram
+      name="Android.FeatureModules.UncachedAwakeInstallDuration.Downloading"/>
+  <affected-histogram
+      name="Android.FeatureModules.UncachedAwakeInstallDuration.Installing"/>
+  <affected-histogram
+      name="Android.FeatureModules.UncachedAwakeInstallDuration.PendingDownload"/>
+  <affected-histogram
+      name="Android.FeatureModules.UncachedAwakeInstallDuration.PendingInstall"/>
   <affected-histogram name="Android.FeatureModules.UncachedInstallDuration"/>
   <affected-histogram
       name="Android.FeatureModules.UncachedInstallDuration.Download"/>
diff --git a/tools/perf/benchmarks/rendering.py b/tools/perf/benchmarks/rendering.py
index 3b6e491..20135bb 100644
--- a/tools/perf/benchmarks/rendering.py
+++ b/tools/perf/benchmarks/rendering.py
@@ -12,6 +12,30 @@
 from telemetry.web_perf import timeline_based_measurement
 
 
+RENDERING_BENCHMARK_UMA = [
+    'Event.Latency.ScrollBegin.Touch.TimeToScrollUpdateSwapBegin4',
+    'Event.Latency.ScrollUpdate.Touch.TimeToScrollUpdateSwapBegin4',
+    'Event.Latency.ScrollBegin.Wheel.TimeToScrollUpdateSwapBegin4',
+    'Event.Latency.ScrollUpdate.Wheel.TimeToScrollUpdateSwapBegin4',
+    'Graphics.Smoothness.Checkerboarding.CompositorAnimation',
+    'Graphics.Smoothness.Checkerboarding.MainThreadAnimation',
+    'Graphics.Smoothness.Checkerboarding.PinchZoom',
+    'Graphics.Smoothness.Checkerboarding.RAF',
+    'Graphics.Smoothness.Checkerboarding.TouchScroll',
+    'Graphics.Smoothness.Checkerboarding.Video',
+    'Graphics.Smoothness.Checkerboarding.WheelScroll',
+    'Graphics.Smoothness.Throughput.MainThread.MainThreadAnimation',
+    'Graphics.Smoothness.Throughput.MainThread.PinchZoom',
+    'Graphics.Smoothness.Throughput.MainThread.RAF',
+    'Graphics.Smoothness.Throughput.MainThread.TouchScroll',
+    'Graphics.Smoothness.Throughput.MainThread.WheelScroll',
+    'Graphics.Smoothness.Throughput.CompositorThread.CompositorAnimation',
+    'Graphics.Smoothness.Throughput.CompositorThread.PinchZoom',
+    'Graphics.Smoothness.Throughput.CompositorThread.TouchScroll',
+    'Graphics.Smoothness.Throughput.CompositorThread.WheelScroll',
+]
+
+
 class _RenderingBenchmark(perf_benchmark.PerfBenchmark):
   @classmethod
   def AddBenchmarkCommandLineArgs(cls, parser):
@@ -32,26 +56,7 @@
     category_filter = chrome_trace_category_filter.CreateLowOverheadFilter()
     options = timeline_based_measurement.Options(category_filter)
     options.config.chrome_trace_config.EnableUMAHistograms(
-        'Event.Latency.ScrollBegin.Touch.TimeToScrollUpdateSwapBegin4',
-        'Event.Latency.ScrollUpdate.Touch.TimeToScrollUpdateSwapBegin4',
-        'Event.Latency.ScrollBegin.Wheel.TimeToScrollUpdateSwapBegin4',
-        'Event.Latency.ScrollUpdate.Wheel.TimeToScrollUpdateSwapBegin4',
-        'Graphics.Smoothness.Checkerboarding.CompositorAnimation',
-        'Graphics.Smoothness.Checkerboarding.MainThreadAnimation',
-        'Graphics.Smoothness.Checkerboarding.PinchZoom',
-        'Graphics.Smoothness.Checkerboarding.RAF',
-        'Graphics.Smoothness.Checkerboarding.TouchScroll',
-        'Graphics.Smoothness.Checkerboarding.Video',
-        'Graphics.Smoothness.Checkerboarding.WheelScroll',
-        'Graphics.Smoothness.Throughput.MainThread.MainThreadAnimation',
-        'Graphics.Smoothness.Throughput.MainThread.PinchZoom',
-        'Graphics.Smoothness.Throughput.MainThread.RAF',
-        'Graphics.Smoothness.Throughput.MainThread.TouchScroll',
-        'Graphics.Smoothness.Throughput.MainThread.WheelScroll',
-        'Graphics.Smoothness.Throughput.CompositorThread.CompositorAnimation',
-        'Graphics.Smoothness.Throughput.CompositorThread.PinchZoom',
-        'Graphics.Smoothness.Throughput.CompositorThread.TouchScroll',
-        'Graphics.Smoothness.Throughput.CompositorThread.WheelScroll')
+        *RENDERING_BENCHMARK_UMA)
     options.SetTimelineBasedMetrics(['renderingMetric', 'umaMetric'])
     return options
 
diff --git a/tools/perf/cli_tools/pinboard/pinboard.py b/tools/perf/cli_tools/pinboard/pinboard.py
index 9db33e06..35e1ce6 100644
--- a/tools/perf/cli_tools/pinboard/pinboard.py
+++ b/tools/perf/cli_tools/pinboard/pinboard.py
@@ -76,6 +76,7 @@
     'load:news:irctc',
     'load:news:wikipedia:2018',
     'intent:coldish:bbc',
+    'Speedometer2',
 ])
 
 
diff --git a/tools/perf/contrib/cluster_telemetry/rendering_ct.py b/tools/perf/contrib/cluster_telemetry/rendering_ct.py
index e0b2670..17174181 100644
--- a/tools/perf/contrib/cluster_telemetry/rendering_ct.py
+++ b/tools/perf/contrib/cluster_telemetry/rendering_ct.py
@@ -9,6 +9,8 @@
 
 from core import perf_benchmark
 
+import benchmarks.rendering as rendering
+
 def ScrollToEndOfPage(action_runner):
   action_runner.Wait(1)
   with action_runner.CreateGestureInteraction('ScrollAction'):
@@ -41,7 +43,6 @@
     category_filter = chrome_trace_category_filter.CreateLowOverheadFilter()
     options = timeline_based_measurement.Options(category_filter)
     options.config.chrome_trace_config.EnableUMAHistograms(
-        'Event.Latency.ScrollBegin.Touch.TimeToScrollUpdateSwapBegin4',
-        'Event.Latency.ScrollUpdate.Touch.TimeToScrollUpdateSwapBegin4')
+        *rendering.RENDERING_BENCHMARK_UMA)
     options.SetTimelineBasedMetrics(['renderingMetric', 'umaMetric'])
     return options
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index cbf4ece..226c0a1 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -127,6 +127,9 @@
 # Benchmark: jetstream
 crbug.com/830600 [ android-nexus-5x android-webview ] jetstream/http://browserbench.org/JetStream/ [ Skip ]
 
+# Benchmark: jetstream2
+crbug.com/1002936 [ android-pixel-2 ] jetstream2/http://browserbench.org/JetStream/ [ Skip ]
+
 # Benchmark: loading.desktop
 crbug.com/723783 [ win ] loading.desktop/Orange_cold [ Skip ]
 crbug.com/723783 [ win ] loading.desktop/Orange_warm [ Skip ]
diff --git a/ui/chromeos/user_activity_power_manager_notifier.cc b/ui/chromeos/user_activity_power_manager_notifier.cc
index 39c64aa..f54e805 100644
--- a/ui/chromeos/user_activity_power_manager_notifier.cc
+++ b/ui/chromeos/user_activity_power_manager_notifier.cc
@@ -55,10 +55,11 @@
   if (connector) {
     // Treat fingerprint attempts as user activies to turn on the screen.
     // I.e., when user tried to use fingerprint to unlock.
-    connector->BindInterface(device::mojom::kServiceName, &fingerprint_ptr_);
+    connector->Connect(device::mojom::kServiceName,
+                       fingerprint_.BindNewPipeAndPassReceiver());
     device::mojom::FingerprintObserverPtr observer;
     fingerprint_observer_binding_.Bind(mojo::MakeRequest(&observer));
-    fingerprint_ptr_->AddFingerprintObserver(std::move(observer));
+    fingerprint_->AddFingerprintObserver(std::move(observer));
   }
 }
 
diff --git a/ui/chromeos/user_activity_power_manager_notifier.h b/ui/chromeos/user_activity_power_manager_notifier.h
index 6c9db45..a0a923b 100644
--- a/ui/chromeos/user_activity_power_manager_notifier.h
+++ b/ui/chromeos/user_activity_power_manager_notifier.h
@@ -10,6 +10,7 @@
 #include "base/time/time.h"
 #include "chromeos/dbus/power/power_manager_client.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "services/device/public/mojom/fingerprint.mojom.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 #include "ui/base/user_activity/user_activity_observer.h"
@@ -66,7 +67,7 @@
 
   UserActivityDetector* detector_;  // not owned
 
-  device::mojom::FingerprintPtr fingerprint_ptr_;
+  mojo::Remote<device::mojom::Fingerprint> fingerprint_;
   mojo::Binding<device::mojom::FingerprintObserver>
       fingerprint_observer_binding_;
 
diff --git a/ui/gfx/transform.cc b/ui/gfx/transform.cc
index 4612850..873388e 100644
--- a/ui/gfx/transform.cc
+++ b/ui/gfx/transform.cc
@@ -392,13 +392,16 @@
 }
 
 void Transform::FlattenTo2d() {
-  matrix_.set(2, 0, 0.0);
-  matrix_.set(2, 1, 0.0);
-  matrix_.set(0, 2, 0.0);
-  matrix_.set(1, 2, 0.0);
-  matrix_.set(2, 2, 1.0);
-  matrix_.set(3, 2, 0.0);
-  matrix_.set(2, 3, 0.0);
+  float tmp[16];
+  matrix_.asColMajorf(tmp);
+  tmp[2] = 0.0;
+  tmp[6] = 0.0;
+  tmp[8] = 0.0;
+  tmp[9] = 0.0;
+  tmp[10] = 1.0;
+  tmp[11] = 0.0;
+  tmp[14] = 0.0;
+  matrix_.setColMajorf(tmp);
 }
 
 bool Transform::IsFlat() const {
diff --git a/ui/gl/android/android_surface_control_compat.cc b/ui/gl/android/android_surface_control_compat.cc
index 9dd58ded..733a409 100644
--- a/ui/gl/android/android_surface_control_compat.cc
+++ b/ui/gl/android/android_surface_control_compat.cc
@@ -13,8 +13,10 @@
 #include "base/android/build_info.h"
 #include "base/atomic_sequence_num.h"
 #include "base/bind.h"
+#include "base/debug/crash_logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/no_destructor.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/trace_event/trace_event.h"
 #include "ui/gfx/color_space.h"
 
@@ -433,8 +435,17 @@
 void SurfaceControl::Transaction::SetColorSpace(
     const Surface& surface,
     const gfx::ColorSpace& color_space) {
+  auto data_space = ColorSpaceToADataSpace(color_space);
+
+  // Log the data space in crash keys for debugging crbug.com/997592.
+  static auto* kCrashKey = base::debug::AllocateCrashKeyString(
+      "data_space_for_buffer", base::debug::CrashKeySize::Size256);
+  auto crash_key_value = base::NumberToString(data_space);
+  base::debug::ScopedCrashKeyString scoped_crash_key(kCrashKey,
+                                                     crash_key_value);
+
   SurfaceControlMethods::Get().ASurfaceTransaction_setBufferDataSpaceFn(
-      transaction_, surface.surface(), ColorSpaceToADataSpace(color_space));
+      transaction_, surface.surface(), data_space);
 }
 
 void SurfaceControl::Transaction::SetOnCompleteCb(
diff --git a/ui/views/accessible_pane_view.cc b/ui/views/accessible_pane_view.cc
index 071f654d..10c6af27 100644
--- a/ui/views/accessible_pane_view.cc
+++ b/ui/views/accessible_pane_view.cc
@@ -77,6 +77,15 @@
 
   focus_manager_->SetFocusedView(initial_focus);
 
+  // TODO(pbos): Move this behavior into FocusManager. Focusing an unfocusable
+  // view should do something smart (move focus to its children or clear focus).
+  // DownloadItemView is an example (isn't focusable, has focusable children).
+  // See https://crbug.com/1000998.
+  // The initially-focused view may not be focusable (but one of its children
+  // might). We may need to advance focus here to make sure focus is on
+  // something focusable.
+  focus_manager_->AdvanceFocusIfNecessary();
+
   // If we already have pane focus, we're done.
   if (pane_has_focus_)
     return true;
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc
index ee4fbf41..f16770b 100644
--- a/ui/views/controls/menu/menu_controller.cc
+++ b/ui/views/controls/menu/menu_controller.cc
@@ -2459,22 +2459,36 @@
     // the parent menu item and not to the right.
     const bool layout_is_rtl = base::i18n::IsRTL();
     const bool create_on_right = prefer_leading != layout_is_rtl;
+
+    const int width_with_right_inset =
+        menu_config.touchable_menu_width + border_and_shadow_insets.right();
+    const int x_max = monitor_bounds.right() - width_with_right_inset;
+    const int x_left = item_bounds.x() - width_with_right_inset;
+    const int x_right = item_bounds.right() - border_and_shadow_insets.left();
     if (create_on_right) {
-      x = item_bounds.right() - border_and_shadow_insets.left();
-      if (monitor_bounds.width() != 0 && (x + menu_config.touchable_menu_width -
-                                              border_and_shadow_insets.right() >
-                                          monitor_bounds.right())) {
+      x = x_right;
+      if (monitor_bounds.width() == 0 || x_right <= x_max) {
+        // Enough room on the right, show normally.
+        x = x_right;
+      } else if (x_left >= monitor_bounds.x()) {
+        // Enough room on the left, show there.
         *is_leading = prefer_leading;
-        x = item_bounds.x() - menu_config.touchable_menu_width -
-            border_and_shadow_insets.right();
+        x = x_left;
+      } else {
+        // No room on either side. Flush the menu to the right edge.
+        x = x_max;
       }
     } else {
-      x = item_bounds.x() - menu_config.touchable_menu_width -
-          border_and_shadow_insets.right();
-      if (monitor_bounds.width() != 0 && x < monitor_bounds.x()) {
+      if (monitor_bounds.width() == 0 || x_left >= monitor_bounds.x()) {
+        // Enough room on the left, show normally.
+        x = x_left;
+      } else if (x_right <= x_max) {
+        // Enough room on the right, show there.
         *is_leading = !prefer_leading;
-        x = item_bounds.x() + menu_config.touchable_menu_width -
-            border_and_shadow_insets.left();
+        x = x_right;
+      } else {
+        // No room on either side. Flush the menu to the left edge.
+        x = monitor_bounds.x();
       }
     }
     y = item_bounds.y() - border_and_shadow_insets.top() -
diff --git a/ui/views/controls/menu/menu_controller_unittest.cc b/ui/views/controls/menu/menu_controller_unittest.cc
index 0890c287..b582cf0d 100644
--- a/ui/views/controls/menu/menu_controller_unittest.cc
+++ b/ui/views/controls/menu/menu_controller_unittest.cc
@@ -336,7 +336,8 @@
       MenuItemView::MenuPosition::kBestFit;
 };
 
-class MenuControllerTest : public ViewsTestBase {
+class MenuControllerTest : public ViewsTestBase,
+                           public testing::WithParamInterface<bool> {
  public:
   MenuControllerTest() = default;
 
@@ -344,6 +345,12 @@
 
   // ViewsTestBase:
   void SetUp() override {
+    if (testing::UnitTest::GetInstance()->current_test_info()->value_param()) {
+      // Setup right to left environment if necessary.
+      if (GetParam())
+        base::i18n::SetRTLForTesting(true);
+    }
+
     std::unique_ptr<DestructingTestViewsDelegate> views_delegate(
         new DestructingTestViewsDelegate());
     test_views_delegate_ = views_delegate.get();
@@ -378,13 +385,18 @@
                                                  &is_leading);
   }
 
-  gfx::Rect CalculateBubbleMenuBounds(const MenuBoundsOptions& options) {
+  gfx::Rect CalculateBubbleMenuBounds(const MenuBoundsOptions& options,
+                                      MenuItemView* menu_item) {
     SetUpMenuControllerForCalculateBounds(options);
     bool is_leading;
-    return menu_controller_->CalculateBubbleMenuBounds(menu_item_.get(), true,
+    return menu_controller_->CalculateBubbleMenuBounds(menu_item, true,
                                                        &is_leading);
   }
 
+  gfx::Rect CalculateBubbleMenuBounds(const MenuBoundsOptions& options) {
+    return CalculateBubbleMenuBounds(options, menu_item_.get());
+  }
+
 #if defined(USE_AURA)
   // Verifies that a non-nested menu fully closes when receiving an escape key.
   void TestAsyncEscapeKey() {
@@ -547,6 +559,32 @@
     EXPECT_TRUE(options.monitor_bounds.Contains(final_bounds));
   }
 
+  void TestSubmenuFitsOnScreen(MenuItemView* item,
+                               const gfx::Rect& monitor_bounds,
+                               const gfx::Rect& parent_bounds) {
+    MenuBoundsOptions options;
+    options.menu_anchor = MenuAnchorPosition::kBubbleAbove;
+    options.monitor_bounds = monitor_bounds;
+
+    // Adjust the final bounds to not include the shadow and border.
+    const gfx::Insets border_and_shadow_insets =
+        BubbleBorder::GetBorderAndShadowInsets(
+            MenuConfig::instance().touchable_menu_shadow_elevation);
+
+    MenuItemView* parent_item = item->GetParentMenuItem();
+    SubmenuView* sub_menu = parent_item->GetSubmenu();
+
+    parent_item->SetBoundsRect(parent_bounds);
+    sub_menu->ShowAt(owner(), parent_item->bounds(), false);
+    gfx::Rect final_bounds = CalculateBubbleMenuBounds(options, item);
+    final_bounds.Inset(border_and_shadow_insets);
+    sub_menu->Close();
+
+    EXPECT_TRUE(options.monitor_bounds.Contains(final_bounds))
+        << options.monitor_bounds.ToString() << " does not contain "
+        << final_bounds.ToString();
+  }
+
  protected:
   void SetPendingStateItem(MenuItemView* item) {
     menu_controller_->pending_state_.item = item;
@@ -790,6 +828,8 @@
   DISALLOW_COPY_AND_ASSIGN(MenuControllerTest);
 };
 
+INSTANTIATE_TEST_SUITE_P(, MenuControllerTest, testing::Bool());
+
 #if defined(USE_X11)
 // Tests that an event targeter which blocks events will be honored by the menu
 // event dispatcher.
@@ -1784,7 +1824,7 @@
 }
 
 // Test that menus show up on screen with non-zero sized anchors.
-TEST_F(MenuControllerTest, TestMenuFitsOnScreen) {
+TEST_P(MenuControllerTest, TestMenuFitsOnScreen) {
   const int display_size = 500;
   // Simulate multiple display layouts.
   for (int x = -1; x <= 1; x++)
@@ -1798,7 +1838,7 @@
 }
 
 // Test that menus show up on screen with zero sized anchors.
-TEST_F(MenuControllerTest, TestMenuFitsOnScreenSmallAnchor) {
+TEST_P(MenuControllerTest, TestMenuFitsOnScreenSmallAnchor) {
   const int display_size = 500;
   // Simulate multiple display layouts.
   for (int x = -1; x <= 1; x++)
@@ -1814,6 +1854,45 @@
     }
 }
 
+// Test that submenus are displayed within the screen bounds on smaller screens.
+TEST_P(MenuControllerTest, TestSubmenuFitsOnScreen) {
+  menu_controller()->set_use_touchable_layout(true);
+  MenuItemView* sub_item = menu_item()->GetSubmenu()->GetMenuItemAt(0);
+  sub_item->AppendMenuItemWithLabel(11, base::ASCIIToUTF16("Subitem.One"));
+
+  const int menu_width = MenuConfig::instance().touchable_menu_width;
+  const gfx::Size parent_size(menu_width, menu_width);
+
+  const int kDisplayWidth = parent_size.width() * 2;
+  const int kDisplayHeight = parent_size.height() * 2;
+
+  // Simulate multiple display layouts.
+  for (int x = -1; x <= 1; x++)
+    for (int y = -1; y <= 1; y++) {
+      const gfx::Rect monitor_bounds(x * kDisplayWidth, y * kDisplayHeight,
+                                     kDisplayWidth, kDisplayHeight);
+
+      const int x_min = monitor_bounds.x();
+      const int x_max = monitor_bounds.right() - parent_size.width();
+      const int x_mid = (x_min + x_max) / 2;
+
+      const int y_min = monitor_bounds.y();
+      const int y_max = monitor_bounds.bottom() - parent_size.height();
+      const int y_mid = (y_min + y_max) / 2;
+
+      TestSubmenuFitsOnScreen(sub_item, monitor_bounds,
+                              gfx::Rect(gfx::Point(x_min, y_min), parent_size));
+      TestSubmenuFitsOnScreen(sub_item, monitor_bounds,
+                              gfx::Rect(gfx::Point(x_max, y_min), parent_size));
+      TestSubmenuFitsOnScreen(sub_item, monitor_bounds,
+                              gfx::Rect(gfx::Point(x_mid, y_min), parent_size));
+      TestSubmenuFitsOnScreen(sub_item, monitor_bounds,
+                              gfx::Rect(gfx::Point(x_min, y_mid), parent_size));
+      TestSubmenuFitsOnScreen(sub_item, monitor_bounds,
+                              gfx::Rect(gfx::Point(x_min, y_max), parent_size));
+    }
+}
+
 // Test that a menu that was originally drawn below the anchor does not get
 // squished or move above the anchor when it grows vertically and horizontally
 // beyond the monitor bounds.
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
index 9f23530..5299d7d 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -25,6 +25,7 @@
 #include "ui/base/class_property.h"
 #include "ui/base/hit_test.h"
 #include "ui/base/ime/input_method.h"
+#include "ui/base/ui_base_features.h"
 #include "ui/compositor/layer.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/geometry/point_conversions.h"
@@ -98,6 +99,13 @@
     init_params.type = full_screen ? Widget::InitParams::TYPE_WINDOW
                                    : is_menu ? Widget::InitParams::TYPE_MENU
                                              : Widget::InitParams::TYPE_POPUP;
+#if defined(OS_WIN)
+    // For menus, on Windows versions that support drop shadow remove
+    // the standard frame in order to keep just the shadow.
+    if (features::IsFormControlsRefreshEnabled() &&
+        init_params.type == Widget::InitParams::TYPE_MENU)
+      init_params.remove_standard_frame = true;
+#endif
     init_params.bounds = bounds;
     init_params.ownership = Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET;
     init_params.layer_type = ui::LAYER_NOT_DRAWN;
diff --git a/ui/views/widget/widget_hwnd_utils.cc b/ui/views/widget/widget_hwnd_utils.cc
index 9edfa2c..0cccf60 100644
--- a/ui/views/widget/widget_hwnd_utils.cc
+++ b/ui/views/widget/widget_hwnd_utils.cc
@@ -9,6 +9,7 @@
 #include "base/command_line.h"
 #include "build/build_config.h"
 #include "ui/base/l10n/l10n_util_win.h"
+#include "ui/base/ui_base_features.h"
 #include "ui/base/ui_base_switches.h"
 #include "ui/views/widget/widget_delegate.h"
 #include "ui/views/win/hwnd_message_handler.h"
@@ -108,6 +109,15 @@
       break;
     case Widget::InitParams::TYPE_MENU:
       *style |= WS_POPUP;
+      if (features::IsFormControlsRefreshEnabled() &&
+          params.remove_standard_frame) {
+        // If the platform doesn't support drop shadow, decorate the Window
+        // with just a border.
+        if (ui::win::IsAeroGlassEnabled())
+          *style |= WS_THICKFRAME;
+        else
+          *style |= WS_BORDER;
+      }
       break;
     case Widget::InitParams::TYPE_TOOLTIP:
       *style |= WS_POPUP;