diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index 213a2c76..b747d2f9 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -32,7 +32,7 @@
 encouraged.
 
 If you are uncomfortable speaking up, or feel that your concerns are not being
-duly considered, you can email community@chromium.org, dknox@google.com, or
+duly considered, you can email community@chromium.org, dpranke@chromium.org, or
 groby@chromium.org to request involvement from a community manager. All
 concerns shared with community managers will be kept confidential, but you may
 also submit an anonymous report [here](https://docs.google.com/a/google.com/forms/d/e/1FAIpQLSe-LDjW9eIJ-TpI2poZxnGtU-SvUWkFZc8x0aiKGY1s7NKPdA/viewform?c=0&w=1).
@@ -76,9 +76,6 @@
 Participants warned to stop any harassing behavior are expected to comply
 immediately; failure to do so will result in an escalation of consequences.
 
-The decisions of the Chromium community managers may be appealed via
-community-appeals@chromium.org.
-
 ## Acknowledgements
 
 This Code of Conduct is based on the Geek Feminism Code of Conduct, the Django
diff --git a/DEPS b/DEPS
index 0cdaaacf..32efc19 100644
--- a/DEPS
+++ b/DEPS
@@ -121,7 +121,7 @@
   # 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': '0783aca7ba3189092855b373911cffc1b1303222',
+  'skia_revision': '5f5e1d57a4cef2f22e037fe7338dddff28ffa6a0',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -133,7 +133,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'd01c504e0c185ab2afa53dce85f9d0a6a31d761e',
+  'angle_revision': 'e923a63e312d7869c5c7642693e944ae91389f77',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -141,7 +141,7 @@
   # 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': '8f71f7311f29a2ef769d3d61bdbc73ecd6ceccb2',
+  'swiftshader_revision': '4b9e06d6a2df76966ca38ddba48985b71814c057',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -249,7 +249,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': 'd1be0e70770849c093154fd0892f0495328ed8c2',
+  'dawn_revision': '00976d0db13531acd7533ae7556a69d00c7fa5c6',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -1054,7 +1054,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' +  'e3e66f120fbb129f396292064cf279149883f1a2',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '71b40a07a007a995bee17af078c3543f447b41f0',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78',
@@ -1217,7 +1217,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'db52df17f0d012983dc281e4864c71485a86bd0e',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '69b761e52b10837c3b9f5f28ace9fe9704693784',
+    Var('webrtc_git') + '/src.git' + '@' + '167316b8338feb482f0c1d5239d28ed8a196331d',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1258,7 +1258,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f8840fffa6cc539692d142f76ec9aa22e7bd83b3',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@028687ffe06b8ca7682da5a7776a4403eb0a195a',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/OWNERS b/OWNERS
index 61637e8..daaa74e2 100644
--- a/OWNERS
+++ b/OWNERS
@@ -16,6 +16,8 @@
 per-file AUTHORS=*
 per-file BUILD.gn=file://build/OWNERS
 per-file codereview.settings=agable@chromium.org
+per-file CODE_OF_CONDUCT.md=dpranke@chromium.org
+per-file CODE_OF_CONDUCT.md=groby@chromium.org
 per-file DEPS=*
 per-file PRESUBMIT*.py=agrieve@chromium.org  # For .pydeps changes
 per-file PRESUBMIT*.py=dcheng@chromium.org
diff --git a/WATCHLISTS b/WATCHLISTS
index dfc2960..f6c6285 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -142,7 +142,8 @@
       'filepath': 'ash/',
     },
     'assistant': {
-      'filepath': 'ash/assistant/'\
+      'filepath': 'ash/app_list/views/assistant/'\
+                  '|ash/assistant/'\
                   '|chromeos/assistant/'\
                   '|chromeos/services/assistant/'\
                   '|chrome/browser/ui/ash/assistant/'
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwZoomTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwZoomTest.java
index 44be493..0314abdc 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwZoomTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwZoomTest.java
@@ -19,7 +19,6 @@
 import org.chromium.android_webview.AwContents;
 import org.chromium.android_webview.AwSettings;
 import org.chromium.base.ThreadUtils;
-import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.RetryOnFailure;
 
@@ -36,6 +35,7 @@
     private TestAwContentsClient mContentsClient;
     private AwContents mAwContents;
     private static final float MAXIMUM_SCALE = 2.0f;
+    private static final float EPSILON = 0.00001f;
 
     @Before
     public void setUp() throws Exception {
@@ -109,7 +109,10 @@
 
     private void waitForScaleToBecome(final float expectedScale) throws Throwable {
         AwActivityTestRule.pollInstrumentationThread(
-                () -> expectedScale == mActivityTestRule.getScaleOnUiThread(mAwContents));
+                ()
+                        -> Math.abs(expectedScale
+                                   - mActivityTestRule.getScaleOnUiThread(mAwContents))
+                        < EPSILON);
     }
 
     private void waitUntilCanNotZoom() throws Throwable {
@@ -154,10 +157,8 @@
     }
 
     @Test
-    @DisabledTest(message = "crbug.com/800015")
     @SmallTest
     @Feature({"AndroidWebView"})
-    @RetryOnFailure // Flaky (times out). See http://crbug.com/661879.
     public void testMagnification() throws Throwable {
         mActivityTestRule.getAwSettingsOnUiThread(mAwContents).setSupportZoom(true);
         runMagnificationTest();
@@ -166,10 +167,8 @@
     // According to Android CTS test, zoomIn/Out must work
     // even if supportZoom is turned off.
     @Test
-    @DisabledTest(message = "crbug.com/800015")
     @SmallTest
     @Feature({"AndroidWebView"})
-    @RetryOnFailure
     public void testMagnificationWithZoomSupportOff() throws Throwable {
         mActivityTestRule.getAwSettingsOnUiThread(mAwContents).setSupportZoom(false);
         runMagnificationTest();
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index f8c779f0..8bb4787 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1341,6 +1341,7 @@
     "//ui/base",
     "//ui/base:ui_data_pack",
     "//ui/base/ime",
+    "//ui/base/user_activity",
     "//ui/chromeos",
     "//ui/chromeos/events",
     "//ui/chromeos/resources",
@@ -1901,6 +1902,7 @@
     "//ui/base",
     "//ui/base:test_support",
     "//ui/base/ime",
+    "//ui/base/user_activity",
     "//ui/chromeos",
     "//ui/chromeos/events",
     "//ui/compositor",
diff --git a/ash/app_list/views/search_box_view.cc b/ash/app_list/views/search_box_view.cc
index b29d56f..74a3fa3f 100644
--- a/ash/app_list/views/search_box_view.cc
+++ b/ash/app_list/views/search_box_view.cc
@@ -27,6 +27,7 @@
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/metrics/user_metrics.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/ime/composition_text.h"
@@ -361,6 +362,8 @@
 }
 
 void SearchBoxView::ShowZeroStateSuggestions() {
+  base::RecordAction(
+      base::UserMetricsAction("AppList_ShowZeroStateSuggestions"));
   base::string16 empty_query;
   ContentsChanged(search_box(), empty_query);
 }
diff --git a/ash/app_list/views/search_result_answer_card_view.cc b/ash/app_list/views/search_result_answer_card_view.cc
index 557117d..8f619f0 100644
--- a/ash/app_list/views/search_result_answer_card_view.cc
+++ b/ash/app_list/views/search_result_answer_card_view.cc
@@ -169,6 +169,7 @@
 
     base::RecordAction(base::UserMetricsAction("SearchAnswer_UserInteraction"));
 
+    server_request_start_time_ = base::TimeTicks::Now();
     contents_->Navigate(*new_result->query_url());
   }
 
@@ -243,8 +244,9 @@
 
     SetAccessibleName(base::UTF8ToUTF16(title));
 
-    // TODO(https://crbug.com/894893): Consider where, how to record some
-    // SearchAnswer metrics regarding navigation results and timing.
+    UMA_HISTOGRAM_TIMES(
+        "Apps.AppList.AnswerCardSearchProvider.SearchAnswerNavigationTime",
+        base::TimeTicks::Now() - server_request_start_time_);
 
     is_current_navigation_valid_answer_card_ = true;
     answer_card_url_ = url;
@@ -267,6 +269,10 @@
     }
     SetPreferredSize(content_view->GetPreferredSize());
     container_->Update();
+
+    UMA_HISTOGRAM_TIMES(
+        "Apps.AppList.AnswerCardSearchProvider.SearchAnswerLoadingTime",
+        base::TimeTicks::Now() - server_request_start_time_);
   }
 
   void DidAutoResizeView(const gfx::Size& new_size) override {
@@ -301,6 +307,8 @@
   // Tracks the last time this view was made visible, if still visible.
   base::Optional<base::Time> last_shown_time_;
 
+  base::TimeTicks server_request_start_time_;
+
   DISALLOW_COPY_AND_ASSIGN(AnswerCardResultView);
 };
 
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn
index 4adb466..e5cfc885 100644
--- a/ash/public/cpp/BUILD.gn
+++ b/ash/public/cpp/BUILD.gn
@@ -235,6 +235,7 @@
 }
 
 source_set("test_support") {
+  testonly = true
   sources = [
     "immersive/immersive_fullscreen_controller_test_api.cc",
     "immersive/immersive_fullscreen_controller_test_api.h",
@@ -247,6 +248,7 @@
     "//base",
     "//services/service_manager/public/cpp",
     "//ui/aura",
+    "//ui/aura:test_support",
     "//ui/gfx",
     "//ui/keyboard:mojom",
     "//ui/views",
diff --git a/ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.cc b/ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.cc
index cbcebc5..b343010 100644
--- a/ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.cc
+++ b/ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.cc
@@ -6,11 +6,44 @@
 
 #include "ash/public/cpp/immersive/immersive_fullscreen_controller.h"
 #include "ash/public/cpp/immersive/immersive_fullscreen_controller_delegate.h"
+#include "base/run_loop.h"
 #include "ui/aura/env.h"
+#include "ui/aura/event_injector.h"
 #include "ui/aura/window.h"
+#include "ui/events/base_event_utils.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/views/widget/widget.h"
 
+namespace {
+
+// Update mouse location for |window|. For local window, update its aura::Env
+// directly. For remote window, update aura::Env by injecting a mouse move
+// event. EventInjector is used so that the Window Service side code under mash
+// sees the updated mouse location as well.
+void UpdateMouseLocation(aura::Window* window,
+                         const gfx::Point& screen_location,
+                         bool wait) {
+  if (window->env()->mode() == aura::Env::Mode::LOCAL) {
+    window->env()->SetLastMouseLocation(screen_location);
+    return;
+  }
+
+  ui::MouseEvent event(ui::ET_MOUSE_MOVED, screen_location, screen_location,
+                       ui::EventTimeForNow(), ui::EF_NONE, 0);
+  if (!wait) {
+    aura::EventInjector().Inject(window->GetHost(), &event);
+    return;
+  }
+
+  // Ensure the mouse event goes through when |wait| is set.
+  aura::EventInjector event_injector;
+  base::RunLoop run_loop;
+  event_injector.Inject(window->GetHost(), &event, run_loop.QuitClosure());
+  run_loop.Run();
+}
+
+}  // namespace
+
 namespace ash {
 
 ImmersiveFullscreenControllerTestApi::ImmersiveFullscreenControllerTestApi(
@@ -20,7 +53,8 @@
 ImmersiveFullscreenControllerTestApi::~ImmersiveFullscreenControllerTestApi() =
     default;
 
-void ImmersiveFullscreenControllerTestApi::SetupForTest() {
+void ImmersiveFullscreenControllerTestApi::SetupForTest(
+    bool wait_for_mouse_event) {
   immersive_fullscreen_controller_->animations_disabled_for_test_ = true;
 
   // Move the mouse off of the top-of-window views so that it does not keep the
@@ -34,10 +68,9 @@
       bottommost_in_screen = bounds_in_screen[i].bottom();
   }
   gfx::Point cursor_pos(0, bottommost_in_screen + 10);
-  immersive_fullscreen_controller_->widget()
-      ->GetNativeView()
-      ->env()
-      ->SetLastMouseLocation(cursor_pos);
+  UpdateMouseLocation(
+      immersive_fullscreen_controller_->widget()->GetNativeView(), cursor_pos,
+      wait_for_mouse_event);
   immersive_fullscreen_controller_->UpdateLocatedEventRevealedLock();
 }
 
diff --git a/ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.h b/ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.h
index d8fb97e..6d510fa 100644
--- a/ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.h
+++ b/ash/public/cpp/immersive/immersive_fullscreen_controller_test_api.h
@@ -30,8 +30,11 @@
   };
 
   // Disables animations and moves the mouse so that it is not over the
-  // top-of-window views for the sake of testing.
-  void SetupForTest();
+  // top-of-window views for the sake of testing. |wait_for_mouse_move| should
+  // normally be true to wait for the generated mouse events to go through under
+  // mash. It is provided for tests that call SetupForTest under the scope of
+  // TestMockTimeTaskRunner::ScopedContext that does not allow RunLoop::Run().
+  void SetupForTest(bool wait_for_mouse_event = true);
 
   bool IsTopEdgeHoverTimerRunning() const;
 
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc
index c772886..d5d6143 100644
--- a/ash/shelf/shelf_view_unittest.cc
+++ b/ash/shelf/shelf_view_unittest.cc
@@ -749,6 +749,31 @@
   EXPECT_FALSE(GetButtonByID(last_added)->visible());
 }
 
+TEST_F(ShelfViewTest, OverflowVisibleIndex) {
+  AddButtonsUntilOverflow();
+  ASSERT_TRUE(test_api_->IsOverflowButtonVisible());
+  const int last_visible_index = test_api_->GetLastVisibleIndex();
+
+  test_api_->ShowOverflowBubble();
+  auto overflow_test_api = std::make_unique<ShelfViewTestAPI>(
+      shelf_view_->overflow_bubble()->bubble_view()->shelf_view());
+  base::RunLoop().RunUntilIdle();
+
+  // Opening overflow doesn't change last visible index.
+  EXPECT_EQ(last_visible_index, test_api_->GetLastVisibleIndex());
+
+  test_api_->HideOverflowBubble();
+  AddAppShortcut();
+  test_api_->ShowOverflowBubble();
+  overflow_test_api = std::make_unique<ShelfViewTestAPI>(
+      shelf_view_->overflow_bubble()->bubble_view()->shelf_view());
+  base::RunLoop().RunUntilIdle();
+
+  // Adding another shortcut should go into overflow bubble and not change
+  // shelf index.
+  EXPECT_EQ(last_visible_index, test_api_->GetLastVisibleIndex());
+}
+
 // Adds one platform app button then adds app shortcut until overflow. Verifies
 // that the browser button gets hidden on overflow and last added app shortcut
 // is still visible.
@@ -907,10 +932,8 @@
   test_api_->RunMessageLoopUntilAnimationsDone();
   overflow_test_api.RunMessageLoopUntilAnimationsDone();
   ASSERT_TRUE(test_api_->IsShowingOverflowBubble());
-  // TODO(manucornet): Parts of this test fail with the new UI. Find out why
-  // and re-enable. https://crbug.com/891080
-  // EXPECT_FALSE(is_visible_on_shelf(last_visible_index, test_api_.get()));
-  // EXPECT_TRUE(is_visible_on_shelf(last_visible_index, &overflow_test_api));
+  EXPECT_FALSE(is_visible_on_shelf(last_visible_index, test_api_.get()));
+  EXPECT_TRUE(is_visible_on_shelf(last_visible_index, &overflow_test_api));
 
   // Verify that the item at |last_visible_index| is once again shown on the
   // main shelf after exiting tablet mode.
diff --git a/ash/system/network/network_icon.cc b/ash/system/network/network_icon.cc
index 92f758d..6cbe8c7 100644
--- a/ash/system/network/network_icon.cc
+++ b/ash/system/network/network_icon.cc
@@ -204,7 +204,7 @@
 gfx::Size GetSizeForIconType(IconType icon_type) {
   int size = kMenuIconSize;
   if (IsTrayIcon(icon_type)) {
-    size = kTrayIconSize;
+    size = kUnifiedTrayIconSize;
   } else if (icon_type == ICON_TYPE_DEFAULT_VIEW) {
     size = kUnifiedFeaturePodVectorIconSize;
   }
diff --git a/ash/system/network/tray_network_state_observer.cc b/ash/system/network/tray_network_state_observer.cc
index 0b82966..602433a 100644
--- a/ash/system/network/tray_network_state_observer.cc
+++ b/ash/system/network/tray_network_state_observer.cc
@@ -30,8 +30,7 @@
 namespace ash {
 
 TrayNetworkStateObserver::TrayNetworkStateObserver(Delegate* delegate)
-    : delegate_(delegate),
-      update_frequency_(kUpdateFrequencyMs) {
+    : delegate_(delegate), update_frequency_(kUpdateFrequencyMs) {
   if (ui::ScopedAnimationDurationScaleMode::duration_scale_mode() !=
       ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION) {
     update_frequency_ = 0;  // Send updates immediately for tests.
@@ -64,18 +63,8 @@
   SignalUpdate(false /* notify_a11y */);
 }
 
-// Any change to the Default (primary connected) network, including Strength
-// changes, should trigger a NetworkStateChanged update.
-void TrayNetworkStateObserver::DefaultNetworkChanged(
-    const chromeos::NetworkState* network) {
-  SignalUpdate(true /* notify_a11y */);
-}
-
-// Any change to the Connection State should trigger a NetworkStateChanged
-// update. This is important when both a VPN and a physical network are
-// connected.
-void TrayNetworkStateObserver::NetworkConnectionStateChanged(
-    const chromeos::NetworkState* network) {
+void TrayNetworkStateObserver::ActiveNetworksChanged(
+    const std::vector<const chromeos::NetworkState*>& active_networks) {
   SignalUpdate(true /* notify_a11y */);
 }
 
diff --git a/ash/system/network/tray_network_state_observer.h b/ash/system/network/tray_network_state_observer.h
index 2ec5e36..1f2d611 100644
--- a/ash/system/network/tray_network_state_observer.h
+++ b/ash/system/network/tray_network_state_observer.h
@@ -5,6 +5,8 @@
 #ifndef ASH_SYSTEM_NETWORK_TRAY_NETWORK_STATE_OBSERVER_H_
 #define ASH_SYSTEM_NETWORK_TRAY_NETWORK_STATE_OBSERVER_H_
 
+#include <vector>
+
 #include "base/macros.h"
 #include "base/timer/timer.h"
 #include "chromeos/network/network_state_handler_observer.h"
@@ -33,9 +35,8 @@
   // NetworkStateHandlerObserver
   void NetworkListChanged() override;
   void DeviceListChanged() override;
-  void DefaultNetworkChanged(const chromeos::NetworkState* network) override;
-  void NetworkConnectionStateChanged(
-      const chromeos::NetworkState* network) override;
+  void ActiveNetworksChanged(const std::vector<const chromeos::NetworkState*>&
+                                 active_networks) override;
   void NetworkPropertiesUpdated(const chromeos::NetworkState* network) override;
 
   // NetworkPortalDetector::Observer
diff --git a/ash/system/power/tray_power.cc b/ash/system/power/tray_power.cc
index 25c50ae..f67bf41 100644
--- a/ash/system/power/tray_power.cc
+++ b/ash/system/power/tray_power.cc
@@ -110,7 +110,7 @@
   icon_session_state_color_ = session_state;
 
   image_view()->SetImage(PowerStatus::GetBatteryImage(
-      info, kTrayIconSize, kTrayIconBackgroundColor,
+      info, kUnifiedTrayIconSize, kTrayIconBackgroundColor,
       TrayIconColor(session_state)));
 }
 
diff --git a/ash/wm/overview/overview_item.cc b/ash/wm/overview/overview_item.cc
index 28992bf..0bc90b9 100644
--- a/ash/wm/overview/overview_item.cc
+++ b/ash/wm/overview/overview_item.cc
@@ -199,10 +199,13 @@
   // |transform_window_|'s |minimized_widget| is non null because this only gets
   // called if we see the home launcher on enter (all windows are minimized).
   DCHECK(transform_window_.minimized_widget());
-  // The |item_widget_| will be shown when animation ends.
+  // The |item_widget_| and mask and shadow will be shown when animation ends.
+  // Update the mask after starting the animation since starting the animation
+  // lets the controller know we are in starting animation.
   FadeInWidgetAndMaybeSlideOnEnter(transform_window_.minimized_widget(),
                                    OVERVIEW_ANIMATION_ENTER_FROM_HOME_LAUNCHER,
                                    /*slide=*/true);
+  UpdateMaskAndShadow();
 }
 
 void OverviewItem::UpdateYPositionAndOpacity(
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc
index f806336..fe87b0ea 100644
--- a/ash/wm/overview/overview_session_unittest.cc
+++ b/ash/wm/overview/overview_session_unittest.cc
@@ -2216,8 +2216,8 @@
   ToggleOverview();
 }
 
-// Verify that the mask that is applied to add rounded corners in overview mode
-// is removed during animations and drags.
+// Test that the mask that is applied to add rounded corners in overview mode
+// is removed during animations.
 TEST_F(OverviewSessionTest, RoundedEdgeMaskVisibility) {
   std::unique_ptr<aura::Window> window1(CreateTestWindow());
   std::unique_ptr<aura::Window> window2(CreateTestWindow());
@@ -2225,14 +2225,63 @@
   ::wm::ActivateWindow(window2.get());
   ::wm::ActivateWindow(window1.get());
 
+  ui::ScopedAnimationDurationScaleMode test_duration_mode(
+      ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
+
+  // Test that entering overview mode normally will disable all the masks until
+  // the animation is complete.
+  EnterTabletMode();
+  ToggleOverview();
+  OverviewItem* item1 = GetWindowItemForWindow(0, window1.get());
+  OverviewItem* item2 = GetWindowItemForWindow(0, window2.get());
+  EXPECT_FALSE(HasMaskForItem(item1));
+  EXPECT_FALSE(HasMaskForItem(item2));
+  window1->layer()->GetAnimator()->StopAnimating();
+  window2->layer()->GetAnimator()->StopAnimating();
+  EXPECT_TRUE(HasMaskForItem(item1));
+  EXPECT_TRUE(HasMaskForItem(item2));
+
+  // Tests that entering overview mode with all windows minimized (launcher
+  // button pressed) will still disable all the masks until the animation is
+  // complete.
+  ToggleOverview();
+  wm::GetWindowState(window1.get())->Minimize();
+  wm::GetWindowState(window2.get())->Minimize();
+  ToggleOverview();
+  item1 = GetWindowItemForWindow(0, window1.get());
+  item2 = GetWindowItemForWindow(0, window2.get());
+  EXPECT_FALSE(HasMaskForItem(item1));
+  EXPECT_FALSE(HasMaskForItem(item2));
+  minimized_widget(item1)
+      ->GetNativeWindow()
+      ->layer()
+      ->GetAnimator()
+      ->StopAnimating();
+  minimized_widget(item2)
+      ->GetNativeWindow()
+      ->layer()
+      ->GetAnimator()
+      ->StopAnimating();
+  EXPECT_TRUE(HasMaskForItem(item1));
+  EXPECT_TRUE(HasMaskForItem(item2));
+
+  // Test that leaving overview mode cleans up properly.
+  ToggleOverview();
+}
+
+// Test that the mask that is applied to add rounded corners in overview mode
+// is removed during drags.
+TEST_F(OverviewSessionTest, RoundedEdgeMaskVisibilityDragging) {
+  std::unique_ptr<aura::Window> window1(CreateTestWindow());
+  std::unique_ptr<aura::Window> window2(CreateTestWindow());
+
+  ::wm::ActivateWindow(window2.get());
+  ::wm::ActivateWindow(window1.get());
+
   EnterTabletMode();
   ToggleOverview();
-  base::RunLoop().RunUntilIdle();
   OverviewItem* item1 = GetWindowItemForWindow(0, window1.get());
   OverviewItem* item2 = GetWindowItemForWindow(0, window2.get());
-  EXPECT_TRUE(HasMaskForItem(item1));
-  EXPECT_TRUE(HasMaskForItem(item2));
-
   ui::ScopedAnimationDurationScaleMode test_duration_mode(
       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
 
@@ -2245,7 +2294,6 @@
   generator->PressLeftButton();
   EXPECT_FALSE(window1->layer()->GetAnimator()->is_animating());
   EXPECT_FALSE(window2->layer()->GetAnimator()->is_animating());
-  base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(HasMaskForItem(item1));
   EXPECT_TRUE(HasMaskForItem(item2));
 
@@ -2263,12 +2311,8 @@
   // Verify that the mask is visble again after animation is finished.
   window1->layer()->GetAnimator()->StopAnimating();
   window2->layer()->GetAnimator()->StopAnimating();
-  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(HasMaskForItem(item1));
   EXPECT_TRUE(HasMaskForItem(item2));
-
-  // Test that leaving overview mode cleans up properly.
-  ToggleOverview();
 }
 
 TEST_F(OverviewSessionTest, NoRoundedEdgeMaskFor11Windows) {
diff --git a/base/mac/foundation_util.h b/base/mac/foundation_util.h
index 8aae308..fededa1 100644
--- a/base/mac/foundation_util.h
+++ b/base/mac/foundation_util.h
@@ -380,6 +380,9 @@
   return value_specific;
 }
 
+// Converts |path| to an autoreleased NSURL. Returns nil if |path| is empty.
+BASE_EXPORT NSURL* FilePathToNSURL(const FilePath& path);
+
 // Converts |path| to an autoreleased NSString. Returns nil if |path| is empty.
 BASE_EXPORT NSString* FilePathToNSString(const FilePath& path);
 
diff --git a/base/mac/foundation_util.mm b/base/mac/foundation_util.mm
index 3de70a26..a63b7431 100644
--- a/base/mac/foundation_util.mm
+++ b/base/mac/foundation_util.mm
@@ -436,6 +436,12 @@
       " instead";
 }
 
+NSURL* FilePathToNSURL(const FilePath& path) {
+  if (NSString* path_string = FilePathToNSString(path))
+    return [NSURL fileURLWithPath:path_string];
+  return nil;
+}
+
 NSString* FilePathToNSString(const FilePath& path) {
   if (path.empty())
     return nil;
diff --git a/base/mac/foundation_util_unittest.mm b/base/mac/foundation_util_unittest.mm
index 7b52574..f2b0accf 100644
--- a/base/mac/foundation_util_unittest.mm
+++ b/base/mac/foundation_util_unittest.mm
@@ -305,6 +305,12 @@
   EXPECT_FALSE(GetValueFromDictionary<CFStringRef>(test_dict, CFSTR("one")));
 }
 
+TEST(FoundationUtilTest, FilePathToNSURL) {
+  EXPECT_NSEQ(nil, FilePathToNSURL(FilePath()));
+  EXPECT_NSEQ([NSURL fileURLWithPath:@"/a/b"],
+              FilePathToNSURL(FilePath("/a/b")));
+}
+
 TEST(FoundationUtilTest, FilePathToNSString) {
   EXPECT_NSEQ(nil, FilePathToNSString(FilePath()));
   EXPECT_NSEQ(@"/a/b", FilePathToNSString(FilePath("/a/b")));
diff --git a/base/task/sequence_manager/test/lazy_thread_controller_for_test.cc b/base/task/sequence_manager/test/lazy_thread_controller_for_test.cc
deleted file mode 100644
index 7ab9968..0000000
--- a/base/task/sequence_manager/test/lazy_thread_controller_for_test.cc
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/task/sequence_manager/test/lazy_thread_controller_for_test.h"
-
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_current.h"
-#include "base/time/default_tick_clock.h"
-
-namespace base {
-namespace sequence_manager {
-
-LazyThreadControllerForTest::LazyThreadControllerForTest()
-    : ThreadControllerImpl(
-          MessageLoopCurrent::Get()->ToMessageLoopBaseDeprecated(),
-          nullptr,
-          DefaultTickClock::GetInstance()),
-      thread_ref_(PlatformThread::CurrentRef()) {
-  if (message_loop_base_)
-    task_runner_ = message_loop_base_->GetTaskRunner();
-}
-
-LazyThreadControllerForTest::~LazyThreadControllerForTest() = default;
-
-void LazyThreadControllerForTest::EnsureMessageLoop() {
-  if (message_loop_base_)
-    return;
-  DCHECK(RunsTasksInCurrentSequence());
-  message_loop_base_ = MessageLoopCurrent::Get()->ToMessageLoopBaseDeprecated();
-  DCHECK(message_loop_base_);
-  task_runner_ = message_loop_base_->GetTaskRunner();
-  if (pending_observer_) {
-    RunLoop::AddNestingObserverOnCurrentThread(this);
-    pending_observer_ = false;
-  }
-  if (pending_default_task_runner_) {
-    ThreadControllerImpl::SetDefaultTaskRunner(pending_default_task_runner_);
-    pending_default_task_runner_ = nullptr;
-  }
-}
-
-bool LazyThreadControllerForTest::HasMessageLoop() {
-  return !!message_loop_base_;
-}
-
-void LazyThreadControllerForTest::AddNestingObserver(
-    RunLoop::NestingObserver* observer) {
-  // While |observer| _could_ be associated with the current thread regardless
-  // of the presence of a MessageLoop, the association is delayed until
-  // EnsureMessageLoop() is invoked. This works around a state issue where
-  // otherwise many tests fail because of the following sequence:
-  //   1) blink::scheduler::CreateRendererSchedulerForTests()
-  //       -> SequenceManager::SequenceManager()
-  //       -> LazySchedulerMessageLoopDelegateForTests::AddNestingObserver()
-  //   2) Any test framework with a MessageLoop member (and not caring
-  //      about the blink scheduler) does:
-  //        blink::scheduler::GetSingleThreadTaskRunnerForTesting()->PostTask(
-  //            FROM_HERE, an_init_task_with_a_nested_loop);
-  //        RunLoop.RunUntilIdle();
-  //   3) |a_task_with_a_nested_loop| triggers
-  //          SequenceManager::OnBeginNestedLoop() which:
-  //            a) flags any_thread().is_nested = true;
-  //            b) posts a task to self, which triggers:
-  //                 LazySchedulerMessageLoopDelegateForTests::PostDelayedTask()
-  //   4) This self-task in turn triggers SequenceManager::DoWork()
-  //      which expects to be the only one to trigger nested loops (doesn't
-  //      support SequenceManager::OnBeginNestedLoop() being invoked before
-  //      it kicks in), resulting in it hitting:
-  //      DCHECK_EQ(any_thread().is_nested, delegate_->IsNested()); (1 vs 0).
-  // TODO(skyostil): fix this convolution as part of http://crbug.com/495659.
-  ThreadControllerImpl::nesting_observer_ = observer;
-  if (!HasMessageLoop()) {
-    DCHECK(!pending_observer_);
-    pending_observer_ = true;
-    return;
-  }
-  RunLoop::AddNestingObserverOnCurrentThread(this);
-}
-
-void LazyThreadControllerForTest::RemoveNestingObserver(
-    RunLoop::NestingObserver* observer) {
-  ThreadControllerImpl::nesting_observer_ = nullptr;
-  if (!HasMessageLoop()) {
-    DCHECK(pending_observer_);
-    pending_observer_ = false;
-    return;
-  }
-  // TODO(altimin): Refactor this to use STE::LifetimeObserver.
-  // We can't use message_loop_base_->IsBoundToCurrentThread as
-  // |message_loop_base_| might be deleted.
-  if (MessageLoopCurrent::Get()->ToMessageLoopBaseDeprecated() !=
-      message_loop_base_)
-    return;
-  RunLoop::RemoveNestingObserverOnCurrentThread(this);
-}
-
-bool LazyThreadControllerForTest::RunsTasksInCurrentSequence() {
-  return thread_ref_ == PlatformThread::CurrentRef();
-}
-
-void LazyThreadControllerForTest::ScheduleWork() {
-  EnsureMessageLoop();
-  ThreadControllerImpl::ScheduleWork();
-}
-
-void LazyThreadControllerForTest::SetNextDelayedDoWork(LazyNow* lazy_now,
-                                                       TimeTicks run_time) {
-  EnsureMessageLoop();
-  ThreadControllerImpl::SetNextDelayedDoWork(lazy_now, run_time);
-}
-
-void LazyThreadControllerForTest::SetDefaultTaskRunner(
-    scoped_refptr<SingleThreadTaskRunner> task_runner) {
-  if (!HasMessageLoop()) {
-    pending_default_task_runner_ = task_runner;
-    return;
-  }
-  ThreadControllerImpl::SetDefaultTaskRunner(task_runner);
-}
-
-void LazyThreadControllerForTest::RestoreDefaultTaskRunner() {
-  pending_default_task_runner_ = nullptr;
-  // We can't use message_loop_base_->IsBoundToCurrentThread as
-  // |message_loop_base_| might be deleted.
-  if (HasMessageLoop() &&
-      MessageLoopCurrent::Get()->ToMessageLoopBaseDeprecated() ==
-          message_loop_base_) {
-    ThreadControllerImpl::RestoreDefaultTaskRunner();
-  }
-}
-
-}  // namespace sequence_manager
-}  // namespace base
diff --git a/base/task/sequence_manager/test/lazy_thread_controller_for_test.h b/base/task/sequence_manager/test/lazy_thread_controller_for_test.h
deleted file mode 100644
index 6cc0e523..0000000
--- a/base/task/sequence_manager/test/lazy_thread_controller_for_test.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_TASK_SEQUENCE_MANAGER_TEST_LAZY_THREAD_CONTROLLER_FOR_TEST_H_
-#define BASE_TASK_SEQUENCE_MANAGER_TEST_LAZY_THREAD_CONTROLLER_FOR_TEST_H_
-
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/task/sequence_manager/thread_controller_impl.h"
-#include "base/threading/platform_thread.h"
-
-namespace base {
-namespace sequence_manager {
-
-// This class connects the scheduler to a MessageLoop, but unlike
-// ThreadControllerImpl it allows the message loop to be created lazily
-// after the scheduler has been brought up. This is needed in testing scenarios
-// where Blink is initialized before a MessageLoop has been created.
-//
-// TODO(skyostil): Fix the relevant test suites and remove this class
-// (crbug.com/495659).
-class LazyThreadControllerForTest : public internal::ThreadControllerImpl {
- public:
-  LazyThreadControllerForTest();
-  ~LazyThreadControllerForTest() override;
-
-  // internal::ThreadControllerImpl:
-  void AddNestingObserver(RunLoop::NestingObserver* observer) override;
-  void RemoveNestingObserver(RunLoop::NestingObserver* observer) override;
-  bool RunsTasksInCurrentSequence() override;
-  void ScheduleWork() override;
-  void SetNextDelayedDoWork(LazyNow* lazy_now, TimeTicks run_time) override;
-  void SetDefaultTaskRunner(
-      scoped_refptr<SingleThreadTaskRunner> task_runner) override;
-  void RestoreDefaultTaskRunner() override;
-
- private:
-  bool HasMessageLoop();
-  void EnsureMessageLoop();
-
-  PlatformThreadRef thread_ref_;
-
-  bool pending_observer_ = false;
-  scoped_refptr<SingleThreadTaskRunner> pending_default_task_runner_;
-
-  DISALLOW_COPY_AND_ASSIGN(LazyThreadControllerForTest);
-};
-
-}  // namespace sequence_manager
-}  // namespace base
-
-#endif  // BASE_TASK_SEQUENCE_MANAGER_TEST_LAZY_THREAD_CONTROLLER_FOR_TEST_H_
diff --git a/base/task/task_scheduler/platform_native_worker_pool_win.cc b/base/task/task_scheduler/platform_native_worker_pool_win.cc
index dd58433..0529347 100644
--- a/base/task/task_scheduler/platform_native_worker_pool_win.cc
+++ b/base/task/task_scheduler/platform_native_worker_pool_win.cc
@@ -60,9 +60,8 @@
 #endif
 }
 
-void PlatformNativeWorkerPoolWin::ReEnqueueSequence(
-    SequenceAndTransaction sequence_and_transaction,
-    bool is_changing_pools) {
+void PlatformNativeWorkerPoolWin::ReEnqueueSequenceChangingPool(
+    SequenceAndTransaction sequence_and_transaction) {
   OnCanScheduleSequence(std::move(sequence_and_transaction));
 }
 
@@ -82,8 +81,10 @@
   sequence = worker_pool->task_tracker_->RunAndPopNextTask(
       std::move(sequence.get()), worker_pool);
 
-  // Re-enqueue sequence and then submit another task to the Windows thread
-  // pool.
+  // Reenqueue sequence and then submit another task to the Windows thread pool.
+  //
+  // TODO(fdoray): Use |delegate_| to decide in which pool the Sequence should
+  // be reenqueued.
   if (sequence)
     worker_pool->OnCanScheduleSequence(std::move(sequence));
 
diff --git a/base/task/task_scheduler/platform_native_worker_pool_win.h b/base/task/task_scheduler/platform_native_worker_pool_win.h
index ed663937..2d080aa 100644
--- a/base/task/task_scheduler/platform_native_worker_pool_win.h
+++ b/base/task/task_scheduler/platform_native_worker_pool_win.h
@@ -42,8 +42,8 @@
 
   // SchedulerWorkerPool:
   void JoinForTesting() override;
-  void ReEnqueueSequence(SequenceAndTransaction sequence_and_transaction,
-                         bool is_changing_pools) override;
+  void ReEnqueueSequenceChangingPool(
+      SequenceAndTransaction sequence_and_transaction) override;
 
  private:
   // Callback that gets run by |pool_|. It runs a task off the next sequence on
diff --git a/base/task/task_scheduler/scheduler_worker_pool.h b/base/task/task_scheduler/scheduler_worker_pool.h
index a469719..e308829 100644
--- a/base/task/task_scheduler/scheduler_worker_pool.h
+++ b/base/task/task_scheduler/scheduler_worker_pool.h
@@ -27,10 +27,9 @@
 
     // Invoked when the Sequence in |sequence_and_transaction| is non-empty
     // after the SchedulerWorkerPool has run a task from it. The implementation
-    // must enqueue the Sequence in the appropriate priority queue, depending
-    // on the Sequence's traits.
-    virtual void ReEnqueueSequence(
-        SequenceAndTransaction sequence_and_transaction) = 0;
+    // must return the pool in which the Sequence should be reenqueued.
+    virtual SchedulerWorkerPool* GetWorkerPoolForTraits(
+        const TaskTraits& traits) = 0;
   };
 
   ~SchedulerWorkerPool() override;
@@ -62,12 +61,10 @@
   // task during JoinForTesting(). This can only be called once.
   virtual void JoinForTesting() = 0;
 
-  // Enqueues the Sequence in |sequence_and_transaction| in the worker pool's
-  // priority queue, then wakes up a worker if |is_changing_pools|, i.e. if the
-  // Sequence came from a different worker pool.
-  virtual void ReEnqueueSequence(
-      SequenceAndTransaction sequence_and_transaction,
-      bool is_changing_pools) = 0;
+  // Enqueues the Sequence in |sequence_and_transaction| which was previously in
+  // a different worker pool into this worker pool's priority queue.
+  virtual void ReEnqueueSequenceChangingPool(
+      SequenceAndTransaction sequence_and_transaction) = 0;
 
   // Called when the Sequence in |sequence_and_transaction| can be scheduled.
   // It is expected that TaskTracker::RunNextTask() will be called with
diff --git a/base/task/task_scheduler/scheduler_worker_pool_impl.cc b/base/task/task_scheduler/scheduler_worker_pool_impl.cc
index e7aca3c..8c7ace25 100644
--- a/base/task/task_scheduler/scheduler_worker_pool_impl.cc
+++ b/base/task/task_scheduler/scheduler_worker_pool_impl.cc
@@ -520,12 +520,10 @@
   workers_.clear();
 }
 
-void SchedulerWorkerPoolImpl::ReEnqueueSequence(
-    SequenceAndTransaction sequence_and_transaction,
-    bool is_changing_pools) {
+void SchedulerWorkerPoolImpl::ReEnqueueSequenceChangingPool(
+    SequenceAndTransaction sequence_and_transaction) {
   PushSequenceToPriorityQueue(std::move(sequence_and_transaction));
-  if (is_changing_pools)
-    WakeUpOneWorker();
+  WakeUpOneWorker();
 }
 
 size_t SchedulerWorkerPoolImpl::NumberOfWorkersForTesting() const {
@@ -717,8 +715,19 @@
 
 void SchedulerWorkerPoolImpl::SchedulerWorkerDelegateImpl::ReEnqueueSequence(
     scoped_refptr<Sequence> sequence) {
-  outer_->delegate_->ReEnqueueSequence(
-      SequenceAndTransaction::FromSequence(std::move(sequence)));
+  auto sequence_and_transaction =
+      SequenceAndTransaction::FromSequence(std::move(sequence));
+
+  SchedulerWorkerPool* destination_pool =
+      outer_->delegate_->GetWorkerPoolForTraits(
+          sequence_and_transaction.transaction.traits());
+
+  if (outer_ == destination_pool) {
+    outer_->PushSequenceToPriorityQueue(std::move(sequence_and_transaction));
+  } else {
+    destination_pool->ReEnqueueSequenceChangingPool(
+        std::move(sequence_and_transaction));
+  }
 }
 
 TimeDelta
diff --git a/base/task/task_scheduler/scheduler_worker_pool_impl.h b/base/task/task_scheduler/scheduler_worker_pool_impl.h
index 0ee662f..f9c407b 100644
--- a/base/task/task_scheduler/scheduler_worker_pool_impl.h
+++ b/base/task/task_scheduler/scheduler_worker_pool_impl.h
@@ -101,8 +101,8 @@
 
   // SchedulerWorkerPool:
   void JoinForTesting() override;
-  void ReEnqueueSequence(SequenceAndTransaction sequence_and_transaction,
-                         bool is_changing_pools) override;
+  void ReEnqueueSequenceChangingPool(
+      SequenceAndTransaction sequence_and_transaction) override;
 
   const HistogramBase* num_tasks_before_detach_histogram() const {
     return num_tasks_before_detach_histogram_;
diff --git a/base/task/task_scheduler/scheduler_worker_pool_impl_unittest.cc b/base/task/task_scheduler/scheduler_worker_pool_impl_unittest.cc
index 13ff4312..ada1f906e 100644
--- a/base/task/task_scheduler/scheduler_worker_pool_impl_unittest.cc
+++ b/base/task/task_scheduler/scheduler_worker_pool_impl_unittest.cc
@@ -126,9 +126,9 @@
 
  private:
   // SchedulerWorkerPool::Delegate:
-  void ReEnqueueSequence(
-      SequenceAndTransaction sequence_and_transaction) override {
-    worker_pool_->ReEnqueueSequence(std::move(sequence_and_transaction), false);
+  SchedulerWorkerPool* GetWorkerPoolForTraits(
+      const TaskTraits& traits) override {
+    return worker_pool_.get();
   }
 
   DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolImplTestBase);
diff --git a/base/task/task_scheduler/scheduler_worker_pool_unittest.cc b/base/task/task_scheduler/scheduler_worker_pool_unittest.cc
index 03efefa4..861e22cd 100644
--- a/base/task/task_scheduler/scheduler_worker_pool_unittest.cc
+++ b/base/task/task_scheduler/scheduler_worker_pool_unittest.cc
@@ -164,9 +164,9 @@
 
  private:
   // SchedulerWorkerPool::Delegate:
-  void ReEnqueueSequence(
-      SequenceAndTransaction sequence_and_transaction) override {
-    worker_pool_->ReEnqueueSequence(std::move(sequence_and_transaction), false);
+  SchedulerWorkerPool* GetWorkerPoolForTraits(
+      const TaskTraits& traits) override {
+    return worker_pool_.get();
   }
 
   TrackedRefFactory<SchedulerWorkerPool::Delegate> tracked_ref_factory_;
diff --git a/base/task/task_scheduler/task_scheduler_impl.cc b/base/task/task_scheduler/task_scheduler_impl.cc
index 264d791f..f483f47 100644
--- a/base/task/task_scheduler/task_scheduler_impl.cc
+++ b/base/task/task_scheduler/task_scheduler_impl.cc
@@ -217,7 +217,7 @@
   // This method does not support getting the maximum number of BEST_EFFORT
   // tasks that can run concurrently in a pool.
   DCHECK_NE(traits.priority(), TaskPriority::BEST_EFFORT);
-  return GetWorkerPoolForTraits(traits)
+  return GetWorkerPoolImplForTraits(traits)
       ->GetMaxConcurrentNonBlockedTasksDeprecated();
 }
 
@@ -255,18 +255,6 @@
   task_tracker_->SetExecutionFenceEnabled(execution_fence_enabled);
 }
 
-void TaskSchedulerImpl::ReEnqueueSequence(
-    SequenceAndTransaction sequence_and_transaction) {
-  const TaskTraits new_traits = SetUserBlockingPriorityIfNeeded(
-      sequence_and_transaction.transaction.traits());
-  SchedulerWorkerPool* const destination_worker_pool =
-      GetWorkerPoolForTraits(new_traits);
-  const bool is_changing_pools =
-      !destination_worker_pool->IsBoundToCurrentThread();
-  destination_worker_pool->ReEnqueueSequence(
-      std::move(sequence_and_transaction), is_changing_pools);
-}
-
 bool TaskSchedulerImpl::PostTaskWithSequence(Task task,
                                              scoped_refptr<Sequence> sequence) {
   // Use CHECK instead of DCHECK to crash earlier. See http://crbug.com/711167
@@ -305,7 +293,7 @@
 
 bool TaskSchedulerImpl::IsRunningPoolWithTraits(
     const TaskTraits& traits) const {
-  return GetWorkerPoolForTraits(traits)->IsBoundToCurrentThread();
+  return GetWorkerPoolImplForTraits(traits)->IsBoundToCurrentThread();
 }
 
 void TaskSchedulerImpl::UpdatePriority(scoped_refptr<Sequence> sequence,
@@ -314,10 +302,10 @@
       SequenceAndTransaction::FromSequence(std::move(sequence));
 
   SchedulerWorkerPoolImpl* const current_worker_pool =
-      GetWorkerPoolForTraits(sequence_and_transaction.transaction.traits());
+      GetWorkerPoolImplForTraits(sequence_and_transaction.transaction.traits());
   sequence_and_transaction.transaction.UpdatePriority(priority);
   SchedulerWorkerPoolImpl* const new_worker_pool =
-      GetWorkerPoolForTraits(sequence_and_transaction.transaction.traits());
+      GetWorkerPoolImplForTraits(sequence_and_transaction.transaction.traits());
 
   if (new_worker_pool == current_worker_pool) {
     // |sequence|'s position needs to be updated within its current pool.
@@ -329,18 +317,13 @@
         current_worker_pool->RemoveSequence(sequence_and_transaction.sequence);
     if (sequence_was_found) {
       DCHECK(sequence_and_transaction.sequence);
-      // |sequence| was removed from |current_worker_pool| and is being
-      // reenqueued into |new_worker_pool|, a different pool; set argument
-      // |is_changing_pools| to true to notify |new_worker_pool| that
-      // |sequence| came from a different pool.
-      const bool is_changing_pools = true;
-      new_worker_pool->ReEnqueueSequence(std::move(sequence_and_transaction),
-                                         is_changing_pools);
+      new_worker_pool->ReEnqueueSequenceChangingPool(
+          std::move(sequence_and_transaction));
     }
   }
 }
 
-SchedulerWorkerPoolImpl* TaskSchedulerImpl::GetWorkerPoolForTraits(
+SchedulerWorkerPoolImpl* TaskSchedulerImpl::GetWorkerPoolImplForTraits(
     const TaskTraits& traits) {
   if (traits.priority() == TaskPriority::BEST_EFFORT &&
       background_pool_.has_value()) {
@@ -349,6 +332,11 @@
   return &foreground_pool_.value();
 }
 
+SchedulerWorkerPool* TaskSchedulerImpl::GetWorkerPoolForTraits(
+    const TaskTraits& traits) {
+  return GetWorkerPoolImplForTraits(traits);
+}
+
 TaskTraits TaskSchedulerImpl::SetUserBlockingPriorityIfNeeded(
     const TaskTraits& traits) const {
   return all_tasks_user_blocking_.IsSet()
diff --git a/base/task/task_scheduler/task_scheduler_impl.h b/base/task/task_scheduler/task_scheduler_impl.h
index 46896fb..2528653 100644
--- a/base/task/task_scheduler/task_scheduler_impl.h
+++ b/base/task/task_scheduler/task_scheduler_impl.h
@@ -100,10 +100,14 @@
 
  private:
   // Returns the worker pool that runs Tasks with |traits|.
-  SchedulerWorkerPoolImpl* GetWorkerPoolForTraits(const TaskTraits& traits);
-  const SchedulerWorkerPoolImpl* GetWorkerPoolForTraits(
+  // TODO(fdoray): Move all methods used by TaskSchedulerImpl to the
+  // SchedulerWorkerPool interface and remove the SchedulerWorkerPool*Impl*
+  // accessors.
+  SchedulerWorkerPoolImpl* GetWorkerPoolImplForTraits(const TaskTraits& traits);
+  const SchedulerWorkerPoolImpl* GetWorkerPoolImplForTraits(
       const TaskTraits& traits) const {
-    return const_cast<TaskSchedulerImpl*>(this)->GetWorkerPoolForTraits(traits);
+    return const_cast<TaskSchedulerImpl*>(this)->GetWorkerPoolImplForTraits(
+        traits);
   }
 
   // Returns |traits|, with priority set to TaskPriority::USER_BLOCKING if
@@ -113,8 +117,8 @@
   void ReportHeartbeatMetrics() const;
 
   // SchedulerWorkerPool::Delegate:
-  void ReEnqueueSequence(
-      SequenceAndTransaction sequence_and_transaction) override;
+  SchedulerWorkerPool* GetWorkerPoolForTraits(
+      const TaskTraits& traits) override;
 
   // SchedulerTaskRunnerDelegate:
   bool PostTaskWithSequence(Task task,
diff --git a/base/task/task_scheduler/tracked_ref.h b/base/task/task_scheduler/tracked_ref.h
index 218fffc..2949220 100644
--- a/base/task/task_scheduler/tracked_ref.h
+++ b/base/task/task_scheduler/tracked_ref.h
@@ -103,6 +103,10 @@
 
   explicit operator bool() const { return ptr_ != nullptr; }
 
+  bool operator==(const void* compared_ptr) const {
+    return ptr_ == compared_ptr;
+  }
+
  private:
   friend class TrackedRefFactory<T>;
 
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn
index 1266b4b..513b172 100644
--- a/base/test/BUILD.gn
+++ b/base/test/BUILD.gn
@@ -30,8 +30,6 @@
     "../memory/fake_memory_pressure_monitor.h",
     "../task/sequence_manager/test/fake_task.cc",
     "../task/sequence_manager/test/fake_task.h",
-    "../task/sequence_manager/test/lazy_thread_controller_for_test.cc",
-    "../task/sequence_manager/test/lazy_thread_controller_for_test.h",
     "../task/sequence_manager/test/mock_time_domain.cc",
     "../task/sequence_manager/test/mock_time_domain.h",
     "../task/sequence_manager/test/sequence_manager_for_test.cc",
diff --git a/build/util/lastchange.py b/build/util/lastchange.py
index fb17d04..fd55ce3 100755
--- a/build/util/lastchange.py
+++ b/build/util/lastchange.py
@@ -7,23 +7,20 @@
 lastchange.py -- Chromium revision fetching utility.
 """
 
-import argparse
-import collections
+import re
 import logging
+import argparse
 import os
 import subprocess
 import sys
 
-VersionInfo = collections.namedtuple("VersionInfo",
-                                     ("revision_id", "revision", "timestamp"))
+class VersionInfo(object):
+  def __init__(self, revision_id, full_revision_string, timestamp):
+    self.revision_id = revision_id
+    self.revision = full_revision_string
+    self.timestamp = timestamp
 
-class GitError(Exception):
-  pass
 
-# This function exists for compatibility with logic outside this
-# repository that uses this file as a library.
-# TODO(eliribble) remove this function after it has been ported into
-# the repositories that depend on it
 def RunGitCommand(directory, command):
   """
   Launches git subcommand.
@@ -52,97 +49,50 @@
     return None
 
 
-def _RunGitCommand(directory, command):
+def FetchGitRevision(directory, filter):
   """
-  Launches git subcommand.
+  Fetch the Git hash (and Cr-Commit-Position if any) for a given directory.
+
+  Errors are swallowed.
 
   Returns:
-    The stripped stdout of the git command.
-  Raises:
-    GitError on failure, including a nonzero return code.
+    A VersionInfo object or None on error.
   """
-  command = ['git'] + command
-  # Force shell usage under cygwin. This is a workaround for
-  # mysterious loss of cwd while invoking cygwin's git.
-  # We can't just pass shell=True to Popen, as under win32 this will
-  # cause CMD to be used, while we explicitly want a cygwin shell.
-  if sys.platform == 'cygwin':
-    command = ['sh', '-c', ' '.join(command)]
-  try:
-    logging.info("Executing '%s' in %s", ' '.join(command), directory)
-    proc = subprocess.Popen(command,
-                            stdout=subprocess.PIPE,
-                            stderr=subprocess.PIPE,
-                            cwd=directory,
-                            shell=(sys.platform=='win32'))
-    stdout, stderr = proc.communicate()
-    stdout = stdout.strip()
-    logging.debug("returncode: %d", proc.returncode)
-    logging.debug("stdout: %s", stdout)
-    logging.debug("stderr: %s", stderr)
-    if proc.returncode != 0 or not stdout:
-      raise GitError((
-          "Git command 'git {}' in {} failed: "
-          "rc={}, stdout='{}' stderr='{}'").format(
-          " ".join(command), directory, proc.returncode, stdout, stderr))
-    return stdout
-  except OSError as e:
-    raise GitError("Git command 'git {}' in {} failed: {}".format(
-        " ".join(command), directory, e))
+  hsh = ''
+  git_args = ['log', '-1', '--format=%H %ct']
+  if filter is not None:
+    git_args.append('--grep=' + filter)
+  proc = RunGitCommand(directory, git_args)
+  if proc:
+    output = proc.communicate()[0].strip()
+    if proc.returncode == 0 and output:
+      hsh, ct = output.split()
+    else:
+      logging.error('Git error: rc=%d, output=%r' %
+                    (proc.returncode, output))
+  if not hsh:
+    return None
+  pos = ''
+  proc = RunGitCommand(directory, ['cat-file', 'commit', hsh])
+  if proc:
+    output = proc.communicate()[0]
+    if proc.returncode == 0 and output:
+      for line in reversed(output.splitlines()):
+        if line.startswith('Cr-Commit-Position:'):
+          pos = line.rsplit()[-1].strip()
+          break
+  return VersionInfo(hsh, '%s-%s' % (hsh, pos), int(ct))
 
-def GetMergeBase(directory, ref):
-  """
-  Return the merge-base of HEAD and ref.
 
-  Args:
-    directory: The directory containing the .git directory.
-    ref: The ref to use to find the merge base.
-  Returns:
-    The git commit SHA of the merge-base as a string.
-  """
-  logging.debug("Calculating merge base between HEAD and %s in %s",
-                ref, directory)
-  command = ['merge-base', 'HEAD', ref]
-  return _RunGitCommand(directory, command)
-
-def FetchGitRevision(directory, commit_filter, start_commit="HEAD"):
+def FetchVersionInfo(directory=None, filter=None):
   """
   Returns the last change (as a VersionInfo object)
   from some appropriate revision control system.
-
-  Args:
-    directory: The directory containing the .git directory.
-    commit_filter: A filter to supply to grep to filter commits
-    start_commit: A commit identifier. The result of this function
-      will be limited to only consider commits before the provided
-      commit.
-  Returns:
-    A VersionInfo object. On error all values will be 0.
   """
-  hash_ = ''
-
-  git_args = ['log', '-1', '--format=%H %ct']
-  if commit_filter is not None:
-    git_args.append('--grep=' + commit_filter)
-
-  git_args.append(start_commit)
-
-  output = _RunGitCommand(directory, git_args)
-  hash_, commit_timestamp = output.split()
-  if not hash_:
-    return VersionInfo('0', '0', 0)
-
-  revision = hash_
-  output = _RunGitCommand(directory, ['cat-file', 'commit', hash_])
-  for line in reversed(output.splitlines()):
-    if line.startswith('Cr-Commit-Position:'):
-      pos = line.rsplit()[-1].strip()
-      logging.debug("Found Cr-Commit-Position '%s'", pos)
-      revision = "{}-{}".format(hash_, pos)
-      break
-  return VersionInfo(hash_, revision, int(commit_timestamp))
-
-
+  version_info = FetchGitRevision(directory, filter)
+  if not version_info:
+    version_info = VersionInfo('0', '0', 0)
+  return version_info
 
 
 def GetHeaderGuard(path):
@@ -183,16 +133,6 @@
   return header_contents
 
 
-def GetGitTopDirectory(source_dir):
-  """Get the top git directory - the directory that contains the .git directory.
-
-  Args:
-    source_dir: The directory to search.
-  Returns:
-    The output of "git rev-parse --show-toplevel" as a string
-  """
-  return _RunGitCommand(source_dir, ['rev-parse', '--show-toplevel'])
-
 def WriteIfChanged(file_name, contents):
   """
   Writes the specified contents to the specified file_name
@@ -217,23 +157,20 @@
 
   parser = argparse.ArgumentParser(usage="lastchange.py [options]")
   parser.add_argument("-m", "--version-macro",
-                    help=("Name of C #define when using --header. Defaults to "
-                          "LAST_CHANGE."))
+                    help="Name of C #define when using --header. Defaults to " +
+                    "LAST_CHANGE.",
+                    default="LAST_CHANGE")
   parser.add_argument("-o", "--output", metavar="FILE",
-                    help=("Write last change to FILE. "
-                          "Can be combined with --header to write both files."))
+                    help="Write last change to FILE. " +
+                    "Can be combined with --header to write both files.")
   parser.add_argument("--header", metavar="FILE",
                     help=("Write last change to FILE as a C/C++ header. "
                           "Can be combined with --output to write both files."))
-  parser.add_argument("--merge-base-ref",
-                    default=None,
-                    help=("Only consider changes since the merge "
-                          "base between HEAD and the provided ref"))
   parser.add_argument("--revision-id-only", action='store_true',
                     help=("Output the revision as a VCS revision ID only (in "
                           "Git, a 40-character commit hash, excluding the "
                           "Cr-Commit-Position)."))
-  parser.add_argument("--print-only", action="store_true",
+  parser.add_argument("--print-only", action='store_true',
                     help=("Just print the revision string. Overrides any "
                           "file-output-related options."))
   parser.add_argument("-s", "--source-dir", metavar="DIR",
@@ -243,14 +180,13 @@
                           "matches the supplied filter regex. Defaults to "
                           "'^Change-Id:' to suppress local commits."),
                     default='^Change-Id:')
-
   args, extras = parser.parse_known_args(argv[1:])
 
   logging.basicConfig(level=logging.WARNING)
 
   out_file = args.output
   header = args.header
-  commit_filter = args.filter
+  filter=args.filter
 
   while len(extras) and out_file is None:
     if out_file is None:
@@ -260,37 +196,18 @@
     parser.print_help()
     sys.exit(2)
 
-  source_dir = args.source_dir or os.path.dirname(os.path.abspath(__file__))
-  try:
-    git_top_dir = GetGitTopDirectory(source_dir)
-  except GitError as e:
-    logging.error("Failed to get git top directory from '%s': %s",
-                  source_dir, e)
-    return 2
-
-  if args.merge_base_ref:
-    try:
-      merge_base_sha = GetMergeBase(git_top_dir, args.merge_base_ref)
-    except GitError as e:
-      logging.error("You requested a --merge-base-ref value of '%s' but no "
-                    "merge base could be found between it and HEAD. Git "
-                    "reports: %s", args.merge_base_ref, e)
-      return 3
+  if args.source_dir:
+    src_dir = args.source_dir
   else:
-    merge_base_sha = 'HEAD'
+    src_dir = os.path.dirname(os.path.abspath(__file__))
 
-  try:
-    version_info = FetchGitRevision(git_top_dir, commit_filter, merge_base_sha)
-  except GitError as e:
-    logging.error("Failed to get version info: %s")
-    return 1
-
+  version_info = FetchVersionInfo(directory=src_dir, filter=filter)
   revision_string = version_info.revision
   if args.revision_id_only:
     revision_string = version_info.revision_id
 
   if args.print_only:
-    print(revision_string)
+    print revision_string
   else:
     contents = "LASTCHANGE=%s\n" % revision_string
     if not out_file and not args.header:
diff --git a/build/vs_toolchain.py b/build/vs_toolchain.py
index 1ab7be5..83b5e25d 100755
--- a/build/vs_toolchain.py
+++ b/build/vs_toolchain.py
@@ -367,9 +367,8 @@
   to build with."""
   env_version = GetVisualStudioVersion()
   if env_version == '2017':
-    # VS 2017 Update 9 (15.9.3) with 10.0.17763.132 SDK, 10.0.17134 version of
-    # d3dcompiler_47.dll, with ARM64 libraries.
-    toolchain_hash = '818a152b3f1da991c1725d85be19a0f27af6bab4'
+    # VS 2017 Update 9 (15.9.3) with 10.0.17763.132 SDK with ARM64 libraries.
+    toolchain_hash = 'e04af53255fe13c130e9cfde7d9ac861b9fb674a'
     # Third parties that do not have access to the canonical toolchain can map
     # canonical toolchain version to their own toolchain versions.
     toolchain_hash_mapping_key = 'GYP_MSVS_HASH_%s' % toolchain_hash
diff --git a/build/win/BUILD.gn b/build/win/BUILD.gn
index 12d61c86..99871f8 100644
--- a/build/win/BUILD.gn
+++ b/build/win/BUILD.gn
@@ -82,10 +82,12 @@
   }
 
   group("runtime_libs") {
-    if (is_component_build) {
+    if (is_component_build || current_cpu != "arm64") {
       # Copy the VS runtime DLLs into the isolate so that they don't have to be
       # preinstalled on the target machine. The debug runtimes have a "d" at
-      # the end.
+      # the end. The UCRT files are needed for all non-arm64 builds because
+      # d3dcompiler_47.dll depends on them and they are missing on some Windows
+      # 7 machines.
       if (is_debug) {
         vcrt_suffix = "d"
       } else {
diff --git a/cc/animation/animation_host.cc b/cc/animation/animation_host.cc
index 0db0b63..41a505b 100644
--- a/cc/animation/animation_host.cc
+++ b/cc/animation/animation_host.cc
@@ -326,10 +326,9 @@
   // Mutator may depend on scroll offset as its time input e.g., when there is
   // a worklet animation attached to a scroll timeline.
   // This ordering ensures we use the latest scroll offset as the input to the
-  // mutator even if there are active scroll animations. Furthermore ticking
-  // worklet animations at the end gaurantees that mutator output takes effect
-  // in the same impl frame that it was mutated.
-
+  // mutator even if there are active scroll animations.
+  // The ticking of worklet animations is deferred until draw to ensure that
+  // mutator output takes effect in the same impl frame that it was mutated.
   if (!NeedsTickAnimations())
     return false;
 
@@ -348,14 +347,11 @@
   // to an active timeline has changed. http://crbug.com/767210
   TickMutator(monotonic_time, scroll_tree, is_active_tree);
 
-  // TODO(crbug.com/834452): This works because at the moment the above call is
-  // synchronous. We will need a different approach once it becomes asynchronous
-  // but until then this simple ordering is sufficient.
-  TickAnimationsIf(ticking_animations_, monotonic_time,
-                   [](const Animation& animation) {
-                     return animation.IsWorkletAnimation();
-                   });
-  return true;
+  for (const auto& it : ticking_animations_) {
+    if (!it->IsWorkletAnimation())
+      return true;
+  }
+  return false;
 }
 
 void AnimationHost::TickScrollAnimations(base::TimeTicks monotonic_time,
@@ -365,6 +361,13 @@
   TickMutator(monotonic_time, scroll_tree, true /* is_active_tree */);
 }
 
+void AnimationHost::TickWorkletAnimations(base::TimeTicks monotonic_time) {
+  TickAnimationsIf(ticking_animations_, monotonic_time,
+                   [](const Animation& animation) {
+                     return animation.IsWorkletAnimation();
+                   });
+}
+
 std::unique_ptr<MutatorInputState> AnimationHost::CollectWorkletAnimationsState(
     base::TimeTicks monotonic_time,
     const ScrollTree& scroll_tree,
diff --git a/cc/animation/animation_host.h b/cc/animation/animation_host.h
index fd582c4..e3fc873 100644
--- a/cc/animation/animation_host.h
+++ b/cc/animation/animation_host.h
@@ -106,6 +106,7 @@
                       bool is_active_tree) override;
   void TickScrollAnimations(base::TimeTicks monotonic_time,
                             const ScrollTree& scroll_tree) override;
+  void TickWorkletAnimations(base::TimeTicks monotonic_time) override;
   bool UpdateAnimationState(bool start_ready_animations,
                             MutatorEvents* events) override;
   void PromoteScrollTimelinesPendingToActive() override;
diff --git a/cc/animation/animation_host_unittest.cc b/cc/animation/animation_host_unittest.cc
index c780b92..80bacd83 100644
--- a/cc/animation/animation_host_unittest.cc
+++ b/cc/animation/animation_host_unittest.cc
@@ -149,7 +149,7 @@
 
 // Tests that verify interaction of AnimationHost with LayerTreeMutator.
 
-TEST_F(AnimationHostTest, LayerTreeMutatorUpdateTakesEffectInSameFrame) {
+TEST_F(AnimationHostTest, FastLayerTreeMutatorUpdateTakesEffectInSameFrame) {
   AttachWorkletAnimation();
 
   const float start_opacity = .7f;
@@ -179,6 +179,11 @@
   // should take effect in the same animation frame.
   TickAnimationsTransferEvents(base::TimeTicks(), 0u);
 
+  // Emulate behavior in PrepareToDraw. Animation worklet updates are best
+  // effort, and the animation tick is deferred until draw to allow time for the
+  // updates to arrive.
+  host_impl_->TickWorkletAnimations(base::TimeTicks());
+
   TestLayer* layer =
       client_.FindTestLayer(element_id_, ElementListType::ACTIVE);
   EXPECT_FALSE(layer->is_property_mutated(TargetProperty::OPACITY));
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc
index 51db61db..1ac1b9e 100644
--- a/cc/scheduler/scheduler.cc
+++ b/cc/scheduler/scheduler.cc
@@ -109,6 +109,12 @@
     begin_frame_source_->AddObserver(this);
 }
 
+void Scheduler::NotifyAnimationWorkletStateChange(AnimationWorkletState state,
+                                                  TreeType tree) {
+  state_machine_.NotifyAnimationWorkletStateChange(state, tree);
+  ProcessScheduledActions();
+}
+
 void Scheduler::SetNeedsBeginMainFrame() {
   state_machine_.SetNeedsBeginMainFrame();
   ProcessScheduledActions();
diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h
index f73dd4e..c251af3 100644
--- a/cc/scheduler/scheduler.h
+++ b/cc/scheduler/scheduler.h
@@ -105,6 +105,15 @@
   void NotifyReadyToDraw();
   void SetBeginFrameSource(viz::BeginFrameSource* source);
 
+  using AnimationWorkletState = SchedulerStateMachine::AnimationWorkletState;
+  using TreeType = SchedulerStateMachine::TreeType;
+
+  // Sets whether asynchronous animation worklet mutations are running.
+  // Mutations on the pending tree should block activiation. Mutations on the
+  // active tree should delay draw to allow time for the mutations to complete.
+  void NotifyAnimationWorkletStateChange(AnimationWorkletState state,
+                                         TreeType tree);
+
   // Set |needs_begin_main_frame_| to true, which will cause the BeginFrame
   // source to be told to send BeginFrames to this client so that this client
   // can send a CompositorFrame to the display compositor with appropriate
diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc
index 494b166..0e5fce6 100644
--- a/cc/scheduler/scheduler_state_machine.cc
+++ b/cc/scheduler/scheduler_state_machine.cc
@@ -233,6 +233,10 @@
                     current_pending_tree_is_impl_side_);
   state->SetBoolean("previous_pending_tree_was_impl_side",
                     previous_pending_tree_was_impl_side_);
+  state->SetBoolean("processing_animation_worklets_for_active_tree",
+                    processing_animation_worklets_for_active_tree_);
+  state->SetBoolean("processing_animation_worklets_for_pending_tree",
+                    processing_animation_worklets_for_pending_tree_);
   state->EndDictionary();
 }
 
@@ -374,6 +378,11 @@
   if (ShouldAbortCurrentFrame())
     return true;
 
+  // Delay pending tree activation until animation worklets have completed
+  // their asynchronous updates to pick up initial values.
+  if (processing_animation_worklets_for_pending_tree_)
+    return false;
+
   // At this point, only activate if we are ready to activate.
   return pending_tree_is_ready_for_activation_;
 }
@@ -1122,6 +1131,11 @@
   if (IsDrawThrottled())
     return false;
 
+  // Delay immediate draws when we have pending animation worklet updates to
+  // give them time to produce output before we draw.
+  if (processing_animation_worklets_for_active_tree_)
+    return false;
+
   // In full-pipe mode, we just gave all pipeline stages a chance to contribute.
   // We shouldn't wait any longer in any case - even if there are no updates.
   if (settings_.wait_for_all_pipeline_stages_before_draw)
@@ -1362,6 +1376,25 @@
   active_tree_is_ready_to_draw_ = true;
 }
 
+void SchedulerStateMachine::NotifyAnimationWorkletStateChange(
+    AnimationWorkletState state,
+    TreeType tree) {
+  if (tree == TreeType::ACTIVE) {
+    processing_animation_worklets_for_active_tree_ =
+        (state == AnimationWorkletState::PROCESSING);
+    // TODO(kevers): Determine when we should stop waiting for a mutation cycle
+    // to complete. For example, after pending tree activation, we can discard
+    // stale results for an active tree mutation cycle. Setting needs_redraw_
+    // after completion of each active tree mutation can lead to extra redraws
+    // that are unnecessary.
+    if (state == AnimationWorkletState::IDLE)
+      needs_redraw_ = true;
+  } else {
+    processing_animation_worklets_for_pending_tree_ =
+        (state == AnimationWorkletState::PROCESSING);
+  }
+}
+
 void SchedulerStateMachine::DidCreateAndInitializeLayerTreeFrameSink() {
   DCHECK_EQ(layer_tree_frame_sink_state_, LayerTreeFrameSinkState::CREATING);
   layer_tree_frame_sink_state_ =
diff --git a/cc/scheduler/scheduler_state_machine.h b/cc/scheduler/scheduler_state_machine.h
index bc1e83d..8902adc 100644
--- a/cc/scheduler/scheduler_state_machine.h
+++ b/cc/scheduler/scheduler_state_machine.h
@@ -278,6 +278,15 @@
   // Indicates the active tree's visible tiles are ready to be drawn.
   void NotifyReadyToDraw();
 
+  enum class AnimationWorkletState { PROCESSING, IDLE };
+  enum class TreeType { ACTIVE, PENDING };
+
+  // Indicates if currently processing animation worklets for the active or
+  // pending tree. This is used to determine if the draw deadline should be
+  // extended or activation delayed.
+  void NotifyAnimationWorkletStateChange(AnimationWorkletState state,
+                                         TreeType tree);
+
   void SetNeedsImplSideInvalidation(bool needs_first_draw_on_activation);
 
   bool has_pending_tree() const { return has_pending_tree_; }
@@ -427,6 +436,8 @@
   bool next_invalidation_needs_first_draw_on_activation_ = false;
   bool should_defer_invalidation_for_fast_main_frame_ = true;
   bool begin_frame_is_animate_only_ = false;
+  bool processing_animation_worklets_for_active_tree_ = false;
+  bool processing_animation_worklets_for_pending_tree_ = false;
 
   // Set to true if the main thread fails to respond with a commit or abort the
   // main frame before the draw deadline on the previous impl frame.
diff --git a/cc/scheduler/scheduler_state_machine_unittest.cc b/cc/scheduler/scheduler_state_machine_unittest.cc
index 26d3ada..6953f11 100644
--- a/cc/scheduler/scheduler_state_machine_unittest.cc
+++ b/cc/scheduler/scheduler_state_machine_unittest.cc
@@ -2688,5 +2688,60 @@
   EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
 }
 
+TEST(SchedulerStateMachineTest, BlockDrawIfAnimationWorkletsPending) {
+  SchedulerSettings default_scheduler_settings;
+  StateMachine state(default_scheduler_settings);
+  SET_UP_STATE(state)
+
+  // This test verifies that having pending mutations from Animation Worklets on
+  // the active tree will not trigger the deadline early.
+  state.SetNeedsBeginMainFrame();
+  state.OnBeginImplFrame(0, 10, kAnimateOnly);
+  EXPECT_ACTION_UPDATE_STATE(
+      SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
+  state.NotifyBeginMainFrameStarted();
+  state.NotifyReadyToCommit();
+  EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
+  state.NotifyReadyToActivate();
+  EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
+  EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
+  state.NotifyAnimationWorkletStateChange(
+      SchedulerStateMachine::AnimationWorkletState::PROCESSING,
+      SchedulerStateMachine::TreeType::ACTIVE);
+  EXPECT_FALSE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
+  EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::REGULAR,
+            state.CurrentBeginImplFrameDeadlineMode());
+  state.NotifyAnimationWorkletStateChange(
+      SchedulerStateMachine::AnimationWorkletState::IDLE,
+      SchedulerStateMachine::TreeType::ACTIVE);
+  EXPECT_TRUE(state.ShouldTriggerBeginImplFrameDeadlineImmediately());
+  EXPECT_EQ(SchedulerStateMachine::BeginImplFrameDeadlineMode::IMMEDIATE,
+            state.CurrentBeginImplFrameDeadlineMode());
+}
+
+TEST(SchedulerStateMachineTest, BlockActivationIfAnimationWorkletsPending) {
+  SchedulerSettings settings;
+  StateMachine state(settings);
+  SET_UP_STATE(state)
+
+  // Verify that pending mutations from Animation Worklets block activation.
+  state.SetNeedsBeginMainFrame();
+  state.OnBeginImplFrame(0, 10, kAnimateOnly);
+  EXPECT_ACTION_UPDATE_STATE(
+      SchedulerStateMachine::Action::SEND_BEGIN_MAIN_FRAME);
+  state.NotifyBeginMainFrameStarted();
+  state.NotifyReadyToCommit();
+  EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::COMMIT);
+  state.NotifyAnimationWorkletStateChange(
+      SchedulerStateMachine::AnimationWorkletState::PROCESSING,
+      SchedulerStateMachine::TreeType::PENDING);
+  state.NotifyReadyToActivate();
+  EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::NONE);
+  state.NotifyAnimationWorkletStateChange(
+      SchedulerStateMachine::AnimationWorkletState::IDLE,
+      SchedulerStateMachine::TreeType::PENDING);
+  EXPECT_ACTION_UPDATE_STATE(SchedulerStateMachine::Action::ACTIVATE_SYNC_TREE);
+}
+
 }  // namespace
 }  // namespace cc
diff --git a/cc/tiles/paint_worklet_image_cache.cc b/cc/tiles/paint_worklet_image_cache.cc
index 791cbb3f..0ad7ccf 100644
--- a/cc/tiles/paint_worklet_image_cache.cc
+++ b/cc/tiles/paint_worklet_image_cache.cc
@@ -7,11 +7,10 @@
 
 namespace cc {
 
-// TODO(xidachen): Rename this to PaintWorkletTaskImpl.
-class PaintWorkletImageCacheImpl : public TileTask {
+class PaintWorkletTaskImpl : public TileTask {
  public:
-  PaintWorkletImageCacheImpl(PaintWorkletImageCache* cache,
-                             const PaintImage& paint_image)
+  PaintWorkletTaskImpl(PaintWorkletImageCache* cache,
+                       const PaintImage& paint_image)
       : TileTask(true), cache_(cache), paint_image_(paint_image) {}
 
   // Overridden from Task:
@@ -21,13 +20,13 @@
   void OnTaskCompleted() override {}
 
  protected:
-  ~PaintWorkletImageCacheImpl() override = default;
+  ~PaintWorkletTaskImpl() override = default;
 
  private:
   PaintWorkletImageCache* cache_;
   PaintImage paint_image_;
 
-  DISALLOW_COPY_AND_ASSIGN(PaintWorkletImageCacheImpl);
+  DISALLOW_COPY_AND_ASSIGN(PaintWorkletTaskImpl);
 };
 
 PaintWorkletImageCache::PaintWorkletImageCache() {}
@@ -41,8 +40,7 @@
 
 scoped_refptr<TileTask> PaintWorkletImageCache::GetTaskForPaintWorkletImage(
     const DrawImage& image) {
-  return base::MakeRefCounted<PaintWorkletImageCacheImpl>(this,
-                                                          image.paint_image());
+  return base::MakeRefCounted<PaintWorkletTaskImpl>(this, image.paint_image());
 }
 
 // TODO(xidachen): dispatch the work to a worklet thread, invoke JS callback.
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index a5287ed..560712b 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -1330,6 +1330,14 @@
     }
   }
 
+  // Tick worklet animations here, just before draw, to give animation worklets
+  // as much time as possible to produce their output for this frame. Note that
+  // an animation worklet is asked to produce its output at the beginning of the
+  // frame along side other animations but its output arrives asynchronously so
+  // we tick worklet animations and apply that output here instead.
+  base::TimeTicks monotonic_time = CurrentBeginFrameArgs().frame_time;
+  mutator_host_->TickWorkletAnimations(monotonic_time);
+
   bool ok = active_tree_->UpdateDrawProperties();
   DCHECK(ok) << "UpdateDrawProperties failed during draw";
 
diff --git a/cc/trees/mutator_host.h b/cc/trees/mutator_host.h
index 586373cc..8ff40d8 100644
--- a/cc/trees/mutator_host.h
+++ b/cc/trees/mutator_host.h
@@ -66,6 +66,7 @@
   // Tick animations that depends on scroll offset.
   virtual void TickScrollAnimations(base::TimeTicks monotonic_time,
                                     const ScrollTree& scroll_tree) = 0;
+  virtual void TickWorkletAnimations(base::TimeTicks monotonic_time) = 0;
   virtual bool UpdateAnimationState(bool start_ready_animations,
                                     MutatorEvents* events) = 0;
   virtual void PromoteScrollTimelinesPendingToActive() = 0;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
index d332f0a..9a9a99fb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -113,6 +113,7 @@
 import org.chromium.chrome.browser.ntp.NewTabPageUma;
 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
 import org.chromium.chrome.browser.offlinepages.indicator.OfflineIndicatorController;
+import org.chromium.chrome.browser.omaha.UpdateInfoBarController;
 import org.chromium.chrome.browser.omaha.UpdateMenuItemHelper;
 import org.chromium.chrome.browser.omaha.UpdateMenuItemHelper.MenuButtonState;
 import org.chromium.chrome.browser.page_info.PageInfoController;
@@ -1136,6 +1137,11 @@
     @CallSuper
     protected void initDeferredStartupForActivity() {
         DeferredStartupHandler.getInstance().addDeferredTask(() -> {
+            UpdateInfoBarController.createInstance(ChromeActivity.this);
+            UpdateMenuItemHelper.getInstance().registerObserver(mUpdateStateChangedListener);
+        });
+
+        DeferredStartupHandler.getInstance().addDeferredTask(() -> {
             if (isActivityDestroyed()) return;
             BeamController.registerForBeam(ChromeActivity.this, () -> {
                 Tab currentTab = getActivityTab();
@@ -1143,8 +1149,6 @@
                 if (!currentTab.isUserInteractable()) return null;
                 return currentTab.getUrl();
             });
-
-            UpdateMenuItemHelper.getInstance().registerObserver(mUpdateStateChangedListener);
         });
 
         final String simpleName = getClass().getSimpleName();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/SimpleConfirmInfoBarBuilder.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/SimpleConfirmInfoBarBuilder.java
index 00a2bc9..e92bbb4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/SimpleConfirmInfoBarBuilder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/SimpleConfirmInfoBarBuilder.java
@@ -38,6 +38,13 @@
          *         false otherwise.
          */
         boolean onInfoBarButtonClicked(boolean isPrimary);
+
+        /**
+         * Called when the link of a ConfirmInfoBar is clicked.
+         * @return True if the listener caused the closing of this info bar as a side effect,
+         *         false otherwise.
+         */
+        boolean onInfoBarLinkClicked();
     }
 
     /**
@@ -52,7 +59,7 @@
      */
     public static void create(
             Tab tab, int infobarTypeIdentifier, String message, boolean autoExpire) {
-        create(tab, null, infobarTypeIdentifier, 0, message, null, null, autoExpire);
+        create(tab, null, infobarTypeIdentifier, 0, message, null, null, null, autoExpire);
     }
 
     /**
@@ -65,16 +72,17 @@
      * @param message Message displayed to the user.
      * @param primaryText String shown on the primary ConfirmInfoBar button.
      * @param secondaryText String shown on the secondary ConfirmInfoBar button.
+     * @param linkText String shown as the link text on the ConfirmInfoBar.
      * @param autoExpire Whether the infobar disappears on navigation.
      */
-    public static void create(Tab tab, Listener listener, int infobarTypeIdentifier,
-            int drawableId, String message, String primaryText, String secondaryText,
+    public static void create(Tab tab, Listener listener, int infobarTypeIdentifier, int drawableId,
+            String message, String primaryText, String secondaryText, String linkText,
             boolean autoExpire) {
         Activity activity = tab.getWindowAndroid().getActivity().get();
         Bitmap drawable = activity == null || drawableId == 0 ? null
                 : BitmapFactory.decodeResource(activity.getResources(), drawableId);
         nativeCreate(tab, infobarTypeIdentifier, drawable, message, primaryText, secondaryText,
-                autoExpire, listener);
+                linkText, autoExpire, listener);
     }
 
     @CalledByNative
@@ -87,8 +95,13 @@
         return listener == null ? false : listener.onInfoBarButtonClicked(isPrimary);
     }
 
-    private static native void nativeCreate(
-            Tab tab, int infobarTypeIdentifier, Bitmap drawable, String message, String primaryText,
-            String secondaryText, boolean autoExpire, Object listener);
+    @CalledByNative
+    private static boolean onInfoBarLinkClicked(Listener listener) {
+        return listener == null ? false : listener.onInfoBarLinkClicked();
+    }
+
+    private static native void nativeCreate(Tab tab, int infobarTypeIdentifier, Bitmap drawable,
+            String message, String primaryText, String secondaryText, String linkText,
+            boolean autoExpire, Object listener);
 }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaImageManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaImageManager.java
index 3019531..6ad653b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaImageManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaImageManager.java
@@ -4,8 +4,6 @@
 
 package org.chromium.chrome.browser.media.ui;
 
-import static org.chromium.services.media_session.MediaMetadata.MediaImage;
-
 import android.graphics.Bitmap;
 import android.graphics.Rect;
 import android.text.TextUtils;
@@ -14,6 +12,7 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.content_public.browser.ImageDownloadCallback;
 import org.chromium.content_public.browser.WebContents;
+import org.chromium.services.media_session.MediaImage;
 
 import java.util.HashMap;
 import java.util.Iterator;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/modules/ModuleInstallUi.java b/chrome/android/java/src/org/chromium/chrome/browser/modules/ModuleInstallUi.java
index 7a7ad69d..588b097 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/modules/ModuleInstallUi.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/modules/ModuleInstallUi.java
@@ -110,6 +110,11 @@
                 }
                 return false;
             }
+
+            @Override
+            public boolean onInfoBarLinkClicked() {
+                return false;
+            }
         };
 
         String text = String.format(context.getString(R.string.module_install_failure_text),
@@ -118,6 +123,6 @@
                 InfoBarIdentifier.MODULE_INSTALL_FAILURE_INFOBAR_ANDROID,
                 R.drawable.ic_error_outline_googblue_24dp, text,
                 context.getString(R.string.try_again), context.getString(R.string.cancel),
-                /* autoExpire = */ true);
+                /* linkText = */ null, /* autoExpire = */ true);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/UpdateInfoBarController.java b/chrome/android/java/src/org/chromium/chrome/browser/omaha/UpdateInfoBarController.java
new file mode 100644
index 0000000..8fd36fef
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omaha/UpdateInfoBarController.java
@@ -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.
+
+package org.chromium.chrome.browser.omaha;
+
+import org.chromium.base.Callback;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ApplicationLifetime;
+import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.infobar.InfoBarIdentifier;
+import org.chromium.chrome.browser.infobar.SimpleConfirmInfoBarBuilder;
+import org.chromium.chrome.browser.lifecycle.Destroyable;
+import org.chromium.chrome.browser.omaha.UpdateStatusProvider.UpdateState;
+import org.chromium.chrome.browser.omaha.UpdateStatusProvider.UpdateStatus;
+import org.chromium.chrome.browser.tab.Tab;
+
+/** Helper class that creates infobars based on {@link UpdateState} changes. */
+public class UpdateInfoBarController implements Destroyable {
+    private final Callback<UpdateStatus> mObserver = status -> {
+        handleStatusChange(status);
+    };
+
+    private ChromeActivity mActivity;
+
+    /**
+     * @param activity A {@link ChromeActivity} instance the infobars will be shown in.
+     * @return A new instance of {@link UpdateInfoBarController}.
+     */
+    public static UpdateInfoBarController createInstance(ChromeActivity activity) {
+        return new UpdateInfoBarController(activity);
+    }
+
+    // Destroyable implementation.
+    @Override
+    public void destroy() {
+        UpdateStatusProvider.getInstance().removeObserver(mObserver);
+        mActivity.getLifecycleDispatcher().unregister(this);
+        mActivity = null;
+    }
+
+    private UpdateInfoBarController(ChromeActivity activity) {
+        mActivity = activity;
+        UpdateStatusProvider.getInstance().addObserver(mObserver);
+        mActivity.getLifecycleDispatcher().register(this);
+    }
+
+    private void handleStatusChange(UpdateStatus status) {
+        switch (status.updateState) {
+            case UpdateState.INLINE_UPDATE_READY:
+                showRestartInfobar();
+                break;
+            case UpdateState.INLINE_UPDATE_FAILED:
+                showFailedInfobar();
+                break;
+        }
+    }
+
+    private void restartChrome() {
+        ApplicationLifetime.terminate(true /* restart */);
+    }
+
+    private void retryUpdate() {
+        // TODO(922714): Implement retry.
+    }
+
+    private void showRestartInfobar() {
+        if (mActivity == null) return;
+
+        Tab tab = mActivity.getActivityTabProvider().getActivityTab();
+        if (tab == null) return;
+
+        SimpleConfirmInfoBarBuilder.create(tab,
+                new SimpleConfirmInfoBarBuilder.Listener() {
+                    @Override
+                    public void onInfoBarDismissed() {}
+
+                    @Override
+                    public boolean onInfoBarButtonClicked(boolean isPrimary) {
+                        return false;
+                    }
+
+                    @Override
+                    public boolean onInfoBarLinkClicked() {
+                        restartChrome();
+                        return false;
+                    }
+                },
+                InfoBarIdentifier.INLINE_UPDATE_READY_INFOBAR_ANDROID,
+                R.drawable.infobar_chrome /* drawableId */,
+                mActivity.getString(R.string.inline_update_infobar_ready_message) /* message */,
+                null /* primaryText */, null /* secondaryText */,
+                mActivity.getString(R.string.inline_update_infobar_ready_link_text) /* linkText */,
+                false /* autoExpire */);
+    }
+
+    private void showFailedInfobar() {
+        if (mActivity == null) return;
+
+        Tab tab = mActivity.getActivityTabProvider().getActivityTab();
+        if (tab == null) return;
+
+        SimpleConfirmInfoBarBuilder.create(tab,
+                new SimpleConfirmInfoBarBuilder.Listener() {
+                    @Override
+                    public void onInfoBarDismissed() {}
+
+                    @Override
+                    public boolean onInfoBarButtonClicked(boolean isPrimary) {
+                        if (isPrimary) retryUpdate();
+                        return false;
+                    }
+
+                    @Override
+                    public boolean onInfoBarLinkClicked() {
+                        return false;
+                    }
+                },
+                InfoBarIdentifier.INLINE_UPDATE_FAILED_INFOBAR_ANDROID,
+                R.drawable.infobar_chrome /* drawableId */,
+                mActivity.getString(R.string.inline_update_infobar_failed_message) /* message */,
+                mActivity.getString(R.string.try_again) /* primaryText */,
+                mActivity.getString(R.string.cancel) /* secondaryText */, null /* linkText */,
+                false /* autoExpire */);
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omaha/UpdateMenuItemHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/omaha/UpdateMenuItemHelper.java
index 1747276..759506a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omaha/UpdateMenuItemHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omaha/UpdateMenuItemHelper.java
@@ -19,6 +19,7 @@
 import android.text.TextUtils;
 
 import org.chromium.base.BuildInfo;
+import org.chromium.base.Callback;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
 import org.chromium.base.ObserverList;
@@ -118,6 +119,13 @@
 
     private final Handler mHandler = new Handler(Looper.getMainLooper());
 
+    private final Callback<UpdateStatusProvider.UpdateStatus> mUpdateCallback = status -> {
+        mStatus = status;
+        handleStateChanged();
+        pingObservers();
+        recordUpdateHistogram();
+    };
+
     /**
      * The current state of updates for Chrome.  This can change during runtime and may be {@code
      * null} if the status hasn't been determined yet.
@@ -156,12 +164,7 @@
             return;
         }
 
-        UpdateStatusProvider.getInstance().addObserver(status -> {
-            mStatus = status;
-            handleStateChanged();
-            pingObservers();
-            recordUpdateHistogram();
-        });
+        UpdateStatusProvider.getInstance().addObserver(mUpdateCallback);
     }
 
     /** Unregisters {@code observer} from menu state changes. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreJavaUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreJavaUtils.java
index a05f950..5341400 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreJavaUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreJavaUtils.java
@@ -228,10 +228,15 @@
 
                 return false;
             }
+
+            @Override
+            public boolean onInfoBarLinkClicked() {
+                return false;
+            }
         };
         // TODO(ijamardo, https://crbug.com/838833): Add icon for AR info bar.
         SimpleConfirmInfoBarBuilder.create(tab, listener, InfoBarIdentifier.AR_CORE_UPGRADE_ANDROID,
-                R.drawable.vr_services, infobarText, buttonText, null, true);
+                R.drawable.vr_services, infobarText, buttonText, null, null, true);
     }
 
     @CalledByNative
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java
index dd5813b6..f71fa2c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java
@@ -819,13 +819,19 @@
                 }
                 return false;
             }
+
+            @Override
+            public boolean onInfoBarLinkClicked() {
+                return false;
+            }
         };
 
         SimpleConfirmInfoBarBuilder.create(tab, listener,
                 InfoBarIdentifier.VR_FEEDBACK_INFOBAR_ANDROID, R.drawable.vr_services,
                 activity.getString(R.string.vr_shell_feedback_infobar_description),
                 activity.getString(R.string.vr_shell_feedback_infobar_feedback_button),
-                activity.getString(R.string.no_thanks), true /* autoExpire  */);
+                activity.getString(R.string.no_thanks), null /* linkText */,
+                true /* autoExpire  */);
     }
 
     private static void ensureLifecycleObserverInitialized() {
@@ -999,10 +1005,15 @@
                         VR_SERVICES_UPDATE_RESULT);
                 return false;
             }
+
+            @Override
+            public boolean onInfoBarLinkClicked() {
+                return false;
+            }
         };
         SimpleConfirmInfoBarBuilder.create(tab, listener,
                 InfoBarIdentifier.VR_SERVICES_UPGRADE_ANDROID, R.drawable.vr_services, infobarText,
-                buttonText, null, true);
+                buttonText, null, null, true);
     }
 
     @VisibleForTesting
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index c208f5b..35ee974 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -1940,6 +1940,17 @@
         <ph name="MESSAGE">%1$s<ex>Downloading file (200 MB)</ex></ph> <ph name="LINK_NAME">%2$s<ex>Details</ex></ph> button
       </message>
 
+      <!-- Inline Update Infobar -->
+      <message name="IDS_INLINE_UPDATE_INFOBAR_READY_MESSAGE" desc="Text showing that the update process is almost ready.">
+        Almost finished!
+      </message>
+      <message name="IDS_INLINE_UPDATE_INFOBAR_READY_LINK_TEXT" desc="The clickable link letting the user know they can click to restart Chrome.">
+        Restart Chrome
+      </message>
+      <message name="IDS_INLINE_UPDATE_INFOBAR_FAILED_MESSAGE" desc="Text showing that the update process failed.">
+        Couldn’t download the update
+      </message>
+
       <!-- TranslateInfoBar -->
       <message name="IDS_TRANSLATE_INFOBAR_ERROR">
         Oops. This page could not be translated.
diff --git a/chrome/android/java/strings/android_chrome_strings_grd/IDS_INLINE_UPDATE_INFOBAR_FAILED_MESSAGE.png.sha1 b/chrome/android/java/strings/android_chrome_strings_grd/IDS_INLINE_UPDATE_INFOBAR_FAILED_MESSAGE.png.sha1
new file mode 100644
index 0000000..ec4cc47
--- /dev/null
+++ b/chrome/android/java/strings/android_chrome_strings_grd/IDS_INLINE_UPDATE_INFOBAR_FAILED_MESSAGE.png.sha1
@@ -0,0 +1 @@
+61a0d945b2c1ee46d328fb1cae96b0ebef248bdd
\ No newline at end of file
diff --git a/chrome/android/java/strings/android_chrome_strings_grd/IDS_INLINE_UPDATE_INFOBAR_READY_LINK_TEXT.png.sha1 b/chrome/android/java/strings/android_chrome_strings_grd/IDS_INLINE_UPDATE_INFOBAR_READY_LINK_TEXT.png.sha1
new file mode 100644
index 0000000..c3f406c
--- /dev/null
+++ b/chrome/android/java/strings/android_chrome_strings_grd/IDS_INLINE_UPDATE_INFOBAR_READY_LINK_TEXT.png.sha1
@@ -0,0 +1 @@
+a9c70666edc56785e76fcd6f73d5e991cd35fa75
\ No newline at end of file
diff --git a/chrome/android/java/strings/android_chrome_strings_grd/IDS_INLINE_UPDATE_INFOBAR_READY_MESSAGE.png.sha1 b/chrome/android/java/strings/android_chrome_strings_grd/IDS_INLINE_UPDATE_INFOBAR_READY_MESSAGE.png.sha1
new file mode 100644
index 0000000..c3f406c
--- /dev/null
+++ b/chrome/android/java/strings/android_chrome_strings_grd/IDS_INLINE_UPDATE_INFOBAR_READY_MESSAGE.png.sha1
@@ -0,0 +1 @@
+a9c70666edc56785e76fcd6f73d5e991cd35fa75
\ No newline at end of file
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index b203d6f..54d75c73 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -1115,6 +1115,7 @@
   "java/src/org/chromium/chrome/browser/omaha/ResponseParser.java",
   "java/src/org/chromium/chrome/browser/omaha/StringSanitizer.java",
   "java/src/org/chromium/chrome/browser/omaha/UpdateConfigs.java",
+  "java/src/org/chromium/chrome/browser/omaha/UpdateInfoBarController.java",
   "java/src/org/chromium/chrome/browser/omaha/UpdateMenuItemHelper.java",
   "java/src/org/chromium/chrome/browser/omaha/UpdateStatusProvider.java",
   "java/src/org/chromium/chrome/browser/omaha/VersionNumber.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarContainerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarContainerTest.java
index 6780a30..0ebe7f25 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarContainerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarContainerTest.java
@@ -73,6 +73,11 @@
             }
             return false;
         }
+
+        @Override
+        public boolean onInfoBarLinkClicked() {
+            return false;
+        }
     }
 
     private InfoBarTestAnimationListener mListener;
@@ -107,7 +112,7 @@
             public void run() {
                 SimpleConfirmInfoBarBuilder.create(mActivityTestRule.getActivity().getActivityTab(),
                         testListener, InfoBarIdentifier.TEST_INFOBAR, 0, MESSAGE_TEXT, null, null,
-                        expires);
+                        null, expires);
             }
         });
         mListener.addInfoBarAnimationFinished("InfoBar not added.");
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaImageManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaImageManagerTest.java
index 80803db..60614457 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaImageManagerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/media/ui/MediaImageManagerTest.java
@@ -15,8 +15,6 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
-import static org.chromium.services.media_session.MediaMetadata.MediaImage;
-
 import android.graphics.Bitmap;
 import android.graphics.Rect;
 
@@ -30,6 +28,7 @@
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.content_public.browser.WebContents;
+import org.chromium.services.media_session.MediaImage;
 
 import java.util.ArrayList;
 
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 9b717fb..2329f16 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1491,8 +1491,6 @@
     "signin/signin_promo_util.h",
     "signin/signin_status_metrics_provider_chromeos.cc",
     "signin/signin_status_metrics_provider_chromeos.h",
-    "signin/signin_tracker_factory.cc",
-    "signin/signin_tracker_factory.h",
     "signin/signin_util.cc",
     "signin/signin_util.h",
     "site_details.cc",
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc
index d2386e6..6275a81e 100644
--- a/chrome/browser/apps/guest_view/web_view_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -3533,11 +3533,7 @@
 }
 
 // Tests that webviews do get garbage collected.
-// This test is disabled because it relies on garbage collections triggered from
-// window.gc() to run precisely. This is not the case with unified heap where
-// they need to conservatively scan the stack, potentially keeping objects
-// alive. https://crbug.com/843903
-IN_PROC_BROWSER_TEST_F(WebViewTest, DISABLED_Shim_TestGarbageCollect) {
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestGarbageCollect) {
   TestHelper("testGarbageCollect", "web_view/shim", NO_TEST_SERVER);
   GetGuestViewManager()->WaitForSingleViewGarbageCollected();
 }
diff --git a/chrome/browser/apps/platform_apps/app_window_interactive_uitest.cc b/chrome/browser/apps/platform_apps/app_window_interactive_uitest.cc
index eabd3a2a..15fb04b 100644
--- a/chrome/browser/apps/platform_apps/app_window_interactive_uitest.cc
+++ b/chrome/browser/apps/platform_apps/app_window_interactive_uitest.cc
@@ -15,7 +15,6 @@
 #include "extensions/browser/app_window/native_app_window.h"
 #include "extensions/test/extension_test_message_listener.h"
 #include "extensions/test/result_catcher.h"
-#include "ui/base/ui_base_features.h"
 
 #if defined(OS_MACOSX)
 #include "base/mac/mac_util.h"
@@ -458,9 +457,6 @@
 #define MAYBE_TestFullscreen TestFullscreen
 #endif
 IN_PROC_BROWSER_TEST_F(AppWindowInteractiveTest, MAYBE_TestFullscreen) {
-  // Flaky on CrOS + IsUsingWindowService. https://crbug.com/926007
-  if (features::IsUsingWindowService())
-    return;
   ASSERT_TRUE(RunAppWindowInteractiveTest("testFullscreen")) << message_;
 }
 
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 05a9efa..36fc074 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -5453,3 +5453,14 @@
   return false;
 #endif
 }
+
+bool ChromeContentBrowserClient::IsRendererDebugURLBlacklisted(
+    const GURL& url,
+    content::BrowserContext* context) {
+  PolicyBlacklistService* service =
+      PolicyBlacklistFactory::GetForBrowserContext(context);
+
+  using URLBlacklistState = policy::URLBlacklist::URLBlacklistState;
+  URLBlacklistState blacklist_state = service->GetURLBlacklistState(url);
+  return blacklist_state == URLBlacklistState::URL_IN_BLACKLIST;
+}
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 84946f7c..f9c37fb2 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -551,6 +551,9 @@
   bool IsBuiltinComponent(content::BrowserContext* browser_context,
                           const url::Origin& origin) override;
 
+  bool IsRendererDebugURLBlacklisted(const GURL& url,
+                                     content::BrowserContext* context) override;
+
   // Determines the committed previews state for the passed in params.
   static content::PreviewsState DetermineCommittedPreviewsForURL(
       const GURL& url,
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 167a3868..83c7c1d 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -233,6 +233,7 @@
     "//ui/aura",
     "//ui/base",
     "//ui/base/idle",
+    "//ui/base/user_activity",
     "//ui/chromeos",
     "//ui/chromeos/events",
     "//ui/compositor",
diff --git a/chrome/browser/chromeos/drive/drive_integration_service.cc b/chrome/browser/chromeos/drive/drive_integration_service.cc
index 8c808efe..a5678478 100644
--- a/chrome/browser/chromeos/drive/drive_integration_service.cc
+++ b/chrome/browser/chromeos/drive/drive_integration_service.cc
@@ -519,6 +519,7 @@
         drivefs_host_(profile_->GetPath(),
                       this,
                       this,
+                      content::GetNetworkConnectionTracker(),
                       base::DefaultClock::GetInstance(),
                       chromeos::disks::DiskMountManager::GetInstance(),
                       std::make_unique<base::OneShotTimer>()) {}
diff --git a/chrome/browser/chromeos/login/app_launch_controller.cc b/chrome/browser/chromeos/login/app_launch_controller.cc
index b414c2a..97d09ae 100644
--- a/chrome/browser/chromeos/login/app_launch_controller.cc
+++ b/chrome/browser/chromeos/login/app_launch_controller.cc
@@ -36,11 +36,12 @@
 #include "chromeos/settings/cros_settings_names.h"
 #include "components/user_manager/known_user.h"
 #include "components/user_manager/user_manager.h"
+#include "content/public/browser/network_service_instance.h"
 #include "content/public/browser/notification_service.h"
 #include "extensions/browser/app_window/app_window.h"
 #include "extensions/browser/app_window/app_window_registry.h"
 #include "extensions/common/features/feature_session_type.h"
-#include "net/base/network_change_notifier.h"
+#include "services/network/public/cpp/network_connection_tracker.h"
 #include "ui/base/ui_base_features.h"
 
 namespace chromeos {
@@ -356,8 +357,11 @@
 
 void AppLaunchController::OnNetworkWaitTimedout() {
   DCHECK(waiting_for_network_);
+  auto connection_type = network::mojom::ConnectionType::CONNECTION_UNKNOWN;
+  content::GetNetworkConnectionTracker()->GetConnectionType(&connection_type,
+                                                            base::DoNothing());
   SYSLOG(WARNING) << "OnNetworkWaitTimedout... connection = "
-                  << net::NetworkChangeNotifier::GetConnectionType();
+                  << connection_type;
   network_wait_timedout_ = true;
 
   MaybeShowNetworkConfigureUI();
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc
index dcae12b..4b25e598 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc
@@ -213,9 +213,7 @@
 // static
 void EasyUnlockService::RegisterProfilePrefs(
     user_prefs::PrefRegistrySyncable* registry) {
-  registry->RegisterDictionaryPref(prefs::kEasyUnlockPairing,
-                                   std::make_unique<base::DictionaryValue>());
-
+  registry->RegisterDictionaryPref(prefs::kEasyUnlockPairing);
   proximity_auth::ProximityAuthProfilePrefManager::RegisterPrefs(registry);
 }
 
diff --git a/chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.cc b/chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.cc
index 9e68c31e..f628bc1 100644
--- a/chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.cc
+++ b/chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.cc
@@ -67,10 +67,11 @@
 }
 
 void RegisterProfilePrefs(PrefRegistrySimple* registry) {
-  base::ListValue quick_unlock_whitelist_default;
-  quick_unlock_whitelist_default.AppendString(kQuickUnlockWhitelistOptionAll);
-  registry->RegisterListPref(prefs::kQuickUnlockModeWhitelist,
-                             quick_unlock_whitelist_default.CreateDeepCopy());
+  base::Value::ListStorage quick_unlock_whitelist_default;
+  quick_unlock_whitelist_default.emplace_back(kQuickUnlockWhitelistOptionAll);
+  registry->RegisterListPref(
+      prefs::kQuickUnlockModeWhitelist,
+      base::Value(std::move(quick_unlock_whitelist_default)));
   registry->RegisterIntegerPref(
       prefs::kQuickUnlockTimeout,
       static_cast<int>(PasswordConfirmationFrequency::DAY));
diff --git a/chrome/browser/chromeos/login/signin/merge_session_throttling_utils.cc b/chrome/browser/chromeos/login/signin/merge_session_throttling_utils.cc
index 85eb1b8..987ee002 100644
--- a/chrome/browser/chromeos/login/signin/merge_session_throttling_utils.cc
+++ b/chrome/browser/chromeos/login/signin/merge_session_throttling_utils.cc
@@ -18,8 +18,9 @@
 #include "components/google/core/common/google_util.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/network_service_instance.h"
 #include "content/public/browser/web_contents.h"
-#include "net/base/network_change_notifier.h"
+#include "services/network/public/cpp/network_connection_tracker.h"
 #include "url/gurl.h"
 
 using content::BrowserThread;
@@ -182,7 +183,7 @@
 bool ShouldDelayUrl(const GURL& url) {
   // If we are loading google properties while merge session is in progress,
   // we will show delayed loading page instead.
-  return !net::NetworkChangeNotifier::IsOffline() &&
+  return !content::GetNetworkConnectionTracker()->IsOffline() &&
          !AreAllSessionMergedAlready() &&
          google_util::IsGoogleHostname(url.host_piece(),
                                        google_util::ALLOW_SUBDOMAIN);
diff --git a/chrome/browser/chromeos/net/network_pref_state_observer_unittest.cc b/chrome/browser/chromeos/net/network_pref_state_observer_unittest.cc
index 3078b5c9..1f0d8c6 100644
--- a/chrome/browser/chromeos/net/network_pref_state_observer_unittest.cc
+++ b/chrome/browser/chromeos/net/network_pref_state_observer_unittest.cc
@@ -16,8 +16,8 @@
 #include "chrome/test/base/testing_profile_manager.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/network/network_handler.h"
-#include "chromeos/network/proxy/ui_proxy_config.h"
 #include "chromeos/network/proxy/ui_proxy_config_service.h"
+#include "components/onc/onc_constants.h"
 #include "components/prefs/pref_service.h"
 #include "components/proxy_config/proxy_config_pref_names.h"
 #include "components/proxy_config/proxy_prefs.h"
@@ -84,15 +84,14 @@
 };
 
 TEST_F(NetworkPrefStateObserverTest, LoginUser) {
-  UIProxyConfig ui_proxy_config;
-
   // UIProxyConfigService should exist with device PrefService.
   UIProxyConfigService* device_ui_proxy_config_service =
       NetworkHandler::Get()->ui_proxy_config_service();
   ASSERT_TRUE(device_ui_proxy_config_service);
-  // Default mode for device prefs should be MODE_DIRECT.
-  device_ui_proxy_config_service->GetProxyConfig(kNetworkId, &ui_proxy_config);
-  EXPECT_EQ(UIProxyConfig::MODE_DIRECT, ui_proxy_config.mode);
+  // There should be no proxy config available.
+  base::Value ui_proxy_config(base::Value::Type::DICTIONARY);
+  EXPECT_FALSE(device_ui_proxy_config_service->MergeEnforcedProxyConfig(
+      kNetworkId, &ui_proxy_config));
 
   Profile* profile = LoginAndReturnProfile();
 
@@ -101,9 +100,9 @@
       NetworkHandler::Get()->ui_proxy_config_service();
   ASSERT_TRUE(profile_ui_proxy_config_service);
   ASSERT_NE(device_ui_proxy_config_service, profile_ui_proxy_config_service);
-  // Mode should still be MODE_DIRECT.
-  profile_ui_proxy_config_service->GetProxyConfig(kNetworkId, &ui_proxy_config);
-  EXPECT_EQ(UIProxyConfig::MODE_DIRECT, ui_proxy_config.mode);
+  ui_proxy_config = base::Value(base::Value::Type::DICTIONARY);
+  EXPECT_FALSE(profile_ui_proxy_config_service->MergeEnforcedProxyConfig(
+      kNetworkId, &ui_proxy_config));
 
   // Set the profile pref to PAC script mode.
   std::unique_ptr<base::DictionaryValue> proxy_config(
@@ -114,9 +113,14 @@
   base::RunLoop().RunUntilIdle();
 
   // Mode should now be MODE_PAC_SCRIPT.
-  NetworkHandler::Get()->ui_proxy_config_service()->GetProxyConfig(
-      kNetworkId, &ui_proxy_config);
-  EXPECT_EQ(UIProxyConfig::MODE_PAC_SCRIPT, ui_proxy_config.mode);
+  ui_proxy_config = base::Value(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(NetworkHandler::Get()
+                  ->ui_proxy_config_service()
+                  ->MergeEnforcedProxyConfig(kNetworkId, &ui_proxy_config));
+  base::Value* mode = ui_proxy_config.FindPath(
+      {::onc::network_config::kType, ::onc::kAugmentationActiveSetting});
+  ASSERT_TRUE(mode);
+  EXPECT_EQ(base::Value(::onc::proxy::kPAC), *mode);
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/policy/device_status_collector.cc b/chrome/browser/chromeos/policy/device_status_collector.cc
index e756938..2532508 100644
--- a/chrome/browser/chromeos/policy/device_status_collector.cc
+++ b/chrome/browser/chromeos/policy/device_status_collector.cc
@@ -1094,15 +1094,13 @@
 
 // static
 void DeviceStatusCollector::RegisterPrefs(PrefRegistrySimple* registry) {
-  registry->RegisterDictionaryPref(prefs::kDeviceActivityTimes,
-                                   std::make_unique<base::DictionaryValue>());
+  registry->RegisterDictionaryPref(prefs::kDeviceActivityTimes);
 }
 
 // static
 void DeviceStatusCollector::RegisterProfilePrefs(PrefRegistrySimple* registry) {
   registry->RegisterBooleanPref(prefs::kReportArcStatusEnabled, false);
-  registry->RegisterDictionaryPref(prefs::kUserActivityTimes,
-                                   std::make_unique<base::DictionaryValue>());
+  registry->RegisterDictionaryPref(prefs::kUserActivityTimes);
   registry->RegisterTimePref(prefs::kLastChildScreenTimeReset, Time());
   registry->RegisterTimePref(prefs::kLastChildScreenTimeSaved, Time());
   registry->RegisterIntegerPref(prefs::kChildScreenTimeMilliseconds, 0);
diff --git a/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc b/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
index f817ecf..fbebbbd 100644
--- a/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
+++ b/chrome/browser/chromeos/proxy_config_service_impl_unittest.cc
@@ -26,7 +26,6 @@
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/network/onc/onc_utils.h"
 #include "chromeos/network/proxy/proxy_config_handler.h"
-#include "chromeos/network/proxy/ui_proxy_config.h"
 #include "components/onc/onc_pref_names.h"
 #include "components/prefs/testing_pref_service.h"
 #include "components/proxy_config/proxy_config_pref_names.h"
@@ -50,8 +49,16 @@
 
 namespace {
 
+enum class Mode {
+  kDirect,
+  kAutoDetect,
+  kPac,
+  kSingleProxy,
+  kPerSchemeProxy,
+};
+
 struct Input {
-  UIProxyConfig::Mode mode;
+  Mode mode;
   std::string pac_url;
   std::string server;
   std::string bypass_rules;
@@ -60,9 +67,6 @@
 // Builds an identifier for each test in an array.
 #define TEST_DESC(desc) base::StringPrintf("at line %d <%s>", __LINE__, desc)
 
-// Shortcuts to declare enums within chromeos's ProxyConfig.
-#define MK_MODE(mode) UIProxyConfig::MODE_##mode
-
 // Inspired from net/proxy_resolution/proxy_config_service_linux_unittest.cc.
 const struct TestParams {
   // Short description to identify the test
@@ -75,150 +79,169 @@
   GURL pac_url;
   net::ProxyRulesExpectation proxy_rules;
 } tests[] = {
-  {  // 0
-    TEST_DESC("No proxying"),
+    {
+        // 0
+        TEST_DESC("No proxying"),
 
-    { // Input.
-      MK_MODE(DIRECT),  // mode
+        {
+            // Input.
+            Mode::kDirect,  // mode
+        },
+
+        // Expected result.
+        false,                                // auto_detect
+        GURL(),                               // pac_url
+        net::ProxyRulesExpectation::Empty(),  // proxy_rules
     },
 
-    // Expected result.
-    false,                                   // auto_detect
-    GURL(),                                  // pac_url
-    net::ProxyRulesExpectation::Empty(),     // proxy_rules
-  },
+    {
+        // 1
+        TEST_DESC("Auto detect"),
 
-  {  // 1
-    TEST_DESC("Auto detect"),
+        {
+            // Input.
+            Mode::kAutoDetect,  // mode
+        },
 
-    { // Input.
-      MK_MODE(AUTO_DETECT),  // mode
+        // Expected result.
+        true,                                 // auto_detect
+        GURL(),                               // pac_url
+        net::ProxyRulesExpectation::Empty(),  // proxy_rules
     },
 
-    // Expected result.
-    true,                                    // auto_detect
-    GURL(),                                  // pac_url
-    net::ProxyRulesExpectation::Empty(),     // proxy_rules
-  },
+    {
+        // 2
+        TEST_DESC("Valid PAC URL"),
 
-  {  // 2
-    TEST_DESC("Valid PAC URL"),
+        {
+            // Input.
+            Mode::kPac,              // mode
+            "http://wpad/wpad.dat",  // pac_url
+        },
 
-    { // Input.
-      MK_MODE(PAC_SCRIPT),     // mode
-      "http://wpad/wpad.dat",  // pac_url
+        // Expected result.
+        false,                                // auto_detect
+        GURL("http://wpad/wpad.dat"),         // pac_url
+        net::ProxyRulesExpectation::Empty(),  // proxy_rules
     },
 
-    // Expected result.
-    false,                                   // auto_detect
-    GURL("http://wpad/wpad.dat"),            // pac_url
-    net::ProxyRulesExpectation::Empty(),     // proxy_rules
-  },
+    {
+        // 3
+        TEST_DESC("Invalid PAC URL"),
 
-  {  // 3
-    TEST_DESC("Invalid PAC URL"),
+        {
+            // Input.
+            Mode::kPac,  // mode
+            "wpad.dat",  // pac_url
+        },
 
-    { // Input.
-      MK_MODE(PAC_SCRIPT),  // mode
-      "wpad.dat",           // pac_url
+        // Expected result.
+        false,                                // auto_detect
+        GURL(),                               // pac_url
+        net::ProxyRulesExpectation::Empty(),  // proxy_rules
     },
 
-    // Expected result.
-    false,                                   // auto_detect
-    GURL(),                                  // pac_url
-    net::ProxyRulesExpectation::Empty(),     // proxy_rules
-  },
+    {
+        // 4
+        TEST_DESC("Single-host in proxy list"),
 
-  {  // 4
-    TEST_DESC("Single-host in proxy list"),
+        {
+            // Input.
+            Mode::kSingleProxy,  // mode
+            "",                  // pac_url
+            "www.google.com",    // server
+        },
 
-    { // Input.
-      MK_MODE(SINGLE_PROXY),  // mode
-      "",                     // pac_url
-      "www.google.com",       // server
+        // Expected result.
+        false,                               // auto_detect
+        GURL(),                              // pac_url
+        net::ProxyRulesExpectation::Single(  // proxy_rules
+            "www.google.com:80",             // single proxy
+            "<local>"),                      // bypass rules
     },
 
-    // Expected result.
-    false,                                   // auto_detect
-    GURL(),                                  // pac_url
-    net::ProxyRulesExpectation::Single(      // proxy_rules
-        "www.google.com:80",                 // single proxy
-        "<local>"),                          // bypass rules
-  },
+    {
+        // 5
+        TEST_DESC("Single-host, different port"),
 
-  {  // 5
-    TEST_DESC("Single-host, different port"),
+        {
+            // Input.
+            Mode::kSingleProxy,   // mode
+            "",                   // pac_url
+            "www.google.com:99",  // server
+        },
 
-    { // Input.
-      MK_MODE(SINGLE_PROXY),  // mode
-      "",                     // pac_url
-      "www.google.com:99",    // server
+        // Expected result.
+        false,                               // auto_detect
+        GURL(),                              // pac_url
+        net::ProxyRulesExpectation::Single(  // proxy_rules
+            "www.google.com:99",             // single
+            "<local>"),                      // bypass rules
     },
 
-    // Expected result.
-    false,                                   // auto_detect
-    GURL(),                                  // pac_url
-    net::ProxyRulesExpectation::Single(      // proxy_rules
-        "www.google.com:99",                 // single
-        "<local>"),                          // bypass rules
-  },
+    {
+        // 6
+        TEST_DESC("Tolerate a scheme"),
 
-  {  // 6
-    TEST_DESC("Tolerate a scheme"),
+        {
+            // Input.
+            Mode::kSingleProxy,          // mode
+            "",                          // pac_url
+            "http://www.google.com:99",  // server
+        },
 
-    { // Input.
-      MK_MODE(SINGLE_PROXY),       // mode
-      "",                          // pac_url
-      "http://www.google.com:99",  // server
+        // Expected result.
+        false,                               // auto_detect
+        GURL(),                              // pac_url
+        net::ProxyRulesExpectation::Single(  // proxy_rules
+            "www.google.com:99",             // single proxy
+            "<local>"),                      // bypass rules
     },
 
-    // Expected result.
-    false,                                   // auto_detect
-    GURL(),                                  // pac_url
-    net::ProxyRulesExpectation::Single(      // proxy_rules
-        "www.google.com:99",                 // single proxy
-        "<local>"),                          // bypass rules
-  },
+    {
+        // 7
+        TEST_DESC("Per-scheme proxy rules"),
 
-  {  // 7
-    TEST_DESC("Per-scheme proxy rules"),
+        {
+            // Input.
+            Mode::kPerSchemeProxy,  // mode
+            "",                     // pac_url
+            "http=www.google.com:80;https=https://www.foo.com:110;"
+            "ftp=ftp.foo.com:121;socks=socks5://socks.com:888",  // server
+        },
 
-    { // Input.
-      MK_MODE(PROXY_PER_SCHEME),  // mode
-      "",                         // pac_url
-      "http=www.google.com:80;https=https://www.foo.com:110;"
-      "ftp=ftp.foo.com:121;socks=socks5://socks.com:888",  // server
+        // Expected result.
+        false,                                           // auto_detect
+        GURL(),                                          // pac_url
+        net::ProxyRulesExpectation::PerSchemeWithSocks(  // proxy_rules
+            "www.google.com:80",                         // http
+            "https://www.foo.com:110",                   // https
+            "ftp.foo.com:121",                           // ftp
+            "socks5://socks.com:888",                    // fallback proxy
+            "<local>"),                                  // bypass rules
     },
 
-    // Expected result.
-    false,                          // auto_detect
-    GURL(),                         // pac_url
-    net::ProxyRulesExpectation::PerSchemeWithSocks(  // proxy_rules
-        "www.google.com:80",        // http
-        "https://www.foo.com:110",  // https
-        "ftp.foo.com:121",          // ftp
-        "socks5://socks.com:888",   // fallback proxy
-        "<local>"),                 // bypass rules
-  },
+    {
+        // 8
+        TEST_DESC("Bypass rules"),
 
-  {  // 8
-    TEST_DESC("Bypass rules"),
+        {
+            // Input.
+            Mode::kSingleProxy,  // mode
+            "",                  // pac_url
+            "www.google.com",    // server
+            "*.google.com, *foo.com:99, 1.2.3.4:22, 127.0.0.1/8",
+            // bypass_rules
+        },
 
-    { // Input.
-      MK_MODE(SINGLE_PROXY),      // mode
-      "",                         // pac_url
-      "www.google.com",           // server
-      "*.google.com, *foo.com:99, 1.2.3.4:22, 127.0.0.1/8",  // bypass_rules
+        // Expected result.
+        false,                               // auto_detect
+        GURL(),                              // pac_url
+        net::ProxyRulesExpectation::Single(  // proxy_rules
+            "www.google.com:80",             // single proxy
+                                             // bypass_rules
+            "<local>,*.google.com,*foo.com:99,1.2.3.4:22,127.0.0.1/8"),
     },
-
-    // Expected result.
-    false,                          // auto_detect
-    GURL(),                         // pac_url
-    net::ProxyRulesExpectation::Single(  // proxy_rules
-        "www.google.com:80",             // single proxy
-        // bypass_rules
-        "<local>,*.google.com,*foo.com:99,1.2.3.4:22,127.0.0.1/8"),
-  },
 };  // tests
 
 const char kEthernetPolicy[] =
@@ -320,14 +343,14 @@
 
   base::Value InitConfigWithTestInput(const Input& input) {
     switch (input.mode) {
-      case MK_MODE(DIRECT):
+      case Mode::kDirect:
         return ProxyConfigDictionary::CreateDirect();
-      case MK_MODE(AUTO_DETECT):
+      case Mode::kAutoDetect:
         return ProxyConfigDictionary::CreateAutoDetect();
-      case MK_MODE(PAC_SCRIPT):
+      case Mode::kPac:
         return ProxyConfigDictionary::CreatePacScript(input.pac_url, false);
-      case MK_MODE(SINGLE_PROXY):
-      case MK_MODE(PROXY_PER_SCHEME):
+      case Mode::kSingleProxy:
+      case Mode::kPerSchemeProxy:
         return ProxyConfigDictionary::CreateFixedServers(input.server,
                                                          input.bypass_rules);
     }
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
index 9af3032..0dfad1b 100644
--- a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
@@ -592,7 +592,9 @@
   EXPECT_TRUE(RunNetworkingSubtest("getVisibleNetworksWifi")) << message_;
 }
 
-IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, EnabledNetworkTypes) {
+// TODO(crbug.com/928778): Flaky on CrOS.
+IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
+                       DISABLED_EnabledNetworkTypes) {
   EXPECT_TRUE(RunNetworkingSubtest("enabledNetworkTypes")) << message_;
 }
 
diff --git a/chrome/browser/extensions/extension_fullscreen_apitest.cc b/chrome/browser/extensions/extension_fullscreen_apitest.cc
index dac6cf4..708f5ceb 100644
--- a/chrome/browser/extensions/extension_fullscreen_apitest.cc
+++ b/chrome/browser/extensions/extension_fullscreen_apitest.cc
@@ -71,9 +71,6 @@
 
 IN_PROC_BROWSER_TEST_F(ExtensionApiTest,
                        MAYBE_DisplayModeWindowIsInFullscreen) {
-  // TODO(crbug.com/897879): this test is flaky.
-  if (features::IsSingleProcessMash())
-    return;
   ASSERT_TRUE(RunPlatformAppTest("fullscreen/mq_display_mode")) << message_;
 }
 
diff --git a/chrome/browser/load_library_perf_test.cc b/chrome/browser/load_library_perf_test.cc
index b843d43a..9f28190 100644
--- a/chrome/browser/load_library_perf_test.cc
+++ b/chrome/browser/load_library_perf_test.cc
@@ -25,6 +25,8 @@
 
 namespace {
 
+#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
+
 // Measures the size (bytes) and time to load (sec) of a native library.
 // |library_relative_dir| is the relative path based on DIR_MODULE.
 void MeasureSizeAndTimeToLoadNativeLibrary(
@@ -60,8 +62,6 @@
                          true);
 }
 
-#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
-
 void MeasureSizeAndTimeToLoadCdm(const std::string& cdm_base_dir,
                                  const std::string& cdm_name) {
   MeasureSizeAndTimeToLoadNativeLibrary(
diff --git a/chrome/browser/plugins/plugins_resource_service.cc b/chrome/browser/plugins/plugins_resource_service.cc
index 8223414..2f6b793 100644
--- a/chrome/browser/plugins/plugins_resource_service.cc
+++ b/chrome/browser/plugins/plugins_resource_service.cc
@@ -105,8 +105,7 @@
 
 // static
 void PluginsResourceService::RegisterPrefs(PrefRegistrySimple* registry) {
-  registry->RegisterDictionaryPref(prefs::kPluginsMetadata,
-                                   std::make_unique<base::DictionaryValue>());
+  registry->RegisterDictionaryPref(prefs::kPluginsMetadata);
   registry->RegisterStringPref(prefs::kPluginsResourceCacheUpdate, "0");
 }
 
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index b41c53f68..212e4a1 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -6432,6 +6432,82 @@
   EXPECT_FALSE(context->HasDevicePermission(kTestUrl, kTestUrl, *device_info));
 }
 
+// Handler for embedded http-server, returns a small page with javascript
+// variable and a link to increment it. It's for JavascriptBlacklistable test.
+std::unique_ptr<net::test_server::HttpResponse> JSIncrementerPageHandler(
+    const net::test_server::HttpRequest& request) {
+  if (request.relative_url != "/test.html") {
+    return std::unique_ptr<net::test_server::HttpResponse>();
+  }
+
+  std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
+      new net::test_server::BasicHttpResponse());
+  http_response->set_code(net::HTTP_OK);
+  http_response->set_content(
+      "<head><script type=\"text/javascript\">\n"
+      "<!--\n"
+      "var value = 1;"
+      "var increment = function() {"
+      "  value = value + 1;"
+      "};\n"
+      "//-->\n"
+      "</script></head><body>"
+      "<a id='link' href=\"javascript:increment();\">click</a>"
+      "</body>");
+  http_response->set_content_type("text/html");
+  return http_response;
+}
+
+// Fetch value from page generated by JSIncrementerPageHandler.
+int JSIncrementerFetch(content::WebContents* contents) {
+  int result;
+  EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
+      contents, "domAutomationController.send(value);", &result));
+  return result;
+}
+
+// Tests that javascript-links are handled properly according to blacklist
+// settings, bug 913334.
+IN_PROC_BROWSER_TEST_F(PolicyTest, JavascriptBlacklistable) {
+  embedded_test_server()->RegisterRequestHandler(
+      base::BindRepeating(&JSIncrementerPageHandler));
+  ASSERT_TRUE(embedded_test_server()->Start());
+  content::WebContents* contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  ui_test_utils::NavigateToURL(browser(),
+                               embedded_test_server()->GetURL("/test.html"));
+
+  EXPECT_EQ(JSIncrementerFetch(contents), 1);
+
+  // Without blacklist policy value is incremented properly.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(), GURL("javascript:increment()"),
+      WindowOpenDisposition::CURRENT_TAB, ui_test_utils::BROWSER_TEST_NONE);
+
+  EXPECT_EQ(JSIncrementerFetch(contents), 2);
+
+  // Create and apply a policy.
+  base::ListValue blacklist;
+  blacklist.AppendString("javascript://*");
+  PolicyMap policies;
+  policies.Set(key::kURLBlacklist, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
+               POLICY_SOURCE_CLOUD, blacklist.CreateDeepCopy(), nullptr);
+  UpdateProviderPolicy(policies);
+  FlushBlacklistPolicy();
+
+  // After applying policy javascript url's don't work any more, value leaves
+  // unchanged.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(), GURL("javascript:increment()"),
+      WindowOpenDisposition::CURRENT_TAB, ui_test_utils::BROWSER_TEST_NONE);
+  EXPECT_EQ(JSIncrementerFetch(contents), 2);
+
+  // But in-page links still work even if they are javascript-links.
+  EXPECT_TRUE(content::ExecuteScript(
+      contents, "document.getElementById('link').click();"));
+  EXPECT_EQ(JSIncrementerFetch(contents), 3);
+}
+
 // Similar to PolicyTest but sets the WebAppInstallForceList policy before the
 // browser is started.
 class WebAppInstallForceListPolicyTest : public PolicyTest {
diff --git a/chrome/browser/predictors/glowplug_key_value_table.cc b/chrome/browser/predictors/glowplug_key_value_table.cc
index c5656b17..9d826a2 100644
--- a/chrome/browser/predictors/glowplug_key_value_table.cc
+++ b/chrome/browser/predictors/glowplug_key_value_table.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/predictors/glowplug_key_value_table.h"
 
+#include "base/strings/stringprintf.h"
 #include "third_party/protobuf/src/google/protobuf/message_lite.h"
 
 namespace predictors {
diff --git a/chrome/browser/predictors/glowplug_key_value_table.h b/chrome/browser/predictors/glowplug_key_value_table.h
index 83d1f044..562e349 100644
--- a/chrome/browser/predictors/glowplug_key_value_table.h
+++ b/chrome/browser/predictors/glowplug_key_value_table.h
@@ -9,7 +9,6 @@
 #include <string>
 #include <vector>
 
-#include "base/strings/stringprintf.h"
 #include "sql/statement.h"
 
 namespace google {
diff --git a/chrome/browser/previews/previews_lite_page_decider.cc b/chrome/browser/previews/previews_lite_page_decider.cc
index 6ea4212..b3f661b4 100644
--- a/chrome/browser/previews/previews_lite_page_decider.cc
+++ b/chrome/browser/previews/previews_lite_page_decider.cc
@@ -177,8 +177,7 @@
 void PreviewsLitePageDecider::RegisterProfilePrefs(
     user_prefs::PrefRegistrySyncable* registry) {
   registry->RegisterBooleanPref(kUserNeedsNotification, true);
-  registry->RegisterDictionaryPref(kHostBlacklist,
-                                   std::make_unique<base::DictionaryValue>());
+  registry->RegisterDictionaryPref(kHostBlacklist);
 }
 
 // static
diff --git a/chrome/browser/resource_coordinator/session_restore_policy.cc b/chrome/browser/resource_coordinator/session_restore_policy.cc
index 9589e49c..0c3ca59 100644
--- a/chrome/browser/resource_coordinator/session_restore_policy.cc
+++ b/chrome/browser/resource_coordinator/session_restore_policy.cc
@@ -4,18 +4,49 @@
 
 #include "chrome/browser/resource_coordinator/session_restore_policy.h"
 
+#include <math.h>
+
+#include <algorithm>
+#include <utility>
+
+#include "base/bind.h"
 #include "base/no_destructor.h"
+#include "base/stl_util.h"
 #include "base/system/sys_info.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "build/build_config.h"
 #include "chrome/browser/engagement/site_engagement_service.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/common/url_constants.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/web_contents.h"
 
+#if !defined(OS_ANDROID)
+#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#endif
+
 namespace resource_coordinator {
 
 namespace {
 
+bool IsApp(content::WebContents* contents) {
+  static constexpr char kInternalUrlPrefix[] = "chrome-extension://";
+  const GURL& url = contents->GetLastCommittedURL();
+  return strncmp(url.spec().c_str(), kInternalUrlPrefix,
+                 base::size(kInternalUrlPrefix));
+}
+
+bool IsInternalPage(content::WebContents* contents) {
+  static constexpr char kInternalUrlPrefix[] = "chrome://";
+  const GURL& url = contents->GetLastCommittedURL();
+  return strncmp(url.spec().c_str(), kInternalUrlPrefix,
+                 base::size(kInternalUrlPrefix));
+}
+
 class SysInfoDelegate : public SessionRestorePolicy::Delegate {
  public:
   SysInfoDelegate() {}
@@ -65,10 +96,103 @@
       delegate_(SysInfoDelegate::Get()),
       parsed_params_(GetInfiniteSessionRestoreParams()),
       params_(&parsed_params_),
-      simultaneous_tab_loads_(CalculateSimultaneousTabLoadsFromParams()) {}
+      simultaneous_tab_loads_(CalculateSimultaneousTabLoadsFromParams()),
+      weak_factory_(this) {}
 
 SessionRestorePolicy::~SessionRestorePolicy() = default;
 
+float SessionRestorePolicy::AddTabForScoring(content::WebContents* contents) {
+  DCHECK(!base::ContainsKey(tab_data_, contents));
+
+  // When the first tab is added keep track of a 'now' time. This ensures that
+  // the scoring function returns consistent values over the lifetime of the
+  // policy object.
+  if (tab_data_.empty())
+    now_ = delegate_->NowTicks();
+
+  TabData* tab_data = &tab_data_[contents];
+
+  // Determine if the tab is pinned. This is only defined on desktop platforms.
+#if defined(OS_ANDROID)
+  tab_data->is_pinned = false;
+#else
+  // TODO(chrisha): This is O(n^2) in the number of tabs being restored. Fix
+  // this!
+  // In theory all tabs should belong to a tab-strip, but in tests this isn't
+  // necessarily true.
+  auto* browser_list = BrowserList::GetInstance();
+  for (size_t i = 0; i < browser_list->size(); ++i) {
+    auto* browser = browser_list->get(i);
+    auto* tab_strip = browser->tab_strip_model();
+    int tab_index = tab_strip->GetIndexOfWebContents(contents);
+    if (tab_index == TabStripModel::kNoTab)
+      continue;
+    tab_data->is_pinned = tab_strip->IsTabPinned(tab_index);
+    break;
+  }
+#endif  // !defined(OS_ANDROID)
+
+  // Cache a handful of other properties.
+  tab_data->is_app = IsApp(contents);
+  tab_data->is_internal = IsInternalPage(contents);
+  tab_data->site_engagement = delegate_->GetSiteEngagementScore(contents);
+  tab_data->last_active = now_ - contents->GetLastActiveTime();
+
+  // The local database doesn't exist on Android at all.
+#if !defined(OS_ANDROID)
+  // Get a reader for the local site characteristics data corresponding to this
+  // tab's origin. This makes it possible to determine if the tab has been
+  // observed communicating with the user while in the background. This can be
+  // ready immediately in which case a final score is emitted immediately.
+  // Otherwise, it will be loaded asynchronously and the score will potentially
+  // be updated.
+  Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
+  DCHECK(profile);
+  auto* factory = LocalSiteCharacteristicsDataStoreFactory::GetInstance();
+  auto* store = factory->GetForProfile(profile);
+
+  // The local database isn't always available.
+  // TODO(chrisha): Note that the reader can only not exist in tests. Once we
+  // have a single point to check for the availability of the performance
+  // manager, gate the following logic behind that.
+  if (store) {
+    tab_data->reader = store->GetReaderForOrigin(
+        url::Origin::Create(contents->GetLastCommittedURL()));
+    if (tab_data->reader->DataLoaded()) {
+      SetUsedInBg(tab_data);
+    } else {
+      tab_data->reader->RegisterDataLoadedCallback(
+          base::BindOnce(&SessionRestorePolicy::OnDataLoaded,
+                         weak_factory_.GetWeakPtr(), contents));
+    }
+  }
+#endif  // !defined(OS_ANDROID)
+
+  // Another tab has been added, so an existing all tabs scored notification may
+  // be required.
+  if (HasFinalScore(tab_data)) {
+    ++tabs_scored_;
+    if (notification_state_ == NotificationState::kDelivered)
+      notification_state_ = NotificationState::kNotSent;
+    DispatchNotifyAllTabsScoredIfNeeded();
+  } else {
+    notification_state_ = NotificationState::kNotSent;
+  }
+
+  ScoreTab(tab_data);
+  return tab_data->score;
+}
+
+void SessionRestorePolicy::RemoveTabForScoring(content::WebContents* contents) {
+  auto it = tab_data_.find(contents);
+  DCHECK(it != tab_data_.end());
+
+  if (HasFinalScore(&it->second))
+    --tabs_scored_;
+  tab_data_.erase(it);
+  DispatchNotifyAllTabsScoredIfNeeded();
+}
+
 bool SessionRestorePolicy::ShouldLoad(content::WebContents* contents) const {
   // If the policy is disabled then always return true.
   if (!policy_enabled_)
@@ -89,6 +213,10 @@
       return false;
   }
 
+  auto it = tab_data_.find(contents);
+  DCHECK(it != tab_data_.end());
+  const TabData& tab_data = it->second;
+
   // Enforce a max time since use if one is specified.
   if (!params_->max_time_since_last_use_to_restore.is_zero()) {
     base::TimeDelta time_since_active =
@@ -98,10 +226,8 @@
   }
 
   // Enforce a minimum site engagement score.
-  if (delegate_->GetSiteEngagementScore(contents) <
-      params_->min_site_engagement_to_restore) {
+  if (tab_data.site_engagement < params_->min_site_engagement_to_restore)
     return false;
-  }
 
   return true;
 }
@@ -117,7 +243,8 @@
     : policy_enabled_(policy_enabled),
       delegate_(delegate),
       params_(params),
-      simultaneous_tab_loads_(CalculateSimultaneousTabLoadsFromParams()) {}
+      simultaneous_tab_loads_(CalculateSimultaneousTabLoadsFromParams()),
+      weak_factory_(this) {}
 
 // static
 size_t SessionRestorePolicy::CalculateSimultaneousTabLoads(
@@ -156,13 +283,177 @@
       params_->cores_per_simultaneous_tab_load, delegate_->GetNumberOfCores());
 }
 
+// static
+void SessionRestorePolicy::SetUsedInBg(TabData* tab_data) {
+  static const SiteFeatureUsage kInUse = SiteFeatureUsage::kSiteFeatureInUse;
+  auto& reader = tab_data->reader;
+  DCHECK(reader->DataLoaded());
+
+  // Determine if background communication with the user is used. A pinned tab
+  // has no visible tab title, so tab title updates can be ignored in that case.
+  bool used_in_bg = (reader->UpdatesFaviconInBackground() == kInUse) ||
+                    (reader->UsesNotificationsInBackground() == kInUse);
+  if (!tab_data->is_pinned && (reader->UpdatesTitleInBackground() == kInUse))
+    used_in_bg = true;
+
+  // Persist this data and detach from the reader. We need to detach from the
+  // reader in a separate task because this callback is actually being invoked
+  // by the reader itself; as we're the sole owner, we'll cause it to be deleted
+  // while several stack frames deep in its code, causing an immediate use
+  // after free.
+  tab_data->used_in_bg = used_in_bg;
+  base::SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE,
+                                                     std::move(reader));
+}
+
+void SessionRestorePolicy::DispatchNotifyAllTabsScoredIfNeeded() {
+  // If a notification has already been sent then there's no need to send
+  // another.
+  if (notification_state_ == NotificationState::kDelivered)
+    return;
+
+  if (tabs_scored_ != tab_data_.size()) {
+    // An enroute notification should be canceled, as its no longer valid.
+    notification_state_ = NotificationState::kNotSent;
+    return;
+  }
+
+  // A notification is already enroute, no need to send another.
+  if (notification_state_ == NotificationState::kEnRoute)
+    return;
+
+  // This is done asynchronously so that this notification doesn't arrive before
+  // a tab score is delivered.
+  base::SequencedTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(&SessionRestorePolicy::NotifyAllTabsScored,
+                                weak_factory_.GetWeakPtr()));
+  notification_state_ = NotificationState::kEnRoute;
+}
+
+void SessionRestorePolicy::NotifyAllTabsScored() {
+  // Only deliver the notification if its still desired; pending notifications
+  // can be canceled as conditions change.
+  if (notification_state_ != NotificationState::kEnRoute)
+    return;
+  notify_tab_score_changed_callback_.Run(nullptr, 0.0);
+  notification_state_ = NotificationState::kDelivered;
+}
+
+void SessionRestorePolicy::OnDataLoaded(content::WebContents* contents) {
+  auto it = tab_data_.find(contents);
+  DCHECK(it != tab_data_.end());
+  auto* tab_data = &(it->second);
+  SetUsedInBg(tab_data);
+
+  // Score the tab and notify observers if the score has changed.
+  if (RescoreTabAfterDataLoaded(contents, &it->second))
+    notify_tab_score_changed_callback_.Run(contents, it->second.score);
+
+  ++tabs_scored_;
+  DispatchNotifyAllTabsScoredIfNeeded();
+}
+
+bool SessionRestorePolicy::RescoreTabAfterDataLoaded(
+    content::WebContents* contents /* unused */,
+    TabData* tab_data) {
+  return ScoreTab(tab_data);
+}
+
+// static
+bool SessionRestorePolicy::ScoreTab(TabData* tab_data) {
+  float score = 0.0f;
+
+  // Replicate the logic of the existing ordering mechanism:
+  // - apps
+  // - pinned tabs
+  // - normal tabs
+  // - internal tabs
+  // Within each category, restore newest tab first.
+  if (tab_data->is_app) {
+    score = 3;
+  } else if (tab_data->is_pinned) {
+    score = 2;
+  } else if (!tab_data->is_internal) {
+    score = 1;
+  }
+  score += CalculateAgeScore(tab_data);
+
+  // TODO(chrisha): Add a Finch configurable alternate scoring mechanism that
+  // takes into account background tab usage data.
+
+  if (score == tab_data->score)
+    return false;
+
+  tab_data->score = score;
+  return true;
+}
+
+// static
+float SessionRestorePolicy::CalculateAgeScore(const TabData* tab_data) {
+  // Convert the age into seconds. Cap absolute values less than 1 so that
+  // the inverse will be between -1 and 1.
+  double score = tab_data->last_active.InSecondsF();
+  if (fabs(score) < 1.0f) {
+    if (score > 0)
+      score = 1;
+    else
+      score = -1;
+  }
+  DCHECK_LE(1.0f, fabs(score));
+
+  // Invert the score (1 / score).
+  // Really old (infinity) maps to 0 (lowest priority).
+  // Really young positive age (1) maps to 1 (moderate priority).
+  // A little in the future (-1) maps to -1 (moderate priority).
+  // Really far in the future (-infinity) maps to 0 (highest priority).
+  // Shifting negative scores from [-1, 0] to [1, 2] keeps the scores increasing
+  // with priority.
+  if (score < 0) {
+    score = 2.0 + 1.0 / score;
+  } else {
+    score = 1.0 / score;
+  }
+  DCHECK_LE(0.0, score);
+  DCHECK_GE(2.0, score);
+
+  // Rescale the age score to the range [0, 1] so that it can be added to the
+  // category scores already calculated. Divide by 2 + epsilon so that no
+  // score will end up rounding up to 1.0, but instead be capped at 0.999.
+  score /= 2.002;
+  DCHECK_LE(0.0, score);
+  DCHECK_GT(1.0, score);
+
+  return score;
+}
+
+// static
+bool SessionRestorePolicy::HasFinalScore(const TabData* tab_data) {
+  return tab_data->reader.get() == nullptr;
+}
+
 void SessionRestorePolicy::SetTabLoadsStartedForTesting(
     size_t tab_loads_started) {
   tab_loads_started_ = tab_loads_started;
 }
 
+void SessionRestorePolicy::UpdateSiteEngagementScoreForTesting(
+    content::WebContents* contents,
+    size_t score) {
+  auto it = tab_data_.find(contents);
+  it->second.site_engagement = score;
+}
+
 SessionRestorePolicy::Delegate::Delegate() {}
 
 SessionRestorePolicy::Delegate::~Delegate() {}
 
+SessionRestorePolicy::TabData::TabData() = default;
+
+SessionRestorePolicy::TabData::TabData(TabData&&) = default;
+
+SessionRestorePolicy::TabData::~TabData() = default;
+
+SessionRestorePolicy::TabData& SessionRestorePolicy::TabData::operator=(
+    TabData&&) = default;
+
 }  // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/session_restore_policy.h b/chrome/browser/resource_coordinator/session_restore_policy.h
index 15f91f77..71c297b 100644
--- a/chrome/browser/resource_coordinator/session_restore_policy.h
+++ b/chrome/browser/resource_coordinator/session_restore_policy.h
@@ -5,6 +5,14 @@
 #ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_SESSION_RESTORE_POLICY_H_
 #define CHROME_BROWSER_RESOURCE_COORDINATOR_SESSION_RESTORE_POLICY_H_
 
+#include <memory>
+
+#include "base/callback.h"
+#include "base/containers/flat_map.h"
+#include "base/gtest_prod_util.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "chrome/browser/resource_coordinator/site_characteristics_data_reader.h"
 #include "chrome/browser/resource_coordinator/tab_manager_features.h"
 
 namespace content {
@@ -18,6 +26,22 @@
 // merged into TabManager directly.
 class SessionRestorePolicy {
  public:
+  // Callback that is used by the policy engine to notify its embedder (the
+  // TabLoaderDelegate) of changes to tab priorities as they occur. Zero or one
+  // score updates may be delivered for each contents that is added; callbacks
+  // associated with an explicit WebContents will only be dispatched while the
+  // associated WebContents is still being tracked.
+  //
+  // A callback with a nullptr WebContents is used to indicate that all tabs
+  // have received final scores. This is sent at every transition from "not all
+  // tabs have final scores" to "all tabs have final scores". This condition is
+  // always invalidated at the addition of a new tab, and restored once (a) all
+  // unscored tabs have been removed or (b) all unscored tabs receive a final
+  // score. This can happen multiple times over the lifetime of a
+  // SessionRestorePolicy object.
+  using NotifyTabScoreChangedCallback =
+      base::RepeatingCallback<void(content::WebContents*, float)>;
+
   // Used as a testing seam.
   class Delegate;
 
@@ -28,6 +52,23 @@
 
   size_t simultaneous_tab_loads() const { return simultaneous_tab_loads_; }
 
+  void SetTabScoreChangedCallback(
+      NotifyTabScoreChangedCallback notify_tab_score_changed_callback) {
+    notify_tab_score_changed_callback_ = notify_tab_score_changed_callback;
+  }
+
+  // Notifies the policy engine of a tab (represented by |contents|) that will
+  // be restored. It is expected that the |contents| already be attached to the
+  // appropriate tab strip model. This returns an initial restore priority
+  // score for the |contents|. The score may change asynchronously via a call
+  // to the registered NotifyTabScoreChangedCallback.
+  float AddTabForScoring(content::WebContents* contents);
+
+  // Notifies the policy engine of a tab that is no longer to be restored. No
+  // score change notifications will be sent for this |contents| after it has
+  // been removed.
+  void RemoveTabForScoring(content::WebContents* contents);
+
   // Returns true if the given contents should ever be loaded by
   // session restore. If this returns false then session restore should mark the
   // tab load as deferred and move onto the next tab to restore. Note that this
@@ -60,11 +101,98 @@
 
   void SetTabLoadsStartedForTesting(size_t tab_loads_started);
 
- private:
+  void UpdateSiteEngagementScoreForTesting(content::WebContents* contents,
+                                           size_t score);
+
+ protected:
+  // Holds a handful of data about a tab which is used to prioritize it during
+  // session restore.
+  struct TabData {
+    TabData();
+    TabData(const TabData&) = delete;
+    TabData(TabData&&);
+    ~TabData();
+
+    TabData& operator=(const TabData&) = delete;
+    TabData& operator=(TabData&&);
+
+    // This is used to populate |used_in_bg| once the reader is ready. The
+    // reader is not available on all platforms and test environments. The
+    // presence of a reader indicates that the tab is waiting for additional
+    // data and has not yet provided a final score to the embedder.
+    std::unique_ptr<SiteCharacteristicsDataReader> reader;
+
+    // Indicates whether or not the tab communicates with the user even when it
+    // is in the background (notifications, tab title changes, favicons, etc).
+    // This is set asynchronously.
+    bool used_in_bg = false;
+
+    // Indicates whether or not the tab has been pinned by the user. Only
+    // applicable on desktop platforms.
+    bool is_pinned = false;
+
+    // Indicates whether or not the tab corresponds to a Chrome app (these are
+    // deprecated but we still support them for now). Only applicable on
+    // desktop platforms.
+    bool is_app = false;
+
+    // Indicates whether or not the tab corresponds to an internal chrome://
+    // URL. These are considered lower priority for restoring as they can be
+    // created locally and usually offline, and have very low latency.
+    bool is_internal = false;
+
+    // The site engagement score associated with the tab. Higher values are for
+    // sites that see more engagement.
+    size_t site_engagement = 0;
+
+    // How long ago since the tab was last made the active tab by the user. This
+    // may actually be negative, as it is calculated as a difference between an
+    // arbitrary notion of "now" and some time in the past. Lower values still
+    // correspond to more recently used and usually more important tabs.
+    base::TimeDelta last_active;
+
+    // A higher value here means the tab has higher priority for restoring. This
+    // is calculated based on the values of the above properties, which may
+    // change as new data becomes available.
+    float score = 0.0f;
+  };
+
   // This is safe to call from the constructor if |delegate_| and |params_| are
   // already initialized.
   size_t CalculateSimultaneousTabLoadsFromParams() const;
 
+  // Initializes |used_in_bg| using the data from the |reader|. The reader must
+  // be initialized at the time this is called.
+  static void SetUsedInBg(TabData* tab_data);
+
+  // Posts a task to invoke "NotifyAllTabsScored".
+  void DispatchNotifyAllTabsScoredIfNeeded();
+
+  // Invokes the |notify_tab_scored_callback_| with a nullptr WebContents,
+  // notifying the embedder that all tabs have final scores.
+  void NotifyAllTabsScored();
+
+  // Callback that is invoked when the SiteCharacteristicsDataReader associated
+  // with a WebContents (see TabData above) is ready to use.
+  void OnDataLoaded(content::WebContents* contents);
+
+  // This is a testing seam. By default it immediately redirects to ScoreTab.
+  // This should return true if the score has changed, false otherwise.
+  virtual bool RescoreTabAfterDataLoaded(content::WebContents* contents,
+                                         TabData* tab_data);
+
+  // Calculates a |score| for the given tab. Returns true if it has changed from
+  // the existing score.
+  static bool ScoreTab(TabData* tab_data);
+
+  // Calculates a score for the "age" of the tab. This is a value between 0
+  // (inclusive) and 1 (exclusive), where higher values are attributed to newer
+  // tabs.
+  static float CalculateAgeScore(const TabData* tab_data);
+
+  // Returns true if given tab has had a final score calculated for it.
+  static bool HasFinalScore(const TabData* tab_data);
+
   // Initialized from the InfiniteSessionRestore policy.
   const bool policy_enabled_;
 
@@ -90,11 +218,43 @@
   // and increments this value.
   size_t tab_loads_started_ = 0;
 
+  // The number of tabs for which an accurate initial score has been assigned.
+  // This is incremented only after the full tab data is available, which
+  // may happen asynchronously.
+  size_t tabs_scored_ = 0;
+
+  // Used to track the state of the "all tabs scored" notification.
+  enum class NotificationState : uint16_t {
+    kNotSent = 0,
+    kEnRoute = 1,
+    kDelivered = 2,
+  };
+  NotificationState notification_state_ = NotificationState::kDelivered;
+
+  // The collection of tabs being tracked and various data used for scoring
+  // them.
+  base::flat_map<content::WebContents*, TabData> tab_data_;
+
+  // The callback that is invoked in order to update tab restore order.
+  NotifyTabScoreChangedCallback notify_tab_score_changed_callback_;
+
+  // The value of "now" to use when calculating time since a tab was used. A
+  // constant time is used so that the scores remain constant over the lifetime
+  // of a session restore. Note that overlapping session restores may end up
+  // having last active times that are *newer* than this value (thus negative
+  // ages). CalculateAgeScore can handle this gracefully.
+  base::TimeTicks now_;
+
+  // It's possible for this policy object to be destroyed while it has posted
+  // notifications in flight. The messages are bound to a weak pointer so that
+  // they are not delivered after the policy object is destroyed.
+  base::WeakPtrFactory<SessionRestorePolicy> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(SessionRestorePolicy);
 };
 
 // Abstracts away testing seams for the policy engine. In production code the
-// default implementation wraps to base::SysInfo.
+// default implementation wraps to base::SysInfo and the SiteEngagementService.
 class SessionRestorePolicy::Delegate {
  public:
   Delegate();
diff --git a/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc b/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc
index f56bd6cf..0ebc2394 100644
--- a/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc
+++ b/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc
@@ -4,10 +4,19 @@
 
 #include "chrome/browser/resource_coordinator/session_restore_policy.h"
 
+#include <algorithm>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/rand_util.h"
+#include "base/run_loop.h"
+#include "base/test/bind_test_util.h"
 #include "base/test/simple_test_tick_clock.h"
+#include "chrome/browser/resource_coordinator/local_site_characteristics_data_unittest_utils.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/web_contents_tester.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace resource_coordinator {
@@ -51,11 +60,25 @@
   DISALLOW_COPY_AND_ASSIGN(TestDelegate);
 };
 
+class LenientTabScoreChangeMock {
+ public:
+  LenientTabScoreChangeMock() = default;
+  ~LenientTabScoreChangeMock() = default;
+
+  MOCK_METHOD2(NotifyTabScoreChanged, void(content::WebContents*, float));
+};
+using TabScoreChangeMock = ::testing::StrictMock<LenientTabScoreChangeMock>;
+
 // Exposes testing functions on SessionRestorePolicy.
 class TestSessionRestorePolicy : public SessionRestorePolicy {
  public:
+  using SessionRestorePolicy::CalculateAgeScore;
   using SessionRestorePolicy::CalculateSimultaneousTabLoads;
+  using SessionRestorePolicy::ScoreTab;
   using SessionRestorePolicy::SetTabLoadsStartedForTesting;
+  using SessionRestorePolicy::TabData;
+  using SessionRestorePolicy::UpdateSiteEngagementScoreForTesting;
+
   TestSessionRestorePolicy(bool policy_enabled,
                            const Delegate* delegate,
                            const InfiniteSessionRestoreParams* params)
@@ -63,20 +86,43 @@
 
   ~TestSessionRestorePolicy() override {}
 
+  using RescoreTabCallback =
+      base::RepeatingCallback<bool(content::WebContents*, TabData*)>;
+
+  void SetRescoreTabCallback(RescoreTabCallback rescore_tab_callback) {
+    rescore_tab_callback_ = rescore_tab_callback;
+  }
+
+  bool RescoreTabAfterDataLoaded(content::WebContents* contents,
+                                 TabData* tab_data) override {
+    // Invoke the callback if one is provided.
+    if (!rescore_tab_callback_.is_null())
+      return rescore_tab_callback_.Run(contents, tab_data);
+    // Otherwise defer to the default implementation.
+    return SessionRestorePolicy::RescoreTabAfterDataLoaded(contents, tab_data);
+  }
+
+  float GetTabScore(content::WebContents* contents) const {
+    auto it = tab_data_.find(contents);
+    return it->second.score;
+  }
+
  private:
+  RescoreTabCallback rescore_tab_callback_;
+
   DISALLOW_COPY_AND_ASSIGN(TestSessionRestorePolicy);
 };
 
 }  // namespace
 
-class SessionRestorePolicyTest : public ChromeRenderViewHostTestHarness {
+class SessionRestorePolicyTest : public testing::ChromeTestHarnessWithLocalDB {
  public:
   SessionRestorePolicyTest() : delegate_(&clock_) {}
 
   ~SessionRestorePolicyTest() override {}
 
   void SetUp() override {
-    ChromeRenderViewHostTestHarness::SetUp();
+    testing::ChromeTestHarnessWithLocalDB::SetUp();
 
     // Set some reasonable initial parameters. Tests often override these.
     params_.min_simultaneous_tab_loads = 1;
@@ -115,12 +161,25 @@
     contents2_.reset();
     contents3_.reset();
 
-    ChromeRenderViewHostTestHarness::TearDown();
+    testing::ChromeTestHarnessWithLocalDB::TearDown();
   }
 
   void CreatePolicy(bool policy_enabled) {
     policy_ = std::make_unique<TestSessionRestorePolicy>(policy_enabled,
                                                          &delegate_, &params_);
+    policy_->SetTabScoreChangedCallback(base::BindRepeating(
+        &TabScoreChangeMock::NotifyTabScoreChanged, base::Unretained(&mock_)));
+    policy_->AddTabForScoring(contents1_.get());
+    policy_->AddTabForScoring(contents2_.get());
+    policy_->AddTabForScoring(contents3_.get());
+  }
+
+  void WaitForFinalTabScores() {
+    base::RunLoop run_loop;
+    EXPECT_CALL(mock_, NotifyTabScoreChanged(nullptr, 0.0))
+        .WillOnce(::testing::Invoke(
+            [&run_loop](content::WebContents*, float) { run_loop.Quit(); }));
+    run_loop.Run();
   }
 
  protected:
@@ -128,6 +187,7 @@
   TestDelegate delegate_;
   InfiniteSessionRestoreParams params_;
 
+  TabScoreChangeMock mock_;
   std::unique_ptr<TestSessionRestorePolicy> policy_;
 
   std::unique_ptr<content::WebContents> contents1_;
@@ -176,6 +236,8 @@
   EXPECT_TRUE(policy_->policy_enabled());
   EXPECT_EQ(2u, policy_->simultaneous_tab_loads());
 
+  WaitForFinalTabScores();
+
   // By default all the tabs should be loadable.
   EXPECT_TRUE(policy_->ShouldLoad(contents1_.get()));
   policy_->NotifyTabLoadStarted();
@@ -229,13 +291,14 @@
   policy_->SetTabLoadsStartedForTesting(0);
   constexpr size_t kEngagementLimit = 15;
   params_.min_site_engagement_to_restore = kEngagementLimit;
-  delegate_.SetSiteEngagementScore(kEngagementLimit + 1);
+  policy_->UpdateSiteEngagementScoreForTesting(contents1_.get(),
+                                               kEngagementLimit + 1);
   EXPECT_TRUE(policy_->ShouldLoad(contents1_.get()));
-  policy_->NotifyTabLoadStarted();
-  delegate_.SetSiteEngagementScore(kEngagementLimit);
+  policy_->UpdateSiteEngagementScoreForTesting(contents1_.get(),
+                                               kEngagementLimit);
   EXPECT_TRUE(policy_->ShouldLoad(contents1_.get()));
-  policy_->NotifyTabLoadStarted();
-  delegate_.SetSiteEngagementScore(kEngagementLimit - 1);
+  policy_->UpdateSiteEngagementScoreForTesting(contents1_.get(),
+                                               kEngagementLimit - 1);
   EXPECT_FALSE(policy_->ShouldLoad(contents1_.get()));
 }
 
@@ -245,6 +308,8 @@
   EXPECT_EQ(std::numeric_limits<size_t>::max(),
             policy_->simultaneous_tab_loads());
 
+  WaitForFinalTabScores();
+
   // Set everything aggressive so it would return false if the feature was
   // enabled.
   params_.min_tabs_to_restore = 0;
@@ -266,4 +331,132 @@
   policy_->NotifyTabLoadStarted();
 }
 
+TEST_F(SessionRestorePolicyTest, MultipleAllTabsDoneCallbacks) {
+  CreatePolicy(true);
+  WaitForFinalTabScores();
+
+  // Another "all tabs scored" notification should be sent after more tabs
+  // are added to the policy engine.
+  std::unique_ptr<content::WebContents> contents4 = CreateTestWebContents();
+  std::unique_ptr<content::WebContents> contents5 = CreateTestWebContents();
+  policy_->AddTabForScoring(contents4.get());
+  policy_->AddTabForScoring(contents5.get());
+  WaitForFinalTabScores();
+}
+
+TEST_F(SessionRestorePolicyTest, CalculateAgeScore) {
+  using TabData = TestSessionRestorePolicy::TabData;
+  constexpr int kMonthInSeconds = 60 * 60 * 24 * 31;
+
+  // Generate a bunch of random tab ages.
+  std::vector<TabData> tab_data;
+  tab_data.resize(1000);
+
+  // Generate some known edge cases.
+  size_t i = 0;
+  tab_data[i++].last_active = base::TimeDelta::FromMilliseconds(-1001);
+  tab_data[i++].last_active = base::TimeDelta::FromMilliseconds(-1000);
+  tab_data[i++].last_active = base::TimeDelta::FromMilliseconds(-999);
+  tab_data[i++].last_active = base::TimeDelta::FromMilliseconds(-500);
+  tab_data[i++].last_active = base::TimeDelta::FromMilliseconds(0);
+  tab_data[i++].last_active = base::TimeDelta::FromMilliseconds(500);
+  tab_data[i++].last_active = base::TimeDelta::FromMilliseconds(999);
+  tab_data[i++].last_active = base::TimeDelta::FromMilliseconds(1000);
+  tab_data[i++].last_active = base::TimeDelta::FromMilliseconds(1001);
+
+  // Generate a logarithmic selection of ages to test the whole range.
+  tab_data[i++].last_active = base::TimeDelta::FromSeconds(-1000000);
+  tab_data[i++].last_active = base::TimeDelta::FromSeconds(-100000);
+  tab_data[i++].last_active = base::TimeDelta::FromSeconds(-10000);
+  tab_data[i++].last_active = base::TimeDelta::FromSeconds(-1000);
+  tab_data[i++].last_active = base::TimeDelta::FromSeconds(-100);
+  tab_data[i++].last_active = base::TimeDelta::FromSeconds(-10);
+  tab_data[i++].last_active = base::TimeDelta::FromSeconds(10);
+  tab_data[i++].last_active = base::TimeDelta::FromSeconds(100);
+  tab_data[i++].last_active = base::TimeDelta::FromSeconds(1000);
+  tab_data[i++].last_active = base::TimeDelta::FromSeconds(10000);
+  tab_data[i++].last_active = base::TimeDelta::FromSeconds(100000);
+  tab_data[i++].last_active = base::TimeDelta::FromSeconds(1000000);
+  tab_data[i++].last_active = base::TimeDelta::FromSeconds(10000000);
+
+  // Generate a bunch more random ages.
+  for (; i < tab_data.size(); ++i) {
+    tab_data[i].last_active = base::TimeDelta::FromSeconds(
+        base::RandInt(-kMonthInSeconds, kMonthInSeconds));
+  }
+
+  // Calculate the tab scores.
+  for (i = 0; i < tab_data.size(); ++i) {
+    tab_data[i].score =
+        TestSessionRestorePolicy::CalculateAgeScore(&tab_data[i]);
+  }
+
+  // Sort tabs by increasing last active time.
+  std::sort(tab_data.begin(), tab_data.end(),
+            [](const TabData& td1, const TabData& td2) {
+              return td1.last_active < td2.last_active;
+            });
+
+  // The scores should be in decreasing order (>= is necessary because some
+  // last active times collapse to the same score).
+  for (i = 1; i < tab_data.size(); ++i)
+    ASSERT_GE(tab_data[i - 1].score, tab_data[i].score);
+}
+
+TEST_F(SessionRestorePolicyTest, ScoreTab) {
+  using TabData = TestSessionRestorePolicy::TabData;
+
+  TabData td_app;
+  td_app.is_app = true;
+  EXPECT_TRUE(TestSessionRestorePolicy::ScoreTab(&td_app));
+
+  TabData td_pinned;
+  td_pinned.is_pinned = true;
+  EXPECT_TRUE(TestSessionRestorePolicy::ScoreTab(&td_pinned));
+
+  TabData td_normal_young;
+  TabData td_normal_old;
+  td_normal_young.last_active = base::TimeDelta::FromSeconds(1);
+  td_normal_old.last_active = base::TimeDelta::FromDays(7);
+  EXPECT_TRUE(TestSessionRestorePolicy::ScoreTab(&td_normal_young));
+  EXPECT_TRUE(TestSessionRestorePolicy::ScoreTab(&td_normal_old));
+
+  TabData td_internal;
+  td_internal.is_internal = true;
+  EXPECT_TRUE(TestSessionRestorePolicy::ScoreTab(&td_internal));
+
+  // Check the score produces the expected ordering of tabs.
+  EXPECT_LT(td_internal.score, td_normal_old.score);
+  EXPECT_LT(td_normal_old.score, td_normal_young.score);
+  EXPECT_LT(td_normal_young.score, td_pinned.score);
+  EXPECT_LT(td_pinned.score, td_app.score);
+}
+
+TEST_F(SessionRestorePolicyTest, RescoringSendsNotification) {
+  using TabData = TestSessionRestorePolicy::TabData;
+
+  // Inject code that causes some tabs to receive updated scores.
+  CreatePolicy(true);
+  policy_->SetRescoreTabCallback(base::BindLambdaForTesting(
+      [&](content::WebContents* contents, TabData* tab_data) {
+        float delta = 0;
+        if (contents == contents1_.get())
+          delta = 1.0;
+        else if (contents == contents2_.get())
+          delta = 2.0;
+        tab_data->score += delta;
+        return delta != 0;
+      }));
+
+  // Get the current scores.
+  float score1 = policy_->GetTabScore(contents1_.get());
+  float score2 = policy_->GetTabScore(contents2_.get());
+
+  // Expect tab score change notifications for the first 2 tabs, but not the
+  // third.
+  EXPECT_CALL(mock_, NotifyTabScoreChanged(contents1_.get(), score1 + 1.0));
+  EXPECT_CALL(mock_, NotifyTabScoreChanged(contents2_.get(), score2 + 2.0));
+  WaitForFinalTabScores();
+}
+
 }  // namespace resource_coordinator
diff --git a/chrome/browser/resources/settings/about_page/BUILD.gn b/chrome/browser/resources/settings/about_page/BUILD.gn
index 333dc4020..54af5d44 100644
--- a/chrome/browser/resources/settings/about_page/BUILD.gn
+++ b/chrome/browser/resources/settings/about_page/BUILD.gn
@@ -10,15 +10,12 @@
     ":about_page_browser_proxy",
     ":channel_switcher_dialog",
     ":detailed_build_info",
-    ":management_browser_proxy",
-    ":management_page",
   ]
 }
 
 js_library("about_page") {
   deps = [
     ":about_page_browser_proxy",
-    ":management_browser_proxy",
     "..:lifetime_browser_proxy",
     "..:route",
     "../settings_page:main_page_behavior",
@@ -54,18 +51,3 @@
     "//ui/webui/resources/js:load_time_data",
   ]
 }
-
-js_library("management_browser_proxy") {
-  deps = [
-    "//ui/webui/resources/js:cr",
-    "//ui/webui/resources/js:load_time_data",
-    "//ui/webui/resources/js:promise_resolver",
-    "//ui/webui/resources/js:util",
-  ]
-}
-
-js_library("management_page") {
-  deps = [
-    ":management_browser_proxy",
-  ]
-}
diff --git a/chrome/browser/resources/settings/about_page/about_page.html b/chrome/browser/resources/settings/about_page/about_page.html
index 7590e6e..9968dfd 100644
--- a/chrome/browser/resources/settings/about_page/about_page.html
+++ b/chrome/browser/resources/settings/about_page/about_page.html
@@ -22,8 +22,6 @@
 <if expr="chromeos">
 <link rel="import" href="detailed_build_info.html">
 <link rel="import" href="update_warning_dialog.html">
-<link rel="import" href="management_browser_proxy.html">
-<link rel="import" href="management_page.html">
 <link rel="import" href="../settings_page/settings_subpage.html">
 <link rel="import" href="../reset_page/powerwash_dialog.html">
 </if>
@@ -232,11 +230,6 @@
               id="detailed-build-info-trigger"
               on-click="onDetailedBuildInfoTap_"
               label="$i18n{aboutDetailedBuildInfo}"></cr-link-row>
-          <cr-link-row class="hr" icon-class="subpage-arrow"
-              start-icon="settings:business"
-              id="management-info"
-              on-click="onManagementInfoTap_"
-              label="[[managementTitle_]]"></cr-link-row>
 </if>
         </div>
 <if expr="chromeos">
@@ -245,11 +238,6 @@
             <settings-detailed-build-info></settings-detailed-build-info>
           </settings-subpage>
         </template>
-        <template is="dom-if" route-path="/help/management">
-          <settings-subpage page-title="[[managementTitle_]]">
-            <settings-management-page></settings-management-page>
-          </settings-subpage>
-        </template>
 </if>
       </settings-animated-pages>
     </settings-section>
diff --git a/chrome/browser/resources/settings/about_page/about_page.js b/chrome/browser/resources/settings/about_page/about_page.js
index b51b9fd..df989aa3 100644
--- a/chrome/browser/resources/settings/about_page/about_page.js
+++ b/chrome/browser/resources/settings/about_page/about_page.js
@@ -125,14 +125,6 @@
     },
 
     /** @private */
-    managementTitle_: {
-      type: String,
-      // TODO(raleksandrov): Better to use string from management_strings as
-      // default value here, but this should be never shown.
-      value: 'Management overview',
-    },
-
-    /** @private */
     showUpdateWarningDialog_: {
       type: Boolean,
       value: false,
@@ -169,9 +161,6 @@
     // </if>
   ],
 
-  /** @private {?settings.ManagementBrowserProxy} */
-  browserProxy_: null,
-
   /** @private {?settings.AboutPageBrowserProxy} */
   aboutBrowserProxy_: null,
 
@@ -205,10 +194,6 @@
       this.hasEndOfLife_ = result;
     });
 
-    this.browserProxy_ = settings.ManagementBrowserProxyImpl.getInstance();
-    this.browserProxy_.getManagementTitle().then(title => {
-      this.managementTitle_ = title;
-    });
     // </if>
     // <if expr="not chromeos">
     this.startListening_();
@@ -532,11 +517,6 @@
   },
 
   /** @private */
-  onManagementInfoTap_: function() {
-    settings.navigateTo(settings.routes.MANAGEMENT_INFO);
-  },
-
-  /** @private */
   onRelaunchAndPowerwashTap_: function() {
     if (this.currentUpdateStatusEvent_.rollback) {
       // Wipe already initiated, simply relaunch.
diff --git a/chrome/browser/resources/settings/about_page/management_browser_proxy.html b/chrome/browser/resources/settings/about_page/management_browser_proxy.html
deleted file mode 100644
index abaff42..0000000
--- a/chrome/browser/resources/settings/about_page/management_browser_proxy.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<link rel="import" href="chrome://resources/html/cr.html">
-<script src="management_browser_proxy.js"></script>
diff --git a/chrome/browser/resources/settings/about_page/management_browser_proxy.js b/chrome/browser/resources/settings/about_page/management_browser_proxy.js
deleted file mode 100644
index 17be3bf..0000000
--- a/chrome/browser/resources/settings/about_page/management_browser_proxy.js
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-cr.exportPath('settings');
-/**
- * @typedef {{
- *    name: string,
- *    permissions: !Array<string>
- * }}
- */
-settings.Extension;
-
-cr.define('settings', function() {
-  /** @interface */
-  class ManagementBrowserProxy {
-    /**
-     * @return {!Promise<string>} Return title of the management page
-     */
-    getManagementTitle() {}
-
-    /**
-     * @return {!Promise<string>} Message stating if device is enterprise
-     * managed and by whom.
-     */
-    getDeviceManagementStatus() {}
-
-    /**
-     * @return {!Promise<!Array<string>>} Types of device reporting.
-     */
-    getReportingDevice() {}
-
-    /**
-     * @return {!Promise<!Array<string>>} Types of device reporting.
-     */
-    getReportingSecurity() {}
-
-    /**
-     * @return {!Promise<!Array<string>>} Types of device reporting.
-     */
-    getReportingUserActivity() {}
-
-    /**
-     * @return {!Promise<!Array<string>>} Types of device reporting.
-     */
-    getReportingWeb() {}
-
-    /**
-     * Each extension has a name and a list of permission messages.
-     * @return {!Promise<!Array<!settings.Extension>>} List of extensions.
-     */
-    getExtensions() {}
-
-    /**
-     * @return {!Promise<boolean>} Boolean describing trust root configured
-     * or not.
-     */
-    getLocalTrustRootsInfo() {}
-  }
-
-  /**
-   * @implements {settings.ManagementBrowserProxy}
-   */
-  class ManagementBrowserProxyImpl {
-    /** @override */
-    getManagementTitle() {
-      return cr.sendWithPromise('getManagementTitle');
-    }
-
-    /** @override */
-    getDeviceManagementStatus() {
-      return cr.sendWithPromise('getDeviceManagementStatus');
-    }
-
-    /** @override */
-    getReportingDevice() {
-      return cr.sendWithPromise('getReportingDevice');
-    }
-
-    /** @override */
-    getReportingSecurity() {
-      return cr.sendWithPromise('getReportingSecurity');
-    }
-
-    /** @override */
-    getReportingUserActivity() {
-      return cr.sendWithPromise('getReportingUserActivity');
-    }
-
-    /** @override */
-    getReportingWeb() {
-      return cr.sendWithPromise('getReportingWeb');
-    }
-
-    /** @override */
-    getExtensions() {
-      return cr.sendWithPromise('getExtensions');
-    }
-
-    /** @override */
-    getLocalTrustRootsInfo() {
-      return cr.sendWithPromise('getLocalTrustRootsInfo');
-    }
-  }
-
-  // Make Page a singleton.
-  cr.addSingletonGetter(ManagementBrowserProxyImpl);
-
-  return {
-    ManagementBrowserProxy: ManagementBrowserProxy,
-    ManagementBrowserProxyImpl: ManagementBrowserProxyImpl
-  };
-});
diff --git a/chrome/browser/resources/settings/about_page/management_page.html b/chrome/browser/resources/settings/about_page/management_page.html
deleted file mode 100644
index d4ada60..0000000
--- a/chrome/browser/resources/settings/about_page/management_page.html
+++ /dev/null
@@ -1,149 +0,0 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-
-<link rel="import" href="management_browser_proxy.html">
-<link rel="import" href="../settings_shared_css.html">
-<link rel="import" href="../icons.html">
-<link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-
-<dom-module id="settings-management-page">
-  <template>
-    <style include="settings-shared">
-      cr-policy-indicator {
-        margin-inline-start: var(--cr-controlled-by-spacing);
-      }
-
-      h2 {
-        @apply --cr-title-text;
-        font-weight: 600;
-      }
-
-      ul {
-        list-style-type : none;
-        margin: 0;
-        padding: 0;
-        text-align: start;
-      }
-
-      #reportingInfoList div {
-        align-items: center;
-        display: flex;
-      }
-
-      #reportingInfoList div + div {
-        margin-top: 2em;
-      }
-
-      #reportingInfoList iron-icon {
-        margin-inline-end: 10px;
-        width: 24px;
-      }
-
-      #reportingInfoList,
-      #extensionsTable {
-        margin-bottom: 2em;
-      }
-
-      .table-head {
-        font-weight: 500;
-      }
-
-      .extension-name {
-        width: 30%;
-      }
-
-      .extension-permissions {
-        width: 70%;
-      }
-
-      .content-indented {
-        margin-inline-start: 20px;
-      }
-
-      .subtitle {
-        margin-bottom: 1em;
-        margin-top: 1em;
-      }
-
-    </style>
-      <!--  This is where page content gets dynamically added. -->
-
-      <div class="settings-box two-line single-column"
-           id="managementStatus" hidden>
-        <span id="managementStatusInfo">
-          <a href="$i18nRaw{managementLearnMoreUrl}" target="_blank">
-            $i18n{learnMore}</a>
-        </span>
-      </div>
-
-      <template is="dom-if" if="[[!shouldHidePolicies_(reportingDevice_,
-          reportingSecurity_, reportingUserActivity_, reportingWeb_)]]">
-        <div class="settings-box block single-column" id="policies">
-          <h2>$i18n{managementDeviceReporting}</h2>
-          <div class="content-indented subtitle" id="deviceConfiguration">
-              $i18n{managementDeviceConfiguration}
-          </div>
-          <div id="reportingInfoList">
-            <div class="content-indented"
-              hidden$="[[!reportingDevice_.length]]">
-              <iron-icon icon="settings:computer"></iron-icon>
-              <ul>
-                <template is="dom-repeat" items="[[reportingDevice_]]">
-                  <li>[[i18n(item)]]</li>
-                </template>
-              </ul>
-            </div>
-            <div class="content-indented"
-              hidden$="[[!reportingSecurity_.length]]">
-              <iron-icon icon="settings:security"></iron-icon>
-              <ul>
-                <template is="dom-repeat" items="[[reportingSecurity_]]">
-                  <li>[[i18n(item)]]</li>
-                </template>
-              </ul>
-            </div>
-            <div class="content-indented"
-              hidden$="[[!reportingUserActivity_.length]]">
-              <iron-icon icon="settings:person"></iron-icon>
-              <ul>
-                <template is="dom-repeat" items="[[reportingUserActivity_]]">
-                  <li>[[i18n(item)]]</li>
-                </template>
-              </ul>
-            </div>
-            <div class="content-indented" hidden$="[[!reportingWeb_.length]]">
-              <iron-icon icon="settings:public"></iron-icon>
-              <ul>
-                <template is="dom-repeat" items="[[reportingWeb_]]">
-                  <li>[[i18n(item)]]</li>
-                </template>
-              </ul>
-            </div>
-          </div>
-        </div>
-      </template>
-
-      <div class="settings-box two-line single-column" id="extensions" hidden>
-        <h2>$i18n{managementExtensionReporting}</h2>
-        <div class="content-indented subtitle" id="extensionsInstalled">
-          $i18n{managementExtensionsInstalled}
-        </div>
-        <table class="content-indented" id="extensionsTable">
-          <tr>
-              <td class="extension-name table-head">
-                $i18n{managementExtensionName}
-              </td>
-              <td class="extension-permissions table-head">
-                $i18n{managementExtensionPermissions}
-              </td>
-          </tr>
-        </table>
-      </div>
-
-      <div class="settings-box two-line single-column" id="trustRoots" hidden>
-          <h2>$i18n{managementLocalTrustRoots}</h2>
-          <div class="content-indented" id="trustRootsConfiguration"></div>
-      </div>
-  </template>
-  <script src="management_page.js"></script>
-</dom-module>
diff --git a/chrome/browser/resources/settings/about_page/management_page.js b/chrome/browser/resources/settings/about_page/management_page.js
deleted file mode 100644
index 16bf68d..0000000
--- a/chrome/browser/resources/settings/about_page/management_page.js
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview 'settings-management-page' contains scary information
- * about ChromeOS privacy.
- */
-Polymer({
-  is: 'settings-management-page',
-
-  behaviors: [I18nBehavior],
-
-  properties: {
-    /** @private {!Array<string>} */
-    reportingDevice_: Array,
-
-    /** @private {!Array<string>} */
-    reportingSecurity_: Array,
-
-    /** @private {!Array<string>} */
-    reportingUserActivity_: Array,
-
-    /** @private {!Array<string>} */
-    reportingWeb_: Array,
-  },
-
-  /** @private {?settings.ManagementBrowserProxy} */
-  browserProxy_: null,
-
-  /**
-   * @return {boolean}
-   * @private
-   */
-  shouldHidePolicies_: function() {
-    return !this.reportingDevice_.length && !this.reportingSecurity_.length &&
-        !this.reportingUserActivity_.length && !this.reportingWeb_.length;
-  },
-
-  /** @private */
-  getDeviceManagementStatus_: function() {
-    this.browserProxy_.getDeviceManagementStatus()
-        .then(managedString => {
-          this.$.managementStatusInfo.firstChild.data = managedString + ' ';
-          this.$.managementStatus.hidden = false;
-        })
-        .catch(
-            // On Chrome desktop, the behavior is to show nothing (device
-            // management is outside of Chrome's control), so
-            // RejectJavascriptCallback is used, which throws an error. The
-            // intended handling in this case is to do nothing.
-            () => {});
-  },
-
-  /** @private */
-  getExtensions_: function() {
-    // Show names and permissions of |extensions| in a table.
-    this.browserProxy_.getExtensions().then(extensions => {
-      if (extensions.length == 0) {
-        return;
-      }
-
-      const table = this.$.extensionsTable;
-
-      for (const /** settings.Extension */ extension of extensions) {
-        assert(
-            extension.hasOwnProperty('permissions'),
-            'Each extension must have the permissions field');
-        assert(
-            extension.hasOwnProperty('name'),
-            'Each extension must have the name field');
-
-        const permissionsList = document.createElement('ul');
-        for (const perm of extension.permissions) {
-          const permissionElement = document.createElement('li');
-          permissionElement.textContent = perm;
-          permissionsList.appendChild(permissionElement);
-        }
-
-        const row = table.insertRow();
-        const nameCell = row.insertCell();
-        nameCell.className = 'extension-name';
-        // insertCell(-1) inserts at the last position.
-        const permissionsCell = row.insertCell(-1);
-        permissionsCell.className = 'extension-permissions';
-        nameCell.textContent = extension.name;
-        permissionsCell.appendChild(permissionsList);
-      }
-
-      this.$.extensions.hidden = false;
-    });
-  },
-
-  /** @private */
-  getLocalTrustRootsInfo_: function() {
-    this.browserProxy_.getLocalTrustRootsInfo().then(trustRootsConfigured => {
-      if (trustRootsConfigured) {
-        this.$.trustRootsConfiguration.textContent =
-            loadTimeData.getString('managementTrustRootsConfigured');
-        this.$.trustRoots.hidden = false;
-      }
-    });
-  },
-
-  /** @override */
-  attached: function() {
-    this.browserProxy_ = settings.ManagementBrowserProxyImpl.getInstance();
-
-    this.getDeviceManagementStatus_();
-
-    this.browserProxy_.getReportingDevice().then(reportingSources => {
-      this.reportingDevice_ = reportingSources;
-    });
-
-    this.browserProxy_.getReportingSecurity().then(reportingSources => {
-      this.reportingSecurity_ = reportingSources;
-    });
-
-    this.browserProxy_.getReportingUserActivity().then(reportingSources => {
-      this.reportingUserActivity_ = reportingSources;
-    });
-
-    this.browserProxy_.getReportingWeb().then(reportingSources => {
-      this.reportingWeb_ = reportingSources;
-    });
-
-    this.getExtensions_();
-
-    this.getLocalTrustRootsInfo_();
-  },
-});
diff --git a/chrome/browser/resources/settings/icons.html b/chrome/browser/resources/settings/icons.html
index 735f01b..8a557ec 100644
--- a/chrome/browser/resources/settings/icons.html
+++ b/chrome/browser/resources/settings/icons.html
@@ -77,7 +77,6 @@
 <if expr="not chromeos">
       <g id="build"><path d="M22.7 19l-9.1-9.1c.9-2.3.4-5-1.5-6.9-2-2-5-2.4-7.4-1.3L9 6 6 9 1.6 4.7C.4 7.1.9 10.1 2.9 12.1c1.9 1.9 4.6 2.4 6.9 1.5l9.1 9.1c.4.4 1 .4 1.4 0l2.3-2.3c.5-.4.5-1.1.1-1.4z"></path></g>
 </if>
-      <g id="business"><path d="M12 7V3H2v18h20V7H12zM6 19H4v-2h2v2zm0-4H4v-2h2v2zm0-4H4V9h2v2zm0-4H4V5h2v2zm4 12H8v-2h2v2zm0-4H8v-2h2v2zm0-4H8V9h2v2zm0-4H8V5h2v2zm10 12h-8v-2h2v-2h-2v-2h2v-2h-2V9h8v10zm-2-8h-2v2h2v-2zm0 4h-2v2h2v-2z"></path></g>
       <g id="check-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"></path></g>
 <if expr="chromeos">
       <g id="chevron-left"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"</path></g>
@@ -118,17 +117,14 @@
       <g id="pdf"><path d="M7 11.5h1v-1H7v1zM19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-9.5 8.5c0 .83-.67 1.5-1.5 1.5H7v2H5.5V9H8c.83 0 1.5.67 1.5 1.5v1zm10-1H17v1h1.5V13H17v2h-1.5V9h4v1.5zm-5 3c0 .83-.67 1.5-1.5 1.5h-2.5V9H13c.83 0 1.5.67 1.5 1.5v3zm-2.5 0h1v-3h-1v3z"></path><path fill="none" d="M0 0h24v24H0z"></path></g>
       <g id="palette"><path d="M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9c.83 0 1.5-.67 1.5-1.5 0-.39-.15-.74-.39-1.01-.23-.26-.38-.61-.38-.99 0-.83.67-1.5 1.5-1.5H16c2.76 0 5-2.24 5-5 0-4.42-4.03-8-9-8zm-5.5 9c-.83 0-1.5-.67-1.5-1.5S5.67 9 6.5 9 8 9.67 8 10.5 7.33 12 6.5 12zm3-4C8.67 8 8 7.33 8 6.5S8.67 5 9.5 5s1.5.67 1.5 1.5S10.33 8 9.5 8zm5 0c-.83 0-1.5-.67-1.5-1.5S13.67 5 14.5 5s1.5.67 1.5 1.5S15.33 8 14.5 8zm3 4c-.83 0-1.5-.67-1.5-1.5S16.67 9 17.5 9s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"></path></g>
       <g id="payment-handler"><path d="M20 4H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4v-6h16v6zm0-10H4V6h16v2z"></path></g>
-      <g id="person"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"></path></g>
       <g id="photo"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"></path></g>
       <g id="power-settings-new"><path d="M13 3h-2v10h2V3zm4.83 2.17l-1.42 1.42C17.99 7.86 19 9.81 19 12c0 3.87-3.13 7-7 7s-7-3.13-7-7c0-2.19 1.01-4.14 2.58-5.42L6.17 5.17C4.23 6.82 3 9.26 3 12c0 4.97 4.03 9 9 9s9-4.03 9-9c0-2.74-1.23-5.18-3.17-6.83z"></path></g>
       <g id="protocol-handler"><path d="M21.72 11.33l-6.644-7.035a.97.97 0 0 0-1.38-.01l-1.67 1.72-1.617-1.712a.97.97 0 0 0-1.38-.01l-6.737 6.935c-.187.191-.29.447-.292.719-.002.272.099.529.28.722l6.644 7.034a.949.949 0 0 0 1.38.011l1.671-1.718 1.615 1.71a.949.949 0 0 0 1.381.01l6.74-6.935a1.054 1.054 0 0 0 .01-1.44zM6.947 12.464l3.657 3.785-.974.98-5.273-5.456 5.349-5.378.929.962-3.677 3.7a.998.998 0 0 0-.292.702 1 1 0 0 0 .28.705zm7.35 4.768l-.931-.963 3.68-3.7a1.012 1.012 0 0 0 .007-1.407l-3.656-3.784.974-.98 5.273 5.456-5.348 5.378z"></path></g>
-      <g id="public"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"></path></g>
       <g id="restore"><path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z"></path></g>
       <g id="rotate-right"><path d="M15.55 5.55L11 1v3.07C7.06 4.56 4 7.92 4 12s3.05 7.44 7 7.93v-2.02c-2.84-.48-5-2.94-5-5.91s2.16-5.43 5-5.91V10l4.55-4.45zM19.93 11c-.17-1.39-.72-2.73-1.62-3.89l-1.42 1.42c.54.75.88 1.6 1.02 2.47h2.02zM13 17.9v2.02c1.39-.17 2.74-.71 3.9-1.61l-1.44-1.44c-.75.54-1.59.89-2.46 1.03zm3.89-2.42l1.42 1.41c.9-1.16 1.45-2.5 1.62-3.89h-2.02c-.14.87-.48 1.72-1.02 2.48z"></path></g>
       <g id="sensors"><path d="M10 8.5c-0.8 0-1.5 0.7-1.5 1.5s0.7 1.5 1.5 1.5s1.5-0.7 1.5-1.5S10.8 8.5 10 8.5z M7.6 5.8 C6.2 6.7 5.2 8.2 5.2 10c0 1.8 1 3.4 2.4 4.2l0.8-1.4c-1-0.6-1.6-1.6-1.6-2.8c0-1.2 0.6-2.2 1.6-2.8L7.6 5.8z M14.8 10 c0-1.8-1-3.4-2.4-4.2l-0.8 1.4c0.9 0.6 1.6 1.6 1.6 2.8c0 1.2-0.6 2.2-1.6 2.8l0.8 1.4C13.8 13.4 14.8 11.8 14.8 10z M6 3 c-2.4 1.4-4 4-4 7c0 3 1.6 5.6 4 7l0.8-1.4c-1.9-1.1-3.2-3.2-3.2-5.6c0-2.4 1.3-4.5 3.2-5.6L6 3z M13.2 4.4 c1.9 1.1 3.2 3.2 3.2 5.6c0 2.4-1.3 4.5-3.2 5.6L14 17c2.4-1.4 4-4 4-7c0-3-1.6-5.6-4-7L13.2 4.4z"></path></g>
 <if expr="chromeos">
       <g id="alert-device-out-of-range" fill="none" fill-rule="evenodd"><path d="M-1-1h20v20H-1z"></path><path fill="#C53929" fill-rule="nonzero" d="M8.167 11.5h1.666v1.667H8.167V11.5zm0-6.667h1.666v5H8.167v-5zM8.992.667C4.392.667.667 4.4.667 9s3.725 8.333 8.325 8.333c4.608 0 8.341-3.733 8.341-8.333S13.6.667 8.992.667zm.008 15A6.665 6.665 0 0 1 2.333 9 6.665 6.665 0 0 1 9 2.333 6.665 6.665 0 0 1 15.667 9 6.665 6.665 0 0 1 9 15.667z"></path></g>
-      <g id="security"><path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z"></path></g>
       <g id="signal-cellular-0-bar"><path fill-opacity=".3" d="M2 22h20V2z"></path></g>
       <g id="signal-cellular-1-bar"><path fill-opacity=".3" d="M2 22h20V2z"></path><path d="M12 12L2 22h10z"></path></g>
       <g id="signal-cellular-2-bar"><path fill-opacity=".3" d="M2 22h20V2z"></path><path d="M14 10L2 22h12z"></path></g>
diff --git a/chrome/browser/resources/settings/route.js b/chrome/browser/resources/settings/route.js
index d1e832b..61d7c61c 100644
--- a/chrome/browser/resources/settings/route.js
+++ b/chrome/browser/resources/settings/route.js
@@ -52,7 +52,6 @@
  *   MANAGE_ACCESSIBILITY: (undefined|!settings.Route),
  *   MANAGE_PROFILE: (undefined|!settings.Route),
  *   MANAGE_TTS_SETTINGS: (undefined|!settings.Route),
- *   MANAGEMENT_INFO : (undefined|!settings.Route),
  *   MULTIDEVICE: (undefined|!settings.Route),
  *   MULTIDEVICE_FEATURES: (undefined|!settings.Route),
  *   NETWORK_DETAIL: (undefined|!settings.Route),
@@ -435,7 +434,6 @@
     // route in order to show the subpage on Chrome OS.
     r.ABOUT_ABOUT = r.ABOUT.createSection('/help/about', 'about');
     r.DETAILED_BUILD_INFO = r.ABOUT_ABOUT.createChild('/help/details');
-    r.MANAGEMENT_INFO = r.ABOUT_ABOUT.createChild('/help/management');
     // </if>
 
     return r;
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd
index ea6d6f7..149c085 100644
--- a/chrome/browser/resources/settings/settings_resources.grd
+++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -74,18 +74,6 @@
         <structure name="IDR_SETTINGS_UPDATE_WARNING_DIALOG_JS"
                    file="about_page/update_warning_dialog.js"
                    type="chrome_html" />
-        <structure name="IDR_SETTINGS_MANAGEMENT_PAGE_HTML"
-                    file="about_page/management_page.html"
-                    type="chrome_html"/>
-        <structure name="IDR_SETTINGS_MANAGEMENT_PAGE_JS"
-                    file="about_page/management_page.js"
-                    type="chrome_html"/>
-        <structure name="IDR_SETTINGS_MANAGEMENT_BROWSER_PROXY_HTML"
-                    file="about_page/management_browser_proxy.html"
-                    type="chrome_html"/>
-        <structure name="IDR_SETTINGS_MANAGEMENT_PROXY_JS"
-                    file="about_page/management_browser_proxy.js"
-                    type="chrome_html"/>
       </if>
       <structure name="IDR_SETTINGS_ADD_SITE_DIALOG_HTML"
                  file="site_settings/add_site_dialog.html"
diff --git a/chrome/browser/sessions/session_restore_observer_unittest.cc b/chrome/browser/sessions/session_restore_observer_unittest.cc
index aa1a94c..4a3fdfd 100644
--- a/chrome/browser/sessions/session_restore_observer_unittest.cc
+++ b/chrome/browser/sessions/session_restore_observer_unittest.cc
@@ -7,7 +7,6 @@
 #include <set>
 #include <vector>
 
-#include "base/run_loop.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/resource_coordinator/tab_helper.h"
 #include "chrome/browser/resource_coordinator/tab_load_tracker.h"
diff --git a/chrome/browser/sessions/tab_loader.cc b/chrome/browser/sessions/tab_loader.cc
index a55f56cc..ed8ea1f6 100644
--- a/chrome/browser/sessions/tab_loader.cc
+++ b/chrome/browser/sessions/tab_loader.cc
@@ -45,6 +45,15 @@
   return default_tick_clock.get();
 }
 
+// An implementation of operator< for scored tabs.
+struct ScoredTabComparator {
+  bool operator()(const std::pair<float, content::WebContents*> tab0,
+                  const std::pair<float, content::WebContents*> tab1) {
+    // Greater scores sort first.
+    return tab0.first > tab1.first;
+  }
+};
+
 // Testing seams.
 size_t g_max_loaded_tab_count_for_testing = 0;
 base::RepeatingCallback<void(TabLoader*)>* g_construction_callback = nullptr;
@@ -133,6 +142,62 @@
   MaybeLoadSomeTabs();
 }
 
+void TabLoader::SetTabLoadingEnabledCallbackForTesting(
+    base::RepeatingCallback<void(bool)>* callback) {
+  tab_loading_enabled_callback_ = callback;
+}
+
+bool TabLoader::IsLoadingEnabled() const {
+  return loading_enabled_ && all_tabs_scored_;
+}
+
+void TabLoader::OnIsLoadingEnabledChanged() {
+  ReentrancyHelper lifetime_helper(this);
+
+  // TODO(chrisha): Make the SessionRestoreStatsCollector aware that tab loading
+  // was explicitly stopped or restarted. This can be used to invalidate various
+  // metrics.
+
+  if (IsLoadingEnabled()) {
+    // Extend the timeouts of all loading tabs by the duration that tab loading
+    // was disabled. This is to ensure that there's not a flurry of tab load
+    // timeouts that all occur at once when loading is re-enabled.
+    base::TimeDelta delta = clock_->NowTicks() - tab_loading_disabled_time_;
+    for (auto const_tab : tabs_loading_) {
+      // Directly modify the underlying data. This will temporarily invalidate
+      // the ordering condition of the set, but by incrementing all elements
+      // equally the ordering condition will hold again when finished.
+      LoadingTab* tab = const_cast<LoadingTab*>(&const_tab);
+      tab->loading_start_time += delta;
+    }
+
+    StartTimerIfNeeded();
+    MaybeLoadSomeTabs();
+  } else {
+    StartTimerIfNeeded();
+    tab_loading_disabled_time_ = clock_->NowTicks();
+  }
+
+  if (tab_loading_enabled_callback_)
+    tab_loading_enabled_callback_->Run(IsLoadingEnabled());
+}
+
+void TabLoader::SetAllTabsScored(bool all_tabs_scored) {
+  DCHECK(reentry_depth_ > 0);  // This can only be called internally.
+  if (all_tabs_scored == all_tabs_scored_)
+    return;
+
+  if (all_tabs_scored) {
+    DCHECK(std::is_sorted(tabs_to_load_.begin(), tabs_to_load_.end(),
+                          ScoredTabComparator()));
+  }
+
+  bool was_loading_enabled = IsLoadingEnabled();
+  all_tabs_scored_ = all_tabs_scored;
+  if (was_loading_enabled != IsLoadingEnabled())
+    OnIsLoadingEnabledChanged();
+}
+
 TabLoader::TabLoader(base::TimeTicks restore_started)
     : memory_pressure_listener_(
           base::Bind(&TabLoader::OnMemoryPressure, base::Unretained(this))),
@@ -166,24 +231,41 @@
 
 void TabLoader::SetTabLoadingEnabled(bool loading_enabled) {
   ReentrancyHelper lifetime_helper(this);
-
-  // TODO(chrisha): Make the SessionRestoreStatsCollector aware that tab loading
-  // was explicitly stopped or restarted. This can be used to invalidate various
-  // metrics.
-  if (loading_enabled == is_loading_enabled_)
+  if (loading_enabled == loading_enabled_)
     return;
-  is_loading_enabled_ = loading_enabled;
-  if (is_loading_enabled_) {
-    StartTimerIfNeeded();
-    MaybeLoadSomeTabs();
-  } else {
-    // When active tab loading is reenabled all loads that were initiated before
-    // or during the period when it was disabled can be ignored for timeout
-    // purposes. Otherwise a bunch of tabs may simultaneously timeout and cause
-    // a lot of simultaneous loads.
-    tabs_loading_.clear();
-    StartTimerIfNeeded();
+  bool was_loading_enabled = IsLoadingEnabled();
+  loading_enabled_ = loading_enabled;
+  if (was_loading_enabled != IsLoadingEnabled())
+    OnIsLoadingEnabledChanged();
+}
+
+void TabLoader::NotifyTabScoreChanged(content::WebContents* contents,
+                                      float score) {
+  ReentrancyHelper lifetime_helper(this);
+
+  // If |contents| is specified this is an update of the score for a tab.
+  if (contents) {
+    auto it = FindTabToLoad(contents);
+    it->first = score;
+
+    // If all tabs are already scored (indicating they are sorted) then keep the
+    // tab order sorted.
+    if (all_tabs_scored_)
+      MoveToSortedPosition(it);
+
+    return;
   }
+
+  // Otherwise, this is the policy engine telling us all tabs now have initial
+  // scores. This should only happen after a call to StartLoading, which
+  // implicitly disables tab loading initially. Sort all tabs and start
+  // loading again.
+  DCHECK(!contents);
+  DCHECK(!all_tabs_scored_);
+  DCHECK(!IsLoadingEnabled());
+  std::stable_sort(tabs_to_load_.begin(), tabs_to_load_.end(),
+                   ScoredTabComparator());
+  SetAllTabsScored(true);
 }
 
 void TabLoader::StartLoading(const std::vector<RestoredTab>& tabs) {
@@ -224,15 +306,10 @@
     AddTab(restored_tab.contents());
   }
 
-  StartTimerIfNeeded();
-
-  // When multiple profiles are using the same TabLoader, another profile might
-  // already have started loading. In that case a delegate was already created
-  // and tab loading had already started. Only the initial call to StartLoading
-  // needs to kick off tab loads, as otherwise the state machine is already in
-  // operation.
-  if (!delegate_existed)
-    MaybeLoadSomeTabs();
+  // Disable loading for now, and wait for the policy engine to come back with
+  // a full sort order for the tabs to be loaded. This happens via
+  // NotifyTabScoreChanged.
+  SetAllTabsScored(false);
 }
 
 void TabLoader::OnLoadingStateChange(WebContents* contents,
@@ -242,7 +319,7 @@
   TRACE_EVENT0("browser", "TabLoader::OnLoadingStateChange");
 
   // Calls into this can come from observers that are still running even if
-  // |is_loading_enabled_| is false.
+  // IsLoadingEnabled() is false.
   switch (new_loading_state) {
     // It could be that a tab starts loading from outside of our control. In
     // this case we can consider it as having started to load, and the load
@@ -356,7 +433,13 @@
     return;
   }
 
-  tabs_to_load_.push_back(contents);
+  // Higher scores are more important tabs. Store the score as a negative number
+  // so the more important tabs sort first.
+  float score = delegate_->AddTabForScoring(contents);
+  tabs_to_load_.push_back(std::make_pair(score, contents));
+
+  // Sorting doesn't need to be done here, as it is done en masse once all tab
+  // scores are finalized.
 }
 
 void TabLoader::RemoveTab(WebContents* contents) {
@@ -375,9 +458,11 @@
   tabs_load_initiated_.erase(contents);
 
   {
-    auto it = std::find(tabs_to_load_.begin(), tabs_to_load_.end(), contents);
-    if (it != tabs_to_load_.end())
+    auto it = FindTabToLoad(contents);
+    if (it != tabs_to_load_.end()) {
       tabs_to_load_.erase(it);
+      delegate_->RemoveTabForScoring(contents);
+    }
   }
 }
 
@@ -387,9 +472,10 @@
 
   // This can only be called for a tab that is waiting to be loaded so this
   // should never fail.
-  auto it = std::find(tabs_to_load_.begin(), tabs_to_load_.end(), contents);
+  auto it = FindTabToLoad(contents);
   DCHECK(it != tabs_to_load_.end());
   tabs_to_load_.erase(it);
+  delegate_->RemoveTabForScoring(contents);
 
   // Tabs are considered as starting to load the moment we schedule the load.
   // The actual load notification from TabLoadTracker comes some point after
@@ -404,7 +490,7 @@
   TRACE_EVENT0("browser", "TabLoader::MarkTabAsLoading");
 
   // Calls into this can come from observers that are still running even if
-  // |is_loading_enabled_| is false.
+  // IsLoadingEnabled is true.
 
   // We get notifications for tabs that we're not explicitly tracking, so
   // gracefully handle this.
@@ -423,11 +509,12 @@
   // Second check to see if its a tab load that we did not initiate, but which
   // is being tracked by us.
   {
-    auto it = std::find(tabs_to_load_.begin(), tabs_to_load_.end(), contents);
+    auto it = FindTabToLoad(contents);
     if (it != tabs_to_load_.end()) {
       tabs_to_load_.erase(it);
       tabs_loading_.insert(LoadingTab{clock_->NowTicks(), contents});
       delegate_->NotifyTabLoadStarted();
+      delegate_->RemoveTabForScoring(contents);
       ++scheduled_to_load_count_;
       return;
     }
@@ -440,9 +527,10 @@
 
   // This can only be called for a tab that is waiting to be loaded so this
   // should never fail.
-  auto it = std::find(tabs_to_load_.begin(), tabs_to_load_.end(), contents);
+  auto it = FindTabToLoad(contents);
   DCHECK(it != tabs_to_load_.end());
   tabs_to_load_.erase(it);
+  delegate_->RemoveTabForScoring(contents);
   stats_collector_->DeferTab(&contents->GetController());
 }
 
@@ -450,7 +538,7 @@
   DCHECK(reentry_depth_ > 0);  // This can only be called internally.
   TRACE_EVENT0("browser", "TabLoader::MaybeLoadSomeTabs");
 
-  if (!is_loading_enabled_ || tabs_to_load_.empty())
+  if (!IsLoadingEnabled() || tabs_to_load_.empty())
     return;
 
   // Continue to load tabs while possible. This is in a loop with a
@@ -467,7 +555,7 @@
   // CheckInvariants can't be called directly as the timer is no longer
   // running at this point. However, the conditions under which the timer
   // should be running can be checked.
-  DCHECK(is_loading_enabled_);
+  DCHECK(IsLoadingEnabled());
   DCHECK(!tabs_to_load_.empty());
   DCHECK(!tabs_loading_.empty());
   DCHECK(!force_load_time_.is_null());
@@ -497,14 +585,17 @@
   TRACE_EVENT0("browser", "TabLoader::StopLoadingTabs");
 
   // Calls into this can come from observers that are still running even if
-  // |is_loading_enabled_| is false.
+  // IsLoadingEnabled() is already false.
 
   // Stop the timer and suppress any tab loads while we clean the list.
   SetTabLoadingEnabled(false);
 
   // Notify the stats collector of deferred tabs.
-  for (auto* contents : tabs_to_load_)
+  for (auto score_content_pair : tabs_to_load_) {
+    auto* contents = score_content_pair.second;
+    delegate_->RemoveTabForScoring(contents);
     stats_collector_->DeferTab(&contents->GetController());
+  }
 
   // Clear out the remaining tabs to load and clean ourselves up.
   tabs_to_load_.clear();
@@ -520,7 +611,7 @@
   // Find the next tab to load. This skips tabs that the delegate decides
   // shouldn't be loaded at this moment.
   while (!tabs_to_load_.empty()) {
-    WebContents* contents = tabs_to_load_.front();
+    WebContents* contents = tabs_to_load_.front().second;
     if (delegate_->ShouldLoad(contents))
       return contents;
     MarkTabAsDeferred(contents);
@@ -582,7 +673,7 @@
 void TabLoader::StartTimerIfNeeded() {
   DCHECK(reentry_depth_ > 0);  // This can only be called internally.
 
-  if (!is_loading_enabled_ || tabs_to_load_.empty() || tabs_loading_.empty()) {
+  if (!IsLoadingEnabled() || tabs_to_load_.empty() || tabs_loading_.empty()) {
     if (force_load_timer_.IsRunning()) {
       force_load_time_ = base::TimeTicks();
       force_load_timer_.Stop();
@@ -617,3 +708,53 @@
                             &TabLoader::ForceLoadTimerFired);
   }
 }
+
+TabLoader::TabVector::iterator TabLoader::FindTabToLoad(
+    content::WebContents* contents) {
+  auto it = tabs_to_load_.begin();
+  while (it != tabs_to_load_.end()) {
+    if (it->second == contents)
+      break;
+    ++it;
+  }
+  return it;
+}
+
+TabLoader::TabVector::const_iterator TabLoader::FindTabToLoad(
+    content::WebContents* contents) const {
+  auto it = tabs_to_load_.begin();
+  while (it != tabs_to_load_.end()) {
+    if (it->second == contents)
+      break;
+    ++it;
+  }
+  return it;
+}
+
+void TabLoader::MoveToSortedPosition(TabVector::iterator it) {
+  ScoredTabComparator cmp;
+
+  // Bubble left as needed.
+  while (true) {
+    if (it == tabs_to_load_.begin())
+      break;
+    auto it_left = it;
+    --it_left;
+    if (cmp(*it, *it_left)) {
+      std::iter_swap(it, it_left);
+      it = it_left;
+    }
+  }
+
+  // Bubble right as needed.
+  while (true) {
+    auto it_right = it;
+    ++it_right;
+    if (it_right == tabs_to_load_.end())
+      break;
+    if (cmp(*it_right, *it)) {
+      std::iter_swap(it, it_right);
+      it = it_right;
+    }
+  }
+}
diff --git a/chrome/browser/sessions/tab_loader.h b/chrome/browser/sessions/tab_loader.h
index 210b2ac..a0f5408 100644
--- a/chrome/browser/sessions/tab_loader.h
+++ b/chrome/browser/sessions/tab_loader.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_SESSIONS_TAB_LOADER_H_
 #define CHROME_BROWSER_SESSIONS_TAB_LOADER_H_
 
+#include <utility>
 #include <vector>
 
 #include "base/callback.h"
@@ -90,13 +91,15 @@
 
   using LoadingTabSet = base::flat_set<LoadingTab>;
   using TabSet = base::flat_set<content::WebContents*>;
-  using TabVector = std::vector<content::WebContents*>;
+  using TabVector = std::vector<std::pair<float, content::WebContents*>>;
 
   explicit TabLoader(base::TimeTicks restore_started);
   ~TabLoader() override;
 
   // TabLoaderCallback:
   void SetTabLoadingEnabled(bool loading_enabled) override;
+  void NotifyTabScoreChanged(content::WebContents* contents,
+                             float score) override;
 
   // This is invoked once by RestoreTabs to start loading.
   void StartLoading(const std::vector<RestoredTab>& tabs);
@@ -188,6 +191,31 @@
   // Calls MaybeLoadSomeTabs, but wrapped with entry count management.
   void MaybeLoadSomeTabsForTesting();
 
+  // Sets a tab loading enabled callback for testing.
+  void SetTabLoadingEnabledCallbackForTesting(
+      base::RepeatingCallback<void(bool)>* callback);
+
+  // Returns true if loading is currently enabled, false otherwise. This checks
+  // the value of |loading_enabled_| and |all_tabs_scored_|, which are each
+  // independent mechanisms for disabling tab loading.
+  bool IsLoadingEnabled() const;
+
+  // Starts or stops loading as necessary, depending on the current value of
+  // IsLoadingEnabled. Should only be called if IsLoadingEnabled has changed
+  // values. This is called via SetAllTabsScored or SetTabLoadingEnabled.
+  void OnIsLoadingEnabledChanged();
+
+  void SetAllTabsScored(bool all_tabs_scored);
+
+  TabVector::iterator FindTabToLoad(content::WebContents* contents);
+  TabVector::const_iterator FindTabToLoad(content::WebContents* contents) const;
+
+  // Given a position in |tabs_to_load_|, moves that element into its sorted
+  // position using a bubble sort. This assumes that only data associated with
+  // the particular element has changed, and that the vector is otherwise
+  // sorted.
+  void MoveToSortedPosition(TabVector::iterator it);
+
   // The OS specific delegate of the TabLoader.
   std::unique_ptr<TabLoaderDelegate> delegate_;
 
@@ -209,9 +237,9 @@
   // The delay timer multiplier. See class description for details.
   size_t force_load_delay_multiplier_ = 1;
 
-  // True if tab loading is currently enabled. The delegate can cause this to
-  // toggle.
-  bool is_loading_enabled_ = true;
+  // These two variables determine whether or not tab loading is enabled.
+  bool loading_enabled_ = true;
+  bool all_tabs_scored_ = true;
 
   // The following 3 containers are mutually exclusive. A tab will be in at most
   // one of them at any moment.
@@ -251,6 +279,12 @@
   // not running.
   base::TimeTicks force_load_time_;
 
+  // The time at which tab loading was last disabled. This is used to extend
+  // time outs across "tab loading disabled" time periods (tab loading is
+  // disabled due to loss of network connection, or while waiting for tab
+  // ordering scores to be calculated).
+  base::TimeTicks tab_loading_disabled_time_;
+
   // For keeping TabLoader alive while it's loading even if no
   // SessionRestoreImpls reference it.
   scoped_refptr<TabLoader> this_retainer_;
@@ -275,6 +309,9 @@
   // callers are counted.
   size_t reentry_depth_ = 0;
 
+  // Callback that is invoked by calls to SetTabLoadingEnabled.
+  base::RepeatingCallback<void(bool)>* tab_loading_enabled_callback_ = nullptr;
+
   DISALLOW_COPY_AND_ASSIGN(TabLoader);
 };
 
diff --git a/chrome/browser/sessions/tab_loader_delegate.cc b/chrome/browser/sessions/tab_loader_delegate.cc
index b0affe9..f42d5c5 100644
--- a/chrome/browser/sessions/tab_loader_delegate.cc
+++ b/chrome/browser/sessions/tab_loader_delegate.cc
@@ -54,6 +54,16 @@
   }
 
   // TabLoaderDelegate:
+  float AddTabForScoring(content::WebContents* contents) const override {
+    return policy_->AddTabForScoring(contents);
+  }
+
+  // TabLoaderDelegate:
+  void RemoveTabForScoring(content::WebContents* contents) const override {
+    policy_->RemoveTabForScoring(contents);
+  }
+
+  // TabLoaderDelegate:
   bool ShouldLoad(content::WebContents* contents) const override {
     return policy_->ShouldLoad(contents);
   }
@@ -64,6 +74,10 @@
   // network::NetworkConnectionTracker::NetworkConnectionObserver:
   void OnConnectionChanged(network::mojom::ConnectionType type) override;
 
+  // Callback that is invoked by the policy engine, and forwarded over to the
+  // TabLoader.
+  void NotifyTabScoreChanged(content::WebContents* content, float score);
+
  private:
   // The default policy engine used to implement ShouldLoad.
   resource_coordinator::SessionRestorePolicy default_policy_;
@@ -107,6 +121,11 @@
   if (g_testing_policy) {
     policy_ = g_testing_policy;
   }
+
+  // Register the policy callback.
+  policy_->SetTabScoreChangedCallback(
+      base::BindRepeating(&TabLoaderDelegateImpl::NotifyTabScoreChanged,
+                          weak_factory_.GetWeakPtr()));
 }
 
 TabLoaderDelegateImpl::~TabLoaderDelegateImpl() {
@@ -119,6 +138,11 @@
       type != network::mojom::ConnectionType::CONNECTION_NONE);
 }
 
+void TabLoaderDelegateImpl::NotifyTabScoreChanged(content::WebContents* content,
+                                                  float score) {
+  callback_->NotifyTabScoreChanged(content, score);
+}
+
 }  // namespace
 
 // static
diff --git a/chrome/browser/sessions/tab_loader_delegate.h b/chrome/browser/sessions/tab_loader_delegate.h
index 2a3e18d7..42f8f72 100644
--- a/chrome/browser/sessions/tab_loader_delegate.h
+++ b/chrome/browser/sessions/tab_loader_delegate.h
@@ -22,6 +22,11 @@
   // This function will get called to suppress and to allow tab loading. Tab
   // loading is initially enabled.
   virtual void SetTabLoadingEnabled(bool enable_tab_loading) = 0;
+
+  // Invoked by the delegate to inform the tab loader of a change in the score
+  // of a tab. A higher score means the tab should be restored sooner.
+  virtual void NotifyTabScoreChanged(content::WebContents* contents,
+                                     float score) = 0;
 };
 
 // TabLoaderDelegate is created once the SessionRestore process is complete and
@@ -46,6 +51,16 @@
   // Returns the maximum number of tabs that should be loading simultaneously.
   virtual size_t GetMaxSimultaneousTabLoads() const = 0;
 
+  // Notifies the delegate of a tab that will be restored. This informs the
+  // delegate that this tab is being tracked, and changes in its priority or
+  // ranking should be forwarded to the TabLoader. WebContents provided to the
+  // delegate via this function are guaranteed to remain valid to derefence
+  // until a subsequent RemoveTab. Returns an initial score for the tab.
+  virtual float AddTabForScoring(content::WebContents* contents) const = 0;
+
+  // Notifies the delegate of a tab that is no longer being tracked.
+  virtual void RemoveTabForScoring(content::WebContents* contents) const = 0;
+
   // Determines whether or not the given tab should be loaded. If this returns
   // false, then the TabLoader no longer attempts to load |contents| and removes
   // it from TabLoaders internal state. This is called immediately prior to
diff --git a/chrome/browser/sessions/tab_loader_tester.cc b/chrome/browser/sessions/tab_loader_tester.cc
index 1014171..b3f3f905 100644
--- a/chrome/browser/sessions/tab_loader_tester.cc
+++ b/chrome/browser/sessions/tab_loader_tester.cc
@@ -4,6 +4,9 @@
 
 #include "chrome/browser/sessions/tab_loader_tester.h"
 
+#include "base/run_loop.h"
+#include "base/test/bind_test_util.h"
+
 TabLoaderTester::TabLoaderTester() = default;
 
 TabLoaderTester::TabLoaderTester(TabLoader* tab_loader)
@@ -51,6 +54,10 @@
   tab_loader_->SetTabLoadingEnabled(enabled);
 }
 
+bool TabLoaderTester::IsLoadingEnabled() const {
+  return tab_loader_->IsLoadingEnabled();
+}
+
 size_t TabLoaderTester::force_load_delay_multiplier() const {
   return tab_loader_->force_load_delay_multiplier_;
 }
@@ -63,10 +70,6 @@
   return tab_loader_->force_load_timer_;
 }
 
-bool TabLoaderTester::is_loading_enabled() const {
-  return tab_loader_->is_loading_enabled_;
-}
-
 const TabLoader::TabVector& TabLoaderTester::tabs_to_load() const {
   return tab_loader_->tabs_to_load_;
 }
@@ -92,3 +95,16 @@
       tab_loader_->GetLoadTimeoutPeriod();
   return expiry_time <= tab_loader_->clock_->NowTicks();
 }
+
+void TabLoaderTester::WaitForTabLoadingEnabled() {
+  base::RunLoop run_loop;
+  TabLoader* tab_loader = tab_loader_;
+  auto callback =
+      base::BindLambdaForTesting([&run_loop, tab_loader](bool loading_enabled) {
+        if (loading_enabled && tab_loader->IsLoadingEnabled())
+          run_loop.Quit();
+      });
+  tab_loader_->SetTabLoadingEnabledCallbackForTesting(&callback);
+  run_loop.Run();
+  tab_loader_->SetTabLoadingEnabledCallbackForTesting(nullptr);
+}
diff --git a/chrome/browser/sessions/tab_loader_tester.h b/chrome/browser/sessions/tab_loader_tester.h
index 6aeca249..e515d2a 100644
--- a/chrome/browser/sessions/tab_loader_tester.h
+++ b/chrome/browser/sessions/tab_loader_tester.h
@@ -34,12 +34,12 @@
   void OnMemoryPressure(
       base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
   void SetTabLoadingEnabled(bool enabled);
+  bool IsLoadingEnabled() const;
 
   // Accessors to TabLoader internals.
   size_t force_load_delay_multiplier() const;
   base::TimeTicks force_load_time() const;
   base::OneShotTimer& force_load_timer();
-  bool is_loading_enabled() const;
   const TabVector& tabs_to_load() const;
   size_t scheduled_to_load_count() const;
   static TabLoader* shared_tab_loader();
@@ -47,6 +47,7 @@
   // Additional helper functions.
   bool IsSharedTabLoader() const;
   bool HasTimedOutLoads() const;
+  void WaitForTabLoadingEnabled();
 
  private:
   TabLoader* tab_loader_ = nullptr;
diff --git a/chrome/browser/sessions/tab_loader_unittest.cc b/chrome/browser/sessions/tab_loader_unittest.cc
index b74a938..4c6a06b0 100644
--- a/chrome/browser/sessions/tab_loader_unittest.cc
+++ b/chrome/browser/sessions/tab_loader_unittest.cc
@@ -21,6 +21,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_web_contents_factory.h"
+#include "content/public/test/web_contents_tester.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using resource_coordinator::TabLoadTracker;
@@ -102,7 +103,6 @@
     // TabLoadTracker needs the resource_coordinator WebContentsData to be
     // initialized.
     ResourceCoordinatorTabHelper::CreateForWebContents(test_contents);
-
     restored_tabs_.push_back(
         RestoredTab(test_contents, is_active /* is_active */,
                     false /* is_app */, false /* is_pinned */));
@@ -123,6 +123,13 @@
       CreateRestoredWebContents(false);
   }
 
+  void StartTabLoader() {
+    TabLoader::RestoreTabs(restored_tabs_, clock_.NowTicks());
+    EXPECT_TRUE(tab_loader_.IsSharedTabLoader());
+    EXPECT_FALSE(tab_loader_.IsLoadingEnabled());
+    tab_loader_.WaitForTabLoadingEnabled();
+  }
+
   // The number of loading slots to use. This needs to be set before the
   // TabLoader is created in order to be picked up by it.
   size_t max_simultaneous_loads_;
@@ -158,14 +165,12 @@
   // inactive tabs should immediately be scheduled to load as well.
   max_simultaneous_loads_ = 4;
 
-  // Create the tab loader.
-  TabLoader::RestoreTabs(restored_tabs_, clock_.NowTicks());
-  EXPECT_TRUE(tab_loader_.IsSharedTabLoader());
+  StartTabLoader();
 
   // The loader should be enabled, with 2 tabs loading and 4 tabs left to go.
   // The initial load should exclusively allow active tabs time to load, and
   // fill up the rest of the loading slots.
-  EXPECT_TRUE(tab_loader_.is_loading_enabled());
+  EXPECT_TRUE(tab_loader_.IsLoadingEnabled());
   EXPECT_EQ(4u, tab_loader_.tabs_to_load().size());
   EXPECT_EQ(2u, tab_loader_.scheduled_to_load_count());
   EXPECT_EQ(2u, TabLoadTracker::Get()->GetLoadingTabCount());
@@ -199,12 +204,10 @@
   CreateMultipleRestoredWebContents(1, 1);
   max_simultaneous_loads_ = 1;
 
-  // Create the tab loader.
-  TabLoader::RestoreTabs(restored_tabs_, clock_.NowTicks());
-  EXPECT_TRUE(tab_loader_.IsSharedTabLoader());
+  StartTabLoader();
 
   // The loader should be enabled, with 1 tab loading and 1 tab left to go.
-  EXPECT_TRUE(tab_loader_.is_loading_enabled());
+  EXPECT_TRUE(tab_loader_.IsLoadingEnabled());
   EXPECT_EQ(1u, tab_loader_.tabs_to_load().size());
   EXPECT_EQ(1u, tab_loader_.scheduled_to_load_count());
   EXPECT_EQ(1u, TabLoadTracker::Get()->GetLoadingTabCount());
@@ -215,7 +218,7 @@
 
   // Expect all tabs to be loading. Note that this also validates that
   // force-loads can exceed the number of loadingslots.
-  EXPECT_TRUE(tab_loader_.is_loading_enabled());
+  EXPECT_TRUE(tab_loader_.IsLoadingEnabled());
   EXPECT_TRUE(tab_loader_.tabs_to_load().empty());
   EXPECT_EQ(2u, tab_loader_.scheduled_to_load_count());
   EXPECT_EQ(2u, TabLoadTracker::Get()->GetLoadingTabCount());
@@ -227,12 +230,10 @@
   CreateMultipleRestoredWebContents(1, 1);
   max_simultaneous_loads_ = 1;
 
-  // Create the tab loader.
-  TabLoader::RestoreTabs(restored_tabs_, clock_.NowTicks());
-  EXPECT_TRUE(tab_loader_.IsSharedTabLoader());
+  StartTabLoader();
 
   // The loader should be enabled, with 1 tab loading and 1 tab left to go.
-  EXPECT_TRUE(tab_loader_.is_loading_enabled());
+  EXPECT_TRUE(tab_loader_.IsLoadingEnabled());
   EXPECT_EQ(1u, tab_loader_.tabs_to_load().size());
   EXPECT_EQ(1u, tab_loader_.scheduled_to_load_count());
   EXPECT_EQ(1u, TabLoadTracker::Get()->GetLoadingTabCount());
@@ -242,7 +243,7 @@
   SimulateLoaded(0);
 
   // Expect all tabs to be loaded/loading.
-  EXPECT_TRUE(tab_loader_.is_loading_enabled());
+  EXPECT_TRUE(tab_loader_.IsLoadingEnabled());
   EXPECT_TRUE(tab_loader_.tabs_to_load().empty());
   EXPECT_EQ(2u, tab_loader_.scheduled_to_load_count());
   EXPECT_EQ(1u, TabLoadTracker::Get()->GetLoadedTabCount());
@@ -255,16 +256,18 @@
   // doesn't immediately kick off loading of all tabs and detach.
   CreateMultipleRestoredWebContents(0, 2);
 
-  // Create the tab loader.
-  TabLoader::RestoreTabs(restored_tabs_, clock_.NowTicks());
-  EXPECT_TRUE(tab_loader_.IsSharedTabLoader());
+  max_simultaneous_loads_ = 1;
+  StartTabLoader();
   EXPECT_EQ(1u, tab_loader_.scheduled_to_load_count());
 
-  // Simulate memory pressure and expect the tab loader to disable loading and
-  // detach from being the shared tab loader.
-  EXPECT_TRUE(tab_loader_.is_loading_enabled());
+  // Simulate memory pressure and expect the tab loader to disable loading.
+  EXPECT_TRUE(tab_loader_.IsLoadingEnabled());
   tab_loader_.OnMemoryPressure(
       base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
+  EXPECT_FALSE(tab_loader_.IsLoadingEnabled());
+
+  // Finish loading the tab and expect the tab loader to disconnect.
+  SimulateLoaded(0);
   EXPECT_TRUE(TabLoaderTester::shared_tab_loader() == nullptr);
 }
 
@@ -274,10 +277,9 @@
   // Create the tab loader with 2 loading slots. This should initially start
   // loading 1 tab, due to exclusive initial loading of active tabs.
   max_simultaneous_loads_ = 2;
-  TabLoader::RestoreTabs(restored_tabs_, clock_.NowTicks());
+  StartTabLoader();
   EXPECT_EQ(4u, tab_loader_.tabs_to_load().size());
   EXPECT_EQ(1u, tab_loader_.scheduled_to_load_count());
-  EXPECT_TRUE(tab_loader_.IsSharedTabLoader());
 
   // Simulate a timeout and expect there to be 2 loading tabs and 3 left to
   // load.
@@ -367,10 +369,9 @@
 
   // Create the tab loader. This should initially start loading 1 tab, due to
   // exclusive initial loading of active tabs.
-  TabLoader::RestoreTabs(restored_tabs_, clock_.NowTicks());
+  StartTabLoader();
   EXPECT_EQ(4u, tab_loader_.tabs_to_load().size());
   EXPECT_EQ(1u, tab_loader_.scheduled_to_load_count());
-  EXPECT_TRUE(tab_loader_.IsSharedTabLoader());
 
   // Simulate the first tab as having loaded. Another 2 should start loading.
   SimulateLoaded(0);
@@ -392,10 +393,9 @@
   // Create the tab loader with 1 loading slots. This should initially start
   // loading 1 tab, due to exclusive initial loading of active tabs.
   max_simultaneous_loads_ = 1;
-  TabLoader::RestoreTabs(restored_tabs_, clock_.NowTicks());
+  StartTabLoader();
   EXPECT_EQ(2u, tab_loader_.tabs_to_load().size());
   EXPECT_EQ(1u, tab_loader_.scheduled_to_load_count());
-  EXPECT_TRUE(tab_loader_.IsSharedTabLoader());
 
   // Manually initiate the load on one of the tabs, as would occur if a user
   // focused a tab. The tab should no longer be in the scheduled to load bucket.
diff --git a/chrome/browser/signin/signin_tracker_factory.cc b/chrome/browser/signin/signin_tracker_factory.cc
deleted file mode 100644
index e10b55b5..0000000
--- a/chrome/browser/signin/signin_tracker_factory.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/signin/signin_tracker_factory.h"
-
-#include "chrome/browser/signin/identity_manager_factory.h"
-#include "services/identity/public/cpp/identity_manager.h"
-
-SigninTrackerFactory::SigninTrackerFactory() {}
-SigninTrackerFactory::~SigninTrackerFactory() {}
-
-// static
-std::unique_ptr<SigninTracker> SigninTrackerFactory::CreateForProfile(
-    Profile* profile,
-    SigninTracker::Observer* observer) {
-  return std::unique_ptr<SigninTracker>(new SigninTracker(
-      IdentityManagerFactory::GetForProfile(profile), observer));
-}
diff --git a/chrome/browser/signin/signin_tracker_factory.h b/chrome/browser/signin/signin_tracker_factory.h
deleted file mode 100644
index b3d6c9f..0000000
--- a/chrome/browser/signin/signin_tracker_factory.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SIGNIN_SIGNIN_TRACKER_FACTORY_H_
-#define CHROME_BROWSER_SIGNIN_SIGNIN_TRACKER_FACTORY_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "components/signin/core/browser/signin_tracker.h"
-
-class Profile;
-
-class SigninTrackerFactory {
- public:
-  virtual ~SigninTrackerFactory();
-
-  // Creates a SigninTracker instance that tracks signin for |profile| on
-  // behalf of |observer|.
-  static std::unique_ptr<SigninTracker> CreateForProfile(
-      Profile* profile,
-      SigninTracker::Observer* observer);
-
- private:
-  SigninTrackerFactory();
-
-  DISALLOW_COPY_AND_ASSIGN(SigninTrackerFactory);
-};
-
-#endif  // CHROME_BROWSER_SIGNIN_SIGNIN_TRACKER_FACTORY_H_
diff --git a/chrome/browser/signin/signin_util_win.cc b/chrome/browser/signin/signin_util_win.cc
index 84db32e..7770ee33 100644
--- a/chrome/browser/signin/signin_util_win.cc
+++ b/chrome/browser/signin/signin_util_win.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/win/registry.h"
 #include "base/win/win_util.h"
@@ -23,7 +24,6 @@
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_list.h"
-#include "chrome/browser/ui/sync/one_click_signin_sync_starter.h"
 #include "chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h"
 #include "chrome/credential_provider/common/gcp_strings.h"
 #include "components/os_crypt/os_crypt.h"
@@ -67,7 +67,8 @@
         signin_metrics::PromoAction::PROMO_ACTION_WITH_DEFAULT,
         signin_metrics::Reason::REASON_SIGNIN_PRIMARY_ACCOUNT, account_id,
         DiceTurnSyncOnHelper::SigninAbortedMode::KEEP_ACCOUNT,
-        std::move(*GetDiceTurnSyncOnHelperDelegateForTestingStorage()));
+        std::move(*GetDiceTurnSyncOnHelperDelegateForTestingStorage()),
+        base::DoNothing());
   } else {
     if (!browser)
       browser = chrome::FindLastActiveWithProfile(profile);
diff --git a/chrome/browser/speech/tts_controller_delegate_impl_unittest.cc b/chrome/browser/speech/tts_controller_delegate_impl_unittest.cc
index 0dd8197..80499f5 100644
--- a/chrome/browser/speech/tts_controller_delegate_impl_unittest.cc
+++ b/chrome/browser/speech/tts_controller_delegate_impl_unittest.cc
@@ -39,11 +39,10 @@
 #if defined(OS_CHROMEOS)
   TestingPrefServiceSimple pref_service_;
   // Uses default pref voices.
-  std::unique_ptr<base::DictionaryValue> lang_to_voices =
-      std::make_unique<base::DictionaryValue>();
-  lang_to_voices->SetKey(
+  base::Value lang_to_voices(base::Value::Type::DICTIONARY);
+  lang_to_voices.SetKey(
       "es", base::Value("{\"name\":\"Voice7\",\"extension\":\"id7\"}"));
-  lang_to_voices->SetKey(
+  lang_to_voices.SetKey(
       "noLanguage", base::Value("{\"name\":\"Android\",\"extension\":\"\"}"));
   pref_service_.registry()->RegisterDictionaryPref(
       prefs::kTextToSpeechLangToVoiceName, std::move(lang_to_voices));
diff --git a/chrome/browser/supervised_user/child_accounts/family_info_fetcher.cc b/chrome/browser/supervised_user/child_accounts/family_info_fetcher.cc
index cc8db80..f1c851a 100644
--- a/chrome/browser/supervised_user/child_accounts/family_info_fetcher.cc
+++ b/chrome/browser/supervised_user/child_accounts/family_info_fetcher.cc
@@ -18,6 +18,7 @@
 #include "net/http/http_status_code.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/identity/public/cpp/identity_manager.h"
+#include "services/identity/public/cpp/primary_account_access_token_fetcher.h"
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/simple_url_loader.h"
@@ -125,6 +126,10 @@
 }
 
 void FamilyInfoFetcher::StartFetching() {
+  // TODO(treib): we should stop listening to OnRefreshTokensLoaded which is
+  // unreliable for clients, as there is no way to know whether it has already
+  // happened or not, potentially leading to neverending waits. Note that this
+  // directly affects FamilyInfoFetcherTest.NoRefreshToken.
   if (identity_manager_->HasAccountWithRefreshToken(primary_account_id_)) {
     StartFetchingAccessToken();
   } else {
@@ -134,13 +139,13 @@
 }
 
 void FamilyInfoFetcher::StartFetchingAccessToken() {
-  OAuth2TokenService::ScopeSet scopes;
-  scopes.insert(kScope);
-  access_token_fetcher_ = identity_manager_->CreateAccessTokenFetcherForAccount(
-      primary_account_id_, "family_info_fetcher", scopes,
-      base::BindOnce(&FamilyInfoFetcher::OnAccessTokenFetchCompleteForAccount,
-                     base::Unretained(this), primary_account_id_),
-      identity::AccessTokenFetcher::Mode::kImmediate);
+  OAuth2TokenService::ScopeSet scopes{kScope};
+  access_token_fetcher_ =
+      std::make_unique<identity::PrimaryAccountAccessTokenFetcher>(
+          "family_info_fetcher", identity_manager_, scopes,
+          base::BindOnce(&FamilyInfoFetcher::OnAccessTokenFetchComplete,
+                         base::Unretained(this)),
+          identity::PrimaryAccountAccessTokenFetcher::Mode::kImmediate);
 }
 
 void FamilyInfoFetcher::OnRefreshTokenUpdatedForAccount(
@@ -164,8 +169,7 @@
   consumer_->OnFailure(TOKEN_ERROR);
 }
 
-void FamilyInfoFetcher::OnAccessTokenFetchCompleteForAccount(
-    std::string account_id,
+void FamilyInfoFetcher::OnAccessTokenFetchComplete(
     GoogleServiceAuthError error,
     identity::AccessTokenInfo access_token_info) {
   access_token_fetcher_.reset();
diff --git a/chrome/browser/supervised_user/child_accounts/family_info_fetcher.h b/chrome/browser/supervised_user/child_accounts/family_info_fetcher.h
index 5b96fc2b..05d618d 100644
--- a/chrome/browser/supervised_user/child_accounts/family_info_fetcher.h
+++ b/chrome/browser/supervised_user/child_accounts/family_info_fetcher.h
@@ -20,7 +20,7 @@
 }
 
 namespace identity {
-class AccessTokenFetcher;
+class PrimaryAccountAccessTokenFetcher;
 }
 
 namespace network {
@@ -108,10 +108,8 @@
       const AccountInfo& account_info) override;
   void OnRefreshTokensLoaded() override;
 
-  void OnAccessTokenFetchCompleteForAccount(
-      std::string account_id,
-      GoogleServiceAuthError error,
-      identity::AccessTokenInfo access_token_info);
+  void OnAccessTokenFetchComplete(GoogleServiceAuthError error,
+                                  identity::AccessTokenInfo access_token_info);
 
   void OnSimpleLoaderComplete(std::unique_ptr<std::string> response_body);
 
@@ -133,7 +131,8 @@
   scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
 
   std::string request_path_;
-  std::unique_ptr<identity::AccessTokenFetcher> access_token_fetcher_;
+  std::unique_ptr<identity::PrimaryAccountAccessTokenFetcher>
+      access_token_fetcher_;
   std::string access_token_;
   bool access_token_expired_;
   std::unique_ptr<network::SimpleURLLoader> simple_url_loader_;
diff --git a/chrome/browser/supervised_user/supervised_user_service.cc b/chrome/browser/supervised_user/supervised_user_service.cc
index f554b00c..8df9f00 100644
--- a/chrome/browser/supervised_user/supervised_user_service.cc
+++ b/chrome/browser/supervised_user/supervised_user_service.cc
@@ -992,7 +992,6 @@
   result.Put(syncer::EXTENSION_SETTINGS);
   result.Put(syncer::APPS);
   result.Put(syncer::APP_SETTINGS);
-  result.Put(syncer::APP_NOTIFICATIONS);
   result.Put(syncer::APP_LIST);
   return result;
 }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 5f17f84..2de9ebb0 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1795,6 +1795,7 @@
       "//services/ws/public/cpp",
       "//services/ws/public/mojom",
       "//ui/base/ime",
+      "//ui/base/user_activity",
       "//ui/chromeos",
       "//ui/chromeos/events",
       "//ui/compositor_extra",
@@ -1855,8 +1856,6 @@
       "sync/one_click_signin_links_delegate.h",
       "sync/one_click_signin_links_delegate_impl.cc",
       "sync/one_click_signin_links_delegate_impl.h",
-      "sync/one_click_signin_sync_starter.cc",
-      "sync/one_click_signin_sync_starter.h",
       "user_manager.cc",
       "user_manager.h",
       "views/external_protocol_dialog.cc",
diff --git a/chrome/browser/ui/android/infobars/simple_confirm_infobar_builder.cc b/chrome/browser/ui/android/infobars/simple_confirm_infobar_builder.cc
index 0347c68..d2eb7d0 100644
--- a/chrome/browser/ui/android/infobars/simple_confirm_infobar_builder.cc
+++ b/chrome/browser/ui/android/infobars/simple_confirm_infobar_builder.cc
@@ -30,6 +30,7 @@
       const base::string16& message_str,
       const base::string16& primary_str,
       const base::string16& secondary_str,
+      const base::string16& link_text_str,
       bool auto_expire);
 
   ~SimpleConfirmInfoBarDelegate() override;
@@ -44,6 +45,8 @@
   base::string16 GetButtonLabel(InfoBarButton button) const override;
   bool Accept() override;
   bool Cancel() override;
+  base::string16 GetLinkText() const override;
+  bool LinkClicked(WindowOpenDisposition disposition) override;
 
  private:
   base::android::ScopedJavaGlobalRef<jobject> java_listener_;
@@ -52,6 +55,7 @@
   base::string16 message_str_;
   base::string16 primary_str_;
   base::string16 secondary_str_;
+  base::string16 link_text_str_;
   bool auto_expire_;
 
   DISALLOW_COPY_AND_ASSIGN(SimpleConfirmInfoBarDelegate);
@@ -64,12 +68,14 @@
     const base::string16& message_str,
     const base::string16& primary_str,
     const base::string16& secondary_str,
+    const base::string16& link_text_str,
     bool auto_expire)
     : identifier_(identifier),
       icon_bitmap_(bitmap),
       message_str_(message_str),
       primary_str_(primary_str),
       secondary_str_(secondary_str),
+      link_text_str_(link_text_str),
       auto_expire_(auto_expire) {
   java_listener_.Reset(j_listener);
 }
@@ -121,6 +127,16 @@
       base::android::AttachCurrentThread(), java_listener_, false);
 }
 
+base::string16 SimpleConfirmInfoBarDelegate::GetLinkText() const {
+  return link_text_str_;
+}
+
+bool SimpleConfirmInfoBarDelegate::LinkClicked(
+    WindowOpenDisposition disposition) {
+  return !Java_SimpleConfirmInfoBarBuilder_onInfoBarLinkClicked(
+      base::android::AttachCurrentThread(), java_listener_);
+}
+
 }  // anonymous namespace
 
 // Native JNI methods ---------------------------------------------------------
@@ -133,6 +149,7 @@
     const JavaParamRef<jstring>& j_message,
     const JavaParamRef<jstring>& j_primary,
     const JavaParamRef<jstring>& j_secondary,
+    const JavaParamRef<jstring>& j_link_text,
     jboolean auto_expire,
     const JavaParamRef<jobject>& j_listener) {
   infobars::InfoBarDelegate::InfoBarIdentifier infobar_identifier =
@@ -153,11 +170,15 @@
   base::string16 secondary_str = j_secondary.is_null()
       ? base::string16()
       : base::android::ConvertJavaStringToUTF16(env, j_secondary);
+  base::string16 link_text_str =
+      j_link_text.is_null()
+          ? base::string16()
+          : base::android::ConvertJavaStringToUTF16(env, j_link_text);
 
   InfoBarService* service = InfoBarService::FromWebContents(
       TabAndroid::GetNativeTab(env, j_tab)->web_contents());
   service->AddInfoBar(service->CreateConfirmInfoBar(
       std::make_unique<SimpleConfirmInfoBarDelegate>(
           j_listener, infobar_identifier, icon_bitmap, message_str, primary_str,
-          secondary_str, auto_expire)));
+          secondary_str, link_text_str, auto_expire)));
 }
diff --git a/chrome/browser/ui/app_list/search/app_search_provider.cc b/chrome/browser/ui/app_list/search/app_search_provider.cc
index c7ea109..d15cf690 100644
--- a/chrome/browser/ui/app_list/search/app_search_provider.cc
+++ b/chrome/browser/ui/app_list/search/app_search_provider.cc
@@ -21,6 +21,7 @@
 #include "base/callback_list.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/optional.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
@@ -641,6 +642,9 @@
 
 void AppSearchProvider::Start(const base::string16& query) {
   query_ = query;
+  query_start_time_ = base::TimeTicks::Now();
+  // We only need to record app search latency for queries started by user.
+  record_query_uma_ = true;
   const bool show_recommendations = query.empty();
   // Refresh list of apps to ensure we have the latest launch time information.
   // This will also cause the results to update.
@@ -732,6 +736,8 @@
     MaybeAddResult(&new_results, std::move(result), &seen_or_filtered_apps);
   }
 
+  MaybeRecordQueryLatencyHistogram(false /* empty query */);
+
   SwapResults(&new_results);
   update_results_factory_.InvalidateWeakPtrs();
 }
@@ -768,10 +774,29 @@
     MaybeAddResult(&new_results, std::move(result), &seen_or_filtered_apps);
   }
 
+  MaybeRecordQueryLatencyHistogram(true /* queried search */);
+
   SwapResults(&new_results);
   update_results_factory_.InvalidateWeakPtrs();
 }
 
+void AppSearchProvider::MaybeRecordQueryLatencyHistogram(
+    bool is_queried_search) {
+  // Record the query latency only if search provider is queried by user
+  // initiating a search or getting zero state suggestions.
+  if (!record_query_uma_)
+    return;
+
+  if (is_queried_search) {
+    UMA_HISTOGRAM_TIMES("Apps.AppList.AppSearchProvider.QueryTime",
+                        base::TimeTicks::Now() - query_start_time_);
+  } else {
+    UMA_HISTOGRAM_TIMES("Apps.AppList.AppSearchProvider.ZeroStateLatency",
+                        base::TimeTicks::Now() - query_start_time_);
+  }
+  record_query_uma_ = false;
+}
+
 void AppSearchProvider::UpdateResults() {
   const bool show_recommendations = query_.empty();
 
diff --git a/chrome/browser/ui/app_list/search/app_search_provider.h b/chrome/browser/ui/app_list/search/app_search_provider.h
index 975da27..5997fb7a 100644
--- a/chrome/browser/ui/app_list/search/app_search_provider.h
+++ b/chrome/browser/ui/app_list/search/app_search_provider.h
@@ -73,9 +73,17 @@
       const base::flat_map<std::string, uint16_t>& id_to_app_list_index);
   void UpdateQueriedResults();
 
+  // Records the app search provider's latency when user initiates a search or
+  // gets the zero state suggestions.
+  // If |is_queried_search| is true, record query latency; otherwise, record
+  // zero state recommendation latency.
+  void MaybeRecordQueryLatencyHistogram(bool is_queried_search);
+
   Profile* profile_;
   AppListControllerDelegate* const list_controller_;
   base::string16 query_;
+  base::TimeTicks query_start_time_;
+  bool record_query_uma_ = false;
   Apps apps_;
   AppListModelUpdater* const model_updater_;
   base::Clock* clock_;
diff --git a/chrome/browser/ui/app_list/search/launcher_search/launcher_search_provider.cc b/chrome/browser/ui/app_list/search/launcher_search/launcher_search_provider.cc
index 9538312..c35481e0 100644
--- a/chrome/browser/ui/app_list/search/launcher_search/launcher_search_provider.cc
+++ b/chrome/browser/ui/app_list/search/launcher_search/launcher_search_provider.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/chromeos/launcher_search_provider/launcher_search_provider_service.h"
 
@@ -55,6 +56,10 @@
     std::vector<std::unique_ptr<LauncherSearchResult>> results) {
   DCHECK(Service::Get(profile_)->IsQueryRunning());
 
+  // Record file search query latency metrics.
+  UMA_HISTOGRAM_TIMES("Apps.AppList.LauncherSearchProvider.QueryTime",
+                      base::TimeTicks::Now() - query_start_time_);
+
   // Add this extension's results (erasing any existing results).
   extension_results_[extension_id] = std::move(results);
 
@@ -81,6 +86,7 @@
 
 void LauncherSearchProvider::StartInternal(const base::string16& query) {
   if (!query.empty()) {
+    query_start_time_ = base::TimeTicks::Now();
     Service::Get(profile_)->OnQueryStarted(this, base::UTF16ToUTF8(query),
                                            kLauncherSearchProviderMaxResults);
   }
diff --git a/chrome/browser/ui/app_list/search/launcher_search/launcher_search_provider.h b/chrome/browser/ui/app_list/search/launcher_search/launcher_search_provider.h
index 3508407..12b51f4 100644
--- a/chrome/browser/ui/app_list/search/launcher_search/launcher_search_provider.h
+++ b/chrome/browser/ui/app_list/search/launcher_search/launcher_search_provider.h
@@ -51,6 +51,8 @@
   // The timestamp of the last query.
   base::Time last_query_time_;
 
+  base::TimeTicks query_start_time_;
+
   // The reference to profile to get LauncherSearchProvider service.
   Profile* profile_;
 
diff --git a/chrome/browser/ui/app_list/search/omnibox_provider.cc b/chrome/browser/ui/app_list/search/omnibox_provider.cc
index d63ee64..537931a 100644
--- a/chrome/browser/ui/app_list/search/omnibox_provider.cc
+++ b/chrome/browser/ui/app_list/search/omnibox_provider.cc
@@ -6,6 +6,7 @@
 
 #include "ash/public/cpp/app_list/app_list_features.h"
 #include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
 #include "chrome/browser/autocomplete/chrome_autocomplete_provider_client.h"
 #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h"
 #include "chrome/browser/profiles/profile.h"
@@ -57,6 +58,8 @@
   } else {
     is_zero_state_input_ = false;
   }
+
+  query_start_time_ = base::TimeTicks::Now();
   controller_->Start(input);
 }
 
@@ -74,7 +77,17 @@
 }
 
 void OmniboxProvider::OnResultChanged(bool default_match_changed) {
+  // Record the query latency.
+  RecordQueryLatencyHistogram();
+
   PopulateFromACResult(controller_->result());
 }
 
+void OmniboxProvider::RecordQueryLatencyHistogram() {
+  UMA_HISTOGRAM_TIMES(is_zero_state_input_
+                          ? "Apps.AppList.OmniboxProvider.ZeroStateLatency"
+                          : "Apps.AppList.OmniboxProvider.QueryTime",
+                      base::TimeTicks::Now() - query_start_time_);
+}
+
 }  // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/omnibox_provider.h b/chrome/browser/ui/app_list/search/omnibox_provider.h
index 70d8b09..c021bbf 100644
--- a/chrome/browser/ui/app_list/search/omnibox_provider.h
+++ b/chrome/browser/ui/app_list/search/omnibox_provider.h
@@ -36,11 +36,14 @@
   // AutocompleteControllerDelegate overrides:
   void OnResultChanged(bool default_match_changed) override;
 
+  void RecordQueryLatencyHistogram();
+
   Profile* profile_;
   bool is_zero_state_enabled_ = false;
   // True if the input is empty for zero state suggestion.
   bool is_zero_state_input_ = false;
   AppListControllerDelegate* list_controller_;
+  base::TimeTicks query_start_time_;
 
   // The omnibox AutocompleteController that collects/sorts/dup-
   // eliminates the results as they come in.
diff --git a/chrome/browser/ui/ash/network/network_state_notifier.cc b/chrome/browser/ui/ash/network/network_state_notifier.cc
index 484f1db..10a594e 100644
--- a/chrome/browser/ui/ash/network/network_state_notifier.cc
+++ b/chrome/browser/ui/ash/network/network_state_notifier.cc
@@ -134,13 +134,15 @@
 const char NetworkStateNotifier::kNetworkOutOfCreditsNotificationId[] =
     "chrome://settings/internet/out-of-credits";
 
-NetworkStateNotifier::NetworkStateNotifier()
-    : did_show_out_of_credits_(false), weak_ptr_factory_(this) {
+NetworkStateNotifier::NetworkStateNotifier() : weak_ptr_factory_(this) {
   if (!NetworkHandler::IsInitialized())
     return;
   NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
   handler->AddObserver(this, FROM_HERE);
-  UpdateDefaultNetwork(handler->DefaultNetwork());
+  NetworkStateHandler::NetworkStateList active_networks;
+  handler->GetActiveNetworkListByType(NetworkTypePattern::Default(),
+                                      &active_networks);
+  ActiveNetworksChanged(active_networks);
   NetworkHandler::Get()->network_connection_handler()->AddObserver(this);
 }
 
@@ -158,7 +160,7 @@
       NetworkHandler::Get()->network_state_handler()->GetNetworkState(
           service_path);
   if (network && network->type() == shill::kTypeVPN)
-    connected_vpn_.clear();
+    connected_vpn_guid_.clear();
 
   RemoveConnectNotification();
 }
@@ -186,105 +188,113 @@
       NetworkHandler::Get()->network_state_handler()->GetNetworkState(
           service_path);
   if (network && network->type() == shill::kTypeVPN)
-    connected_vpn_.clear();
+    connected_vpn_guid_.clear();
 }
 
-void NetworkStateNotifier::DefaultNetworkChanged(const NetworkState* network) {
-  if (!UpdateDefaultNetwork(network))
-    return;
-  // If the default network changes to another network, allow the out of
-  // credits notification to be shown again. A delay prevents the notification
-  // from being shown too frequently (see below).
-  if (network)
+void NetworkStateNotifier::ActiveNetworksChanged(
+    const std::vector<const NetworkState*>& active_networks) {
+  std::string active_non_vpn_network_guid;
+  for (const auto* network : active_networks) {
+    if (network->type() == shill::kTypeVPN)
+      UpdateVpnConnectionState(network);
+    else if (active_non_vpn_network_guid.empty())
+      active_non_vpn_network_guid = network->guid();
+  }
+  // If the default network changes, allow the out of credits notification to be
+  // shown again. A delay prevents the notification from being shown too
+  // frequently (see below).
+  if (active_non_vpn_network_guid != active_non_vpn_network_guid_) {
+    active_non_vpn_network_guid_ = active_non_vpn_network_guid;
     did_show_out_of_credits_ = false;
-}
-
-void NetworkStateNotifier::NetworkConnectionStateChanged(
-    const NetworkState* network) {
-  if (network->type() == shill::kTypeVPN)
-    UpdateVpnConnectionState(network);
+    UpdateCellularOutOfCredits();
+  }
 }
 
 void NetworkStateNotifier::NetworkPropertiesUpdated(
     const NetworkState* network) {
   if (network->type() != shill::kTypeCellular)
     return;
-  UpdateCellularOutOfCredits(network);
+  if (network->cellular_out_of_credits())
+    UpdateCellularOutOfCredits();
   UpdateCellularActivating(network);
 }
 
-bool NetworkStateNotifier::UpdateDefaultNetwork(const NetworkState* network) {
-  std::string default_network_path;
-  if (network)
-    default_network_path = network->path();
-  if (default_network_path != last_default_network_) {
-    last_default_network_ = default_network_path;
-    return true;
-  }
-  return false;
-}
-
 void NetworkStateNotifier::UpdateVpnConnectionState(const NetworkState* vpn) {
-  if (vpn->path() == connected_vpn_) {
-    if (!vpn->IsConnectedState() && !vpn->IsConnectingState()) {
+  if (vpn->guid() == connected_vpn_guid_) {
+    if (!vpn->IsConnectingOrConnected()) {
       if (vpn->GetVpnProviderType() != shill::kProviderArcVpn) {
         ShowVpnDisconnectedNotification(vpn);
       }
-      connected_vpn_.clear();
+      connected_vpn_guid_.clear();
     }
   } else if (vpn->IsConnectedState()) {
-    connected_vpn_ = vpn->path();
+    connected_vpn_guid_ = vpn->guid();
   }
 }
 
-void NetworkStateNotifier::UpdateCellularOutOfCredits(
-    const NetworkState* cellular) {
-  // Only display a notification if we are out of credits and have not already
-  // shown a notification (or have since connected to another network type).
-  if (!cellular->cellular_out_of_credits() || did_show_out_of_credits_)
+void NetworkStateNotifier::UpdateCellularOutOfCredits() {
+  // Only show the notification once (reset when the primary network changes).
+  if (did_show_out_of_credits_)
     return;
 
-  // Only display a notification if not connected, connecting, or waiting to
-  // connect to another network.
-  NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
-  const NetworkState* default_network = handler->DefaultNetwork();
-  if (default_network && default_network != cellular)
-    return;
-  if (handler->ConnectingNetworkByType(NetworkTypePattern::NonVirtual()) ||
-      NetworkHandler::Get()
+  // Don't display notification if the UI has requested a network connection.
+  if (NetworkHandler::Get()
           ->network_connection_handler()
-          ->HasPendingConnectRequest())
+          ->HasPendingConnectRequest()) {
     return;
+  }
+
+  NetworkStateHandler::NetworkStateList active_networks;
+  NetworkHandler::Get()->network_state_handler()->GetActiveNetworkListByType(
+      NetworkTypePattern::NonVirtual(), &active_networks);
+  const NetworkState* primary_network = nullptr;
+  for (const auto* network : active_networks) {
+    // Don't display notification if any network is connecting.
+    if (network->IsConnectingState())
+      return;
+    if (!primary_network)
+      primary_network = network;
+  }
+
+  if (!primary_network ||
+      !primary_network->Matches(NetworkTypePattern::Cellular()) ||
+      !primary_network->cellular_out_of_credits()) {
+    return;
+  }
 
   did_show_out_of_credits_ = true;
   base::TimeDelta dtime = base::Time::Now() - out_of_credits_notify_time_;
   if (dtime.InSeconds() > kMinTimeBetweenOutOfCreditsNotifySeconds) {
     out_of_credits_notify_time_ = base::Time::Now();
-    base::string16 error_msg = l10n_util::GetStringFUTF16(
-        IDS_NETWORK_OUT_OF_CREDITS_BODY, base::UTF8ToUTF16(cellular->name()));
+    base::string16 error_msg =
+        l10n_util::GetStringFUTF16(IDS_NETWORK_OUT_OF_CREDITS_BODY,
+                                   base::UTF8ToUTF16(primary_network->name()));
     ShowErrorNotification(
-        cellular->path(), kNetworkOutOfCreditsNotificationId, cellular->type(),
+        primary_network->path(), kNetworkOutOfCreditsNotificationId,
+        primary_network->type(),
         l10n_util::GetStringUTF16(IDS_NETWORK_OUT_OF_CREDITS_TITLE), error_msg,
         base::Bind(&NetworkStateNotifier::ShowMobileSetup,
-                   weak_ptr_factory_.GetWeakPtr(), cellular->guid()));
+                   weak_ptr_factory_.GetWeakPtr(), primary_network->guid()));
   }
 }
 
 void NetworkStateNotifier::UpdateCellularActivating(
     const NetworkState* cellular) {
+  const std::string cellular_guid = cellular->guid();
   // Keep track of any activating cellular network.
   std::string activation_state = cellular->activation_state();
   if (activation_state == shill::kActivationStateActivating) {
-    cellular_activating_.insert(cellular->path());
+    cellular_activating_guids_.insert(cellular_guid);
     return;
   }
   // Only display a notification if this network was activating and is now
   // activated.
-  if (!cellular_activating_.count(cellular->path()) ||
-      activation_state != shill::kActivationStateActivated)
+  if (!cellular_activating_guids_.count(cellular_guid) ||
+      activation_state != shill::kActivationStateActivated) {
     return;
+  }
 
-  cellular_activating_.erase(cellular->path());
+  cellular_activating_guids_.erase(cellular_guid);
   std::unique_ptr<message_center::Notification> notification =
       ash::CreateSystemNotification(
           message_center::NOTIFICATION_TYPE_SIMPLE,
@@ -298,7 +308,7 @@
           {},
           new message_center::HandleNotificationClickDelegate(
               base::Bind(&NetworkStateNotifier::ShowNetworkSettings,
-                         weak_ptr_factory_.GetWeakPtr(), cellular->guid())),
+                         weak_ptr_factory_.GetWeakPtr(), cellular_guid)),
           ash::kNotificationMobileDataIcon,
           message_center::SystemNotificationWarningLevel::CRITICAL_WARNING);
   notification->set_priority(message_center::SYSTEM_PRIORITY);
diff --git a/chrome/browser/ui/ash/network/network_state_notifier.h b/chrome/browser/ui/ash/network/network_state_notifier.h
index 57d1aff..989d462 100644
--- a/chrome/browser/ui/ash/network/network_state_notifier.h
+++ b/chrome/browser/ui/ash/network/network_state_notifier.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <set>
 #include <string>
+#include <vector>
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
@@ -62,8 +63,8 @@
   void DisconnectRequested(const std::string& service_path) override;
 
   // NetworkStateHandlerObserver
-  void DefaultNetworkChanged(const NetworkState* network) override;
-  void NetworkConnectionStateChanged(const NetworkState* network) override;
+  void ActiveNetworksChanged(
+      const std::vector<const NetworkState*>& active_networks) override;
   void NetworkPropertiesUpdated(const NetworkState* network) override;
 
   void ConnectErrorPropertiesSucceeded(
@@ -89,7 +90,7 @@
 
   // Helper methods to update state and check for notifications.
   void UpdateVpnConnectionState(const NetworkState* vpn);
-  void UpdateCellularOutOfCredits(const NetworkState* cellular);
+  void UpdateCellularOutOfCredits();
   void UpdateCellularActivating(const NetworkState* cellular);
 
   // Shows the network settings for |network_id|.
@@ -98,11 +99,19 @@
   // Shows the mobile setup dialog for |network_id|.
   void ShowMobileSetup(const std::string& network_id);
 
-  std::string last_default_network_;
-  bool did_show_out_of_credits_;
+  // Set to the GUID of the connected VPN network if any, otherwise empty.
+  // Used for displaying VPN disconnected notification.
+  std::string connected_vpn_guid_;
+
+  // Tracks state for out of credits notification.
+  bool did_show_out_of_credits_ = false;
   base::Time out_of_credits_notify_time_;
-  std::set<std::string> cellular_activating_;
-  std::string connected_vpn_;
+  // Set to the GUID of the active non VPN network if any, otherwise empty.
+  std::string active_non_vpn_network_guid_;
+
+  // Tracks GUIDs of activating cellular networks for activation notification.
+  std::set<std::string> cellular_activating_guids_;
+
   base::WeakPtrFactory<NetworkStateNotifier> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(NetworkStateNotifier);
diff --git a/chrome/browser/ui/ash/system_tray_client.cc b/chrome/browser/ui/ash/system_tray_client.cc
index b097669..995ce794 100644
--- a/chrome/browser/ui/ash/system_tray_client.cc
+++ b/chrome/browser/ui/ash/system_tray_client.cc
@@ -300,8 +300,10 @@
     return;
   }
 
-  // Otherwise show enterprise special settings subpage.
-  ShowSettingsSubPageForActiveUser(chrome::kManagementSubPage);
+  // Otherwise show enterprise help in a browser tab.
+  chrome::ScopedTabbedBrowserDisplayer displayer(
+      ProfileManager::GetActiveUserProfile());
+  ShowSingletonTab(displayer.browser(), GURL(chrome::kLearnMoreEnterpriseURL));
 }
 
 void SystemTrayClient::ShowNetworkConfigure(const std::string& network_id) {
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
deleted file mode 100644
index 0a6a9542..0000000
--- a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
+++ /dev/null
@@ -1,538 +0,0 @@
-// Copyright (c) 2012 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/ui/sync/one_click_signin_sync_starter.h"
-
-#include <stddef.h>
-
-#include "base/bind.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/metrics/user_metrics.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/policy/cloud/user_policy_signin_service.h"
-#include "chrome/browser/policy/cloud/user_policy_signin_service_factory.h"
-#include "chrome/browser/profiles/profile_attributes_entry.h"
-#include "chrome/browser/profiles/profile_attributes_storage.h"
-#include "chrome/browser/profiles/profile_avatar_icon_util.h"
-#include "chrome/browser/profiles/profile_io_data.h"
-#include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/profiles/profile_window.h"
-#include "chrome/browser/signin/identity_manager_factory.h"
-#include "chrome/browser/signin/signin_tracker_factory.h"
-#include "chrome/browser/signin/signin_util.h"
-#include "chrome/browser/sync/profile_sync_service_factory.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/browser_list.h"
-#include "chrome/browser/ui/browser_tabstrip.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/chrome_pages.h"
-#include "chrome/browser/ui/tab_dialogs.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
-#include "chrome/browser/unified_consent/unified_consent_service_factory.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/grit/generated_resources.h"
-#include "components/account_id/account_id.h"
-#include "components/prefs/pref_service.h"
-#include "components/signin/core/browser/signin_metrics.h"
-#include "components/sync/base/sync_prefs.h"
-#include "components/sync/driver/sync_service.h"
-#include "components/sync/driver/sync_user_settings.h"
-#include "components/unified_consent/feature.h"
-#include "components/unified_consent/unified_consent_service.h"
-#include "content/public/browser/storage_partition.h"
-#include "net/base/url_util.h"
-#include "services/identity/public/cpp/identity_manager.h"
-#include "services/identity/public/cpp/primary_account_mutator.h"
-#include "ui/base/l10n/l10n_util.h"
-
-namespace {
-
-// UMA histogram for tracking what users do when presented with the signin
-// screen.
-// Hence,
-//   (a) existing enumerated constants should never be deleted or reordered, and
-//   (b) new constants should only be appended at the end of the enumeration.
-//
-// Keep this in sync with SigninChoice in histograms.xml.
-enum SigninChoice {
-  SIGNIN_CHOICE_CANCEL = 0,
-  SIGNIN_CHOICE_CONTINUE = 1,
-  SIGNIN_CHOICE_NEW_PROFILE = 2,
-  // SIGNIN_CHOICE_SIZE should always be last - this is a count of the number
-  // of items in this enum.
-  SIGNIN_CHOICE_SIZE,
-};
-
-void SetUserChoiceHistogram(SigninChoice choice) {
-  UMA_HISTOGRAM_ENUMERATION("Enterprise.UserSigninChoice",
-                            choice,
-                            SIGNIN_CHOICE_SIZE);
-}
-
-}  // namespace
-
-OneClickSigninSyncStarter::OneClickSigninSyncStarter(
-    Profile* profile,
-    Browser* browser,
-    const std::string& gaia_id,
-    const std::string& email,
-    const std::string& password,
-    const std::string& refresh_token,
-    signin_metrics::AccessPoint signin_access_point,
-    signin_metrics::Reason signin_reason,
-    ProfileMode profile_mode,
-    Callback sync_setup_completed_callback)
-    : profile_(nullptr),
-      signin_access_point_(signin_access_point),
-      signin_reason_(signin_reason),
-      sync_setup_completed_callback_(sync_setup_completed_callback),
-      first_account_added_to_cookie_(false),
-      weak_pointer_factory_(this) {
-  DCHECK(profile);
-  BrowserList::AddObserver(this);
-  Initialize(profile, browser);
-  DCHECK(!refresh_token.empty());
-
-  DCHECK(primary_account_mutator_);
-  primary_account_mutator_->LegacyStartSigninWithRefreshTokenForPrimaryAccount(
-      refresh_token, gaia_id, email,
-      base::BindOnce(&OneClickSigninSyncStarter::ConfirmSignin,
-                     weak_pointer_factory_.GetWeakPtr(), profile_mode));
-}
-
-void OneClickSigninSyncStarter::OnBrowserRemoved(Browser* browser) {
-  if (browser == browser_)
-    browser_ = nullptr;
-}
-
-OneClickSigninSyncStarter::~OneClickSigninSyncStarter() {
-  BrowserList::RemoveObserver(this);
-  LoginUIServiceFactory::GetForProfile(profile_)->RemoveObserver(this);
-}
-
-void OneClickSigninSyncStarter::Initialize(Profile* profile, Browser* browser) {
-  DCHECK(profile);
-
-  if (profile_)
-    LoginUIServiceFactory::GetForProfile(profile_)->RemoveObserver(this);
-
-  profile_ = profile;
-  browser_ = browser;
-
-  LoginUIServiceFactory::GetForProfile(profile_)->AddObserver(this);
-
-  signin_tracker_ = SigninTrackerFactory::CreateForProfile(profile_, this);
-
-  // Let the sync service know that setup is in progress so it doesn't start
-  // syncing until the user has finished any configuration.
-  syncer::SyncService* sync_service = GetSyncService();
-  if (sync_service)
-    sync_blocker_ = sync_service->GetSetupInProgressHandle();
-
-  // Make sure the syncing is requested, otherwise the IdentityManager's primary
-  // account mutator will not be able to complete successfully.
-  syncer::SyncPrefs sync_prefs(profile_->GetPrefs());
-  sync_prefs.SetSyncRequested(true);
-
-  // Cache the IdentityManager's PrimaryAccountMutator each time the profile
-  // gets changed, as it will be used from multiple places in several methods.
-  primary_account_mutator_ = IdentityManagerFactory::GetForProfile(profile_)
-                                 ->GetPrimaryAccountMutator();
-}
-
-void OneClickSigninSyncStarter::ConfirmSignin(ProfileMode profile_mode,
-                                              const std::string& oauth_token) {
-  identity::IdentityManager* identity_manager =
-      IdentityManagerFactory::GetForProfile(profile_);
-
-  if (identity_manager->HasPrimaryAccount()) {
-    // The user is already signed in - just tell IdentityManager's primary
-    // account mutator to continue with its re-auth flow.
-    DCHECK_EQ(CURRENT_PROFILE, profile_mode);
-    primary_account_mutator_->LegacyCompletePendingPrimaryAccountSignin();
-    return;
-  }
-
-  switch (profile_mode) {
-    case CURRENT_PROFILE: {
-      // If this is a new signin (no account authenticated yet) try loading
-      // policy for this user now, before any signed in services are
-      // initialized.
-      policy::UserPolicySigninService* policy_service =
-          policy::UserPolicySigninServiceFactory::GetForProfile(profile_);
-      policy_service->RegisterForPolicyWithLoginToken(
-          primary_account_mutator_->LegacyPrimaryAccountForAuthInProgress()
-              .email,
-          oauth_token,
-          base::Bind(&OneClickSigninSyncStarter::OnRegisteredForPolicy,
-                     weak_pointer_factory_.GetWeakPtr()));
-      break;
-    }
-    case NEW_PROFILE:
-      // If this is a new signin (no account authenticated yet) in a new
-      // profile, then just create the new signed-in profile and skip loading
-      // the policy as there is no need to ask the user again if they should be
-      // signed in to a new profile. Note that in this case the policy will be
-      // applied after the new profile is signed in.
-      CreateNewSignedInProfile();
-      break;
-  }
-}
-
-OneClickSigninSyncStarter::SigninDialogDelegate::SigninDialogDelegate(
-    base::WeakPtr<OneClickSigninSyncStarter> sync_starter)
-    : sync_starter_(sync_starter) {
-}
-
-OneClickSigninSyncStarter::SigninDialogDelegate::~SigninDialogDelegate() {
-}
-
-void OneClickSigninSyncStarter::SigninDialogDelegate::OnCancelSignin() {
-  SetUserChoiceHistogram(SIGNIN_CHOICE_CANCEL);
-  base::RecordAction(
-      base::UserMetricsAction("Signin_EnterpriseAccountPrompt_Cancel"));
-  if (sync_starter_)
-    sync_starter_->CancelSigninAndDelete();
-}
-
-void OneClickSigninSyncStarter::SigninDialogDelegate::OnContinueSignin() {
-  SetUserChoiceHistogram(SIGNIN_CHOICE_CONTINUE);
-  base::RecordAction(
-      base::UserMetricsAction("Signin_EnterpriseAccountPrompt_ImportData"));
-
-  if (sync_starter_)
-    sync_starter_->LoadPolicyWithCachedCredentials();
-}
-
-void OneClickSigninSyncStarter::SigninDialogDelegate::OnSigninWithNewProfile() {
-  SetUserChoiceHistogram(SIGNIN_CHOICE_NEW_PROFILE);
-  base::RecordAction(
-      base::UserMetricsAction("Signin_EnterpriseAccountPrompt_DontImportData"));
-
-  if (sync_starter_)
-    sync_starter_->CreateNewSignedInProfile();
-}
-
-void OneClickSigninSyncStarter::OnRegisteredForPolicy(
-    const std::string& dm_token, const std::string& client_id) {
-  // If there's no token for the user (policy registration did not succeed) just
-  // finish signing in.
-  if (dm_token.empty()) {
-    DVLOG(1) << "Policy registration failed";
-    primary_account_mutator_->LegacyCompletePendingPrimaryAccountSignin();
-    return;
-  }
-
-  DVLOG(1) << "Policy registration succeeded: dm_token=" << dm_token;
-
-  // Stash away a copy of our CloudPolicyClient (should not already have one).
-  DCHECK(dm_token_.empty());
-  DCHECK(client_id_.empty());
-  dm_token_ = dm_token;
-  client_id_ = client_id;
-
-  if (signin_util::IsForceSigninEnabled()) {
-    LoadPolicyWithCachedCredentials();
-    return;
-  }
-
-  // Allow user to create a new profile before continuing with sign-in.
-  browser_ = EnsureBrowser(browser_, profile_);
-  content::WebContents* web_contents =
-      browser_->tab_strip_model()->GetActiveWebContents();
-  if (!web_contents) {
-    CancelSigninAndDelete();
-    return;
-  }
-
-  base::RecordAction(
-      base::UserMetricsAction("Signin_Show_EnterpriseAccountPrompt"));
-
-  TabDialogs::FromWebContents(web_contents)
-      ->ShowProfileSigninConfirmation(
-          browser_, profile_,
-          primary_account_mutator_->LegacyPrimaryAccountForAuthInProgress()
-              .email,
-          std::make_unique<SigninDialogDelegate>(
-              weak_pointer_factory_.GetWeakPtr()));
-}
-
-void OneClickSigninSyncStarter::LoadPolicyWithCachedCredentials() {
-  DCHECK(!dm_token_.empty());
-  DCHECK(!client_id_.empty());
-  policy::UserPolicySigninService* policy_service =
-      policy::UserPolicySigninServiceFactory::GetForProfile(profile_);
-
-  std::string username =
-      primary_account_mutator_->LegacyPrimaryAccountForAuthInProgress().email;
-  std::string gaia_id =
-      primary_account_mutator_->LegacyPrimaryAccountForAuthInProgress().gaia;
-  DCHECK(username.empty() == gaia_id.empty());
-  AccountId account_id =
-      username.empty() ? EmptyAccountId()
-                       : AccountId::FromUserEmailGaiaId(username, gaia_id);
-  policy_service->FetchPolicyForSignedInUser(
-      account_id, dm_token_, client_id_,
-      content::BrowserContext::GetDefaultStoragePartition(profile_)
-          ->GetURLLoaderFactoryForBrowserProcess(),
-      base::Bind(&OneClickSigninSyncStarter::OnPolicyFetchComplete,
-                 weak_pointer_factory_.GetWeakPtr()));
-}
-
-void OneClickSigninSyncStarter::OnPolicyFetchComplete(bool success) {
-  // For now, we allow signin to complete even if the policy fetch fails. If
-  // we ever want to change this behavior, we could call
-  // PrimaryAccountMutator::ClearPrimaryAccount() here instead.
-  DLOG_IF(ERROR, !success) << "Error fetching policy for user";
-  DVLOG_IF(1, success) << "Policy fetch successful - completing signin";
-
-  primary_account_mutator_->LegacyCompletePendingPrimaryAccountSignin();
-}
-
-void OneClickSigninSyncStarter::CreateNewSignedInProfile() {
-  const std::string email =
-      primary_account_mutator_->LegacyPrimaryAccountForAuthInProgress().email;
-  DCHECK(!email.empty());
-
-  // Create a new profile and have it call back when done so we can inject our
-  // signin credentials.
-  size_t icon_index = g_browser_process->profile_manager()->
-      GetProfileAttributesStorage().ChooseAvatarIconIndexForNewProfile();
-  ProfileManager::CreateMultiProfileAsync(
-      base::UTF8ToUTF16(email), profiles::GetDefaultAvatarIconUrl(icon_index),
-      base::Bind(&OneClickSigninSyncStarter::CompleteInitForNewProfile,
-                 weak_pointer_factory_.GetWeakPtr()));
-}
-
-void OneClickSigninSyncStarter::CompleteInitForNewProfile(
-    Profile* new_profile,
-    Profile::CreateStatus status) {
-  DCHECK_NE(profile_, new_profile);
-
-  // TODO(atwilson): On error, unregister the client to release the DMToken
-  // and surface a better error for the user.
-  switch (status) {
-    case Profile::CREATE_STATUS_LOCAL_FAIL: {
-      NOTREACHED() << "Error creating new profile";
-      CancelSigninAndDelete();
-      return;
-    }
-    case Profile::CREATE_STATUS_CREATED: {
-      break;
-    }
-    case Profile::CREATE_STATUS_INITIALIZED:
-      // Pre-DICE, the refresh token is copied to the new profile and the user
-      // does not need to autehnticate in the new profile.
-      CopyCredentialsToNewProfileAndFinishSignin(new_profile);
-      break;
-    case Profile::CREATE_STATUS_REMOTE_FAIL:
-    case Profile::CREATE_STATUS_CANCELED:
-    case Profile::MAX_CREATE_STATUS: {
-      NOTREACHED() << "Invalid profile creation status";
-      CancelSigninAndDelete();
-      return;
-    }
-  }
-}
-
-void OneClickSigninSyncStarter::CopyCredentialsToNewProfileAndFinishSignin(
-    Profile* new_profile) {
-  // Wait until the profile is initialized before we transfer credentials.
-  identity::IdentityManager* new_identity_manager =
-      IdentityManagerFactory::GetForProfile(new_profile);
-  auto* new_primary_account_mutator =
-      new_identity_manager->GetPrimaryAccountMutator();
-  DCHECK(new_primary_account_mutator);
-
-  DCHECK(!primary_account_mutator_->LegacyPrimaryAccountForAuthInProgress()
-              .email.empty());
-
-  identity::IdentityManager* identity_manager =
-      IdentityManagerFactory::GetForProfile(profile_);
-  DCHECK(!identity_manager->HasPrimaryAccount());
-  DCHECK(!new_identity_manager->HasPrimaryAccount());
-
-  // Copy credentials from the old profile to the just-created profile,
-  // and switch over to tracking that profile.
-  new_primary_account_mutator->LegacyCopyCredentialsFrom(
-      *primary_account_mutator_);
-  FinishSyncServiceSetup();
-  Initialize(new_profile, nullptr);
-  DCHECK_EQ(profile_, new_profile);
-
-  // We've transferred our credentials to the new profile - notify that
-  // the signin for the original profile was cancelled (must do this after
-  // we have called Initialize() with the new profile, as otherwise this
-  // object will get freed when the signin on the old profile is cancelled.
-  // ClearPrimaryAccount does not actually remove the accounts if the
-  // signin is still pending. See http://crbug.com/799437.
-  primary_account_mutator_->ClearPrimaryAccount(
-      identity::PrimaryAccountMutator::ClearAccountsAction::kRemoveAll,
-      signin_metrics::TRANSFER_CREDENTIALS,
-      signin_metrics::SignoutDelete::IGNORE_METRIC);
-
-  if (!dm_token_.empty()) {
-    // Load policy for the just-created profile - once policy has finished
-    // loading the signin process will complete.
-    DCHECK(!client_id_.empty());
-    LoadPolicyWithCachedCredentials();
-  } else {
-    // No policy to load - simply complete the signin process.
-    primary_account_mutator_->LegacyCompletePendingPrimaryAccountSignin();
-  }
-
-  // Unlock the new profile.
-  ProfileAttributesEntry* entry;
-  bool has_entry =
-      g_browser_process->profile_manager()
-          ->GetProfileAttributesStorage()
-          .GetProfileAttributesWithPath(profile_->GetPath(), &entry);
-  DCHECK(has_entry);
-  entry->SetIsSigninRequired(false);
-
-  // Open the profile's first window, after all initialization.
-  profiles::FindOrCreateNewWindowForProfile(
-      new_profile, chrome::startup::IS_PROCESS_STARTUP,
-      chrome::startup::IS_FIRST_RUN, false);
-}
-
-void OneClickSigninSyncStarter::CancelSigninAndDelete() {
-  DCHECK(primary_account_mutator_->LegacyIsPrimaryAccountAuthInProgress());
-
-  // ClearPrimaryAccount does not actually remove the accounts if the
-  // signin is still pending. See http://crbug.com/799437.
-  primary_account_mutator_->ClearPrimaryAccount(
-      identity::PrimaryAccountMutator::ClearAccountsAction::kRemoveAll,
-      signin_metrics::ABORT_SIGNIN,
-      signin_metrics::SignoutDelete::IGNORE_METRIC);
-  // The statement above results in a call to SigninFailed() which will free
-  // this object, so do not refer to the OneClickSigninSyncStarter object
-  // after this point.
-}
-
-void OneClickSigninSyncStarter::OnSyncConfirmationUIClosed(
-    LoginUIService::SyncConfirmationUIClosedResult result) {
-  // We didn't run this callback in AccountAddedToCookie so do it now.
-  if (!sync_setup_completed_callback_.is_null())
-    sync_setup_completed_callback_.Run(SYNC_SETUP_SUCCESS);
-
-  unified_consent::UnifiedConsentService* consent_service =
-      UnifiedConsentServiceFactory::GetForProfile(profile_);
-
-  switch (result) {
-    case LoginUIService::CONFIGURE_SYNC_FIRST:
-      if (consent_service)
-        consent_service->EnableGoogleServices();
-      ShowSyncSetupSettingsSubpage();
-      break;
-    case LoginUIService::SYNC_WITH_DEFAULT_SETTINGS: {
-      syncer::SyncService* sync_service = GetSyncService();
-      if (sync_service)
-        sync_service->GetUserSettings()->SetFirstSetupComplete();
-      if (consent_service)
-        consent_service->EnableGoogleServices();
-      FinishSyncServiceSetup();
-      break;
-    }
-    case LoginUIService::ABORT_SIGNIN:
-      primary_account_mutator_->ClearPrimaryAccount(
-          identity::PrimaryAccountMutator::ClearAccountsAction::kDefault,
-          signin_metrics::ABORT_SIGNIN,
-          signin_metrics::SignoutDelete::IGNORE_METRIC);
-      FinishSyncServiceSetup();
-      break;
-  }
-
-  delete this;
-}
-
-void OneClickSigninSyncStarter::SigninFailed(
-    const GoogleServiceAuthError& error) {
-  if (!sync_setup_completed_callback_.is_null())
-    sync_setup_completed_callback_.Run(SYNC_SETUP_FAILURE);
-
-  FinishSyncServiceSetup();
-  switch (error.state()) {
-    case GoogleServiceAuthError::SERVICE_UNAVAILABLE:
-      DisplayFinalConfirmationBubble(
-          l10n_util::GetStringUTF16(IDS_SYNC_UNRECOVERABLE_ERROR));
-      break;
-    case GoogleServiceAuthError::REQUEST_CANCELED:
-      // No error notification needed if the user manually cancelled signin.
-      break;
-    default:
-      DisplayFinalConfirmationBubble(
-          l10n_util::GetStringUTF16(IDS_SYNC_ERROR_SIGNING_IN));
-      break;
-  }
-  delete this;
-}
-
-void OneClickSigninSyncStarter::SigninSuccess() {
-  signin_metrics::LogSigninAccessPointCompleted(
-      signin_access_point_,
-      signin_metrics::PromoAction::PROMO_ACTION_NO_SIGNIN_PROMO);
-  signin_metrics::LogSigninReason(signin_reason_);
-  base::RecordAction(base::UserMetricsAction("Signin_Signin_Succeed"));
-}
-
-void OneClickSigninSyncStarter::AccountAddedToCookie(
-    const GoogleServiceAuthError& error) {
-  if (first_account_added_to_cookie_)
-    return;
-
-  first_account_added_to_cookie_ = true;
-
-  // Regardless of whether the account was successfully added or not,
-  // continue with sync starting.
-
-  // |sync_setup_completed_callback_| will be run after the modal is closed.
-  DisplayModalSyncConfirmationWindow();
-}
-
-void OneClickSigninSyncStarter::DisplayFinalConfirmationBubble(
-    const base::string16& custom_message) {
-  browser_ = EnsureBrowser(browser_, profile_);
-  LoginUIServiceFactory::GetForProfile(browser_->profile())
-      ->DisplayLoginResult(browser_, custom_message, base::string16());
-}
-
-void OneClickSigninSyncStarter::DisplayModalSyncConfirmationWindow() {
-  browser_ = EnsureBrowser(browser_, profile_);
-  browser_->signin_view_controller()->ShowModalSyncConfirmationDialog(browser_);
-}
-
-// static
-Browser* OneClickSigninSyncStarter::EnsureBrowser(Browser* browser,
-                                                  Profile* profile) {
-  if (!browser) {
-    // The user just created a new profile or has closed the browser that
-    // we used previously. Grab the most recently active browser or else
-    // create a new one.
-    browser = chrome::FindLastActiveWithProfile(profile);
-    if (!browser) {
-      browser = new Browser(Browser::CreateParams(profile, true));
-      chrome::AddTabAt(browser, GURL(), -1, true);
-    }
-    browser->window()->Show();
-  }
-  return browser;
-}
-
-void OneClickSigninSyncStarter::ShowSyncSetupSettingsSubpage() {
-  chrome::ShowSettingsSubPage(browser_, chrome::kSyncSetupSubPage);
-}
-
-syncer::SyncService* OneClickSigninSyncStarter::GetSyncService() {
-  if (!profile_->IsSyncAllowed())
-    return nullptr;
-  return ProfileSyncServiceFactory::GetSyncServiceForProfile(profile_);
-}
-
-void OneClickSigninSyncStarter::FinishSyncServiceSetup() {
-  sync_blocker_.reset();
-}
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_starter.h b/chrome/browser/ui/sync/one_click_signin_sync_starter.h
deleted file mode 100644
index 394e14b..0000000
--- a/chrome/browser/ui/sync/one_click_signin_sync_starter.h
+++ /dev/null
@@ -1,198 +0,0 @@
-// Copyright (c) 2012 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_UI_SYNC_ONE_CLICK_SIGNIN_SYNC_STARTER_H_
-#define CHROME_BROWSER_UI_SYNC_ONE_CLICK_SIGNIN_SYNC_STARTER_H_
-
-#include <memory>
-#include <string>
-
-#include "base/callback_forward.h"
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser_list_observer.h"
-#include "chrome/browser/ui/sync/profile_signin_confirmation_helper.h"
-#include "chrome/browser/ui/webui/signin/login_ui_service.h"
-#include "components/signin/core/browser/signin_tracker.h"
-
-class Browser;
-
-namespace identity {
-class PrimaryAccountMutator;
-}
-
-namespace syncer {
-class SyncService;
-class SyncSetupInProgressHandle;
-}  // namespace syncer
-
-// Waits for successful sign-in notification from the signin manager and then
-// starts the sync machine.  Instances of this class delete themselves once
-// the job is done.
-class OneClickSigninSyncStarter : public SigninTracker::Observer,
-                                  public BrowserListObserver,
-                                  public LoginUIService::Observer {
- public:
-  enum ProfileMode {
-    // Attempts to sign the user in |profile_|. Note that if the account to be
-    // signed in is a managed account, then a profile confirmation dialog is
-    // shown and the user has the possibility to create a new profile before
-    // signing in.
-    CURRENT_PROFILE,
-
-    // Creates a new profile and signs the user in this new profile.
-    NEW_PROFILE
-  };
-
-  // Result of the sync setup.
-  enum SyncSetupResult {
-    SYNC_SETUP_SUCCESS,
-    SYNC_SETUP_FAILURE
-  };
-
-  using Callback = base::Callback<void(SyncSetupResult)>;
-
-  // |profile| must not be NULL, however |browser| can be. When using the
-  // OneClickSigninSyncStarter from a browser, provide both.
-  // If |display_confirmation| is true, the user will be prompted to confirm the
-  // signin before signin completes.
-  // |callback| is always executed before OneClickSigninSyncStarter is deleted.
-  // It can be empty.
-  OneClickSigninSyncStarter(Profile* profile,
-                            Browser* browser,
-                            const std::string& gaia_id,
-                            const std::string& email,
-                            const std::string& password,
-                            const std::string& refresh_token,
-                            signin_metrics::AccessPoint signin_access_point,
-                            signin_metrics::Reason signin_reason,
-                            ProfileMode profile_mode,
-                            Callback callback);
-
-  // BrowserListObserver override.
-  void OnBrowserRemoved(Browser* browser) override;
-
-  // If the |browser| argument is non-null, returns the pointer directly.
-  // Otherwise creates a new browser for the given profile on the given
-  // desktop, adds an empty tab and makes sure the browser is visible.
-  static Browser* EnsureBrowser(Browser* browser, Profile* profile);
-
- protected:
-  ~OneClickSigninSyncStarter() override;
-
-  // Overridden from tests.
-  virtual void ShowSyncSetupSettingsSubpage();
-
- private:
-  friend class OneClickSigninSyncStarterTest;
-  FRIEND_TEST_ALL_PREFIXES(OneClickSigninSyncStarterTest, CallbackSigninFailed);
-  FRIEND_TEST_ALL_PREFIXES(OneClickSigninSyncStarterTest, CallbackNull);
-
-  // Initializes the internals of the OneClickSigninSyncStarter object. Can also
-  // be used to re-initialize the object to refer to a newly created profile.
-  void Initialize(Profile* profile, Browser* browser);
-
-  // SigninTracker::Observer override.
-  void SigninFailed(const GoogleServiceAuthError& error) override;
-  void SigninSuccess() override;
-  void AccountAddedToCookie(const GoogleServiceAuthError& error) override;
-
-  // LoginUIService::Observer override.
-  void OnSyncConfirmationUIClosed(
-      LoginUIService::SyncConfirmationUIClosedResult result) override;
-
-  // User input handler for the signin confirmation dialog.
-  class SigninDialogDelegate
-    : public ui::ProfileSigninConfirmationDelegate {
-   public:
-    SigninDialogDelegate(
-        base::WeakPtr<OneClickSigninSyncStarter> sync_starter);
-    ~SigninDialogDelegate() override;
-    void OnCancelSignin() override;
-    void OnContinueSignin() override;
-    void OnSigninWithNewProfile() override;
-
-   private:
-    base::WeakPtr<OneClickSigninSyncStarter> sync_starter_;
-  };
-  friend class SigninDialogDelegate;
-
-  // Callback invoked once policy registration is complete. If registration
-  // fails, |dm_token| and |client_id| will be empty.
-  void OnRegisteredForPolicy(const std::string& dm_token,
-                             const std::string& client_id);
-
-  // Callback invoked when a policy fetch request has completed. |success| is
-  // true if policy was successfully fetched.
-  void OnPolicyFetchComplete(bool success);
-
-  // Called to create a new profile, which is then signed in with the
-  // in-progress auth credentials currently stored in this object.
-  void CreateNewSignedInProfile();
-
-  // Copies the sign-in credentials to |new_profile| and starts syncing in
-  // |new_profile|.
-  void CopyCredentialsToNewProfileAndFinishSignin(Profile* new_profile);
-
-  // Helper function that loads policy with the cached |dm_token_| and
-  // |client_id|, then completes the signin process.
-  void LoadPolicyWithCachedCredentials();
-
-  // Callback invoked once a profile is created, so we can complete the
-  // credentials transfer, load policy, and open the first window.
-  void CompleteInitForNewProfile(Profile* profile,
-                                 Profile::CreateStatus status);
-
-  // Cancels the in-progress signin for this profile.
-  void CancelSigninAndDelete();
-
-  // Callback invoked to check whether the user needs policy or if a
-  // confirmation is required (in which case we have to prompt the user first).
-  void ConfirmSignin(ProfileMode profile_mode, const std::string& oauth_token);
-
-  // GetSyncService returns non-NULL pointer if sync is enabled.
-  syncer::SyncService* GetSyncService();
-
-  // Finishes the setup of the profile sync service.
-  void FinishSyncServiceSetup();
-
-  // Shows the post-signin confirmation bubble. If |custom_message| is empty,
-  // the default "You are signed in" message is displayed.
-  void DisplayFinalConfirmationBubble(const base::string16& custom_message);
-
-  // Displays the sync confirmation modal dialog.
-  void DisplayModalSyncConfirmationWindow();
-
-  Profile* profile_;
-  Browser* browser_;
-  signin_metrics::AccessPoint signin_access_point_;
-  signin_metrics::Reason signin_reason_;
-  identity::PrimaryAccountMutator* primary_account_mutator_;
-  std::unique_ptr<SigninTracker> signin_tracker_;
-
-  // Callback executed when sync setup succeeds or fails.
-  Callback sync_setup_completed_callback_;
-
-  // Policy credentials we keep while determining whether to create
-  // a new profile for an enterprise user or not.
-  std::string dm_token_;
-  std::string client_id_;
-
-  // This only cares about the first AccountAddedToCookie event. Since
-  // SigninTracker always expects an observer, this object will just disregard
-  // following AccountAddedToCookie calls triggered by account reconciliation.
-  bool first_account_added_to_cookie_;
-
-  // Prevents Sync from running until configuration is complete.
-  std::unique_ptr<syncer::SyncSetupInProgressHandle> sync_blocker_;
-
-  base::WeakPtrFactory<OneClickSigninSyncStarter> weak_pointer_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(OneClickSigninSyncStarter);
-};
-
-
-#endif  // CHROME_BROWSER_UI_SYNC_ONE_CLICK_SIGNIN_SYNC_STARTER_H_
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_starter_unittest.cc b/chrome/browser/ui/sync/one_click_signin_sync_starter_unittest.cc
deleted file mode 100644
index 656a102..0000000
--- a/chrome/browser/ui/sync/one_click_signin_sync_starter_unittest.cc
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/sync/one_click_signin_sync_starter.h"
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/test/base/chrome_render_view_host_test_harness.h"
-#include "chrome/test/base/testing_profile.h"
-#include "components/browser_sync/browser_sync_switches.h"
-#include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "services/identity/public/cpp/identity_test_environment.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-class OneClickSigninSyncStarterTest : public ChromeRenderViewHostTestHarness {
- public:
-  OneClickSigninSyncStarterTest()
-      : sync_starter_(nullptr), failed_count_(0), succeeded_count_(0) {}
-
-  // ChromeRenderViewHostTestHarness:
-  void SetUp() override {
-    ChromeRenderViewHostTestHarness::SetUp();
-
-    // Disable sync to simplify the creation of a OneClickSigninSyncStarter.
-    base::CommandLine::ForCurrentProcess()->AppendSwitch(
-        switches::kDisableSync);
-
-    IdentityTestEnvironmentProfileAdaptor identity_test_env_profile_adaptor(
-        profile());
-    account_info_ = identity_test_env_profile_adaptor.identity_test_env()
-                        ->MakePrimaryAccountAvailable("test@email.com");
-  }
-
-  void Callback(OneClickSigninSyncStarter::SyncSetupResult result) {
-    if (result == OneClickSigninSyncStarter::SYNC_SETUP_SUCCESS)
-      ++succeeded_count_;
-    else
-      ++failed_count_;
-  }
-
-  // ChromeRenderViewHostTestHarness:
-  content::BrowserContext* CreateBrowserContext() override {
-    // Create the sign in manager required by OneClickSigninSyncStarter.
-    return IdentityTestEnvironmentProfileAdaptor::
-        CreateProfileForIdentityTestEnvironment()
-            .release();
-  }
-
- protected:
-  void CreateSyncStarter(OneClickSigninSyncStarter::Callback callback) {
-    std::string refresh_token =
-        "refresh_token_for_" +
-        account_info_.account_id;  // This matches the refresh token string set
-                                   // in identity::SetRefreshTokenForAccount.
-    sync_starter_ = new OneClickSigninSyncStarter(
-        profile(), nullptr, account_info_.gaia, account_info_.email,
-        std::string(), refresh_token,
-        signin_metrics::AccessPoint::ACCESS_POINT_UNKNOWN,
-        signin_metrics::Reason::REASON_UNKNOWN_REASON,
-        OneClickSigninSyncStarter::CURRENT_PROFILE, callback);
-  }
-
-  // Deletes itself when SigninFailed() or SigninSuccess() is called.
-  OneClickSigninSyncStarter* sync_starter_;
-
-  // Number of times that the callback is called with SYNC_SETUP_FAILURE.
-  int failed_count_;
-
-  // Number of times that the callback is called with SYNC_SETUP_SUCCESS.
-  int succeeded_count_;
-
-  // Holds information for the account currently logged in.
-  AccountInfo account_info_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(OneClickSigninSyncStarterTest);
-};
-
-// Verifies that the callback is invoked when sync setup fails.
-TEST_F(OneClickSigninSyncStarterTest, CallbackSigninFailed) {
-  CreateSyncStarter(base::Bind(&OneClickSigninSyncStarterTest::Callback,
-                               base::Unretained(this)));
-  sync_starter_->SigninFailed(GoogleServiceAuthError(
-      GoogleServiceAuthError::REQUEST_CANCELED));
-  EXPECT_EQ(1, failed_count_);
-  EXPECT_EQ(0, succeeded_count_);
-}
-
-// Verifies that there is no crash when the callback is NULL.
-TEST_F(OneClickSigninSyncStarterTest, CallbackNull) {
-  CreateSyncStarter(OneClickSigninSyncStarter::Callback());
-  sync_starter_->SigninFailed(GoogleServiceAuthError(
-      GoogleServiceAuthError::REQUEST_CANCELED));
-  EXPECT_EQ(0, failed_count_);
-  EXPECT_EQ(0, succeeded_count_);
-}
diff --git a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest.cc b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest.cc
index d11ac97..c737177 100644
--- a/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest.cc
+++ b/chrome/browser/ui/views/autofill/save_card_bubble_views_browsertest.cc
@@ -13,7 +13,6 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/metrics/user_action_tester.h"
 #include "base/test/scoped_feature_list.h"
-#include "build/build_config.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
@@ -95,11 +94,9 @@
     "link: "
     "{0}.\",\"template_parameter\":[{\"display_text\":\"Link\",\"url\":\"https:"
     "//www.example.com/\"}]}]},\"context_token\":\"dummy_context_token\"}";
-const char kResponsePaymentsFailure[] =
+const char kResponseGetUploadDetailsFailure[] =
     "{\"error\":{\"code\":\"FAILED_PRECONDITION\",\"user_error_message\":\"An "
     "unexpected error has occurred. Please try again later.\"}}";
-const char kURLUploadCardRequest[] =
-    "https://payments.google.com/payments/apis/chromepaymentsservice/savecard";
 
 const double kFakeGeolocationLatitude = 1.23;
 const double kFakeGeolocationLongitude = 4.56;
@@ -512,7 +509,7 @@
 
   void SetUploadDetailsRpcPaymentsDeclines() {
     test_url_loader_factory()->AddResponse(kURLGetUploadDetailsRequest,
-                                           kResponsePaymentsFailure);
+                                           kResponseGetUploadDetailsFailure);
   }
 
   void SetUploadDetailsRpcServerError() {
@@ -521,11 +518,6 @@
                                            net::HTTP_INTERNAL_SERVER_ERROR);
   }
 
-  void SetUploadCardRpcPaymentsFails() {
-    test_url_loader_factory()->AddResponse(kURLUploadCardRequest,
-                                           kResponsePaymentsFailure);
-  }
-
   void ClickOnView(views::View* view) {
     DCHECK(view);
     ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
@@ -598,19 +590,19 @@
     return specified_view;
   }
 
-  void ClickOnCancelButton(bool strike_expected = false) {
+  void ClickOnCancelButton() {
     SaveCardBubbleViews* save_card_bubble_views = GetSaveCardBubbleViews();
     DCHECK(save_card_bubble_views);
-    if (strike_expected &&
-        (base::FeatureList::IsEnabled(
-             features::kAutofillSaveCreditCardUsesStrikeSystem) ||
-         base::FeatureList::IsEnabled(
-             features::kAutofillSaveCreditCardUsesStrikeSystemV2))) {
+    if (base::FeatureList::IsEnabled(
+            features::kAutofillSaveCreditCardUsesStrikeSystem) ||
+        base::FeatureList::IsEnabled(
+            features::kAutofillSaveCreditCardUsesStrikeSystemV2)) {
       ResetEventWaiterForSequence(
           {DialogEvent::STRIKE_CHANGE_COMPLETE, DialogEvent::BUBBLE_CLOSED});
     } else {
       ResetEventWaiterForSequence({DialogEvent::BUBBLE_CLOSED});
     }
+
     ClickOnDialogViewWithIdAndWait(DialogViewId::CANCEL_BUTTON);
     DCHECK(!GetSaveCardBubbleViews());
   }
@@ -728,12 +720,8 @@
 IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest,
                        Local_ClickingNoThanksClosesBubble) {
   // Enable the updated UI.
-  scoped_feature_list_.InitWithFeatures(
-      // Enabled
-      {features::kAutofillSaveCardImprovedUserConsent},
-      // Disabled
-      {features::kAutofillSaveCreditCardUsesStrikeSystem,
-       features::kAutofillSaveCreditCardUsesStrikeSystemV2});
+  scoped_feature_list_.InitAndEnableFeature(
+      features::kAutofillSaveCardImprovedUserConsent);
 
   // Submitting the form and having Payments decline offering to save should
   // show the local save bubble.
@@ -1266,8 +1254,7 @@
       {features::kAutofillSaveCardImprovedUserConsent,
        features::kAutofillUpstream},
       // Disabled
-      {features::kAutofillSaveCreditCardUsesStrikeSystem,
-       features::kAutofillSaveCreditCardUsesStrikeSystemV2});
+      {});
 
   // Start sync.
   harness_->SetupSync();
@@ -2288,414 +2275,4 @@
             year_input()->GetTextForRow(year_input()->selected_index()));
 }
 
-// TODO(crbug.com/884817): Investigate combining local vs. upload tests using a
-//                         boolean to branch local vs. upload logic.
-
-// Tests StrikeDatabase interaction with the local save bubble. Ensures that no
-// strikes are added if the feature flag is disabled.
-IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest,
-                       StrikeDatabase_Local_StrikeNotAddedIfExperimentFlagOff) {
-  // Disable the the SaveCreditCardUsesStrikeSystem experiments.
-  scoped_feature_list_.InitWithFeatures(
-      // Enabled
-      {features::kAutofillSaveCardImprovedUserConsent},
-      // Disabled
-      {features::kAutofillSaveCreditCardUsesStrikeSystem,
-       features::kAutofillSaveCreditCardUsesStrikeSystemV2});
-
-  // Submitting the form and having Payments decline offering to save should
-  // show the local save bubble.
-  // (Must wait for response from Payments before accessing the controller.)
-  ResetEventWaiterForSequence({DialogEvent::OFFERED_LOCAL_SAVE});
-  NavigateTo(kCreditCardUploadForm);
-  FillAndSubmitForm();
-  WaitForObservedEvent();
-  EXPECT_TRUE(
-      FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_LOCAL)->visible());
-
-  base::HistogramTester histogram_tester;
-  ClickOnCancelButton();
-
-  // Ensure that no strike was added because the feature is disabled.
-  histogram_tester.ExpectTotalCount(
-      "Autofill.StrikeDatabase.NthStrikeAdded.CreditCardSave", 0);
-}
-
-// Tests StrikeDatabase interaction with the upload save bubble. Ensures that no
-// strikes are added if the feature flag is disabled.
-IN_PROC_BROWSER_TEST_F(
-    SaveCardBubbleViewsFullFormBrowserTest,
-    StrikeDatabase_Upload_StrikeNotAddedIfExperimentFlagOff) {
-  // Disable the the SaveCreditCardUsesStrikeSystem experiments.
-  scoped_feature_list_.InitWithFeatures(
-      // Enabled
-      {features::kAutofillUpstream,
-       features::kAutofillSaveCardImprovedUserConsent},
-      // Disabled
-      {features::kAutofillSaveCreditCardUsesStrikeSystem,
-       features::kAutofillSaveCreditCardUsesStrikeSystemV2});
-
-  // Start sync.
-  harness_->SetupSync();
-
-  // Set up the Payments RPC.
-  SetUploadDetailsRpcPaymentsAccepts();
-
-  // Submitting the form should show the upload save bubble and legal footer.
-  // (Must wait for response from Payments before accessing the controller.)
-  ResetEventWaiterForSequence(
-      {DialogEvent::REQUESTED_UPLOAD_SAVE,
-       DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE});
-  NavigateTo(kCreditCardUploadForm);
-  FillAndSubmitForm();
-  WaitForObservedEvent();
-  EXPECT_TRUE(
-      FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_UPLOAD)->visible());
-  EXPECT_TRUE(FindViewInBubbleById(DialogViewId::FOOTNOTE_VIEW)->visible());
-
-  base::HistogramTester histogram_tester;
-
-  ClickOnCancelButton();
-
-  // Ensure that no strike was added because the feature is disabled.
-  histogram_tester.ExpectTotalCount(
-      "Autofill.StrikeDatabase.NthStrikeAdded.CreditCardSave", 0);
-}
-
-// Tests StrikeDatabase interaction with the local save bubble. Ensures that a
-// strike is added if the bubble is ignored.
-IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest,
-                       StrikeDatabase_Local_AddStrikeIfBubbleIgnored) {
-  scoped_feature_list_.InitAndEnableFeature(
-      features::kAutofillSaveCreditCardUsesStrikeSystemV2);
-
-  TestAutofillClock test_clock;
-  test_clock.SetNow(base::Time::Now());
-
-  // Set up the Payments RPC.
-  SetUploadDetailsRpcPaymentsDeclines();
-
-  // Submitting the form and having Payments decline offering to save should
-  // show the local save bubble.
-  // (Must wait for response from Payments before accessing the controller.)
-  ResetEventWaiterForSequence({DialogEvent::OFFERED_LOCAL_SAVE});
-  NavigateTo(kCreditCardUploadForm);
-  FillAndSubmitForm();
-  WaitForObservedEvent();
-  EXPECT_TRUE(
-      FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_LOCAL)->visible());
-
-  // Clicking the [X] close button should dismiss the bubble.
-  ClickOnCloseButton();
-
-  // Add an event observer to the controller to detect strike changes.
-  AddEventObserverToController();
-
-  base::HistogramTester histogram_tester;
-
-  // Wait long enough to avoid bubble stickiness, then navigate away from the
-  // page.
-  test_clock.Advance(kCardBubbleSurviveNavigationTime);
-  ResetEventWaiterForSequence({DialogEvent::STRIKE_CHANGE_COMPLETE});
-  NavigateTo(kCreditCardUploadForm);
-  WaitForObservedEvent();
-
-  // Ensure that a strike was added due to the bubble being ignored.
-  histogram_tester.ExpectUniqueSample(
-      "Autofill.StrikeDatabase.NthStrikeAdded.CreditCardSave",
-      /*sample=*/1, /*count=*/1);
-}
-
-// Tests StrikeDatabase interaction with the upload save bubble. Ensures that a
-// strike is added if the bubble is ignored.
-IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest,
-                       StrikeDatabase_Upload_AddStrikeIfBubbleIgnored) {
-  scoped_feature_list_.InitAndEnableFeature(
-      features::kAutofillSaveCreditCardUsesStrikeSystemV2);
-
-  TestAutofillClock test_clock;
-  test_clock.SetNow(base::Time::Now());
-
-  // Start sync.
-  harness_->SetupSync();
-
-  // Set up the Payments RPC.
-  SetUploadDetailsRpcPaymentsAccepts();
-
-  // Submitting the form should show the upload save bubble and legal footer.
-  // (Must wait for response from Payments before accessing the controller.)
-  ResetEventWaiterForSequence(
-      {DialogEvent::REQUESTED_UPLOAD_SAVE,
-       DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE});
-  NavigateTo(kCreditCardUploadForm);
-  FillAndSubmitForm();
-  WaitForObservedEvent();
-  EXPECT_TRUE(
-      FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_UPLOAD)->visible());
-  EXPECT_TRUE(FindViewInBubbleById(DialogViewId::FOOTNOTE_VIEW)->visible());
-
-  // Clicking the [X] close button should dismiss the bubble.
-  ClickOnCloseButton();
-
-  // Add an event observer to the controller to detect strike changes.
-  AddEventObserverToController();
-
-  base::HistogramTester histogram_tester;
-
-  // Wait long enough to avoid bubble stickiness, then navigate away from the
-  // page.
-  test_clock.Advance(kCardBubbleSurviveNavigationTime);
-  ResetEventWaiterForSequence({DialogEvent::STRIKE_CHANGE_COMPLETE});
-  NavigateTo(kCreditCardUploadForm);
-  WaitForObservedEvent();
-
-  // Ensure that a strike was added due to the bubble being ignored.
-  histogram_tester.ExpectUniqueSample(
-      "Autofill.StrikeDatabase.NthStrikeAdded.CreditCardSave",
-      /*sample=*/1, /*count=*/1);
-}
-
-// Tests the local save bubble. Ensures that clicking the [No thanks] button
-// successfully causes the bubble to go away.
-IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest,
-                       StrikeDatabase_Local_AddStrikeIfBubbleDeclined) {
-  // Enable the updated UI.
-  scoped_feature_list_.InitAndEnableFeature(
-      features::kAutofillSaveCardImprovedUserConsent);
-
-  // Submitting the form and having Payments decline offering to save should
-  // show the local save bubble.
-  // (Must wait for response from Payments before accessing the controller.)
-  ResetEventWaiterForSequence({DialogEvent::OFFERED_LOCAL_SAVE});
-  NavigateTo(kCreditCardUploadForm);
-  FillAndSubmitForm();
-  WaitForObservedEvent();
-  EXPECT_TRUE(
-      FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_LOCAL)->visible());
-
-  // Clicking [No thanks] should cancel and close it.
-  base::HistogramTester histogram_tester;
-  ClickOnCancelButton(/*strike_expected=*/true);
-
-  // Ensure that a strike was added.
-  histogram_tester.ExpectUniqueSample(
-      "Autofill.StrikeDatabase.NthStrikeAdded.CreditCardSave",
-      /*sample=*/(1), /*count=*/1);
-}
-
-// Tests the upload save bubble. Ensures that clicking the [No thanks] button
-// successfully causes a strike to be added.
-IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest,
-                       StrikeDatabase_Upload_AddStrikeIfBubbleDeclined) {
-  // Enable the updated UI.
-  scoped_feature_list_.InitWithFeatures(
-      // Enabled
-      {features::kAutofillSaveCardImprovedUserConsent,
-       features::kAutofillUpstream},
-      // Disabled
-      {});
-
-  // Start sync.
-  harness_->SetupSync();
-
-  // Set up the Payments RPC.
-  SetUploadDetailsRpcPaymentsAccepts();
-
-  // Submitting the form should show the upload save bubble and legal footer.
-  // (Must wait for response from Payments before accessing the controller.)
-  ResetEventWaiterForSequence(
-      {DialogEvent::REQUESTED_UPLOAD_SAVE,
-       DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE});
-  NavigateTo(kCreditCardUploadForm);
-  FillAndSubmitForm();
-  WaitForObservedEvent();
-  EXPECT_TRUE(
-      FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_UPLOAD)->visible());
-  EXPECT_TRUE(FindViewInBubbleById(DialogViewId::FOOTNOTE_VIEW)->visible());
-
-  // Clicking [No thanks] should cancel and close it.
-  base::HistogramTester histogram_tester;
-  ClickOnCancelButton(/*strike_expected=*/true);
-
-  // Ensure that a strike was added.
-  histogram_tester.ExpectUniqueSample(
-      "Autofill.StrikeDatabase.NthStrikeAdded.CreditCardSave",
-      /*sample=*/(1), /*count=*/1);
-}
-
-// Tests overall StrikeDatabase interaction with the local save bubble. Runs an
-// example of declining the prompt three times and ensuring that the
-// offer-to-save bubble does not appear on the fourth try. Then, ensures that no
-// strikes are added if the card already has max strikes.
-IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest,
-                       StrikeDatabase_Local_FullFlowTest) {
-  scoped_feature_list_.InitWithFeatures(
-      // Enabled
-      {features::kAutofillSaveCardImprovedUserConsent,
-       features::kAutofillSaveCreditCardUsesStrikeSystemV2},
-      // Disabled
-      {});
-
-  bool controller_observer_set = false;
-
-  // Show and ignore the bubble kMaxStrikesToPreventPoppingUpOfferToSavePrompt
-  // times in order to accrue maximum strikes.
-  for (int i = 0; i < kMaxStrikesToPreventPoppingUpOfferToSavePrompt; i++) {
-    // Submitting the form and having Payments decline offering to save should
-    // show the local save bubble.
-    // (Must wait for response from Payments before accessing the controller.)
-    ResetEventWaiterForSequence({DialogEvent::OFFERED_LOCAL_SAVE});
-    NavigateTo(kCreditCardUploadForm);
-    FillAndSubmitForm();
-    WaitForObservedEvent();
-    EXPECT_TRUE(
-        FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_LOCAL)->visible());
-
-    if (!controller_observer_set) {
-      // Add an event observer to the controller.
-      AddEventObserverToController();
-      ReduceAnimationTime();
-      controller_observer_set = true;
-    }
-
-    base::HistogramTester histogram_tester;
-    ResetEventWaiterForSequence({DialogEvent::STRIKE_CHANGE_COMPLETE});
-    ClickOnCancelButton(/*strike_expected=*/true);
-    WaitForObservedEvent();
-
-    // Ensure that a strike was added due to the bubble being declined.
-    // The sample logged is the Nth strike added, or (i+1).
-    histogram_tester.ExpectUniqueSample(
-        "Autofill.StrikeDatabase.NthStrikeAdded.CreditCardSave",
-        /*sample=*/(i + 1), /*count=*/1);
-  }
-
-  base::HistogramTester histogram_tester;
-
-  // Submit the form a fourth time. Since the card now has maximum strikes (3),
-  // the icon should be shown but the bubble should not.
-  ResetEventWaiterForSequence({DialogEvent::OFFERED_LOCAL_SAVE});
-  NavigateTo(kCreditCardUploadForm);
-  FillAndSubmitForm();
-  WaitForObservedEvent();
-  EXPECT_TRUE(GetSaveCardIconView()->visible());
-  EXPECT_FALSE(GetSaveCardBubbleViews());
-
-  // Click the icon to show the bubble.
-  ResetEventWaiterForSequence({DialogEvent::BUBBLE_SHOWN});
-  ClickOnView(GetSaveCardIconView());
-  WaitForObservedEvent();
-  EXPECT_TRUE(
-      FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_LOCAL)->visible());
-
-  ClickOnCancelButton();
-
-  // Ensure that no strike was added because the card already had max strikes.
-  histogram_tester.ExpectTotalCount(
-      "Autofill.StrikeDatabase.NthStrikeAdded.CreditCardSave", 0);
-
-  // Verify that the correct histogram entry was logged.
-  histogram_tester.ExpectBucketCount(
-      "Autofill.StrikeDatabase.CreditCardSaveNotOfferedDueToMaxStrikes",
-      AutofillMetrics::SaveTypeMetric::LOCAL, 1);
-
-  // UMA should have recorded bubble rejection.
-  histogram_tester.ExpectUniqueSample(
-      "Autofill.SaveCreditCardPrompt.Local.FirstShow",
-      AutofillMetrics::SAVE_CARD_ICON_SHOWN_WITHOUT_PROMPT, 1);
-}
-
-// Tests overall StrikeDatabase interaction with the upload save bubble. Runs an
-// example of declining the prompt three times and ensuring that the
-// offer-to-save bubble does not appear on the fourth try. Then, ensures that no
-// strikes are added if the card already has max strikes.
-IN_PROC_BROWSER_TEST_F(SaveCardBubbleViewsFullFormBrowserTest,
-                       StrikeDatabase_Upload_FullFlowTest) {
-  scoped_feature_list_.InitWithFeatures(
-      // Enabled
-      {features::kAutofillSaveCardImprovedUserConsent,
-       features::kAutofillSaveCreditCardUsesStrikeSystemV2},
-      // Disabled
-      {});
-
-  bool controller_observer_set = false;
-
-  // Start sync.
-  harness_->SetupSync();
-
-  // Set up the Payments RPC.
-  SetUploadDetailsRpcPaymentsAccepts();
-
-  // Show and ignore the bubble kMaxStrikesToPreventPoppingUpOfferToSavePrompt
-  // times in order to accrue maximum strikes.
-  for (int i = 0; i < kMaxStrikesToPreventPoppingUpOfferToSavePrompt; i++) {
-    // Submitting the form should show the upload save bubble and legal footer.
-    // (Must wait for response from Payments before accessing the controller.)
-    ResetEventWaiterForSequence(
-        {DialogEvent::REQUESTED_UPLOAD_SAVE,
-         DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE});
-    NavigateTo(kCreditCardUploadForm);
-    FillAndSubmitForm();
-    WaitForObservedEvent();
-    EXPECT_TRUE(FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_UPLOAD)
-                    ->visible());
-    EXPECT_TRUE(FindViewInBubbleById(DialogViewId::FOOTNOTE_VIEW)->visible());
-
-    if (!controller_observer_set) {
-      // Add an event observer to the controller.
-      AddEventObserverToController();
-      ReduceAnimationTime();
-      controller_observer_set = true;
-    }
-
-    base::HistogramTester histogram_tester;
-
-    ClickOnCancelButton(/*strike_expected=*/true);
-    WaitForObservedEvent();
-
-    // Ensure that a strike was added due to the bubble being declined.
-    // The sample logged is the Nth strike added, or (i+1).
-    histogram_tester.ExpectUniqueSample(
-        "Autofill.StrikeDatabase.NthStrikeAdded.CreditCardSave",
-        /*sample=*/(i + 1), /*count=*/1);
-  }
-
-  base::HistogramTester histogram_tester;
-
-  // Submit the form a fourth time. Since the card now has maximum strikes (3),
-  // the icon should be shown but the bubble should not.
-  ResetEventWaiterForSequence(
-      {DialogEvent::REQUESTED_UPLOAD_SAVE,
-       DialogEvent::RECEIVED_GET_UPLOAD_DETAILS_RESPONSE});
-  NavigateTo(kCreditCardUploadForm);
-  FillAndSubmitForm();
-  WaitForObservedEvent();
-  EXPECT_TRUE(GetSaveCardIconView()->visible());
-  EXPECT_FALSE(GetSaveCardBubbleViews());
-
-  // Click the icon to show the bubble.
-  ResetEventWaiterForSequence({DialogEvent::BUBBLE_SHOWN});
-  ClickOnView(GetSaveCardIconView());
-  WaitForObservedEvent();
-  EXPECT_TRUE(
-      FindViewInBubbleById(DialogViewId::MAIN_CONTENT_VIEW_UPLOAD)->visible());
-  EXPECT_TRUE(FindViewInBubbleById(DialogViewId::FOOTNOTE_VIEW)->visible());
-
-  ClickOnCancelButton();
-
-  // Ensure that no strike was added because the card already had max strikes.
-  histogram_tester.ExpectTotalCount(
-      "Autofill.StrikeDatabase.NthStrikeAdded.CreditCardSave", 0);
-
-  // Verify that the correct histogram entry was logged.
-  histogram_tester.ExpectBucketCount(
-      "Autofill.StrikeDatabase.CreditCardSaveNotOfferedDueToMaxStrikes",
-      AutofillMetrics::SaveTypeMetric::SERVER, 1);
-
-  // UMA should have recorded bubble rejection.
-  histogram_tester.ExpectUniqueSample(
-      "Autofill.SaveCreditCardPrompt.Upload.FirstShow",
-      AutofillMetrics::SAVE_CARD_ICON_SHOWN_WITHOUT_PROMPT, 1);
-}
-
 }  // namespace autofill
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
index 65fceee..d1eb098 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -82,7 +82,6 @@
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/ws/public/mojom/window_tree_constants.mojom.h"
 #include "ui/aura/client/aura_constants.h"
-#include "ui/aura/event_injector.h"
 #include "ui/aura/test/env_test_helper.h"
 #include "ui/aura/test/mus/change_completion_waiter.h"
 #include "ui/base/class_property.h"
@@ -267,15 +266,6 @@
   DISALLOW_COPY_AND_ASSIGN(ImmersiveModeTester);
 };
 
-// Update mouse location of aura::Env by injecting a mouse move event.
-// EventInjector is used so that the Window Service side code under mash sees
-// the updated mouse location as well.
-void UpdateMouseLocation(aura::Window* window, const gfx::Point& location) {
-  ui::MouseEvent event(ui::ET_MOUSE_MOVED, location, location,
-                       ui::EventTimeForNow(), ui::EF_NONE, 0);
-  aura::EventInjector().Inject(window->GetHost(), &event);
-}
-
 }  // namespace
 
 using views::Widget;
@@ -448,10 +438,6 @@
   void PreRunTestOnMainThread() override {
     InProcessBrowserTest::PreRunTestOnMainThread();
 
-    // Move mouse cursor beyond immersive UI to avoid affecting tests.
-    UpdateMouseLocation(browser()->window()->GetNativeWindow(),
-                        gfx::Point(0, 100));
-
     BrowserView::SetDisableRevealerDelayForTesting(true);
 
     ash::ImmersiveFullscreenControllerTestApi(
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc
index acda0da0..57b8e9b 100644
--- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc
+++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash_browsertest.cc
@@ -63,11 +63,11 @@
 
   GURL GetAppUrl() { return https_server_.GetURL("/simple.html"); }
 
-  void LaunchAppBrowser(bool await_url_load = true) {
+  void LaunchAppBrowser(bool wait = true) {
     ui_test_utils::UrlLoadObserver url_observer(
         GetAppUrl(), content::NotificationService::AllSources());
     browser_ = ExtensionBrowserTest::LaunchAppBrowser(app_);
-    if (await_url_load) {
+    if (wait) {
       // Wait for the URL to load so that the location bar end-state stabilizes.
       url_observer.Wait();
     }
@@ -77,7 +77,7 @@
     // which triggers an animation.
     ash::ImmersiveFullscreenControllerTestApi(
         static_cast<ImmersiveModeControllerAsh*>(controller_)->controller())
-        .SetupForTest();
+        .SetupForTest(/*wait_for_mouse_event=*/wait);
 
     browser_->window()->Show();
   }
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_no_sinks_view.cc b/chrome/browser/ui/views/media_router/cast_dialog_no_sinks_view.cc
index d5ea9023..bc864e6 100644
--- a/chrome/browser/ui/views/media_router/cast_dialog_no_sinks_view.cc
+++ b/chrome/browser/ui/views/media_router/cast_dialog_no_sinks_view.cc
@@ -25,6 +25,7 @@
 #include "ui/base/page_transition_types.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/paint_vector_icon.h"
+#include "ui/native_theme/native_theme.h"
 #include "ui/views/controls/button/image_button.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/throbber.h"
@@ -83,10 +84,11 @@
       l10n_util::GetStringUTF16(IDS_MEDIA_ROUTER_STATUS_NO_DEVICES_FOUND);
   auto help_icon = std::make_unique<views::ImageButton>(this);
   views::ImageButton* help_icon_ptr = help_icon.get();
-  help_icon->SetImage(
-      views::Button::STATE_NORMAL,
-      gfx::CreateVectorIcon(::vector_icons::kHelpOutlineIcon, kPrimaryIconSize,
-                            gfx::kChromeIconGrey));
+  const SkColor icon_color = help_icon->GetNativeTheme()->GetSystemColor(
+      ui::NativeTheme::kColorId_DefaultIconColor);
+  help_icon->SetImage(views::Button::STATE_NORMAL,
+                      gfx::CreateVectorIcon(::vector_icons::kHelpOutlineIcon,
+                                            kPrimaryIconSize, icon_color));
   help_icon->SetFocusForPlatform();
   help_icon->SetBorder(
       views::CreateEmptyBorder(gfx::Insets(kPrimaryIconBorderWidth)));
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_sink_button.cc b/chrome/browser/ui/views/media_router/cast_dialog_sink_button.cc
index 1bd79bdd..4c9e79c 100644
--- a/chrome/browser/ui/views/media_router/cast_dialog_sink_button.cc
+++ b/chrome/browser/ui/views/media_router/cast_dialog_sink_button.cc
@@ -140,9 +140,10 @@
         sink.state == UIMediaSinkState::CONNECTED);
   } else if (sink.issue) {
     auto icon_view = std::make_unique<views::ImageView>();
+    const SkColor icon_color = icon_view->GetNativeTheme()->GetSystemColor(
+        ui::NativeTheme::kColorId_DefaultIconColor);
     icon_view->SetImage(CreateVectorIcon(::vector_icons::kInfoOutlineIcon,
-                                         kPrimaryIconSize,
-                                         gfx::kChromeIconGrey));
+                                         kPrimaryIconSize, icon_color));
     icon_view->SetBorder(
         views::CreateEmptyBorder(gfx::Insets(kPrimaryIconBorderWidth)));
     return icon_view;
diff --git a/chrome/browser/ui/views/media_router/cast_toolbar_button.cc b/chrome/browser/ui/views/media_router/cast_toolbar_button.cc
index 518a2444..ecdd6d781 100644
--- a/chrome/browser/ui/views/media_router/cast_toolbar_button.cc
+++ b/chrome/browser/ui/views/media_router/cast_toolbar_button.cc
@@ -8,6 +8,7 @@
 #include "chrome/browser/media/router/media_router_dialog_controller.h"
 #include "chrome/browser/media/router/media_router_factory.h"
 #include "chrome/browser/media/router/media_router_metrics.h"
+#include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/layout_constants.h"
 #include "chrome/browser/ui/media_router/media_router_ui_service.h"
@@ -16,29 +17,13 @@
 #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"
 #include "ui/gfx/paint_vector_icon.h"
+#include "ui/native_theme/native_theme.h"
 
 namespace media_router {
 
-namespace {
-
-SkColor GetIconColor(const gfx::VectorIcon* icon_id) {
-  if (icon_id == &::vector_icons::kMediaRouterIdleIcon)
-    return gfx::kChromeIconGrey;
-  else if (icon_id == &::vector_icons::kMediaRouterActiveIcon)
-    return gfx::kGoogleBlue500;
-  else if (icon_id == &::vector_icons::kMediaRouterWarningIcon)
-    return gfx::kGoogleYellow700;
-  else if (icon_id == &::vector_icons::kMediaRouterErrorIcon)
-    return gfx::kGoogleRed700;
-
-  NOTREACHED();
-  return gfx::kPlaceholderColor;
-}
-
-}  // namespace
-
 // static
 std::unique_ptr<CastToolbarButton> CastToolbarButton::Create(Browser* browser) {
   std::unique_ptr<MediaRouterContextualMenu> context_menu =
@@ -179,4 +164,21 @@
   return MediaRouterUIService::Get(profile_)->action_controller();
 }
 
+SkColor CastToolbarButton::GetIconColor(const gfx::VectorIcon* icon_id) const {
+  if (icon_id == &::vector_icons::kMediaRouterIdleIcon) {
+    return GetThemeProvider()->GetColor(
+        ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON);
+  } else if (icon_id == &::vector_icons::kMediaRouterActiveIcon) {
+    return gfx::kGoogleBlue500;
+  } else if (icon_id == &::vector_icons::kMediaRouterWarningIcon) {
+    return GetNativeTheme()->GetSystemColor(
+        ui::NativeTheme::kColorId_AlertSeverityMedium);
+  } else if (icon_id == &::vector_icons::kMediaRouterErrorIcon) {
+    return GetNativeTheme()->GetSystemColor(
+        ui::NativeTheme::kColorId_AlertSeverityHigh);
+  }
+  NOTREACHED();
+  return gfx::kPlaceholderColor;
+}
+
 }  // namespace media_router
diff --git a/chrome/browser/ui/views/media_router/cast_toolbar_button.h b/chrome/browser/ui/views/media_router/cast_toolbar_button.h
index 3663686..f9d07cc 100644
--- a/chrome/browser/ui/views/media_router/cast_toolbar_button.h
+++ b/chrome/browser/ui/views/media_router/cast_toolbar_button.h
@@ -72,6 +72,8 @@
 
   MediaRouterActionController* GetActionController() const;
 
+  SkColor GetIconColor(const gfx::VectorIcon* icon_id) const;
+
   Browser* const browser_;
   Profile* const profile_;
 
diff --git a/chrome/browser/ui/views/media_router/cast_toolbar_button_unittest.cc b/chrome/browser/ui/views/media_router/cast_toolbar_button_unittest.cc
index 396181c..938ea8b 100644
--- a/chrome/browser/ui/views/media_router/cast_toolbar_button_unittest.cc
+++ b/chrome/browser/ui/views/media_router/cast_toolbar_button_unittest.cc
@@ -8,6 +8,8 @@
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/media/router/media_router_factory.h"
 #include "chrome/browser/media/router/test/mock_media_router.h"
+#include "chrome/browser/themes/theme_properties.h"
+#include "chrome/browser/themes/theme_service.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/media_router/media_router_ui_service.h"
 #include "chrome/browser/ui/media_router/media_router_ui_service_factory.h"
@@ -19,10 +21,12 @@
 #include "components/vector_icons/vector_icons.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/theme_provider.h"
 #include "ui/events/base_event_utils.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/image/image_unittest_util.h"
 #include "ui/gfx/paint_vector_icon.h"
+#include "ui/native_theme/native_theme.h"
 
 using testing::_;
 using testing::WithArg;
@@ -86,10 +90,35 @@
         browser_.get(), true, false, &context_menu_observer_);
     button_ = std::make_unique<CastToolbarButton>(browser_.get(), media_router,
                                                   std::move(context_menu));
+
+    // Button needs to be in a widget to be able to access ThemeProvider.
+    widget_ = std::make_unique<views::Widget>();
+    views::Widget::InitParams params =
+        CreateParams(views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+    params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+    widget_->Init(params);
+    widget_->SetContentsView(button_.get());
+
+    ui::NativeTheme* native_theme = button_->GetNativeTheme();
+    idle_icon_ = gfx::Image(
+        gfx::CreateVectorIcon(vector_icons::kMediaRouterIdleIcon,
+                              button_->GetThemeProvider()->GetColor(
+                                  ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON)));
+    warning_icon_ = gfx::Image(gfx::CreateVectorIcon(
+        vector_icons::kMediaRouterWarningIcon,
+        native_theme->GetSystemColor(
+            ui::NativeTheme::kColorId_AlertSeverityMedium)));
+    error_icon_ = gfx::Image(gfx::CreateVectorIcon(
+        vector_icons::kMediaRouterErrorIcon,
+        native_theme->GetSystemColor(
+            ui::NativeTheme::kColorId_AlertSeverityHigh)));
+    active_icon_ = gfx::Image(gfx::CreateVectorIcon(
+        vector_icons::kMediaRouterActiveIcon, gfx::kGoogleBlue500));
   }
 
   void TearDown() override {
     button_.reset();
+    widget_.reset();
     browser_.reset();
     window_.reset();
     profile_.reset();
@@ -103,22 +132,15 @@
 
   std::unique_ptr<BrowserWindow> window_;
   std::unique_ptr<Browser> browser_;
+  std::unique_ptr<views::Widget> widget_;
   std::unique_ptr<CastToolbarButton> button_;
   MockContextMenuObserver context_menu_observer_;
   std::unique_ptr<TestingProfile> profile_;
 
-  const gfx::Image idle_icon_ =
-      gfx::Image(gfx::CreateVectorIcon(vector_icons::kMediaRouterIdleIcon,
-                                       gfx::kChromeIconGrey));
-  const gfx::Image warning_icon_ =
-      gfx::Image(gfx::CreateVectorIcon(vector_icons::kMediaRouterWarningIcon,
-                                       gfx::kGoogleYellow700));
-  const gfx::Image error_icon_ =
-      gfx::Image(gfx::CreateVectorIcon(vector_icons::kMediaRouterErrorIcon,
-                                       gfx::kGoogleRed700));
-  const gfx::Image active_icon_ =
-      gfx::Image(gfx::CreateVectorIcon(vector_icons::kMediaRouterActiveIcon,
-                                       gfx::kGoogleBlue500));
+  gfx::Image idle_icon_;
+  gfx::Image warning_icon_;
+  gfx::Image error_icon_;
+  gfx::Image active_icon_;
 
   const std::vector<MediaRoute> local_display_route_list_ = {
       CreateLocalDisplayRoute()};
diff --git a/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc b/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc
index 145deb87..baf039e1 100644
--- a/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc
+++ b/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc
@@ -24,6 +24,7 @@
 #include "chrome/browser/ui/view_ids.h"
 #include "chrome/browser/ui/views/chrome_layout_provider.h"
 #include "chrome/browser/ui/views/profiles/incognito_window_count_view.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_ink_drop_util.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/grit/generated_resources.h"
 #include "services/identity/public/cpp/identity_manager.h"
@@ -133,10 +134,15 @@
       }
     }
   } else if (sync_state == SyncState::kError) {
-    color = gfx::kGoogleRed600;
+    color =
+        AdjustHighlightColorForContrast(gfx::kGoogleRed300, gfx::kGoogleRed600,
+                                        gfx::kGoogleRed050, gfx::kGoogleRed900);
     text = l10n_util::GetStringUTF16(IDS_AVATAR_BUTTON_SYNC_ERROR);
   } else if (sync_state == SyncState::kPaused) {
-    color = gfx::kGoogleBlue600;
+    color = AdjustHighlightColorForContrast(
+        gfx::kGoogleBlue300, gfx::kGoogleBlue600, gfx::kGoogleBlue050,
+        gfx::kGoogleBlue900);
+
     text = l10n_util::GetStringUTF16(IDS_AVATAR_BUTTON_SYNC_PAUSED);
   }
 
@@ -169,6 +175,10 @@
   UpdateText();
 }
 
+void AvatarToolbarButton::AddedToWidget() {
+  UpdateText();
+}
+
 void AvatarToolbarButton::OnAvatarErrorChanged() {
   UpdateIcon();
   UpdateText();
@@ -395,3 +405,33 @@
 
   SetLayoutInsetDelta(layout_insets);
 }
+
+SkColor AvatarToolbarButton::AdjustHighlightColorForContrast(
+    SkColor desired_dark_color,
+    SkColor desired_light_color,
+    SkColor dark_extreme,
+    SkColor light_extreme) const {
+  const ui::ThemeProvider* theme_provider = GetThemeProvider();
+  if (!theme_provider)
+    return desired_light_color;
+  SkColor toolbar_color =
+      GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR);
+  SkColor contrasting_color = color_utils::PickContrastingColor(
+      desired_dark_color, desired_light_color, toolbar_color);
+  SkColor limit =
+      contrasting_color == desired_dark_color ? dark_extreme : light_extreme;
+  // Setting highlight color will set the text to the highlight color, and the
+  // background to the same color with a low alpha. This means that our target
+  // contrast is between the text (the highlight color) and a blend of the
+  // highlight color and the toolbar color.
+  SkColor base_color = color_utils::AlphaBlend(contrasting_color, toolbar_color,
+                                               kToolbarButtonBackgroundAlpha);
+
+  // Add a fudge factor to the minimum contrast ratio since we'll actually be
+  // blending with the adjusted color.
+  SkAlpha blend_alpha = color_utils::GetBlendValueWithMinimumContrast(
+      contrasting_color, limit, base_color,
+      color_utils::kMinimumReadableContrastRatio * 1.05);
+
+  return color_utils::AlphaBlend(limit, contrasting_color, blend_alpha);
+}
diff --git a/chrome/browser/ui/views/profiles/avatar_toolbar_button.h b/chrome/browser/ui/views/profiles/avatar_toolbar_button.h
index 47742db..80bdd67 100644
--- a/chrome/browser/ui/views/profiles/avatar_toolbar_button.h
+++ b/chrome/browser/ui/views/profiles/avatar_toolbar_button.h
@@ -34,11 +34,14 @@
   void UpdateText();
 
  private:
+  FRIEND_TEST_ALL_PREFIXES(AvatarToolbarButtonTest,
+                           HighlightMeetsMinimumContrast);
   enum class SyncState { kNormal, kPaused, kError };
 
   // ToolbarButton:
   void NotifyClick(const ui::Event& event) override;
   void OnThemeChanged() override;
+  void AddedToWidget() override;
 
   // AvatarButtonErrorControllerDelegate:
   void OnAvatarErrorChanged() override;
@@ -78,6 +81,18 @@
 
   void SetInsets();
 
+  // Chooses from |desired_dark_color| and |desired_light_color| based on
+  // whether the toolbar background is dark or light.
+  //
+  // If the resulting color will achieve sufficient contrast,
+  // returns it. Otherwise, blends it towards |dark_extreme| if it's light, or
+  // |dark_extreme| if it's dark until minimum contrast is achieved, and returns
+  // the result.
+  SkColor AdjustHighlightColorForContrast(SkColor desired_dark_color,
+                                          SkColor desired_light_color,
+                                          SkColor dark_extreme,
+                                          SkColor light_extreme) const;
+
   Browser* const browser_;
   Profile* const profile_;
 
diff --git a/chrome/browser/ui/views/profiles/avatar_toolbar_button_unittest.cc b/chrome/browser/ui/views/profiles/avatar_toolbar_button_unittest.cc
new file mode 100644
index 0000000..dcc7c39
--- /dev/null
+++ b/chrome/browser/ui/views/profiles/avatar_toolbar_button_unittest.cc
@@ -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.
+
+#include "chrome/browser/ui/views/profiles/avatar_toolbar_button.h"
+
+#include "chrome/browser/themes/theme_properties.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/test_with_browser_view.h"
+#include "ui/base/theme_provider.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/views/widget/widget.h"
+
+class AvatarToolbarButtonTest : public TestWithBrowserView {};
+
+// CrOS only shows the avatar button for incognito/guest.
+#if !defined(OS_CHROMEOS)
+
+TEST_F(AvatarToolbarButtonTest, HighlightMeetsMinimumContrast) {
+  auto button = std::make_unique<AvatarToolbarButton>(browser());
+  button->set_owned_by_client();
+
+  browser_view()->GetWidget()->GetContentsView()->AddChildView(button.get());
+
+  SkColor toolbar_color =
+      button->GetThemeProvider()->GetColor(ThemeProperties::COLOR_TOOLBAR);
+  SkColor highlight_color = SkColorSetRGB(0xFE, 0x00, 0x00);
+
+  DCHECK_LT(color_utils::GetContrastRatio(highlight_color, toolbar_color),
+            color_utils::kMinimumReadableContrastRatio);
+
+  SkColor result = button->AdjustHighlightColorForContrast(
+      highlight_color, highlight_color, SK_ColorBLACK, SK_ColorWHITE);
+  EXPECT_GT(color_utils::GetContrastRatio(result, toolbar_color),
+            color_utils::kMinimumReadableContrastRatio);
+}
+
+#endif
diff --git a/chrome/browser/ui/views/sync/inline_login_ui_browsertest.cc b/chrome/browser/ui/views/sync/inline_login_ui_browsertest.cc
index 922d77c..635dd4f3 100644
--- a/chrome/browser/ui/views/sync/inline_login_ui_browsertest.cc
+++ b/chrome/browser/ui/views/sync/inline_login_ui_browsertest.cc
@@ -166,11 +166,8 @@
 
   MOCK_METHOD1(OnClientOAuthSuccess, void(const ClientOAuthResult& result));
   MOCK_METHOD1(OnClientOAuthFailure, void(const GoogleServiceAuthError& error));
-  MOCK_METHOD4(CreateSyncStarter,
-               void(Browser*,
-                    const GURL&,
-                    const std::string&,
-                    OneClickSigninSyncStarter::ProfileMode));
+  MOCK_METHOD3(CreateSyncStarter,
+               void(Browser*, const GURL&, const std::string&));
 
   GaiaAuthFetcher* GetGaiaAuthFetcher() { return GetGaiaAuthFetcherForTest(); }
 
@@ -219,11 +216,8 @@
       bool confirm_untrusted_signin,
       bool is_force_sign_in_with_usermanager);
 
-  MOCK_METHOD4(CreateSyncStarter,
-               void(Browser*,
-                    const GURL&,
-                    const std::string&,
-                    OneClickSigninSyncStarter::ProfileMode));
+  MOCK_METHOD3(CreateSyncStarter,
+               void(Browser*, const GURL&, const std::string&));
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockSyncStarterInlineSigninHelper);
@@ -567,9 +561,7 @@
           std::string(),
           false,  // confirm untrusted signin
           false);
-  EXPECT_CALL(*helper,
-              CreateSyncStarter(_, _, "refresh_token",
-                                OneClickSigninSyncStarter::CURRENT_PROFILE));
+  EXPECT_CALL(*helper, CreateSyncStarter(_, _, "refresh_token"));
 
   ProfileAttributesEntry* entry;
   ASSERT_TRUE(g_browser_process->profile_manager()
@@ -606,9 +598,7 @@
           std::string(),
           false,  // confirm untrusted signin
           false);
-  EXPECT_CALL(*helper,
-              CreateSyncStarter(_, _, "refresh_token",
-                                OneClickSigninSyncStarter::CURRENT_PROFILE));
+  EXPECT_CALL(*helper, CreateSyncStarter(_, _, "refresh_token"));
 
   SimulateOnClientOAuthSuccess(helper, "refresh_token");
   base::RunLoop().RunUntilIdle();
@@ -659,9 +649,7 @@
           std::string(),
           true,  // confirm untrusted signin
           false);
-  EXPECT_CALL(*helper,
-              CreateSyncStarter(_, _, "refresh_token",
-                                OneClickSigninSyncStarter::CURRENT_PROFILE));
+  EXPECT_CALL(*helper, CreateSyncStarter(_, _, "refresh_token"));
   SimulateOnClientOAuthSuccess(helper, "refresh_token");
   EXPECT_TRUE(OneClickSigninDialogView::IsShowing());
   views::DialogDelegateView* dialog_delegate =
@@ -693,9 +681,7 @@
 
   // Even though "choose what to sync" is false, the source of the URL is
   // settings, which means the user wants to CONFIGURE_SYNC_FIRST.
-  EXPECT_CALL(*helper,
-              CreateSyncStarter(_, _, "refresh_token",
-                                OneClickSigninSyncStarter::CURRENT_PROFILE));
+  EXPECT_CALL(*helper, CreateSyncStarter(_, _, "refresh_token"));
 
   SimulateOnClientOAuthSuccess(helper, "refresh_token");
   base::RunLoop().RunUntilIdle();
@@ -758,9 +744,7 @@
           handler, test_shared_loader_factory(), browser()->profile(), url,
           "foo@gmail.com", "gaiaid-12345", "password", "auth_code",
           std::string(), false, true);
-  EXPECT_CALL(*helper,
-              CreateSyncStarter(_, _, "refresh_token",
-                                OneClickSigninSyncStarter::CURRENT_PROFILE));
+  EXPECT_CALL(*helper, CreateSyncStarter(_, _, "refresh_token"));
 
   ProfileAttributesEntry* entry;
   ASSERT_TRUE(g_browser_process->profile_manager()
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
index 39386f28..f67cd02 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -68,7 +68,6 @@
 #include "chrome/browser/ui/webui/chromeos/bluetooth_dialog_localized_strings_provider.h"
 #include "chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.h"
 #include "chrome/browser/ui/webui/chromeos/smb_shares/smb_shares_localized_strings_provider.h"
-#include "chrome/browser/ui/webui/management_ui_handler.h"
 #include "chromeos/constants/chromeos_features.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/services/assistant/public/features.h"
@@ -418,33 +417,11 @@
     {"aboutUpdateWarningTitle", IDS_SETTINGS_ABOUT_PAGE_UPDATE_WARNING_TITLE},
     {"aboutUpdateWarningContinue",
      IDS_SETTINGS_ABOUT_PAGE_UPDATE_WARNING_CONTINUE_BUTTON},
-
-    // About page, Management subpage
-    {"managementTitle", IDS_MANAGEMENT_TITLE},
-    {"managementDeviceReporting", IDS_MANAGEMENT_DEVICE_REPORTING},
-    {"managementDeviceConfiguration", IDS_MANAGEMENT_DEVICE_CONFIGURATION},
-    {"managementExtensionReporting", IDS_MANAGEMENT_EXTENSION_REPORTING},
-    {"managementExtensionsInstalled", IDS_MANAGEMENT_EXTENSIONS_INSTALLED},
-    {"managementExtensionName", IDS_MANAGEMENT_EXTENSIONS_NAME},
-    {"managementExtensionPermissions", IDS_MANAGEMENT_EXTENSIONS_PERMISSIONS},
-    {kManagementLogUploadEnabled, IDS_MANAGEMENT_LOG_UPLOAD_ENABLED},
-    {kManagementReportActivityTimes,
-     IDS_MANAGEMENT_REPORT_DEVICE_ACTIVITY_TIMES},
-    {kManagementReportHardwareStatus,
-     IDS_MANAGEMENT_REPORT_DEVICE_HARDWARE_STATUS},
-    {kManagementReportNetworkInterfaces,
-     IDS_MANAGEMENT_REPORT_DEVICE_NETWORK_INTERFACES},
-    {kManagementReportUsers, IDS_MANAGEMENT_REPORT_DEVICE_USERS},
-    {"managementLocalTrustRoots", IDS_MANAGEMENT_LOCAL_TRUST_ROOTS},
-    {"managementTrustRootsConfigured", IDS_MANAGEMENT_TRUST_ROOTS_CONFIGURED}
 #endif  // defined(OS_CHROMEOS)
   };
   AddLocalizedStringsBulk(html_source, kLocalizedStrings,
                           base::size(kLocalizedStrings));
-#if defined(OS_CHROMEOS)
-  html_source->AddString("managementLearnMoreUrl",
-                         chrome::kManagedUiLearnMoreUrl);
-#endif
+
   html_source->AddString(
       "aboutUpgradeUpToDate",
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc
index 3f23bea8..4f6f9a76 100644
--- a/chrome/browser/ui/webui/settings/md_settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc
@@ -88,7 +88,6 @@
 #include "chrome/browser/chromeos/multidevice_setup/multidevice_setup_client_factory.h"
 #include "chrome/browser/signin/account_tracker_service_factory.h"
 #include "chrome/browser/ui/webui/chromeos/smb_shares/smb_handler.h"
-#include "chrome/browser/ui/webui/management_ui_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h"
 #include "chrome/browser/ui/webui/settings/chromeos/android_apps_handler.h"
@@ -193,7 +192,6 @@
   AddSettingsPageUIHandler(std::make_unique<StartupPagesHandler>(web_ui));
 
 #if defined(OS_CHROMEOS)
-  AddSettingsPageUIHandler(std::make_unique<ManagementUIHandler>());
   AddSettingsPageUIHandler(
       std::make_unique<chromeos::settings::AccessibilityHandler>(web_ui));
   AddSettingsPageUIHandler(
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 9927f26..bf019c91 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
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h"
 
+#include <utility>
+
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/logging.h"
@@ -138,7 +140,8 @@
     signin_metrics::Reason signin_reason,
     const std::string& account_id,
     SigninAbortedMode signin_aborted_mode,
-    std::unique_ptr<Delegate> delegate)
+    std::unique_ptr<Delegate> delegate,
+    base::OnceClosure callback)
     : delegate_(std::move(delegate)),
       profile_(profile),
       identity_manager_(IdentityManagerFactory::GetForProfile(profile)),
@@ -147,6 +150,7 @@
       signin_reason_(signin_reason),
       signin_aborted_mode_(signin_aborted_mode),
       account_info_(GetAccountInfo(identity_manager_, account_id)),
+      scoped_callback_runner_(std::move(callback)),
       shutdown_subscription_(
           DiceTurnSyncOnHelperShutdownNotifierFactory::GetInstance()
               ->Get(profile)
@@ -158,9 +162,6 @@
   // Should not start syncing if the profile is already authenticated
   DCHECK(!identity_manager_->HasPrimaryAccount());
 
-  // Force sign-in uses the modal sign-in flow.
-  DCHECK(!signin_util::IsForceSigninEnabled());
-
   if (account_info_.gaia.empty() || account_info_.email.empty()) {
     LOG(ERROR) << "Cannot turn Sync On for invalid account.";
     base::SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
@@ -210,7 +211,8 @@
           signin_reason,
           account_id,
           signin_aborted_mode,
-          std::make_unique<DiceTurnSyncOnHelperDelegateImpl>(browser)) {}
+          std::make_unique<DiceTurnSyncOnHelperDelegateImpl>(browser),
+          base::OnceClosure()) {}
 
 DiceTurnSyncOnHelper::~DiceTurnSyncOnHelper() {
 }
diff --git a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h
index df43aecd..84007e3 100644
--- a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h
+++ b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "base/callback_forward.h"
+#include "base/callback_helpers.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/profiles/profile.h"
@@ -92,15 +93,18 @@
 
   // Create a helper that turns sync on for an account that is already present
   // in the token service.
+  // |callback| is called at the end of the flow (i.e. after the user closes the
+  // sync confirmation dialog).
   DiceTurnSyncOnHelper(Profile* profile,
                        signin_metrics::AccessPoint signin_access_point,
                        signin_metrics::PromoAction signin_promo_action,
                        signin_metrics::Reason signin_reason,
                        const std::string& account_id,
                        SigninAbortedMode signin_aborted_mode,
-                       std::unique_ptr<Delegate> delegate);
+                       std::unique_ptr<Delegate> delegate,
+                       base::OnceClosure callback);
 
-  // Convenience constructor using the default delegate.
+  // Convenience constructor using the default delegate and empty callback.
   DiceTurnSyncOnHelper(Profile* profile,
                        Browser* browser,
                        signin_metrics::AccessPoint signin_access_point,
@@ -211,6 +215,9 @@
   std::string dm_token_;
   std::string client_id_;
 
+  // Called when this object is deleted.
+  base::ScopedClosureRunner scoped_callback_runner_;
+
   std::unique_ptr<SyncStartupTracker> sync_startup_tracker_;
   std::unique_ptr<KeyedServiceShutdownNotifier::Subscription>
       shutdown_subscription_;
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 8fff227..489640a 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
@@ -255,7 +255,8 @@
       DiceTurnSyncOnHelper::SigninAbortedMode mode) {
     return new DiceTurnSyncOnHelper(
         profile(), kAccessPoint, kSigninPromoAction, kSigninReason, account_id_,
-        mode, std::make_unique<TestDiceTurnSyncOnHelperDelegate>(this));
+        mode, std::make_unique<TestDiceTurnSyncOnHelperDelegate>(this),
+        base::DoNothing());
   }
 
   void UseEnterpriseAccount() {
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
index e1592060..97497aa 100644
--- a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/bind.h"
@@ -36,6 +37,7 @@
 #include "chrome/browser/signin/local_auth.h"
 #include "chrome/browser/signin/signin_promo.h"
 #include "chrome/browser/signin/signin_util.h"
+#include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_window.h"
@@ -44,6 +46,8 @@
 #include "chrome/browser/ui/tab_modal_confirm_dialog_delegate.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/user_manager.h"
+#include "chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h"
+#include "chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_delegate_impl.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
 #include "chrome/browser/ui/webui/signin/signin_utils.h"
@@ -81,6 +85,30 @@
 
 namespace {
 
+// Specific implementation of DiceTurnSyncOnHelper::Delegate for forced signin
+// flows. Some confirmation prompts are skipped.
+class ForcedSigninDiceTurnSyncOnHelperDelegate
+    : public DiceTurnSyncOnHelperDelegateImpl {
+ public:
+  explicit ForcedSigninDiceTurnSyncOnHelperDelegate(Browser* browser)
+      : DiceTurnSyncOnHelperDelegateImpl(browser) {}
+
+ private:
+  void ShowMergeSyncDataConfirmation(
+      const std::string& previous_email,
+      const std::string& new_email,
+      DiceTurnSyncOnHelper::SigninChoiceCallback callback) override {
+    NOTREACHED();
+  }
+
+  void ShowEnterpriseAccountConfirmation(
+      const std::string& email,
+      DiceTurnSyncOnHelper::SigninChoiceCallback callback) override {
+    std::move(callback).Run(
+        DiceTurnSyncOnHelper ::SigninChoice::SIGNIN_CHOICE_CONTINUE);
+  }
+};
+
 #if defined(OS_WIN)
 
 // Returns a list of valid signin domains that were passed in
@@ -215,14 +243,15 @@
   return false;
 }
 
-// Callback for OneClickSigninSyncStarter.
+// Callback for DiceTurnOnSyncHelper.
 void OnSyncSetupComplete(Profile* profile,
                          base::WeakPtr<InlineLoginHandlerImpl> handler,
                          const std::string& username,
-                         const std::string& password,
-                         OneClickSigninSyncStarter::SyncSetupResult result) {
-  if (result == OneClickSigninSyncStarter::SYNC_SETUP_SUCCESS &&
-      !password.empty()) {
+                         const std::string& password) {
+  identity::IdentityManager* identity_manager =
+      IdentityManagerFactory::GetForProfile(profile);
+  bool has_primary_account = identity_manager->HasPrimaryAccount();
+  if (has_primary_account && !password.empty()) {
     scoped_refptr<password_manager::PasswordStore> password_store =
         PasswordStoreFactory::GetForProfile(profile,
                                             ServiceAccessType::EXPLICIT_ACCESS);
@@ -235,8 +264,15 @@
       LocalAuth::SetLocalAuthCredentials(profile, password);
   }
 
-  if (handler)
-    handler->SyncStarterCallback(result);
+  if (handler) {
+    handler->SyncStarterCallback(has_primary_account);
+  } else if (signin_util::IsForceSigninEnabled() && !has_primary_account) {
+    BrowserList::CloseAllBrowsersWithProfile(
+        profile, base::Bind(&LockProfileAndShowUserManager),
+        // Cannot be called because skip_beforeunload is true.
+        BrowserList::CloseCallback(),
+        /*skip_beforeunload=*/true);
+  }
 }
 
 }  // namespace
@@ -384,8 +420,6 @@
     }
     LogSigninReason(reason);
   } else {
-    if (HandleCrossAccountError(result.refresh_token))
-      return;
     if (confirm_untrusted_signin_) {
       // Display a confirmation dialog to the user.
       base::RecordAction(
@@ -398,8 +432,7 @@
                          base::Unretained(this), result.refresh_token));
       return;
     }
-    CreateSyncStarter(browser, current_url_, result.refresh_token,
-                      OneClickSigninSyncStarter::CURRENT_PROFILE);
+    CreateSyncStarter(browser, current_url_, result.refresh_token);
     base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
   }
 }
@@ -409,15 +442,13 @@
     bool confirmed) {
   base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
   if (confirmed) {
-    CreateSyncStarter(nullptr, current_url_, refresh_token,
-                      OneClickSigninSyncStarter::CURRENT_PROFILE);
+    CreateSyncStarter(nullptr, current_url_, refresh_token);
     return;
   }
 
   base::RecordAction(base::UserMetricsAction("Signin_Undo_Signin"));
   if (handler_) {
-    handler_->SyncStarterCallback(
-        OneClickSigninSyncStarter::SYNC_SETUP_FAILURE);
+    handler_->SyncStarterCallback(false);
   } else if (signin_util::IsForceSigninEnabled()) {
     BrowserList::CloseAllBrowsersWithProfile(
         profile_, base::Bind(&LockProfileAndShowUserManager),
@@ -427,76 +458,41 @@
   }
 }
 
-void InlineSigninHelper::CreateSyncStarter(
-    Browser* browser,
-    const GURL& current_url,
-    const std::string& refresh_token,
-    OneClickSigninSyncStarter::ProfileMode profile_mode) {
-  // OneClickSigninSyncStarter will delete itself once the job is done.
-  new OneClickSigninSyncStarter(
-      profile_, browser, gaia_id_, email_, password_, refresh_token,
-      signin::GetAccessPointForEmbeddedPromoURL(current_url),
-      signin::GetSigninReasonForEmbeddedPromoURL(current_url), profile_mode,
-      base::Bind(&OnSyncSetupComplete, profile_, handler_, email_, password_));
-}
-
-bool InlineSigninHelper::HandleCrossAccountError(
-    const std::string& refresh_token) {
-  // With force sign in enabled, cross account
-  // sign in will be rejected in the early stage so there is no need to show the
-  // warning page here.
-  if (signin_util::IsForceSigninEnabled())
-    return false;
-
-  std::string last_email =
-      profile_->GetPrefs()->GetString(prefs::kGoogleServicesLastUsername);
-
-  // TODO(skym): Warn for high risk upgrade scenario, crbug.com/572754.
-  if (!IsCrossAccountError(profile_, email_, gaia_id_))
-    return false;
-
-  Browser* browser = chrome::FindLastActiveWithProfile(profile_);
-  content::WebContents* web_contents =
-      browser->tab_strip_model()->GetActiveWebContents();
-
-  SigninEmailConfirmationDialog::AskForConfirmation(
-      web_contents, profile_, last_email, email_,
-      base::Bind(&InlineSigninHelper::ConfirmEmailAction,
-                 base::Unretained(this), web_contents, refresh_token));
-  return true;
-}
-
-void InlineSigninHelper::ConfirmEmailAction(
-    content::WebContents* web_contents,
-    const std::string& refresh_token,
-    SigninEmailConfirmationDialog::Action action) {
-  // There is no need to show the untrusted signin prompt, because the
-  // SigninEmailConfirmationDialog already displays the account that is being
-  // signed in.
-  Browser* browser = chrome::FindLastActiveWithProfile(profile_);
-  switch (action) {
-    case SigninEmailConfirmationDialog::CREATE_NEW_USER:
-      base::RecordAction(
-          base::UserMetricsAction("Signin_ImportDataPrompt_DontImport"));
-      CreateSyncStarter(browser, current_url_, refresh_token,
-                        OneClickSigninSyncStarter::NEW_PROFILE);
-      break;
-    case SigninEmailConfirmationDialog::START_SYNC:
-      base::RecordAction(
-          base::UserMetricsAction("Signin_ImportDataPrompt_ImportData"));
-      CreateSyncStarter(browser, current_url_, refresh_token,
-                        OneClickSigninSyncStarter::CURRENT_PROFILE);
-      break;
-    case SigninEmailConfirmationDialog::CLOSE:
-      base::RecordAction(
-          base::UserMetricsAction("Signin_ImportDataPrompt_Cancel"));
-      if (handler_) {
-        handler_->SyncStarterCallback(
-            OneClickSigninSyncStarter::SYNC_SETUP_FAILURE);
-      }
-      break;
+void InlineSigninHelper::CreateSyncStarter(Browser* browser,
+                                           const GURL& current_url,
+                                           const std::string& refresh_token) {
+  identity::IdentityManager* identity_manager =
+      IdentityManagerFactory::GetForProfile(profile_);
+  if (identity_manager->HasPrimaryAccount()) {
+    // Already signed in, nothing to do.
+    if (handler_)
+      handler_->SyncStarterCallback(true);
+    return;
   }
-  base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
+
+  if (!browser)
+    browser = chrome::OpenEmptyWindow(profile_);
+
+  std::string account_id =
+      identity_manager->GetAccountsMutator()->AddOrUpdateAccount(
+          gaia_id_, email_, refresh_token,
+          /*is_under_advanced_protection=*/false,
+          signin_metrics::SourceForRefreshTokenOperation::
+              kInlineLoginHandler_Signin);
+
+  std::unique_ptr<DiceTurnSyncOnHelper::Delegate> delegate =
+      signin_util::IsForceSigninEnabled()
+          ? std::make_unique<ForcedSigninDiceTurnSyncOnHelperDelegate>(browser)
+          : std::make_unique<DiceTurnSyncOnHelperDelegateImpl>(browser);
+
+  new DiceTurnSyncOnHelper(
+      profile_, signin::GetAccessPointForEmbeddedPromoURL(current_url),
+      signin_metrics::PromoAction::PROMO_ACTION_NO_SIGNIN_PROMO,
+      signin::GetSigninReasonForEmbeddedPromoURL(current_url), account_id,
+      DiceTurnSyncOnHelper::SigninAbortedMode::REMOVE_ACCOUNT,
+      std::move(delegate),
+      base::BindOnce(&OnSyncSetupComplete, profile_, handler_, email_,
+                     password_));
 }
 
 void InlineSigninHelper::OnClientOAuthFailure(
@@ -634,7 +630,7 @@
 
   if (skip_for_now) {
     signin::SetUserSkippedPromo(Profile::FromWebUI(web_ui()));
-    SyncStarterCallback(OneClickSigninSyncStarter::SYNC_SETUP_FAILURE);
+    SyncStarterCallback(false);
     return;
   }
 
@@ -886,7 +882,7 @@
     SendLSTFetchResultsMessage(error_value);
     return;
   }
-  SyncStarterCallback(OneClickSigninSyncStarter::SYNC_SETUP_FAILURE);
+  SyncStarterCallback(false);
   Browser* browser = GetDesktopBrowser();
   Profile* profile = Profile::FromWebUI(web_ui());
 
@@ -914,8 +910,7 @@
   return browser;
 }
 
-void InlineLoginHandlerImpl::SyncStarterCallback(
-    OneClickSigninSyncStarter::SyncSetupResult result) {
+void InlineLoginHandlerImpl::SyncStarterCallback(bool sync_setup_success) {
   content::WebContents* contents = web_ui()->GetWebContents();
 
   if (contents->GetController().GetPendingEntry()) {
@@ -930,7 +925,7 @@
       signin::GetAccessPointForEmbeddedPromoURL(current_url);
   bool auto_close = signin::IsAutoCloseEnabledInEmbeddedURL(current_url);
 
-  if (result == OneClickSigninSyncStarter::SYNC_SETUP_FAILURE) {
+  if (!sync_setup_success) {
     RedirectToNtpOrAppsPage(contents, access_point);
   } else if (auto_close) {
     bool show_account_management = ShouldShowAccountManagement(
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_impl.h b/chrome/browser/ui/webui/signin/inline_login_handler_impl.h
index 4938786..047a9e3b 100644
--- a/chrome/browser/ui/webui/signin/inline_login_handler_impl.h
+++ b/chrome/browser/ui/webui/signin/inline_login_handler_impl.h
@@ -13,16 +13,23 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "chrome/browser/ui/sync/one_click_signin_sync_starter.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/signin/inline_login_handler.h"
 #include "chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "google_apis/gaia/gaia_auth_consumer.h"
+#include "google_apis/gaia/gaia_auth_fetcher.h"
+
+namespace content {
+class StoragePartition;
+}
 
 namespace network {
 class SharedURLLoaderFactory;
 }
 
+class Browser;
+
 // Implementation for the inline login WebUI handler on desktop Chrome. Once
 // CrOS migrates to the same webview approach as desktop Chrome, much of the
 // code in this class should move to its base class |InlineLoginHandler|.
@@ -40,7 +47,7 @@
   }
 
   Browser* GetDesktopBrowser();
-  void SyncStarterCallback(OneClickSigninSyncStarter::SyncSetupResult result);
+  void SyncStarterCallback(bool sync_setup_success);
   // Closes the current tab and shows the account management view of the avatar
   // bubble if |show_account_management| is true.
   void CloseTab(bool show_account_management);
@@ -134,7 +141,7 @@
 // sync after InlineLoginHandlerImpl has acquired the auth tokens from GAIA.
 // This is a separate class from InlineLoginHandlerImpl because the full signin
 // process is asynchronous and can outlive the signin UI.
-// InlineLoginHandlerImpl is destryed once the UI is closed.
+// InlineLoginHandlerImpl is destroyed once the UI is closed.
 class InlineSigninHelper : public GaiaAuthConsumer {
  public:
   InlineSigninHelper(
@@ -156,18 +163,6 @@
   GaiaAuthFetcher* GetGaiaAuthFetcherForTest() { return &gaia_auth_fetcher_; }
 
  private:
-  // Handles cross account sign in error. If the supplied |email| does not match
-  // the last signed in email of the current profile, then Chrome will show a
-  // confirmation dialog before starting sync. It returns true if there is a
-  // cross account error, and false otherwise.
-  bool HandleCrossAccountError(const std::string& refresh_token);
-
-  // Callback used with ConfirmEmailDialogDelegate.
-  void ConfirmEmailAction(
-      content::WebContents* web_contents,
-      const std::string& refresh_token,
-      SigninEmailConfirmationDialog::Action action);
-
   // Overridden from GaiaAuthConsumer.
   void OnClientOAuthSuccess(const ClientOAuthResult& result) override;
   void OnClientOAuthFailure(const GoogleServiceAuthError& error)
@@ -184,11 +179,9 @@
 
   // Creates the sync starter.  Virtual for tests. Call to exchange oauth code
   // for tokens.
-  virtual void CreateSyncStarter(
-      Browser* browser,
-      const GURL& current_url,
-      const std::string& refresh_token,
-      OneClickSigninSyncStarter::ProfileMode profile_mode);
+  virtual void CreateSyncStarter(Browser* browser,
+                                 const GURL& current_url,
+                                 const std::string& refresh_token);
 
   GaiaAuthFetcher gaia_auth_fetcher_;
   base::WeakPtr<InlineLoginHandlerImpl> handler_;
diff --git a/chrome/browser/ui/webui/version_handler_win.cc b/chrome/browser/ui/webui/version_handler_win.cc
index 9e1dd10..777c4ce 100644
--- a/chrome/browser/ui/webui/version_handler_win.cc
+++ b/chrome/browser/ui/webui/version_handler_win.cc
@@ -12,9 +12,8 @@
 
 namespace {
 
-// rerurn marketing version of Windows OS
-// may return an empty string if values returned by base::win::OSinfo
-// are not defined below
+// Return the marketing version of Windows OS, this may return an empty string
+// if values returned by base::win::OSinfo are not defined below.
 std::string FullWindowsVersion() {
   std::string version;
   base::win::OSInfo* gi = base::win::OSInfo::GetInstance();
@@ -92,3 +91,8 @@
   base::Value arg(version);
   CallJavascriptFunction("returnOsVersion", arg);
 }
+
+// static
+std::string VersionHandlerWindows::GetFullWindowsVersionForTesting() {
+  return FullWindowsVersion();
+}
diff --git a/chrome/browser/ui/webui/version_handler_win.h b/chrome/browser/ui/webui/version_handler_win.h
index 52536db..83a41ec 100644
--- a/chrome/browser/ui/webui/version_handler_win.h
+++ b/chrome/browser/ui/webui/version_handler_win.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_UI_WEBUI_VERSION_HANDLER_WIN_H_
 #define CHROME_BROWSER_UI_WEBUI_VERSION_HANDLER_WIN_H_
 
+#include <string>
+
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ui/webui/version_handler.h"
@@ -21,6 +23,9 @@
   // Callbacks from windows::VersionLoader.
   void OnVersion(const std::string& version);
 
+  // Expose the |FullWindowsVersion| defined in the .cc file for testing.
+  static std::string GetFullWindowsVersionForTesting();
+
  private:
   base::WeakPtrFactory<VersionHandlerWindows> weak_factory_;
 
diff --git a/chrome/browser/ui/webui/version_handler_win_unittest.cc b/chrome/browser/ui/webui/version_handler_win_unittest.cc
index 074c79fa..b054b57 100644
--- a/chrome/browser/ui/webui/version_handler_win_unittest.cc
+++ b/chrome/browser/ui/webui/version_handler_win_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/test/scoped_os_info_override_win.h"
 #include "base/test/test_reg_util_win.h"
 #include "base/win/registry.h"
-#include "chrome/browser/ui/webui/version_handler_win.cc"
+#include "chrome/browser/ui/webui/version_handler_win.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 class WebUIWindowsVersion : public testing::Test {
@@ -37,33 +37,38 @@
   // override base::win::OSInfo
   base::test::ScopedOSInfoOverride os(
       base::test::ScopedOSInfoOverride::Type::kWin10Pro);
-  EXPECT_EQ(FullWindowsVersion(), "10 OS Build 15063.555");
+  EXPECT_EQ(VersionHandlerWindows::GetFullWindowsVersionForTesting(),
+            "10 OS Build 15063.555");
 }
 
 TEST_F(WebUIWindowsVersion, WinServer2016) {
   ubr_key.WriteValue(L"UBR", 1555);
   base::test::ScopedOSInfoOverride os(
       base::test::ScopedOSInfoOverride::Type::kWinServer2016);
-  EXPECT_EQ(FullWindowsVersion(), "Server OS Build 17134.1555");
+  EXPECT_EQ(VersionHandlerWindows::GetFullWindowsVersionForTesting(),
+            "Server OS Build 17134.1555");
 }
 
 TEST_F(WebUIWindowsVersion, Win81Pro) {
   ubr_key.WriteValue(L"UBR", 0UL);
   base::test::ScopedOSInfoOverride os(
       base::test::ScopedOSInfoOverride::Type::kWin81Pro);
-  EXPECT_EQ(FullWindowsVersion(), "8.1 Build 9600");
+  EXPECT_EQ(VersionHandlerWindows::GetFullWindowsVersionForTesting(),
+            "8.1 Build 9600");
 }
 
 TEST_F(WebUIWindowsVersion, WinServer2012R2) {
   ubr_key.WriteValue(L"UBR", 0UL);
   base::test::ScopedOSInfoOverride os(
       base::test::ScopedOSInfoOverride::Type::kWinServer2012R2);
-  EXPECT_EQ(FullWindowsVersion(), "Server 2012 R2 Build 9600");
+  EXPECT_EQ(VersionHandlerWindows::GetFullWindowsVersionForTesting(),
+            "Server 2012 R2 Build 9600");
 }
 
 TEST_F(WebUIWindowsVersion, Win7ProSP1) {
   ubr_key.WriteValue(L"UBR", 0UL);
   base::test::ScopedOSInfoOverride os(
       base::test::ScopedOSInfoOverride::Type::kWin7ProSP1);
-  EXPECT_EQ(FullWindowsVersion(), "7 Service Pack 1 Build 7601");
+  EXPECT_EQ(VersionHandlerWindows::GetFullWindowsVersionForTesting(),
+            "7 Service Pack 1 Build 7601");
 }
diff --git a/chrome/browser/vr/elements/content_element_unittest.cc b/chrome/browser/vr/elements/content_element_unittest.cc
index 94d0429..daf52443 100644
--- a/chrome/browser/vr/elements/content_element_unittest.cc
+++ b/chrome/browser/vr/elements/content_element_unittest.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "chrome/browser/vr/elements/content_element.h"
 #include "chrome/browser/vr/elements/keyboard.h"
diff --git a/chrome/browser/vr/model/text_input_info.cc b/chrome/browser/vr/model/text_input_info.cc
index b4c95dd..61972a7 100644
--- a/chrome/browser/vr/model/text_input_info.cc
+++ b/chrome/browser/vr/model/text_input_info.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 
+#include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 
 namespace vr {
@@ -182,7 +183,7 @@
   int to_commit =
       current.CommittedTextBeforeCursor().size() - common_prefix_length;
   if (to_commit > 0 || had_selection) {
-    DCHECK(to_delete == 0);
+    DCHECK_EQ(0, to_delete);
     edits.push_back(TextEditAction(TextEditActionType::COMMIT_TEXT,
                                    current.CommittedTextBeforeCursor().substr(
                                        common_prefix_length, to_commit),
diff --git a/chrome/browser/vr/model/text_input_info.h b/chrome/browser/vr/model/text_input_info.h
index 868863f..ae377d9a 100644
--- a/chrome/browser/vr/model/text_input_info.h
+++ b/chrome/browser/vr/model/text_input_info.h
@@ -5,11 +5,9 @@
 #ifndef CHROME_BROWSER_VR_MODEL_TEXT_INPUT_INFO_H_
 #define CHROME_BROWSER_VR_MODEL_TEXT_INPUT_INFO_H_
 
-#include <vector>
+#include <string>
 
 #include "base/strings/string16.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/vr/text_edit_action.h"
 #include "chrome/browser/vr/vr_base_export.h"
 
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc
index e0f7d5e..d6a1ad2 100644
--- a/chrome/common/webui_url_constants.cc
+++ b/chrome/common/webui_url_constants.cc
@@ -307,7 +307,6 @@
 // 'multidevice/features' is a child of the 'multidevice' route
 const char kConnectedDevicesSubPage[] = "multidevice/features";
 const char kLockScreenSubPage[] = "lockScreen";
-const char kManagementSubPage[] = "help/management";
 const char kNetworkDetailSubPage[] = "networkDetail";
 const char kPowerSubPage[] = "power";
 const char kSmbSharesPageAddDialog[] = "smbShares?showAddShare=true";
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h
index 287fbed..ad60b90e 100644
--- a/chrome/common/webui_url_constants.h
+++ b/chrome/common/webui_url_constants.h
@@ -299,7 +299,6 @@
 extern const char kInternetSubPage[];
 extern const char kConnectedDevicesSubPage[];
 extern const char kLockScreenSubPage[];
-extern const char kManagementSubPage[];
 extern const char kNetworkDetailSubPage[];
 extern const char kPowerSubPage[];
 extern const char kSmbSharesPage[];
diff --git a/chrome/installer/mini_installer/chrome.release b/chrome/installer/mini_installer/chrome.release
index bdf0219..a29cd7d 100644
--- a/chrome/installer/mini_installer/chrome.release
+++ b/chrome/installer/mini_installer/chrome.release
@@ -18,6 +18,7 @@
 #
 # Chrome version dir entries, sorted alphabetically.
 #
+api-ms-win-*.dll: %(VersionDir)s\
 chrome.dll: %(VersionDir)s\
 chrome_100_percent.pak: %(VersionDir)s\
 chrome_child.dll: %(VersionDir)s\
@@ -36,6 +37,7 @@
 natives_blob.bin: %(VersionDir)s\
 notification_helper.exe: %(VersionDir)s\
 resources.pak: %(VersionDir)s\
+ucrtbase*.dll: %(VersionDir)s\
 v8_context_snapshot.bin: %(VersionDir)s\
 #
 # Sub directories living in the version dir
diff --git a/chrome/service/service_utility_process_host.cc b/chrome/service/service_utility_process_host.cc
index fba3089..25fbc02 100644
--- a/chrome/service/service_utility_process_host.cc
+++ b/chrome/service/service_utility_process_host.cc
@@ -55,11 +55,11 @@
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/constants.h"
 #include "services/service_manager/public/mojom/service.mojom.h"
-#include "services/service_manager/runner/host/service_process_launcher.h"
-#include "services/service_manager/runner/host/service_process_launcher_factory.h"
 #include "services/service_manager/sandbox/sandbox_type.h"
 #include "services/service_manager/sandbox/switches.h"
 #include "services/service_manager/service_manager.h"
+#include "services/service_manager/service_process_launcher.h"
+#include "services/service_manager/service_process_launcher_factory.h"
 #include "ui/base/ui_base_switches.h"
 
 namespace {
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index e2a0d8d0..5a5ce1a 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -3678,11 +3678,6 @@
     }
   }
 
-  if (enable_one_click_signin) {
-    sources +=
-        [ "../browser/ui/sync/one_click_signin_sync_starter_unittest.cc" ]
-  }
-
   if (enable_extensions) {
     sources += [
       "../../apps/saved_files_service_unittest.cc",
@@ -4497,6 +4492,7 @@
       "../browser/ui/views/payments/payment_request_item_list_unittest.cc",
       "../browser/ui/views/payments/validating_textfield_unittest.cc",
       "../browser/ui/views/payments/view_stack_unittest.cc",
+      "../browser/ui/views/profiles/avatar_toolbar_button_unittest.cc",
       "../browser/ui/views/relaunch_notification/relaunch_notification_controller_unittest.cc",
       "../browser/ui/views/relaunch_notification/relaunch_required_timer_internal_unittest.cc",
       "../browser/ui/views/relaunch_notification/wall_clock_timer_unittest.cc",
diff --git a/chrome/test/chromedriver/commands_unittest.cc b/chrome/test/chromedriver/commands_unittest.cc
index 7b730e1..68099d7 100644
--- a/chrome/test/chromedriver/commands_unittest.cc
+++ b/chrome/test/chromedriver/commands_unittest.cc
@@ -456,14 +456,14 @@
   session.implicit_wait = base::TimeDelta::FromSeconds(1);
   session.SwitchToSubFrame("frame_id1", std::string());
   base::DictionaryValue params;
-  params.SetString("using", "id");
-  params.SetString("value", "a");
+  params.SetString("using", "css selector");
+  params.SetString("value", "#a");
   std::unique_ptr<base::Value> result;
   ASSERT_EQ(kOk,
             ExecuteFindElement(1, &session, &web_view, params, &result,
                                nullptr).code());
   base::DictionaryValue param;
-  param.SetString("id", "a");
+  param.SetString("css selector", "#a");
   base::ListValue expected_args;
   expected_args.Append(param.CreateDeepCopy());
   web_view.Verify("frame_id1", &expected_args, result.get());
@@ -473,8 +473,8 @@
   FindElementWebView web_view(true, kElementNotExistsQueryOnce);
   Session session("id");
   base::DictionaryValue params;
-  params.SetString("using", "id");
-  params.SetString("value", "a");
+  params.SetString("using", "css selector");
+  params.SetString("value", "#a");
   std::unique_ptr<base::Value> result;
   ASSERT_EQ(kNoSuchElement,
             ExecuteFindElement(1, &session, &web_view, params, &result,
@@ -487,14 +487,14 @@
   session.implicit_wait = base::TimeDelta::FromSeconds(1);
   session.SwitchToSubFrame("frame_id2", std::string());
   base::DictionaryValue params;
-  params.SetString("using", "name");
-  params.SetString("value", "b");
+  params.SetString("using", "css selector");
+  params.SetString("value", "*[name='b']");
   std::unique_ptr<base::Value> result;
   ASSERT_EQ(kOk,
             ExecuteFindElements(1, &session, &web_view, params, &result,
                                 nullptr).code());
   base::DictionaryValue param;
-  param.SetString("name", "b");
+  param.SetString("css selector", "*[name='b']");
   base::ListValue expected_args;
   expected_args.Append(param.CreateDeepCopy());
   web_view.Verify("frame_id2", &expected_args, result.get());
@@ -504,8 +504,8 @@
   Session session("id");
   FindElementWebView web_view(false, kElementNotExistsQueryOnce);
   base::DictionaryValue params;
-  params.SetString("using", "id");
-  params.SetString("value", "a");
+  params.SetString("using", "css selector");
+  params.SetString("value", "#a");
   std::unique_ptr<base::Value> result;
   ASSERT_EQ(kOk,
             ExecuteFindElements(1, &session, &web_view, params, &result,
@@ -521,7 +521,7 @@
   session.implicit_wait = base::TimeDelta::FromSeconds(1);
   session.SwitchToSubFrame("frame_id3", std::string());
   base::DictionaryValue params;
-  params.SetString("using", "tag name");
+  params.SetString("using", "css selector");
   params.SetString("value", "div");
   std::string element_id = "1";
   std::unique_ptr<base::Value> result;
@@ -530,7 +530,7 @@
       ExecuteFindChildElement(
           1, &session, &web_view, element_id, params, &result).code());
   base::DictionaryValue locator_param;
-  locator_param.SetString("tag name", "div");
+  locator_param.SetString("css selector", "div");
   base::DictionaryValue root_element_param;
   root_element_param.SetString("ELEMENT", element_id);
   base::ListValue expected_args;
@@ -543,8 +543,8 @@
   Session session("id");
   FindElementWebView web_view(true, kElementNotExistsQueryOnce);
   base::DictionaryValue params;
-  params.SetString("using", "id");
-  params.SetString("value", "a");
+  params.SetString("using", "css selector");
+  params.SetString("value", "#a");
   std::string element_id = "1";
   std::unique_ptr<base::Value> result;
   ASSERT_EQ(
@@ -559,8 +559,8 @@
   session.implicit_wait = base::TimeDelta::FromSeconds(1);
   session.SwitchToSubFrame("frame_id4", std::string());
   base::DictionaryValue params;
-  params.SetString("using", "class name");
-  params.SetString("value", "c");
+  params.SetString("using", "css selector");
+  params.SetString("value", ".c");
   std::string element_id = "1";
   std::unique_ptr<base::Value> result;
   ASSERT_EQ(
@@ -568,7 +568,7 @@
       ExecuteFindChildElements(
           1, &session, &web_view, element_id, params, &result).code());
   base::DictionaryValue locator_param;
-  locator_param.SetString("class name", "c");
+  locator_param.SetString("css selector", ".c");
   base::DictionaryValue root_element_param;
   root_element_param.SetString("ELEMENT", element_id);
   base::ListValue expected_args;
@@ -581,8 +581,8 @@
   Session session("id");
   FindElementWebView web_view(false, kElementNotExistsQueryOnce);
   base::DictionaryValue params;
-  params.SetString("using", "id");
-  params.SetString("value", "a");
+  params.SetString("using", "css selector");
+  params.SetString("value", "#a");
   std::string element_id = "1";
   std::unique_ptr<base::Value> result;
   ASSERT_EQ(
@@ -599,8 +599,8 @@
   FindElementWebView web_view(true, kElementExistsTimeout);
   session.implicit_wait = base::TimeDelta::FromMilliseconds(2);
   base::DictionaryValue params;
-  params.SetString("using", "id");
-  params.SetString("value", "a");
+  params.SetString("using", "css selector");
+  params.SetString("value", "#a");
   params.SetString("id", "1");
   std::unique_ptr<base::Value> result;
   ASSERT_EQ(kNoSuchElement,
@@ -634,8 +634,8 @@
   Session session("id");
   ErrorCallFunctionWebView web_view(kUnknownError);
   base::DictionaryValue params;
-  params.SetString("using", "id");
-  params.SetString("value", "a");
+  params.SetString("using", "css selector");
+  params.SetString("value", "#a");
   std::unique_ptr<base::Value> value;
   ASSERT_EQ(kUnknownError,
             ExecuteFindElement(1, &session, &web_view, params, &value,
@@ -649,8 +649,8 @@
   Session session("id");
   ErrorCallFunctionWebView web_view(kStaleElementReference);
   base::DictionaryValue params;
-  params.SetString("using", "id");
-  params.SetString("value", "a");
+  params.SetString("using", "css selector");
+  params.SetString("value", "#a");
   std::string element_id = "1";
   std::unique_ptr<base::Value> result;
   ASSERT_EQ(
diff --git a/chrome/tools/build/win/create_installer_archive.py b/chrome/tools/build/win/create_installer_archive.py
index be9c38d..b16b16bd 100755
--- a/chrome/tools/build/win/create_installer_archive.py
+++ b/chrome/tools/build/win/create_installer_archive.py
@@ -435,36 +435,6 @@
     shutil.copyfile(src, dest)
 
 
-# Taken and modified from:
-# third_party\blink\tools\blinkpy\web_tests\port\factory.py
-def _read_configuration_from_gn(build_dir):
-  """Return the configuration to used based on args.gn, if possible."""
-  path = os.path.join(build_dir, 'args.gn')
-  if not os.path.exists(path):
-    path = os.path.join(build_dir, 'toolchain.ninja')
-    if not os.path.exists(path):
-      # This does not appear to be a GN-based build directory, so we don't
-      # know how to interpret it.
-      return None
-
-    # toolchain.ninja exists, but args.gn does not; this can happen when
-    # `gn gen` is run with no --args.
-    return 'Debug'
-
-  args = open(path).read()
-  for l in args.splitlines():
-    # See the original of this function and then gn documentation for why this
-    # regular expression is correct:
-    # https://chromium.googlesource.com/chromium/src/+/master/tools/gn/docs/reference.md#GN-build-language-grammar
-    m = re.match('^\s*is_debug\s*=\s*false(\s*$|\s*#.*$)', l)
-    if m:
-      return 'Release'
-
-  # if is_debug is set to anything other than false, or if it
-  # does not exist at all, we should use the default value (True).
-  return 'Debug'
-
-
 def ParseDLLsFromDeps(build_dir, runtime_deps_file):
   """Parses the runtime_deps file and returns the set of DLLs in it, relative
   to build_dir."""
diff --git a/chromeos/DEPS b/chromeos/DEPS
index ec728f1..4bb3be5 100644
--- a/chromeos/DEPS
+++ b/chromeos/DEPS
@@ -26,6 +26,6 @@
   ],
 
   ".*test\.cc": [
-    "+services/network/test/test_url_loader_factory.h",
+    "+services/network/test",
   ],
 }
diff --git a/chromeos/components/drivefs/BUILD.gn b/chromeos/components/drivefs/BUILD.gn
index 8315837..1344deb 100644
--- a/chromeos/components/drivefs/BUILD.gn
+++ b/chromeos/components/drivefs/BUILD.gn
@@ -77,6 +77,7 @@
     "//net",
     "//net:test_support",
     "//services/identity/public/mojom",
+    "//services/network:test_support",
     "//services/network/public/cpp:cpp",
     "//services/service_manager/public/cpp",
     "//services/service_manager/public/cpp/test:test_support",
diff --git a/chromeos/components/drivefs/drivefs_host.cc b/chromeos/components/drivefs/drivefs_host.cc
index 5c49f6d..32e7fce 100644
--- a/chromeos/components/drivefs/drivefs_host.cc
+++ b/chromeos/components/drivefs/drivefs_host.cc
@@ -19,8 +19,8 @@
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/platform/platform_channel_endpoint.h"
 #include "mojo/public/cpp/system/invitation.h"
-#include "net/base/network_change_notifier.h"
 #include "services/identity/public/mojom/constants.mojom.h"
+#include "services/network/public/cpp/network_connection_tracker.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/service_manager/public/cpp/connector.h"
 
@@ -47,8 +47,7 @@
       public drive::DriveNotificationObserver {
  public:
   explicit MountState(DriveFsHost* host)
-      : host_(host),
-        weak_ptr_factory_(this) {
+      : host_(host), weak_ptr_factory_(this) {
     host_->disk_mount_manager_->AddObserver(this);
 
     auto access_token = host_->account_token_delegate_->TakeCachedAccessToken();
@@ -74,8 +73,9 @@
         FROM_HERE, kMountTimeout,
         base::BindOnce(&MountState::OnTimedOut, base::Unretained(this)));
 
-    search_ =
-        std::make_unique<DriveFsSearch>(GetDriveFsInterface(), host_->clock_);
+    search_ = std::make_unique<DriveFsSearch>(
+        GetDriveFsInterface(), host_->network_connection_tracker_,
+        host_->clock_);
   }
 
   ~MountState() override {
@@ -299,15 +299,18 @@
   DISALLOW_COPY_AND_ASSIGN(MountState);
 };
 
-DriveFsHost::DriveFsHost(const base::FilePath& profile_path,
-                         DriveFsHost::Delegate* delegate,
-                         DriveFsHost::MountObserver* mount_observer,
-                         const base::Clock* clock,
-                         chromeos::disks::DiskMountManager* disk_mount_manager,
-                         std::unique_ptr<base::OneShotTimer> timer)
+DriveFsHost::DriveFsHost(
+    const base::FilePath& profile_path,
+    DriveFsHost::Delegate* delegate,
+    DriveFsHost::MountObserver* mount_observer,
+    network::NetworkConnectionTracker* network_connection_tracker,
+    const base::Clock* clock,
+    chromeos::disks::DiskMountManager* disk_mount_manager,
+    std::unique_ptr<base::OneShotTimer> timer)
     : profile_path_(profile_path),
       delegate_(delegate),
       mount_observer_(mount_observer),
+      network_connection_tracker_(network_connection_tracker),
       clock_(clock),
       disk_mount_manager_(disk_mount_manager),
       timer_(std::move(timer)),
@@ -315,6 +318,7 @@
           std::make_unique<DriveFsAuth>(clock, profile_path, delegate)) {
   DCHECK(delegate_);
   DCHECK(mount_observer_);
+  DCHECK(network_connection_tracker_);
   DCHECK(clock_);
 }
 
diff --git a/chromeos/components/drivefs/drivefs_host.h b/chromeos/components/drivefs/drivefs_host.h
index 91fa719..afd01f49 100644
--- a/chromeos/components/drivefs/drivefs_host.h
+++ b/chromeos/components/drivefs/drivefs_host.h
@@ -31,6 +31,10 @@
 }
 }  // namespace chromeos
 
+namespace network {
+class NetworkConnectionTracker;
+}
+
 namespace drivefs {
 
 class DriveFsBootstrapListener;
@@ -78,6 +82,7 @@
   DriveFsHost(const base::FilePath& profile_path,
               Delegate* delegate,
               MountObserver* mount_observer,
+              network::NetworkConnectionTracker* network_connection_tracker,
               const base::Clock* clock,
               chromeos::disks::DiskMountManager* disk_mount_manager,
               std::unique_ptr<base::OneShotTimer> timer);
@@ -120,6 +125,7 @@
 
   Delegate* const delegate_;
   MountObserver* const mount_observer_;
+  network::NetworkConnectionTracker* const network_connection_tracker_;
   const base::Clock* const clock_;
   chromeos::disks::DiskMountManager* const disk_mount_manager_;
   std::unique_ptr<base::OneShotTimer> timer_;
diff --git a/chromeos/components/drivefs/drivefs_host_unittest.cc b/chromeos/components/drivefs/drivefs_host_unittest.cc
index dc1c097..9157482 100644
--- a/chromeos/components/drivefs/drivefs_host_unittest.cc
+++ b/chromeos/components/drivefs/drivefs_host_unittest.cc
@@ -28,10 +28,10 @@
 #include "components/invalidation/impl/fake_invalidation_service.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
-#include "net/base/mock_network_change_notifier.h"
 #include "services/identity/public/mojom/constants.mojom.h"
 #include "services/identity/public/mojom/identity_manager.mojom-test-utils.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/test/test_network_connection_tracker.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/service.h"
@@ -263,7 +263,9 @@
 class DriveFsHostTest : public ::testing::Test, public mojom::DriveFsBootstrap {
  public:
   DriveFsHostTest()
-      : mock_identity_manager_(&clock_),
+      : network_connection_tracker_(
+            network::TestNetworkConnectionTracker::CreateInstance()),
+        mock_identity_manager_(&clock_),
         bootstrap_binding_(this),
         binding_(&mock_drivefs_) {
     clock_.SetNow(base::Time::Now());
@@ -284,8 +286,9 @@
     auto timer = std::make_unique<base::MockOneShotTimer>();
     timer_ = timer.get();
     host_ = std::make_unique<DriveFsHost>(
-        profile_path_, host_delegate_.get(), host_delegate_.get(), &clock_,
-        disk_manager_.get(), std::move(timer));
+        profile_path_, host_delegate_.get(), host_delegate_.get(),
+        network_connection_tracker_.get(), &clock_, disk_manager_.get(),
+        std::move(timer));
   }
 
   void TearDown() override {
@@ -406,6 +409,8 @@
   base::test::ScopedTaskEnvironment task_environment_;
   AccountId account_id_;
   std::unique_ptr<chromeos::disks::MockDiskMountManager> disk_manager_;
+  std::unique_ptr<network::TestNetworkConnectionTracker>
+      network_connection_tracker_;
   base::SimpleTestClock clock_;
   MockIdentityManager mock_identity_manager_;
   service_manager::TestConnectorFactory connector_factory_;
@@ -413,7 +418,6 @@
   std::unique_ptr<TestingDriveFsHostDelegate> host_delegate_;
   std::unique_ptr<DriveFsHost> host_;
   base::MockOneShotTimer* timer_;
-  net::test::MockNetworkChangeNotifier network_;
 
   mojo::Binding<mojom::DriveFsBootstrap> bootstrap_binding_;
   MockDriveFs mock_drivefs_;
@@ -687,8 +691,9 @@
     host_delegate_ = std::make_unique<TestingDriveFsHostDelegate>(
         connector_factory_.CreateConnector(), account);
     host_ = std::make_unique<DriveFsHost>(
-        profile_path_, host_delegate_.get(), host_delegate_.get(), &clock_,
-        disk_manager_.get(), std::make_unique<base::MockOneShotTimer>());
+        profile_path_, host_delegate_.get(), host_delegate_.get(),
+        network_connection_tracker_.get(), &clock_, disk_manager_.get(),
+        std::make_unique<base::MockOneShotTimer>());
     EXPECT_FALSE(host_->Mount());
     EXPECT_FALSE(host_->IsMounted());
   }
diff --git a/chromeos/components/drivefs/drivefs_search.cc b/chromeos/components/drivefs/drivefs_search.cc
index 239ad61..b05289a 100644
--- a/chromeos/components/drivefs/drivefs_search.cc
+++ b/chromeos/components/drivefs/drivefs_search.cc
@@ -5,7 +5,7 @@
 #include "chromeos/components/drivefs/drivefs_search.h"
 
 #include "base/bind.h"
-#include "net/base/network_change_notifier.h"
+#include "services/network/public/cpp/network_connection_tracker.h"
 
 namespace drivefs {
 
@@ -21,8 +21,14 @@
 
 }  // namespace
 
-DriveFsSearch::DriveFsSearch(mojom::DriveFs* drivefs, const base::Clock* clock)
-    : drivefs_(drivefs), clock_(clock), weak_ptr_factory_(this) {}
+DriveFsSearch::DriveFsSearch(
+    mojom::DriveFs* drivefs,
+    network::NetworkConnectionTracker* network_connection_tracker,
+    const base::Clock* clock)
+    : drivefs_(drivefs),
+      network_connection_tracker_(network_connection_tracker),
+      clock_(clock),
+      weak_ptr_factory_(this) {}
 
 DriveFsSearch::~DriveFsSearch() = default;
 
@@ -41,7 +47,7 @@
 
   drivefs::mojom::SearchQueryPtr search;
   drivefs::mojom::QueryParameters::QuerySource source = query->query_source;
-  if (net::NetworkChangeNotifier::IsOffline() &&
+  if (network_connection_tracker_->IsOffline() &&
       source != drivefs::mojom::QueryParameters::QuerySource::kLocalOnly) {
     // No point trying cloud query if we know we are offline.
     source = drivefs::mojom::QueryParameters::QuerySource::kLocalOnly;
diff --git a/chromeos/components/drivefs/drivefs_search.h b/chromeos/components/drivefs/drivefs_search.h
index 44f0df0..5137db8e 100644
--- a/chromeos/components/drivefs/drivefs_search.h
+++ b/chromeos/components/drivefs/drivefs_search.h
@@ -15,12 +15,18 @@
 #include "base/time/clock.h"
 #include "chromeos/components/drivefs/mojom/drivefs.mojom.h"
 
+namespace network {
+class NetworkConnectionTracker;
+}
+
 namespace drivefs {
 
 // Handles search queries to DriveFS.
 class COMPONENT_EXPORT(DRIVEFS) DriveFsSearch {
  public:
-  DriveFsSearch(mojom::DriveFs* drivefs, const base::Clock* clock);
+  DriveFsSearch(mojom::DriveFs* drivefs,
+                network::NetworkConnectionTracker* network_connection_tracker,
+                const base::Clock* clock);
   ~DriveFsSearch();
 
   // Starts DriveFs search query and returns whether it will be
@@ -38,6 +44,7 @@
       base::Optional<std::vector<drivefs::mojom::QueryItemPtr>> items);
 
   mojom::DriveFs* const drivefs_;
+  network::NetworkConnectionTracker* const network_connection_tracker_;
   const base::Clock* const clock_;
   base::Time last_shared_with_me_response_;
 
diff --git a/chromeos/components/drivefs/drivefs_search_unittest.cc b/chromeos/components/drivefs/drivefs_search_unittest.cc
index a1abd5e..427e43a 100644
--- a/chromeos/components/drivefs/drivefs_search_unittest.cc
+++ b/chromeos/components/drivefs/drivefs_search_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/test/simple_test_clock.h"
 #include "chromeos/components/drivefs/mojom/drivefs.mojom-test-utils.h"
 #include "mojo/public/cpp/bindings/binding.h"
-#include "net/base/mock_network_change_notifier.h"
+#include "services/network/test/test_network_connection_tracker.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -55,11 +55,16 @@
 
 class DriveFsSearchTest : public testing::Test {
  public:
-  DriveFsSearchTest() { clock_.SetNow(base::Time::Now()); }
+  DriveFsSearchTest()
+      : network_connection_tracker_(
+            network::TestNetworkConnectionTracker::CreateInstance()) {
+    clock_.SetNow(base::Time::Now());
+  }
 
  protected:
   base::test::ScopedTaskEnvironment task_environment_;
-  net::test::MockNetworkChangeNotifier network_;
+  std::unique_ptr<network::TestNetworkConnectionTracker>
+      network_connection_tracker_;
   MockDriveFs mock_drivefs_;
   base::SimpleTestClock clock_;
 };
@@ -99,7 +104,8 @@
 };
 
 TEST_F(DriveFsSearchTest, Search) {
-  DriveFsSearch search(&mock_drivefs_, &clock_);
+  DriveFsSearch search(&mock_drivefs_, network_connection_tracker_.get(),
+                       &clock_);
 
   EXPECT_CALL(mock_drivefs_, OnStartSearchQuery(_));
   EXPECT_CALL(mock_drivefs_, OnGetNextPage(_))
@@ -125,7 +131,8 @@
 }
 
 TEST_F(DriveFsSearchTest, Search_Fail) {
-  DriveFsSearch search(&mock_drivefs_, &clock_);
+  DriveFsSearch search(&mock_drivefs_, network_connection_tracker_.get(),
+                       &clock_);
 
   EXPECT_CALL(mock_drivefs_, OnStartSearchQuery(_));
   EXPECT_CALL(mock_drivefs_, OnGetNextPage(_))
@@ -149,10 +156,11 @@
 }
 
 TEST_F(DriveFsSearchTest, Search_OnlineToOffline) {
-  DriveFsSearch search(&mock_drivefs_, &clock_);
+  DriveFsSearch search(&mock_drivefs_, network_connection_tracker_.get(),
+                       &clock_);
 
-  network_.SetConnectionType(
-      net::NetworkChangeNotifier::ConnectionType::CONNECTION_NONE);
+  network_connection_tracker_->SetConnectionType(
+      network::mojom::ConnectionType::CONNECTION_NONE);
 
   EXPECT_CALL(mock_drivefs_, OnStartSearchQuery(_));
   EXPECT_CALL(mock_drivefs_, OnGetNextPage(_))
@@ -178,7 +186,8 @@
 }
 
 TEST_F(DriveFsSearchTest, Search_OnlineToOfflineFallback) {
-  DriveFsSearch search(&mock_drivefs_, &clock_);
+  DriveFsSearch search(&mock_drivefs_, network_connection_tracker_.get(),
+                       &clock_);
 
   EXPECT_CALL(mock_drivefs_,
               OnStartSearchQuery(
@@ -214,7 +223,8 @@
 }
 
 TEST_F(DriveFsSearchTest, Search_SharedWithMeCaching) {
-  DriveFsSearch search(&mock_drivefs_, &clock_);
+  DriveFsSearch search(&mock_drivefs_, network_connection_tracker_.get(),
+                       &clock_);
 
   EXPECT_CALL(mock_drivefs_,
               OnStartSearchQuery(
@@ -294,7 +304,8 @@
 }
 
 TEST_F(DriveFsSearchTest, Search_NoErrorCaching) {
-  DriveFsSearch search(&mock_drivefs_, &clock_);
+  DriveFsSearch search(&mock_drivefs_, network_connection_tracker_.get(),
+                       &clock_);
 
   EXPECT_CALL(mock_drivefs_,
               OnStartSearchQuery(
diff --git a/chromeos/network/BUILD.gn b/chromeos/network/BUILD.gn
index 756c831..867f1081 100644
--- a/chromeos/network/BUILD.gn
+++ b/chromeos/network/BUILD.gn
@@ -150,8 +150,6 @@
     "proxy/proxy_config_handler.h",
     "proxy/proxy_config_service_impl.cc",
     "proxy/proxy_config_service_impl.h",
-    "proxy/ui_proxy_config.cc",
-    "proxy/ui_proxy_config.h",
     "proxy/ui_proxy_config_service.cc",
     "proxy/ui_proxy_config_service.h",
     "shill_property_handler.cc",
@@ -211,6 +209,7 @@
     "//components/prefs",
     "//components/prefs:test_support",
     "//components/proxy_config",
+    "//components/sync_preferences:test_support",
     "//crypto",
     "//crypto:test_support",
     "//dbus",
@@ -250,6 +249,7 @@
     "onc/variable_expander_unittest.cc",
     "prohibited_technologies_handler_unittest.cc",
     "proxy/proxy_config_service_impl_unittest.cc",
+    "proxy/ui_proxy_config_service_unittest.cc",
     "shill_property_handler_unittest.cc",
   ]
 }
diff --git a/chromeos/network/DEPS b/chromeos/network/DEPS
index 085fe7ab..3ff0236a 100644
--- a/chromeos/network/DEPS
+++ b/chromeos/network/DEPS
@@ -23,3 +23,9 @@
   "+third_party/cros_system_api",
   "+url",
 ]
+
+specific_include_rules = {
+ "ui_proxy_config_service_unittest.cc": [
+    "+components/sync_preferences/testing_pref_service_syncable.h"
+  ],
+}
diff --git a/chromeos/network/network_state_handler.cc b/chromeos/network/network_state_handler.cc
index ce2a088..78c6ed4 100644
--- a/chromeos/network/network_state_handler.cc
+++ b/chromeos/network/network_state_handler.cc
@@ -72,19 +72,13 @@
 
 bool ShouldIncludeNetworkInList(const NetworkState* network_state,
                                 bool configured_only,
-                                bool visible_only,
-                                bool get_active) {
+                                bool visible_only) {
   if (configured_only && !network_state->IsInProfile())
     return false;
 
   if (visible_only && !network_state->visible())
     return false;
 
-  bool is_network_active =
-      network_state->IsConnectedState() || network_state->IsConnectingState();
-  if (is_network_active != get_active)
-    return false;
-
   if (network_state->type() == shill::kTypeWifi &&
       !network_state->tether_guid().empty()) {
     // Wi-Fi networks which are actually underlying Wi-Fi hotspots for a
@@ -98,6 +92,26 @@
 
 }  // namespace
 
+// Class for tracking properties that affect whether a NetworkState is active.
+class NetworkStateHandler::ActiveNetworkState {
+ public:
+  explicit ActiveNetworkState(const NetworkState* network)
+      : guid_(network->guid()),
+        connection_state_(network->connection_state()) {}
+
+  bool MatchesNetworkState(const NetworkState* network) {
+    return guid_ == network->guid() &&
+           connection_state_ == network->connection_state();
+  }
+
+ private:
+  // Unique network identifier.
+  const std::string guid_;
+  // Active networks have a connected or connecting |connection_state_|, see
+  // NetworkState::Is{Connected|Connecting}State.
+  const std::string connection_state_;
+};
+
 const char NetworkStateHandler::kDefaultCheckPortalList[] =
     "ethernet,wifi,cellular";
 
@@ -357,79 +371,33 @@
 
 const NetworkState* NetworkStateHandler::ConnectedNetworkByType(
     const NetworkTypePattern& type) {
-  // Sort to ensure visible networks are listed first.
-  if (!network_list_sorted_)
-    SortNetworkList(false /* ensure_cellular */);
-
-  const NetworkState* connected_network = nullptr;
-  for (auto iter = network_list_.begin(); iter != network_list_.end(); ++iter) {
-    const NetworkState* network = (*iter)->AsNetworkState();
-    DCHECK(network);
-    if (!network->update_received())
-      continue;
-    if (!network->IsConnectedState())
-      break;  // Connected networks are listed first.
-    if (network->Matches(type)) {
-      connected_network = network;
-      break;
-    }
+  NetworkStateList active_networks;
+  GetActiveNetworkListByType(type, &active_networks);
+  for (auto* network : active_networks) {
+    if (network->IsConnectedState())
+      return network;
   }
-
-  // Ethernet networks are prioritized over Tether networks.
-  if (connected_network && connected_network->type() == shill::kTypeEthernet) {
-    return connected_network;
-  }
-
-  // Tether networks are prioritized over non-Ethernet networks.
-  if (type.MatchesPattern(NetworkTypePattern::Tether())) {
-    for (auto iter = tether_network_list_.begin();
-         iter != tether_network_list_.end(); ++iter) {
-      const NetworkState* network = (*iter)->AsNetworkState();
-      DCHECK(network);
-      if (network->IsConnectedState())
-        return network;
-    }
-  }
-
-  return connected_network;
+  return nullptr;
 }
 
 const NetworkState* NetworkStateHandler::ConnectingNetworkByType(
-    const NetworkTypePattern& type) const {
-  const NetworkState* connecting_network = nullptr;
-
-  // Active networks are always listed first by Shill so no need to sort.
-  for (auto iter = network_list_.begin(); iter != network_list_.end(); ++iter) {
-    const NetworkState* network = (*iter)->AsNetworkState();
-    DCHECK(network);
-    if (!network->update_received() || network->IsConnectedState())
-      continue;
-    if (!network->IsConnectingState())
-      break;  // Connected and connecting networks are listed first.
-    if (network->Matches(type)) {
-      connecting_network = network;
-      break;
-    }
+    const NetworkTypePattern& type) {
+  NetworkStateList active_networks;
+  GetActiveNetworkListByType(type, &active_networks);
+  for (auto* network : active_networks) {
+    if (network->IsConnectingState())
+      return network;
   }
+  return nullptr;
+}
 
-  // Ethernet networks are prioritized over Tether networks.
-  if (connecting_network &&
-      connecting_network->type() == shill::kTypeEthernet) {
-    return connecting_network;
-  }
-
-  // Tether networks are prioritized over non-Ethernet networks.
-  if (type.MatchesPattern(NetworkTypePattern::Tether())) {
-    for (auto iter = tether_network_list_.begin();
-         iter != tether_network_list_.end(); ++iter) {
-      const NetworkState* network = (*iter)->AsNetworkState();
-      DCHECK(network);
-      if (network->IsConnectingState())
-        return network;
-    }
-  }
-
-  return connecting_network;
+const NetworkState* NetworkStateHandler::ActiveNetworkByType(
+    const NetworkTypePattern& type) {
+  NetworkStateList active_networks;
+  GetActiveNetworkListByType(type, &active_networks);
+  if (active_networks.size() > 0)
+    return active_networks.front();
+  return nullptr;
 }
 
 const NetworkState* NetworkStateHandler::FirstNetworkByType(
@@ -509,6 +477,25 @@
                                                bool visible_only,
                                                size_t limit,
                                                NetworkStateList* list) {
+  GetNetworkListByTypeImpl(type, configured_only, visible_only,
+                           false /* active_only */, limit, list);
+}
+
+void NetworkStateHandler::GetActiveNetworkListByType(
+    const NetworkTypePattern& type,
+    NetworkStateList* list) {
+  GetNetworkListByTypeImpl(type, false /* configured_only */,
+                           false /* visible_only */, true /* active_only */,
+                           0 /* no limit */, list);
+}
+
+void NetworkStateHandler::GetNetworkListByTypeImpl(
+    const NetworkTypePattern& type,
+    bool configured_only,
+    bool visible_only,
+    bool active_only,
+    size_t limit,
+    NetworkStateList* list) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(list);
   list->clear();
@@ -526,40 +513,48 @@
     AppendTetherNetworksToList(true /* get_active */, limit, list);
 
   // Second, add active non-Tether networks.
-  for (auto iter = network_list_.begin();
-       iter != network_list_.end() && list->size() < limit; ++iter) {
-    const NetworkState* network = (*iter)->AsNetworkState();
+  for (const auto& managed : network_list_) {
+    const NetworkState* network = managed.get()->AsNetworkState();
     DCHECK(network);
     if (!network->update_received() || !network->Matches(type))
       continue;
-    if (!ShouldIncludeNetworkInList(network, configured_only, visible_only,
-                                    true /* get_active */)) {
+    if (!network->IsConnectingOrConnected())
+      break;  // Shill lists active networks first.
+    if (!ShouldIncludeNetworkInList(network, configured_only, visible_only))
       continue;
-    }
+
     if (network->type() == shill::kTypeEthernet) {
       // Ethernet networks should always be in front.
       list->insert(list->begin(), network);
     } else {
       list->push_back(network);
     }
+    if (list->size() >= limit)
+      return;
   }
 
+  if (active_only)
+    return;
+
   // Third, add inactive Tether networks.
   if (type.MatchesPattern(NetworkTypePattern::Tether()))
     AppendTetherNetworksToList(false /* get_active */, limit, list);
+  if (list->size() >= limit)
+    return;
 
   // Fourth, add inactive non-Tether networks.
-  for (auto iter = network_list_.begin();
-       iter != network_list_.end() && list->size() < limit; ++iter) {
-    const NetworkState* network = (*iter)->AsNetworkState();
+  for (const auto& managed : network_list_) {
+    const NetworkState* network = managed.get()->AsNetworkState();
     DCHECK(network);
     if (!network->update_received() || !network->Matches(type))
       continue;
-    if (!ShouldIncludeNetworkInList(network, configured_only, visible_only,
-                                    false /* get_active */)) {
+    if (network->IsConnectingOrConnected())
       continue;
-    }
+    if (!ShouldIncludeNetworkInList(network, configured_only, visible_only))
+      continue;
     list->push_back(network);
+    if (list->size() >= limit)
+      return;
   }
 }
 
@@ -575,12 +570,12 @@
        iter != tether_network_list_.end() && list->size() < limit; ++iter) {
     const NetworkState* network = (*iter)->AsNetworkState();
     DCHECK(network);
-
+    if (network->IsConnectingOrConnected() != get_active)
+      continue;
     if (!ShouldIncludeNetworkInList(network, false /* configured_only */,
-                                    false /* visible_only */, get_active)) {
+                                    false /* visible_only */)) {
       continue;
     }
-
     list->push_back(network);
   }
 }
@@ -709,14 +704,17 @@
   for (auto iter = tether_network_list_.begin();
        iter != tether_network_list_.end(); ++iter) {
     if (iter->get()->AsNetworkState()->guid() == guid) {
-      NetworkState* wifi_network = GetModifiableNetworkStateFromGuid(
-          iter->get()->AsNetworkState()->tether_guid());
+      NetworkState* tether_network = iter->get()->AsNetworkState();
+      bool was_active = tether_network->IsConnectingOrConnected();
+      NetworkState* wifi_network =
+          GetModifiableNetworkStateFromGuid(tether_network->tether_guid());
       if (wifi_network)
         wifi_network->set_tether_guid(std::string());
-
       tether_network_list_.erase(iter);
-      NotifyNetworkListChanged();
 
+      if (was_active)
+        NotifyIfActiveNetworksChanged();
+      NotifyNetworkListChanged();
       return true;
     }
   }
@@ -1394,6 +1392,8 @@
     NotifyNetworkPropertiesUpdated(network);
     if (network->path() == default_network_path_)
       NotifyDefaultNetworkChanged();
+    if (network->IsConnectingOrConnected())
+      NotifyIfActiveNetworksChanged();
   } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
     DeviceState* device = GetModifiableDeviceState(path);
     if (!device)
@@ -1428,6 +1428,7 @@
   if (type == ManagedState::MANAGED_TYPE_NETWORK) {
     SortNetworkList(true /* ensure_cellular */);
     UpdateNetworkStats();
+    NotifyIfActiveNetworksChanged();
     NotifyNetworkListChanged();
     UpdateManagedWifiNetworkAvailable();
   } else if (type == ManagedState::MANAGED_TYPE_DEVICE) {
@@ -1803,6 +1804,7 @@
   for (auto& observer : observers_)
     observer.NetworkConnectionStateChanged(network);
   notifying_network_observers_ = false;
+  NotifyIfActiveNetworksChanged();
 }
 
 void NetworkStateHandler::NotifyDefaultNetworkChanged() {
@@ -1823,6 +1825,36 @@
   notifying_network_observers_ = false;
 }
 
+bool NetworkStateHandler::ActiveNetworksChanged(
+    const NetworkStateList& active_networks) {
+  if (active_networks.size() != active_network_list_.size())
+    return true;
+  for (size_t i = 0; i < active_network_list_.size(); ++i) {
+    if (!active_network_list_[i].MatchesNetworkState(active_networks[i]))
+      return true;
+  }
+  return false;
+}
+
+void NetworkStateHandler::NotifyIfActiveNetworksChanged() {
+  SCOPED_NET_LOG_IF_SLOW();
+  NET_LOG(EVENT) << "NOTIFY:ActiveNetworksChanged";
+  NetworkStateList active_networks;
+  GetActiveNetworkListByType(NetworkTypePattern::Default(), &active_networks);
+  if (!ActiveNetworksChanged(active_networks))
+    return;
+
+  active_network_list_.clear();
+  active_network_list_.reserve(active_networks.size());
+  for (const NetworkState* network : active_networks)
+    active_network_list_.emplace_back(network);
+
+  notifying_network_observers_ = true;
+  for (auto& observer : observers_)
+    observer.ActiveNetworksChanged(active_networks);
+  notifying_network_observers_ = false;
+}
+
 void NetworkStateHandler::NotifyNetworkPropertiesUpdated(
     const NetworkState* network) {
   SCOPED_NET_LOG_IF_SLOW();
diff --git a/chromeos/network/network_state_handler.h b/chromeos/network/network_state_handler.h
index db4b931..137370f8 100644
--- a/chromeos/network/network_state_handler.h
+++ b/chromeos/network/network_state_handler.h
@@ -161,12 +161,15 @@
   // differ.
   const NetworkState* DefaultNetwork() const;
 
-  // Returns the primary connected network of matching |type|, otherwise NULL.
+  // Returns the primary connected network matching |type|, otherwise null.
   const NetworkState* ConnectedNetworkByType(const NetworkTypePattern& type);
 
-  // Like ConnectedNetworkByType() but returns a connecting network or NULL.
-  const NetworkState* ConnectingNetworkByType(
-      const NetworkTypePattern& type) const;
+  // Returns the primary connecting network matching |type|, otherwise null.
+  const NetworkState* ConnectingNetworkByType(const NetworkTypePattern& type);
+
+  // Returns the primary active network of matching |type|, otherwise null.
+  // See also GetActiveNetworkListByType.
+  const NetworkState* ActiveNetworkByType(const NetworkTypePattern& type);
 
   // Like ConnectedNetworkByType() but returns any matching visible network or
   // NULL. Mostly useful for mobile networks where there is generally only one
@@ -200,6 +203,14 @@
                             size_t limit,
                             NetworkStateList* list);
 
+  // Sets |list| to contain the active networks matching |type|. An 'active'
+  // network is connecting or connected, and the first connected active network
+  // is the primary or 'default' network providing connectivity (which may be a
+  // VPN, use NetworkTypePattern::NonVirtual() to ignore VPNs). See
+  // GetNetworkListByType for notes on |list| results.
+  void GetActiveNetworkListByType(const NetworkTypePattern& type,
+                                  NetworkStateList* list);
+
   // Finds and returns the NetworkState associated with |service_path| or NULL
   // if not found. If |configured_only| is true, only returns saved entries
   // (IsInProfile is true).
@@ -452,6 +463,14 @@
   FRIEND_TEST_ALL_PREFIXES(NetworkStateHandlerTest,
                            BlockedByPolicyOnlyManagedIfAvailable);
 
+  // Implementation for GetNetworkListByType and GetActiveNetworkListByType.
+  void GetNetworkListByTypeImpl(const NetworkTypePattern& type,
+                                bool configured_only,
+                                bool visible_only,
+                                bool active_only,
+                                size_t limit,
+                                NetworkStateList* list);
+
   // Sorts the network list. Called when all network updates have been received,
   // or when the network list is requested but the list is in an unsorted state.
   // Networks are sorted as follows, maintaining the existing relative ordering:
@@ -527,6 +546,11 @@
   // Notifies observers when the default network or its properties change.
   void NotifyDefaultNetworkChanged();
 
+  // Notifies observers when the active state of any current or previously
+  // active network changes, or the active networks order changes.
+  bool ActiveNetworksChanged(const NetworkStateList& active_networks);
+  void NotifyIfActiveNetworksChanged();
+
   // Notifies observers about changes to |network|, including IPConfg.
   void NotifyNetworkPropertiesUpdated(const NetworkState* network);
 
@@ -600,6 +624,10 @@
   // |network_list_|.
   ManagedStateList tether_network_list_;
 
+  // List of active networks, used to limit ActiveNetworksChanged events.
+  class ActiveNetworkState;
+  std::vector<ActiveNetworkState> active_network_list_;
+
   // Set to true when the network list is sorted, cleared when network updates
   // arrive. Used to trigger sorting when needed.
   bool network_list_sorted_ = false;
diff --git a/chromeos/network/network_state_handler_observer.cc b/chromeos/network/network_state_handler_observer.cc
index 16f35f9..aae9396 100644
--- a/chromeos/network/network_state_handler_observer.cc
+++ b/chromeos/network/network_state_handler_observer.cc
@@ -10,33 +10,29 @@
 
 NetworkStateHandlerObserver::~NetworkStateHandlerObserver() = default;
 
-void NetworkStateHandlerObserver::NetworkListChanged() {
-}
+void NetworkStateHandlerObserver::NetworkListChanged() {}
 
-void NetworkStateHandlerObserver::DeviceListChanged() {
-}
+void NetworkStateHandlerObserver::DeviceListChanged() {}
 
 void NetworkStateHandlerObserver::DefaultNetworkChanged(
-    const NetworkState* network) {
-}
+    const NetworkState* network) {}
 
 void NetworkStateHandlerObserver::NetworkConnectionStateChanged(
-    const NetworkState* network) {
-}
+    const NetworkState* network) {}
+
+void NetworkStateHandlerObserver::ActiveNetworksChanged(
+    const std::vector<const NetworkState*>& active_networks) {}
 
 void NetworkStateHandlerObserver::NetworkPropertiesUpdated(
-    const NetworkState* network) {
-}
+    const NetworkState* network) {}
 
 void NetworkStateHandlerObserver::DevicePropertiesUpdated(
-    const chromeos::DeviceState* device) {
-}
+    const chromeos::DeviceState* device) {}
 
 void NetworkStateHandlerObserver::ScanRequested(
     const NetworkTypePattern& type) {}
 
-void NetworkStateHandlerObserver::ScanCompleted(const DeviceState* device) {
-}
+void NetworkStateHandlerObserver::ScanCompleted(const DeviceState* device) {}
 
 void NetworkStateHandlerObserver::OnShuttingDown() {}
 
diff --git a/chromeos/network/network_state_handler_observer.h b/chromeos/network/network_state_handler_observer.h
index da1a9d04..6e1d125 100644
--- a/chromeos/network/network_state_handler_observer.h
+++ b/chromeos/network/network_state_handler_observer.h
@@ -41,6 +41,12 @@
   // The connection state of |network| changed.
   virtual void NetworkConnectionStateChanged(const NetworkState* network);
 
+  // Triggered when the connection state of any current or previously active
+  // (connected or connecting) network changes. Provides the current list of
+  // active networks, which may include a VPN.
+  virtual void ActiveNetworksChanged(
+      const std::vector<const NetworkState*>& active_networks);
+
   // One or more properties of |network| have been updated. Note: this will get
   // called in *addition* to NetworkConnectionStateChanged() when the
   // connection state property changes. Use this to track properties like
diff --git a/chromeos/network/network_state_handler_unittest.cc b/chromeos/network/network_state_handler_unittest.cc
index 7583eb9..7f074ce 100644
--- a/chromeos/network/network_state_handler_unittest.cc
+++ b/chromeos/network/network_state_handler_unittest.cc
@@ -40,11 +40,6 @@
 
 namespace {
 
-void ErrorCallbackFunction(const std::string& error_name,
-                           const std::string& error_message) {
-  LOG(ERROR) << "Shill Error: " << error_name << " : " << error_message;
-}
-
 const char kShillManagerClientStubWifiDevice[] = "/device/stub_wifi_device1";
 const char kShillManagerClientStubCellularDevice[] =
     "/device/stub_cellular_device1";
@@ -71,21 +66,22 @@
 
 const char kProfilePath[] = "/network/test";
 
-using chromeos::DeviceState;
-using chromeos::NetworkState;
-using chromeos::NetworkStateHandler;
+void ErrorCallbackFunction(const std::string& error_name,
+                           const std::string& error_message) {
+  LOG(ERROR) << "Shill Error: " << error_name << " : " << error_message;
+}
+
+std::vector<std::string> GetNetworkPaths(
+    const std::vector<const NetworkState*>& networks) {
+  std::vector<std::string> result;
+  for (const auto* network : networks)
+    result.push_back(network->path());
+  return result;
+}
 
 class TestObserver final : public chromeos::NetworkStateHandlerObserver {
  public:
-  explicit TestObserver(NetworkStateHandler* handler)
-      : handler_(handler),
-        device_list_changed_count_(0),
-        device_count_(0),
-        network_list_changed_count_(0),
-        network_count_(0),
-        default_network_change_count_(0),
-        scan_completed_count_(0) {}
-
+  explicit TestObserver(NetworkStateHandler* handler) : handler_(handler) {}
   ~TestObserver() override = default;
 
   void DeviceListChanged() override {
@@ -103,10 +99,6 @@
                                    0 /* no limit */,
                                    &networks);
     network_count_ = networks.size();
-    if (network_count_ == 0) {
-      default_network_ = "";
-      default_network_connection_state_ = "";
-    }
     ++network_list_changed_count_;
   }
 
@@ -125,6 +117,12 @@
     connection_state_changes_[network->path()]++;
   }
 
+  void ActiveNetworksChanged(
+      const std::vector<const NetworkState*>& active_networks) override {
+    ++active_network_change_count_;
+    active_network_paths_ = GetNetworkPaths(active_networks);
+  }
+
   void NetworkPropertiesUpdated(const NetworkState* network) override {
     DCHECK(network);
     property_updates_[network->path()]++;
@@ -144,13 +142,14 @@
     scan_completed_count_++;
   }
 
+  size_t active_network_change_count() { return active_network_change_count_; }
+  size_t default_network_change_count() {
+    return default_network_change_count_;
+  }
   size_t device_list_changed_count() { return device_list_changed_count_; }
   size_t device_count() { return device_count_; }
   size_t network_list_changed_count() { return network_list_changed_count_; }
   size_t network_count() { return network_count_; }
-  size_t default_network_change_count() {
-    return default_network_change_count_;
-  }
   size_t scan_requested_count() { return scan_requests_.size(); }
   const std::vector<NetworkTypePattern>& scan_requests() {
     return scan_requests_;
@@ -158,6 +157,7 @@
   size_t scan_completed_count() { return scan_completed_count_; }
   void reset_change_counts() {
     VLOG(1) << "=== RESET CHANGE COUNTS ===";
+    active_network_change_count_ = 0;
     default_network_change_count_ = 0;
     device_list_changed_count_ = 0;
     network_list_changed_count_ = 0;
@@ -169,6 +169,9 @@
     property_updates_.clear();
     device_property_updates_.clear();
   }
+  const std::vector<std::string>& active_network_paths() {
+    return active_network_paths_;
+  }
   std::string default_network() { return default_network_; }
   std::string default_network_connection_state() {
     return default_network_connection_state_;
@@ -193,13 +196,15 @@
 
  private:
   NetworkStateHandler* handler_;
-  size_t device_list_changed_count_;
-  size_t device_count_;
-  size_t network_list_changed_count_;
-  size_t network_count_;
-  size_t default_network_change_count_;
+  size_t active_network_change_count_ = 0;
+  size_t default_network_change_count_ = 0;
+  size_t device_list_changed_count_ = 0;
+  size_t device_count_ = 0;
+  size_t network_list_changed_count_ = 0;
+  size_t network_count_ = 0;
   std::vector<NetworkTypePattern> scan_requests_;
-  size_t scan_completed_count_;
+  size_t scan_completed_count_ = 0;
+  std::vector<std::string> active_network_paths_;
   std::string default_network_;
   std::string default_network_connection_state_;
   std::map<std::string, int> property_updates_;
@@ -396,6 +401,31 @@
             test_observer_->default_network_connection_state());
 }
 
+TEST_F(NetworkStateHandlerTest, NetworkStateHandlerStubActiveNetworks) {
+  NetworkStateHandler::NetworkStateList active_networks;
+  network_state_handler_->GetActiveNetworkListByType(
+      NetworkTypePattern::Default(), &active_networks);
+  std::vector<std::string> active_network_paths =
+      GetNetworkPaths(active_networks);
+  const std::vector<std::string> expected_active_network_paths = {
+      kShillManagerClientStubDefaultService,
+      kShillManagerClientStubDefaultWifi};
+  EXPECT_EQ(expected_active_network_paths, active_network_paths);
+
+  EXPECT_EQ(
+      kShillManagerClientStubDefaultService,
+      network_state_handler_->ActiveNetworkByType(NetworkTypePattern::Default())
+          ->path());
+  EXPECT_EQ(kShillManagerClientStubDefaultService,
+            network_state_handler_
+                ->ActiveNetworkByType(NetworkTypePattern::Ethernet())
+                ->path());
+  EXPECT_EQ(
+      kShillManagerClientStubDefaultWifi,
+      network_state_handler_->ActiveNetworkByType(NetworkTypePattern::WiFi())
+          ->path());
+}
+
 TEST_F(NetworkStateHandlerTest, GetNetworkList) {
   network_state_handler_->SetTetherTechnologyState(
       NetworkStateHandler::TECHNOLOGY_ENABLED);
@@ -639,6 +669,19 @@
   EXPECT_EQ(cellular, list[2]->path());
   EXPECT_EQ(kTetherGuid2, list[3]->guid());
   EXPECT_EQ(wifi2, list[4]->path());
+
+  // Get active networks.
+  network_state_handler_->GetActiveNetworkListByType(
+      NetworkTypePattern::Default(), &list);
+  std::vector<std::string> active_network_paths = GetNetworkPaths(list);
+  const std::vector<std::string> expected_active_network_paths = {
+      kShillManagerClientStubDefaultService, kTetherGuid1,
+      kShillManagerClientStubCellular};
+  EXPECT_EQ(expected_active_network_paths, active_network_paths);
+  EXPECT_EQ(
+      kTetherGuid1,
+      network_state_handler_->ActiveNetworkByType(NetworkTypePattern::Tether())
+          ->path());
 }
 
 TEST_F(NetworkStateHandlerTest, NetworkListChanged) {
@@ -855,6 +898,7 @@
   EXPECT_EQ("", ethernet->security_class());
   EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(eth1));
   EXPECT_EQ(0u, test_observer_->default_network_change_count());
+  EXPECT_EQ(0u, test_observer_->active_network_change_count());
   base::Value security_class_value("TestSecurityClass");
   SetServiceProperty(eth1, shill::kSecurityClassProperty, security_class_value);
   base::RunLoop().RunUntilIdle();
@@ -878,6 +922,7 @@
   EXPECT_EQ(1, wifi->signal_strength());
   EXPECT_EQ(1, test_observer_->PropertyUpdatesForService(wifi1));
   EXPECT_EQ(0u, test_observer_->default_network_change_count());
+  EXPECT_EQ(0u, test_observer_->active_network_change_count());
   base::Value signal_strength_value(11);
   SetServiceProperty(wifi1, shill::kSignalStrengthProperty,
                      signal_strength_value);
@@ -887,6 +932,7 @@
   // The change should trigger an additional properties updated event.
   EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(wifi1));
   EXPECT_EQ(0u, test_observer_->default_network_change_count());
+  EXPECT_EQ(0u, test_observer_->active_network_change_count());
 }
 
 TEST_F(NetworkStateHandlerTest, ServicePropertyChangedNotIneterstingInactive) {
@@ -1546,6 +1592,81 @@
   EXPECT_EQ(1, test_observer_->ConnectionStateChangesForService(eth1));
 }
 
+TEST_F(NetworkStateHandlerTest, NetworkActiveNetworksStateChanged) {
+  // Initial state is just connected to Ethernet.
+  std::vector<std::string> expected_active_network_paths = {
+      kShillManagerClientStubDefaultService,
+      kShillManagerClientStubDefaultWifi};
+  EXPECT_EQ(expected_active_network_paths,
+            test_observer_->active_network_paths());
+
+  // Remove Ethernet.
+  service_test_->RemoveService(kShillManagerClientStubDefaultService);
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(1u, test_observer_->active_network_change_count());
+  expected_active_network_paths = {kShillManagerClientStubDefaultWifi};
+  EXPECT_EQ(expected_active_network_paths,
+            test_observer_->active_network_paths());
+
+  // Disconnect Wifi1.
+  test_observer_->reset_change_counts();
+  service_test_->SetServiceProperty(kShillManagerClientStubDefaultWifi,
+                                    shill::kStateProperty,
+                                    base::Value(shill::kStateIdle));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(1u, test_observer_->active_network_change_count());
+  expected_active_network_paths = {};
+  EXPECT_EQ(expected_active_network_paths,
+            test_observer_->active_network_paths());
+
+  // Confirm that changing the connection state to the same value does *not*
+  // signal the observer.
+  service_test_->SetServiceProperty(kShillManagerClientStubDefaultWifi,
+                                    shill::kStateProperty,
+                                    base::Value(shill::kStateIdle));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(1u, test_observer_->active_network_change_count());
+
+  // Add two Tether networks.
+  test_observer_->reset_change_counts();
+  network_state_handler_->SetTetherTechnologyState(
+      NetworkStateHandler::TECHNOLOGY_ENABLED);
+  network_state_handler_->AddTetherNetworkState(
+      kTetherGuid1, kTetherName1, kTetherCarrier1, kTetherBatteryPercentage1,
+      kTetherSignalStrength1, kTetherHasConnectedToHost1);
+  network_state_handler_->AddTetherNetworkState(
+      kTetherGuid2, kTetherName2, kTetherCarrier2, kTetherBatteryPercentage2,
+      kTetherSignalStrength2, kTetherHasConnectedToHost2);
+  network_state_handler_->SetTetherNetworkStateConnecting(kTetherGuid1);
+  network_state_handler_->AssociateTetherNetworkStateWithWifiNetwork(
+      kTetherGuid1, "wifi2_guid");
+  service_test_->SetServiceProperty(kShillManagerClientStubWifi2,
+                                    shill::kStateProperty,
+                                    base::Value(shill::kStateOnline));
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(1u, test_observer_->active_network_change_count());
+
+  // Connect the first Tether network.
+  test_observer_->reset_change_counts();
+  network_state_handler_->SetTetherNetworkStateConnected(kTetherGuid1);
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(1u, test_observer_->active_network_change_count());
+  expected_active_network_paths = {kTetherGuid1};
+  EXPECT_EQ(expected_active_network_paths,
+            test_observer_->active_network_paths());
+
+  // Reconnect Ethernet
+  test_observer_->reset_change_counts();
+  AddService(kShillManagerClientStubDefaultService, "eth1_guid", "eth1",
+             shill::kTypeEthernet, shill::kStateOnline);
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(1u, test_observer_->active_network_change_count());
+  expected_active_network_paths = {kShillManagerClientStubDefaultService,
+                                   kTetherGuid1};
+  EXPECT_EQ(expected_active_network_paths,
+            test_observer_->active_network_paths());
+}
+
 TEST_F(NetworkStateHandlerTest, DefaultServiceDisconnected) {
   const std::string eth1 = kShillManagerClientStubDefaultService;
   const std::string wifi1 = kShillManagerClientStubDefaultWifi;
diff --git a/chromeos/network/proxy/ui_proxy_config.cc b/chromeos/network/proxy/ui_proxy_config.cc
deleted file mode 100644
index d13fe1ef..0000000
--- a/chromeos/network/proxy/ui_proxy_config.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chromeos/network/proxy/ui_proxy_config.h"
-
-#include "base/logging.h"
-#include "components/proxy_config/proxy_config_dictionary.h"
-#include "net/proxy_resolution/proxy_config.h"
-#include "url/url_constants.h"
-
-namespace chromeos {
-
-UIProxyConfig::UIProxyConfig()
-    : mode(MODE_DIRECT), state(ProxyPrefs::CONFIG_UNSET) {}
-
-UIProxyConfig::~UIProxyConfig() = default;
-
-bool UIProxyConfig::FromNetProxyConfig(const net::ProxyConfig& net_config) {
-  *this = UIProxyConfig();  // Reset to default.
-  const net::ProxyConfig::ProxyRules& rules = net_config.proxy_rules();
-  switch (rules.type) {
-    case net::ProxyConfig::ProxyRules::Type::EMPTY:
-      if (!net_config.HasAutomaticSettings()) {
-        mode = UIProxyConfig::MODE_DIRECT;
-      } else if (net_config.auto_detect()) {
-        mode = UIProxyConfig::MODE_AUTO_DETECT;
-      } else if (net_config.has_pac_url()) {
-        mode = UIProxyConfig::MODE_PAC_SCRIPT;
-        automatic_proxy.pac_url = net_config.pac_url();
-      } else {
-        return false;
-      }
-      return true;
-    case net::ProxyConfig::ProxyRules::Type::PROXY_LIST:
-      if (rules.single_proxies.IsEmpty())
-        return false;
-      mode = MODE_SINGLE_PROXY;
-      single_proxy.server = rules.single_proxies.Get();
-      return true;
-    case net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME:
-      // Make sure we have valid server for at least one of the protocols.
-      if (rules.proxies_for_http.IsEmpty() &&
-          rules.proxies_for_https.IsEmpty() &&
-          rules.proxies_for_ftp.IsEmpty() && rules.fallback_proxies.IsEmpty()) {
-        return false;
-      }
-      mode = MODE_PROXY_PER_SCHEME;
-      if (!rules.proxies_for_http.IsEmpty())
-        http_proxy.server = rules.proxies_for_http.Get();
-      if (!rules.proxies_for_https.IsEmpty())
-        https_proxy.server = rules.proxies_for_https.Get();
-      if (!rules.proxies_for_ftp.IsEmpty())
-        ftp_proxy.server = rules.proxies_for_ftp.Get();
-      if (!rules.fallback_proxies.IsEmpty())
-        socks_proxy.server = rules.fallback_proxies.Get();
-      return true;
-    default:
-      NOTREACHED() << "Unrecognized proxy config mode";
-      break;
-  }
-  return false;
-}
-
-}  // namespace chromeos
diff --git a/chromeos/network/proxy/ui_proxy_config.h b/chromeos/network/proxy/ui_proxy_config.h
deleted file mode 100644
index 978d4f4..0000000
--- a/chromeos/network/proxy/ui_proxy_config.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROMEOS_NETWORK_PROXY_UI_PROXY_CONFIG_H_
-#define CHROMEOS_NETWORK_PROXY_UI_PROXY_CONFIG_H_
-
-#include <memory>
-#include <string>
-
-#include "base/component_export.h"
-#include "components/proxy_config/proxy_prefs.h"
-#include "net/base/proxy_server.h"
-#include "net/proxy_resolution/proxy_bypass_rules.h"
-#include "url/gurl.h"
-
-namespace net {
-class ProxyConfig;
-}
-
-namespace chromeos {
-
-// Contrary to other platforms which simply use the systems' UI to allow users
-// to configure proxies, we have to implement our own UI on the chromeos device.
-// This requires extra and specific UI requirements that net::ProxyConfig does
-// not supply.  So we create an augmented analog to net::ProxyConfig here to
-// include and handle these UI requirements, e.g.
-// - state of configuration e.g. where it was picked up from - policy,
-//   extension, etc (refer to ProxyPrefs::ConfigState)
-// - the read/write access of a proxy setting
-// - may add more stuff later.
-// This is then converted to the common net::ProxyConfig before being pushed
-// to PrefProxyConfigTrackerImpl::OnProxyConfigChanged and then to the network
-// stack.
-struct COMPONENT_EXPORT(CHROMEOS_NETWORK) UIProxyConfig {
-  // Specifies if proxy config is direct, auto-detect, using pac script,
-  // single-proxy, or proxy-per-scheme.
-  enum Mode {
-    MODE_DIRECT,
-    MODE_AUTO_DETECT,
-    MODE_PAC_SCRIPT,
-    MODE_SINGLE_PROXY,
-    MODE_PROXY_PER_SCHEME,
-  };
-
-  // Proxy setting for mode = direct or auto-detect or using pac script.
-  struct AutomaticProxy {
-    GURL pac_url;  // Set if proxy is using pac script.
-  };
-
-  // Proxy setting for mode = single-proxy or proxy-per-scheme.
-  struct ManualProxy {
-    net::ProxyServer server;
-  };
-
-  UIProxyConfig();
-  ~UIProxyConfig();
-
-  // Converts net::ProxyConfig to |this|.
-  bool FromNetProxyConfig(const net::ProxyConfig& net_config);
-
-  Mode mode;
-
-  ProxyPrefs::ConfigState state;
-
-  // Set if mode is MODE_DIRECT or MODE_AUTO_DETECT or MODE_PAC_SCRIPT.
-  AutomaticProxy automatic_proxy;
-  // Set if mode is MODE_SINGLE_PROXY.
-  ManualProxy single_proxy;
-  // Set if mode is MODE_PROXY_PER_SCHEME and has http proxy.
-  ManualProxy http_proxy;
-  // Set if mode is MODE_PROXY_PER_SCHEME and has https proxy.
-  ManualProxy https_proxy;
-  // Set if mode is MODE_PROXY_PER_SCHEME and has ftp proxy.
-  ManualProxy ftp_proxy;
-  // Set if mode is MODE_PROXY_PER_SCHEME and has socks proxy.
-  ManualProxy socks_proxy;
-};
-
-}  // namespace chromeos
-
-#endif  // CHROMEOS_NETWORK_PROXY_UI_PROXY_CONFIG_H_
diff --git a/chromeos/network/proxy/ui_proxy_config_service.cc b/chromeos/network/proxy/ui_proxy_config_service.cc
index f68f38f..b154b87 100644
--- a/chromeos/network/proxy/ui_proxy_config_service.cc
+++ b/chromeos/network/proxy/ui_proxy_config_service.cc
@@ -25,23 +25,6 @@
 
 namespace {
 
-const char* ModeToString(UIProxyConfig::Mode mode) {
-  switch (mode) {
-    case UIProxyConfig::MODE_DIRECT:
-      return "direct";
-    case UIProxyConfig::MODE_AUTO_DETECT:
-      return "auto-detect";
-    case UIProxyConfig::MODE_PAC_SCRIPT:
-      return "pacurl";
-    case UIProxyConfig::MODE_SINGLE_PROXY:
-      return "single-proxy";
-    case UIProxyConfig::MODE_PROXY_PER_SCHEME:
-      return "proxy-per-scheme";
-  }
-  NOTREACHED() << "Unrecognized mode type";
-  return "";
-}
-
 // Writes the proxy config of |network| to |proxy_config|.  Sets |onc_source| to
 // the source of this configuration. Returns false if no proxy was configured
 // for this network.
@@ -59,10 +42,144 @@
                                                            proxy_config);
 }
 
-// Returns true if proxy settings from |onc_source| are editable.
-bool IsNetworkProxySettingsEditable(const onc::ONCSource onc_source) {
-  return onc_source != onc::ONC_SOURCE_DEVICE_POLICY &&
-         onc_source != onc::ONC_SOURCE_USER_POLICY;
+std::string EffectiveConfigStateToOncSourceString(
+    ProxyPrefs::ConfigState effective_config_state,
+    bool is_local_state_config,
+    onc::ONCSource onc_source) {
+  // If source precedes prefs, the config came from prefs - set by either policy
+  // or extensions.
+  if (ProxyConfigServiceImpl::PrefPrecedes(effective_config_state)) {
+    if (effective_config_state == ProxyPrefs::CONFIG_EXTENSION)
+      return ::onc::kAugmentationActiveExtension;
+    return is_local_state_config ? ::onc::kAugmentationDevicePolicy
+                                 : ::onc::kAugmentationUserPolicy;
+  }
+
+  // If network is managed, proxy settings should be marked as policy managed,
+  // even if the proxy settings are not set by policy - this reports the
+  // default proxy settings as non-user modifiable.
+  if (onc_source == onc::ONC_SOURCE_USER_POLICY)
+    return ::onc::kAugmentationUserPolicy;
+  if (onc_source == onc::ONC_SOURCE_DEVICE_POLICY)
+    return ::onc::kAugmentationDevicePolicy;
+
+  return std::string();
+}
+
+base::Value CreateEffectiveValue(const std::string& source, base::Value value) {
+  base::Value dict(base::Value::Type::DICTIONARY);
+  dict.SetKey(::onc::kAugmentationEffectiveSetting, base::Value(source));
+  // ActiveExtension is a special source type indicating that the Effective
+  // value is the Active value and was set by an extension. It does not provide
+  // a separate value.
+  if (source != ::onc::kAugmentationActiveExtension) {
+    dict.SetKey(source, value.Clone());
+  }
+  dict.SetKey(::onc::kAugmentationActiveSetting, std::move(value));
+  dict.SetKey(::onc::kAugmentationUserEditable, base::Value(false));
+  return dict;
+}
+
+void SetManualProxy(base::Value* manual,
+                    const std::string& source,
+                    const std::string& key,
+                    const net::ProxyList& proxy_list) {
+  if (proxy_list.IsEmpty()) {
+    manual->SetPath({key, ::onc::proxy::kHost},
+                    CreateEffectiveValue(source, base::Value("")));
+    manual->SetPath({key, ::onc::proxy::kPort},
+                    CreateEffectiveValue(source, base::Value(0)));
+    return;
+  }
+
+  const net::ProxyServer& proxy = proxy_list.Get();
+  manual->SetPath(
+      {key, ::onc::proxy::kHost},
+      CreateEffectiveValue(source, base::Value(proxy.host_port_pair().host())));
+  manual->SetPath(
+      {key, ::onc::proxy::kPort},
+      CreateEffectiveValue(source, base::Value(proxy.host_port_pair().port())));
+}
+
+base::Value OncValueWithMode(const std::string& source,
+                             const std::string& mode) {
+  base::Value result(base::Value::Type::DICTIONARY);
+  result.SetKey(::onc::network_config::kType,
+                CreateEffectiveValue(source, base::Value(mode)));
+  return result;
+}
+
+base::Value OncValueForManualProxyList(
+    const std::string& source,
+    const net::ProxyList& for_http,
+    const net::ProxyList& for_https,
+    const net::ProxyList& for_ftp,
+    const net::ProxyList& fallback,
+    const net::ProxyBypassRules& bypass_rules) {
+  if (for_http.IsEmpty() && for_https.IsEmpty() && for_ftp.IsEmpty() &&
+      fallback.IsEmpty()) {
+    return base::Value();
+  }
+  base::Value result = OncValueWithMode(source, ::onc::proxy::kManual);
+
+  base::Value* manual = result.SetKey(
+      ::onc::proxy::kManual, base::Value(base::Value::Type::DICTIONARY));
+  SetManualProxy(manual, source, ::onc::proxy::kHttp, for_http);
+  SetManualProxy(manual, source, ::onc::proxy::kHttps, for_https);
+  SetManualProxy(manual, source, ::onc::proxy::kFtp, for_ftp);
+  SetManualProxy(manual, source, ::onc::proxy::kSocks, fallback);
+
+  base::Value exclude_domains(base::Value::Type::LIST);
+  for (const auto& rule : bypass_rules.rules())
+    exclude_domains.GetList().emplace_back(rule->ToString());
+  result.SetKey(::onc::proxy::kExcludeDomains,
+                CreateEffectiveValue(source, std::move(exclude_domains)));
+
+  return result;
+}
+
+base::Value OncValueForEmptyProxyRules(const net::ProxyConfig& net_config,
+                                       const std::string& source) {
+  if (!net_config.HasAutomaticSettings()) {
+    return OncValueWithMode(source, ::onc::proxy::kDirect);
+  }
+
+  if (net_config.auto_detect()) {
+    return OncValueWithMode(source, ::onc::proxy::kWPAD);
+  }
+
+  if (net_config.has_pac_url()) {
+    base::Value result = OncValueWithMode(source, ::onc::proxy::kPAC);
+    result.SetKey(
+        ::onc::proxy::kPAC,
+        CreateEffectiveValue(source, base::Value(net_config.pac_url().spec())));
+    return result;
+  }
+
+  return base::Value();
+}
+
+base::Value NetProxyConfigAsOncValue(const net::ProxyConfig& net_config,
+                                     const std::string& source) {
+  switch (net_config.proxy_rules().type) {
+    case net::ProxyConfig::ProxyRules::Type::EMPTY:
+      return OncValueForEmptyProxyRules(net_config, source);
+    case net::ProxyConfig::ProxyRules::Type::PROXY_LIST:
+      return OncValueForManualProxyList(source,
+                                        net_config.proxy_rules().single_proxies,
+                                        net_config.proxy_rules().single_proxies,
+                                        net_config.proxy_rules().single_proxies,
+                                        net_config.proxy_rules().single_proxies,
+                                        net_config.proxy_rules().bypass_rules);
+    case net::ProxyConfig::ProxyRules::Type::PROXY_LIST_PER_SCHEME:
+      return OncValueForManualProxyList(
+          source, net_config.proxy_rules().proxies_for_http,
+          net_config.proxy_rules().proxies_for_https,
+          net_config.proxy_rules().proxies_for_ftp,
+          net_config.proxy_rules().fallback_proxies,
+          net_config.proxy_rules().bypass_rules);
+  }
+  return base::Value();
 }
 
 }  // namespace
@@ -92,37 +209,73 @@
 
 UIProxyConfigService::~UIProxyConfigService() = default;
 
-void UIProxyConfigService::UpdateFromPrefs(const std::string& network_guid) {
+bool UIProxyConfigService::MergeEnforcedProxyConfig(
+    const std::string& network_guid,
+    base::Value* proxy_settings) {
   current_ui_network_guid_ = network_guid;
   const NetworkState* network = nullptr;
-  if (!network_guid.empty()) {
-    network =
-        NetworkHandler::Get()->network_state_handler()->GetNetworkStateFromGuid(
-            network_guid);
-    if (!network) {
-      NET_LOG(ERROR) << "No NetworkState for guid: " << network_guid;
-    } else if (!network->IsNonProfileType() && !network->IsInProfile()) {
-      NET_LOG(ERROR) << "Network not in profile: " << network_guid;
-      network = nullptr;
-    }
-  }
+  DCHECK(!network_guid.empty());
+  DCHECK(proxy_settings->is_dict());
+
+  network =
+      NetworkHandler::Get()->network_state_handler()->GetNetworkStateFromGuid(
+          network_guid);
   if (!network) {
+    NET_LOG(ERROR) << "No NetworkState for guid: " << network_guid;
     current_ui_network_guid_.clear();
-    current_ui_config_ = UIProxyConfig();
-    return;
+    return false;
   }
 
-  DetermineEffectiveConfig(*network);
-  VLOG(1) << "Current ui network: " << network->name() << ", "
-          << ModeToString(current_ui_config_.mode) << ", "
-          << ProxyPrefs::ConfigStateToDebugString(current_ui_config_.state);
-}
+  if (!network->IsNonProfileType() && !network->IsInProfile()) {
+    NET_LOG(ERROR) << "Network not in profile: " << network_guid;
+    current_ui_network_guid_.clear();
+    return false;
+  }
 
-void UIProxyConfigService::GetProxyConfig(const std::string& network_guid,
-                                          UIProxyConfig* config) {
-  if (network_guid != current_ui_network_guid_)
-    UpdateFromPrefs(network_guid);
-  *config = current_ui_config_;
+  // The pref service to read proxy settings that apply to all networks.
+  // Settings from the profile overrule local state.
+  DCHECK(local_state_prefs_);
+  PrefService* top_pref_service =
+      profile_prefs_ ? profile_prefs_ : local_state_prefs_;
+
+  // Get prefs proxy config if available.
+  net::ProxyConfigWithAnnotation pref_config;
+  ProxyPrefs::ConfigState pref_state =
+      ProxyConfigServiceImpl::ReadPrefConfig(top_pref_service, &pref_config);
+
+  // Get network proxy config if available.
+  net::ProxyConfigWithAnnotation network_config;
+  net::ProxyConfigService::ConfigAvailability network_availability =
+      net::ProxyConfigService::CONFIG_UNSET;
+  onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
+  if (chromeos::GetProxyConfig(profile_prefs_, local_state_prefs_, *network,
+                               &network_config, &onc_source)) {
+    // Network is private or shared with user using shared proxies.
+    NET_LOG(EVENT) << "UIProxyConfigService for "
+                   << (profile_prefs_ ? "user" : "login")
+                   << ": using proxy of network: " << network->path();
+    network_availability = net::ProxyConfigService::CONFIG_VALID;
+  }
+
+  // Determine effective proxy config, either from prefs or network.
+  ProxyPrefs::ConfigState effective_config_state;
+  net::ProxyConfigWithAnnotation effective_config;
+  ProxyConfigServiceImpl::GetEffectiveProxyConfig(
+      pref_state, pref_config, network_availability, network_config, false,
+      &effective_config_state, &effective_config);
+
+  const std::string source = EffectiveConfigStateToOncSourceString(
+      effective_config_state, !profile_prefs_, onc_source);
+  if (source.empty())
+    return false;
+
+  base::Value enforced_settings =
+      NetProxyConfigAsOncValue(effective_config.value(), source);
+  if (enforced_settings.is_none())
+    return false;
+
+  proxy_settings->MergeDictionary(&enforced_settings);
+  return true;
 }
 
 bool UIProxyConfigService::HasDefaultNetworkProxyConfigured() {
@@ -139,49 +292,10 @@
           mode == ProxyPrefs::MODE_FIXED_SERVERS);
 }
 
-void UIProxyConfigService::DetermineEffectiveConfig(
-    const NetworkState& network) {
-  DCHECK(local_state_prefs_);
-
-  // The pref service to read proxy settings that apply to all networks.
-  // Settings from the profile overrule local state.
-  PrefService* top_pref_service =
-      profile_prefs_ ? profile_prefs_ : local_state_prefs_;
-
-  // Get prefs proxy config if available.
-  net::ProxyConfigWithAnnotation pref_config;
-  ProxyPrefs::ConfigState pref_state =
-      ProxyConfigServiceImpl::ReadPrefConfig(top_pref_service, &pref_config);
-
-  // Get network proxy config if available.
-  net::ProxyConfigWithAnnotation network_config;
-  net::ProxyConfigService::ConfigAvailability network_availability =
-      net::ProxyConfigService::CONFIG_UNSET;
-  onc::ONCSource onc_source = onc::ONC_SOURCE_NONE;
-  if (chromeos::GetProxyConfig(profile_prefs_, local_state_prefs_, network,
-                               &network_config, &onc_source)) {
-    // Network is private or shared with user using shared proxies.
-    VLOG(1) << this << ": using proxy of network: " << network.path();
-    network_availability = net::ProxyConfigService::CONFIG_VALID;
-  }
-
-  // Determine effective proxy config, either from prefs or network.
-  ProxyPrefs::ConfigState effective_config_state;
-  net::ProxyConfigWithAnnotation effective_config;
-  ProxyConfigServiceImpl::GetEffectiveProxyConfig(
-      pref_state, pref_config, network_availability, network_config, false,
-      &effective_config_state, &effective_config);
-
-  // Store effective proxy into |current_ui_config_|.
-  current_ui_config_.FromNetProxyConfig(effective_config.value());
-  current_ui_config_.state = effective_config_state;
-  if (!ProxyConfigServiceImpl::PrefPrecedes(effective_config_state) &&
-      !IsNetworkProxySettingsEditable(onc_source)) {
-    current_ui_config_.state = ProxyPrefs::CONFIG_POLICY;
-  }
-}
-
 void UIProxyConfigService::OnPreferenceChanged(const std::string& pref_name) {
+  // TODO(tbarzic): Send network update notifications for all networks that
+  //     might be affected by the proxy pref change, not just the last network
+  //     whose properties were fetched.
   if (current_ui_network_guid_.empty())
     return;
   const NetworkState* network =
@@ -189,7 +303,6 @@
           current_ui_network_guid_);
   if (!network)
     return;
-  UpdateFromPrefs(current_ui_network_guid_);
   NetworkHandler::Get()
       ->network_state_handler()
       ->SendUpdateNotificationForNetwork(network->path());
diff --git a/chromeos/network/proxy/ui_proxy_config_service.h b/chromeos/network/proxy/ui_proxy_config_service.h
index 0f5da93..830d6e43 100644
--- a/chromeos/network/proxy/ui_proxy_config_service.h
+++ b/chromeos/network/proxy/ui_proxy_config_service.h
@@ -9,20 +9,21 @@
 
 #include "base/component_export.h"
 #include "base/macros.h"
-#include "chromeos/network/proxy/ui_proxy_config.h"
 #include "components/prefs/pref_change_registrar.h"
 
 class PrefService;
 
+namespace base {
+class Value;
+}
+
 namespace chromeos {
 
-class NetworkState;
-
-// This class provides an interface to the UI for getting and setting a proxy
-// configuration. Primarily this class caches the "current" requested config
-// and populates UIProxyConfig for convenient UI consumption.
-// NOTE: This class must be rebuilt when the logged in profile changes.
-// ALSO NOTE: The provided PrefService instances are used both to retreive proxy
+// This class provides an interface to the UI for getting a network proxy
+// configuration.
+// NOTE: This class must be rebuilt with the primary user's profile prefs when
+// the primary user logs in.
+// ALSO NOTE: The provided PrefService instances are used both to retrieve proxy
 // configurations set by an extension, and for ONC policy information associated
 // with a network. (Per-network proxy configurations are stored in Shill,
 // but ONC policy configuration is stored in PrefService).
@@ -35,35 +36,33 @@
                        PrefService* local_state_prefs);
   ~UIProxyConfigService();
 
-  // Called when ::proxy_config::prefs change or to force an update.
-  void UpdateFromPrefs(const std::string& guid);
-
-  // Called from UI to retrieve the active proxy configuration. This will be,
-  // in highest to lowest priority order:
-  // * A policy enforced proxy associated with |network_guid|.
-  // * A proxy set by an extension in the active PrefService.
-  // * A user specified proxy associated with |network_guid|.
-  void GetProxyConfig(const std::string& network_guid, UIProxyConfig* config);
+  // Generates ONC dictionary for proxy settings enforced for the network, and
+  // writes them to |proxy_settings|. The proxy settings that will be written to
+  // |proxy_settings| will be one of the following (in order of preference):
+  // * A proxy enforced by a user policy (provided by kProxy prefence).
+  // * A proxy set by an extension in the active PrefService (also provided by
+  //   kProxy pref).
+  // * A proxy set by an ONC policy associated with |network_guid|.
+  //
+  // |proxy_settings| is expected to be a dictionary value containing ONC proxy
+  // settings, and will generally contain the proxy settings reported by shill
+  // (which will have user set per-network proxy settings, if they are
+  // available).
+  //
+  // Returns whether |proxy_settings| have been changed.
+  bool MergeEnforcedProxyConfig(const std::string& network_guid,
+                                base::Value* proxy_settings);
 
   // Returns true if there is a default network and it has a proxy configuration
   // with mode == MODE_FIXED_SERVERS.
   bool HasDefaultNetworkProxyConfigured();
 
  private:
-  // Determines effective proxy config based on prefs from config tracker,
-  // |network| and if user is using shared proxies.  The effective config is
-  // stored in |current_ui_config_| but not activated on network stack, and
-  // hence, not picked up by observers.
-  void DetermineEffectiveConfig(const NetworkState& network);
-
   void OnPreferenceChanged(const std::string& pref_name);
 
   // GUID of network used for current_ui_config_.
   std::string current_ui_network_guid_;
 
-  // Proxy configuration for |current_ui_network_guid_|.
-  UIProxyConfig current_ui_config_;
-
   PrefService* profile_prefs_;  // unowned
   PrefChangeRegistrar profile_registrar_;
 
diff --git a/chromeos/network/proxy/ui_proxy_config_service_unittest.cc b/chromeos/network/proxy/ui_proxy_config_service_unittest.cc
new file mode 100644
index 0000000..34e4a382
--- /dev/null
+++ b/chromeos/network/proxy/ui_proxy_config_service_unittest.cc
@@ -0,0 +1,964 @@
+// 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 "chromeos/network/proxy/ui_proxy_config_service.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/json/json_reader.h"
+#include "base/strings/string_util.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/values.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state_test.h"
+#include "components/onc/onc_pref_names.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/proxy_config/pref_proxy_config_tracker_impl.h"
+#include "components/proxy_config/proxy_config_dictionary.h"
+#include "components/proxy_config/proxy_config_pref_names.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+
+namespace chromeos {
+
+namespace {
+
+constexpr char kTestUserWifiGuid[] = "wifi1";
+constexpr char kTestUserWifiConfig[] = R"({
+    "GUID": "wifi1", "Type": "wifi", "Profile": "user_profile_path",
+    "ProxySettings": {"Type": "WPAD"}})";
+
+constexpr char kTestSharedWifiGuid[] = "wifi2";
+constexpr char kTestSharedWifiConfig[] = R"({
+    "GUID": "wifi2", "Type": "wifi", "Profile": "shared_profile_path"})";
+
+constexpr char kTestUnconfiguredWifiGuid[] = "wifi2";
+constexpr char kTestUnconfiguredWifiConfig[] = R"({
+    "GUID": "wifi2", "Type": "wifi"})";
+
+constexpr char kAugmentedOncValueTemplate[] =
+    R"({"Active": $2, "Effective": "$1", "$1": $2, "UserEditable": $3})";
+
+constexpr char kAugmentedOncValueWithUserSettingTemplate[] =
+    R"({"Active": $2, "Effective": "$1", "$1": $2, "UserSetting": $3,
+      "UserEditable": $4})";
+
+std::string UserSettingOncValue(const std::string& value) {
+  return base::ReplaceStringPlaceholders(
+      kAugmentedOncValueTemplate, {"UserSetting", value, "true"}, nullptr);
+}
+
+std::string UserPolicyOncValue(const std::string& value) {
+  return base::ReplaceStringPlaceholders(
+      kAugmentedOncValueTemplate, {"UserPolicy", value, "false"}, nullptr);
+}
+
+std::string DevicePolicyOncValue(const std::string& value) {
+  return base::ReplaceStringPlaceholders(
+      kAugmentedOncValueTemplate, {"DevicePolicy", value, "false"}, nullptr);
+}
+
+std::string ExtensionControlledOncValue(const std::string& value) {
+  return base::ReplaceStringPlaceholders(
+      R"({"Active": $1,"Effective": "ActiveExtension",
+          "UserEditable": false})",
+      {value}, nullptr);
+}
+
+std::string UserPolicyAndUserSettingOncValue(const std::string& policy,
+                                             const std::string& user_setting) {
+  return base::ReplaceStringPlaceholders(
+      kAugmentedOncValueWithUserSettingTemplate,
+      {
+          "UserPolicy",
+          policy,
+          user_setting,
+          "false",
+      },
+      nullptr);
+}
+
+std::string ExtensionControlledAndUserSettingOncValue(
+    const std::string& extension,
+    const std::string& user_setting) {
+  return base::ReplaceStringPlaceholders(
+      R"({"Active": $1,"Effective": "ActiveExtension", "UserSetting": $2,
+          "UserEditable": false})",
+      {extension, user_setting}, nullptr);
+}
+
+}  // namespace
+
+class UIProxyConfigServiceTest : public NetworkStateTest {
+ public:
+  UIProxyConfigServiceTest()
+      : scoped_task_environment_(
+            base::test::ScopedTaskEnvironment::MainThreadType::UI) {
+    PrefProxyConfigTrackerImpl::RegisterProfilePrefs(user_prefs_.registry());
+    PrefProxyConfigTrackerImpl::RegisterPrefs(local_state_.registry());
+    onc::RegisterProfilePrefs(user_prefs_.registry());
+    onc::RegisterPrefs(local_state_.registry());
+  }
+
+  void SetUp() override {
+    DBusThreadManager::Initialize();
+    NetworkStateTest::SetUp();
+    ClearDefaultServices();
+    NetworkHandler::Initialize();
+    ConfigureService(kTestUserWifiConfig);
+    ConfigureService(kTestSharedWifiConfig);
+    ConfigureService(kTestUnconfiguredWifiConfig);
+  }
+
+  void TearDown() override {
+    NetworkHandler::Shutdown();
+
+    ShutdownNetworkState();
+    NetworkStateTest::TearDown();
+
+    DBusThreadManager::Shutdown();
+  }
+
+  ~UIProxyConfigServiceTest() override = default;
+
+  std::unique_ptr<UIProxyConfigService> CreateServiceOffLocalState() {
+    return std::make_unique<UIProxyConfigService>(nullptr, &local_state_);
+  }
+
+  std::unique_ptr<UIProxyConfigService> CreateServiceForUser() {
+    return std::make_unique<UIProxyConfigService>(&user_prefs_, &local_state_);
+  }
+
+ protected:
+  sync_preferences::TestingPrefServiceSyncable user_prefs_;
+  TestingPrefServiceSimple local_state_;
+
+ private:
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+};
+
+TEST_F(UIProxyConfigServiceTest, UnknownNetwork) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_FALSE(service->MergeEnforcedProxyConfig("unkown_network", &config));
+  EXPECT_EQ(base::Value(base::Value::Type::DICTIONARY), config);
+}
+
+TEST_F(UIProxyConfigServiceTest, UserConfigOnly) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_FALSE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+  EXPECT_EQ(base::Value(base::Value::Type::DICTIONARY), config);
+}
+
+TEST_F(UIProxyConfigServiceTest, LocalStatePrefIgnoredForUserService) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  base::Value policy_prefs_config =
+      ProxyConfigDictionary::CreatePacScript("http://pac/script.pac", true);
+  local_state_.SetManagedPref(
+      proxy_config::prefs::kProxy,
+      base::Value::ToUniquePtrValue(std::move(policy_prefs_config)));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_FALSE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+  EXPECT_EQ(base::Value(base::Value::Type::DICTIONARY), config);
+}
+
+TEST_F(UIProxyConfigServiceTest, LocalStatePolicyPrefForDeviceService) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceOffLocalState();
+
+  base::Value policy_prefs_config =
+      ProxyConfigDictionary::CreatePacScript("http://pac/script.pac", true);
+  local_state_.SetManagedPref(
+      proxy_config::prefs::kProxy,
+      base::Value::ToUniquePtrValue(std::move(policy_prefs_config)));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1, "PAC": $2})",
+      {DevicePolicyOncValue(R"("PAC")"),
+       DevicePolicyOncValue(R"("http://pac/script.pac")")},
+      nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest,
+       UserPolicyProxyNotMergedForUnconfiguredNetork) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceOffLocalState();
+
+  base::Value policy_prefs_config =
+      ProxyConfigDictionary::CreatePacScript("http://pac/script.pac", true);
+  user_prefs_.SetManagedPref(
+      proxy_config::prefs::kProxy,
+      base::Value::ToUniquePtrValue(std::move(policy_prefs_config)));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_FALSE(
+      service->MergeEnforcedProxyConfig(kTestUnconfiguredWifiGuid, &config));
+  EXPECT_EQ(base::Value(base::Value::Type::DICTIONARY), config);
+}
+
+TEST_F(UIProxyConfigServiceTest, ExtensionProxyNotMergedForUnconfiguredNetork) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceOffLocalState();
+
+  base::Value extension_prefs_config =
+      ProxyConfigDictionary::CreatePacScript("http://pac/script.pac", true);
+  user_prefs_.SetExtensionPref(
+      proxy_config::prefs::kProxy,
+      base::Value::ToUniquePtrValue(std::move(extension_prefs_config)));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_FALSE(
+      service->MergeEnforcedProxyConfig(kTestUnconfiguredWifiGuid, &config));
+  EXPECT_EQ(base::Value(base::Value::Type::DICTIONARY), config);
+}
+
+TEST_F(UIProxyConfigServiceTest, OncPolicyNotMergedForUnfongiuredNetork) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceOffLocalState();
+
+  const std::string user_onc_config = base::ReplaceStringPlaceholders(
+      R"([{"GUID": "$1", "Type": "WiFi", "ProxySettings": {"Type": "WPAD"}}])",
+      {kTestUnconfiguredWifiGuid}, nullptr);
+  user_prefs_.SetManagedPref(::onc::prefs::kOpenNetworkConfiguration,
+                             base::JSONReader::Read(user_onc_config));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_FALSE(
+      service->MergeEnforcedProxyConfig(kTestUnconfiguredWifiGuid, &config));
+  EXPECT_EQ(base::Value(base::Value::Type::DICTIONARY), config);
+}
+
+TEST_F(UIProxyConfigServiceTest, PacPolicyPref) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  base::Value policy_prefs_config =
+      ProxyConfigDictionary::CreatePacScript("http://pac/script.pac", true);
+  user_prefs_.SetManagedPref(
+      proxy_config::prefs::kProxy,
+      base::Value::ToUniquePtrValue(std::move(policy_prefs_config)));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1, "PAC": $2})",
+      {UserPolicyOncValue(R"("PAC")"),
+       UserPolicyOncValue(R"("http://pac/script.pac")")},
+      nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, AutoDetectPolicyPref) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  base::Value policy_prefs_config = ProxyConfigDictionary::CreateAutoDetect();
+  user_prefs_.SetManagedPref(
+      proxy_config::prefs::kProxy,
+      base::Value::ToUniquePtrValue(std::move(policy_prefs_config)));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1})", {UserPolicyOncValue(R"("WPAD")")}, nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, DirectPolicyPref) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  base::Value policy_prefs_config = ProxyConfigDictionary::CreateDirect();
+  user_prefs_.SetManagedPref(
+      proxy_config::prefs::kProxy,
+      base::Value::ToUniquePtrValue(std::move(policy_prefs_config)));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1})", {UserPolicyOncValue(R"("Direct")")}, nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, ManualPolicyPref) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  base::Value policy_prefs_config = ProxyConfigDictionary::CreateFixedServers(
+      "http=proxy1:81;https=proxy2:81;ftp=proxy3:81;socks=proxy4:81",
+      "localhost");
+  user_prefs_.SetManagedPref(
+      proxy_config::prefs::kProxy,
+      base::Value::ToUniquePtrValue(std::move(policy_prefs_config)));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1,
+          "Manual": {
+            "HTTPProxy": {"Host": $2, "Port": $6},
+            "SecureHTTPProxy": {"Host": $3, "Port": $6},
+            "FTPProxy": {"Host": $4, "Port": $6},
+            "SOCKS": {"Host": $5, "Port": $6}
+          },
+          "ExcludeDomains": $7
+          })",
+      {UserPolicyOncValue(R"("Manual")"), UserPolicyOncValue(R"("proxy1")"),
+       UserPolicyOncValue(R"("proxy2")"), UserPolicyOncValue(R"("proxy3")"),
+       UserPolicyOncValue(R"("proxy4")"), UserPolicyOncValue("81"),
+       UserPolicyOncValue(R"(["localhost"])")},
+      nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, PartialManualPolicyPref) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  base::Value policy_prefs_config = ProxyConfigDictionary::CreateFixedServers(
+      "http=proxy1:81;ftp=proxy3:83;", "");
+  user_prefs_.SetManagedPref(
+      proxy_config::prefs::kProxy,
+      base::Value::ToUniquePtrValue(std::move(policy_prefs_config)));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1,
+          "Manual": {
+            "HTTPProxy": {"Host": $2, "Port": $3},
+            "FTPProxy": {"Host": $4, "Port": $5},
+            "SecureHTTPProxy": {"Host": $6, "Port": $7},
+            "SOCKS": {"Host": $6, "Port": $7}
+          },
+          "ExcludeDomains": $8
+          })",
+      {UserPolicyOncValue(R"("Manual")"), UserPolicyOncValue(R"("proxy1")"),
+       UserPolicyOncValue("81"), UserPolicyOncValue(R"("proxy3")"),
+       UserPolicyOncValue("83"), UserPolicyOncValue(R"("")"),
+       UserPolicyOncValue("0"), UserPolicyOncValue("[]")},
+      nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, ManualPolicyPrefWithPacPreset) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  base::Value policy_prefs_config = ProxyConfigDictionary::CreateFixedServers(
+      "http=proxy:80;https=proxy:80;ftp=proxy:80;socks=proxy:80", "localhost");
+  user_prefs_.SetManagedPref(
+      proxy_config::prefs::kProxy,
+      base::Value::ToUniquePtrValue(std::move(policy_prefs_config)));
+
+  std::string config_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1, "PAC": $2})",
+      {UserSettingOncValue(R"("PAC")"),
+       UserSettingOncValue(R"("http://pac/test.script.pac")")},
+      nullptr);
+  std::unique_ptr<base::Value> config = base::JSONReader::Read(config_json);
+  ASSERT_TRUE(config) << config_json;
+
+  EXPECT_TRUE(
+      service->MergeEnforcedProxyConfig(kTestUserWifiGuid, config.get()));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1,
+          "Manual": {
+            "HTTPProxy": {"Host": $2, "Port": $3},
+            "SecureHTTPProxy": {"Host": $2, "Port": $3},
+            "FTPProxy": {"Host": $2, "Port": $3},
+            "SOCKS": {"Host": $2, "Port": $3}
+          },
+          "PAC": $4,
+          "ExcludeDomains": $5
+         })",
+      {UserPolicyAndUserSettingOncValue(R"("Manual")", R"("PAC")"),
+       UserPolicyOncValue(R"("proxy")"), UserPolicyOncValue("80"),
+       UserSettingOncValue(R"("http://pac/test.script.pac")"),
+       UserPolicyOncValue(R"(["localhost"])")},
+      nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, *config);
+}
+
+TEST_F(UIProxyConfigServiceTest, PacExtensionPref) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  base::Value extension_prefs_config =
+      ProxyConfigDictionary::CreatePacScript("http://pac/script.pac", true);
+  user_prefs_.SetExtensionPref(
+      proxy_config::prefs::kProxy,
+      base::Value::ToUniquePtrValue(std::move(extension_prefs_config)));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1, "PAC": $2})",
+      {ExtensionControlledOncValue(R"("PAC")"),
+       ExtensionControlledOncValue(R"("http://pac/script.pac")")},
+      nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, AutoDetectExtensionPref) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  base::Value extension_prefs_config =
+      ProxyConfigDictionary::CreateAutoDetect();
+  user_prefs_.SetExtensionPref(
+      proxy_config::prefs::kProxy,
+      base::Value::ToUniquePtrValue(std::move(extension_prefs_config)));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1})", {ExtensionControlledOncValue(R"("WPAD")")}, nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, DirectExtensionPref) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  base::Value extension_prefs_config = ProxyConfigDictionary::CreateDirect();
+  user_prefs_.SetExtensionPref(
+      proxy_config::prefs::kProxy,
+      base::Value::ToUniquePtrValue(std::move(extension_prefs_config)));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1})", {ExtensionControlledOncValue(R"("Direct")")}, nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, ManualExtensionPref) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  base::Value extension_prefs_config =
+      ProxyConfigDictionary::CreateFixedServers(
+          "http=proxy1:81;https=proxy2:82;ftp=proxy3:83;socks=proxy4:81",
+          "localhost");
+  user_prefs_.SetExtensionPref(
+      proxy_config::prefs::kProxy,
+      base::Value::ToUniquePtrValue(std::move(extension_prefs_config)));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1,
+          "Manual": {
+            "HTTPProxy": {"Host": $2, "Port": $3},
+            "SecureHTTPProxy": {"Host": $4, "Port": $5},
+            "FTPProxy": {"Host": $6, "Port": $7},
+            "SOCKS": {"Host": $8, "Port": $3}
+          },
+          "ExcludeDomains": $9
+          })",
+      {ExtensionControlledOncValue(R"("Manual")"),
+       ExtensionControlledOncValue(R"("proxy1")"),
+       ExtensionControlledOncValue("81"),
+       ExtensionControlledOncValue(R"("proxy2")"),
+       ExtensionControlledOncValue("82"),
+       ExtensionControlledOncValue(R"("proxy3")"),
+       ExtensionControlledOncValue("83"),
+       ExtensionControlledOncValue(R"("proxy4")"),
+       ExtensionControlledOncValue(R"(["localhost"])")},
+      nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, ExtensionProxyOverridesDefault) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  base::Value extension_prefs_config = ProxyConfigDictionary::CreatePacScript(
+      "http://extension/script.pac", true);
+  user_prefs_.SetExtensionPref(
+      proxy_config::prefs::kProxy,
+      base::Value::ToUniquePtrValue(std::move(extension_prefs_config)));
+
+  std::string config_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1, "PAC": $2})",
+      {UserSettingOncValue(R"("PAC")"),
+       UserSettingOncValue(R"("http://default/script.pac")")},
+      nullptr);
+  std::unique_ptr<base::Value> config = base::JSONReader::Read(config_json);
+  ASSERT_TRUE(config) << config_json;
+
+  EXPECT_TRUE(
+      service->MergeEnforcedProxyConfig(kTestUserWifiGuid, config.get()));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1, "PAC": $2})",
+      {ExtensionControlledAndUserSettingOncValue(R"("PAC")", R"("PAC")"),
+       ExtensionControlledAndUserSettingOncValue(
+           R"("http://extension/script.pac")",
+           R"("http://default/script.pac")")},
+      nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, *config);
+}
+
+TEST_F(UIProxyConfigServiceTest, PolicyPrefOverridesExtensionPref) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  base::Value policy_prefs_config =
+      ProxyConfigDictionary::CreatePacScript("http://managed/script.pac", true);
+  user_prefs_.SetManagedPref(
+      proxy_config::prefs::kProxy,
+      base::Value::ToUniquePtrValue(std::move(policy_prefs_config)));
+
+  base::Value extension_prefs_config =
+      ProxyConfigDictionary::CreateAutoDetect();
+  user_prefs_.SetExtensionPref(
+      proxy_config::prefs::kProxy,
+      base::Value::ToUniquePtrValue(std::move(extension_prefs_config)));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1, "PAC": $2})",
+      {UserPolicyOncValue(R"("PAC")"),
+       UserPolicyOncValue(R"("http://managed/script.pac")")},
+      nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, PolicyPrefForSharedNetwork) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  base::Value policy_prefs_config = ProxyConfigDictionary::CreateAutoDetect();
+  user_prefs_.SetManagedPref(
+      proxy_config::prefs::kProxy,
+      base::Value::ToUniquePtrValue(std::move(policy_prefs_config)));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestSharedWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1})", {UserPolicyOncValue(R"("WPAD")")}, nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, ExtensionPrefForSharedNetwork) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  base::Value extension_prefs_config =
+      ProxyConfigDictionary::CreateAutoDetect();
+  user_prefs_.SetExtensionPref(
+      proxy_config::prefs::kProxy,
+      base::Value::ToUniquePtrValue(std::move(extension_prefs_config)));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestSharedWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1})", {ExtensionControlledOncValue(R"("WPAD")")}, nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, PacOncUserPolicy) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  const std::string onc_config = base::ReplaceStringPlaceholders(
+      R"([{"GUID": "$1", "Type": "WiFi", "ProxySettings": {"Type": "PAC",
+           "PAC": "http://onc/script.pac"}}])",
+      {kTestUserWifiGuid}, nullptr);
+  user_prefs_.SetManagedPref(::onc::prefs::kOpenNetworkConfiguration,
+                             base::JSONReader::Read(onc_config));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1, "PAC": $2})",
+      {UserPolicyOncValue(R"("PAC")"),
+       UserPolicyOncValue(R"("http://onc/script.pac")")},
+      nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, AutoDetectOncUserPolicy) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  const std::string onc_config = base::ReplaceStringPlaceholders(
+      R"([{"GUID": "$1", "Type": "WiFi", "ProxySettings": {"Type": "WPAD"}}])",
+      {kTestUserWifiGuid}, nullptr);
+  user_prefs_.SetManagedPref(::onc::prefs::kOpenNetworkConfiguration,
+                             base::JSONReader::Read(onc_config));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1})", {UserPolicyOncValue(R"("WPAD")")}, nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+// Tests that ONC policy configured networks without proxy settings force Direct
+// connection.
+TEST_F(UIProxyConfigServiceTest, OncUserPolicyWithoutProxySettings) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  const std::string onc_config = base::ReplaceStringPlaceholders(
+      R"([{"GUID": "$1", "Type": "WiFi", "AutoConnect": false}])",
+      {kTestUserWifiGuid}, nullptr);
+  user_prefs_.SetManagedPref(::onc::prefs::kOpenNetworkConfiguration,
+                             base::JSONReader::Read(onc_config));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1})", {UserPolicyOncValue(R"("Direct")")}, nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, DirectOncUserPolicy) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  const std::string onc_config = base::ReplaceStringPlaceholders(
+      R"([{"GUID": "$1", "Type": "WiFi",
+           "ProxySettings": {"Type": "Direct"}}])",
+      {kTestUserWifiGuid}, nullptr);
+  user_prefs_.SetManagedPref(::onc::prefs::kOpenNetworkConfiguration,
+                             base::JSONReader::Read(onc_config));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1})", {UserPolicyOncValue(R"("Direct")")}, nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, ManualOncUserPolicy) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  const std::string onc_config = base::ReplaceStringPlaceholders(
+      R"([{"GUID": "$1", "Type": "WiFi", "ProxySettings": {
+           "Type": "Manual",
+           "ExcludeDomains": ["foo.test", "localhost"],
+           "Manual": {
+             "HTTPProxy": {"Host": "proxy1", "Port": 81},
+             "SecureHTTPProxy": {"Host": "proxy2", "Port": 82},
+             "FTPProxy": {"Host": "proxy3", "Port": 83},
+             "SOCKS": {"Host": "proxy4", "Port": 83}}}}])",
+      {kTestUserWifiGuid}, nullptr);
+  user_prefs_.SetManagedPref(::onc::prefs::kOpenNetworkConfiguration,
+                             base::JSONReader::Read(onc_config));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1,
+          "Manual": {
+            "HTTPProxy": {"Host": $2, "Port": $3},
+            "SecureHTTPProxy": {"Host": $4, "Port": $5},
+            "FTPProxy": {"Host": $6, "Port": $7},
+            "SOCKS": {"Host": $8, "Port": $7}
+          },
+          "ExcludeDomains": $9
+          })",
+      {UserPolicyOncValue(R"("Manual")"), UserPolicyOncValue(R"("proxy1")"),
+       UserPolicyOncValue("81"), UserPolicyOncValue(R"("proxy2")"),
+       UserPolicyOncValue("82"), UserPolicyOncValue(R"("proxy3")"),
+       UserPolicyOncValue("83"), UserPolicyOncValue(R"("proxy4")"),
+       UserPolicyOncValue(R"(["foo.test", "localhost"])")},
+      nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, PartialManualOncUserPolicy) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  const std::string onc_config = base::ReplaceStringPlaceholders(
+      R"([{"GUID": "$1", "Type": "WiFi", "ProxySettings": {
+           "Type": "Manual",
+           "Manual": {
+             "HTTPProxy": {"Host": "proxy1", "Port": 81},
+             "SOCKS": {"Host": "proxy4", "Port": 84}}}}])",
+      {kTestUserWifiGuid}, nullptr);
+  user_prefs_.SetManagedPref(::onc::prefs::kOpenNetworkConfiguration,
+                             base::JSONReader::Read(onc_config));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1,
+          "Manual": {
+            "HTTPProxy": {"Host": $2, "Port": $3},
+            "SOCKS": {"Host": $4, "Port": $5},
+            "SecureHTTPProxy": {"Host": $6, "Port": $7},
+            "FTPProxy": {"Host": $6, "Port": $7}
+          },
+          "ExcludeDomains": $8
+          })",
+      {UserPolicyOncValue(R"("Manual")"), UserPolicyOncValue(R"("proxy1")"),
+       UserPolicyOncValue("81"), UserPolicyOncValue(R"("proxy4")"),
+       UserPolicyOncValue("84"), UserPolicyOncValue(R"("")"),
+       UserPolicyOncValue("0"), UserPolicyOncValue(R"([])")},
+      nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, OncDevicePolicy) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  const std::string onc_config = base::ReplaceStringPlaceholders(
+      R"([{"GUID": "$1", "Type": "WiFi", "ProxySettings": {"Type": "PAC",
+           "PAC": "http://onc/script.pac"}}])",
+      {kTestUserWifiGuid}, nullptr);
+  local_state_.SetManagedPref(::onc::prefs::kDeviceOpenNetworkConfiguration,
+                              base::JSONReader::Read(onc_config));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1, "PAC": $2})",
+      {DevicePolicyOncValue(R"("PAC")"),
+       DevicePolicyOncValue(R"("http://onc/script.pac")")},
+      nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, OncUserPolicyForSharedNetwork) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  const std::string onc_config = base::ReplaceStringPlaceholders(
+      R"([{"GUID": "$1", "Type": "WiFi", "ProxySettings": {"Type": "WPAD"}}])",
+      {kTestSharedWifiGuid}, nullptr);
+  user_prefs_.SetManagedPref(::onc::prefs::kOpenNetworkConfiguration,
+                             base::JSONReader::Read(onc_config));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestSharedWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1})", {UserPolicyOncValue(R"("WPAD")")}, nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, OncDevicePolicyForSharedNetwork) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  const std::string onc_config = base::ReplaceStringPlaceholders(
+      R"([{"GUID": "$1", "Type": "WiFi", "ProxySettings": {"Type": "PAC",
+           "PAC": "http://onc/script.pac"}}])",
+      {kTestSharedWifiGuid}, nullptr);
+  local_state_.SetManagedPref(::onc::prefs::kDeviceOpenNetworkConfiguration,
+                              base::JSONReader::Read(onc_config));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestSharedWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1, "PAC": $2})",
+      {DevicePolicyOncValue(R"("PAC")"),
+       DevicePolicyOncValue(R"("http://onc/script.pac")")},
+      nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, OncUserAndDevicePolicy) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  const std::string user_onc_config = base::ReplaceStringPlaceholders(
+      R"([{"GUID": "$1", "Type": "WiFi", "ProxySettings": {"Type": "WPAD"}}])",
+      {kTestUserWifiGuid}, nullptr);
+  user_prefs_.SetManagedPref(::onc::prefs::kOpenNetworkConfiguration,
+                             base::JSONReader::Read(user_onc_config));
+
+  const std::string device_onc_config = base::ReplaceStringPlaceholders(
+      R"([{"GUID": "$1", "Type": "WiFi", "ProxySettings": {"Type": "PAC",
+           "PAC": "http://onc/script.pac"}}])",
+      {kTestUserWifiGuid}, nullptr);
+  local_state_.SetManagedPref(::onc::prefs::kDeviceOpenNetworkConfiguration,
+                              base::JSONReader::Read(device_onc_config));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1})", {UserPolicyOncValue(R"("WPAD")")}, nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, OncUserAndDevicePolicyBuiltOffLocalState) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceOffLocalState();
+
+  const std::string user_onc_config = base::ReplaceStringPlaceholders(
+      R"([{"GUID": "$1", "Type": "WiFi", "ProxySettings": {"Type": "WPAD"}}])",
+      {kTestUserWifiGuid}, nullptr);
+  user_prefs_.SetManagedPref(::onc::prefs::kOpenNetworkConfiguration,
+                             base::JSONReader::Read(user_onc_config));
+
+  const std::string device_onc_config = base::ReplaceStringPlaceholders(
+      R"([{"GUID": "$1", "Type": "WiFi", "ProxySettings": {"Type": "PAC",
+           "PAC": "http://onc/script.pac"}}])",
+      {kTestUserWifiGuid}, nullptr);
+  local_state_.SetManagedPref(::onc::prefs::kDeviceOpenNetworkConfiguration,
+                              base::JSONReader::Read(device_onc_config));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1, "PAC": $2})",
+      {DevicePolicyOncValue(R"("PAC")"),
+       DevicePolicyOncValue(R"("http://onc/script.pac")")},
+      nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, OncUserPolicyOverridesUserSettings) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  const std::string user_onc_config = base::ReplaceStringPlaceholders(
+      R"([{"GUID": "$1", "Type": "WiFi", "ProxySettings": {"Type": "WPAD"}}])",
+      {kTestUserWifiGuid}, nullptr);
+  user_prefs_.SetManagedPref(::onc::prefs::kOpenNetworkConfiguration,
+                             base::JSONReader::Read(user_onc_config));
+
+  std::string config_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1, "PAC": $2})",
+      {UserSettingOncValue(R"("PAC")"),
+       UserSettingOncValue(R"("http://pac/test.script.pac")")},
+      nullptr);
+  std::unique_ptr<base::Value> config = base::JSONReader::Read(config_json);
+  ASSERT_TRUE(config) << config_json;
+
+  EXPECT_TRUE(
+      service->MergeEnforcedProxyConfig(kTestUserWifiGuid, config.get()));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1, "PAC": $2})",
+      {UserPolicyAndUserSettingOncValue(R"("WPAD")", R"("PAC")"),
+       UserSettingOncValue(R"("http://pac/test.script.pac")")},
+      nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, *config);
+}
+
+TEST_F(UIProxyConfigServiceTest, PolicyPrefOverridesOncPolicy) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  base::Value policy_prefs_config =
+      ProxyConfigDictionary::CreatePacScript("http://pac/script.pac", true);
+  user_prefs_.SetManagedPref(
+      proxy_config::prefs::kProxy,
+      base::Value::ToUniquePtrValue(std::move(policy_prefs_config)));
+
+  const std::string user_onc_config = base::ReplaceStringPlaceholders(
+      R"([{"GUID": "$1", "Type": "WiFi", "ProxySettings": {"Type": "WPAD"}}])",
+      {kTestUserWifiGuid}, nullptr);
+  user_prefs_.SetManagedPref(::onc::prefs::kOpenNetworkConfiguration,
+                             base::JSONReader::Read(user_onc_config));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1, "PAC": $2})",
+      {UserPolicyOncValue(R"("PAC")"),
+       UserPolicyOncValue(R"("http://pac/script.pac")")},
+      nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+TEST_F(UIProxyConfigServiceTest, ExtensionPrefOverridesOncPolicy) {
+  std::unique_ptr<UIProxyConfigService> service = CreateServiceForUser();
+
+  base::Value extension_prefs_config =
+      ProxyConfigDictionary::CreatePacScript("http://pac/script.pac", true);
+  user_prefs_.SetExtensionPref(
+      proxy_config::prefs::kProxy,
+      base::Value::ToUniquePtrValue(std::move(extension_prefs_config)));
+
+  const std::string user_onc_config = base::ReplaceStringPlaceholders(
+      R"([{"GUID": "$1", "Type": "WiFi", "ProxySettings": {"Type": "WPAD"}}])",
+      {kTestUserWifiGuid}, nullptr);
+  user_prefs_.SetManagedPref(::onc::prefs::kOpenNetworkConfiguration,
+                             base::JSONReader::Read(user_onc_config));
+
+  base::Value config(base::Value::Type::DICTIONARY);
+  EXPECT_TRUE(service->MergeEnforcedProxyConfig(kTestUserWifiGuid, &config));
+
+  std::string expected_json = base::ReplaceStringPlaceholders(
+      R"({"Type": $1, "PAC": $2})",
+      {ExtensionControlledOncValue(R"("PAC")"),
+       ExtensionControlledOncValue(R"("http://pac/script.pac")")},
+      nullptr);
+  std::unique_ptr<base::Value> expected = base::JSONReader::Read(expected_json);
+  ASSERT_TRUE(expected) << expected_json;
+  EXPECT_EQ(*expected, config);
+}
+
+}  // namespace chromeos
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.cc b/chromeos/services/assistant/assistant_manager_service_impl.cc
index 0627762..42c0a74 100644
--- a/chromeos/services/assistant/assistant_manager_service_impl.cc
+++ b/chromeos/services/assistant/assistant_manager_service_impl.cc
@@ -103,8 +103,8 @@
     : media_session_(std::make_unique<AssistantMediaSession>(connector)),
       action_module_(std::make_unique<action::CrosActionModule>(
           this,
-          base::FeatureList::IsEnabled(
-              assistant::features::kAssistantAppSupport))),
+          assistant::features::IsAppSupportEnabled(),
+          assistant::features::IsRoutinesEnabled())),
       chromium_api_delegate_(service->io_task_runner()),
       display_connection_(std::make_unique<CrosDisplayConnection>(this)),
       assistant_settings_manager_(
@@ -873,6 +873,9 @@
                       service_->assistant_state()->locale().value(),
                       spoken_feedback_enabled_);
 
+  internal_options->SetClientControlEnabled(
+      assistant::features::IsRoutinesEnabled());
+
   if (base::FeatureList::IsEnabled(assistant::features::kAssistantVoiceMatch) &&
       assistant_settings_manager_->speaker_id_enrollment_done()) {
     internal_options->EnableRequireVoiceMatchVerification();
diff --git a/chromeos/services/assistant/public/features.cc b/chromeos/services/assistant/public/features.cc
index 5009cc7..73b4ad8 100644
--- a/chromeos/services/assistant/public/features.cc
+++ b/chromeos/services/assistant/public/features.cc
@@ -19,6 +19,9 @@
 const base::Feature kAssistantAppSupport{"AssistantAppSupport",
                                          base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kAssistantRoutines{"AssistantRoutines",
+                                       base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kInAssistantNotifications{
     "InAssistantNotifications", base::FEATURE_DISABLED_BY_DEFAULT};
 
@@ -38,14 +41,23 @@
 const base::Feature kTimerTicks{"ChromeOSAssistantTimerTicks",
                                 base::FEATURE_DISABLED_BY_DEFAULT};
 
-bool IsInAssistantNotificationsEnabled() {
-  return base::FeatureList::IsEnabled(kInAssistantNotifications);
+bool IsAppSupportEnabled() {
+  return base::FeatureList::IsEnabled(
+      assistant::features::kAssistantAppSupport);
 }
 
 bool IsDspHotwordEnabled() {
   return base::FeatureList::IsEnabled(kEnableDspHotword);
 }
 
+bool IsInAssistantNotificationsEnabled() {
+  return base::FeatureList::IsEnabled(kInAssistantNotifications);
+}
+
+bool IsRoutinesEnabled() {
+  return base::FeatureList::IsEnabled(kAssistantRoutines);
+}
+
 bool IsStereoAudioInputEnabled() {
   return base::FeatureList::IsEnabled(kEnableStereoAudioInput);
 }
diff --git a/chromeos/services/assistant/public/features.h b/chromeos/services/assistant/public/features.h
index 379645b3..9fa407a 100644
--- a/chromeos/services/assistant/public/features.h
+++ b/chromeos/services/assistant/public/features.h
@@ -24,6 +24,10 @@
 COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC)
 extern const base::Feature kAssistantAppSupport;
 
+// Enables Assistant routines.
+COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC)
+extern const base::Feature kAssistantRoutines;
+
 // Enables in-Assistant notifications.
 COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC)
 extern const base::Feature kInAssistantNotifications;
@@ -48,10 +52,14 @@
 COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC)
 extern const base::Feature kTimerTicks;
 
+COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsAppSupportEnabled();
+
+COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsDspHotwordEnabled();
+
 COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC)
 bool IsInAssistantNotificationsEnabled();
 
-COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsDspHotwordEnabled();
+COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsRoutinesEnabled();
 
 COMPONENT_EXPORT(ASSISTANT_SERVICE_PUBLIC) bool IsStereoAudioInputEnabled();
 
diff --git a/components/autofill/core/browser/autofill_data_model.cc b/components/autofill/core/browser/autofill_data_model.cc
index dd580ec..a5e96ec 100644
--- a/components/autofill/core/browser/autofill_data_model.cc
+++ b/components/autofill/core/browser/autofill_data_model.cc
@@ -80,4 +80,10 @@
   return use_date_ < AutofillClock::Now() - kDisusedDataModelDeletionTimeDelta;
 }
 
+AutofillDataModel::ValidityState AutofillDataModel::GetValidityState(
+    ServerFieldType type,
+    AutofillDataModel::ValidationSource source) const {
+  return AutofillDataModel::UNSUPPORTED;
+}
+
 }  // namespace autofill
diff --git a/components/autofill/core/browser/autofill_data_model.h b/components/autofill/core/browser/autofill_data_model.h
index a6d005ae..3a543f9 100644
--- a/components/autofill/core/browser/autofill_data_model.h
+++ b/components/autofill/core/browser/autofill_data_model.h
@@ -22,6 +22,26 @@
 // PersonalDataManager.
 class AutofillDataModel : public FormGroup {
  public:
+  enum ValidityState {
+    // The field has not been validated.
+    UNVALIDATED = 0,
+    // The field is empty.
+    EMPTY = 1,
+    // The field is valid.
+    VALID = 2,
+    // The field is invalid.
+    INVALID = 3,
+    // The validation for the field is unsupported.
+    UNSUPPORTED = 4,
+  };
+
+  enum ValidationSource {
+    // The validity state is according to the client validation.
+    CLIENT = 0,
+    // The validity state is according to the server validation.
+    SERVER = 1,
+  };
+
   AutofillDataModel(const std::string& guid, const std::string& origin);
   ~AutofillDataModel() override;
 
@@ -70,6 +90,10 @@
   // longer than |kDisusedCreditCardDeletionTimeDelta|.
   virtual bool IsDeletable() const;
 
+  // Returns the validity state of the specified autofill type.
+  virtual ValidityState GetValidityState(ServerFieldType type,
+                                         ValidationSource source) const;
+
  protected:
   // Called to update |use_count_| and |use_date_| when this data model is
   // the subject of user interaction (usually, when it's used to fill a form).
diff --git a/components/autofill/core/browser/autofill_field.cc b/components/autofill/core/browser/autofill_field.cc
index e0eb40c..afc5e7c 100644
--- a/components/autofill/core/browser/autofill_field.cc
+++ b/components/autofill/core/browser/autofill_field.cc
@@ -6,8 +6,6 @@
 
 #include <stdint.h>
 
-#include <utility>
-
 #include "base/feature_list.h"
 #include "base/strings/string_number_conversions.h"
 #include "components/autofill/core/browser/field_types.h"
@@ -73,18 +71,17 @@
 }
 
 void AutofillField::add_possible_types_validities(
-    const std::map<ServerFieldType, AutofillProfile::ValidityState>&
-        possible_types_validities) {
+    const ServerFieldTypeValidityStateMap& possible_types_validities) {
   for (const auto& possible_type_validity : possible_types_validities) {
     possible_types_validities_[possible_type_validity.first].push_back(
         possible_type_validity.second);
   }
 }
 
-std::vector<AutofillProfile::ValidityState>
+std::vector<AutofillDataModel::ValidityState>
 AutofillField::get_validities_for_possible_type(ServerFieldType type) {
   if (possible_types_validities_.find(type) == possible_types_validities_.end())
-    return {AutofillProfile::UNVALIDATED};
+    return {AutofillDataModel::UNVALIDATED};
   return possible_types_validities_[type];
 }
 
@@ -187,7 +184,7 @@
   for (const auto& possible_type : possible_types_) {
     if (possible_types_validities_[possible_type].empty()) {
       possible_types_validities_[possible_type].push_back(
-          AutofillProfile::UNVALIDATED);
+          AutofillDataModel::UNVALIDATED);
     }
   }
 }
diff --git a/components/autofill/core/browser/autofill_field.h b/components/autofill/core/browser/autofill_field.h
index 8b565fb..b7f9069 100644
--- a/components/autofill/core/browser/autofill_field.h
+++ b/components/autofill/core/browser/autofill_field.h
@@ -7,7 +7,10 @@
 
 #include <stddef.h>
 
+#include <map>
 #include <string>
+#include <utility>
+#include <vector>
 
 #include "base/macros.h"
 #include "base/optional.h"
@@ -22,9 +25,12 @@
 
 namespace autofill {
 
-typedef std::map<ServerFieldType, std::vector<AutofillProfile::ValidityState>>
+typedef std::map<ServerFieldType, std::vector<AutofillDataModel::ValidityState>>
     ServerFieldTypeValidityStatesMap;
 
+typedef std::map<ServerFieldType, AutofillDataModel::ValidityState>
+    ServerFieldTypeValidityStateMap;
+
 class AutofillField : public FormFieldData {
  public:
   enum PhonePart {
@@ -60,8 +66,7 @@
   void set_heuristic_type(ServerFieldType type);
   void set_server_type(ServerFieldType type);
   void add_possible_types_validities(
-      const std::map<ServerFieldType, AutofillProfile::ValidityState>&
-          possible_types_validities);
+      const ServerFieldTypeValidityStateMap& possible_types_validities);
   void set_server_predictions(
       const std::vector<AutofillQueryResponseContents::Field::FieldPrediction>
           predictions) {
@@ -74,8 +79,8 @@
       const ServerFieldTypeValidityStatesMap& possible_types_validities) {
     possible_types_validities_ = possible_types_validities;
   }
-  std::vector<AutofillProfile::ValidityState> get_validities_for_possible_type(
-      ServerFieldType);
+  std::vector<AutofillDataModel::ValidityState>
+      get_validities_for_possible_type(ServerFieldType);
 
   void SetHtmlType(HtmlFieldType type, HtmlFieldMode mode);
   void set_previously_autofilled(bool previously_autofilled) {
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index 77edb59..984768d 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -1819,8 +1819,7 @@
     base::TrimWhitespace(field->value, base::TRIM_ALL, &value);
 
     for (const AutofillProfile& profile : profiles) {
-      std::map<ServerFieldType, AutofillProfile::ValidityState>
-          matching_types_validities;
+      ServerFieldTypeValidityStateMap matching_types_validities;
       profile.GetMatchingTypesAndValidities(value, app_locale, &matching_types,
                                             &matching_types_validities);
       field->add_possible_types_validities(matching_types_validities);
@@ -1833,9 +1832,8 @@
 
     if (matching_types.empty()) {
       matching_types.insert(UNKNOWN_TYPE);
-      std::map<ServerFieldType, AutofillProfile::ValidityState>
-          matching_types_validities;
-      matching_types_validities[UNKNOWN_TYPE] = AutofillProfile::UNVALIDATED;
+      ServerFieldTypeValidityStateMap matching_types_validities;
+      matching_types_validities[UNKNOWN_TYPE] = AutofillDataModel::UNVALIDATED;
       field->add_possible_types_validities(matching_types_validities);
     }
 
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc
index 5749edf..de8b4839 100644
--- a/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -8,6 +8,7 @@
 
 #include <algorithm>
 #include <memory>
+#include <tuple>
 #include <utility>
 #include <vector>
 
@@ -4423,8 +4424,8 @@
     : public AutofillManagerTest,
       public ::testing::WithParamInterface<
           std::tuple<ProfileMatchingTypesTestCase,
-                     int,        // AutofillProfile::ValidityState
-                     bool>> {};  // AutofillProfile::ValidationSource
+                     int,        // AutofillDataModel::ValidityState
+                     bool>> {};  // AutofillDataModel::ValidationSource
 
 const ProfileMatchingTypesTestCase kProfileMatchingTypesTestCases[] = {
     // Profile fields matches.
@@ -4518,9 +4519,9 @@
   // Unpack the test paramters
   const auto& test_case = std::get<0>(GetParam());
   auto validity_state =
-      static_cast<AutofillProfile::ValidityState>(std::get<1>(GetParam()));
+      static_cast<AutofillDataModel::ValidityState>(std::get<1>(GetParam()));
   const auto& validation_source =
-      static_cast<AutofillProfile::ValidationSource>(std::get<2>(GetParam()));
+      static_cast<AutofillDataModel::ValidationSource>(std::get<2>(GetParam()));
 
   SCOPED_TRACE(base::StringPrintf(
       "Test: input_value='%s', field_type=%s, validity_state=%d, "
@@ -4529,8 +4530,8 @@
       AutofillType(test_case.field_type).ToString().c_str(), validity_state,
       validation_source));
 
-  ASSERT_LE(AutofillProfile::UNVALIDATED, validity_state);
-  ASSERT_LE(validity_state, AutofillProfile::UNSUPPORTED);
+  ASSERT_LE(AutofillDataModel::UNVALIDATED, validity_state);
+  ASSERT_LE(validity_state, AutofillDataModel::UNSUPPORTED);
 
   // Set up the test profiles.
   std::vector<AutofillProfile> profiles;
@@ -4557,11 +4558,11 @@
     for (auto& profile : profiles) {
       if (test_case.field_type == UNKNOWN_TYPE) {
         // An UNKNOWN type is always UNVALIDATED
-        validity_state = AutofillProfile::UNVALIDATED;
+        validity_state = AutofillDataModel::UNVALIDATED;
       } else if (profile.IsAnInvalidPhoneNumber(test_case.field_type)) {
         // a phone field is a compound field, an invalid part would make it
         // invalid.
-        validity_state = AutofillProfile::INVALID;
+        validity_state = AutofillDataModel::INVALID;
       }
       profile.SetValidityState(test_case.field_type, validity_state,
                                validation_source);
@@ -4606,9 +4607,9 @@
     EXPECT_NE(possible_types_validities.end(),
               possible_types_validities.find(test_case.field_type));
     EXPECT_EQ(possible_types_validities[test_case.field_type][0],
-              (validation_source == AutofillProfile::SERVER)
+              (validation_source == AutofillDataModel::SERVER)
                   ? validity_state
-                  : AutofillProfile::UNVALIDATED);
+                  : AutofillDataModel::UNVALIDATED);
   }
 }
 
@@ -4617,8 +4618,8 @@
     ProfileMatchingTypesTest,
     testing::Combine(
         testing::ValuesIn(kProfileMatchingTypesTestCases),
-        testing::Range(static_cast<int>(AutofillProfile::UNVALIDATED),
-                       static_cast<int>(AutofillProfile::UNSUPPORTED) + 1),
+        testing::Range(static_cast<int>(AutofillDataModel::UNVALIDATED),
+                       static_cast<int>(AutofillDataModel::UNSUPPORTED) + 1),
         testing::Bool()));
 
 // Tests that DeterminePossibleFieldTypesForUpload is called when a form is
@@ -4684,8 +4685,8 @@
                          "", "Memphis", "Tennessee", "38116", "US",
                          "(234) 567-8901");
     profile.set_guid("00000000-0000-0000-0000-000000000001");
-    profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::VALID,
-                             AutofillProfile::SERVER);
+    profile.SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::VALID,
+                             AutofillDataModel::SERVER);
     profiles.push_back(profile);
   }
   {
@@ -4694,8 +4695,8 @@
                          "1331 W Georgia", "", "Vancouver", "Tennessee",
                          "V4D 4S4", "CA", "(778) 567-8901");
     profile.set_guid("00000000-0000-0000-0000-000000000002");
-    profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::INVALID,
-                             AutofillProfile::SERVER);
+    profile.SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::INVALID,
+                             AutofillDataModel::SERVER);
     profiles.push_back(profile);
   }
 
@@ -4703,7 +4704,7 @@
   typedef struct {
     std::string input_value;
     ServerFieldType field_type;
-    std::vector<AutofillProfile::ValidityState> expected_validity_states;
+    std::vector<AutofillDataModel::ValidityState> expected_validity_states;
   } TestFieldData;
 
   std::vector<TestFieldData> test_cases[3];
@@ -4712,16 +4713,18 @@
   // possible_field_types would only include the type ADDRESS_HOME_STATE, and
   // the corresponding validity of that type would include both VALID and
   // INVALID.
-  test_cases[0].push_back({"Tennessee",
-                           ADDRESS_HOME_STATE,
-                           {AutofillProfile::VALID, AutofillProfile::INVALID}});
+  test_cases[0].push_back(
+      {"Tennessee",
+       ADDRESS_HOME_STATE,
+       {AutofillDataModel::VALID, AutofillDataModel::INVALID}});
   // Alice appears only in the second profile as a NAME_FIRST, and it's
   // UNVALIDATED.
   test_cases[1].push_back(
-      {"Alice", NAME_FIRST, {AutofillProfile::UNVALIDATED}});
+      {"Alice", NAME_FIRST, {AutofillDataModel::UNVALIDATED}});
   // An UNKNOWN type is always UNVALIDATED.
-  test_cases[2].push_back(
-      {"What a beautiful day!", UNKNOWN_TYPE, {AutofillProfile::UNVALIDATED}});
+  test_cases[2].push_back({"What a beautiful day!",
+                           UNKNOWN_TYPE,
+                           {AutofillDataModel::UNVALIDATED}});
 
   for (const std::vector<TestFieldData>& test_fields : test_cases) {
     FormData form;
diff --git a/components/autofill/core/browser/autofill_profile.cc b/components/autofill/core/browser/autofill_profile.cc
index cffe334..ab576415 100644
--- a/components/autofill/core/browser/autofill_profile.cc
+++ b/components/autofill/core/browser/autofill_profile.cc
@@ -337,8 +337,7 @@
     const base::string16& text,
     const std::string& app_locale,
     ServerFieldTypeSet* matching_types,
-    std::map<ServerFieldType, AutofillProfile::ValidityState>*
-        matching_types_validities) const {
+    ServerFieldTypeValidityStateMap* matching_types_validities) const {
   if (!matching_types && !matching_types_validities)
     return;
 
@@ -892,7 +891,7 @@
   return false;
 }
 
-AutofillProfile::ValidityState AutofillProfile::GetValidityState(
+AutofillDataModel::ValidityState AutofillProfile::GetValidityState(
     ServerFieldType type,
     ValidationSource validation_source) const {
   if (validation_source == CLIENT) {
diff --git a/components/autofill/core/browser/autofill_profile.h b/components/autofill/core/browser/autofill_profile.h
index ff02d24..716f726e 100644
--- a/components/autofill/core/browser/autofill_profile.h
+++ b/components/autofill/core/browser/autofill_profile.h
@@ -9,6 +9,7 @@
 
 #include <iosfwd>
 #include <list>
+#include <map>
 #include <string>
 #include <vector>
 
@@ -40,26 +41,6 @@
     SERVER_PROFILE,
   };
 
-  enum ValidityState {
-    // The field has not been validated.
-    UNVALIDATED = 0,
-    // The field is empty.
-    EMPTY = 1,
-    // The field is valid.
-    VALID = 2,
-    // The field is invalid.
-    INVALID = 3,
-    // The validation for the field is unsupported.
-    UNSUPPORTED = 4,
-  };
-
-  enum ValidationSource {
-    // The validity state is according to the client validation.
-    CLIENT = 0,
-    // The validity state is according to the server validation.
-    SERVER = 1,
-  };
-
   AutofillProfile(const std::string& guid, const std::string& origin);
 
   // Server profile constructor. The type must be SERVER_PROFILE (this serves
@@ -253,7 +234,7 @@
 
   // Returns the validity state of the specified autofill type.
   ValidityState GetValidityState(ServerFieldType type,
-                                 ValidationSource source) const;
+                                 ValidationSource source) const override;
 
   // Sets the validity state of the specified autofill type.
   // This should only be called from autofill profile validtion API or in tests.
diff --git a/components/autofill/core/browser/autofill_profile_unittest.cc b/components/autofill/core/browser/autofill_profile_unittest.cc
index f1b3303..6320fe08 100644
--- a/components/autofill/core/browser/autofill_profile_unittest.cc
+++ b/components/autofill/core/browser/autofill_profile_unittest.cc
@@ -1058,7 +1058,7 @@
   AutofillProfile b = a;
   b.SetRawInfo(NAME_FIRST, UTF8ToUTF16("Märion"));
   b.SetRawInfo(NAME_MIDDLE, UTF8ToUTF16("Mitchéll"));
-  b.SetRawInfo(NAME_LAST,UTF8ToUTF16("Morrison"));
+  b.SetRawInfo(NAME_LAST, UTF8ToUTF16("Morrison"));
   b.SetRawInfo(NAME_FULL, UTF8ToUTF16(""));
 
   EXPECT_TRUE(a.SaveAdditionalInfo(b, "en-US"));
@@ -1130,7 +1130,8 @@
   {
     AutofillProfile profile;
     profile.SetValidityState(PHONE_HOME_CITY_AND_NUMBER,
-                             AutofillProfile::INVALID, AutofillProfile::CLIENT);
+                             AutofillDataModel::INVALID,
+                             AutofillDataModel::CLIENT);
 
     // It's based on the server side validation.
     EXPECT_EQ(false, profile.IsAnInvalidPhoneNumber(ADDRESS_HOME_LINE1));
@@ -1144,8 +1145,8 @@
 
   {
     AutofillProfile profile;
-    profile.SetValidityState(PHONE_HOME_CITY_CODE, AutofillProfile::INVALID,
-                             AutofillProfile::SERVER);
+    profile.SetValidityState(PHONE_HOME_CITY_CODE, AutofillDataModel::INVALID,
+                             AutofillDataModel::SERVER);
     EXPECT_EQ(false, profile.IsAnInvalidPhoneNumber(ADDRESS_HOME_LINE2));
 
     EXPECT_EQ(true, profile.IsAnInvalidPhoneNumber(PHONE_HOME_NUMBER));
@@ -1157,7 +1158,8 @@
   {
     AutofillProfile profile;
     profile.SetValidityState(PHONE_BILLING_COUNTRY_CODE,
-                             AutofillProfile::INVALID, AutofillProfile::SERVER);
+                             AutofillDataModel::INVALID,
+                             AutofillDataModel::SERVER);
     EXPECT_EQ(false, profile.IsAnInvalidPhoneNumber(ADDRESS_HOME_LINE2));
 
     EXPECT_EQ(false, profile.IsAnInvalidPhoneNumber(PHONE_HOME_NUMBER));
@@ -1167,8 +1169,8 @@
   }
   {
     AutofillProfile profile;
-    profile.SetValidityState(PHONE_BILLING_NUMBER, AutofillProfile::EMPTY,
-                             AutofillProfile::SERVER);
+    profile.SetValidityState(PHONE_BILLING_NUMBER, AutofillDataModel::EMPTY,
+                             AutofillDataModel::SERVER);
     EXPECT_EQ(false, profile.IsAnInvalidPhoneNumber(PHONE_HOME_CITY_CODE));
 
     EXPECT_EQ(false, profile.IsAnInvalidPhoneNumber(PHONE_HOME_NUMBER));
@@ -1179,8 +1181,9 @@
   }
   {
     AutofillProfile profile;
-    profile.SetValidityState(PHONE_BILLING_WHOLE_NUMBER, AutofillProfile::VALID,
-                             AutofillProfile::SERVER);
+    profile.SetValidityState(PHONE_BILLING_WHOLE_NUMBER,
+                             AutofillDataModel::VALID,
+                             AutofillDataModel::SERVER);
     EXPECT_EQ(false,
               profile.IsAnInvalidPhoneNumber(PHONE_BILLING_COUNTRY_CODE));
 
@@ -1196,26 +1199,26 @@
   AutofillProfile profile;
 
   // The default validity state should be UNVALIDATED.
-  EXPECT_EQ(
-      AutofillProfile::UNVALIDATED,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillDataModel::UNVALIDATED,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
 
   // Make sure setting the validity state works.
-  profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::VALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
-  profile.SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::INVALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
-  profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::EMPTY,
-                           AutofillProfile::AutofillProfile::CLIENT);
-  EXPECT_EQ(AutofillProfile::VALID,
+  profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID,
+                           AutofillDataModel::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::INVALID,
+                           AutofillDataModel::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::EMPTY,
+                           AutofillDataModel::CLIENT);
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(ADDRESS_HOME_COUNTRY,
-                                     AutofillProfile::AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::INVALID,
-            profile.GetValidityState(ADDRESS_HOME_CITY,
-                                     AutofillProfile::AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::EMPTY,
-            profile.GetValidityState(ADDRESS_HOME_STATE,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
+  EXPECT_EQ(
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(
+      AutofillDataModel::EMPTY,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_FALSE(profile.IsValidByClient());
 }
 
@@ -1224,26 +1227,26 @@
   EXPECT_TRUE(test::GetFullProfile().IsValidByServer());
 
   // The default validity state should be UNVALIDATED.
-  EXPECT_EQ(
-      AutofillProfile::UNVALIDATED,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::SERVER));
+  EXPECT_EQ(AutofillDataModel::UNVALIDATED,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::SERVER));
 
   // Make sure setting the validity state works.
-  profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::VALID,
-                           AutofillProfile::AutofillProfile::SERVER);
-  profile.SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::INVALID,
-                           AutofillProfile::AutofillProfile::SERVER);
-  profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::EMPTY,
-                           AutofillProfile::AutofillProfile::SERVER);
-  EXPECT_EQ(AutofillProfile::VALID,
+  profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID,
+                           AutofillDataModel::SERVER);
+  profile.SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::INVALID,
+                           AutofillDataModel::SERVER);
+  profile.SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::EMPTY,
+                           AutofillDataModel::SERVER);
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(ADDRESS_HOME_COUNTRY,
-                                     AutofillProfile::AutofillProfile::SERVER));
-  EXPECT_EQ(AutofillProfile::INVALID,
-            profile.GetValidityState(ADDRESS_HOME_CITY,
-                                     AutofillProfile::AutofillProfile::SERVER));
-  EXPECT_EQ(AutofillProfile::EMPTY,
-            profile.GetValidityState(ADDRESS_HOME_STATE,
-                                     AutofillProfile::AutofillProfile::SERVER));
+                                     AutofillDataModel::SERVER));
+  EXPECT_EQ(
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::SERVER));
+  EXPECT_EQ(
+      AutofillDataModel::EMPTY,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::SERVER));
   EXPECT_FALSE(profile.IsValidByServer());
 }
 
@@ -1252,26 +1255,26 @@
 
   // The validity state of unsupported types should be UNSUPPORTED.
   EXPECT_EQ(
-      AutofillProfile::UNSUPPORTED,
-      profile.GetValidityState(ADDRESS_HOME_LINE1, AutofillProfile::CLIENT));
+      AutofillDataModel::UNSUPPORTED,
+      profile.GetValidityState(ADDRESS_HOME_LINE1, AutofillDataModel::CLIENT));
 
   // Make sure setting the validity state of an unsupported type does nothing.
-  profile.SetValidityState(ADDRESS_HOME_LINE1, AutofillProfile::VALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
-  profile.SetValidityState(ADDRESS_HOME_LINE2, AutofillProfile::INVALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_LINE1, AutofillDataModel::VALID,
+                           AutofillDataModel::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_LINE2, AutofillDataModel::INVALID,
+                           AutofillDataModel::CLIENT);
   profile.SetValidityState(PHONE_HOME_CITY_AND_NUMBER,
-                           AutofillProfile::UNVALIDATED,
-                           AutofillProfile::AutofillProfile::CLIENT);
-  EXPECT_EQ(AutofillProfile::UNSUPPORTED,
-            profile.GetValidityState(ADDRESS_HOME_LINE1,
-                                     AutofillProfile::AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::UNSUPPORTED,
-            profile.GetValidityState(ADDRESS_HOME_LINE2,
-                                     AutofillProfile::AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::UNVALIDATED,
+                           AutofillDataModel::UNVALIDATED,
+                           AutofillDataModel::CLIENT);
+  EXPECT_EQ(
+      AutofillDataModel::UNSUPPORTED,
+      profile.GetValidityState(ADDRESS_HOME_LINE1, AutofillDataModel::CLIENT));
+  EXPECT_EQ(
+      AutofillDataModel::UNSUPPORTED,
+      profile.GetValidityState(ADDRESS_HOME_LINE2, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::UNVALIDATED,
             profile.GetValidityState(PHONE_HOME_CITY_AND_NUMBER,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 }
 
 TEST(AutofillProfileTest, GetClientValidityBitfieldValue_Country) {
@@ -1281,18 +1284,18 @@
   // bitfield value should be empty.
   EXPECT_EQ(0, profile.GetClientValidityBitfieldValue());
 
-  profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::EMPTY,
-                           AutofillProfile::AutofillProfile::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::EMPTY,
+                           AutofillDataModel::CLIENT);
   // 0b01
   EXPECT_EQ(1, profile.GetClientValidityBitfieldValue());
 
-  profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::VALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID,
+                           AutofillDataModel::CLIENT);
   // 0b10
   EXPECT_EQ(2, profile.GetClientValidityBitfieldValue());
 
-  profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::INVALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::INVALID,
+                           AutofillDataModel::CLIENT);
   // 0b11
   EXPECT_EQ(3, profile.GetClientValidityBitfieldValue());
 }
@@ -1304,18 +1307,18 @@
   // bitfield value should be empty.
   EXPECT_EQ(0, profile.GetClientValidityBitfieldValue());
 
-  profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::EMPTY,
-                           AutofillProfile::AutofillProfile::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::EMPTY,
+                           AutofillDataModel::CLIENT);
   // 0b0100
   EXPECT_EQ(4, profile.GetClientValidityBitfieldValue());
 
-  profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::VALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::VALID,
+                           AutofillDataModel::CLIENT);
   // 0b1000
   EXPECT_EQ(8, profile.GetClientValidityBitfieldValue());
 
-  profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::INVALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::INVALID,
+                           AutofillDataModel::CLIENT);
   // 0b1100
   EXPECT_EQ(12, profile.GetClientValidityBitfieldValue());
 }
@@ -1327,18 +1330,18 @@
   // bitfield value should be empty.
   EXPECT_EQ(0, profile.GetClientValidityBitfieldValue());
 
-  profile.SetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::EMPTY,
-                           AutofillProfile::AutofillProfile::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::EMPTY,
+                           AutofillDataModel::CLIENT);
   // 0b010000
   EXPECT_EQ(16, profile.GetClientValidityBitfieldValue());
 
-  profile.SetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::VALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::VALID,
+                           AutofillDataModel::CLIENT);
   // 0b100000
   EXPECT_EQ(32, profile.GetClientValidityBitfieldValue());
 
-  profile.SetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::INVALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::INVALID,
+                           AutofillDataModel::CLIENT);
   // 0b110000
   EXPECT_EQ(48, profile.GetClientValidityBitfieldValue());
 }
@@ -1350,18 +1353,18 @@
   // bitfield value should be empty.
   EXPECT_EQ(0, profile.GetClientValidityBitfieldValue());
 
-  profile.SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::EMPTY,
-                           AutofillProfile::AutofillProfile::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::EMPTY,
+                           AutofillDataModel::CLIENT);
   // 0b01000000
   EXPECT_EQ(64, profile.GetClientValidityBitfieldValue());
 
-  profile.SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::VALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::VALID,
+                           AutofillDataModel::CLIENT);
   // 0b10000000
   EXPECT_EQ(128, profile.GetClientValidityBitfieldValue());
 
-  profile.SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::INVALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::INVALID,
+                           AutofillDataModel::CLIENT);
   // 0b11000000
   EXPECT_EQ(192, profile.GetClientValidityBitfieldValue());
 }
@@ -1374,20 +1377,18 @@
   EXPECT_EQ(0, profile.GetClientValidityBitfieldValue());
 
   profile.SetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                           AutofillProfile::EMPTY,
-                           AutofillProfile::AutofillProfile::CLIENT);
+                           AutofillDataModel::EMPTY, AutofillDataModel::CLIENT);
   // 0b0100000000
   EXPECT_EQ(256, profile.GetClientValidityBitfieldValue());
 
   profile.SetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                           AutofillProfile::VALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
+                           AutofillDataModel::VALID, AutofillDataModel::CLIENT);
   // 0b1000000000
   EXPECT_EQ(512, profile.GetClientValidityBitfieldValue());
 
   profile.SetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                           AutofillProfile::INVALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
+                           AutofillDataModel::INVALID,
+                           AutofillDataModel::CLIENT);
   // 0b1100000000
   EXPECT_EQ(768, profile.GetClientValidityBitfieldValue());
 }
@@ -1399,18 +1400,18 @@
   // bitfield value should be empty.
   EXPECT_EQ(0, profile.GetClientValidityBitfieldValue());
 
-  profile.SetValidityState(EMAIL_ADDRESS, AutofillProfile::EMPTY,
-                           AutofillProfile::AutofillProfile::CLIENT);
+  profile.SetValidityState(EMAIL_ADDRESS, AutofillDataModel::EMPTY,
+                           AutofillDataModel::CLIENT);
   // 0b010000000000
   EXPECT_EQ(1024, profile.GetClientValidityBitfieldValue());
 
-  profile.SetValidityState(EMAIL_ADDRESS, AutofillProfile::VALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
+  profile.SetValidityState(EMAIL_ADDRESS, AutofillDataModel::VALID,
+                           AutofillDataModel::CLIENT);
   // 0b100000000000
   EXPECT_EQ(2048, profile.GetClientValidityBitfieldValue());
 
-  profile.SetValidityState(EMAIL_ADDRESS, AutofillProfile::INVALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
+  profile.SetValidityState(EMAIL_ADDRESS, AutofillDataModel::INVALID,
+                           AutofillDataModel::CLIENT);
   // 0b110000000000
   EXPECT_EQ(3072, profile.GetClientValidityBitfieldValue());
 }
@@ -1422,18 +1423,18 @@
   // bitfield value should be empty.
   EXPECT_EQ(0, profile.GetClientValidityBitfieldValue());
 
-  profile.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillProfile::EMPTY,
-                           AutofillProfile::AutofillProfile::CLIENT);
+  profile.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::EMPTY,
+                           AutofillDataModel::CLIENT);
   // 0b01000000000000
   EXPECT_EQ(4096, profile.GetClientValidityBitfieldValue());
 
-  profile.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
+  profile.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID,
+                           AutofillDataModel::CLIENT);
   // 0b10000000000000
   EXPECT_EQ(8192, profile.GetClientValidityBitfieldValue());
 
-  profile.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillProfile::INVALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
+  profile.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::INVALID,
+                           AutofillDataModel::CLIENT);
   // 0b11000000000000
   EXPECT_EQ(12288, profile.GetClientValidityBitfieldValue());
 }
@@ -1445,40 +1446,40 @@
   // bitfield value should be empty.
   EXPECT_EQ(0, profile.GetClientValidityBitfieldValue());
 
-  profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::VALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
-  profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::UNVALIDATED,
-                           AutofillProfile::AutofillProfile::CLIENT);
-  profile.SetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::EMPTY,
-                           AutofillProfile::AutofillProfile::CLIENT);
-  profile.SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::INVALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID,
+                           AutofillDataModel::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::UNVALIDATED,
+                           AutofillDataModel::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::EMPTY,
+                           AutofillDataModel::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::INVALID,
+                           AutofillDataModel::CLIENT);
   profile.SetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                           AutofillProfile::UNVALIDATED,
-                           AutofillProfile::AutofillProfile::CLIENT);
-  profile.SetValidityState(EMAIL_ADDRESS, AutofillProfile::INVALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
-  profile.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillProfile::EMPTY,
-                           AutofillProfile::AutofillProfile::CLIENT);
+                           AutofillDataModel::UNVALIDATED,
+                           AutofillDataModel::CLIENT);
+  profile.SetValidityState(EMAIL_ADDRESS, AutofillDataModel::INVALID,
+                           AutofillDataModel::CLIENT);
+  profile.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::EMPTY,
+                           AutofillDataModel::CLIENT);
   EXPECT_FALSE(profile.IsValidByClient());
   // 0b01110011010010
   EXPECT_EQ(7378, profile.GetClientValidityBitfieldValue());
 
-  profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::EMPTY,
-                           AutofillProfile::AutofillProfile::CLIENT);
-  profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::INVALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
-  profile.SetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::VALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
-  profile.SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::VALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::EMPTY,
+                           AutofillDataModel::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::INVALID,
+                           AutofillDataModel::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::VALID,
+                           AutofillDataModel::CLIENT);
+  profile.SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::VALID,
+                           AutofillDataModel::CLIENT);
   profile.SetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                           AutofillProfile::INVALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
-  profile.SetValidityState(EMAIL_ADDRESS, AutofillProfile::UNVALIDATED,
-                           AutofillProfile::AutofillProfile::CLIENT);
-  profile.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillProfile::INVALID,
-                           AutofillProfile::AutofillProfile::CLIENT);
+                           AutofillDataModel::INVALID,
+                           AutofillDataModel::CLIENT);
+  profile.SetValidityState(EMAIL_ADDRESS, AutofillDataModel::UNVALIDATED,
+                           AutofillDataModel::CLIENT);
+  profile.SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::INVALID,
+                           AutofillDataModel::CLIENT);
   EXPECT_FALSE(profile.IsValidByClient());
   // 0b11001110101101
   EXPECT_EQ(13229, profile.GetClientValidityBitfieldValue());
@@ -1494,23 +1495,23 @@
 
   // 0b01
   profile.SetClientValidityFromBitfieldValue(1);
-  EXPECT_EQ(AutofillProfile::EMPTY,
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(ADDRESS_HOME_COUNTRY,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_TRUE(profile.IsValidByClient());
 
   // 0b10
   profile.SetClientValidityFromBitfieldValue(2);
-  EXPECT_EQ(AutofillProfile::VALID,
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(ADDRESS_HOME_COUNTRY,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_TRUE(profile.IsValidByClient());
 
   // 0b11
   profile.SetClientValidityFromBitfieldValue(3);
-  EXPECT_EQ(AutofillProfile::INVALID,
+  EXPECT_EQ(AutofillDataModel::INVALID,
             profile.GetValidityState(ADDRESS_HOME_COUNTRY,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_FALSE(profile.IsValidByClient());
 }
 
@@ -1524,23 +1525,23 @@
 
   // 0b0100
   profile.SetClientValidityFromBitfieldValue(4);
-  EXPECT_EQ(AutofillProfile::EMPTY,
-            profile.GetValidityState(ADDRESS_HOME_STATE,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+  EXPECT_EQ(
+      AutofillDataModel::EMPTY,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_TRUE(profile.IsValidByClient());
 
   // 0b1000
   profile.SetClientValidityFromBitfieldValue(8);
-  EXPECT_EQ(AutofillProfile::VALID,
-            profile.GetValidityState(ADDRESS_HOME_STATE,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+  EXPECT_EQ(
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_TRUE(profile.IsValidByClient());
 
   // 0b1100
   profile.SetClientValidityFromBitfieldValue(12);
-  EXPECT_EQ(AutofillProfile::INVALID,
-            profile.GetValidityState(ADDRESS_HOME_STATE,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+  EXPECT_EQ(
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_FALSE(profile.IsValidByClient());
 }
 
@@ -1554,23 +1555,23 @@
 
   // 0b010000
   profile.SetClientValidityFromBitfieldValue(16);
-  EXPECT_EQ(AutofillProfile::EMPTY,
-            profile.GetValidityState(ADDRESS_HOME_ZIP,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+  EXPECT_EQ(
+      AutofillDataModel::EMPTY,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
   EXPECT_TRUE(profile.IsValidByClient());
 
   // 0b100000
   profile.SetClientValidityFromBitfieldValue(32);
-  EXPECT_EQ(AutofillProfile::VALID,
-            profile.GetValidityState(ADDRESS_HOME_ZIP,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+  EXPECT_EQ(
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
   EXPECT_TRUE(profile.IsValidByClient());
 
   // 0b110000
   profile.SetClientValidityFromBitfieldValue(48);
-  EXPECT_EQ(AutofillProfile::INVALID,
-            profile.GetValidityState(ADDRESS_HOME_ZIP,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+  EXPECT_EQ(
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
   EXPECT_FALSE(profile.IsValidByClient());
 }
 
@@ -1584,23 +1585,23 @@
 
   // 0b01000000
   profile.SetClientValidityFromBitfieldValue(64);
-  EXPECT_EQ(AutofillProfile::EMPTY,
-            profile.GetValidityState(ADDRESS_HOME_CITY,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+  EXPECT_EQ(
+      AutofillDataModel::EMPTY,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
   EXPECT_TRUE(profile.IsValidByClient());
 
   // 0b10000000
   profile.SetClientValidityFromBitfieldValue(128);
-  EXPECT_EQ(AutofillProfile::VALID,
-            profile.GetValidityState(ADDRESS_HOME_CITY,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+  EXPECT_EQ(
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
   EXPECT_TRUE(profile.IsValidByClient());
 
   // 0b11000000
   profile.SetClientValidityFromBitfieldValue(192);
-  EXPECT_EQ(AutofillProfile::INVALID,
-            profile.GetValidityState(ADDRESS_HOME_CITY,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+  EXPECT_EQ(
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
   EXPECT_FALSE(profile.IsValidByClient());
 }
 
@@ -1615,23 +1616,23 @@
 
   // 0b0100000000
   profile.SetClientValidityFromBitfieldValue(256);
-  EXPECT_EQ(AutofillProfile::EMPTY,
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_TRUE(profile.IsValidByClient());
 
   // 0b1000000000
   profile.SetClientValidityFromBitfieldValue(512);
-  EXPECT_EQ(AutofillProfile::VALID,
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_TRUE(profile.IsValidByClient());
 
   // 0b1100000000
   profile.SetClientValidityFromBitfieldValue(768);
-  EXPECT_EQ(AutofillProfile::INVALID,
+  EXPECT_EQ(AutofillDataModel::INVALID,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_FALSE(profile.IsValidByClient());
 }
 
@@ -1645,23 +1646,20 @@
 
   // 0b010000000000
   profile.SetClientValidityFromBitfieldValue(1024);
-  EXPECT_EQ(AutofillProfile::EMPTY,
-            profile.GetValidityState(EMAIL_ADDRESS,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillDataModel::EMPTY,
+            profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT));
   EXPECT_TRUE(profile.IsValidByClient());
 
   // 0b100000000000
   profile.SetClientValidityFromBitfieldValue(2048);
-  EXPECT_EQ(AutofillProfile::VALID,
-            profile.GetValidityState(EMAIL_ADDRESS,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT));
   EXPECT_TRUE(profile.IsValidByClient());
 
   // 0b110000000000
   profile.SetClientValidityFromBitfieldValue(3072);
-  EXPECT_EQ(AutofillProfile::INVALID,
-            profile.GetValidityState(EMAIL_ADDRESS,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillDataModel::INVALID,
+            profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT));
   EXPECT_FALSE(profile.IsValidByClient());
 }
 
@@ -1675,23 +1673,23 @@
 
   // 0b01000000000000
   profile.SetClientValidityFromBitfieldValue(4096);
-  EXPECT_EQ(AutofillProfile::EMPTY,
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_TRUE(profile.IsValidByClient());
 
   // 0b10000000000000
   profile.SetClientValidityFromBitfieldValue(8192);
-  EXPECT_EQ(AutofillProfile::VALID,
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_TRUE(profile.IsValidByClient());
 
   // 0b11000000000000
   profile.SetClientValidityFromBitfieldValue(12288);
-  EXPECT_EQ(AutofillProfile::INVALID,
+  EXPECT_EQ(AutofillDataModel::INVALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_FALSE(profile.IsValidByClient());
 }
 
@@ -1704,53 +1702,51 @@
 
   // 0b01110011010010
   profile.SetClientValidityFromBitfieldValue(7378);
-  EXPECT_EQ(AutofillProfile::VALID,
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(ADDRESS_HOME_COUNTRY,
-                                     AutofillProfile::AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::UNVALIDATED,
-            profile.GetValidityState(ADDRESS_HOME_STATE,
-                                     AutofillProfile::AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::EMPTY,
-            profile.GetValidityState(ADDRESS_HOME_ZIP,
-                                     AutofillProfile::AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::INVALID,
-            profile.GetValidityState(ADDRESS_HOME_CITY,
-                                     AutofillProfile::AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::UNVALIDATED,
+                                     AutofillDataModel::CLIENT));
+  EXPECT_EQ(
+      AutofillDataModel::UNVALIDATED,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
+  EXPECT_EQ(
+      AutofillDataModel::EMPTY,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
+  EXPECT_EQ(
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::UNVALIDATED,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::INVALID,
-            profile.GetValidityState(EMAIL_ADDRESS,
-                                     AutofillProfile::AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::EMPTY,
+                                     AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::INVALID,
+            profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 
   EXPECT_FALSE(profile.IsValidByClient());
 
   // 0b11001110101101
   profile.SetClientValidityFromBitfieldValue(13229);
-  EXPECT_EQ(AutofillProfile::EMPTY,
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(ADDRESS_HOME_COUNTRY,
-                                     AutofillProfile::AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::INVALID,
-            profile.GetValidityState(ADDRESS_HOME_STATE,
-                                     AutofillProfile::AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::VALID,
-            profile.GetValidityState(ADDRESS_HOME_ZIP,
-                                     AutofillProfile::AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::VALID,
-            profile.GetValidityState(ADDRESS_HOME_CITY,
-                                     AutofillProfile::AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::INVALID,
+                                     AutofillDataModel::CLIENT));
+  EXPECT_EQ(
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
+  EXPECT_EQ(
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
+  EXPECT_EQ(
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::INVALID,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::UNVALIDATED,
-            profile.GetValidityState(EMAIL_ADDRESS,
-                                     AutofillProfile::AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::INVALID,
+                                     AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::UNVALIDATED,
+            profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::INVALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_FALSE(profile.IsValidByClient());
 }
 
@@ -1874,10 +1870,10 @@
 enum Expectation { GREATER, LESS, EQUAL };
 
 struct HasGreaterFrescocencyTestCase {
-  const AutofillProfile::ValidityState client_validity_state_a;
-  const AutofillProfile::ValidityState server_validity_state_a;
-  const AutofillProfile::ValidityState client_validity_state_b;
-  const AutofillProfile::ValidityState server_validity_state_b;
+  const AutofillDataModel::ValidityState client_validity_state_a;
+  const AutofillDataModel::ValidityState server_validity_state_a;
+  const AutofillDataModel::ValidityState client_validity_state_b;
+  const AutofillDataModel::ValidityState server_validity_state_b;
 
   const bool use_client_validation;
   const bool use_server_validation;
@@ -1893,17 +1889,17 @@
   AutofillProfile profile_b("00000000-0000-0000-0000-000000000002", "");
 
   profile_a.SetValidityState(EMAIL_ADDRESS, test_case.client_validity_state_a,
-                             AutofillProfile::CLIENT);
+                             AutofillDataModel::CLIENT);
   profile_a.SetValidityState(ADDRESS_HOME_ZIP,
                              test_case.server_validity_state_a,
-                             AutofillProfile::SERVER);
+                             AutofillDataModel::SERVER);
 
   profile_b.SetValidityState(ADDRESS_HOME_CITY,
                              test_case.client_validity_state_b,
-                             AutofillProfile::CLIENT);
+                             AutofillDataModel::CLIENT);
   profile_b.SetValidityState(PHONE_HOME_NUMBER,
                              test_case.server_validity_state_b,
-                             AutofillProfile::SERVER);
+                             AutofillDataModel::SERVER);
 
   base::Time now = base::Time::Now();
 
@@ -1930,57 +1926,60 @@
     HasGreaterFrescocencyTest,
     testing::Values(
         HasGreaterFrescocencyTestCase{
-            AutofillProfile::VALID, AutofillProfile::INVALID,
-            AutofillProfile::VALID, AutofillProfile::UNVALIDATED, false, false,
+            AutofillDataModel::VALID, AutofillDataModel::INVALID,
+            AutofillDataModel::VALID, AutofillDataModel::UNVALIDATED, false,
+            false, EQUAL},
+        HasGreaterFrescocencyTestCase{
+            AutofillDataModel::INVALID, AutofillDataModel::VALID,
+            AutofillDataModel::VALID, AutofillDataModel::INVALID, false, false,
             EQUAL},
         HasGreaterFrescocencyTestCase{
-            AutofillProfile::INVALID, AutofillProfile::VALID,
-            AutofillProfile::VALID, AutofillProfile::INVALID, false, false,
-            EQUAL},
-        HasGreaterFrescocencyTestCase{
-            AutofillProfile::INVALID, AutofillProfile::VALID,
-            AutofillProfile::VALID, AutofillProfile::INVALID, false, true,
+            AutofillDataModel::INVALID, AutofillDataModel::VALID,
+            AutofillDataModel::VALID, AutofillDataModel::INVALID, false, true,
             GREATER},
         HasGreaterFrescocencyTestCase{
-            AutofillProfile::INVALID, AutofillProfile::INVALID,
-            AutofillProfile::VALID, AutofillProfile::INVALID, false, true,
+            AutofillDataModel::INVALID, AutofillDataModel::INVALID,
+            AutofillDataModel::VALID, AutofillDataModel::INVALID, false, true,
             EQUAL},
         HasGreaterFrescocencyTestCase{
-            AutofillProfile::INVALID, AutofillProfile::VALID,
-            AutofillProfile::VALID, AutofillProfile::VALID, false, true, EQUAL},
-        HasGreaterFrescocencyTestCase{
-            AutofillProfile::INVALID, AutofillProfile::INVALID,
-            AutofillProfile::VALID, AutofillProfile::UNVALIDATED, false, true,
-            LESS},
-        HasGreaterFrescocencyTestCase{
-            AutofillProfile::INVALID, AutofillProfile::VALID,
-            AutofillProfile::VALID, AutofillProfile::INVALID, true, true,
+            AutofillDataModel::INVALID, AutofillDataModel::VALID,
+            AutofillDataModel::VALID, AutofillDataModel::VALID, false, true,
             EQUAL},
-        HasGreaterFrescocencyTestCase{AutofillProfile::INVALID,
-                                      AutofillProfile::INVALID,
-                                      AutofillProfile::UNVALIDATED,
-                                      AutofillProfile::VALID, true, true, LESS},
         HasGreaterFrescocencyTestCase{
-            AutofillProfile::VALID, AutofillProfile::VALID,
-            AutofillProfile::VALID, AutofillProfile::VALID, true, true, EQUAL},
+            AutofillDataModel::INVALID, AutofillDataModel::INVALID,
+            AutofillDataModel::VALID, AutofillDataModel::UNVALIDATED, false,
+            true, LESS},
         HasGreaterFrescocencyTestCase{
-            AutofillProfile::VALID, AutofillProfile::UNVALIDATED,
-            AutofillProfile::VALID, AutofillProfile::INVALID, true, true,
+            AutofillDataModel::INVALID, AutofillDataModel::VALID,
+            AutofillDataModel::VALID, AutofillDataModel::INVALID, true, true,
+            EQUAL},
+        HasGreaterFrescocencyTestCase{
+            AutofillDataModel::INVALID, AutofillDataModel::INVALID,
+            AutofillDataModel::UNVALIDATED, AutofillDataModel::VALID, true,
+            true, LESS},
+        HasGreaterFrescocencyTestCase{
+            AutofillDataModel::VALID, AutofillDataModel::VALID,
+            AutofillDataModel::VALID, AutofillDataModel::VALID, true, true,
+            EQUAL},
+        HasGreaterFrescocencyTestCase{
+            AutofillDataModel::VALID, AutofillDataModel::UNVALIDATED,
+            AutofillDataModel::VALID, AutofillDataModel::INVALID, true, true,
             GREATER},
         HasGreaterFrescocencyTestCase{
-            AutofillProfile::VALID, AutofillProfile::INVALID,
-            AutofillProfile::INVALID, AutofillProfile::VALID, true, false,
+            AutofillDataModel::VALID, AutofillDataModel::INVALID,
+            AutofillDataModel::INVALID, AutofillDataModel::VALID, true, false,
             GREATER},
         HasGreaterFrescocencyTestCase{
-            AutofillProfile::INVALID, AutofillProfile::INVALID,
-            AutofillProfile::UNVALIDATED, AutofillProfile::VALID, true, false,
-            LESS},
+            AutofillDataModel::INVALID, AutofillDataModel::INVALID,
+            AutofillDataModel::UNVALIDATED, AutofillDataModel::VALID, true,
+            false, LESS},
         HasGreaterFrescocencyTestCase{
-            AutofillProfile::VALID, AutofillProfile::INVALID,
-            AutofillProfile::VALID, AutofillProfile::VALID, true, false, EQUAL},
+            AutofillDataModel::VALID, AutofillDataModel::INVALID,
+            AutofillDataModel::VALID, AutofillDataModel::VALID, true, false,
+            EQUAL},
         HasGreaterFrescocencyTestCase{
-            AutofillProfile::VALID, AutofillProfile::UNVALIDATED,
-            AutofillProfile::INVALID, AutofillProfile::INVALID, true, false,
+            AutofillDataModel::VALID, AutofillDataModel::UNVALIDATED,
+            AutofillDataModel::INVALID, AutofillDataModel::INVALID, true, false,
             GREATER}));
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/autofill_profile_validation_util.cc b/components/autofill/core/browser/autofill_profile_validation_util.cc
index 15b2d592..45f0530 100644
--- a/components/autofill/core/browser/autofill_profile_validation_util.cc
+++ b/components/autofill/core/browser/autofill_profile_validation_util.cc
@@ -55,19 +55,19 @@
 // Otherwise, return false.
 bool SetValidityStateForAddressField(const AutofillProfile* profile,
                                      AddressField address_field,
-                                     AutofillProfile::ValidityState state) {
+                                     AutofillDataModel::ValidityState state) {
   ServerFieldType server_field = i18n::TypeForField(address_field,
                                                     /*billing=*/false);
   if (server_field == UNKNOWN_TYPE)
     return false;
   DCHECK(profile);
-  profile->SetValidityState(server_field, state, AutofillProfile::CLIENT);
+  profile->SetValidityState(server_field, state, AutofillDataModel::CLIENT);
   return true;
 }
 
 // Set the validity state of all address fields in the |profile| to |state|.
 void SetAllAddressValidityStates(const AutofillProfile* profile,
-                                 AutofillProfile::ValidityState state) {
+                                 AutofillDataModel::ValidityState state) {
   DCHECK(profile);
   for (auto field : kFields)
     SetValidityStateForAddressField(profile, field, state);
@@ -110,54 +110,56 @@
 
 void SetEmptyValidityIfEmpty(const AutofillProfile* profile) {
   if (profile->GetRawInfo(ADDRESS_HOME_COUNTRY).empty())
-    profile->SetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::EMPTY,
-                              AutofillProfile::CLIENT);
+    profile->SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::EMPTY,
+                              AutofillDataModel::CLIENT);
   if (profile->GetRawInfo(ADDRESS_HOME_STATE).empty())
-    profile->SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::EMPTY,
-                              AutofillProfile::CLIENT);
+    profile->SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::EMPTY,
+                              AutofillDataModel::CLIENT);
   if (profile->GetRawInfo(ADDRESS_HOME_CITY).empty())
-    profile->SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::EMPTY,
-                              AutofillProfile::CLIENT);
+    profile->SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::EMPTY,
+                              AutofillDataModel::CLIENT);
   if (profile->GetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY).empty())
     profile->SetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                              AutofillProfile::EMPTY, AutofillProfile::CLIENT);
+                              AutofillDataModel::EMPTY,
+                              AutofillDataModel::CLIENT);
   if (profile->GetRawInfo(ADDRESS_HOME_ZIP).empty())
-    profile->SetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::EMPTY,
-                              AutofillProfile::CLIENT);
+    profile->SetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::EMPTY,
+                              AutofillDataModel::CLIENT);
 }
 
 void SetInvalidIfUnvalidated(const AutofillProfile* profile) {
   if (profile->GetValidityState(ADDRESS_HOME_COUNTRY,
-                                AutofillProfile::CLIENT) ==
-      AutofillProfile::UNVALIDATED) {
-    profile->SetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::INVALID,
-                              AutofillProfile::CLIENT);
+                                AutofillDataModel::CLIENT) ==
+      AutofillDataModel::UNVALIDATED) {
+    profile->SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::INVALID,
+                              AutofillDataModel::CLIENT);
   }
 
-  if (profile->GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT) ==
-      AutofillProfile::UNVALIDATED) {
-    profile->SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::INVALID,
-                              AutofillProfile::CLIENT);
+  if (profile->GetValidityState(ADDRESS_HOME_STATE,
+                                AutofillDataModel::CLIENT) ==
+      AutofillDataModel::UNVALIDATED) {
+    profile->SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::INVALID,
+                              AutofillDataModel::CLIENT);
   }
 
-  if (profile->GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT) ==
-      AutofillProfile::UNVALIDATED) {
-    profile->SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::INVALID,
-                              AutofillProfile::CLIENT);
+  if (profile->GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT) ==
+      AutofillDataModel::UNVALIDATED) {
+    profile->SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::INVALID,
+                              AutofillDataModel::CLIENT);
   }
 
   if (profile->GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                AutofillProfile::CLIENT) ==
-      AutofillProfile::UNVALIDATED) {
+                                AutofillDataModel::CLIENT) ==
+      AutofillDataModel::UNVALIDATED) {
     profile->SetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                              AutofillProfile::INVALID,
-                              AutofillProfile::CLIENT);
+                              AutofillDataModel::INVALID,
+                              AutofillDataModel::CLIENT);
   }
 
-  if (profile->GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT) ==
-      AutofillProfile::UNVALIDATED) {
-    profile->SetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::INVALID,
-                              AutofillProfile::CLIENT);
+  if (profile->GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT) ==
+      AutofillDataModel::UNVALIDATED) {
+    profile->SetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::INVALID,
+                              AutofillDataModel::CLIENT);
   }
 }
 
@@ -166,58 +168,62 @@
   // subregion can only be validated if its super-region is VALID. In  this
   // case, it's VALID if it has not been marked as INVALID or EMPTY.
 
-  if (profile->GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT) ==
-      AutofillProfile::UNVALIDATED) {
-    profile->SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::VALID,
-                              AutofillProfile::CLIENT);
+  if (profile->GetValidityState(ADDRESS_HOME_STATE,
+                                AutofillDataModel::CLIENT) ==
+      AutofillDataModel::UNVALIDATED) {
+    profile->SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::VALID,
+                              AutofillDataModel::CLIENT);
   }
 
-  if (profile->GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT) ==
-          AutofillProfile::UNVALIDATED &&
-      profile->GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT) ==
-          AutofillProfile::VALID) {
-    profile->SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::VALID,
-                              AutofillProfile::CLIENT);
+  if (profile->GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT) ==
+          AutofillDataModel::UNVALIDATED &&
+      profile->GetValidityState(ADDRESS_HOME_STATE,
+                                AutofillDataModel::CLIENT) ==
+          AutofillDataModel::VALID) {
+    profile->SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::VALID,
+                              AutofillDataModel::CLIENT);
   }
 
   if (profile->GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                AutofillProfile::CLIENT) ==
-          AutofillProfile::UNVALIDATED &&
-      profile->GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT) ==
-          AutofillProfile::VALID) {
+                                AutofillDataModel::CLIENT) ==
+          AutofillDataModel::UNVALIDATED &&
+      profile->GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT) ==
+          AutofillDataModel::VALID) {
     profile->SetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                              AutofillProfile::VALID, AutofillProfile::CLIENT);
+                              AutofillDataModel::VALID,
+                              AutofillDataModel::CLIENT);
   }
 
   // ZIP only depends on COUNTRY. If it's not so far marked as INVALID or EMPTY,
   // then it's VALID.
-  if (profile->GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT) ==
-      AutofillProfile::UNVALIDATED) {
-    profile->SetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::VALID,
-                              AutofillProfile::CLIENT);
+  if (profile->GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT) ==
+      AutofillDataModel::UNVALIDATED) {
+    profile->SetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::VALID,
+                              AutofillDataModel::CLIENT);
   }
 }
 
 void ApplyValidOnlyIfAllChildrenNotInvalid(const AutofillProfile* profile) {
-  if (profile->GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT) ==
-          AutofillProfile::INVALID &&
-      profile->GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT) ==
-          AutofillProfile::INVALID) {
-    profile->SetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::INVALID,
-                              AutofillProfile::CLIENT);
+  if (profile->GetValidityState(ADDRESS_HOME_STATE,
+                                AutofillDataModel::CLIENT) ==
+          AutofillDataModel::INVALID &&
+      profile->GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT) ==
+          AutofillDataModel::INVALID) {
+    profile->SetValidityState(ADDRESS_HOME_COUNTRY, AutofillDataModel::INVALID,
+                              AutofillDataModel::CLIENT);
   }
 
-  if (profile->GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT) ==
-      AutofillProfile::INVALID) {
-    profile->SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::INVALID,
-                              AutofillProfile::CLIENT);
+  if (profile->GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT) ==
+      AutofillDataModel::INVALID) {
+    profile->SetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::INVALID,
+                              AutofillDataModel::CLIENT);
   }
 
   if (profile->GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                AutofillProfile::CLIENT) ==
-      AutofillProfile::INVALID) {
-    profile->SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::INVALID,
-                              AutofillProfile::CLIENT);
+                                AutofillDataModel::CLIENT) ==
+      AutofillDataModel::INVALID) {
+    profile->SetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::INVALID,
+                              AutofillDataModel::CLIENT);
   }
 }
 
@@ -239,7 +245,7 @@
   DCHECK(address_validator);
   DCHECK(profile);
 
-  SetAllAddressValidityStates(profile, AutofillProfile::UNVALIDATED);
+  SetAllAddressValidityStates(profile, AutofillDataModel::UNVALIDATED);
 
   if (!base::ContainsValue(
           CountryDataMap::GetInstance()->country_codes(),
@@ -247,13 +253,14 @@
     // If the country code is not in the database, the country code and the
     // profile are invalid, and other fields cannot be validated, because it is
     // unclear which, if any, rule should apply.
-    SetValidityStateForAddressField(profile, COUNTRY, AutofillProfile::INVALID);
+    SetValidityStateForAddressField(profile, COUNTRY,
+                                    AutofillDataModel::INVALID);
     SetEmptyValidityIfEmpty(profile);
     return AddressValidator::SUCCESS;
   }
 
   // The COUNTRY was already listed in the CountryDataMap, therefore it's valid.
-  SetValidityStateForAddressField(profile, COUNTRY, AutofillProfile::VALID);
+  SetValidityStateForAddressField(profile, COUNTRY, AutofillDataModel::VALID);
 
   AddressData address;
   InitializeAddressFromProfile(*profile, &address);
@@ -264,7 +271,7 @@
 
   for (auto problem : problems)
     SetValidityStateForAddressField(profile, problem.first,
-                                    AutofillProfile::INVALID);
+                                    AutofillDataModel::INVALID);
 
   SetEmptyValidityIfEmpty(profile);
 
@@ -301,24 +308,24 @@
 void ValidateEmailAddress(const AutofillProfile* profile) {
   const base::string16& email = profile->GetRawInfo(EMAIL_ADDRESS);
   if (email.empty()) {
-    profile->SetValidityState(EMAIL_ADDRESS, AutofillProfile::EMPTY,
-                              AutofillProfile::CLIENT);
+    profile->SetValidityState(EMAIL_ADDRESS, AutofillDataModel::EMPTY,
+                              AutofillDataModel::CLIENT);
     return;
   }
 
   profile->SetValidityState(EMAIL_ADDRESS,
                             autofill::IsValidEmailAddress(email)
-                                ? AutofillProfile::VALID
-                                : AutofillProfile::INVALID,
-                            AutofillProfile::CLIENT);
+                                ? AutofillDataModel::VALID
+                                : AutofillDataModel::INVALID,
+                            AutofillDataModel::CLIENT);
 }
 
 void ValidatePhoneNumber(const AutofillProfile* profile) {
   const std::string& phone_number =
       base::UTF16ToUTF8(profile->GetRawInfo(PHONE_HOME_WHOLE_NUMBER));
   if (phone_number.empty()) {
-    profile->SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillProfile::EMPTY,
-                              AutofillProfile::CLIENT);
+    profile->SetValidityState(PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::EMPTY,
+                              AutofillDataModel::CLIENT);
     return;
   }
 
@@ -329,8 +336,8 @@
     // If the country code is not in the database, the phone number cannot be
     // validated.
     profile->SetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                              AutofillProfile::UNVALIDATED,
-                              AutofillProfile::CLIENT);
+                              AutofillDataModel::UNVALIDATED,
+                              AutofillDataModel::CLIENT);
     return;
   }
 
@@ -338,9 +345,9 @@
   profile->SetValidityState(
       PHONE_HOME_WHOLE_NUMBER,
       phone_util->IsPossibleNumberForString(phone_number, country_code)
-          ? AutofillProfile::VALID
-          : AutofillProfile::INVALID,
-      AutofillProfile::CLIENT);
+          ? AutofillDataModel::VALID
+          : AutofillDataModel::INVALID,
+      AutofillDataModel::CLIENT);
 }
 
 }  // namespace profile_validation_util
diff --git a/components/autofill/core/browser/autofill_profile_validation_util_unittest.cc b/components/autofill/core/browser/autofill_profile_validation_util_unittest.cc
index 6b609ed..4b36d54 100644
--- a/components/autofill/core/browser/autofill_profile_validation_util_unittest.cc
+++ b/components/autofill/core/browser/autofill_profile_validation_util_unittest.cc
@@ -84,24 +84,24 @@
   // Postal Code: "H3B 2T9", Country Code: "CA",
   AutofillProfile profile(autofill::test::GetFullValidProfileForCanada());
   ValidateAddressTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   // For Canada, there is no rule and data to validate the city.
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
   // Canada doesn't have a dependent locality. It's not filled, and yet the
   // profile is valid.
-  EXPECT_EQ(AutofillProfile::EMPTY,
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest,
@@ -112,23 +112,23 @@
   AutofillProfile profile(autofill::test::GetFullValidProfileForCanada());
   profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16(country_code));
   ValidateAddressTest(&profile);
-  EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillDataModel::INVALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   // The zip, the state and the city can't be validated, because we don't know
   // the country, in the strict validation this is considered as invalid.
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::EMPTY,
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest,
@@ -138,23 +138,23 @@
   AutofillProfile profile(autofill::test::GetFullValidProfileForCanada());
   profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16(""));
   ValidateAddressTest(&profile);
-  EXPECT_EQ(
-      AutofillProfile::EMPTY,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillDataModel::EMPTY,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   // The zip, the state and the city can't be validated, because we don't know
   // the country, in the strict validation this is considered as invalid.
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::EMPTY,
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest,
@@ -165,21 +165,21 @@
   AutofillProfile profile(autofill::test::GetFullValidProfileForCanada());
   profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16(country_code));
   ValidateAddressTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+      AutofillDataModel::UNVALIDATED,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::UNVALIDATED,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::UNVALIDATED,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::EMPTY,
+      AutofillDataModel::UNVALIDATED,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::UNVALIDATED,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::UNVALIDATED,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_AdminAreaNotExists) {
@@ -188,23 +188,23 @@
   profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16(admin_area_code));
 
   ValidateAddressTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   // The city can't be validated, because we don't know the state, in the strict
   // validation this is considered as invalid.
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::EMPTY,
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_EmptyAdminArea) {
@@ -212,23 +212,23 @@
   profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16(""));
 
   ValidateAddressTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::EMPTY,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
+      AutofillDataModel::EMPTY,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   // The city can't be validated, because we don't know the state, in the strict
   // validation this is considered as invalid.
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::EMPTY,
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_AdminAreaFullName) {
@@ -237,21 +237,21 @@
   profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16(admin_area));
 
   ValidateAddressTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::EMPTY,
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_AdminAreaLowerCase) {
@@ -260,21 +260,21 @@
   profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16(admin_area));
 
   ValidateAddressTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::EMPTY,
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest,
@@ -284,21 +284,21 @@
   profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16(admin_area));
 
   ValidateAddressTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::EMPTY,
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest,
@@ -313,21 +313,21 @@
   profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16(postal_code));
 
   ValidateAddressTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::EMPTY,
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_ValidZipNoSpace) {
@@ -336,21 +336,21 @@
   profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16(postal_code));
 
   ValidateAddressTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::EMPTY,
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_ValidZipLowerCase) {
@@ -360,21 +360,21 @@
   profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16(postal_code));
 
   ValidateAddressTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::EMPTY,
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_InvalidZip) {
@@ -383,21 +383,21 @@
   profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16(postal_code));
 
   ValidateAddressTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::EMPTY,
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_EmptyZip) {
@@ -405,21 +405,21 @@
   profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16(""));
 
   ValidateAddressTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::EMPTY,
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::EMPTY,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::EMPTY,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest, ValidateAddress_EmptyCity) {
@@ -430,21 +430,21 @@
   profile.SetRawInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16(""));
 
   ValidateAddressTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::EMPTY,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::EMPTY,
+      AutofillDataModel::EMPTY,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest, ValidateFullProfile_EmptyFields) {
@@ -455,21 +455,21 @@
   profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16(""));
 
   ValidateAddressTest(&profile);
+  EXPECT_EQ(AutofillDataModel::EMPTY,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::EMPTY,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+      AutofillDataModel::EMPTY,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::EMPTY,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::EMPTY,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::EMPTY,
+      AutofillDataModel::EMPTY,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::EMPTY,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::EMPTY,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest, ValidateFullValidProfileForChina) {
@@ -480,21 +480,21 @@
   AutofillProfile profile(autofill::test::GetFullValidProfileForChina());
 
   ValidateAddressTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::VALID,
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest,
@@ -504,25 +504,25 @@
   profile.SetRawInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16(invalid_city));
 
   ValidateAddressTest(&profile);
-  EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   // The city which is the only dependent field on state is invalid, in the
   // strict validation the state would also be considered as invalid.
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
   // The dependent locality can't be validated, because we don't know the city,
   // in the strict validation this is considered as invalid.
-  EXPECT_EQ(AutofillProfile::INVALID,
+  EXPECT_EQ(AutofillDataModel::INVALID,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest,
@@ -535,25 +535,25 @@
   profile.SetRawInfo(ADDRESS_HOME_CITY, base::UTF8ToUTF16(city));
 
   ValidateAddressTest(&profile);
-  EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   // The city which is the only dependent field on state is invalid, in the
   // strict validation the state would also be considered as invalid.
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
   // The dependent locality can't be validated, because we don't know the city,
   // in the strict validation this is considered as invalid.
-  EXPECT_EQ(AutofillProfile::INVALID,
+  EXPECT_EQ(AutofillDataModel::INVALID,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest,
@@ -568,21 +568,21 @@
                      base::UTF8ToUTF16(district));
 
   ValidateAddressTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::VALID,
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest,
@@ -593,21 +593,21 @@
   profile.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY, base::UTF8ToUTF16(""));
 
   ValidateAddressTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::EMPTY,
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest,
@@ -619,23 +619,23 @@
   profile.SetRawInfo(ADDRESS_HOME_DEPENDENT_LOCALITY, base::UTF8ToUTF16("赫"));
 
   ValidateAddressTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   // The dependent locality which is the only dependent field on city is
   // invalid, in the strict validation the city would also be invalid.
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::INVALID,
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::INVALID,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest,
@@ -648,23 +648,23 @@
                      base::UTF8ToUTF16("蒙城县"));
 
   ValidateAddressTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   // The only that depend on city (dependent locality) is invalid,
   //  in the strict validation city would also be considered as invalid.
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::INVALID,
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::INVALID,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest, ValidatePhone_FullValidProfile) {
@@ -672,18 +672,18 @@
   // Country Code: "CA", Phone Number: "15141112233"
   AutofillProfile profile(autofill::test::GetFullValidProfileForCanada());
   ValidatePhoneTest(&profile);
-  EXPECT_EQ(AutofillProfile::VALID,
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest, ValidatePhone_EmptyPhoneNumber) {
   AutofillProfile profile(autofill::test::GetFullValidProfileForCanada());
   profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::string16());
   ValidatePhoneTest(&profile);
-  EXPECT_EQ(AutofillProfile::EMPTY,
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest,
@@ -694,9 +694,9 @@
   AutofillProfile profile(autofill::test::GetFullValidProfileForCanada());
   profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16(country_code));
   ValidatePhoneTest(&profile);
-  EXPECT_EQ(AutofillProfile::UNVALIDATED,
+  EXPECT_EQ(AutofillDataModel::UNVALIDATED,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest,
@@ -708,103 +708,103 @@
   profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::UTF8ToUTF16(country_code));
   profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::string16());
   ValidatePhoneTest(&profile);
-  EXPECT_EQ(AutofillProfile::EMPTY,
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest, ValidatePhone_InvalidPhoneNumber) {
   AutofillProfile profile(autofill::test::GetFullValidProfileForCanada());
   profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::ASCIIToUTF16("33"));
   ValidatePhoneTest(&profile);
-  EXPECT_EQ(AutofillProfile::INVALID,
+  EXPECT_EQ(AutofillDataModel::INVALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 
   profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
                      base::ASCIIToUTF16("151411122334"));
   ValidatePhoneTest(&profile);
-  EXPECT_EQ(AutofillProfile::INVALID,
+  EXPECT_EQ(AutofillDataModel::INVALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 
   profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
                      base::ASCIIToUTF16("1(514)111-22-334"));
   ValidatePhoneTest(&profile);
-  EXPECT_EQ(AutofillProfile::INVALID,
+  EXPECT_EQ(AutofillDataModel::INVALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 
   profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
                      base::ASCIIToUTF16("251411122334"));
   ValidatePhoneTest(&profile);
-  EXPECT_EQ(AutofillProfile::INVALID,
+  EXPECT_EQ(AutofillDataModel::INVALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 
   profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::ASCIIToUTF16("Hello!"));
   ValidatePhoneTest(&profile);
-  EXPECT_EQ(AutofillProfile::INVALID,
+  EXPECT_EQ(AutofillDataModel::INVALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest, ValidatePhone_ValidPhoneNumber) {
   AutofillProfile profile(autofill::test::GetFullValidProfileForCanada());
   profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::ASCIIToUTF16("5141112233"));
   ValidatePhoneTest(&profile);
-  EXPECT_EQ(AutofillProfile::VALID,
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 
   profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
                      base::ASCIIToUTF16("514-111-2233"));
   ValidatePhoneTest(&profile);
-  EXPECT_EQ(AutofillProfile::VALID,
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 
   profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
                      base::ASCIIToUTF16("1(514)111-22-33"));
   ValidatePhoneTest(&profile);
-  EXPECT_EQ(AutofillProfile::VALID,
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 
   profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
                      base::ASCIIToUTF16("+1 514 111 22 33"));
   ValidatePhoneTest(&profile);
-  EXPECT_EQ(AutofillProfile::VALID,
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 
   profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
                      base::ASCIIToUTF16("+1 (514)-111-22-33"));
   ValidatePhoneTest(&profile);
-  EXPECT_EQ(AutofillProfile::VALID,
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 
   profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
                      base::ASCIIToUTF16("(514)-111-22-33"));
   ValidatePhoneTest(&profile);
-  EXPECT_EQ(AutofillProfile::VALID,
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 
   profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
                      base::ASCIIToUTF16("+1 650 GOO OGLE"));
   ValidatePhoneTest(&profile);
-  EXPECT_EQ(AutofillProfile::VALID,
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 
   profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER,
                      base::ASCIIToUTF16("778 111 22 33"));
   ValidatePhoneTest(&profile);
-  EXPECT_EQ(AutofillProfile::VALID,
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest, ValidateEmail_FullValidProfile) {
@@ -812,16 +812,16 @@
   // Email: "alice@wonderland.ca"
   AutofillProfile profile(autofill::test::GetFullValidProfileForCanada());
   ValidateEmailTest(&profile);
-  EXPECT_EQ(AutofillProfile::VALID,
-            profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest, ValidateEmail_EmptyEmailAddress) {
   AutofillProfile profile(autofill::test::GetFullValidProfileForCanada());
   profile.SetRawInfo(EMAIL_ADDRESS, base::string16());
   ValidateEmailTest(&profile);
-  EXPECT_EQ(AutofillProfile::EMPTY,
-            profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillDataModel::EMPTY,
+            profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest,
@@ -829,24 +829,24 @@
   AutofillProfile profile(autofill::test::GetFullValidProfileForCanada());
   profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("Hello!"));
   ValidateEmailTest(&profile);
-  EXPECT_EQ(AutofillProfile::INVALID,
-            profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillDataModel::INVALID,
+            profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT));
 
   profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("alice.wonderland"));
   ValidateEmailTest(&profile);
-  EXPECT_EQ(AutofillProfile::INVALID,
-            profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillDataModel::INVALID,
+            profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT));
 
   profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("alice@"));
   ValidateEmailTest(&profile);
-  EXPECT_EQ(AutofillProfile::INVALID,
-            profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillDataModel::INVALID,
+            profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT));
 
   profile.SetRawInfo(EMAIL_ADDRESS,
                      base::ASCIIToUTF16("alice@=wonderland.com"));
   ValidateEmailTest(&profile);
-  EXPECT_EQ(AutofillProfile::INVALID,
-            profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillDataModel::INVALID,
+            profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest, ValidateEmail_ValidEmailAddress) {
@@ -854,40 +854,40 @@
 
   profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("alice@wonderland"));
   ValidateEmailTest(&profile);
-  EXPECT_EQ(AutofillProfile::VALID,
-            profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT));
 
   profile.SetRawInfo(EMAIL_ADDRESS,
                      base::ASCIIToUTF16("alice@wonderland.fiction"));
   ValidateEmailTest(&profile);
-  EXPECT_EQ(AutofillProfile::VALID,
-            profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT));
 
   profile.SetRawInfo(EMAIL_ADDRESS,
                      base::ASCIIToUTF16("alice+cat@wonderland.fiction.book"));
   ValidateEmailTest(&profile);
-  EXPECT_EQ(AutofillProfile::VALID,
-            profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest, ValidateProfile_FullValidProfile) {
   // This is a full valid profile:
   AutofillProfile profile(autofill::test::GetFullValidProfileForCanada());
   ValidateProfileTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::VALID,
-            profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::VALID,
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest,
@@ -896,20 +896,20 @@
   AutofillProfile profile(autofill::test::GetFullValidProfileForCanada());
   profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("ABC 123"));
   ValidateProfileTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::VALID,
-            profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::VALID,
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest,
@@ -918,20 +918,20 @@
   AutofillProfile profile(autofill::test::GetFullValidProfileForCanada());
   profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, base::ASCIIToUTF16("33"));
   ValidateProfileTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::INVALID,
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::INVALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::VALID,
-            profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest,
@@ -940,20 +940,20 @@
   AutofillProfile profile(autofill::test::GetFullValidProfileForCanada());
   profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("fakeaddress"));
   ValidateProfileTest(&profile);
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::VALID,
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::INVALID,
-            profile.GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::INVALID,
+            profile.GetValidityState(EMAIL_ADDRESS, AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest,
@@ -968,33 +968,33 @@
   ValidateProfileTest(&profile);
   // The fields that depend on country (state and zip) are both invalid,
   // therefore in the strict validation this is considered as invalid.
-  EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillDataModel::INVALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   // The state is not a Chinese state, so it's considered as invalid.
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   // The city can't be validated, because the state value is not
   // valid, in the strict validation this is considered as invalid.
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
 
-  EXPECT_EQ(AutofillProfile::EMPTY,
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::UNSUPPORTED,
+                                     AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::UNSUPPORTED,
             profile.GetValidityState(ADDRESS_HOME_STREET_ADDRESS,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
   // The zip is not a Chinese one, therefore it's invalid.
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
   // Phone number is validated regardless of the country.
-  EXPECT_EQ(AutofillProfile::VALID,
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest,
@@ -1010,35 +1010,35 @@
 
   // The fields that depend on Country (state and zip) are both invalid,
   // therefore in the strict validation this is considered as invalid.
-  EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillDataModel::INVALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   // The state is not a Canadian state, so it's considered as invalid.
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   // We can't validate city, because state is not valid, in the strict
   // validation this is considered as invalid.
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
   // The dependent locality is not a Canadian field, so it's considered as
   // invalid.
-  EXPECT_EQ(AutofillProfile::INVALID,
+  EXPECT_EQ(AutofillDataModel::INVALID,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::UNSUPPORTED,
+                                     AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::UNSUPPORTED,
             profile.GetValidityState(ADDRESS_HOME_STREET_ADDRESS,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 
   // The zip is not a Canadian one, therefore it's invalid.
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
   // Phone number is validated regardless of the country.
-  EXPECT_EQ(AutofillProfile::VALID,
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest,
@@ -1052,34 +1052,34 @@
 
   ValidateProfileTest(&profile);
 
-  EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   // The only field that depends on state (city) is invalid, in the strict
   // validation this makes state also invalid.
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   // The city is in another province.
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
   // The dependent locality can't be validated, because the city value is not
   // valid, in the strict validation this is considered as invalid.
-  EXPECT_EQ(AutofillProfile::INVALID,
+  EXPECT_EQ(AutofillDataModel::INVALID,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::UNSUPPORTED,
+                                     AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::UNSUPPORTED,
             profile.GetValidityState(ADDRESS_HOME_STREET_ADDRESS,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
   // Phone number is validated regardless of the country.
-  EXPECT_EQ(AutofillProfile::VALID,
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 }
 
 TEST_F(AutofillProfileValidationUtilTest,
@@ -1093,33 +1093,33 @@
 
   ValidateProfileTest(&profile);
 
+  EXPECT_EQ(AutofillDataModel::VALID,
+            profile.GetValidityState(ADDRESS_HOME_COUNTRY,
+                                     AutofillDataModel::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_COUNTRY, AutofillProfile::CLIENT));
-  EXPECT_EQ(
-      AutofillProfile::EMPTY,
-      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillProfile::CLIENT));
+      AutofillDataModel::EMPTY,
+      profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT));
   // City can't be validated, because the state is missing, in the strict
   // validation this is considered as invalid.
   EXPECT_EQ(
-      AutofillProfile::INVALID,
-      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT));
+      AutofillDataModel::INVALID,
+      profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT));
   // The dependent locality can't be validated, because we don't know the city,
   // in the strict validation this is considered as invalid.
-  EXPECT_EQ(AutofillProfile::INVALID,
+  EXPECT_EQ(AutofillDataModel::INVALID,
             profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
-                                     AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::UNSUPPORTED,
+                                     AutofillDataModel::CLIENT));
+  EXPECT_EQ(AutofillDataModel::UNSUPPORTED,
             profile.GetValidityState(ADDRESS_HOME_STREET_ADDRESS,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 
   EXPECT_EQ(
-      AutofillProfile::VALID,
-      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
+      AutofillDataModel::VALID,
+      profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT));
   // Phone number is validated regardless of the country.
-  EXPECT_EQ(AutofillProfile::VALID,
+  EXPECT_EQ(AutofillDataModel::VALID,
             profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER,
-                                     AutofillProfile::CLIENT));
+                                     AutofillDataModel::CLIENT));
 }
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/autofill_profile_validator_unittest.cc b/components/autofill/core/browser/autofill_profile_validator_unittest.cc
index 72a48f3..5278b8b 100644
--- a/components/autofill/core/browser/autofill_profile_validator_unittest.cc
+++ b/components/autofill/core/browser/autofill_profile_validator_unittest.cc
@@ -87,7 +87,7 @@
     for (auto expectation : expected_validity_) {
       EXPECT_EQ(expectation.second,
                 profile->GetValidityState(expectation.first,
-                                          AutofillProfile::CLIENT));
+                                          AutofillDataModel::CLIENT));
     }
   }
 
@@ -101,7 +101,7 @@
 
   AutofillProfileValidatorCallback onvalidated_cb_;
 
-  std::vector<std::pair<ServerFieldType, AutofillProfile::ValidityState>>
+  std::vector<std::pair<ServerFieldType, AutofillDataModel::ValidityState>>
       expected_validity_;
 
  private:
@@ -122,11 +122,11 @@
   EXPECT_EQ(false, AreRulesLoadedForRegion(country_code));
 
   // Set up the test expectations.
-  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID},
-                        {ADDRESS_HOME_STATE, AutofillProfile::VALID},
-                        {ADDRESS_HOME_ZIP, AutofillProfile::VALID},
-                        {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID},
-                        {EMAIL_ADDRESS, AutofillProfile::VALID}};
+  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID},
+                        {ADDRESS_HOME_STATE, AutofillDataModel::VALID},
+                        {ADDRESS_HOME_ZIP, AutofillDataModel::VALID},
+                        {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID},
+                        {EMAIL_ADDRESS, AutofillDataModel::VALID}};
 
   // Start the validator.
   validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_));
@@ -143,11 +143,11 @@
   EXPECT_EQ(true, AreRulesLoadedForRegion(country_code));
 
   // Set up the test expectations.
-  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID},
-                        {ADDRESS_HOME_STATE, AutofillProfile::VALID},
-                        {ADDRESS_HOME_ZIP, AutofillProfile::VALID},
-                        {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID},
-                        {EMAIL_ADDRESS, AutofillProfile::VALID}};
+  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID},
+                        {ADDRESS_HOME_STATE, AutofillDataModel::VALID},
+                        {ADDRESS_HOME_ZIP, AutofillDataModel::VALID},
+                        {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID},
+                        {EMAIL_ADDRESS, AutofillDataModel::VALID}};
 
   // Start the validator.
   validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_));
@@ -164,11 +164,12 @@
   EXPECT_EQ(false, AreRulesLoadedForRegion(country_code));
 
   // Set up the test expectations.
-  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::INVALID},
-                        {ADDRESS_HOME_STATE, AutofillProfile::INVALID},
-                        {ADDRESS_HOME_ZIP, AutofillProfile::INVALID},
-                        {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::UNVALIDATED},
-                        {EMAIL_ADDRESS, AutofillProfile::VALID}};
+  expected_validity_ = {
+      {ADDRESS_HOME_COUNTRY, AutofillDataModel::INVALID},
+      {ADDRESS_HOME_STATE, AutofillDataModel::INVALID},
+      {ADDRESS_HOME_ZIP, AutofillDataModel::INVALID},
+      {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::UNVALIDATED},
+      {EMAIL_ADDRESS, AutofillDataModel::VALID}};
 
   // Start the validator.
   validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_));
@@ -184,11 +185,11 @@
   EXPECT_EQ(false, AreRulesLoadedForRegion(country_code));
 
   // Set up the test expectations.
-  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID},
-                        {ADDRESS_HOME_STATE, AutofillProfile::UNVALIDATED},
-                        {ADDRESS_HOME_ZIP, AutofillProfile::UNVALIDATED},
-                        {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID},
-                        {EMAIL_ADDRESS, AutofillProfile::VALID}};
+  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID},
+                        {ADDRESS_HOME_STATE, AutofillDataModel::UNVALIDATED},
+                        {ADDRESS_HOME_ZIP, AutofillDataModel::UNVALIDATED},
+                        {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID},
+                        {EMAIL_ADDRESS, AutofillDataModel::VALID}};
 
   // Start the validator.
   validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_));
@@ -203,11 +204,12 @@
 
   // Set up the test expectations.
   // The phone is validated for the US.
-  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::EMPTY},
-                        {ADDRESS_HOME_STATE, AutofillProfile::INVALID},
-                        {ADDRESS_HOME_ZIP, AutofillProfile::INVALID},
-                        {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::UNVALIDATED},
-                        {EMAIL_ADDRESS, AutofillProfile::VALID}};
+  expected_validity_ = {
+      {ADDRESS_HOME_COUNTRY, AutofillDataModel::EMPTY},
+      {ADDRESS_HOME_STATE, AutofillDataModel::INVALID},
+      {ADDRESS_HOME_ZIP, AutofillDataModel::INVALID},
+      {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::UNVALIDATED},
+      {EMAIL_ADDRESS, AutofillDataModel::VALID}};
 
   // Start the validator.
   validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_));
@@ -220,11 +222,11 @@
                      base::UTF8ToUTF16("Invalid Phone"));
 
   // Set up the test expectations.
-  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID},
-                        {ADDRESS_HOME_STATE, AutofillProfile::VALID},
-                        {ADDRESS_HOME_ZIP, AutofillProfile::VALID},
-                        {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::INVALID},
-                        {EMAIL_ADDRESS, AutofillProfile::VALID}};
+  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID},
+                        {ADDRESS_HOME_STATE, AutofillDataModel::VALID},
+                        {ADDRESS_HOME_ZIP, AutofillDataModel::VALID},
+                        {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::INVALID},
+                        {EMAIL_ADDRESS, AutofillDataModel::VALID}};
 
   // Start the validator.
   validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_));
@@ -236,11 +238,11 @@
   profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("Invalid State"));
 
   // Set up the test expectations.
-  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID},
-                        {ADDRESS_HOME_STATE, AutofillProfile::INVALID},
-                        {ADDRESS_HOME_ZIP, AutofillProfile::VALID},
-                        {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID},
-                        {EMAIL_ADDRESS, AutofillProfile::VALID}};
+  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID},
+                        {ADDRESS_HOME_STATE, AutofillDataModel::INVALID},
+                        {ADDRESS_HOME_ZIP, AutofillDataModel::VALID},
+                        {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID},
+                        {EMAIL_ADDRESS, AutofillDataModel::VALID}};
 
   // Start the validator.
   validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_));
@@ -254,11 +256,11 @@
   profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("Invalid State"));
 
   // Set up the test expectations.
-  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID},
-                        {ADDRESS_HOME_STATE, AutofillProfile::INVALID},
-                        {ADDRESS_HOME_ZIP, AutofillProfile::VALID},
-                        {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::EMPTY},
-                        {EMAIL_ADDRESS, AutofillProfile::VALID}};
+  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID},
+                        {ADDRESS_HOME_STATE, AutofillDataModel::INVALID},
+                        {ADDRESS_HOME_ZIP, AutofillDataModel::VALID},
+                        {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::EMPTY},
+                        {EMAIL_ADDRESS, AutofillDataModel::VALID}};
 
   // Start the validator.
   validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_));
@@ -272,11 +274,11 @@
   profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("Invalid Zip"));
 
   // Set up the test expectations.
-  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID},
-                        {ADDRESS_HOME_STATE, AutofillProfile::VALID},
-                        {ADDRESS_HOME_ZIP, AutofillProfile::INVALID},
-                        {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID},
-                        {EMAIL_ADDRESS, AutofillProfile::INVALID}};
+  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID},
+                        {ADDRESS_HOME_STATE, AutofillDataModel::VALID},
+                        {ADDRESS_HOME_ZIP, AutofillDataModel::INVALID},
+                        {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID},
+                        {EMAIL_ADDRESS, AutofillDataModel::INVALID}};
 
   // Start the validator.
   validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_));
@@ -290,11 +292,11 @@
   profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("Invalid Zip"));
 
   // Set up the test expectations.
-  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID},
-                        {ADDRESS_HOME_STATE, AutofillProfile::VALID},
-                        {ADDRESS_HOME_ZIP, AutofillProfile::INVALID},
-                        {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID},
-                        {EMAIL_ADDRESS, AutofillProfile::EMPTY}};
+  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID},
+                        {ADDRESS_HOME_STATE, AutofillDataModel::VALID},
+                        {ADDRESS_HOME_ZIP, AutofillDataModel::INVALID},
+                        {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID},
+                        {EMAIL_ADDRESS, AutofillDataModel::EMPTY}};
 
   // Start the validator.
   validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_));
@@ -308,11 +310,11 @@
   profile.SetRawInfo(ADDRESS_HOME_ZIP, base::string16());
 
   // Set up the test expectations.
-  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID},
-                        {ADDRESS_HOME_STATE, AutofillProfile::VALID},
-                        {ADDRESS_HOME_ZIP, AutofillProfile::EMPTY},
-                        {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID},
-                        {EMAIL_ADDRESS, AutofillProfile::INVALID}};
+  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID},
+                        {ADDRESS_HOME_STATE, AutofillDataModel::VALID},
+                        {ADDRESS_HOME_ZIP, AutofillDataModel::EMPTY},
+                        {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID},
+                        {EMAIL_ADDRESS, AutofillDataModel::INVALID}};
 
   // Start the validator.
   validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_));
@@ -327,11 +329,11 @@
                      base::UTF8ToUTF16("Invalid Phone"));
 
   // Set up the test expectations.
-  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID},
-                        {ADDRESS_HOME_STATE, AutofillProfile::VALID},
-                        {ADDRESS_HOME_ZIP, AutofillProfile::VALID},
-                        {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::INVALID},
-                        {EMAIL_ADDRESS, AutofillProfile::INVALID}};
+  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID},
+                        {ADDRESS_HOME_STATE, AutofillDataModel::VALID},
+                        {ADDRESS_HOME_ZIP, AutofillDataModel::VALID},
+                        {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::INVALID},
+                        {EMAIL_ADDRESS, AutofillDataModel::INVALID}};
 
   // Start the validator.
   validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_));
@@ -343,11 +345,11 @@
   profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("Invalid Email"));
 
   // Set up the test expectations.
-  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID},
-                        {ADDRESS_HOME_STATE, AutofillProfile::VALID},
-                        {ADDRESS_HOME_ZIP, AutofillProfile::VALID},
-                        {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::VALID},
-                        {EMAIL_ADDRESS, AutofillProfile::INVALID}};
+  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID},
+                        {ADDRESS_HOME_STATE, AutofillDataModel::VALID},
+                        {ADDRESS_HOME_ZIP, AutofillDataModel::VALID},
+                        {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID},
+                        {EMAIL_ADDRESS, AutofillDataModel::INVALID}};
 
   // Start the validator.
   validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_));
@@ -363,11 +365,11 @@
   profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("Invalid State"));
 
   // Set up the test expectations.
-  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillProfile::VALID},
-                        {ADDRESS_HOME_STATE, AutofillProfile::INVALID},
-                        {ADDRESS_HOME_ZIP, AutofillProfile::VALID},
-                        {PHONE_HOME_WHOLE_NUMBER, AutofillProfile::INVALID},
-                        {EMAIL_ADDRESS, AutofillProfile::INVALID}};
+  expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID},
+                        {ADDRESS_HOME_STATE, AutofillDataModel::INVALID},
+                        {ADDRESS_HOME_ZIP, AutofillDataModel::VALID},
+                        {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::INVALID},
+                        {EMAIL_ADDRESS, AutofillDataModel::INVALID}};
 
   // Start the validator.
   validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_));
diff --git a/components/autofill/core/browser/autofill_test_utils.cc b/components/autofill/core/browser/autofill_test_utils.cc
index 9126d95..ffab385a 100644
--- a/components/autofill/core/browser/autofill_test_utils.cc
+++ b/components/autofill/core/browser/autofill_test_utils.cc
@@ -587,7 +587,7 @@
     std::vector<ServerFieldTypeValidityStatesMap>&
         possible_field_types_validities,
     const std::vector<ServerFieldType>& possible_types,
-    const std::vector<AutofillProfile::ValidityState>& validity_states) {
+    const std::vector<AutofillDataModel::ValidityState>& validity_states) {
   possible_field_types.push_back(ServerFieldTypeSet());
   possible_field_types_validities.push_back(ServerFieldTypeValidityStatesMap());
 
diff --git a/components/autofill/core/browser/autofill_test_utils.h b/components/autofill/core/browser/autofill_test_utils.h
index b67a11c36..02eb584 100644
--- a/components/autofill/core/browser/autofill_test_utils.h
+++ b/components/autofill/core/browser/autofill_test_utils.h
@@ -216,7 +216,7 @@
     std::vector<ServerFieldTypeValidityStatesMap>&
         possible_field_types_validities,
     const std::vector<ServerFieldType>& possible_type,
-    const std::vector<AutofillProfile::ValidityState>& validity_state = {});
+    const std::vector<AutofillDataModel::ValidityState>& validity_state = {});
 
 // Fills the upload |field| with the information passed by parameter. If the
 // value of a const char* parameter is NULL, the corresponding attribute won't
diff --git a/components/autofill/core/browser/field_filler.cc b/components/autofill/core/browser/field_filler.cc
index e1e56eb0..8e4270d 100644
--- a/components/autofill/core/browser/field_filler.cc
+++ b/components/autofill/core/browser/field_filler.cc
@@ -624,6 +624,7 @@
                                 FormFieldData* field_data,
                                 const base::string16& cvc) {
   const AutofillType type = field.Type();
+
   // Don't fill if autocomplete=off is set on |field| on desktop for non credit
   // card related fields.
   if (!base::FeatureList::IsEnabled(features::kAutofillAlwaysFillAddresses) &&
@@ -632,6 +633,25 @@
     return false;
   }
 
+  // Check for the validity of the data. Leave the field empty if the data is
+  // invalid and the relevant feature is enabled.
+  bool use_server_validation = base::FeatureList::IsEnabled(
+      autofill::features::kAutofillProfileServerValidation);
+  bool use_client_validation = base::FeatureList::IsEnabled(
+      autofill::features::kAutofillProfileClientValidation);
+  ServerFieldType server_field_type = type.GetStorableType();
+
+  if ((use_client_validation &&
+       data_model.GetValidityState(server_field_type,
+                                   AutofillProfile::CLIENT) ==
+           AutofillProfile::INVALID) ||
+      (use_server_validation &&
+       data_model.GetValidityState(server_field_type,
+                                   AutofillProfile::SERVER) ==
+           AutofillProfile::INVALID)) {
+    return false;
+  }
+
   base::string16 value = data_model.GetInfo(type, app_locale_);
   if (type.GetStorableType() == CREDIT_CARD_VERIFICATION_CODE)
     value = cvc;
diff --git a/components/autofill/core/browser/field_filler_unittest.cc b/components/autofill/core/browser/field_filler_unittest.cc
index eb2f6986..3bed68d2 100644
--- a/components/autofill/core/browser/field_filler_unittest.cc
+++ b/components/autofill/core/browser/field_filler_unittest.cc
@@ -110,6 +110,29 @@
   EXPECT_EQ(ASCIIToUTF16("Nov"), field.option_contents[content_index]);
 }
 
+void TestFillingInvalidFields(const base::string16& state,
+                              const base::string16& city) {
+  AutofillProfile profile = test::GetFullProfile();
+  profile.SetValidityState(ADDRESS_HOME_STATE, AutofillProfile::INVALID,
+                           AutofillProfile::SERVER);
+  profile.SetValidityState(ADDRESS_HOME_CITY, AutofillProfile::INVALID,
+                           AutofillProfile::CLIENT);
+
+  AutofillField field_state;
+  field_state.set_heuristic_type(ADDRESS_HOME_STATE);
+  AutofillField field_city;
+  field_city.set_heuristic_type(ADDRESS_HOME_CITY);
+
+  FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
+  filler.FillFormField(field_state, profile, &field_state,
+                       /*cvc=*/base::string16());
+  EXPECT_EQ(state, field_state.value);
+
+  filler.FillFormField(field_city, profile, &field_city,
+                       /*cvc=*/base::string16());
+  EXPECT_EQ(city, field_city.value);
+}
+
 struct CreditCardTestCase {
   std::string card_number_;
   size_t total_splits_;
@@ -388,6 +411,50 @@
   EXPECT_EQ(ASCIIToUTF16("4111111111111111"), field.value);
 }
 
+// Verify that when the relevant feature is enabled, the invalid fields don't
+// get filled.
+TEST_F(AutofillFieldFillerTest, FillFormField_Validity_ServerClient) {
+  base::test::ScopedFeatureList scoped_features;
+  scoped_features.InitWithFeatures(
+      /*enabled_features=*/{features::kAutofillProfileServerValidation,
+                            features::kAutofillProfileClientValidation},
+      /*disabled_features=*/{});
+  // State's validity is set by server and city's validity by client.
+  TestFillingInvalidFields(/*state=*/base::string16(),
+                           /*city=*/base::string16());
+}
+
+TEST_F(AutofillFieldFillerTest, FillFormField_Validity_OnlyServer) {
+  base::test::ScopedFeatureList scoped_features;
+  scoped_features.InitWithFeatures(
+      /*enabled_features=*/{features::kAutofillProfileServerValidation},
+      /*disabled_features=*/{features::kAutofillProfileClientValidation});
+  // State's validity is set by server and city's validity by client.
+  TestFillingInvalidFields(/*state=*/base::string16(),
+                           /*city=*/ASCIIToUTF16("Elysium"));
+}
+
+TEST_F(AutofillFieldFillerTest, FillFormField_Validity_OnlyClient) {
+  base::test::ScopedFeatureList scoped_features;
+  scoped_features.InitWithFeatures(
+      /*enabled_features=*/{features::kAutofillProfileClientValidation},
+      /*disabled_features=*/{features::kAutofillProfileServerValidation});
+  // State's validity is set by server and city's validity by client.
+  TestFillingInvalidFields(/*state=*/ASCIIToUTF16("CA"),
+                           /*city=*/base::string16());
+}
+
+TEST_F(AutofillFieldFillerTest, FillFormField_NoValidity) {
+  base::test::ScopedFeatureList scoped_features;
+  scoped_features.InitWithFeatures(
+      /*enabled_features=*/{},
+      /*disabled_features=*/{features::kAutofillProfileServerValidation,
+                             features::kAutofillProfileClientValidation});
+  // State's validity is set by server and city's validity by client.
+  TestFillingInvalidFields(/*state=*/ASCIIToUTF16("CA"),
+                           /*city=*/ASCIIToUTF16("Elysium"));
+}
+
 struct AutofillFieldFillerTestCase {
   HtmlFieldType field_type;
   size_t field_max_length;
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc
index 35664d3b..e9f57feb 100644
--- a/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -2303,18 +2303,27 @@
         /*enabled_features=*/{features::kAutofillProfileServerValidation,
                               features::kAutofillProfileClientValidation},
         /*disabled_features=*/{features::kAutofillSuppressDisusedAddresses});
-    std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
-        AutofillType(EMAIL_ADDRESS), base::string16(), false,
-        std::vector<ServerFieldType>());
+    std::vector<Suggestion> email_suggestions =
+        personal_data_->GetProfileSuggestions(AutofillType(EMAIL_ADDRESS),
+                                              base::string16(), false,
+                                              std::vector<ServerFieldType>());
 
     for (auto* profile : profiles) {
       ASSERT_EQ(profile->guid() == valid_profile.guid(),
                 profile->IsValidByClient());
       ASSERT_TRUE(profile->IsValidByServer());
     }
-    ASSERT_EQ(2U, suggestions.size());
-    EXPECT_EQ(base::ASCIIToUTF16("alice@wonderland.ca"), suggestions[0].value);
-    EXPECT_EQ(base::ASCIIToUTF16("invalid email"), suggestions[1].value);
+    ASSERT_EQ(1U, email_suggestions.size());
+    EXPECT_EQ(base::ASCIIToUTF16("alice@wonderland.ca"),
+              email_suggestions[0].value);
+
+    std::vector<Suggestion> name_suggestions =
+        personal_data_->GetProfileSuggestions(AutofillType(NAME_FIRST),
+                                              base::string16(), false,
+                                              std::vector<ServerFieldType>());
+    ASSERT_EQ(2U, name_suggestions.size());
+    EXPECT_EQ(base::ASCIIToUTF16("Alice"), name_suggestions[0].value);
+    EXPECT_EQ(base::ASCIIToUTF16("Marion1"), name_suggestions[1].value);
   }
 
   // Set the validity state of ADDRESS_HOME_STATE to INVALID on the prefs.
@@ -2324,8 +2333,9 @@
     std::string autofill_profile_validity;
     personal_data_->pref_service_->SetString(prefs::kAutofillProfileValidity,
                                              autofill_profile_validity);
-    (*profile_validity_map.mutable_field_validity_states())[static_cast<int>(
-        ADDRESS_HOME_STATE)] = static_cast<int>(AutofillProfile::INVALID);
+    (*profile_validity_map
+          .mutable_field_validity_states())[static_cast<int>(EMAIL_ADDRESS)] =
+        static_cast<int>(AutofillProfile::INVALID);
     (*user_profile_validity_map
           .mutable_profile_validity())[invalid_profile.guid()] =
         profile_validity_map;
@@ -2343,9 +2353,10 @@
                               features::kAutofillProfileServerValidation},
         /*disabled_features=*/{features::kAutofillSuppressDisusedAddresses});
 
-    std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
-        AutofillType(EMAIL_ADDRESS), base::string16(), false,
-        std::vector<ServerFieldType>());
+    std::vector<Suggestion> email_suggestions =
+        personal_data_->GetProfileSuggestions(AutofillType(EMAIL_ADDRESS),
+                                              base::string16(), false,
+                                              std::vector<ServerFieldType>());
 
     for (auto* profile : profiles) {
       ASSERT_EQ(profile->guid() == valid_profile.guid(),
@@ -2353,9 +2364,17 @@
       ASSERT_EQ(profile->guid() == valid_profile.guid(),
                 profile->IsValidByServer());
     }
-    ASSERT_EQ(2U, suggestions.size());
-    EXPECT_EQ(base::ASCIIToUTF16("alice@wonderland.ca"), suggestions[0].value);
-    EXPECT_EQ(base::ASCIIToUTF16("invalid email"), suggestions[1].value);
+    ASSERT_EQ(1U, email_suggestions.size());
+    EXPECT_EQ(base::ASCIIToUTF16("alice@wonderland.ca"),
+              email_suggestions[0].value);
+
+    std::vector<Suggestion> name_suggestions =
+        personal_data_->GetProfileSuggestions(AutofillType(NAME_FIRST),
+                                              base::string16(), false,
+                                              std::vector<ServerFieldType>());
+    ASSERT_EQ(2U, name_suggestions.size());
+    EXPECT_EQ(base::ASCIIToUTF16("Alice"), name_suggestions[0].value);
+    EXPECT_EQ(base::ASCIIToUTF16("Marion1"), name_suggestions[1].value);
   }
   // Invalid based on client, and server. Relying only on the client source.
   {
@@ -2364,9 +2383,10 @@
         /*enabled_features=*/{features::kAutofillProfileClientValidation},
         /*disabled_features=*/{features::kAutofillSuppressDisusedAddresses,
                                features::kAutofillProfileServerValidation});
-    std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
-        AutofillType(EMAIL_ADDRESS), base::string16(), false,
-        std::vector<ServerFieldType>());
+    std::vector<Suggestion> email_suggestions =
+        personal_data_->GetProfileSuggestions(AutofillType(EMAIL_ADDRESS),
+                                              base::string16(), false,
+                                              std::vector<ServerFieldType>());
 
     for (auto* profile : profiles) {
       ASSERT_EQ(profile->guid() == valid_profile.guid(),
@@ -2374,9 +2394,17 @@
       ASSERT_EQ(profile->guid() == valid_profile.guid(),
                 profile->IsValidByServer());
     }
-    ASSERT_EQ(2U, suggestions.size());
-    EXPECT_EQ(base::ASCIIToUTF16("alice@wonderland.ca"), suggestions[0].value);
-    EXPECT_EQ(base::ASCIIToUTF16("invalid email"), suggestions[1].value);
+    ASSERT_EQ(1U, email_suggestions.size());
+    EXPECT_EQ(base::ASCIIToUTF16("alice@wonderland.ca"),
+              email_suggestions[0].value);
+
+    std::vector<Suggestion> name_suggestions =
+        personal_data_->GetProfileSuggestions(AutofillType(NAME_FIRST),
+                                              base::string16(), false,
+                                              std::vector<ServerFieldType>());
+    ASSERT_EQ(2U, name_suggestions.size());
+    EXPECT_EQ(base::ASCIIToUTF16("Alice"), name_suggestions[0].value);
+    EXPECT_EQ(base::ASCIIToUTF16("Marion1"), name_suggestions[1].value);
   }
   // Invalid based on client, and server. Relying on server as a validity
   // source.
@@ -2386,10 +2414,11 @@
         /*enabled_features=*/{features::kAutofillProfileServerValidation},
         /*disabled_features=*/{features::kAutofillProfileClientValidation,
                                features::kAutofillSuppressDisusedAddresses});
-
-    std::vector<Suggestion> suggestions = personal_data_->GetProfileSuggestions(
-        AutofillType(EMAIL_ADDRESS), base::string16(), false,
-        std::vector<ServerFieldType>());
+    LOG(ERROR) << __FUNCTION__;
+    std::vector<Suggestion> email_suggestions =
+        personal_data_->GetProfileSuggestions(AutofillType(EMAIL_ADDRESS),
+                                              base::string16(), false,
+                                              std::vector<ServerFieldType>());
 
     for (auto* profile : profiles) {
       ASSERT_EQ(profile->guid() == valid_profile.guid(),
@@ -2397,9 +2426,17 @@
       ASSERT_EQ(profile->guid() == valid_profile.guid(),
                 profile->IsValidByServer());
     }
-    ASSERT_EQ(2U, suggestions.size());
-    EXPECT_EQ(base::ASCIIToUTF16("alice@wonderland.ca"), suggestions[0].value);
-    EXPECT_EQ(base::ASCIIToUTF16("invalid email"), suggestions[1].value);
+    ASSERT_EQ(1U, email_suggestions.size());
+    EXPECT_EQ(base::ASCIIToUTF16("alice@wonderland.ca"),
+              email_suggestions[0].value);
+
+    std::vector<Suggestion> name_suggestions =
+        personal_data_->GetProfileSuggestions(AutofillType(NAME_FIRST),
+                                              base::string16(), false,
+                                              std::vector<ServerFieldType>());
+    ASSERT_EQ(2U, name_suggestions.size());
+    EXPECT_EQ(base::ASCIIToUTF16("Alice"), name_suggestions[0].value);
+    EXPECT_EQ(base::ASCIIToUTF16("Marion1"), name_suggestions[1].value);
   }
 }
 
@@ -6950,10 +6987,10 @@
   std::vector<ServerFieldType> types = {
       ADDRESS_HOME_LINE1, ADDRESS_HOME_STATE, ADDRESS_HOME_COUNTRY,
       EMAIL_ADDRESS,      ADDRESS_HOME_ZIP,   NAME_FULL};
-  std::vector<AutofillProfile::ValidityState> states = {
-      AutofillProfile::UNSUPPORTED, AutofillProfile::EMPTY,
-      AutofillProfile::INVALID,     AutofillProfile::VALID,
-      AutofillProfile::UNVALIDATED, AutofillProfile::INVALID};
+  std::vector<AutofillDataModel::ValidityState> states = {
+      AutofillDataModel::UNSUPPORTED, AutofillDataModel::EMPTY,
+      AutofillDataModel::INVALID,     AutofillDataModel::VALID,
+      AutofillDataModel::UNVALIDATED, AutofillDataModel::INVALID};
   ASSERT_EQ(types.size(), states.size());
   for (unsigned long i = 0; i < types.size(); ++i) {
     (*profile_validity_map
@@ -6974,7 +7011,7 @@
   autofill_profile_validity.clear();
   (*profile_validity_map
         .mutable_field_validity_states())[static_cast<int>(EMAIL_ADDRESS)] =
-      static_cast<int>(AutofillProfile::VALID);
+      static_cast<int>(AutofillDataModel::VALID);
   (*user_profile_validity_map.mutable_profile_validity())[guid] =
       profile_validity_map;
   ASSERT_TRUE(
@@ -7001,7 +7038,7 @@
   validities =
       personal_data_->GetProfileValidityByGUID(guid).field_validity_states();
   ASSERT_FALSE(validities.empty());
-  EXPECT_EQ(validities.at(EMAIL_ADDRESS), AutofillProfile::VALID);
+  EXPECT_EQ(validities.at(EMAIL_ADDRESS), AutofillDataModel::VALID);
 }
 
 // Use the client side validation API to validate three PDM profiles. This one
@@ -7024,25 +7061,25 @@
   ASSERT_EQ(1U, profiles.size());
 
   EXPECT_TRUE(profiles[0]->is_client_validity_states_updated());
-  EXPECT_EQ(AutofillProfile::VALID,
+  EXPECT_EQ(AutofillDataModel::VALID,
             profiles[0]->GetValidityState(ADDRESS_HOME_COUNTRY,
                                           AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::INVALID,
+  EXPECT_EQ(AutofillDataModel::INVALID,
             profiles[0]->GetValidityState(ADDRESS_HOME_STATE,
                                           AutofillProfile::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
+      AutofillDataModel::VALID,
       profiles[0]->GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::INVALID,
+  EXPECT_EQ(AutofillDataModel::INVALID,
             profiles[0]->GetValidityState(ADDRESS_HOME_CITY,
                                           AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::EMPTY,
+  EXPECT_EQ(AutofillDataModel::EMPTY,
             profiles[0]->GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY,
                                           AutofillProfile::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::VALID,
+      AutofillDataModel::VALID,
       profiles[0]->GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::VALID,
+  EXPECT_EQ(AutofillDataModel::VALID,
             profiles[0]->GetValidityState(PHONE_HOME_WHOLE_NUMBER,
                                           AutofillProfile::CLIENT));
 }
@@ -7110,7 +7147,7 @@
   ASSERT_EQ(1U, profiles.size());
   // The validities were updated when the profile was added.
   EXPECT_EQ(
-      AutofillProfile::INVALID,
+      AutofillDataModel::INVALID,
       profiles[0]->GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT));
 
   // Change the email, the validity update would turn false.
@@ -7126,7 +7163,7 @@
   profiles = personal_data_->GetProfiles();
   ASSERT_EQ(1U, profiles.size());
   EXPECT_EQ(
-      AutofillProfile::INVALID,
+      AutofillDataModel::INVALID,
       profiles[0]->GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT));
 
   // Try with the flag as not updated.
@@ -7137,7 +7174,7 @@
   profiles = personal_data_->GetProfiles();
   ASSERT_EQ(1U, profiles.size());
   EXPECT_EQ(
-      AutofillProfile::VALID,
+      AutofillDataModel::VALID,
       profiles[0]->GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT));
 }
 
@@ -7200,17 +7237,17 @@
   // Verify that the version of the last update is set to this version.
   EXPECT_EQ(CHROME_VERSION_MAJOR, GetLastVersionValidatedUpdate());
 
-  EXPECT_EQ(AutofillProfile::VALID,
+  EXPECT_EQ(AutofillDataModel::VALID,
             profiles[0]->GetValidityState(ADDRESS_HOME_COUNTRY,
                                           AutofillProfile::CLIENT));
   EXPECT_EQ(
-      AutofillProfile::INVALID,
+      AutofillDataModel::INVALID,
       profiles[0]->GetValidityState(EMAIL_ADDRESS, AutofillProfile::CLIENT));
 
-  EXPECT_EQ(AutofillProfile::VALID,
+  EXPECT_EQ(AutofillDataModel::VALID,
             profiles[1]->GetValidityState(ADDRESS_HOME_COUNTRY,
                                           AutofillProfile::CLIENT));
-  EXPECT_EQ(AutofillProfile::INVALID,
+  EXPECT_EQ(AutofillDataModel::INVALID,
             profiles[1]->GetValidityState(ADDRESS_HOME_STATE,
                                           AutofillProfile::CLIENT));
 }
@@ -7271,7 +7308,7 @@
   personal_data_->UpdateClientValidityStates(profiles);
 
   EXPECT_FALSE(profiles[0]->is_client_validity_states_updated());
-  EXPECT_EQ(AutofillProfile::UNVALIDATED,
+  EXPECT_EQ(AutofillDataModel::UNVALIDATED,
             profiles[0]->GetValidityState(ADDRESS_HOME_COUNTRY,
                                           AutofillProfile::CLIENT));
 }
@@ -7428,7 +7465,7 @@
     EXPECT_FALSE(personal_data_->ShouldShowCardsFromAccountOption());
     // The metric should not be logged if the user had no server cards.
     histogram_tester.ExpectTotalCount(kHistogramName, 0);
-  };
+  }
 
   // Re-set some server cards. Check that the function now returns true.
   SetServerCards(server_cards);
diff --git a/components/autofill/core/browser/suggestion_selection.cc b/components/autofill/core/browser/suggestion_selection.cc
index 354c174..c4f1237 100644
--- a/components/autofill/core/browser/suggestion_selection.cc
+++ b/components/autofill/core/browser/suggestion_selection.cc
@@ -69,6 +69,23 @@
                      matched_profiles->size() < kMaxSuggestedProfilesCount;
        i++) {
     AutofillProfile* profile = profiles[i];
+    bool use_server_validation = base::FeatureList::IsEnabled(
+        autofill::features::kAutofillProfileServerValidation);
+    bool use_client_validation = base::FeatureList::IsEnabled(
+        autofill::features::kAutofillProfileClientValidation);
+
+    ServerFieldType server_field_type = type.GetStorableType();
+    if ((use_client_validation &&
+         profile->GetValidityState(server_field_type,
+                                   AutofillProfile::CLIENT) ==
+             AutofillProfile::INVALID) ||
+        (use_server_validation &&
+         profile->GetValidityState(server_field_type,
+                                   AutofillProfile::SERVER) ==
+             AutofillProfile::INVALID)) {
+      continue;
+    }
+
     base::string16 value =
         GetInfoInOneLine(profile, type, comparator.app_locale());
     if (value.empty())
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc b/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
index 297d627..7b88c1b8 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
+++ b/components/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.cc
@@ -567,8 +567,11 @@
         server_id, sync_pb::WalletMetadataSpecifics::CARD, &cache_);
     if (it == cache_.end())
       return;
-    // Implicitly, we filter out ADD (not in cache) and REMOVE (!data_model()).
-    DCHECK(change.type() == AutofillProfileChange::UPDATE);
+    // Deletions and creations are treated by Wallet data sync (and propagated
+    // here by AutofillMultipleChanged()). We only treat updates here.
+    if (change.type() != AutofillProfileChange::UPDATE) {
+      return;
+    }
 
     const sync_pb::WalletMetadataSpecifics& remote =
         it->GetSpecifics().wallet_metadata();
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc
index 8d29299c..733c205 100644
--- a/components/browser_sync/profile_sync_service.cc
+++ b/components/browser_sync/profile_sync_service.cc
@@ -1908,12 +1908,25 @@
 
 void ProfileSyncService::StopAndClear() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(!is_stopping_and_clearing_);
+
+  // This can happen if the user had disabled sync before and is now setting up
+  // sync again but hits the "Cancel" button on the confirmation dialog.
+  // TODO(crbug.com/906034): Maybe we can streamline the defaults and the
+  // behavior on setting up sync so that either this whole early return goes
+  // away or it treats all "Cancel the confirmation" cases?
+  if (!user_settings_->IsSyncRequested()) {
+    StopImpl(CLEAR_DATA);
+    return;
+  }
+
   // We need to remember that clearing of data is needed when sync will be
   // stopped. This flag is cleared in OnSyncRequestedPrefChange() where sync
-  // gets stopped.
+  // gets stopped. This happens synchronously when |user_settings_| get changed
+  // below.
+  DCHECK(!is_stopping_and_clearing_);
   is_stopping_and_clearing_ = true;
   user_settings_->SetSyncRequested(false);
+  DCHECK(!is_stopping_and_clearing_);
 }
 
 void ProfileSyncService::ReconfigureDatatypeManager(
diff --git a/components/browser_sync/profile_sync_service_unittest.cc b/components/browser_sync/profile_sync_service_unittest.cc
index e43ed67..2321e122b 100644
--- a/components/browser_sync/profile_sync_service_unittest.cc
+++ b/components/browser_sync/profile_sync_service_unittest.cc
@@ -951,6 +951,28 @@
   EXPECT_TRUE(local_device_info_provider()->GetLocalDeviceInfo());
 }
 
+TEST_F(ProfileSyncServiceWithStandaloneTransportTest, CancelSyncAfterSignOut) {
+  SignIn();
+  CreateService(ProfileSyncService::AUTO_START);
+  InitializeForNthSync();
+  ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
+            service()->GetTransportState());
+  base::Time last_synced_time = service()->GetLastSyncedTime();
+  ASSERT_LT(base::Time::Now() - last_synced_time,
+            base::TimeDelta::FromMinutes(1));
+
+  // Disable sync.
+  service()->StopAndClear();
+  EXPECT_FALSE(service()->IsSyncFeatureEnabled());
+
+  // Calling StopAndClear while already stopped should not crash. This may
+  // (under some circumstances) happen when the user enables sync again but hits
+  // the cancel button at the end of the process.
+  ASSERT_FALSE(service()->GetUserSettings()->IsSyncRequested());
+  service()->StopAndClear();
+  EXPECT_FALSE(service()->IsSyncFeatureEnabled());
+}
+
 // Verify that credential errors get returned from GetAuthError().
 TEST_F(ProfileSyncServiceTest, CredentialErrorReturned) {
   // This test needs to manually send access tokens (or errors), so disable
diff --git a/components/content_settings/core/browser/content_settings_pref_unittest.cc b/components/content_settings/core/browser/content_settings_pref_unittest.cc
index 0291514..652a041e 100644
--- a/components/content_settings/core/browser/content_settings_pref_unittest.cc
+++ b/components/content_settings/core/browser/content_settings_pref_unittest.cc
@@ -109,8 +109,7 @@
   }
 
   TestingPrefServiceSimple prefs;
-  prefs.registry()->RegisterDictionaryPref(
-      kTestContentSettingPrefName, std::make_unique<base::DictionaryValue>());
+  prefs.registry()->RegisterDictionaryPref(kTestContentSettingPrefName);
   prefs.SetUserPref(kTestContentSettingPrefName,
                     std::move(original_pref_value));
 
diff --git a/components/cronet/cronet_prefs_manager.cc b/components/cronet/cronet_prefs_manager.cc
index cc9326c..77569a88 100644
--- a/components/cronet/cronet_prefs_manager.cc
+++ b/components/cronet/cronet_prefs_manager.cc
@@ -240,8 +240,7 @@
   PrefServiceFactory factory;
   factory.set_user_prefs(json_pref_store_);
   scoped_refptr<PrefRegistrySimple> registry(new PrefRegistrySimple());
-  registry->RegisterDictionaryPref(kHttpServerPropertiesPref,
-                                   std::make_unique<base::DictionaryValue>());
+  registry->RegisterDictionaryPref(kHttpServerPropertiesPref);
 
   if (enable_network_quality_estimator) {
     // Use lossy prefs to limit the overhead of reading/writing the prefs.
diff --git a/components/dom_distiller/content/renderer/distiller_native_javascript.cc b/components/dom_distiller/content/renderer/distiller_native_javascript.cc
index 7493fff..379776d 100644
--- a/components/dom_distiller/content/renderer/distiller_native_javascript.cc
+++ b/components/dom_distiller/content/renderer/distiller_native_javascript.cc
@@ -34,7 +34,7 @@
   v8::Context::Scope context_scope(context);
 
   v8::Local<v8::Object> distiller_obj =
-      GetOrCreateDistillerObject(isolate, context->Global());
+      GetOrCreateDistillerObject(isolate, context);
 
   EnsureServiceConnected();
 
@@ -56,10 +56,12 @@
     const base::Callback<Sig> callback) {
   v8::Local<v8::Context> context = isolate->GetCurrentContext();
   // Get the isolate associated with this object.
-  javascript_object->Set(gin::StringToSymbol(isolate, name),
-                         gin::CreateFunctionTemplate(isolate, callback)
-                             ->GetFunction(context)
-                             .ToLocalChecked());
+  javascript_object
+      ->Set(context, gin::StringToSymbol(isolate, name),
+            gin::CreateFunctionTemplate(isolate, callback)
+                ->GetFunction(context)
+                .ToLocalChecked())
+      .Check();
 }
 
 void DistillerNativeJavaScript::EnsureServiceConnected() {
@@ -68,14 +70,19 @@
   }
 }
 
-v8::Local<v8::Object> GetOrCreateDistillerObject(v8::Isolate* isolate,
-                                                 v8::Local<v8::Object> global) {
+v8::Local<v8::Object> GetOrCreateDistillerObject(
+    v8::Isolate* isolate,
+    v8::Local<v8::Context> context) {
+  v8::Local<v8::Object> global = context->Global();
   v8::Local<v8::Object> distiller_obj;
-  v8::Local<v8::Value> distiller_value =
-      global->Get(gin::StringToV8(isolate, "distiller"));
-  if (distiller_value.IsEmpty() || !distiller_value->IsObject()) {
+  v8::Local<v8::Value> distiller_value;
+  if (!global->Get(context, gin::StringToV8(isolate, "distiller"))
+           .ToLocal(&distiller_value) ||
+      !distiller_value->IsObject()) {
     distiller_obj = v8::Object::New(isolate);
-    global->Set(gin::StringToSymbol(isolate, "distiller"), distiller_obj);
+    global
+        ->Set(context, gin::StringToSymbol(isolate, "distiller"), distiller_obj)
+        .Check();
   } else {
     distiller_obj = v8::Local<v8::Object>::Cast(distiller_value);
   }
diff --git a/components/dom_distiller/content/renderer/distiller_native_javascript.h b/components/dom_distiller/content/renderer/distiller_native_javascript.h
index ecea477..4640d71 100644
--- a/components/dom_distiller/content/renderer/distiller_native_javascript.h
+++ b/components/dom_distiller/content/renderer/distiller_native_javascript.h
@@ -39,8 +39,9 @@
 };
 
 // static
-v8::Local<v8::Object> GetOrCreateDistillerObject(v8::Isolate* isolate,
-                                                 v8::Local<v8::Object> global);
+v8::Local<v8::Object> GetOrCreateDistillerObject(
+    v8::Isolate* isolate,
+    v8::Local<v8::Context> context);
 
 }  // namespace dom_distiller
 
diff --git a/components/flags_ui/resources/flags.js b/components/flags_ui/resources/flags.js
index adbd575..c993e96 100644
--- a/components/flags_ui/resources/flags.js
+++ b/components/flags_ui/resources/flags.js
@@ -39,6 +39,9 @@
         $('tab-content-unavailable'));
   }
 
+  // Update the restart container.
+  jstProcess(new JsEvalContext(experimentalFeaturesData), $('needs-restart'));
+
   // Add handlers to dynamically created HTML elements.
   var elements = document.getElementsByClassName('experiment-select');
   for (var i = 0; i < elements.length; ++i) {
diff --git a/components/infobars/core/infobar_delegate.h b/components/infobars/core/infobar_delegate.h
index 5a0576c8..fbb4f3c 100644
--- a/components/infobars/core/infobar_delegate.h
+++ b/components/infobars/core/infobar_delegate.h
@@ -157,6 +157,8 @@
     NEAR_OOM_REDUCTION_INFOBAR_ANDROID = 86,
     LITE_PAGE_PREVIEWS_INFOBAR = 87,
     MODULE_INSTALL_FAILURE_INFOBAR_ANDROID = 88,
+    INLINE_UPDATE_READY_INFOBAR_ANDROID = 89,
+    INLINE_UPDATE_FAILED_INFOBAR_ANDROID = 90,
   };
 
   // Describes navigation events, used to decide whether infobars should be
diff --git a/components/ntp_tiles/popular_sites_impl.cc b/components/ntp_tiles/popular_sites_impl.cc
index 5ce49d8..4d6c754 100644
--- a/components/ntp_tiles/popular_sites_impl.cc
+++ b/components/ntp_tiles/popular_sites_impl.cc
@@ -214,12 +214,12 @@
 #endif
 
 // Creates the list of popular sites based on a snapshot available for mobile.
-std::unique_ptr<base::ListValue> DefaultPopularSites() {
+base::Value DefaultPopularSites() {
 #if !defined(OS_ANDROID) && !defined(OS_IOS)
-  return std::make_unique<base::ListValue>();
+  return base::Value(base::Value::Type::LIST);
 #else
   if (!base::FeatureList::IsEnabled(kPopularSitesBakedInContentFeature)) {
-    return std::make_unique<base::ListValue>();
+    return base::Value(base::Value::Type::LIST);
   }
   std::unique_ptr<base::ListValue> sites =
       base::ListValue::From(base::JSONReader::Read(
@@ -240,7 +240,7 @@
     SetDefaultResourceForSite(index++, icon_resource, sites.get());
   }
 #endif  // GOOGLE_CHROME_BUILD
-  return sites;
+  return base::Value::FromUniquePtrValue(std::move(sites));
 #endif  // OS_ANDROID || OS_IOS
 }
 
diff --git a/components/policy/content/policy_blacklist_service.h b/components/policy/content/policy_blacklist_service.h
index 9d36c38..b294f86 100644
--- a/components/policy/content/policy_blacklist_service.h
+++ b/components/policy/content/policy_blacklist_service.h
@@ -21,8 +21,7 @@
 // PolicyBlacklistService and PolicyBlacklistFactory provide a way for
 // us to access URLBlacklistManager, a policy block list service based on
 // the Preference Service. The URLBlacklistManager responds to permission
-// changes and is per-Profile. The PolicyBlacklistNavigationThrottle accesses
-// this service to determine what we should block.
+// changes and is per-Profile.
 class PolicyBlacklistService : public KeyedService {
  public:
   using CheckSafeSearchCallback = base::OnceCallback<void(bool is_safe)>;
diff --git a/components/policy/core/common/BUILD.gn b/components/policy/core/common/BUILD.gn
index f9005485..05b89101 100644
--- a/components/policy/core/common/BUILD.gn
+++ b/components/policy/core/common/BUILD.gn
@@ -156,6 +156,7 @@
     "//components/crash/core/common:crash_key",  # Remove once https://crbug.com/685996 is fixed.
     "//components/data_use_measurement/core",
     "//components/prefs",
+    "//components/strings",
     "//components/version_info",
     "//extensions/buildflags",
     "//google_apis",
@@ -294,6 +295,7 @@
     "//components/account_id",
     "//components/policy:generated",
     "//components/policy/proto",
+    "//components/strings",
     "//crypto",
     "//net",
     "//services/network/public/cpp",
diff --git a/components/policy/core/common/DEPS b/components/policy/core/common/DEPS
index ccec57e6f..d64281e 100644
--- a/components/policy/core/common/DEPS
+++ b/components/policy/core/common/DEPS
@@ -1,6 +1,7 @@
 include_rules = [
   "+components/account_id",
   "-components/policy/core/browser",
+  "+components/strings",
   "+components/crash/core/common/crash_key.h",  # Remove once https://crbug.com/685996 is fixed.
   "+components/data_use_measurement/core",
   "+extensions/buildflags",
diff --git a/components/policy/core/common/config_dir_policy_loader_unittest.cc b/components/policy/core/common/config_dir_policy_loader_unittest.cc
index 56edbe4..1f3d434 100644
--- a/components/policy/core/common/config_dir_policy_loader_unittest.cc
+++ b/components/policy/core/common/config_dir_policy_loader_unittest.cc
@@ -21,6 +21,7 @@
 #include "components/policy/core/common/policy_bundle.h"
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/core/common/policy_types.h"
+#include "components/strings/grit/components_strings.h"
 
 namespace policy {
 
@@ -242,7 +243,7 @@
   for (unsigned int i = 1; i <= 8; ++i) {
     expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
         .GetMutable(kHomepageLocation)
-        ->AddError(kPolicyConfictDiffValue);
+        ->AddError(IDS_POLICY_CONFLICT_DIFF_VALUE);
   }
   EXPECT_TRUE(bundle->Equals(expected_bundle));
 }
diff --git a/components/policy/core/common/policy_bundle_unittest.cc b/components/policy/core/common/policy_bundle_unittest.cc
index ab6bd0a9..ce44509 100644
--- a/components/policy/core/common/policy_bundle_unittest.cc
+++ b/components/policy/core/common/policy_bundle_unittest.cc
@@ -12,6 +12,7 @@
 #include "components/policy/core/common/external_data_fetcher.h"
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/core/common/policy_types.h"
+#include "components/strings/grit/components_strings.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace policy {
@@ -192,12 +193,16 @@
   PolicyMap expected;
   expected.Set(kPolicyClashing0, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
                POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(0), nullptr);
-  expected.GetMutable(kPolicyClashing0)->AddError(kPolicyConfictDiffValue);
-  expected.GetMutable(kPolicyClashing0)->AddError(kPolicyConfictDiffValue);
+  expected.GetMutable(kPolicyClashing0)
+      ->AddError(IDS_POLICY_CONFLICT_DIFF_VALUE);
+  expected.GetMutable(kPolicyClashing0)
+      ->AddError(IDS_POLICY_CONFLICT_DIFF_VALUE);
   expected.Set(kPolicyClashing1, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
                POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(1), nullptr);
-  expected.GetMutable(kPolicyClashing1)->AddError(kPolicyConfictSameValue);
-  expected.GetMutable(kPolicyClashing1)->AddError(kPolicyConfictDiffValue);
+  expected.GetMutable(kPolicyClashing1)
+      ->AddError(IDS_POLICY_CONFLICT_SAME_VALUE);
+  expected.GetMutable(kPolicyClashing1)
+      ->AddError(IDS_POLICY_CONFLICT_DIFF_VALUE);
   expected.Set(kPolicy0, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
                POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(0), nullptr);
   expected.Set(kPolicy1, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
diff --git a/components/policy/core/common/policy_loader_win_unittest.cc b/components/policy/core/common/policy_loader_win_unittest.cc
index 04b2975..f2bbb23 100644
--- a/components/policy/core/common/policy_loader_win_unittest.cc
+++ b/components/policy/core/common/policy_loader_win_unittest.cc
@@ -38,6 +38,7 @@
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/core/common/policy_types.h"
 #include "components/policy/core/common/schema_map.h"
+#include "components/strings/grit/components_strings.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using base::UTF8ToUTF16;
@@ -450,7 +451,7 @@
            nullptr);
   expected.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
       .GetMutable(test_keys::kKeyString)
-      ->AddError(kPolicyConfictDiffValue);
+      ->AddError(IDS_POLICY_CONFLICT_DIFF_VALUE);
   EXPECT_TRUE(Matches(expected));
 }
 
@@ -503,19 +504,19 @@
   expected_policy.Set(
       "a", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_PLATFORM,
       std::make_unique<base::Value>(kMachineMandatory), nullptr);
-  expected_policy.GetMutable("a")->AddError(kPolicyConfictDiffValue);
-  expected_policy.GetMutable("a")->AddError(kPolicyConfictDiffValue);
-  expected_policy.GetMutable("a")->AddError(kPolicyConfictDiffValue);
+  expected_policy.GetMutable("a")->AddError(IDS_POLICY_CONFLICT_DIFF_VALUE);
+  expected_policy.GetMutable("a")->AddError(IDS_POLICY_CONFLICT_DIFF_VALUE);
+  expected_policy.GetMutable("a")->AddError(IDS_POLICY_CONFLICT_DIFF_VALUE);
   expected_policy.Set("b", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
                       POLICY_SOURCE_PLATFORM,
                       std::make_unique<base::Value>(kUserMandatory), nullptr);
-  expected_policy.GetMutable("b")->AddError(kPolicyConfictSameValue);
-  expected_policy.GetMutable("b")->AddError(kPolicyConfictDiffValue);
+  expected_policy.GetMutable("b")->AddError(IDS_POLICY_CONFLICT_SAME_VALUE);
+  expected_policy.GetMutable("b")->AddError(IDS_POLICY_CONFLICT_DIFF_VALUE);
   expected_policy.Set("c", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE,
                       POLICY_SOURCE_PLATFORM,
                       std::make_unique<base::Value>(kMachineRecommended),
                       nullptr);
-  expected_policy.GetMutable("c")->AddError(kPolicyConfictDiffValue);
+  expected_policy.GetMutable("c")->AddError(IDS_POLICY_CONFLICT_DIFF_VALUE);
   expected_policy.Set("d", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
                       POLICY_SOURCE_PLATFORM,
                       std::make_unique<base::Value>(kUserRecommended), nullptr);
diff --git a/components/policy/core/common/policy_map.cc b/components/policy/core/common/policy_map.cc
index ac08a70..8e4b97739 100644
--- a/components/policy/core/common/policy_map.cc
+++ b/components/policy/core/common/policy_map.cc
@@ -10,16 +10,9 @@
 #include "base/stl_util.h"
 #include "base/strings/strcat.h"
 #include "base/strings/utf_string_conversions.h"
+#include "components/strings/grit/components_strings.h"
 
 namespace policy {
-
-const char kPolicyConfictSameValue[] =
-    "Warning: More than one source is present for the policy, but the values "
-    "are the same.";
-const char kPolicyConfictDiffValue[] =
-    "Warning: More than one source with conflicting values is present for this "
-    "policy!";
-
 PolicyMap::Entry::Entry() = default;
 
 PolicyMap::Entry::~Entry() = default;
@@ -184,11 +177,10 @@
     if (!entry || it.second.has_higher_priority_than(*entry))
       Set(it.first, it.second.DeepCopy());
     if (entry) {
-      // TODO(pastarmovj): Figure out a way to localize those errors.
       if (entry->value && it.second.value->Equals(entry->value.get()))
-        GetMutable(it.first)->AddError(kPolicyConfictSameValue);
+        GetMutable(it.first)->AddError(IDS_POLICY_CONFLICT_SAME_VALUE);
       else
-        GetMutable(it.first)->AddError(kPolicyConfictDiffValue);
+        GetMutable(it.first)->AddError(IDS_POLICY_CONFLICT_DIFF_VALUE);
     }
   }
 }
diff --git a/components/policy/core/common/policy_map.h b/components/policy/core/common/policy_map.h
index 4df7fb7..f693073a 100644
--- a/components/policy/core/common/policy_map.h
+++ b/components/policy/core/common/policy_map.h
@@ -21,9 +21,6 @@
 
 namespace policy {
 
-POLICY_EXPORT extern const char kPolicyConfictSameValue[];
-POLICY_EXPORT extern const char kPolicyConfictDiffValue[];
-
 // A mapping of policy names to policy values for a given policy namespace.
 class POLICY_EXPORT PolicyMap {
  public:
diff --git a/components/policy/core/common/policy_map_unittest.cc b/components/policy/core/common/policy_map_unittest.cc
index d37eb68b..1d7857b 100644
--- a/components/policy/core/common/policy_map_unittest.cc
+++ b/components/policy/core/common/policy_map_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "components/policy/core/common/external_data_manager.h"
 #include "components/policy/core/common/policy_types.h"
+#include "components/strings/grit/components_strings.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace policy {
@@ -238,25 +239,25 @@
   c.Set(kTestPolicyName1, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
         POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("chromium.org"),
         nullptr);
-  c.GetMutable(kTestPolicyName1)->AddError(kPolicyConfictSameValue);
+  c.GetMutable(kTestPolicyName1)->AddError(IDS_POLICY_CONFLICT_SAME_VALUE);
   // |a| has precedence over |b|.
   c.Set(kTestPolicyName2, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
         POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(true), nullptr);
-  c.GetMutable(kTestPolicyName2)->AddError(kPolicyConfictDiffValue);
+  c.GetMutable(kTestPolicyName2)->AddError(IDS_POLICY_CONFLICT_DIFF_VALUE);
   c.Set(kTestPolicyName3, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
         POLICY_SOURCE_ENTERPRISE_DEFAULT, nullptr,
         CreateExternalDataFetcher("a"));
-  c.GetMutable(kTestPolicyName3)->AddError(kPolicyConfictDiffValue);
+  c.GetMutable(kTestPolicyName3)->AddError(IDS_POLICY_CONFLICT_DIFF_VALUE);
   // POLICY_SCOPE_MACHINE over POLICY_SCOPE_USER for POLICY_LEVEL_RECOMMENDED.
   c.Set(kTestPolicyName4, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE,
         POLICY_SOURCE_PUBLIC_SESSION_OVERRIDE,
         std::make_unique<base::Value>(true), nullptr);
-  c.GetMutable(kTestPolicyName4)->AddError(kPolicyConfictSameValue);
+  c.GetMutable(kTestPolicyName4)->AddError(IDS_POLICY_CONFLICT_SAME_VALUE);
   // POLICY_LEVEL_MANDATORY over POLICY_LEVEL_RECOMMENDED.
   c.Set(kTestPolicyName5, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
         POLICY_SOURCE_PLATFORM, std::make_unique<base::Value>(std::string()),
         nullptr);
-  c.GetMutable(kTestPolicyName5)->AddError(kPolicyConfictSameValue);
+  c.GetMutable(kTestPolicyName5)->AddError(IDS_POLICY_CONFLICT_SAME_VALUE);
   // Merge new ones.
   c.Set(kTestPolicyName6, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
         POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(true), nullptr);
@@ -264,7 +265,7 @@
   c.Set(kTestPolicyName7, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
         POLICY_SOURCE_ACTIVE_DIRECTORY, std::make_unique<base::Value>(true),
         nullptr);
-  c.GetMutable(kTestPolicyName7)->AddError(kPolicyConfictSameValue);
+  c.GetMutable(kTestPolicyName7)->AddError(IDS_POLICY_CONFLICT_SAME_VALUE);
 
   EXPECT_TRUE(a.Equals(c));
 }
diff --git a/components/policy/core/common/policy_service_impl_unittest.cc b/components/policy/core/common/policy_service_impl_unittest.cc
index 323a6fe..0aec35e9 100644
--- a/components/policy/core/common/policy_service_impl_unittest.cc
+++ b/components/policy/core/common/policy_service_impl_unittest.cc
@@ -19,6 +19,7 @@
 #include "components/policy/core/common/mock_policy_service.h"
 #include "components/policy/core/common/policy_types.h"
 #include "components/policy/policy_constants.h"
+#include "components/strings/grit/components_strings.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -362,8 +363,8 @@
                std::make_unique<base::Value>(13), nullptr);
   expected.Set("aaa", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
                POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(0), nullptr);
-  expected.GetMutable("aaa")->AddError(kPolicyConfictDiffValue);
-  expected.GetMutable("aaa")->AddError(kPolicyConfictDiffValue);
+  expected.GetMutable("aaa")->AddError(IDS_POLICY_CONFLICT_DIFF_VALUE);
+  expected.GetMutable("aaa")->AddError(IDS_POLICY_CONFLICT_DIFF_VALUE);
   policy0_.Set("aaa", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
                POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(0), nullptr);
   policy1_.Set("aaa", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
@@ -378,7 +379,7 @@
 
   expected.Set("aaa", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
                POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(1), nullptr);
-  expected.GetMutable("aaa")->AddError(kPolicyConfictDiffValue);
+  expected.GetMutable("aaa")->AddError(IDS_POLICY_CONFLICT_DIFF_VALUE);
   policy0_.Erase("aaa");
   provider0_.UpdateChromePolicy(policy0_);
   EXPECT_TRUE(VerifyPolicies(
@@ -386,7 +387,7 @@
 
   expected.Set("aaa", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
                POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(2), nullptr);
-  expected.GetMutable("aaa")->AddError(kPolicyConfictSameValue);
+  expected.GetMutable("aaa")->AddError(IDS_POLICY_CONFLICT_SAME_VALUE);
   policy1_.Set("aaa", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
                POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(1), nullptr);
   provider1_.UpdateChromePolicy(policy1_);
@@ -541,14 +542,17 @@
   expected.Set(kSameLevelPolicy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
                POLICY_SOURCE_ENTERPRISE_DEFAULT,
                std::make_unique<base::Value>("bundle0"), nullptr);
-  expected.GetMutable(kSameLevelPolicy)->AddError(kPolicyConfictDiffValue);
-  expected.GetMutable(kSameLevelPolicy)->AddError(kPolicyConfictDiffValue);
+  expected.GetMutable(kSameLevelPolicy)
+      ->AddError(IDS_POLICY_CONFLICT_DIFF_VALUE);
+  expected.GetMutable(kSameLevelPolicy)
+      ->AddError(IDS_POLICY_CONFLICT_DIFF_VALUE);
   // For policies with different levels and scopes, the highest priority
   // level/scope combination takes precedence, on every namespace.
   expected.Set(kDiffLevelPolicy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
                POLICY_SOURCE_PLATFORM, std::make_unique<base::Value>("bundle2"),
                nullptr);
-  expected.GetMutable(kDiffLevelPolicy)->AddError(kPolicyConfictSameValue);
+  expected.GetMutable(kDiffLevelPolicy)
+      ->AddError(IDS_POLICY_CONFLICT_SAME_VALUE);
   EXPECT_TRUE(policy_service_->GetPolicies(
       PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())).Equals(expected));
   EXPECT_TRUE(policy_service_->GetPolicies(
diff --git a/components/policy/core/common/schema_map_unittest.cc b/components/policy/core/common/schema_map_unittest.cc
index 4be3944..0bee8f3 100644
--- a/components/policy/core/common/schema_map_unittest.cc
+++ b/components/policy/core/common/schema_map_unittest.cc
@@ -13,6 +13,7 @@
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/core/common/policy_types.h"
 #include "components/policy/core/common/schema.h"
+#include "components/strings/grit/components_strings.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace policy {
@@ -184,7 +185,7 @@
   // Merged twice so this causes a conflict.
   expected_bundle.Get(chrome_ns)
       .GetMutable("ChromePolicy")
-      ->AddError(kPolicyConfictSameValue);
+      ->AddError(IDS_POLICY_CONFLICT_SAME_VALUE);
   EXPECT_TRUE(bundle.Equals(expected_bundle));
 
   // Mismatched types are also removed.
diff --git a/components/policy_strings.grdp b/components/policy_strings.grdp
index 492691fd..f12a1af6 100644
--- a/components/policy_strings.grdp
+++ b/components/policy_strings.grdp
@@ -482,4 +482,10 @@
   <message name="IDS_POLICY_HIDE_EXPANDED_STATUS" desc="Text for the link that hides the policy status. Used when the policy status is too long to be always visible.">
     Hide status
   </message>
+  <message name="IDS_POLICY_CONFLICT_SAME_VALUE" desc="Text explaining that a policy had conflicting sources, but with the same values.">
+    Warning: More than one source is present for the policy, but the values are the same.
+  </message>
+  <message name="IDS_POLICY_CONFLICT_DIFF_VALUE" desc="Text explaining that a policy had conflicting sources and values.">
+    Warning: More than one source with conflicting values is present for this policy!
+  </message>
 </grit-part>
diff --git a/components/prefs/pref_member_unittest.cc b/components/prefs/pref_member_unittest.cc
index abdfeab..a7d4a5ea 100644
--- a/components/prefs/pref_member_unittest.cc
+++ b/components/prefs/pref_member_unittest.cc
@@ -29,8 +29,7 @@
   registry->RegisterIntegerPref(kIntPref, 0);
   registry->RegisterDoublePref(kDoublePref, 0.0);
   registry->RegisterStringPref(kStringPref, "default");
-  registry->RegisterListPref(kStringListPref,
-                             std::make_unique<base::ListValue>());
+  registry->RegisterListPref(kStringListPref);
 }
 
 class GetPrefValueHelper
diff --git a/components/prefs/pref_service_unittest.cc b/components/prefs/pref_service_unittest.cc
index 3e6c1916..3bdcf35 100644
--- a/components/prefs/pref_service_unittest.cc
+++ b/components/prefs/pref_service_unittest.cc
@@ -381,7 +381,6 @@
   for (size_t i = 0; i < base::size(kRegistrationToWriteFlags); ++i) {
     RegistrationToWriteFlags entry = kRegistrationToWriteFlags[i];
     registry->RegisterDictionaryPref(entry.pref_name,
-                                     std::make_unique<base::DictionaryValue>(),
                                      entry.registration_flags);
 
     SCOPED_TRACE("Currently testing pref with name: " +
diff --git a/components/prefs/scoped_user_pref_update_unittest.cc b/components/prefs/scoped_user_pref_update_unittest.cc
index 0fcfbd6..fa1dc71 100644
--- a/components/prefs/scoped_user_pref_update_unittest.cc
+++ b/components/prefs/scoped_user_pref_update_unittest.cc
@@ -81,12 +81,13 @@
 }
 
 TEST_F(ScopedUserPrefUpdateTest, UpdatingListPrefWithDefaults) {
-  auto defaults = std::make_unique<base::ListValue>();
-  defaults->GetList().emplace_back("firstvalue");
-  defaults->GetList().emplace_back("secondvalue");
+  base::Value::ListStorage defaults;
+  defaults.emplace_back("firstvalue");
+  defaults.emplace_back("secondvalue");
 
   std::string pref_name = "mypref";
-  prefs_.registry()->RegisterListPref(pref_name, std::move(defaults));
+  prefs_.registry()->RegisterListPref(pref_name,
+                                      base::Value(std::move(defaults)));
   EXPECT_EQ(2u, prefs_.GetList(pref_name)->GetList().size());
 
   ListPrefUpdate update(&prefs_, pref_name);
@@ -95,9 +96,9 @@
 }
 
 TEST_F(ScopedUserPrefUpdateTest, UpdatingDictionaryPrefWithDefaults) {
-  auto defaults = std::make_unique<base::DictionaryValue>();
-  defaults->SetKey("firstkey", base::Value("value"));
-  defaults->SetKey("secondkey", base::Value("value"));
+  base::Value defaults(base::Value::Type::DICTIONARY);
+  defaults.SetKey("firstkey", base::Value("value"));
+  defaults.SetKey("secondkey", base::Value("value"));
 
   std::string pref_name = "mypref";
   prefs_.registry()->RegisterDictionaryPref(pref_name, std::move(defaults));
diff --git a/components/proxy_config/pref_proxy_config_tracker_impl.cc b/components/proxy_config/pref_proxy_config_tracker_impl.cc
index 924105e..82c2af04 100644
--- a/components/proxy_config/pref_proxy_config_tracker_impl.cc
+++ b/components/proxy_config/pref_proxy_config_tracker_impl.cc
@@ -236,17 +236,15 @@
 
 // static
 void PrefProxyConfigTrackerImpl::RegisterPrefs(PrefRegistrySimple* registry) {
-  registry->RegisterDictionaryPref(
-      proxy_config::prefs::kProxy,
-      std::make_unique<base::Value>(ProxyConfigDictionary::CreateSystem()));
+  registry->RegisterDictionaryPref(proxy_config::prefs::kProxy,
+                                   ProxyConfigDictionary::CreateSystem());
 }
 
 // static
 void PrefProxyConfigTrackerImpl::RegisterProfilePrefs(
     PrefRegistrySimple* registry) {
-  registry->RegisterDictionaryPref(
-      proxy_config::prefs::kProxy,
-      std::make_unique<base::Value>(ProxyConfigDictionary::CreateSystem()));
+  registry->RegisterDictionaryPref(proxy_config::prefs::kProxy,
+                                   ProxyConfigDictionary::CreateSystem());
   registry->RegisterBooleanPref(proxy_config::prefs::kUseSharedProxies, false);
 }
 
diff --git a/components/signin/core/browser/BUILD.gn b/components/signin/core/browser/BUILD.gn
index bdf504e..8bd17392 100644
--- a/components/signin/core/browser/BUILD.gn
+++ b/components/signin/core/browser/BUILD.gn
@@ -152,8 +152,6 @@
     "signin_status_metrics_provider_base.h",
     "signin_status_metrics_provider_delegate.cc",
     "signin_status_metrics_provider_delegate.h",
-    "signin_tracker.cc",
-    "signin_tracker.h",
     "webdata/token_service_table.cc",
     "webdata/token_service_table.h",
     "webdata/token_web_data.cc",
@@ -275,7 +273,6 @@
     "signin_manager_unittest.cc",
     "signin_metrics_unittest.cc",
     "signin_status_metrics_provider_unittest.cc",
-    "signin_tracker_unittest.cc",
     "ubertoken_fetcher_impl_unittest.cc",
     "webdata/token_service_table_unittest.cc",
   ]
diff --git a/components/signin/core/browser/account_reconcilor.cc b/components/signin/core/browser/account_reconcilor.cc
index 0393eb4d..501ec3dd 100644
--- a/components/signin/core/browser/account_reconcilor.cc
+++ b/components/signin/core/browser/account_reconcilor.cc
@@ -27,6 +27,7 @@
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/google_service_auth_error.h"
+#include "services/identity/public/cpp/accounts_in_cookie_jar_info.h"
 #include "services/identity/public/cpp/accounts_mutator.h"
 
 using signin::AccountReconcilorDelegate;
@@ -194,7 +195,6 @@
       client_(client),
       cookie_manager_service_(cookie_manager_service),
       registered_with_identity_manager_(false),
-      registered_with_cookie_manager_service_(false),
       registered_with_content_settings_(false),
       is_reconcile_started_(false),
       first_execution_(true),
@@ -216,7 +216,6 @@
   VLOG(1) << "AccountReconcilor::~AccountReconcilor";
   // Make sure shutdown was called first.
   DCHECK(!registered_with_identity_manager_);
-  DCHECK(!registered_with_cookie_manager_service_);
 }
 
 void AccountReconcilor::Initialize(bool start_reconcile_if_tokens_available) {
@@ -238,14 +237,12 @@
 
 void AccountReconcilor::EnableReconcile() {
   DCHECK(delegate_->IsReconcileEnabled());
-  RegisterWithCookieManagerService();
   RegisterWithContentSettings();
   RegisterWithIdentityManager();
 }
 
 void AccountReconcilor::DisableReconcile(bool logout_all_accounts) {
   AbortReconcile();
-  UnregisterWithCookieManagerService();
   UnregisterWithIdentityManager();
   UnregisterWithContentSettings();
 
@@ -301,27 +298,6 @@
   registered_with_identity_manager_ = false;
 }
 
-void AccountReconcilor::RegisterWithCookieManagerService() {
-  VLOG(1) << "AccountReconcilor::RegisterWithCookieManagerService";
-  // During re-auth, the reconcilor will get a callback about successful signin
-  // even when the profile is already connected.  Avoid re-registering
-  // with the helper since this will DCHECK.
-  if (registered_with_cookie_manager_service_)
-    return;
-
-  cookie_manager_service_->AddObserver(this);
-  registered_with_cookie_manager_service_ = true;
-}
-
-void AccountReconcilor::UnregisterWithCookieManagerService() {
-  VLOG(1) << "AccountReconcilor::UnregisterWithCookieManagerService";
-  if (!registered_with_cookie_manager_service_)
-    return;
-
-  cookie_manager_service_->RemoveObserver(this);
-  registered_with_cookie_manager_service_ = false;
-}
-
 signin_metrics::AccountReconcilorState AccountReconcilor::GetState() {
   if (!is_reconcile_started_) {
     return (error_during_last_reconcile_.state() !=
@@ -472,11 +448,13 @@
     return;
   }
 
-  // Rely on the GCMS to manage calls to and responses from ListAccounts.
-  std::vector<gaia::ListedAccount> gaia_accounts;
-  if (cookie_manager_service_->ListAccounts(&gaia_accounts, nullptr)) {
-    OnGaiaAccountsInCookieUpdated(
-        gaia_accounts, std::vector<gaia::ListedAccount>(),
+  // Rely on the IdentityManager to manage calls to and responses from
+  // ListAccounts.
+  identity::AccountsInCookieJarInfo accounts_in_cookie_jar =
+      identity_manager_->GetAccountsInCookieJar();
+  if (accounts_in_cookie_jar.accounts_are_fresh) {
+    OnAccountsInCookieUpdated(
+        accounts_in_cookie_jar,
         GoogleServiceAuthError(GoogleServiceAuthError::NONE));
   }
 }
@@ -529,11 +507,12 @@
   first_execution_ = false;
 }
 
-void AccountReconcilor::OnGaiaAccountsInCookieUpdated(
-        const std::vector<gaia::ListedAccount>& accounts,
-        const std::vector<gaia::ListedAccount>& signed_out_accounts,
-        const GoogleServiceAuthError& error) {
-  VLOG(1) << "AccountReconcilor::OnGaiaAccountsInCookieUpdated: "
+void AccountReconcilor::OnAccountsInCookieUpdated(
+    const identity::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
+    const GoogleServiceAuthError& error) {
+  const std::vector<gaia::ListedAccount>& accounts(
+      accounts_in_cookie_jar_info.signed_in_accounts);
+  VLOG(1) << "AccountReconcilor::OnAccountsInCookieUpdated: "
           << "CookieJar " << accounts.size() << " accounts, "
           << "Reconcilor's state is " << is_reconcile_started_ << ", "
           << "Error was " << error.ToString();
@@ -605,7 +584,7 @@
   }
 }
 
-void AccountReconcilor::OnGaiaCookieDeletedByUserAction() {
+void AccountReconcilor::OnAccountsCookieDeletedByUserAction() {
   if (!delegate_->ShouldRevokeTokensOnCookieDeleted())
     return;
 
diff --git a/components/signin/core/browser/account_reconcilor.h b/components/signin/core/browser/account_reconcilor.h
index 6cf7cbd9..20eb9d5 100644
--- a/components/signin/core/browser/account_reconcilor.h
+++ b/components/signin/core/browser/account_reconcilor.h
@@ -41,7 +41,6 @@
 
 class AccountReconcilor : public KeyedService,
                           public content_settings::Observer,
-                          public GaiaCookieManagerService::Observer,
                           public identity::IdentityManager::Observer {
  public:
   // When an instance of this class exists, the account reconcilor is suspended.
@@ -273,17 +272,6 @@
                                ContentSettingsType content_type,
                                const std::string& resource_identifier) override;
 
-  // Overridden from GaiaGookieManagerService::Observer.
-  void OnAddAccountToCookieCompleted(
-      const std::string& account_id,
-      const GoogleServiceAuthError& error) override;
-  void OnSetAccountsInCookieCompleted(
-      const GoogleServiceAuthError& error) override;
-  void OnGaiaAccountsInCookieUpdated(
-        const std::vector<gaia::ListedAccount>& accounts,
-        const std::vector<gaia::ListedAccount>& signed_out_accounts,
-        const GoogleServiceAuthError& error) override;
-  void OnGaiaCookieDeletedByUserAction() override;
 
   // Overridden from identity::IdentityManager::Observer.
   void OnEndBatchOfRefreshTokenStateChanges() override;
@@ -291,6 +279,15 @@
   void OnErrorStateOfRefreshTokenUpdatedForAccount(
       const AccountInfo& account_info,
       const GoogleServiceAuthError& error) override;
+  void OnAddAccountToCookieCompleted(
+      const std::string& account_id,
+      const GoogleServiceAuthError& error) override;
+  void OnSetAccountsInCookieCompleted(
+      const GoogleServiceAuthError& error) override;
+  void OnAccountsInCookieUpdated(
+      const identity::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
+      const GoogleServiceAuthError& error) override;
+  void OnAccountsCookieDeletedByUserAction() override;
 
   void FinishReconcileWithMultiloginEndpoint(
       const std::string& primary_account,
@@ -321,7 +318,6 @@
   GaiaCookieManagerService* cookie_manager_service_;
 
   bool registered_with_identity_manager_;
-  bool registered_with_cookie_manager_service_;
   bool registered_with_content_settings_;
 
   // True while the reconcilor is busy checking or managing the accounts in
diff --git a/components/signin/core/browser/account_reconcilor_unittest.cc b/components/signin/core/browser/account_reconcilor_unittest.cc
index 2b85df62b..2f8fc12 100644
--- a/components/signin/core/browser/account_reconcilor_unittest.cc
+++ b/components/signin/core/browser/account_reconcilor_unittest.cc
@@ -280,7 +280,7 @@
                               const std::string& username);
 
   void SimulateAddAccountToCookieCompleted(
-      GaiaCookieManagerService::Observer* observer,
+      identity::IdentityManager::Observer* observer,
       const std::string& account_id,
       const GoogleServiceAuthError& error);
 
@@ -289,7 +289,7 @@
       const ContentSettingsPattern& primary_pattern);
 
   void SimulateSetAccountsInCookieCompleted(
-      GaiaCookieManagerService::Observer* observer,
+      identity::IdentityManager::Observer* observer,
       const GoogleServiceAuthError& error);
 
   void SetAccountConsistency(signin::AccountConsistencyMethod method);
@@ -452,14 +452,14 @@
 }
 
 void AccountReconcilorTest::SimulateAddAccountToCookieCompleted(
-    GaiaCookieManagerService::Observer* observer,
+    identity::IdentityManager::Observer* observer,
     const std::string& account_id,
     const GoogleServiceAuthError& error) {
   observer->OnAddAccountToCookieCompleted(account_id, error);
 }
 
 void AccountReconcilorTest::SimulateSetAccountsInCookieCompleted(
-    GaiaCookieManagerService::Observer* observer,
+    identity::IdentityManager::Observer* observer,
     const GoogleServiceAuthError& error) {
   observer->OnSetAccountsInCookieCompleted(error);
 }
@@ -1652,7 +1652,7 @@
   {
     std::unique_ptr<AccountReconcilor::ScopedSyncedDataDeletion> deletion =
         reconcilor->GetScopedSyncDataDeletion();
-    reconcilor->OnGaiaCookieDeletedByUserAction();
+    reconcilor->OnAccountsCookieDeletedByUserAction();
     EXPECT_TRUE(
         identity_manager->HasAccountWithRefreshToken(primary_account_id));
     EXPECT_FALSE(
@@ -1663,7 +1663,7 @@
   }
 
   identity_test_env()->SetRefreshTokenForAccount(secondary_account_id);
-  reconcilor->OnGaiaCookieDeletedByUserAction();
+  reconcilor->OnAccountsCookieDeletedByUserAction();
 
   // Without scoped deletion, the primary token is also invalidated.
   EXPECT_TRUE(identity_manager->HasAccountWithRefreshToken(primary_account_id));
@@ -1691,7 +1691,7 @@
   {
     std::unique_ptr<AccountReconcilor::ScopedSyncedDataDeletion> deletion =
         reconcilor->GetScopedSyncDataDeletion();
-    reconcilor->OnGaiaCookieDeletedByUserAction();
+    reconcilor->OnAccountsCookieDeletedByUserAction();
     EXPECT_EQ(GoogleServiceAuthError::InvalidGaiaCredentialsReason::
                   CREDENTIALS_REJECTED_BY_CLIENT,
               identity_manager
@@ -1983,8 +1983,10 @@
   // Add extra cookie change notification. Reconcilor should ignore it.
   gaia::ListedAccount listed_account =
       ListedAccountFromCookieParams(cookie_params, account_id);
-  reconcilor->OnGaiaAccountsInCookieUpdated(
-      {listed_account}, {}, GoogleServiceAuthError::AuthErrorNone());
+  identity::AccountsInCookieJarInfo accounts_in_cookie_jar_info = {
+      /*accounts_are_fresh=*/true, {listed_account}, {}};
+  reconcilor->OnAccountsInCookieUpdated(
+      accounts_in_cookie_jar_info, GoogleServiceAuthError::AuthErrorNone());
 
   base::RunLoop().RunUntilIdle();
 
diff --git a/components/signin/core/browser/signin_tracker.cc b/components/signin/core/browser/signin_tracker.cc
deleted file mode 100644
index 230b49e..0000000
--- a/components/signin/core/browser/signin_tracker.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/signin/core/browser/signin_tracker.h"
-
-#include "google_apis/gaia/gaia_constants.h"
-
-SigninTracker::SigninTracker(identity::IdentityManager* identity_manager,
-                             Observer* observer)
-    : identity_manager_(identity_manager), observer_(observer) {
-  Initialize();
-}
-
-SigninTracker::~SigninTracker() {
-  identity_manager_->RemoveObserver(this);
-}
-
-void SigninTracker::Initialize() {
-  DCHECK(observer_);
-  identity_manager_->AddObserver(this);
-}
-
-void SigninTracker::OnPrimaryAccountSet(const AccountInfo& account_info) {
-  if (identity_manager_->HasAccountWithRefreshToken(account_info.account_id))
-    observer_->SigninSuccess();
-}
-
-void SigninTracker::OnPrimaryAccountSigninFailed(
-    const GoogleServiceAuthError& error) {
-  observer_->SigninFailed(error);
-}
-
-void SigninTracker::OnRefreshTokenUpdatedForAccount(
-    const AccountInfo& account_info) {
-  if (account_info.account_id != identity_manager_->GetPrimaryAccountId())
-    return;
-
-  observer_->SigninSuccess();
-}
-
-void SigninTracker::OnAddAccountToCookieCompleted(
-    const std::string& account_id,
-    const GoogleServiceAuthError& error) {
-  observer_->AccountAddedToCookie(error);
-}
diff --git a/components/signin/core/browser/signin_tracker.h b/components/signin/core/browser/signin_tracker.h
deleted file mode 100644
index 0e6e8c5b..0000000
--- a/components/signin/core/browser/signin_tracker.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_TRACKER_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_TRACKER_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "google_apis/gaia/google_service_auth_error.h"
-#include "services/identity/public/cpp/identity_manager.h"
-
-// The signin flow logic is spread across several classes with varying
-// responsibilities:
-//
-// SigninTracker (this class) - This class listens to notifications from the
-// IdentityManager services and coalesces them into
-// notifications for the UI layer. This is the class that encapsulates the logic
-// that determines whether a user is fully logged in or not, and exposes
-// callbacks so various pieces of the UI (OneClickSyncStarter) can track the
-// current startup state.
-//
-// SyncSetupHandler - This class is primarily responsible for interacting with
-// the web UI for performing system login and sync configuration. Receives
-// callbacks from the UI when the user wishes to initiate a login, and
-// translates system state (login errors, etc) into the appropriate calls into
-// the UI to reflect this status to the user.
-//
-// LoginUIService - Our desktop UI flows rely on having only a single login flow
-// visible to the user at once. This is achieved via LoginUIService
-// (a KeyedService that keeps track of the currently visible
-// login UI).
-//
-// IdentityManager - Records the currently-logged-in user and handles all
-// interaction with the GAIA backend during the signin process. Unlike
-// SigninTracker, IdentityManager only knows about the GAIA login state and is
-// not aware of the state of any signed in services.
-// What is more, IdentityManager also maintains and manages OAuth2 tokens for
-// the accounts connected to this profile.
-// Last, the IdentityManager is also responsible for adding or removing cookies
-// from the cookie jar from the browser process. A single source of information
-// about GAIA cookies in the cookie jar that are fetchable via /ListAccounts.
-//
-// ProfileSyncService - Provides the external API for interacting with the
-// sync framework. Listens for notifications for tokens to know when to startup
-// sync, and provides an Observer interface to notify the UI layer of changes
-// in sync state so they can be reflected in the UI.
-class SigninTracker : public identity::IdentityManager::Observer {
- public:
-  class Observer {
-   public:
-    // The signin attempt failed, and the cause is passed in |error|.
-    virtual void SigninFailed(const GoogleServiceAuthError& error) = 0;
-
-    // The signin attempt succeeded.
-    virtual void SigninSuccess() = 0;
-
-    // The signed in account has been added into the content area cookie jar.
-    // This will be called only after a call to SigninSuccess().
-    virtual void AccountAddedToCookie(const GoogleServiceAuthError& error) = 0;
-  };
-
-  // Creates a SigninTracker that tracks the signin status on the passed
-  // classes, and notifies the |observer| on status changes. All of the
-  // instances with the exception of |account_reconcilor| must be non-null and
-  // must outlive the SigninTracker. |account_reconcilor| will be used if it is
-  // non-null.
-  SigninTracker(identity::IdentityManager* identity_manager,
-                Observer* observer);
-  ~SigninTracker() override;
-
-  // identity::IdentityManager::Observer implementation.
-  void OnPrimaryAccountSet(const AccountInfo& account_info) override;
-  void OnPrimaryAccountSigninFailed(
-      const GoogleServiceAuthError& error) override;
-  void OnRefreshTokenUpdatedForAccount(
-      const AccountInfo& account_info) override;
-  void OnAddAccountToCookieCompleted(
-      const std::string& account_id,
-      const GoogleServiceAuthError& error) override;
-
- private:
-  // Initializes this by adding notifications and observers.
-  void Initialize();
-
-  // The classes whose collective signin status we are tracking.
-  identity::IdentityManager* identity_manager_;
-
-  // Weak pointer to the observer we call when the signin state changes.
-  Observer* observer_;
-
-  DISALLOW_COPY_AND_ASSIGN(SigninTracker);
-};
-
-#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_TRACKER_H_
diff --git a/components/signin/core/browser/signin_tracker_unittest.cc b/components/signin/core/browser/signin_tracker_unittest.cc
deleted file mode 100644
index e6114a3..0000000
--- a/components/signin/core/browser/signin_tracker_unittest.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/signin/core/browser/signin_tracker.h"
-
-#include "base/compiler_specific.h"
-#include "base/test/scoped_task_environment.h"
-#include "build/build_config.h"
-#include "google_apis/gaia/gaia_constants.h"
-#include "google_apis/gaia/google_service_auth_error.h"
-#include "services/identity/public/cpp/identity_test_environment.h"
-
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::_;
-using ::testing::AnyNumber;
-using ::testing::Mock;
-using ::testing::Return;
-using ::testing::ReturnRef;
-
-namespace {
-
-#if defined(OS_CHROMEOS)
-using FakeSigninManagerForTesting = FakeSigninManagerBase;
-#else
-using FakeSigninManagerForTesting = FakeSigninManager;
-#endif  // OS_CHROMEOS
-
-class MockObserver : public SigninTracker::Observer {
- public:
-  MockObserver() {}
-  ~MockObserver() {}
-
-  MOCK_METHOD1(SigninFailed, void(const GoogleServiceAuthError&));
-  MOCK_METHOD0(SigninSuccess, void(void));
-  MOCK_METHOD1(AccountAddedToCookie, void(const GoogleServiceAuthError&));
-};
-
-}  // namespace
-
-class SigninTrackerTest : public testing::Test {
- public:
-  SigninTrackerTest() {
-    tracker_ = std::make_unique<SigninTracker>(
-        identity_test_env_.identity_manager(), &observer_);
-  }
-
-  ~SigninTrackerTest() override { tracker_.reset(); }
-
-  base::test::ScopedTaskEnvironment task_environment_;
-  std::unique_ptr<SigninTracker> tracker_;
-  identity::IdentityTestEnvironment identity_test_env_;
-  MockObserver observer_;
-};
-
-#if !defined(OS_CHROMEOS)
-TEST_F(SigninTrackerTest, SignInFails) {
-  const GoogleServiceAuthError error(
-      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
-
-  // Signin failure should result in a SigninFailed callback.
-  EXPECT_CALL(observer_, SigninSuccess()).Times(0);
-  EXPECT_CALL(observer_, SigninFailed(error));
-
-  // Mimic calling IdentityManager::GoogleSigninFailed().
-  tracker_->OnPrimaryAccountSigninFailed(error);
-}
-#endif  // !defined(OS_CHROMEOS)
-
-TEST_F(SigninTrackerTest, SignInSucceeds) {
-  EXPECT_CALL(observer_, SigninSuccess());
-  EXPECT_CALL(observer_, SigninFailed(_)).Times(0);
-
-  std::string email = "user@gmail.com";
-  identity_test_env_.MakePrimaryAccountAvailable(email);
-}
-
-#if !defined(OS_CHROMEOS)
-TEST_F(SigninTrackerTest, SignInSucceedsWithExistingAccount) {
-  EXPECT_CALL(observer_, SigninSuccess());
-  EXPECT_CALL(observer_, SigninFailed(_)).Times(0);
-
-  std::string email = "user@gmail.com";
-  AccountInfo account_info = identity_test_env_.MakeAccountAvailable(email);
-  identity_test_env_.SetPrimaryAccount(account_info.email);
-}
-#endif
diff --git a/components/signin/core/browser/test_signin_client.h b/components/signin/core/browser/test_signin_client.h
index ef6fe58..98cbaf0 100644
--- a/components/signin/core/browser/test_signin_client.h
+++ b/components/signin/core/browser/test_signin_client.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/callback_forward.h"
@@ -50,8 +51,11 @@
   // Wraps the test_url_loader_factory().
   scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
 
-  // Returns FakeCookieManager.
   network::mojom::CookieManager* GetCookieManager() override;
+  void set_cookie_manager(
+      std::unique_ptr<network::mojom::CookieManager> cookie_manager) {
+    cookie_manager_ = std::move(cookie_manager);
+  }
 
   network::TestURLLoaderFactory* test_url_loader_factory() {
     return &test_url_loader_factory_;
diff --git a/components/sync/PRESUBMIT.py b/components/sync/PRESUBMIT.py
index 130a337..85d7e51 100644
--- a/components/sync/PRESUBMIT.py
+++ b/components/sync/PRESUBMIT.py
@@ -27,9 +27,12 @@
   'SUPERVISED_USER_WHITELISTS',  # See previous.
 
   # Deprecated types:
+  'DEPRECATED_APP_NOTIFICATIONS',
+  'DEPRECATED_ARTICLES',
   'DEPRECATED_SUPERVISED_USERS',
   'DEPRECATED_SUPERVISED_USER_SHARED_SETTINGS',
-  'DEPRECATED_ARTICLES',
+  'DEPRECATED_SYNCED_NOTIFICATIONS',
+  'DEPRECATED_SYNCED_NOTIFICATION_APP_INFO',
   'DEPRECATED_WIFI_CREDENTIALS']
 
 # Root tags are used as prefixes when creating storage keys, so certain strings
diff --git a/components/sync/base/data_type_histogram.h b/components/sync/base/data_type_histogram.h
index b87ac3c4..e0bf40d 100644
--- a/components/sync/base/data_type_histogram.h
+++ b/components/sync/base/data_type_histogram.h
@@ -92,16 +92,16 @@
       case ::syncer::EXTENSION_SETTINGS:                         \
         PER_DATA_TYPE_MACRO("ExtensionSettings");                \
         break;                                                   \
-      case ::syncer::APP_NOTIFICATIONS:                          \
+      case ::syncer::DEPRECATED_APP_NOTIFICATIONS:               \
         PER_DATA_TYPE_MACRO("AppNotifications");                 \
         break;                                                   \
       case ::syncer::HISTORY_DELETE_DIRECTIVES:                  \
         PER_DATA_TYPE_MACRO("HistoryDeleteDirectives");          \
         break;                                                   \
-      case ::syncer::SYNCED_NOTIFICATIONS:                       \
+      case ::syncer::DEPRECATED_SYNCED_NOTIFICATIONS:            \
         PER_DATA_TYPE_MACRO("SyncedNotifications");              \
         break;                                                   \
-      case ::syncer::SYNCED_NOTIFICATION_APP_INFO:               \
+      case ::syncer::DEPRECATED_SYNCED_NOTIFICATION_APP_INFO:    \
         PER_DATA_TYPE_MACRO("SyncedNotificationAppInfo");        \
         break;                                                   \
       case ::syncer::DICTIONARY:                                 \
diff --git a/components/sync/base/model_type.h b/components/sync/base/model_type.h
index 1b03052..e4d6154d 100644
--- a/components/sync/base/model_type.h
+++ b/components/sync/base/model_type.h
@@ -91,13 +91,13 @@
   // An extension setting from the extension settings API.
   EXTENSION_SETTINGS,
   // App notifications. Deprecated.
-  APP_NOTIFICATIONS,
+  DEPRECATED_APP_NOTIFICATIONS,
   // History delete directives.
   HISTORY_DELETE_DIRECTIVES,
   // Synced push notifications. Deprecated.
-  SYNCED_NOTIFICATIONS,
+  DEPRECATED_SYNCED_NOTIFICATIONS,
   // Synced Notification app info. Deprecated.
-  SYNCED_NOTIFICATION_APP_INFO,
+  DEPRECATED_SYNCED_NOTIFICATION_APP_INFO,
   // Custom spelling dictionary.
   DICTIONARY,
   // Favicon images.
@@ -209,9 +209,10 @@
       BOOKMARKS, PREFERENCES, PASSWORDS, AUTOFILL_PROFILE, AUTOFILL,
       AUTOFILL_WALLET_DATA, AUTOFILL_WALLET_METADATA, THEMES, TYPED_URLS,
       EXTENSIONS, SEARCH_ENGINES, SESSIONS, APPS, APP_SETTINGS,
-      EXTENSION_SETTINGS, APP_NOTIFICATIONS, HISTORY_DELETE_DIRECTIVES,
-      SYNCED_NOTIFICATIONS, SYNCED_NOTIFICATION_APP_INFO, DICTIONARY,
-      FAVICON_IMAGES, FAVICON_TRACKING, DEVICE_INFO, PRIORITY_PREFERENCES,
+      EXTENSION_SETTINGS, DEPRECATED_APP_NOTIFICATIONS,
+      HISTORY_DELETE_DIRECTIVES, DEPRECATED_SYNCED_NOTIFICATIONS,
+      DEPRECATED_SYNCED_NOTIFICATION_APP_INFO, DICTIONARY, FAVICON_IMAGES,
+      FAVICON_TRACKING, DEVICE_INFO, PRIORITY_PREFERENCES,
       SUPERVISED_USER_SETTINGS, DEPRECATED_SUPERVISED_USERS,
       DEPRECATED_SUPERVISED_USER_SHARED_SETTINGS, DEPRECATED_ARTICLES, APP_LIST,
       DEPRECATED_WIFI_CREDENTIALS, SUPERVISED_USER_WHITELISTS, ARC_PACKAGE,
diff --git a/components/sync/base/sync_prefs.cc b/components/sync/base/sync_prefs.cc
index eebaaef..978b6575 100644
--- a/components/sync/base/sync_prefs.cc
+++ b/components/sync/base/sync_prefs.cc
@@ -21,16 +21,14 @@
 
 namespace {
 // Groups of prefs that always have the same value as a "master" pref.
-// For example, the APPS group has {APP_NOTIFICATIONS, APP_SETTINGS}
+// For example, the APPS group has {APP_LIST, APP_SETTINGS}
 // (as well as APPS, but that is implied), so
-//   pref_groups_[APPS] =       { APP_NOTIFICATIONS,
-//                                          APP_SETTINGS }
+//   pref_groups_[APPS] =       { APP_LIST, APP_SETTINGS }
 //   pref_groups_[EXTENSIONS] = { EXTENSION_SETTINGS }
 // etc.
 using PrefGroupsMap = std::map<ModelType, ModelTypeSet>;
 PrefGroupsMap ComputePrefGroups() {
   PrefGroupsMap pref_groups;
-  pref_groups[APPS].Put(APP_NOTIFICATIONS);
   pref_groups[APPS].Put(APP_SETTINGS);
   pref_groups[APPS].Put(APP_LIST);
   pref_groups[APPS].Put(ARC_PACKAGE);
@@ -380,10 +378,10 @@
     case SEARCH_ENGINES:
     case APP_SETTINGS:
     case EXTENSION_SETTINGS:
-    case APP_NOTIFICATIONS:
+    case DEPRECATED_APP_NOTIFICATIONS:
     case HISTORY_DELETE_DIRECTIVES:
-    case SYNCED_NOTIFICATIONS:
-    case SYNCED_NOTIFICATION_APP_INFO:
+    case DEPRECATED_SYNCED_NOTIFICATIONS:
+    case DEPRECATED_SYNCED_NOTIFICATION_APP_INFO:
     case DICTIONARY:
     case FAVICON_IMAGES:
     case FAVICON_TRACKING:
diff --git a/components/sync/base/sync_prefs_unittest.cc b/components/sync/base/sync_prefs_unittest.cc
index e754251..fb2c334 100644
--- a/components/sync/base/sync_prefs_unittest.cc
+++ b/components/sync/base/sync_prefs_unittest.cc
@@ -257,7 +257,6 @@
     }
     if (type == APPS) {
       expected_preferred_types.Put(APP_LIST);
-      expected_preferred_types.Put(APP_NOTIFICATIONS);
       expected_preferred_types.Put(APP_SETTINGS);
       expected_preferred_types.Put(ARC_PACKAGE);
     }
diff --git a/components/sync/driver/model_association_manager.cc b/components/sync/driver/model_association_manager.cc
index f8101dd..fc9cfc4 100644
--- a/components/sync/driver/model_association_manager.cc
+++ b/components/sync/driver/model_association_manager.cc
@@ -36,14 +36,14 @@
     // in parallel with the UI types.
     PASSWORDS, AUTOFILL, AUTOFILL_PROFILE, AUTOFILL_WALLET_DATA,
     AUTOFILL_WALLET_METADATA, EXTENSION_SETTINGS, APP_SETTINGS, TYPED_URLS,
-    HISTORY_DELETE_DIRECTIVES, SYNCED_NOTIFICATIONS,
-    SYNCED_NOTIFICATION_APP_INFO,
+    HISTORY_DELETE_DIRECTIVES, DEPRECATED_SYNCED_NOTIFICATIONS,
+    DEPRECATED_SYNCED_NOTIFICATION_APP_INFO,
 
     // UI thread data types.
     BOOKMARKS, PREFERENCES, PRIORITY_PREFERENCES, EXTENSIONS, APPS, APP_LIST,
     ARC_PACKAGE, READING_LIST, THEMES, SEARCH_ENGINES, SESSIONS,
-    APP_NOTIFICATIONS, DICTIONARY, FAVICON_IMAGES, FAVICON_TRACKING, PRINTERS,
-    USER_CONSENTS, USER_EVENTS, SUPERVISED_USER_SETTINGS,
+    DEPRECATED_APP_NOTIFICATIONS, DICTIONARY, FAVICON_IMAGES, FAVICON_TRACKING,
+    PRINTERS, USER_CONSENTS, USER_EVENTS, SUPERVISED_USER_SETTINGS,
     SUPERVISED_USER_WHITELISTS, DEPRECATED_WIFI_CREDENTIALS,
     DEPRECATED_SUPERVISED_USERS, MOUNTAIN_SHARES,
     DEPRECATED_SUPERVISED_USER_SHARED_SETTINGS, DEPRECATED_ARTICLES,
diff --git a/components/sync/engine_impl/directory_update_handler_unittest.cc b/components/sync/engine_impl/directory_update_handler_unittest.cc
index 02addc6..6486051 100644
--- a/components/sync/engine_impl/directory_update_handler_unittest.cc
+++ b/components/sync/engine_impl/directory_update_handler_unittest.cc
@@ -251,30 +251,31 @@
 }
 
 TEST_F(DirectoryUpdateHandlerProcessUpdateTest, GarbageCollectionByVersion) {
-  DirectoryTypeDebugInfoEmitter emitter(SYNCED_NOTIFICATIONS, &type_observers_);
-  DirectoryUpdateHandler handler(dir(), SYNCED_NOTIFICATIONS, ui_worker(),
-                                 &emitter);
+  DirectoryTypeDebugInfoEmitter emitter(DEPRECATED_SYNCED_NOTIFICATIONS,
+                                        &type_observers_);
+  DirectoryUpdateHandler handler(dir(), DEPRECATED_SYNCED_NOTIFICATIONS,
+                                 ui_worker(), &emitter);
   StatusController status;
 
   sync_pb::DataTypeProgressMarker progress;
   progress.set_data_type_id(
-      GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS));
+      GetSpecificsFieldNumberFromModelType(DEPRECATED_SYNCED_NOTIFICATIONS));
   progress.set_token("token");
   progress.mutable_gc_directive()->set_version_watermark(kDefaultVersion + 10);
 
   sync_pb::DataTypeContext context;
   context.set_data_type_id(
-      GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS));
+      GetSpecificsFieldNumberFromModelType(DEPRECATED_SYNCED_NOTIFICATIONS));
   context.set_context("context");
   context.set_version(1);
 
   std::unique_ptr<sync_pb::SyncEntity> e1 =
       CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e1")), "",
-                   SYNCED_NOTIFICATIONS);
+                   DEPRECATED_SYNCED_NOTIFICATIONS);
 
   std::unique_ptr<sync_pb::SyncEntity> e2 =
       CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e2")), "",
-                   SYNCED_NOTIFICATIONS);
+                   DEPRECATED_SYNCED_NOTIFICATIONS);
   e2->set_version(kDefaultVersion + 100);
 
   // Add to the applicable updates list.
@@ -290,7 +291,7 @@
   handler.ApplyUpdates(&status);
 
   // Verify none is deleted because they are unapplied during GC.
-  EXPECT_TRUE(TypeRootExists(SYNCED_NOTIFICATIONS));
+  EXPECT_TRUE(TypeRootExists(DEPRECATED_SYNCED_NOTIFICATIONS));
   EXPECT_TRUE(EntryExists(e1->id_string()));
   EXPECT_TRUE(EntryExists(e2->id_string()));
 
@@ -309,32 +310,33 @@
 // Create 2 entries, one is 15-days-old, another is 5-days-old. Check if sync
 // will delete 15-days-old entry when server set expired age is 10 days.
 TEST_F(DirectoryUpdateHandlerProcessUpdateTest, GarbageCollectionByAge) {
-  DirectoryTypeDebugInfoEmitter emitter(SYNCED_NOTIFICATIONS, &type_observers_);
-  DirectoryUpdateHandler handler(dir(), SYNCED_NOTIFICATIONS, ui_worker(),
-                                 &emitter);
+  DirectoryTypeDebugInfoEmitter emitter(DEPRECATED_SYNCED_NOTIFICATIONS,
+                                        &type_observers_);
+  DirectoryUpdateHandler handler(dir(), DEPRECATED_SYNCED_NOTIFICATIONS,
+                                 ui_worker(), &emitter);
   StatusController status;
 
   sync_pb::DataTypeProgressMarker progress;
   progress.set_data_type_id(
-      GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS));
+      GetSpecificsFieldNumberFromModelType(DEPRECATED_SYNCED_NOTIFICATIONS));
   progress.set_token("token");
   progress.mutable_gc_directive()->set_age_watermark_in_days(20);
 
   sync_pb::DataTypeContext context;
   context.set_data_type_id(
-      GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS));
+      GetSpecificsFieldNumberFromModelType(DEPRECATED_SYNCED_NOTIFICATIONS));
   context.set_context("context");
   context.set_version(1);
 
   std::unique_ptr<sync_pb::SyncEntity> e1 =
       CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e1")), "",
-                   SYNCED_NOTIFICATIONS);
+                   DEPRECATED_SYNCED_NOTIFICATIONS);
   e1->set_mtime(
       TimeToProtoTime(base::Time::Now() - base::TimeDelta::FromDays(15)));
 
   std::unique_ptr<sync_pb::SyncEntity> e2 =
       CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e2")), "",
-                   SYNCED_NOTIFICATIONS);
+                   DEPRECATED_SYNCED_NOTIFICATIONS);
   e2->set_mtime(
       TimeToProtoTime(base::Time::Now() - base::TimeDelta::FromDays(5)));
 
@@ -351,7 +353,7 @@
   handler.ApplyUpdates(&status);
 
   // Verify none is deleted because they are unapplied during GC.
-  EXPECT_TRUE(TypeRootExists(SYNCED_NOTIFICATIONS));
+  EXPECT_TRUE(TypeRootExists(DEPRECATED_SYNCED_NOTIFICATIONS));
   EXPECT_TRUE(EntryExists(e1->id_string()));
   EXPECT_TRUE(EntryExists(e2->id_string()));
 
@@ -372,38 +374,39 @@
 // 5-days-old. Check if sync will delete 15-days-old entry when server set
 // max_number_of_items is 2.
 TEST_F(DirectoryUpdateHandlerProcessUpdateTest, GarbageCollectionByItemLimit) {
-  DirectoryTypeDebugInfoEmitter emitter(SYNCED_NOTIFICATIONS, &type_observers_);
-  DirectoryUpdateHandler handler(dir(), SYNCED_NOTIFICATIONS, ui_worker(),
-                                 &emitter);
+  DirectoryTypeDebugInfoEmitter emitter(DEPRECATED_SYNCED_NOTIFICATIONS,
+                                        &type_observers_);
+  DirectoryUpdateHandler handler(dir(), DEPRECATED_SYNCED_NOTIFICATIONS,
+                                 ui_worker(), &emitter);
   StatusController status;
 
   sync_pb::DataTypeProgressMarker progress;
   progress.set_data_type_id(
-      GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS));
+      GetSpecificsFieldNumberFromModelType(DEPRECATED_SYNCED_NOTIFICATIONS));
   progress.set_token("token");
   progress.mutable_gc_directive()->set_max_number_of_items(3);
 
   sync_pb::DataTypeContext context;
   context.set_data_type_id(
-      GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS));
+      GetSpecificsFieldNumberFromModelType(DEPRECATED_SYNCED_NOTIFICATIONS));
   context.set_context("context");
   context.set_version(1);
 
   std::unique_ptr<sync_pb::SyncEntity> e1 =
       CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e1")), "",
-                   SYNCED_NOTIFICATIONS);
+                   DEPRECATED_SYNCED_NOTIFICATIONS);
   e1->set_mtime(
       TimeToProtoTime(base::Time::Now() - base::TimeDelta::FromDays(15)));
 
   std::unique_ptr<sync_pb::SyncEntity> e2 =
       CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e2")), "",
-                   SYNCED_NOTIFICATIONS);
+                   DEPRECATED_SYNCED_NOTIFICATIONS);
   e2->set_mtime(
       TimeToProtoTime(base::Time::Now() - base::TimeDelta::FromDays(5)));
 
   std::unique_ptr<sync_pb::SyncEntity> e3 =
       CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e3")), "",
-                   SYNCED_NOTIFICATIONS);
+                   DEPRECATED_SYNCED_NOTIFICATIONS);
   e3->set_mtime(
       TimeToProtoTime(base::Time::Now() - base::TimeDelta::FromDays(10)));
 
@@ -421,7 +424,7 @@
   handler.ApplyUpdates(&status);
 
   // Verify none is deleted because they are unapplied during GC.
-  EXPECT_TRUE(TypeRootExists(SYNCED_NOTIFICATIONS));
+  EXPECT_TRUE(TypeRootExists(DEPRECATED_SYNCED_NOTIFICATIONS));
   EXPECT_TRUE(EntryExists(e1->id_string()));
   EXPECT_TRUE(EntryExists(e2->id_string()));
 
@@ -439,15 +442,17 @@
 }
 
 TEST_F(DirectoryUpdateHandlerProcessUpdateTest, ContextVersion) {
-  DirectoryTypeDebugInfoEmitter emitter(SYNCED_NOTIFICATIONS, &type_observers_);
-  DirectoryUpdateHandler handler(dir(), SYNCED_NOTIFICATIONS, ui_worker(),
-                                 &emitter);
+  DirectoryTypeDebugInfoEmitter emitter(DEPRECATED_SYNCED_NOTIFICATIONS,
+                                        &type_observers_);
+  DirectoryUpdateHandler handler(dir(), DEPRECATED_SYNCED_NOTIFICATIONS,
+                                 ui_worker(), &emitter);
   StatusController status;
-  int field_number = GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS);
+  int field_number =
+      GetSpecificsFieldNumberFromModelType(DEPRECATED_SYNCED_NOTIFICATIONS);
 
   sync_pb::DataTypeProgressMarker progress;
   progress.set_data_type_id(
-      GetSpecificsFieldNumberFromModelType(SYNCED_NOTIFICATIONS));
+      GetSpecificsFieldNumberFromModelType(DEPRECATED_SYNCED_NOTIFICATIONS));
   progress.set_token("token");
 
   sync_pb::DataTypeContext old_context;
@@ -457,7 +462,7 @@
 
   std::unique_ptr<sync_pb::SyncEntity> e1 =
       CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e1")), "",
-                   SYNCED_NOTIFICATIONS);
+                   DEPRECATED_SYNCED_NOTIFICATIONS);
 
   SyncEntityList updates;
   updates.push_back(e1.get());
@@ -470,15 +475,15 @@
   handler.ApplyUpdates(&status);
 
   // The PREFERENCES root should be auto-created.
-  EXPECT_TRUE(TypeRootExists(SYNCED_NOTIFICATIONS));
+  EXPECT_TRUE(TypeRootExists(DEPRECATED_SYNCED_NOTIFICATIONS));
 
   EXPECT_TRUE(EntryExists(e1->id_string()));
 
   {
     sync_pb::DataTypeContext dir_context;
     syncable::ReadTransaction trans(FROM_HERE, dir());
-    trans.directory()->GetDataTypeContext(&trans, SYNCED_NOTIFICATIONS,
-                                          &dir_context);
+    trans.directory()->GetDataTypeContext(
+        &trans, DEPRECATED_SYNCED_NOTIFICATIONS, &dir_context);
     EXPECT_EQ(old_context.SerializeAsString(), dir_context.SerializeAsString());
   }
 
@@ -489,7 +494,7 @@
 
   std::unique_ptr<sync_pb::SyncEntity> e2 =
       CreateUpdate(SyncableIdToProto(Id::CreateFromServerId("e2")), "",
-                   SYNCED_NOTIFICATIONS);
+                   DEPRECATED_SYNCED_NOTIFICATIONS);
   updates.clear();
   updates.push_back(e2.get());
 
@@ -506,8 +511,8 @@
   {
     sync_pb::DataTypeContext dir_context;
     syncable::ReadTransaction trans(FROM_HERE, dir());
-    trans.directory()->GetDataTypeContext(&trans, SYNCED_NOTIFICATIONS,
-                                          &dir_context);
+    trans.directory()->GetDataTypeContext(
+        &trans, DEPRECATED_SYNCED_NOTIFICATIONS, &dir_context);
     EXPECT_EQ(old_context.SerializeAsString(), dir_context.SerializeAsString());
   }
 }
diff --git a/components/sync/protocol/nigori_specifics.proto b/components/sync/protocol/nigori_specifics.proto
index fbb22bec..8f37992 100644
--- a/components/sync/protocol/nigori_specifics.proto
+++ b/components/sync/protocol/nigori_specifics.proto
@@ -52,10 +52,6 @@
   // Passwords are always encrypted, so we don't need a field here.
   // History delete directives need to be consumable by the server, and
   // thus can't be encrypted.
-  // Synced Notifications need to be consumed by the server (the read flag)
-  // and thus can't be encrypted.
-  // Synced Notification App Info is set by the server, and thus cannot be
-  // encrypted.
   optional bool encrypt_bookmarks = 13;
   optional bool encrypt_preferences = 14;
   optional bool encrypt_autofill_profile = 15;
@@ -74,7 +70,7 @@
   optional bool encrypt_everything = 24;
 
   optional bool encrypt_extension_settings = 25;
-  optional bool encrypt_app_notifications = 26;
+  optional bool encrypt_app_notifications = 26 [deprecated = true];
   optional bool encrypt_app_settings = 27;
 
   // User device information. Contains information about each device that has a
diff --git a/components/sync/syncable/model_type.cc b/components/sync/syncable/model_type.cc
index 2b50bc1..d1b6ef5 100644
--- a/components/sync/syncable/model_type.cc
+++ b/components/sync/syncable/model_type.cc
@@ -94,16 +94,16 @@
     {EXTENSION_SETTINGS, "EXTENSION_SETTING", "extension_settings",
      "Extension settings",
      sync_pb::EntitySpecifics::kExtensionSettingFieldNumber, 14},
-    {APP_NOTIFICATIONS, "APP_NOTIFICATION", "app_notifications",
+    {DEPRECATED_APP_NOTIFICATIONS, "APP_NOTIFICATION", "app_notifications",
      "App Notifications", sync_pb::EntitySpecifics::kAppNotificationFieldNumber,
      15},
     {HISTORY_DELETE_DIRECTIVES, "HISTORY_DELETE_DIRECTIVE",
      "history_delete_directives", "History Delete Directives",
      sync_pb::EntitySpecifics::kHistoryDeleteDirectiveFieldNumber, 16},
-    {SYNCED_NOTIFICATIONS, "SYNCED_NOTIFICATION", "synced_notifications",
-     "Synced Notifications",
+    {DEPRECATED_SYNCED_NOTIFICATIONS, "SYNCED_NOTIFICATION",
+     "synced_notifications", "Synced Notifications",
      sync_pb::EntitySpecifics::kSyncedNotificationFieldNumber, 20},
-    {SYNCED_NOTIFICATION_APP_INFO, "SYNCED_NOTIFICATION_APP_INFO",
+    {DEPRECATED_SYNCED_NOTIFICATION_APP_INFO, "SYNCED_NOTIFICATION_APP_INFO",
      "synced_notification_app_info", "Synced Notification App Info",
      sync_pb::EntitySpecifics::kSyncedNotificationAppInfoFieldNumber, 31},
     {DICTIONARY, "DICTIONARY", "dictionary", "Dictionary",
@@ -126,8 +126,8 @@
     {DEPRECATED_SUPERVISED_USER_SHARED_SETTINGS, "MANAGED_USER_SHARED_SETTING",
      "managed_user_shared_settings", "Managed User Shared Settings",
      sync_pb::EntitySpecifics::kManagedUserSharedSettingFieldNumber, 30},
-    {DEPRECATED_ARTICLES, "ARTICLE", "deprecated_articles",
-     "Deprecated Articles", sync_pb::EntitySpecifics::kArticleFieldNumber, 28},
+    {DEPRECATED_ARTICLES, "ARTICLE", "articles", "Articles",
+     sync_pb::EntitySpecifics::kArticleFieldNumber, 28},
     {APP_LIST, "APP_LIST", "app_list", "App List",
      sync_pb::EntitySpecifics::kAppListFieldNumber, 29},
     {DEPRECATED_WIFI_CREDENTIALS, "WIFI_CREDENTIAL", "wifi_credentials",
@@ -222,16 +222,16 @@
     case EXTENSION_SETTINGS:
       specifics->mutable_extension_setting();
       break;
-    case APP_NOTIFICATIONS:
+    case DEPRECATED_APP_NOTIFICATIONS:
       specifics->mutable_app_notification();
       break;
     case HISTORY_DELETE_DIRECTIVES:
       specifics->mutable_history_delete_directive();
       break;
-    case SYNCED_NOTIFICATIONS:
+    case DEPRECATED_SYNCED_NOTIFICATIONS:
       specifics->mutable_synced_notification();
       break;
-    case SYNCED_NOTIFICATION_APP_INFO:
+    case DEPRECATED_SYNCED_NOTIFICATION_APP_INFO:
       specifics->mutable_synced_notification_app_info();
       break;
     case DICTIONARY:
@@ -389,13 +389,13 @@
   if (specifics.has_extension_setting())
     return EXTENSION_SETTINGS;
   if (specifics.has_app_notification())
-    return APP_NOTIFICATIONS;
+    return DEPRECATED_APP_NOTIFICATIONS;
   if (specifics.has_history_delete_directive())
     return HISTORY_DELETE_DIRECTIVES;
   if (specifics.has_synced_notification())
-    return SYNCED_NOTIFICATIONS;
+    return DEPRECATED_SYNCED_NOTIFICATIONS;
   if (specifics.has_synced_notification_app_info())
-    return SYNCED_NOTIFICATION_APP_INFO;
+    return DEPRECATED_SYNCED_NOTIFICATION_APP_INFO;
   if (specifics.has_dictionary())
     return DICTIONARY;
   if (specifics.has_favicon_image())
@@ -465,10 +465,10 @@
   // We never encrypt history delete directives.
   encryptable_user_types.Remove(HISTORY_DELETE_DIRECTIVES);
   // Synced notifications are not encrypted since the server must see changes.
-  encryptable_user_types.Remove(SYNCED_NOTIFICATIONS);
+  encryptable_user_types.Remove(DEPRECATED_SYNCED_NOTIFICATIONS);
   // Synced Notification App Info does not have private data, so it is not
   // encrypted.
-  encryptable_user_types.Remove(SYNCED_NOTIFICATION_APP_INFO);
+  encryptable_user_types.Remove(DEPRECATED_SYNCED_NOTIFICATION_APP_INFO);
   // Device info data is not encrypted because it might be synced before
   // encryption is ready.
   encryptable_user_types.Remove(DEVICE_INFO);
diff --git a/components/sync/syncable/nigori_util.cc b/components/sync/syncable/nigori_util.cc
index 973e84e9..7c25678 100644
--- a/components/sync/syncable/nigori_util.cc
+++ b/components/sync/syncable/nigori_util.cc
@@ -263,7 +263,8 @@
   nigori->set_encrypt_app_settings(encrypted_types.Has(APP_SETTINGS));
   nigori->set_encrypt_extension_settings(
       encrypted_types.Has(EXTENSION_SETTINGS));
-  nigori->set_encrypt_app_notifications(encrypted_types.Has(APP_NOTIFICATIONS));
+  nigori->set_encrypt_app_notifications(
+      encrypted_types.Has(DEPRECATED_APP_NOTIFICATIONS));
   nigori->set_encrypt_dictionary(encrypted_types.Has(DICTIONARY));
   nigori->set_encrypt_favicon_images(encrypted_types.Has(FAVICON_IMAGES));
   nigori->set_encrypt_favicon_tracking(encrypted_types.Has(FAVICON_TRACKING));
@@ -311,7 +312,7 @@
   if (nigori.encrypt_extension_settings())
     encrypted_types.Put(EXTENSION_SETTINGS);
   if (nigori.encrypt_app_notifications())
-    encrypted_types.Put(APP_NOTIFICATIONS);
+    encrypted_types.Put(DEPRECATED_APP_NOTIFICATIONS);
   if (nigori.encrypt_dictionary())
     encrypted_types.Put(DICTIONARY);
   if (nigori.encrypt_favicon_images())
diff --git a/components/update_client/request_sender.cc b/components/update_client/request_sender.cc
index b665716..aceb8d8 100644
--- a/components/update_client/request_sender.cc
+++ b/components/update_client/request_sender.cc
@@ -25,10 +25,10 @@
 namespace {
 
 // This is an ECDSA prime256v1 named-curve key.
-constexpr int kKeyVersion = 8;
+constexpr int kKeyVersion = 9;
 const char kKeyPubBytesBase64[] =
-    "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE+J2iCpfk8lThcuKUPzTaVcUjhNR3"
-    "AYHK+tTelGdHvyGGx7RP7BphYSPmpH6P4Vr72ak0W1a0bW55O9HW2oz3rQ==";
+    "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEsVwVMmIJaWBjktSx9m1JrZWYBvMm"
+    "bsrGGQPhScDtao+DloD871YmEeunAaQvRMZgDh1nCaWkVG6wo75+yDbKDA==";
 
 // The ETag header carries the ECSDA signature of the protocol response, if
 // signing has been used.
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 8599194..fe1d609 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -159,7 +159,6 @@
     "//services/service_manager/public/cpp",
     "//services/service_manager/public/mojom",
     "//services/service_manager/runner/common",
-    "//services/service_manager/runner/host:lib",
     "//services/service_manager/zygote:zygote_buildflags",
     "//services/shape_detection:lib",
     "//services/shape_detection/public/mojom",
diff --git a/content/browser/background_fetch/background_fetch_delegate_proxy.cc b/content/browser/background_fetch/background_fetch_delegate_proxy.cc
index 27877d48..30509f72 100644
--- a/content/browser/background_fetch/background_fetch_delegate_proxy.cc
+++ b/content/browser/background_fetch/background_fetch_delegate_proxy.cc
@@ -103,7 +103,7 @@
 
   void StartRequest(const std::string& job_unique_id,
                     const url::Origin& origin,
-                    scoped_refptr<BackgroundFetchRequestInfo> request) {
+                    const scoped_refptr<BackgroundFetchRequestInfo>& request) {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
     DCHECK(request);
 
@@ -316,23 +316,6 @@
                      std::move(wrapped_callback)));
 }
 
-BackgroundFetchDelegateProxy::JobDetails::JobDetails(
-    base::WeakPtr<Controller> controller,
-    std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
-        active_fetch_requests)
-    : controller(controller) {
-  for (auto& request_info : active_fetch_requests) {
-    DCHECK(request_info);
-    std::string download_guid = request_info->download_guid();
-    current_request_map[std::move(download_guid)] = std::move(request_info);
-  }
-}
-
-BackgroundFetchDelegateProxy::JobDetails::JobDetails(JobDetails&& details) =
-    default;
-
-BackgroundFetchDelegateProxy::JobDetails::~JobDetails() = default;
-
 BackgroundFetchDelegateProxy::BackgroundFetchDelegateProxy(
     BrowserContext* browser_context)
     : weak_ptr_factory_(this) {
@@ -353,7 +336,7 @@
 }
 
 void BackgroundFetchDelegateProxy::SetClickEventDispatcher(
-    const DispatchClickEventCallback callback) {
+    DispatchClickEventCallback callback) {
   click_event_dispatcher_callback_ = std::move(callback);
 }
 
@@ -378,15 +361,11 @@
 
 void BackgroundFetchDelegateProxy::CreateDownloadJob(
     base::WeakPtr<Controller> controller,
-    std::unique_ptr<BackgroundFetchDescription> fetch_description,
-    std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
-        active_fetch_requests) {
+    std::unique_ptr<BackgroundFetchDescription> fetch_description) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  DCHECK(!job_details_map_.count(fetch_description->job_unique_id));
-  job_details_map_.emplace(
-      fetch_description->job_unique_id,
-      JobDetails(controller, std::move(active_fetch_requests)));
+  DCHECK(!controller_map_.count(fetch_description->job_unique_id));
+  controller_map_[fetch_description->job_unique_id] = std::move(controller);
 
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::UI},
@@ -397,17 +376,12 @@
 void BackgroundFetchDelegateProxy::StartRequest(
     const std::string& job_unique_id,
     const url::Origin& origin,
-    scoped_refptr<BackgroundFetchRequestInfo> request) {
+    const scoped_refptr<BackgroundFetchRequestInfo>& request) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  DCHECK(job_details_map_.count(job_unique_id));
-  JobDetails& job_details = job_details_map_.find(job_unique_id)->second;
-  DCHECK(job_details.controller);
-
-  std::string download_guid = request->download_guid();
-  DCHECK(!download_guid.empty());
-
-  job_details.current_request_map[download_guid] = request;
+  DCHECK(controller_map_.count(job_unique_id));
+  DCHECK(request);
+  DCHECK(!request->download_guid().empty());
 
   base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
                            base::BindOnce(&Core::StartRequest, ui_core_ptr_,
@@ -421,15 +395,8 @@
     blink::mojom::BackgroundFetchService::UpdateUICallback update_ui_callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  auto job_details_iter = job_details_map_.find(job_unique_id);
-  if (job_details_iter == job_details_map_.end()) {
-    std::move(update_ui_callback)
-        .Run(blink::mojom::BackgroundFetchError::INVALID_ID);
-    return;
-  }
-
-  JobDetails& job_details = job_details_iter->second;
-  job_details.update_ui_callback = std::move(update_ui_callback);
+  DCHECK(!update_ui_callback_map_.count(job_unique_id));
+  update_ui_callback_map_.emplace(job_unique_id, std::move(update_ui_callback));
 
   base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
                            base::BindOnce(&Core::UpdateUI, ui_core_ptr_,
@@ -449,7 +416,7 @@
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::UI},
       base::BindOnce(&Core::MarkJobComplete, ui_core_ptr_, job_unique_id));
-  job_details_map_.erase(job_unique_id);
+  controller_map_.erase(job_unique_id);
 }
 
 void BackgroundFetchDelegateProxy::OnJobCancelled(
@@ -462,15 +429,11 @@
       reason_to_abort ==
           blink::mojom::BackgroundFetchFailureReason::DOWNLOAD_TOTAL_EXCEEDED);
 
-  // TODO(delphick): The controller may not exist as persistence is not yet
-  // implemented.
-  auto job_details_iter = job_details_map_.find(job_unique_id);
-  if (job_details_iter == job_details_map_.end())
-    return;
+  DCHECK(controller_map_.count(job_unique_id));
+  auto& controller = controller_map_[job_unique_id];
 
-  JobDetails& job_details = job_details_iter->second;
-  if (job_details.controller)
-    job_details.controller->AbortFromDelegate(reason_to_abort);
+  if (controller)
+    controller->AbortFromDelegate(reason_to_abort);
 }
 
 void BackgroundFetchDelegateProxy::DidStartRequest(
@@ -479,23 +442,11 @@
     std::unique_ptr<BackgroundFetchResponse> response) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  // TODO(delphick): The controller may not exist as persistence is not yet
-  // implemented.
-  auto job_details_iter = job_details_map_.find(job_unique_id);
-  if (job_details_iter == job_details_map_.end())
-    return;
+  DCHECK(controller_map_.count(job_unique_id));
+  auto& controller = controller_map_[job_unique_id];
 
-  JobDetails& job_details = job_details_iter->second;
-
-  const scoped_refptr<BackgroundFetchRequestInfo>& request_info =
-      job_details.current_request_map[guid];
-  DCHECK(request_info);
-  DCHECK_EQ(guid, request_info->download_guid());
-
-  request_info->PopulateWithResponse(std::move(response));
-
-  if (job_details.controller)
-    job_details.controller->DidStartRequest(request_info);
+  if (controller)
+    controller->DidStartRequest(guid, std::move(response));
 }
 
 void BackgroundFetchDelegateProxy::DidActivateUI(
@@ -506,15 +457,12 @@
 
 void BackgroundFetchDelegateProxy::DidUpdateUI(
     const std::string& job_unique_id) {
-  auto job_details_iter = job_details_map_.find(job_unique_id);
-  if (job_details_iter == job_details_map_.end())
-    return;
+  auto it = update_ui_callback_map_.find(job_unique_id);
+  DCHECK(it != update_ui_callback_map_.end());
+  DCHECK(it->second);
 
-  JobDetails& job_details = job_details_iter->second;
-
-  DCHECK(job_details.update_ui_callback);
-  std::move(job_details.update_ui_callback)
-      .Run(blink::mojom::BackgroundFetchError::NONE);
+  std::move(it->second).Run(blink::mojom::BackgroundFetchError::NONE);
+  update_ui_callback_map_.erase(it);
 }
 
 void BackgroundFetchDelegateProxy::OnDownloadUpdated(
@@ -524,22 +472,11 @@
     uint64_t bytes_downloaded) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  // TODO(delphick): The controller may not exist as persistence is not yet
-  // implemented.
-  auto job_details_iter = job_details_map_.find(job_unique_id);
-  if (job_details_iter == job_details_map_.end())
-    return;
+  DCHECK(controller_map_.count(job_unique_id));
+  auto& controller = controller_map_[job_unique_id];
 
-  JobDetails& job_details = job_details_iter->second;
-
-  // TODO(peter): Should we update the |request_info| with the progress?
-  if (job_details.controller) {
-    const scoped_refptr<BackgroundFetchRequestInfo>& request_info =
-        job_details.current_request_map[guid];
-    DCHECK(request_info);
-    DCHECK_EQ(guid, request_info->download_guid());
-    job_details.controller->DidUpdateRequest(request_info, bytes_uploaded,
-                                             bytes_downloaded);
+  if (controller) {
+    controller->DidUpdateRequest(guid, bytes_uploaded, bytes_downloaded);
   }
 }
 
@@ -549,33 +486,24 @@
     std::unique_ptr<BackgroundFetchResult> result) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  // TODO(delphick): The controller may not exist as persistence is not yet
-  // implemented.
-  auto job_details_iter = job_details_map_.find(job_unique_id);
-  if (job_details_iter == job_details_map_.end())
-    return;
+  DCHECK(controller_map_.count(job_unique_id));
+  auto& controller = controller_map_[job_unique_id];
 
-  JobDetails& job_details = job_details_iter->second;
-
-  const scoped_refptr<BackgroundFetchRequestInfo>& request_info =
-      job_details.current_request_map[guid];
-  DCHECK(request_info);
-  DCHECK_EQ(guid, request_info->download_guid());
-  request_info->SetResult(std::move(result));
-
-  if (job_details.controller)
-    job_details.controller->DidCompleteRequest(request_info);
+  if (controller)
+    controller->DidCompleteRequest(guid, std::move(result));
 }
 
 void BackgroundFetchDelegateProxy::GetUploadData(
     const std::string& job_unique_id,
     const std::string& download_guid,
     BackgroundFetchDelegate::GetUploadDataCallback callback) {
-  auto& job_details = job_details_map_.find(job_unique_id)->second;
-  DCHECK(job_details.controller);
+  DCHECK(controller_map_.count(job_unique_id));
+  auto& controller = controller_map_[job_unique_id];
 
-  const auto& request = job_details.current_request_map[download_guid];
-  job_details.controller->GetUploadData(request, std::move(callback));
+  if (controller)
+    controller->GetUploadData(download_guid, std::move(callback));
+  else
+    std::move(callback).Run(nullptr);
 }
 
 }  // namespace content
diff --git a/content/browser/background_fetch/background_fetch_delegate_proxy.h b/content/browser/background_fetch/background_fetch_delegate_proxy.h
index 6dcd1871..adb7ac46 100644
--- a/content/browser/background_fetch/background_fetch_delegate_proxy.h
+++ b/content/browser/background_fetch/background_fetch_delegate_proxy.h
@@ -38,19 +38,20 @@
    public:
     // Called when the given |request| has started fetching.
     virtual void DidStartRequest(
-        const scoped_refptr<BackgroundFetchRequestInfo>& request) = 0;
+        const std::string& guid,
+        std::unique_ptr<BackgroundFetchResponse> response) = 0;
 
-    // Called when the given |request| has an update, meaning that a total of
-    // |bytes_uploaded| of the request were uploaded, and a total of
+    // Called when the request with the given |guid| has an update, meaning that
+    // a total of |bytes_uploaded| of the request were uploaded, and a total of
     // |bytes_downloaded| are now available for the response.
-    virtual void DidUpdateRequest(
-        const scoped_refptr<BackgroundFetchRequestInfo>& request,
-        uint64_t bytes_uploaded,
-        uint64_t bytes_downloaded) = 0;
+    virtual void DidUpdateRequest(const std::string& guid,
+                                  uint64_t bytes_uploaded,
+                                  uint64_t bytes_downloaded) = 0;
 
-    // Called when the given |request| has been completed.
+    // Called when the request with the given |guid| has been completed.
     virtual void DidCompleteRequest(
-        const scoped_refptr<BackgroundFetchRequestInfo>& request) = 0;
+        const std::string& guid,
+        std::unique_ptr<BackgroundFetchResult> result) = 0;
 
     // Called when the delegate aborts a Background Fetch registration.
     virtual void AbortFromDelegate(
@@ -59,10 +60,10 @@
     // Called by the delegate when the Download Service is requesting the
     // upload data.
     virtual void GetUploadData(
-        const scoped_refptr<BackgroundFetchRequestInfo>& request,
+        const std::string& guid,
         BackgroundFetchDelegate::GetUploadDataCallback callback) = 0;
 
-    virtual ~Controller() {}
+    virtual ~Controller() = default;
   };
 
   explicit BackgroundFetchDelegateProxy(BrowserContext* browser_context);
@@ -71,8 +72,7 @@
 
   // Set BackgroundFetchClick event dispatcher callback, which is a method on
   // the background fetch context.
-  void SetClickEventDispatcher(
-      const DispatchClickEventCallback click_event_callback);
+  void SetClickEventDispatcher(DispatchClickEventCallback click_event_callback);
 
   // Gets size of the icon to display with the Background Fetch UI.
   void GetIconDisplaySize(
@@ -86,32 +86,25 @@
 
   // Creates a new download grouping described by |fetch_description|. Further
   // downloads started by StartRequest will also use
-  // |fetch_description.job_unique_id| so that a notification can be updated
+  // |fetch_description->job_unique_id| so that a notification can be updated
   // with the current status. If the download was already started in a previous
-  // browser session, then |fetch_description.current_guids| should contain the
+  // browser session, then |fetch_description->current_guids| should contain the
   // GUIDs of in progress downloads, while completed downloads are recorded in
-  // |fetch_description.completed_parts|. The size of the completed parts is
-  // recorded in |fetch_description.completed_parts_size| and total download
-  // size is stored in |fetch_description.total_parts_size|.
-  // |active_fetch_requests| contains the BackgroundFetchRequestInfos
-  // needed to correctly resume an ongoing fetch.
+  // |fetch_description->completed_requests|.
   // Should only be called from the Controller (on the IO thread).
   void CreateDownloadJob(
       base::WeakPtr<Controller> controller,
-      std::unique_ptr<BackgroundFetchDescription> fetch_description,
-      std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
-          active_fetch_requests);
+      std::unique_ptr<BackgroundFetchDescription> fetch_description);
 
   // Requests that the download manager start fetching |request|.
   // Should only be called from the Controller (on the IO
   // thread).
   void StartRequest(const std::string& job_unique_id,
                     const url::Origin& origin,
-                    scoped_refptr<BackgroundFetchRequestInfo> request);
+                    const scoped_refptr<BackgroundFetchRequestInfo>& request);
 
   // Updates the representation of this registration in the user interface to
-  // match the given |title| or |icon|. |update_ui_callback| should be called
-  // after all the relevant UI information has been processed.
+  // match the given |title| or |icon|.
   // Called from the Controller (on the IO thread).
   void UpdateUI(const std::string& job_unique_id,
                 const base::Optional<std::string>& title,
@@ -169,28 +162,12 @@
   std::unique_ptr<Core, BrowserThread::DeleteOnUIThread> ui_core_;
   base::WeakPtr<Core> ui_core_ptr_;
 
-  struct JobDetails {
-    JobDetails(base::WeakPtr<Controller> controller,
-               std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
-                   active_fetch_requests);
-    JobDetails(JobDetails&& details);
-    ~JobDetails();
+  // Map from unique job ids to the controller.
+  std::map<std::string, base::WeakPtr<Controller>> controller_map_;
 
-    base::WeakPtr<Controller> controller;
-
-    // Map from DownloadService GUIDs to their corresponding request.
-    base::flat_map<std::string, scoped_refptr<BackgroundFetchRequestInfo>>
-        current_request_map;
-
-    blink::mojom::BackgroundFetchService::UpdateUICallback update_ui_callback;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(JobDetails);
-  };
-
-  // Map from unique job ids to a JobDetails containing the outstanding download
-  // GUIDs and the controller that started the download.
-  std::map<std::string, JobDetails> job_details_map_;
+  // The callback to run after the UI information has been updated.
+  std::map<std::string, blink::mojom::BackgroundFetchService::UpdateUICallback>
+      update_ui_callback_map_;
 
   DispatchClickEventCallback click_event_dispatcher_callback_;
   base::WeakPtrFactory<BackgroundFetchDelegateProxy> weak_ptr_factory_;
diff --git a/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc b/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
index ea14e02992..7d3c650 100644
--- a/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
+++ b/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
@@ -143,17 +143,18 @@
   FakeController() : weak_ptr_factory_(this) {}
 
   void DidStartRequest(
-      const scoped_refptr<BackgroundFetchRequestInfo>& request) override {
+      const std::string& guid,
+      std::unique_ptr<BackgroundFetchResponse> response) override {
     request_started_ = true;
   }
 
-  void DidUpdateRequest(
-      const scoped_refptr<BackgroundFetchRequestInfo>& request,
-      uint64_t bytes_uploaded,
-      uint64_t bytes_downloaded) override {}
+  void DidUpdateRequest(const std::string& guid,
+                        uint64_t bytes_uploaded,
+                        uint64_t bytes_downloaded) override {}
 
   void DidCompleteRequest(
-      const scoped_refptr<BackgroundFetchRequestInfo>& request) override {
+      const std::string& guid,
+      std::unique_ptr<BackgroundFetchResult> result) override {
     request_completed_ = true;
   }
 
@@ -161,7 +162,7 @@
       blink::mojom::BackgroundFetchFailureReason reason_to_abort) override {}
 
   void GetUploadData(
-      const scoped_refptr<BackgroundFetchRequestInfo>& request,
+      const std::string& guid,
       BackgroundFetchDelegate::GetUploadDataCallback callback) override {}
 
   bool request_started_ = false;
@@ -216,8 +217,7 @@
       /* outstanding_guids= */ std::vector<std::string>(),
       /* start_paused= */ false);
   delegate_proxy_.CreateDownloadJob(controller.weak_ptr_factory_.GetWeakPtr(),
-                                    std::move(fetch_description),
-                                    /* active_fetch_requests= */ {});
+                                    std::move(fetch_description));
 
   delegate_proxy_.StartRequest(kExampleUniqueId, url::Origin(), request);
   base::RunLoop().RunUntilIdle();
@@ -244,8 +244,7 @@
       /* outstanding_guids= */ std::vector<std::string>(),
       /* start_paused= */ false);
   delegate_proxy_.CreateDownloadJob(controller.weak_ptr_factory_.GetWeakPtr(),
-                                    std::move(fetch_description),
-                                    /* active_fetch_requests= */ {});
+                                    std::move(fetch_description));
 
   delegate_proxy_.StartRequest(kExampleUniqueId, url::Origin(), request);
   base::RunLoop().RunUntilIdle();
@@ -277,8 +276,7 @@
       /* outstanding_guids= */ std::vector<std::string>(),
       /* start_paused= */ false);
   delegate_proxy_.CreateDownloadJob(controller.weak_ptr_factory_.GetWeakPtr(),
-                                    std::move(fetch_description1),
-                                    /* active_fetch_requests= */ {});
+                                    std::move(fetch_description1));
 
   auto fetch_description2 = std::make_unique<BackgroundFetchDescription>(
       kExampleUniqueId2, url::Origin(), /* title= */ "Job 2", SkBitmap(),
@@ -288,8 +286,7 @@
       /* outstanding_guids= */ std::vector<std::string>(),
       /* start_paused= */ false);
   delegate_proxy_.CreateDownloadJob(controller2.weak_ptr_factory_.GetWeakPtr(),
-                                    std::move(fetch_description2),
-                                    /* active_fetch_requests= */ {});
+                                    std::move(fetch_description2));
 
   delegate_proxy_.StartRequest(kExampleUniqueId, url::Origin(), request);
   delegate_proxy_.StartRequest(kExampleUniqueId2, url::Origin(), request2);
@@ -328,8 +325,7 @@
       /* start_paused= */ false);
 
   delegate_proxy_.CreateDownloadJob(controller.weak_ptr_factory_.GetWeakPtr(),
-                                    std::move(fetch_description),
-                                    /* active_fetch_requests= */ {});
+                                    std::move(fetch_description));
 
   delegate_proxy_.StartRequest(kExampleUniqueId, url::Origin(), request);
   base::RunLoop().RunUntilIdle();
@@ -369,11 +365,9 @@
       /* start_paused= */ false);
 
   delegate_proxy1.CreateDownloadJob(controller1.weak_ptr_factory_.GetWeakPtr(),
-                                    std::move(fetch_description1),
-                                    /* active_fetch_requests= */ {});
+                                    std::move(fetch_description1));
   delegate_proxy2.CreateDownloadJob(controller2.weak_ptr_factory_.GetWeakPtr(),
-                                    std::move(fetch_description2),
-                                    /* active_fetch_requests= */ {});
+                                    std::move(fetch_description2));
 
   auto request = CreateRequestInfo(/* request_index= */ 0,
                                    blink::mojom::FetchAPIRequest::New());
diff --git a/content/browser/background_fetch/background_fetch_job_controller.cc b/content/browser/background_fetch/background_fetch_job_controller.cc
index d01d733..d3d17da0 100644
--- a/content/browser/background_fetch/background_fetch_job_controller.cc
+++ b/content/browser/background_fetch/background_fetch_job_controller.cc
@@ -121,9 +121,11 @@
       complete_requests_uploaded_bytes_cache_, options_->download_total,
       upload_total_, std::move(active_guids), start_paused);
 
+  for (auto& active_request : active_fetch_requests)
+    active_request_map_[active_request->download_guid()] = active_request;
+
   delegate_proxy_->CreateDownloadJob(weak_ptr_factory_.GetWeakPtr(),
-                                     std::move(fetch_description),
-                                     std::move(active_fetch_requests));
+                                     std::move(fetch_description));
 }
 
 BackgroundFetchJobController::~BackgroundFetchJobController() {
@@ -155,24 +157,36 @@
     return;
   }
 
+  active_request_map_[request->download_guid()] = request;
   delegate_proxy_->StartRequest(registration_id().unique_id(),
-                                registration_id().origin(), request);
+                                registration_id().origin(), request.get());
 }
 
 void BackgroundFetchJobController::DidStartRequest(
-    const scoped_refptr<BackgroundFetchRequestInfo>& request) {
+    const std::string& guid,
+    std::unique_ptr<BackgroundFetchResponse> response) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  DCHECK(active_request_map_.count(guid));
+  const auto& request = active_request_map_[guid];
+  DCHECK(request);
+
+  request->PopulateWithResponse(std::move(response));
+
   // TODO(crbug.com/884672): Stop the fetch if the cross origin filter fails.
   BackgroundFetchCrossOriginFilter filter(registration_id_.origin(), *request);
   request->set_can_populate_body(filter.CanPopulateBody());
 }
 
-void BackgroundFetchJobController::DidUpdateRequest(
-    const scoped_refptr<BackgroundFetchRequestInfo>& request,
-    uint64_t bytes_uploaded,
-    uint64_t bytes_downloaded) {
+void BackgroundFetchJobController::DidUpdateRequest(const std::string& guid,
+                                                    uint64_t bytes_uploaded,
+                                                    uint64_t bytes_downloaded) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
+  DCHECK(active_request_map_.count(guid));
+  const auto& request = active_request_map_[guid];
+  DCHECK(request);
+
   // Don't send download updates so the size is not leaked.
   // Upload updates are fine since that information is already available.
   if (!request->can_populate_body() && bytes_downloaded > 0u)
@@ -193,9 +207,16 @@
 }
 
 void BackgroundFetchJobController::DidCompleteRequest(
-    const scoped_refptr<BackgroundFetchRequestInfo>& request) {
+    const std::string& guid,
+    std::unique_ptr<BackgroundFetchResult> result) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
+  DCHECK(active_request_map_.count(guid));
+  const auto& request = active_request_map_[guid];
+  DCHECK(request);
+
+  request->SetResult(std::move(result));
+
   if (request->can_populate_body())
     complete_requests_downloaded_bytes_cache_ += request->GetFileSize();
   active_request_downloaded_bytes_ -= request->GetFileSize();
@@ -324,8 +345,12 @@
 }
 
 void BackgroundFetchJobController::GetUploadData(
-    const scoped_refptr<BackgroundFetchRequestInfo>& request,
+    const std::string& guid,
     BackgroundFetchDelegate::GetUploadDataCallback callback) {
+  DCHECK(active_request_map_.count(guid));
+  const auto& request = active_request_map_[guid];
+  DCHECK(request);
+
   data_manager_->GetRequestBlob(
       registration_id(), request,
       base::BindOnce(&BackgroundFetchJobController::DidGetUploadData,
diff --git a/content/browser/background_fetch/background_fetch_job_controller.h b/content/browser/background_fetch/background_fetch_job_controller.h
index 98b52ad..13550d6 100644
--- a/content/browser/background_fetch/background_fetch_job_controller.h
+++ b/content/browser/background_fetch/background_fetch_job_controller.h
@@ -90,17 +90,18 @@
 
   // BackgroundFetchDelegateProxy::Controller implementation:
   void DidStartRequest(
-      const scoped_refptr<BackgroundFetchRequestInfo>& request) override;
-  void DidUpdateRequest(
-      const scoped_refptr<BackgroundFetchRequestInfo>& request,
-      uint64_t bytes_uploaded,
-      uint64_t bytes_downloaded) override;
+      const std::string& guid,
+      std::unique_ptr<BackgroundFetchResponse> response) override;
+  void DidUpdateRequest(const std::string& guid,
+                        uint64_t bytes_uploaded,
+                        uint64_t bytes_downloaded) override;
   void DidCompleteRequest(
-      const scoped_refptr<BackgroundFetchRequestInfo>& request) override;
+      const std::string& guid,
+      std::unique_ptr<BackgroundFetchResult> result) override;
   void AbortFromDelegate(
       blink::mojom::BackgroundFetchFailureReason failure_reason) override;
   void GetUploadData(
-      const scoped_refptr<BackgroundFetchRequestInfo>& request,
+      const std::string& guid,
       BackgroundFetchDelegate::GetUploadDataCallback callback) override;
 
   // Aborts the fetch. |callback| will run with the result of marking the
@@ -150,6 +151,10 @@
   // boundaries. It is owned by the BackgroundFetchContext.
   BackgroundFetchDelegateProxy* delegate_proxy_;
 
+  // A map from the download GUID to the active request.
+  std::map<std::string, scoped_refptr<BackgroundFetchRequestInfo>>
+      active_request_map_;
+
   // The registration ID of the fetch this controller represents.
   BackgroundFetchRegistrationId registration_id_;
 
diff --git a/content/browser/background_fetch/background_fetch_scheduler_unittest.cc b/content/browser/background_fetch/background_fetch_scheduler_unittest.cc
index 1d26645..333e688 100644
--- a/content/browser/background_fetch/background_fetch_scheduler_unittest.cc
+++ b/content/browser/background_fetch/background_fetch_scheduler_unittest.cc
@@ -52,14 +52,15 @@
   ~FakeController() override = default;
 
   void DidCompleteRequest(
-      const scoped_refptr<BackgroundFetchRequestInfo>& request) override {
+      const std::string& guid,
+      std::unique_ptr<BackgroundFetchResult> result) override {
     // Record the completed request. Store everything after the origin and the
     // slash, to be able to directly compare with the provided requests.
     controller_sequence_list_->push_back(
-        request->fetch_request()->url.path().substr(1));
+        result->response->url_chain[0].path().substr(1));
 
     // Continue normally.
-    BackgroundFetchJobController::DidCompleteRequest(request);
+    BackgroundFetchJobController::DidCompleteRequest(guid, std::move(result));
   }
 
  private:
diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h
index 03b16dde..2483419e 100644
--- a/content/browser/bad_message.h
+++ b/content/browser/bad_message.h
@@ -238,6 +238,7 @@
   RFH_DETACH_MAIN_FRAME = 210,
   RFH_DOCUMENT_INTERFACE_BROKER_MISSING = 211,
   RFPH_POST_MESSAGE_INVALID_SOURCE_ORIGIN = 212,
+  INVALID_INITIATOR_ORIGIN = 213,
 
   // Please add new elements here. The naming convention is abbreviated class
   // name (e.g. RenderFrameHost becomes RFH) plus a unique description of the
diff --git a/content/browser/frame_host/ipc_utils.cc b/content/browser/frame_host/ipc_utils.cc
index 1530444..47bfd1e 100644
--- a/content/browser/frame_host/ipc_utils.cc
+++ b/content/browser/frame_host/ipc_utils.cc
@@ -45,6 +45,22 @@
   return true;
 }
 
+bool VerifyInitiatorOrigin(int process_id,
+                           const url::Origin& initiator_origin) {
+  // TODO(lukasza, nasko): Verify precursor origin via CanAccessDataForOrigin.
+  if (initiator_origin.opaque())
+    return true;
+
+  auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
+  if (!policy->CanAccessDataForOrigin(process_id, initiator_origin.GetURL())) {
+    bad_message::ReceivedBadMessage(process_id,
+                                    bad_message::INVALID_INITIATOR_ORIGIN);
+    return false;
+  }
+
+  return true;
+}
+
 }  // namespace
 
 bool VerifyDownloadUrlParams(
@@ -62,7 +78,9 @@
     return false;
   }
 
-  // TODO(lukasza): Verify |params.initiator_origin|.
+  // Verify |params.initiator_origin|.
+  if (!VerifyInitiatorOrigin(process_id, params.initiator_origin))
+    return false;
 
   return true;
 }
@@ -106,7 +124,9 @@
     return false;
   }
 
-  // TODO(lukasza): Verify |params.initiator_origin|.
+  // Verify |params.initiator_origin|.
+  if (!VerifyInitiatorOrigin(process_id, params.initiator_origin))
+    return false;
 
   return true;
 }
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc
index ad2231d4..b3265ed6 100644
--- a/content/browser/frame_host/navigation_controller_impl.cc
+++ b/content/browser/frame_host/navigation_controller_impl.cc
@@ -2673,6 +2673,14 @@
   // URLs, unlike the cases below where we clear it if the navigation doesn't
   // proceed.
   if (IsRendererDebugURL(params.url)) {
+    // Renderer-debug URLs won't go through NavigationThrottlers so we have to
+    // check them explicitly. See bug 913334.
+    if (GetContentClient()->browser()->IsRendererDebugURLBlacklisted(
+            params.url, browser_context_)) {
+      DiscardPendingEntry(false);
+      return;
+    }
+
     HandleRendererDebugURL(node, params.url);
     return;
   }
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index 12e38b8b..caf9e5fe 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -979,6 +979,13 @@
                                            gpu_feature_info_for_hardware_gpu);
     gpu_data_manager->UpdateGpuInfo(gpu_info, gpu_info_for_hardware_gpu);
   }
+
+#if defined(OS_ANDROID)
+  // Android may kill the GPU process to free memory, especially when the app
+  // is the background, so Android cannot have a hard limit on GPU starts.
+  // Reset crash count on Android when context creation succeeds.
+  hardware_accelerated_recent_crash_count_ = 0;
+#endif
 }
 
 void GpuProcessHost::DidFailInitialize() {
diff --git a/content/browser/media/session/media_metadata_sanitizer.cc b/content/browser/media/session/media_metadata_sanitizer.cc
index c98ad630..33cd5e4 100644
--- a/content/browser/media/session/media_metadata_sanitizer.cc
+++ b/content/browser/media/session/media_metadata_sanitizer.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <string>
 
+#include "services/media_session/public/cpp/media_image.h"
 #include "services/media_session/public/cpp/media_metadata.h"
 
 namespace content {
@@ -42,8 +43,7 @@
   return true;
 }
 
-bool CheckMediaImageSanity(
-    const media_session::MediaMetadata::MediaImage& image) {
+bool CheckMediaImageSanity(const media_session::MediaImage& image) {
   if (!CheckMediaImageSrcSanity(image.src))
     return false;
   if (image.type.size() > kMaxMediaImageTypeLength)
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 9244b9a1..41eb2bb 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -2531,6 +2531,7 @@
 }
 
 void RenderProcessHostImpl::PurgeAndSuspend() {
+  TRACE_EVENT0("renderer_host", "RenderProcessHostImpl::PurgeAndSuspend");
   GetRendererInterface()->ProcessPurgeAndSuspend();
 }
 
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index c6a41c4..83d0a79 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -7,12 +7,14 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/feature_list.h"
+#include "base/guid.h"
 #include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/post_task.h"
 #include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "content/browser/bad_message.h"
+#include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/dom_storage/dom_storage_context_wrapper.h"
 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
 #include "content/browser/frame_host/navigator.h"
@@ -311,6 +313,18 @@
   // Tests that a given file path sent in a FrameHostMsg_RunFileChooser will
   // cause renderer to be killed.
   void TestFileChooserWithPath(const base::FilePath& path);
+
+  void IsolateOrigin(const std::string& hostname) {
+    ChildProcessSecurityPolicyImpl::GetInstance()->AddIsolatedOrigins(
+        {url::Origin::Create(embedded_test_server()->GetURL(hostname, "/"))});
+
+    // Force a BrowsingInstance swap by navigating cross-site (the newly
+    // isolated origin only affects *future* BrowsingInstances).
+    std::string cross_site_hostname = base::GenerateGUID() + ".com";
+    EXPECT_TRUE(NavigateToURL(
+        shell(),
+        embedded_test_server()->GetURL(cross_site_hostname, "/title1.html")));
+  }
 };
 
 void SecurityExploitBrowserTest::TestFileChooserWithPath(
@@ -997,10 +1011,9 @@
 // a disallowed URL (e.g., file URL), that navigation is blocked.
 IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
                        BlockIllegalOpenURLFromRemoteFrame) {
-  // This test is only valid in site-per-process mode, where a cross-site
-  // iframe will have a proxy in the main frame's process.
-  if (!AreAllSitesIsolatedForTesting())
-    return;
+  // Explicitly isolating a.com helps ensure that this test is applicable on
+  // platforms without site-per-process.
+  IsolateOrigin("a.com");
 
   GURL main_url(embedded_test_server()->GetURL(
       "a.com", "/cross_site_iframe_factory.html?a(b)"));
@@ -1126,10 +1139,9 @@
 // FrameMsg_PostMessage_Params::source_origin.  See also
 // https://crbug.com/915721.
 IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, PostMessageSourceOrigin) {
-  // On platforms without full Site Isolation (i.e. site-per-process), both
-  // frames can share a process - the test doesn't make sense in such scenario.
-  if (!AreAllSitesIsolatedForTesting())
-    return;
+  // Explicitly isolating a.com helps ensure that this test is applicable on
+  // platforms without site-per-process.
+  IsolateOrigin("b.com");
 
   // Navigate to a page with an OOPIF.
   GURL main_url(embedded_test_server()->GetURL(
@@ -1172,4 +1184,104 @@
             kill_waiter.Wait());
 }
 
+class OpenUrlIpcInterceptor : public BrowserMessageFilter {
+ public:
+  // Starts listening for IPC messages to |process|, intercepting
+  // FrameHostMsg_OpenURL IPC message and storing once it comes.
+  explicit OpenUrlIpcInterceptor(RenderProcessHost* process)
+      : BrowserMessageFilter(FrameMsgStart) {
+    process->AddFilter(this);
+  }
+
+  // Waits for FrameHostMsg_OpenURL (if it didn't come yet) and returns
+  // message payload to the caller.
+  void WaitForMessage(int32_t* out_routing_id,
+                      FrameHostMsg_OpenURL_Params* out_params) {
+    run_loop_.Run();
+    *out_routing_id = intercepted_routing_id_;
+    *out_params = intercepted_params_;
+  }
+
+ private:
+  ~OpenUrlIpcInterceptor() override = default;
+
+  void OnOpenURL(const FrameHostMsg_OpenURL_Params& params) {
+    intercepted_params_ = params;
+  }
+
+  bool OnMessageReceived(const IPC::Message& message) override {
+    // Only intercept one message.
+    if (already_intercepted_)
+      return false;
+
+    // See if we got FrameHostMsg_RouteMessageEvent and if so unpack and store
+    // its payload in OnRouteMessageEvent.
+    bool handled = true;
+    IPC_BEGIN_MESSAGE_MAP(OpenUrlIpcInterceptor, message)
+      IPC_MESSAGE_HANDLER(FrameHostMsg_OpenURL, OnOpenURL)
+      IPC_MESSAGE_UNHANDLED(handled = false)
+    IPC_END_MESSAGE_MAP()
+
+    // If we got FrameHostMsg_RouteMessageEvent, then also store the routing ID
+    // and signal to the main test thread that it can stop waiting.
+    if (handled) {
+      already_intercepted_ = true;
+      intercepted_routing_id_ = message.routing_id();
+      run_loop_.Quit();
+    }
+
+    return handled;
+  }
+
+  bool already_intercepted_ = false;
+  int32_t intercepted_routing_id_;
+  FrameHostMsg_OpenURL_Params intercepted_params_;
+  base::RunLoop run_loop_;
+
+  DISALLOW_COPY_AND_ASSIGN(OpenUrlIpcInterceptor);
+};
+
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
+                       InvalidRemoteNavigationInitiator) {
+  // Explicitly isolating a.com helps ensure that this test is applicable on
+  // platforms without site-per-process.
+  IsolateOrigin("a.com");
+
+  // Navigate to a test page where the subframe is cross-site (and because of
+  // IsolateOrigin call above in a separate process) from the main frame.
+  GURL main_url(embedded_test_server()->GetURL(
+      "a.com", "/cross_site_iframe_factory.html?a(b)"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+  RenderFrameHost* main_frame = shell()->web_contents()->GetMainFrame();
+  RenderProcessHost* main_process = main_frame->GetProcess();
+  EXPECT_EQ(2u, shell()->web_contents()->GetAllFrames().size());
+  RenderFrameHost* subframe = shell()->web_contents()->GetAllFrames()[1];
+  RenderProcessHost* subframe_process = subframe->GetProcess();
+  EXPECT_NE(main_process->GetID(), subframe_process->GetID());
+
+  // Prepare to intercept FrameHostMsg_OpenURL IPC message that will come from
+  // the main frame process.
+  auto ipc_interceptor =
+      base::MakeRefCounted<OpenUrlIpcInterceptor>(main_process);
+
+  // Have the main frame request navigation in the "remote" subframe.  This will
+  // result in FrameHostMsg_OpenURL IPC being sent to the RenderFrameProxyHost.
+  EXPECT_TRUE(ExecJs(shell()->web_contents()->GetMainFrame(),
+                     "window.frames[0].location = '/title1.html';"));
+  int intercepted_routing_id;
+  FrameHostMsg_OpenURL_Params intercepted_params;
+  ipc_interceptor->WaitForMessage(&intercepted_routing_id, &intercepted_params);
+
+  // Change the intercepted message to simulate a compromised subframe renderer
+  // lying that the |initiator_origin| is the origin of the |subframe|.
+  FrameHostMsg_OpenURL_Params evil_params = intercepted_params;
+  evil_params.initiator_origin = subframe->GetLastCommittedOrigin();
+  FrameHostMsg_OpenURL evil_msg(intercepted_routing_id, evil_params);
+
+  // Inject the invalid IPC and verify that the renderer gets terminated.
+  RenderProcessHostKillWaiter kill_waiter(main_process);
+  IpcSecurityTestUtil::PwnMessageReceived(main_process->GetChannel(), evil_msg);
+  EXPECT_EQ(bad_message::INVALID_INITIATOR_ORIGIN, kill_waiter.Wait());
+}
+
 }  // namespace content
diff --git a/content/browser/service_manager/service_manager_context.cc b/content/browser/service_manager/service_manager_context.cc
index 580ac8f..e41a379 100644
--- a/content/browser/service_manager/service_manager_context.cc
+++ b/content/browser/service_manager/service_manager_context.cc
@@ -81,9 +81,9 @@
 #include "services/service_manager/public/cpp/service.h"
 #include "services/service_manager/public/mojom/service.mojom.h"
 #include "services/service_manager/runner/common/client_util.h"
-#include "services/service_manager/runner/host/service_process_launcher.h"
 #include "services/service_manager/sandbox/sandbox_type.h"
 #include "services/service_manager/service_manager.h"
+#include "services/service_manager/service_process_launcher.h"
 #include "services/shape_detection/public/mojom/constants.mojom.h"
 #include "services/tracing/public/mojom/constants.mojom.h"
 #include "services/tracing/tracing_service.h"
diff --git a/content/browser/tracing/background_tracing_manager_impl.cc b/content/browser/tracing/background_tracing_manager_impl.cc
index e8e65f4..f094ae0 100644
--- a/content/browser/tracing/background_tracing_manager_impl.cc
+++ b/content/browser/tracing/background_tracing_manager_impl.cc
@@ -727,7 +727,8 @@
       auto config = TraceConfig(
           "benchmark,toplevel,ipc,base,browser,navigation,omnibox,ui,shutdown,"
           "safe_browsing,Java,EarlyJava,loading,startup,mojom,renderer_host,"
-          "disabled-by-default-system_stats,disabled-by-default-cpu_profiler",
+          "disabled-by-default-system_stats,disabled-by-default-cpu_profiler,"
+          "dwrite",
           record_mode);
       // Filter only browser process events.
       base::trace_event::TraceConfig::ProcessFilterConfig process_config(
@@ -738,7 +739,7 @@
     case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_RENDERERS:
       return TraceConfig(
           "benchmark,toplevel,ipc,base,ui,v8,renderer,blink,blink_gc,mojom,"
-          "latency,latencyInfo,renderer_host,"
+          "latency,latencyInfo,renderer_host,cc,memory,dwrite,"
           "disabled-by-default-v8.gc,"
           "disabled-by-default-blink_gc,"
           "disabled-by-default-renderer.scheduler,"
diff --git a/content/browser/webrtc/webrtc_audio_browsertest.cc b/content/browser/webrtc/webrtc_audio_browsertest.cc
index 74116973..1b15aa6b 100644
--- a/content/browser/webrtc/webrtc_audio_browsertest.cc
+++ b/content/browser/webrtc/webrtc_audio_browsertest.cc
@@ -20,6 +20,9 @@
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gtest/include/gtest/gtest-param-test.h"
 
+const char kAudioConstraints[] = "audio: {echoCancellation: {exact: false}}";
+const char kVideoConstraints[] = "video:true";
+
 namespace content {
 
 // This class tests the scenario when permission to access mic or camera is
@@ -69,66 +72,96 @@
     MakeTypicalCall(javascript, "/media/peerconnection-call-audio.html");
   }
 
+  std::string BuildConstraints(const char* audio, const char* video) {
+    DCHECK(audio);
+    DCHECK(video);
+
+    std::string audio_str(audio);
+    std::string video_str(video);
+    if (!audio_str.empty() && !video_str.empty())
+      return "{" + audio_str + "," + video_str + "}";
+    if (!audio_str.empty())
+      return "{" + audio_str + "}";
+
+    return "{" + video_str + "}";
+  }
+
  private:
   base::test::ScopedFeatureList audio_service_features_;
 };
 
 IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
                        CanMakeVideoCallAndThenRenegotiateToAudio) {
-  MakeAudioDetectingPeerConnectionCall(
-      "callAndRenegotiateToAudio({audio: {echoCancellation: {exact: false}}, "
-      "video:true}, {audio: {echoCancellation: {exact: false}}});");
+  std::string constraints =
+      BuildConstraints(kAudioConstraints, kVideoConstraints);
+  std::string audio_only_constraints = BuildConstraints(kAudioConstraints, "");
+  MakeAudioDetectingPeerConnectionCall("callAndRenegotiateToAudio(" +
+                                       constraints + ", " +
+                                       audio_only_constraints + ");");
 }
 
 IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
                        EstablishAudioVideoCallAndEnsureAudioIsPlaying) {
-  MakeAudioDetectingPeerConnectionCall(
-      "callAndEnsureAudioIsPlaying({audio: {echoCancellation: {exact: false}}, "
-      "video:true});");
+  std::string constraints =
+      BuildConstraints(kAudioConstraints, kVideoConstraints);
+  MakeAudioDetectingPeerConnectionCall("callAndEnsureAudioIsPlaying(" +
+                                       constraints + ");");
 }
 
 IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
                        EstablishAudioOnlyCallAndEnsureAudioIsPlaying) {
-  MakeAudioDetectingPeerConnectionCall(
-      "callAndEnsureAudioIsPlaying({audio:{echoCancellation: {exact: "
-      "false}}});");
+  std::string constraints =
+      BuildConstraints(kAudioConstraints, kVideoConstraints);
+  MakeAudioDetectingPeerConnectionCall("callAndEnsureAudioIsPlaying(" +
+                                       constraints + ");");
 }
 
 IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
                        EstablishIsac16KCallAndEnsureAudioIsPlaying) {
+  std::string constraints =
+      BuildConstraints(kAudioConstraints, kVideoConstraints);
   MakeAudioDetectingPeerConnectionCall(
-      "callWithIsac16KAndEnsureAudioIsPlaying({audio:{echoCancellation: "
-      "{exact: false}}});");
+      "callWithIsac16KAndEnsureAudioIsPlaying(" + constraints + ");");
 }
 
 IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
                        EstablishAudioVideoCallAndVerifyRemoteMutingWorks) {
+  std::string constraints =
+      BuildConstraints(kAudioConstraints, kVideoConstraints);
   MakeAudioDetectingPeerConnectionCall(
-      "callAndEnsureRemoteAudioTrackMutingWorks();");
+      "callAndEnsureRemoteAudioTrackMutingWorks(" + constraints + ");");
 }
 
 IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
                        EstablishAudioVideoCallAndVerifyLocalMutingWorks) {
+  std::string constraints =
+      BuildConstraints(kAudioConstraints, kVideoConstraints);
   MakeAudioDetectingPeerConnectionCall(
-      "callAndEnsureLocalAudioTrackMutingWorks();");
+      "callAndEnsureLocalAudioTrackMutingWorks(" + constraints + ");");
 }
 
 IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
                        EnsureLocalVideoMuteDoesntMuteAudio) {
+  std::string constraints =
+      BuildConstraints(kAudioConstraints, kVideoConstraints);
   MakeAudioDetectingPeerConnectionCall(
-      "callAndEnsureLocalVideoMutingDoesntMuteAudio();");
+      "callAndEnsureLocalVideoMutingDoesntMuteAudio(" + constraints + ");");
 }
 
 IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
                        EnsureRemoteVideoMuteDoesntMuteAudio) {
+  std::string constraints =
+      BuildConstraints(kAudioConstraints, kVideoConstraints);
   MakeAudioDetectingPeerConnectionCall(
-      "callAndEnsureRemoteVideoMutingDoesntMuteAudio();");
+      "callAndEnsureRemoteVideoMutingDoesntMuteAudio(" + constraints + ");");
 }
 
 IN_PROC_BROWSER_TEST_P(WebRtcAudioBrowserTest,
                        EstablishAudioVideoCallAndVerifyUnmutingWorks) {
-  MakeAudioDetectingPeerConnectionCall(
-      "callAndEnsureAudioTrackUnmutingWorks();");
+  std::string constraints =
+      BuildConstraints(kAudioConstraints, kVideoConstraints);
+  MakeAudioDetectingPeerConnectionCall("callAndEnsureAudioTrackUnmutingWorks(" +
+                                       constraints + ");");
 }
 
 // We run these tests with the audio service both in and out of the the browser
diff --git a/content/browser/websockets/websocket_manager.cc b/content/browser/websockets/websocket_manager.cc
index 94ee27c..08e32d0 100644
--- a/content/browser/websockets/websocket_manager.cc
+++ b/content/browser/websockets/websocket_manager.cc
@@ -83,8 +83,10 @@
   }
 
   bool CanReadRawCookies(const GURL& url) override {
-    return ChildProcessSecurityPolicyImpl::GetInstance()->CanReadRawCookies(
-        manager_->process_id_);
+    ChildProcessSecurityPolicyImpl* impl =
+        ChildProcessSecurityPolicyImpl::GetInstance();
+    return impl->CanReadRawCookies(manager_->process_id_) &&
+           impl->CanAccessDataForOrigin(manager_->process_id_, url);
   }
 
   void OnCreateURLRequest(int child_id,
diff --git a/content/child/browser_font_resource_trusted.cc b/content/child/browser_font_resource_trusted.cc
index a43e2d1..f5145e3 100644
--- a/content/child/browser_font_resource_trusted.cc
+++ b/content/child/browser_font_resource_trusted.cc
@@ -422,16 +422,11 @@
   // Convert position and clip.
   WebFloatPoint web_position(static_cast<float>(position->x),
                              static_cast<float>(position->y));
-  WebRect web_clip;
-  if (!clip) {
-    // Use entire canvas. PaintCanvas doesn't have a size on it, so we just use
-    // the current clip bounds.
-    SkRect skclip = destination->getLocalClipBounds();
-    web_clip = WebRect(skclip.fLeft, skclip.fTop, skclip.fRight - skclip.fLeft,
-                       skclip.fBottom - skclip.fTop);
-  } else {
-    web_clip = WebRect(clip->point.x, clip->point.y,
-                       clip->size.width, clip->size.height);
+
+  cc::PaintCanvasAutoRestore auto_restore(destination, !!clip);
+  if (clip) {
+    destination->clipRect(SkRect::MakeXYWH(
+        clip->point.x, clip->point.y, clip->size.width, clip->size.height));
   }
 
   TextRunCollection runs(text);
@@ -439,7 +434,7 @@
     int32_t run_begin = 0;
     int32_t run_len = 0;
     WebTextRun run = runs.GetRunAt(i, &run_begin, &run_len);
-    font_->DrawText(destination, run, web_position, color, web_clip);
+    font_->DrawText(destination, run, web_position, color);
 
     // Advance to the next run. Note that we avoid doing this for the last run
     // since it's unnecessary, measuring text is slow, and most of the time
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 148d2d6..ccb6dff 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -38,9 +38,9 @@
 
 using blink::WebRuntimeFeatures;
 
-namespace content {
+namespace {
 
-static void SetRuntimeFeatureDefaultsForPlatform() {
+void SetRuntimeFeatureDefaultsForPlatform() {
 #if defined(OS_ANDROID)
   // Android does not have support for PagePopup
   WebRuntimeFeatures::EnablePagePopup(false);
@@ -99,18 +99,9 @@
 #endif
 }
 
-void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
-    const base::CommandLine& command_line) {
-  bool enable_experimental_web_platform_features =
-      command_line.HasSwitch(switches::kEnableExperimentalWebPlatformFeatures);
-  if (enable_experimental_web_platform_features)
-    WebRuntimeFeatures::EnableExperimentalFeatures(true);
-
-  SetRuntimeFeatureDefaultsForPlatform();
-
-  // Begin individual features.
-  // Do not add individual features above this line.
-
+void SetIndividualRuntimeFeatures(
+    const base::CommandLine& command_line,
+    bool enable_experimental_web_platform_features) {
   WebRuntimeFeatures::EnableOriginTrials(
       base::FeatureList::IsEnabled(features::kOriginTrials));
 
@@ -220,6 +211,8 @@
   if (command_line.HasSwitch(switches::kEnablePrintBrowser))
     WebRuntimeFeatures::EnablePrintBrowser(true);
 
+  // TODO(yashard): Remove |enable_experimental_web_platform_features| flag
+  // since the feature should have been enabled when it is set to experimental
   if (command_line.HasSwitch(switches::kEnableNetworkInformationDownlinkMax) ||
       enable_experimental_web_platform_features) {
     WebRuntimeFeatures::EnableNetInfoDownlinkMax(true);
@@ -257,6 +250,8 @@
   if (command_line.HasSwitch(switches::kDisableRemotePlaybackAPI))
     WebRuntimeFeatures::EnableRemotePlaybackAPI(false);
 
+  // TODO(yashard): Remove |enable_experimental_web_platform_features| flag
+  // since the feature should have been enabled when it is set to experimental
   WebRuntimeFeatures::EnableSecMetadata(
       base::FeatureList::IsEnabled(features::kSecMetadata) ||
       enable_experimental_web_platform_features);
@@ -381,6 +376,8 @@
   WebRuntimeFeatures::EnableWebAuth(
       base::FeatureList::IsEnabled(features::kWebAuth));
 
+  // TODO(yashard): Remove |enable_experimental_web_platform_features| flag
+  // since the feature should have been enabled when it is set to experimental
   WebRuntimeFeatures::EnableWebAuthGetTransports(
       base::FeatureList::IsEnabled(features::kWebAuthGetTransports) ||
       enable_experimental_web_platform_features);
@@ -484,14 +481,6 @@
     WebRuntimeFeatures::EnableForbidSyncXHRInPageDismissal(true);
   }
 
-  // End individual features.
-  // Do not add individual features below this line.
-
-  if (command_line.HasSwitch(
-          switches::kDisableOriginTrialControlledBlinkFeatures)) {
-    WebRuntimeFeatures::EnableOriginTrialControlledFeatures(false);
-  }
-
   WebRuntimeFeatures::EnableAutoplayIgnoresWebAudio(
       base::FeatureList::IsEnabled(media::kAutoplayIgnoreWebAudio));
 
@@ -500,17 +489,6 @@
       base::FeatureList::IsEnabled(media::kMediaControlsExpandGesture));
 #endif
 
-  // Enable explicitly enabled features, and then disable explicitly disabled
-  // ones.
-  for (const std::string& feature :
-       FeaturesFromSwitch(command_line, switches::kEnableBlinkFeatures)) {
-    WebRuntimeFeatures::EnableFeatureFromString(feature, true);
-  }
-  for (const std::string& feature :
-       FeaturesFromSwitch(command_line, switches::kDisableBlinkFeatures)) {
-    WebRuntimeFeatures::EnableFeatureFromString(feature, false);
-  }
-
   WebRuntimeFeatures::EnablePortals(
       base::FeatureList::IsEnabled(blink::features::kPortals));
 
@@ -523,6 +501,8 @@
   WebRuntimeFeatures::EnableNoHoverAfterLayoutChange(
       base::FeatureList::IsEnabled(features::kNoHoverAfterLayoutChange));
 
+  // TODO(yashard): Remove |enable_experimental_web_platform_features| flag
+  // since the feature should have been enabled when it is set to experimental
   WebRuntimeFeatures::EnableJankTracking(
       base::FeatureList::IsEnabled(blink::features::kJankTracking) ||
           enable_experimental_web_platform_features,
@@ -540,4 +520,41 @@
       base::FeatureList::IsEnabled(blink::features::kRTCGetDisplayMedia));
 }
 
+}  // namespace
+
+namespace content {
+
+void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
+    const base::CommandLine& command_line) {
+  // Set experimental features
+  bool enable_experimental_web_platform_features =
+      command_line.HasSwitch(switches::kEnableExperimentalWebPlatformFeatures);
+  if (enable_experimental_web_platform_features)
+    WebRuntimeFeatures::EnableExperimentalFeatures(true);
+
+  SetRuntimeFeatureDefaultsForPlatform();
+
+  // Set origin trial features
+  if (command_line.HasSwitch(
+          switches::kDisableOriginTrialControlledBlinkFeatures)) {
+    WebRuntimeFeatures::EnableOriginTrialControlledFeatures(false);
+  }
+
+  // TODO(yashard): Remove |enable_experimental_web_platform_features|
+  // flag since no individual feature should need it
+  SetIndividualRuntimeFeatures(command_line,
+                               enable_experimental_web_platform_features);
+
+  // Enable explicitly enabled features, and then disable explicitly disabled
+  // ones.
+  for (const std::string& feature :
+       FeaturesFromSwitch(command_line, switches::kEnableBlinkFeatures)) {
+    WebRuntimeFeatures::EnableFeatureFromString(feature, true);
+  }
+  for (const std::string& feature :
+       FeaturesFromSwitch(command_line, switches::kDisableBlinkFeatures)) {
+    WebRuntimeFeatures::EnableFeatureFromString(feature, false);
+  }
+}
+
 }  // namespace content
diff --git a/content/public/app/BUILD.gn b/content/public/app/BUILD.gn
index 2e831337..5f44e2d 100644
--- a/content/public/app/BUILD.gn
+++ b/content/public/app/BUILD.gn
@@ -41,7 +41,7 @@
   "//base:i18n",
   "//content:export",
   "//content/public/common:common_sources",
-  "//services/service_manager/background:lib",
+  "//services/service_manager",
   "//services/service_manager/embedder",
   "//services/service_manager/public/cpp",
 ]
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index b411105..5e6bac9 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -920,4 +920,10 @@
   return false;
 }
 
+bool ContentBrowserClient::IsRendererDebugURLBlacklisted(
+    const GURL& url,
+    BrowserContext* context) {
+  return false;
+}
+
 }  // namespace content
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index a12bf4c..bbfa613 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -1448,6 +1448,12 @@
   // to native code, and as such whether its log messages should be recorded.
   virtual bool IsBuiltinComponent(BrowserContext* browser_context,
                                   const url::Origin& origin);
+
+  // Returns whether given |url| has to be blocked. It's used only for renderer
+  // debug URLs, as other requests are handled via NavigationThrottlers and
+  // blacklist policies are applied there.
+  virtual bool IsRendererDebugURLBlacklisted(const GURL& url,
+                                             BrowserContext* context);
 };
 
 }  // namespace content
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index bbe5a56..070e3e6 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -68,7 +68,7 @@
 
 // Enable unified garbage collection in Blink.
 const base::Feature kBlinkHeapUnifiedGarbageCollection{
-    "BlinkHeapUnifiedGarbageCollection", base::FEATURE_ENABLED_BY_DEFAULT};
+    "BlinkHeapUnifiedGarbageCollection", base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Enable bloated renderer detection.
 const base::Feature kBloatedRendererDetection{
diff --git a/content/public/test/blink_test_environment.cc b/content/public/test/blink_test_environment.cc
index cd91cd55f..98bd3a4 100644
--- a/content/public/test/blink_test_environment.cc
+++ b/content/public/test/blink_test_environment.cc
@@ -9,8 +9,6 @@
 #include "base/command_line.h"
 #include "base/run_loop.h"
 #include "base/strings/string_tokenizer.h"
-#include "base/task/task_scheduler/task_scheduler.h"
-#include "base/test/scoped_task_environment.h"
 #include "base/test/test_discardable_memory_allocator.h"
 #include "build/build_config.h"
 #include "content/common/content_switches_internal.h"
@@ -38,12 +36,8 @@
 class TestEnvironment {
  public:
   TestEnvironment()
-#if !defined(OS_ANDROID)
-      // On Android, Java pumps UI messages.
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI)
-#endif
-  {
+      : blink_test_support_(
+            TestBlinkWebUnitTestSupport::SchedulerType::kRealScheduler) {
     base::DiscardableMemoryAllocator::SetInstance(
         &discardable_memory_allocator_);
   }
@@ -52,12 +46,9 @@
 
   // This returns when both the main thread and the TaskSchedules queues are
   // empty.
-  void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); }
+  void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
 
  private:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-
-  // Must be instantiated after ScopedTaskEnvironment.
   TestBlinkWebUnitTestSupport blink_test_support_;
   TestContentClientInitializer content_initializer_;
   base::TestDiscardableMemoryAllocator discardable_memory_allocator_;
diff --git a/content/shell/test_runner/accessibility_controller.cc b/content/shell/test_runner/accessibility_controller.cc
index 146b573..b7df52f 100644
--- a/content/shell/test_runner/accessibility_controller.cc
+++ b/content/shell/test_runner/accessibility_controller.cc
@@ -71,8 +71,10 @@
   if (bindings.IsEmpty())
     return;
   v8::Local<v8::Object> global = context->Global();
-  global->Set(gin::StringToV8(isolate, "accessibilityController"),
-              bindings.ToV8());
+  global
+      ->Set(context, gin::StringToV8(isolate, "accessibilityController"),
+            bindings.ToV8())
+      .Check();
 }
 
 AccessibilityControllerBindings::AccessibilityControllerBindings(
diff --git a/content/shell/test_runner/event_sender.cc b/content/shell/test_runner/event_sender.cc
index 277029b..00490b1 100644
--- a/content/shell/test_runner/event_sender.cc
+++ b/content/shell/test_runner/event_sender.cc
@@ -702,7 +702,8 @@
   if (bindings.IsEmpty())
     return;
   v8::Local<v8::Object> global = context->Global();
-  global->Set(gin::StringToV8(isolate, "eventSender"), bindings.ToV8());
+  global->Set(context, gin::StringToV8(isolate, "eventSender"), bindings.ToV8())
+      .Check();
 }
 
 gin::ObjectTemplateBuilder EventSenderBindings::GetObjectTemplateBuilder(
diff --git a/content/shell/test_runner/gamepad_controller.cc b/content/shell/test_runner/gamepad_controller.cc
index b6651c9..5207c83 100644
--- a/content/shell/test_runner/gamepad_controller.cc
+++ b/content/shell/test_runner/gamepad_controller.cc
@@ -91,7 +91,10 @@
   if (bindings.IsEmpty())
     return;
   v8::Local<v8::Object> global = context->Global();
-  global->Set(gin::StringToV8(isolate, "gamepadController"), bindings.ToV8());
+  global
+      ->Set(context, gin::StringToV8(isolate, "gamepadController"),
+            bindings.ToV8())
+      .Check();
 }
 
 GamepadControllerBindings::GamepadControllerBindings(
diff --git a/content/shell/test_runner/gc_controller.cc b/content/shell/test_runner/gc_controller.cc
index 00a210ba..ec6d4030 100644
--- a/content/shell/test_runner/gc_controller.cc
+++ b/content/shell/test_runner/gc_controller.cc
@@ -34,7 +34,10 @@
   if (controller.IsEmpty())
     return;
   v8::Local<v8::Object> global = context->Global();
-  global->Set(gin::StringToV8(isolate, "GCController"), controller.ToV8());
+  global
+      ->Set(context, gin::StringToV8(isolate, "GCController"),
+            controller.ToV8())
+      .Check();
 }
 
 GCController::GCController(TestInterfaces* interfaces)
diff --git a/content/shell/test_runner/test_runner.cc b/content/shell/test_runner/test_runner.cc
index 75e89d3..edb1eaa 100644
--- a/content/shell/test_runner/test_runner.cc
+++ b/content/shell/test_runner/test_runner.cc
@@ -332,7 +332,8 @@
   v8::Local<v8::Object> global = context->Global();
   v8::Local<v8::Value> v8_bindings = bindings.ToV8();
 
-  global->Set(gin::StringToV8(isolate, "testRunner"), v8_bindings);
+  global->Set(context, gin::StringToV8(isolate, "testRunner"), v8_bindings)
+      .Check();
 
   // Inject some JavaScript to the top-level frame of a reftest in the
   // web-platform-tests suite to have the same reftest screenshot timing as
diff --git a/content/shell/test_runner/text_input_controller.cc b/content/shell/test_runner/text_input_controller.cc
index 0dabe7d2..42a70b2b 100644
--- a/content/shell/test_runner/text_input_controller.cc
+++ b/content/shell/test_runner/text_input_controller.cc
@@ -85,7 +85,10 @@
   if (bindings.IsEmpty())
     return;
   v8::Local<v8::Object> global = context->Global();
-  global->Set(gin::StringToV8(isolate, "textInputController"), bindings.ToV8());
+  global
+      ->Set(context, gin::StringToV8(isolate, "textInputController"),
+            bindings.ToV8())
+      .Check();
 }
 
 TextInputControllerBindings::TextInputControllerBindings(
diff --git a/content/test/data/media/peerconnection-call-audio.html b/content/test/data/media/peerconnection-call-audio.html
index b93e4c2..ee824a27 100644
--- a/content/test/data/media/peerconnection-call-audio.html
+++ b/content/test/data/media/peerconnection-call-audio.html
@@ -93,9 +93,8 @@
     localStream.getAudioTracks()[0].enabled = enabled;
   }
 
-  function callAndEnsureRemoteAudioTrackMutingWorks() {
-    setupCallAndPromiseAudioPlaying(
-        {audio: {echoCancellation: {exact: false}}, video: true}).then(() => {
+  function callAndEnsureRemoteAudioTrackMutingWorks(constraints) {
+    setupCallAndPromiseAudioPlaying(constraints).then(() => {
       // Call is up, now mute the remote track and check we stop playing out
       // audio (after a small delay, we don't expect it to happen instantly).
       enableRemoteAudio(gSecondConnection, false);
@@ -105,9 +104,8 @@
     .catch(failTest);
   }
 
-  function callAndEnsureLocalAudioTrackMutingWorks() {
-    setupCallAndPromiseAudioPlaying(
-        {audio: {echoCancellation: {exact: false}}, video: true}).then(() => {
+  function callAndEnsureLocalAudioTrackMutingWorks(constraints) {
+    setupCallAndPromiseAudioPlaying(constraints).then(() => {
       // Call is up, now mute the local track of the sending side and ensure
       // the receiving side stops receiving audio.
       enableLocalAudio(gFirstConnection, false);
@@ -117,9 +115,8 @@
     .catch(failTest);
   }
 
-  function callAndEnsureAudioTrackUnmutingWorks() {
-    setupCallAndPromiseAudioPlaying(
-        {audio: {echoCancellation: {exact: false}}, video: true}).then(() => {
+  function callAndEnsureAudioTrackUnmutingWorks(constraints) {
+    setupCallAndPromiseAudioPlaying(constraints).then(() => {
       // Mute, wait a while, unmute, verify audio gets back up.
       // (Also, ensure video muting doesn't affect audio).
       enableRemoteAudio(gSecondConnection, false);
@@ -137,18 +134,16 @@
     }).catch(failTest);
   }
 
-  function callAndEnsureLocalVideoMutingDoesntMuteAudio() {
-    setupCallAndPromiseAudioPlaying(
-        {audio: {echoCancellation: {exact: false}}, video: true}).then(() => {
+  function callAndEnsureLocalVideoMutingDoesntMuteAudio(constraints) {
+    setupCallAndPromiseAudioPlaying(constraints).then(() => {
       enableLocalVideo(gFirstConnection, false);
       return ensureAudioPlaying(gSecondConnection)
           .then(reportTestSuccess);
     });
   }
 
-  function callAndEnsureRemoteVideoMutingDoesntMuteAudio() {
-    setupCallAndPromiseAudioPlaying(
-        {audio: {echoCancellation: {exact: false}}, video: true}).then(() => {
+  function callAndEnsureRemoteVideoMutingDoesntMuteAudio(constraints) {
+    setupCallAndPromiseAudioPlaying(constraints).then(() => {
       enableRemoteVideo(gSecondConnection, false);
       return ensureAudioPlaying(gSecondConnection)
           .then(reportTestSuccess);
diff --git a/content/test/test_blink_web_unit_test_support.cc b/content/test/test_blink_web_unit_test_support.cc
index cf6940e0..8fc2e274 100644
--- a/content/test/test_blink_web_unit_test_support.cc
+++ b/content/test/test_blink_web_unit_test_support.cc
@@ -13,6 +13,8 @@
 #include "base/path_service.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/task_scheduler/task_scheduler.h"
+#include "base/test/null_task_runner.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
@@ -129,7 +131,8 @@
 
 namespace content {
 
-TestBlinkWebUnitTestSupport::TestBlinkWebUnitTestSupport()
+TestBlinkWebUnitTestSupport::TestBlinkWebUnitTestSupport(
+    TestBlinkWebUnitTestSupport::SchedulerType scheduler_type)
     : weak_factory_(this) {
 #if defined(OS_MACOSX)
   base::mac::ScopedNSAutoreleasePool autorelease_pool;
@@ -147,7 +150,9 @@
 
   scoped_refptr<base::SingleThreadTaskRunner> dummy_task_runner;
   std::unique_ptr<base::ThreadTaskRunnerHandle> dummy_task_runner_handle;
-  if (!base::ThreadTaskRunnerHandle::IsSet()) {
+  if (scheduler_type == SchedulerType::kMockScheduler) {
+    main_thread_scheduler_ =
+        blink::scheduler::CreateWebMainThreadSchedulerForTests();
     // Dummy task runner is initialized here because the blink::Initialize
     // creates IsolateHolder which needs the current task runner handle. There
     // should be no task posted to this task runner. The message loop is not
@@ -155,12 +160,17 @@
     // of message loops, and their types are not known upfront. Some tests also
     // create their own thread bundles or message loops, and doing the same in
     // TestBlinkWebUnitTestSupport would introduce a conflict.
-    dummy_task_runner = base::MakeRefCounted<DummyTaskRunner>();
+    dummy_task_runner = base::MakeRefCounted<base::NullTaskRunner>();
     dummy_task_runner_handle.reset(
         new base::ThreadTaskRunnerHandle(dummy_task_runner));
+  } else {
+    DCHECK_EQ(scheduler_type, SchedulerType::kRealScheduler);
+    main_thread_scheduler_ =
+        blink::scheduler::WebThreadScheduler::CreateMainThreadScheduler(
+            base::MessageLoop::CreateMessagePumpForType(
+                base::MessageLoop::TYPE_DEFAULT));
+    base::TaskScheduler::CreateAndStartWithDefaultParams("BlinkTestSupport");
   }
-  main_thread_scheduler_ =
-      blink::scheduler::CreateWebMainThreadSchedulerForTests();
 
   // Initialize mojo firstly to enable Blink initialization to use it.
   InitializeMojo();
diff --git a/content/test/test_blink_web_unit_test_support.h b/content/test/test_blink_web_unit_test_support.h
index b83e010f..411c718 100644
--- a/content/test/test_blink_web_unit_test_support.h
+++ b/content/test/test_blink_web_unit_test_support.h
@@ -30,7 +30,21 @@
 // An implementation of BlinkPlatformImpl for tests.
 class TestBlinkWebUnitTestSupport : public BlinkPlatformImpl {
  public:
-  TestBlinkWebUnitTestSupport();
+  enum class SchedulerType {
+    // Create a mock version of scheduling infrastructure, which just forwards
+    // all calls to the default task runner.
+    // All non-blink users (content_unittests etc) should call this method.
+    // Each test has to create base::test::ScopedTaskEnvironment manually.
+    kMockScheduler,
+    // Initialize blink platform with the real scheduler.
+    // Should be used only by webkit_unit_tests.
+    // Tests don't have to create base::test::ScopedTaskEnvironment, but should
+    // be careful not to leak any tasks to the other tests.
+    kRealScheduler,
+  };
+
+  explicit TestBlinkWebUnitTestSupport(
+      SchedulerType scheduler_type = SchedulerType::kMockScheduler);
   ~TestBlinkWebUnitTestSupport() override;
 
   blink::WebBlobRegistry* GetBlobRegistry() override;
diff --git a/extensions/browser/api/networking_private/networking_private_chromeos.cc b/extensions/browser/api/networking_private/networking_private_chromeos.cc
index d924aad2..00d7289e 100644
--- a/extensions/browser/api/networking_private/networking_private_chromeos.cc
+++ b/extensions/browser/api/networking_private/networking_private_chromeos.cc
@@ -28,7 +28,6 @@
 #include "chromeos/network/onc/onc_translator.h"
 #include "chromeos/network/onc/onc_utils.h"
 #include "chromeos/network/portal_detector/network_portal_detector.h"
-#include "chromeos/network/proxy/ui_proxy_config.h"
 #include "chromeos/network/proxy/ui_proxy_config_service.h"
 #include "components/onc/onc_constants.h"
 #include "components/proxy_config/proxy_prefs.h"
@@ -47,7 +46,6 @@
 using chromeos::NetworkStateHandler;
 using chromeos::NetworkTypePattern;
 using chromeos::ShillManagerClient;
-using chromeos::UIProxyConfig;
 using extensions::NetworkingPrivateDelegate;
 
 namespace private_api = extensions::api::networking_private;
@@ -224,74 +222,6 @@
   return device_state;
 }
 
-// Ensures that |container| has a DictionaryValue for |key| and returns it.
-base::DictionaryValue* EnsureDictionaryValue(const std::string& key,
-                                             base::DictionaryValue* container) {
-  base::DictionaryValue* dict;
-  if (!container->GetDictionary(key, &dict)) {
-    container->SetWithoutPathExpansion(
-        key, std::make_unique<base::DictionaryValue>());
-    container->GetDictionary(key, &dict);
-  }
-  return dict;
-}
-
-// Sets the active and effective ONC dictionary values of |dict| based on
-// |state|. Also sets the UserEditable property to false.
-void SetProxyEffectiveValue(base::DictionaryValue* dict,
-                            ProxyPrefs::ConfigState state,
-                            std::unique_ptr<base::Value> value) {
-  // NOTE: ProxyPrefs::ConfigState only exposes 'CONFIG_POLICY' so just use
-  // 'UserPolicy' here for the effective type. The existing UI does not
-  // differentiate between policy types. TODO(stevenjb): Eliminate UIProxyConfig
-  // and instead generate a proper ONC dictionary with the correct policy source
-  // preserved. crbug.com/662529.
-  dict->SetKey(::onc::kAugmentationEffectiveSetting,
-               base::Value(state == ProxyPrefs::CONFIG_EXTENSION
-                               ? ::onc::kAugmentationActiveExtension
-                               : ::onc::kAugmentationUserPolicy));
-  if (state != ProxyPrefs::CONFIG_EXTENSION) {
-    std::unique_ptr<base::Value> value_copy(value->CreateDeepCopy());
-    dict->SetWithoutPathExpansion(::onc::kAugmentationUserPolicy,
-                                  std::move(value_copy));
-  }
-  dict->SetWithoutPathExpansion(::onc::kAugmentationActiveSetting,
-                                std::move(value));
-  dict->SetKey(::onc::kAugmentationUserEditable, base::Value(false));
-}
-
-std::string GetProxySettingsType(const UIProxyConfig::Mode& mode) {
-  switch (mode) {
-    case UIProxyConfig::MODE_DIRECT:
-      return ::onc::proxy::kDirect;
-    case UIProxyConfig::MODE_AUTO_DETECT:
-      return ::onc::proxy::kWPAD;
-    case UIProxyConfig::MODE_PAC_SCRIPT:
-      return ::onc::proxy::kPAC;
-    case UIProxyConfig::MODE_SINGLE_PROXY:
-    case UIProxyConfig::MODE_PROXY_PER_SCHEME:
-      return ::onc::proxy::kManual;
-  }
-  NOTREACHED();
-  return ::onc::proxy::kDirect;
-}
-
-void SetManualProxy(base::DictionaryValue* manual,
-                    ProxyPrefs::ConfigState state,
-                    const std::string& key,
-                    const UIProxyConfig::ManualProxy& proxy) {
-  base::DictionaryValue* dict = EnsureDictionaryValue(key, manual);
-  base::DictionaryValue* host_dict =
-      EnsureDictionaryValue(::onc::proxy::kHost, dict);
-  SetProxyEffectiveValue(
-      host_dict, state,
-      std::make_unique<base::Value>(proxy.server.host_port_pair().host()));
-  uint16_t port = proxy.server.host_port_pair().port();
-  base::DictionaryValue* port_dict =
-      EnsureDictionaryValue(::onc::proxy::kPort, dict);
-  SetProxyEffectiveValue(port_dict, state, std::make_unique<base::Value>(port));
-}
-
 private_api::Certificate GetCertDictionary(
     const NetworkCertificateHandler::Certificate& cert) {
   private_api::Certificate api_cert;
@@ -884,79 +814,20 @@
 void NetworkingPrivateChromeOS::SetManagedActiveProxyValues(
     const std::string& guid,
     base::DictionaryValue* dictionary) {
-  // NOTE: We use UIProxyConfigService and UIProxyConfig for historical
-  // reasons. The model and service were written for a much older UI but
-  // contain a fair amount of subtle logic which is why we use them.
-  // TODO(stevenjb): Re-factor this code and eliminate UIProxyConfig once
-  // the old options UI is abandoned. crbug.com/662529.
-  chromeos::UIProxyConfigService* ui_proxy_config_service =
-      NetworkHandler::Get()->ui_proxy_config_service();
-  ui_proxy_config_service->UpdateFromPrefs(guid);
-  UIProxyConfig config;
-  ui_proxy_config_service->GetProxyConfig(guid, &config);
-  ProxyPrefs::ConfigState state = config.state;
+  const std::string proxy_settings_key = ::onc::network_config::kProxySettings;
+  base::Value* proxy_settings = dictionary->FindKeyOfType(
+      proxy_settings_key, base::Value::Type::DICTIONARY);
 
-  VLOG(1) << "CONFIG STATE FOR: " << guid << ": " << state
-          << " MODE: " << config.mode;
-
-  if (state != ProxyPrefs::CONFIG_POLICY &&
-      state != ProxyPrefs::CONFIG_EXTENSION &&
-      state != ProxyPrefs::CONFIG_OTHER_PRECEDE) {
-    return;
+  if (!proxy_settings) {
+    proxy_settings = dictionary->SetKey(
+        proxy_settings_key, base::Value(base::Value::Type::DICTIONARY));
   }
 
-  // Ensure that the ProxySettings dictionary exists.
-  base::DictionaryValue* proxy_settings =
-      EnsureDictionaryValue(::onc::network_config::kProxySettings, dictionary);
-  VLOG(2) << " PROXY: " << *proxy_settings;
+  NetworkHandler::Get()->ui_proxy_config_service()->MergeEnforcedProxyConfig(
+      guid, proxy_settings);
 
-  // Ensure that the ProxySettings.Type dictionary exists and set the Type
-  // value to the value from |ui_proxy_config_service|.
-  base::DictionaryValue* proxy_type_dict =
-      EnsureDictionaryValue(::onc::network_config::kType, proxy_settings);
-  SetProxyEffectiveValue(proxy_type_dict, state,
-                         base::WrapUnique<base::Value>(new base::Value(
-                             GetProxySettingsType(config.mode))));
-
-  // Update any appropriate sub dictionary based on the new type.
-  switch (config.mode) {
-    case UIProxyConfig::MODE_SINGLE_PROXY: {
-      // Use the same proxy value (config.single_proxy) for all proxies.
-      base::DictionaryValue* manual =
-          EnsureDictionaryValue(::onc::proxy::kManual, proxy_settings);
-      SetManualProxy(manual, state, ::onc::proxy::kHttp, config.single_proxy);
-      SetManualProxy(manual, state, ::onc::proxy::kHttps, config.single_proxy);
-      SetManualProxy(manual, state, ::onc::proxy::kFtp, config.single_proxy);
-      SetManualProxy(manual, state, ::onc::proxy::kSocks, config.single_proxy);
-      break;
-    }
-    case UIProxyConfig::MODE_PROXY_PER_SCHEME: {
-      base::DictionaryValue* manual =
-          EnsureDictionaryValue(::onc::proxy::kManual, proxy_settings);
-      if (config.http_proxy.server.is_valid())
-        SetManualProxy(manual, state, ::onc::proxy::kHttp, config.http_proxy);
-      if (config.https_proxy.server.is_valid())
-        SetManualProxy(manual, state, ::onc::proxy::kHttps, config.https_proxy);
-      if (config.ftp_proxy.server.is_valid())
-        SetManualProxy(manual, state, ::onc::proxy::kFtp, config.ftp_proxy);
-      if (config.socks_proxy.server.is_valid())
-        SetManualProxy(manual, state, ::onc::proxy::kSocks, config.socks_proxy);
-      break;
-    }
-    case UIProxyConfig::MODE_PAC_SCRIPT: {
-      base::DictionaryValue* pac =
-          EnsureDictionaryValue(::onc::proxy::kPAC, proxy_settings);
-      SetProxyEffectiveValue(pac, state,
-                             base::WrapUnique<base::Value>(new base::Value(
-                                 config.automatic_proxy.pac_url.spec())));
-      break;
-    }
-    case UIProxyConfig::MODE_DIRECT:
-    case UIProxyConfig::MODE_AUTO_DETECT:
-      break;
-  }
-
-  VLOG(2) << " NEW PROXY: " << *proxy_settings;
+  if (proxy_settings->DictEmpty())
+    dictionary->RemoveKey(proxy_settings_key);
 }
 
 }  // namespace extensions
diff --git a/extensions/shell/BUILD.gn b/extensions/shell/BUILD.gn
index 691b82a..6d6db7c 100644
--- a/extensions/shell/BUILD.gn
+++ b/extensions/shell/BUILD.gn
@@ -196,6 +196,7 @@
       "browser/shell_native_app_window_aura.h",
     ]
     deps += [
+      "//ui/base/user_activity",
       "//ui/platform_window",
       "//ui/wm",
       "//ui/wm/public",
diff --git a/media/gpu/test/BUILD.gn b/media/gpu/test/BUILD.gn
index 058dda9..8940e0e 100644
--- a/media/gpu/test/BUILD.gn
+++ b/media/gpu/test/BUILD.gn
@@ -154,6 +154,7 @@
   static_library("video_player_test_environment") {
     testonly = true
     sources = [
+      "video_player/video_player_test_environment.cc",
       "video_player/video_player_test_environment.h",
     ]
     data = [
diff --git a/media/gpu/test/video_player/video_player_test_environment.cc b/media/gpu/test/video_player/video_player_test_environment.cc
new file mode 100644
index 0000000..1c40bcf
--- /dev/null
+++ b/media/gpu/test/video_player/video_player_test_environment.cc
@@ -0,0 +1,51 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/gpu/test/video_player/video_player_test_environment.h"
+
+namespace media {
+namespace test {
+VideoPlayerTestEnvironment::VideoPlayerTestEnvironment(const Video* video)
+    : video_(video) {}
+
+VideoPlayerTestEnvironment::~VideoPlayerTestEnvironment() = default;
+
+void VideoPlayerTestEnvironment::SetUp() {
+  // Setting up a task environment will create a task runner for the current
+  // thread and allow posting tasks to other threads. This is required for the
+  // test video player to function correctly.
+  TestTimeouts::Initialize();
+  task_environment_ = std::make_unique<base::test::ScopedTaskEnvironment>(
+      base::test::ScopedTaskEnvironment::MainThreadType::UI);
+
+  // Perform all static initialization that is required when running video
+  // decoders in a test environment.
+#if BUILDFLAG(USE_VAAPI)
+  media::VaapiWrapper::PreSandboxInitialization();
+#endif
+
+#if defined(USE_OZONE)
+  // Initialize Ozone. This is necessary to gain access to the GPU for hardware
+  // video decode acceleration.
+  LOG(WARNING) << "Initializing Ozone Platform...\n"
+                  "If this hangs indefinitely please call 'stop ui' first!";
+  ui::OzonePlatform::InitParams params = {.single_process = false};
+  ui::OzonePlatform::InitializeForUI(params);
+  ui::OzonePlatform::InitializeForGPU(params);
+  ui::OzonePlatform::GetInstance()->AfterSandboxEntry();
+
+  // Initialize the Ozone GPU helper. If this is not done an error will occur:
+  // "Check failed: drm. No devices available for buffer allocation."
+  // Note: If a task environment is not set up initialization will hang
+  // indefinitely here.
+  gpu_helper_.reset(new ui::OzoneGpuTestHelper());
+  gpu_helper_->Initialize(base::ThreadTaskRunnerHandle::Get());
+#endif
+}
+
+void VideoPlayerTestEnvironment::TearDown() {
+  task_environment_.reset();
+}
+}  // namespace test
+}  // namespace media
diff --git a/media/gpu/test/video_player/video_player_test_environment.h b/media/gpu/test/video_player/video_player_test_environment.h
index 3d36e3ea..cb66a573 100644
--- a/media/gpu/test/video_player/video_player_test_environment.h
+++ b/media/gpu/test/video_player/video_player_test_environment.h
@@ -27,7 +27,8 @@
 // the entire test run.
 class VideoPlayerTestEnvironment : public ::testing::Environment {
  public:
-  explicit VideoPlayerTestEnvironment(const Video* video) : video_(video) {}
+  explicit VideoPlayerTestEnvironment(const Video* video);
+  ~VideoPlayerTestEnvironment();
 
   // Set up the video decode test environment, only called once.
   void SetUp() override;
@@ -47,44 +48,6 @@
   std::unique_ptr<ui::OzoneGpuTestHelper> gpu_helper_;
 #endif
 };
-
-void VideoPlayerTestEnvironment::SetUp() {
-  // Setting up a task environment will create a task runner for the current
-  // thread and allow posting tasks to other threads. This is required for the
-  // test video player to function correctly.
-  TestTimeouts::Initialize();
-  task_environment_ = std::make_unique<base::test::ScopedTaskEnvironment>(
-      base::test::ScopedTaskEnvironment::MainThreadType::UI);
-
-  // Perform all static initialization that is required when running video
-  // decoders in a test environment.
-#if BUILDFLAG(USE_VAAPI)
-  media::VaapiWrapper::PreSandboxInitialization();
-#endif
-
-#if defined(USE_OZONE)
-  // Initialize Ozone. This is necessary to gain access to the GPU for hardware
-  // video decode acceleration.
-  LOG(WARNING) << "Initializing Ozone Platform...\n"
-                  "If this hangs indefinitely please call 'stop ui' first!";
-  ui::OzonePlatform::InitParams params = {.single_process = false};
-  ui::OzonePlatform::InitializeForUI(params);
-  ui::OzonePlatform::InitializeForGPU(params);
-  ui::OzonePlatform::GetInstance()->AfterSandboxEntry();
-
-  // Initialize the Ozone GPU helper. If this is not done an error will occur:
-  // "Check failed: drm. No devices available for buffer allocation."
-  // Note: If a task environment is not set up initialization will hang
-  // indefinitely here.
-  gpu_helper_.reset(new ui::OzoneGpuTestHelper());
-  gpu_helper_->Initialize(base::ThreadTaskRunnerHandle::Get());
-#endif
-}
-
-void VideoPlayerTestEnvironment::TearDown() {
-  task_environment_.reset();
-}
-
 }  // namespace test
 }  // namespace media
 
diff --git a/media/gpu/v4l2/v4l2_image_processor.cc b/media/gpu/v4l2/v4l2_image_processor.cc
index 76b576f..bd013f9 100644
--- a/media/gpu/v4l2/v4l2_image_processor.cc
+++ b/media/gpu/v4l2/v4l2_image_processor.cc
@@ -9,6 +9,7 @@
 #include <sys/eventfd.h>
 #include <sys/ioctl.h>
 #include <sys/mman.h>
+#include <tuple>
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
@@ -43,13 +44,6 @@
 
 namespace media {
 
-V4L2ImageProcessor::InputRecord::InputRecord() : at_device(false) {}
-
-V4L2ImageProcessor::InputRecord::InputRecord(
-    const V4L2ImageProcessor::InputRecord&) = default;
-
-V4L2ImageProcessor::InputRecord::~InputRecord() {}
-
 V4L2ImageProcessor::OutputRecord::OutputRecord() : at_device(false) {}
 
 V4L2ImageProcessor::OutputRecord::OutputRecord(OutputRecord&&) = default;
@@ -85,9 +79,6 @@
       device_(device),
       device_thread_("V4L2ImageProcessorThread"),
       device_poll_thread_("V4L2ImageProcessorDevicePollThread"),
-      input_streamon_(false),
-      input_buffer_queued_count_(0),
-      output_streamon_(false),
       output_buffer_queued_count_(0),
       num_buffers_(num_buffers),
       error_cb_(error_cb) {}
@@ -446,7 +437,7 @@
   DCHECK(device_thread_.task_runner()->BelongsToCurrentThread());
 
   EnqueueOutput(job_record.get());
-  input_queue_.emplace(std::move(job_record));
+  input_job_queue_.emplace(std::move(job_record));
   EnqueueInput();
 }
 
@@ -484,7 +475,7 @@
 bool V4L2ImageProcessor::CreateInputBuffers() {
   VLOGF(2);
   DCHECK(device_thread_.task_runner()->BelongsToCurrentThread());
-  DCHECK(!input_streamon_);
+  DCHECK_EQ(input_queue_, nullptr);
 
   struct v4l2_control control;
   memset(&control, 0, sizeof(control));
@@ -527,31 +518,27 @@
     IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_CROP, &crop);
   }
 
-  struct v4l2_requestbuffers reqbufs;
-  memset(&reqbufs, 0, sizeof(reqbufs));
-  reqbufs.count = num_buffers_;
-  reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-  reqbufs.memory = input_memory_type_;
-  IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs);
-  if (reqbufs.count != num_buffers_) {
-    VLOGF(1) << "Failed to allocate input buffers. reqbufs.count="
-             << reqbufs.count << ", num_buffers=" << num_buffers_;
+  input_queue_ = device_->GetQueue(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+  if (!input_queue_)
+    return false;
+
+  if (input_queue_->AllocateBuffers(num_buffers_, input_memory_type_) == 0u)
+    return false;
+
+  if (input_queue_->AllocatedBuffersCount() != num_buffers_) {
+    VLOGF(1) << "Failed to allocate the required number of input buffers. "
+             << "Requested " << num_buffers_ << ", got "
+             << input_queue_->AllocatedBuffersCount() << ".";
     return false;
   }
 
-  DCHECK(input_buffer_map_.empty());
-  input_buffer_map_.resize(reqbufs.count);
-
-  for (size_t i = 0; i < input_buffer_map_.size(); ++i)
-    free_input_buffers_.push_back(i);
-
   return true;
 }
 
 bool V4L2ImageProcessor::CreateOutputBuffers() {
   VLOGF(2);
   DCHECK(device_thread_.task_runner()->BelongsToCurrentThread());
-  DCHECK(!output_streamon_);
+  DCHECK_EQ(output_queue_, nullptr);
 
   struct v4l2_rect visible_rect;
   visible_rect.left = 0;
@@ -560,6 +547,10 @@
   visible_rect.height =
     base::checked_cast<__u32>(output_visible_size_.height());
 
+  output_queue_ = device_->GetQueue(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+  if (!output_queue_)
+    return false;
+
   struct v4l2_selection selection_arg;
   memset(&selection_arg, 0, sizeof(selection_arg));
   selection_arg.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -574,20 +565,18 @@
     IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_S_CROP, &crop);
   }
 
-  struct v4l2_requestbuffers reqbufs;
-  memset(&reqbufs, 0, sizeof(reqbufs));
-  reqbufs.count = num_buffers_;
-  reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-  reqbufs.memory = output_memory_type_;
-  IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_REQBUFS, &reqbufs);
-  if (reqbufs.count != num_buffers_) {
-    VLOGF(1) << "Failed to allocate output buffers. reqbufs.count="
-             << reqbufs.count << ", num_buffers=" << num_buffers_;
+  if (output_queue_->AllocateBuffers(num_buffers_, output_memory_type_) == 0)
+    return false;
+
+  if (output_queue_->AllocatedBuffersCount() != num_buffers_) {
+    VLOGF(1) << "Failed to allocate output buffers. Allocated number="
+             << output_queue_->AllocatedBuffersCount()
+             << ", Requested number=" << num_buffers_;
     return false;
   }
 
   DCHECK(output_buffer_map_.empty());
-  output_buffer_map_.resize(reqbufs.count);
+  output_buffer_map_.resize(output_queue_->AllocatedBuffersCount());
 
   // Get the DMA-BUF FDs for MMAP buffers
   if (output_memory_type_ == V4L2_MEMORY_MMAP) {
@@ -608,32 +597,17 @@
 void V4L2ImageProcessor::DestroyInputBuffers() {
   VLOGF(2);
   DCHECK(device_thread_.task_runner()->BelongsToCurrentThread());
-  DCHECK(!input_streamon_);
 
-  struct v4l2_requestbuffers reqbufs;
-  memset(&reqbufs, 0, sizeof(reqbufs));
-  reqbufs.count = 0;
-  reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-  reqbufs.memory = input_memory_type_;
-  IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);
-
-  input_buffer_map_.clear();
-  free_input_buffers_.clear();
+  input_queue_->DeallocateBuffers();
 }
 
 void V4L2ImageProcessor::DestroyOutputBuffers() {
   VLOGF(2);
   DCHECK(device_thread_.task_runner()->BelongsToCurrentThread());
-  DCHECK(!output_streamon_);
 
   output_buffer_map_.clear();
 
-  struct v4l2_requestbuffers reqbufs;
-  memset(&reqbufs, 0, sizeof(reqbufs));
-  reqbufs.count = 0;
-  reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-  reqbufs.memory = output_memory_type_;
-  IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);
+  output_queue_->DeallocateBuffers();
 }
 
 void V4L2ImageProcessor::DevicePollTask(bool poll_device) {
@@ -672,31 +646,32 @@
     return;
   }
 
-  bool poll_device =
-      (input_buffer_queued_count_ > 0 || output_buffer_queued_count_ > 0);
+  bool poll_device = (input_queue_->QueuedBuffersCount() > 0 ||
+                      output_buffer_queued_count_ > 0);
 
   device_poll_thread_.task_runner()->PostTask(
       FROM_HERE, base::BindOnce(&V4L2ImageProcessor::DevicePollTask,
                                 base::Unretained(this), poll_device));
 
-  DVLOGF(3) << __func__ << ": buffer counts: INPUT[" << input_queue_.size()
-            << "] => DEVICE[" << free_input_buffers_.size() << "+"
-            << input_buffer_queued_count_ << "/" << input_buffer_map_.size()
-            << "->" << output_buffer_map_.size() - output_buffer_queued_count_
-            << "+" << output_buffer_queued_count_ << "/"
-            << output_buffer_map_.size() << "]";
+  DVLOGF(3) << __func__ << ": buffer counts: INPUT[" << input_job_queue_.size()
+            << "] => DEVICE[" << input_queue_->FreeBuffersCount() << "+"
+            << input_queue_->QueuedBuffersCount() << "/"
+            << input_queue_->AllocatedBuffersCount() << "->"
+            << output_buffer_map_.size() - output_buffer_queued_count_ << "+"
+            << output_buffer_queued_count_ << "/" << output_buffer_map_.size()
+            << "]";
 }
 
 void V4L2ImageProcessor::EnqueueInput() {
   DVLOGF(4);
   DCHECK(device_thread_.task_runner()->BelongsToCurrentThread());
 
-  const int old_inputs_queued = input_buffer_queued_count_;
-  while (!input_queue_.empty() && !free_input_buffers_.empty()) {
+  const size_t old_inputs_queued = input_queue_->QueuedBuffersCount();
+  while (!input_job_queue_.empty() && input_queue_->FreeBuffersCount() > 0) {
     if (!EnqueueInputRecord())
       return;
   }
-  if (old_inputs_queued == 0 && input_buffer_queued_count_ != 0) {
+  if (old_inputs_queued == 0 && input_queue_->QueuedBuffersCount() != 0) {
     // We started up a previously empty queue.
     // Queue state changed; signal interrupt.
     if (!device_->SetDevicePollInterrupt()) {
@@ -704,11 +679,8 @@
       return;
     }
     // VIDIOC_STREAMON if we haven't yet.
-    if (!input_streamon_) {
-      __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-      IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type);
-      input_streamon_ = true;
-    }
+    if (!input_queue_->Streamon())
+      return;
   }
 }
 
@@ -728,50 +700,37 @@
       return;
     }
     // Start VIDIOC_STREAMON if we haven't yet.
-    if (!output_streamon_) {
-      __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-      IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type);
-      output_streamon_ = true;
-    }
+    if (!output_queue_->Streamon())
+      return;
   }
 }
 
 void V4L2ImageProcessor::Dequeue() {
   DVLOGF(4);
   DCHECK(device_thread_.task_runner()->BelongsToCurrentThread());
+  DCHECK(input_queue_->IsStreaming());
 
   // Dequeue completed input (VIDEO_OUTPUT) buffers,
   // and recycle to the free list.
   struct v4l2_buffer dqbuf;
   struct v4l2_plane planes[VIDEO_MAX_PLANES];
-  while (input_buffer_queued_count_ > 0) {
-    DCHECK(input_streamon_);
-    memset(&dqbuf, 0, sizeof(dqbuf));
-    memset(&planes, 0, sizeof(planes));
-    dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-    dqbuf.memory = input_memory_type_;
-    dqbuf.m.planes = planes;
-    dqbuf.length = input_layout_.num_buffers();
-    if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) {
-      if (errno == EAGAIN) {
-        // EAGAIN if we're just out of buffers to dequeue.
-        break;
-      }
-      VPLOGF(1) << "ioctl() failed: VIDIOC_DQBUF";
+  while (input_queue_->QueuedBuffersCount() > 0) {
+    bool res;
+    V4L2ReadableBufferRef buffer;
+    std::tie(res, buffer) = input_queue_->DequeueBuffer();
+    if (!res) {
       NotifyError();
       return;
     }
-    InputRecord& input_record = input_buffer_map_[dqbuf.index];
-    DCHECK(input_record.at_device);
-    input_record.at_device = false;
-    input_record.frame = NULL;
-    free_input_buffers_.push_back(dqbuf.index);
-    input_buffer_queued_count_--;
+    if (!buffer) {
+      // No error occurred, we are just out of buffers to dequeue.
+      break;
+    }
   }
   // Dequeue completed output (VIDEO_CAPTURE) buffers, recycle to the free list.
   // Return the finished buffer to the client via the job ready callback.
   while (output_buffer_queued_count_ > 0) {
-    DCHECK(output_streamon_);
+    DCHECK(output_queue_->IsStreaming());
     memset(&dqbuf, 0, sizeof(dqbuf));
     memset(&planes, 0, sizeof(planes));
     dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
@@ -805,66 +764,41 @@
 
 bool V4L2ImageProcessor::EnqueueInputRecord() {
   DVLOGF(4);
-  DCHECK(!input_queue_.empty());
-  DCHECK(!free_input_buffers_.empty());
+  DCHECK(!input_job_queue_.empty());
+  DCHECK_GT(input_queue_->FreeBuffersCount(), 0u);
 
   // Enqueue an input (VIDEO_OUTPUT) buffer for an input video frame.
-  std::unique_ptr<JobRecord> job_record = std::move(input_queue_.front());
-  input_queue_.pop();
-  const int index = free_input_buffers_.back();
-  InputRecord& input_record = input_buffer_map_[index];
-  DCHECK(!input_record.at_device);
-  input_record.frame = job_record->input_frame;
-  struct v4l2_buffer qbuf;
-  struct v4l2_plane qbuf_planes[VIDEO_MAX_PLANES];
-  memset(&qbuf, 0, sizeof(qbuf));
-  memset(qbuf_planes, 0, sizeof(qbuf_planes));
-  qbuf.index = index;
-  qbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-  qbuf.memory = input_memory_type_;
-  qbuf.m.planes = qbuf_planes;
-  qbuf.length = input_layout_.num_buffers();
+  std::unique_ptr<JobRecord> job_record = std::move(input_job_queue_.front());
+  input_job_queue_.pop();
+  V4L2WritableBufferRef buffer(input_queue_->GetFreeBuffer());
+  DCHECK(buffer.IsValid());
 
-  std::vector<int> fds;
-  if (input_memory_type_ == V4L2_MEMORY_DMABUF) {
-    auto& scoped_fds = input_record.frame->DmabufFds();
-    if (scoped_fds.size() != input_layout_.num_buffers()) {
-      VLOGF(1) << "Invalid number of planes in the frame";
-      return false;
-    }
-    for (auto& fd : scoped_fds)
-      fds.push_back(fd.get());
-  }
+  std::vector<void*> user_ptrs;
   for (size_t i = 0; i < input_layout_.num_buffers(); ++i) {
-    qbuf.m.planes[i].bytesused =
-        VideoFrame::PlaneSize(input_record.frame->format(), i,
-                              input_layout_.coded_size())
-            .GetArea();
-    qbuf.m.planes[i].length = qbuf.m.planes[i].bytesused;
-    switch (input_memory_type_) {
-      case V4L2_MEMORY_USERPTR:
-        qbuf.m.planes[i].m.userptr =
-            reinterpret_cast<unsigned long>(input_record.frame->data(i));
-        break;
-      case V4L2_MEMORY_DMABUF:
-        qbuf.m.planes[i].m.fd = fds[i];
-        break;
-      default:
-        NOTREACHED();
-        return false;
-    }
+    int bytes_used = VideoFrame::PlaneSize(job_record->input_frame->format(), i,
+                                           input_layout_.coded_size())
+                         .GetArea();
+    buffer.SetPlaneBytesUsed(i, bytes_used);
+    if (buffer.Memory() == V4L2_MEMORY_USERPTR)
+      user_ptrs.push_back(job_record->input_frame->data(i));
   }
-  DVLOGF(4) << "Calling VIDIOC_QBUF: " << V4L2Device::V4L2BufferToString(qbuf);
-  IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
-  input_record.at_device = true;
 
+  switch (input_memory_type_) {
+    case V4L2_MEMORY_USERPTR:
+      std::move(buffer).QueueUserPtr(user_ptrs);
+      break;
+    case V4L2_MEMORY_DMABUF:
+      std::move(buffer).QueueDMABuf(job_record->input_frame->DmabufFds());
+      break;
+    default:
+      NOTREACHED();
+      return false;
+  }
   DVLOGF(4) << "enqueued frame ts="
             << job_record->input_frame->timestamp().InMilliseconds()
             << " to device.";
 
   running_jobs_.emplace(std::move(job_record));
-  free_input_buffers_.pop_back();
-  input_buffer_queued_count_++;
 
   return true;
 }
@@ -956,34 +890,19 @@
     return;
   }
 
-  if (input_streamon_) {
-    __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-    IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMOFF, &type);
-  }
-  input_streamon_ = false;
+  if (!input_queue_->Streamoff())
+    return;
 
-  if (output_streamon_) {
-    __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-    IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMOFF, &type);
-  }
-  output_streamon_ = false;
+  if (!output_queue_->Streamoff())
+    return;
 
   // Reset all our accounting info.
-  while (!input_queue_.empty())
-    input_queue_.pop();
+  while (!input_job_queue_.empty())
+    input_job_queue_.pop();
 
   while (!running_jobs_.empty())
     running_jobs_.pop();
 
-  free_input_buffers_.clear();
-  for (size_t i = 0; i < input_buffer_map_.size(); ++i) {
-    InputRecord& input_record = input_buffer_map_[i];
-    input_record.at_device = false;
-    input_record.frame = NULL;
-    free_input_buffers_.push_back(i);
-  }
-  input_buffer_queued_count_ = 0;
-
   for (auto& output_buffer : output_buffer_map_)
     output_buffer.at_device = false;
   output_buffer_queued_count_ = 0;
diff --git a/media/gpu/v4l2/v4l2_image_processor.h b/media/gpu/v4l2/v4l2_image_processor.h
index 78e180f1c..99e266e 100644
--- a/media/gpu/v4l2/v4l2_image_processor.h
+++ b/media/gpu/v4l2/v4l2_image_processor.h
@@ -75,15 +75,6 @@
       ErrorCB error_cb);
 
  private:
-  // Record for input buffers.
-  struct InputRecord {
-    InputRecord();
-    InputRecord(const V4L2ImageProcessor::InputRecord&);
-    ~InputRecord();
-    scoped_refptr<VideoFrame> frame;
-    bool at_device;
-  };
-
   // Record for output buffers.
   struct OutputRecord {
     OutputRecord();
@@ -189,20 +180,12 @@
 
   // All the below members are to be accessed from device_thread_ only
   // (if it's running).
-  base::queue<std::unique_ptr<JobRecord>> input_queue_;
+  base::queue<std::unique_ptr<JobRecord>> input_job_queue_;
   base::queue<std::unique_ptr<JobRecord>> running_jobs_;
 
-  // Input queue state.
-  bool input_streamon_;
-  // Number of input buffers enqueued to the device.
-  int input_buffer_queued_count_;
-  // Input buffers ready to use; LIFO since we don't care about ordering.
-  std::vector<int> free_input_buffers_;
-  // Mapping of int index to an input buffer record.
-  std::vector<InputRecord> input_buffer_map_;
+  scoped_refptr<V4L2Queue> input_queue_;
+  scoped_refptr<V4L2Queue> output_queue_;
 
-  // Output queue state.
-  bool output_streamon_;
   // Number of output buffers enqueued to the device.
   int output_buffer_queued_count_;
   // Mapping of int index to an output buffer record.
diff --git a/mojo/public/tools/bindings/chromium_bindings_configuration.gni b/mojo/public/tools/bindings/chromium_bindings_configuration.gni
index 00a4b1e..86c0ea48 100644
--- a/mojo/public/tools/bindings/chromium_bindings_configuration.gni
+++ b/mojo/public/tools/bindings/chromium_bindings_configuration.gni
@@ -38,6 +38,7 @@
   "//services/proxy_resolver/public/cpp/typemaps.gni",
   "//services/resource_coordinator/public/cpp/typemaps.gni",
   "//services/service_manager/public/cpp/typemaps.gni",
+  "//services/tracing/public/mojom/typemaps.gni",
   "//services/ws/public/mojom/ime/typemaps.gni",
   "//services/viz/privileged/cpp/typemaps.gni",
   "//services/viz/privileged/interfaces/compositing/typemaps.gni",
diff --git a/net/quic/quic_chromium_packet_writer.cc b/net/quic/quic_chromium_packet_writer.cc
index cee7f62..fbdc48d 100644
--- a/net/quic/quic_chromium_packet_writer.cc
+++ b/net/quic/quic_chromium_packet_writer.cc
@@ -190,12 +190,6 @@
     OnWriteComplete(result.error_code);
 }
 
-bool QuicChromiumPacketWriter::IsWriteBlockedDataBuffered() const {
-  // Chrome sockets' Write() methods buffer the data until the Write is
-  // permitted.
-  return true;
-}
-
 bool QuicChromiumPacketWriter::IsWriteBlocked() const {
   return (force_write_blocked_ || write_in_progress_);
 }
diff --git a/net/quic/quic_chromium_packet_writer.h b/net/quic/quic_chromium_packet_writer.h
index 731f3cf..a1558ef 100644
--- a/net/quic/quic_chromium_packet_writer.h
+++ b/net/quic/quic_chromium_packet_writer.h
@@ -88,7 +88,6 @@
                                 const quic::QuicIpAddress& self_address,
                                 const quic::QuicSocketAddress& peer_address,
                                 quic::PerPacketOptions* options) override;
-  bool IsWriteBlockedDataBuffered() const override;
   bool IsWriteBlocked() const override;
   void SetWritable() override;
   quic::QuicByteCount GetMaxPacketSize(
diff --git a/net/spdy/spdy_session_fuzzer.cc b/net/spdy/spdy_session_fuzzer.cc
index 93a9429..8298d707 100644
--- a/net/spdy/spdy_session_fuzzer.cc
+++ b/net/spdy/spdy_session_fuzzer.cc
@@ -70,6 +70,12 @@
       const SSLConfig& ssl_config,
       const SSLClientSocketContext& context) override;
 
+  std::unique_ptr<SSLClientSocket> CreateSSLClientSocket(
+      std::unique_ptr<StreamSocket> nested_socket,
+      const HostPortPair& host_and_port,
+      const SSLConfig& ssl_config,
+      const SSLClientSocketContext& context) override;
+
  private:
   SocketDataProviderArray<SSLSocketDataProvider> mock_ssl_data_;
 };
@@ -94,6 +100,17 @@
                                                mock_ssl_data_.GetNext());
 }
 
+std::unique_ptr<SSLClientSocket>
+FuzzedSocketFactoryWithMockSSLData::CreateSSLClientSocket(
+    std::unique_ptr<StreamSocket> nested_socket,
+    const HostPortPair& host_and_port,
+    const SSLConfig& ssl_config,
+    const SSLClientSocketContext& context) {
+  return std::make_unique<MockSSLClientSocket>(std::move(nested_socket),
+                                               host_and_port, ssl_config,
+                                               mock_ssl_data_.GetNext());
+}
+
 }  // namespace
 
 }  // namespace net
diff --git a/net/third_party/quic/core/http/quic_spdy_session_test.cc b/net/third_party/quic/core/http/quic_spdy_session_test.cc
index 46795a5..99f635bc 100644
--- a/net/third_party/quic/core/http/quic_spdy_session_test.cc
+++ b/net/third_party/quic/core/http/quic_spdy_session_test.cc
@@ -776,8 +776,6 @@
   MockPacketWriter* writer = static_cast<MockPacketWriter*>(
       QuicConnectionPeer::GetWriter(session_.connection()));
   EXPECT_CALL(*writer, IsWriteBlocked()).WillRepeatedly(Return(true));
-  EXPECT_CALL(*writer, IsWriteBlockedDataBuffered())
-      .WillRepeatedly(Return(true));
   EXPECT_CALL(*writer, WritePacket(_, _, _, _, _)).Times(0);
 
   TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
diff --git a/net/third_party/quic/core/quic_connection_test.cc b/net/third_party/quic/core/quic_connection_test.cc
index 48dc3b2..2e214c2 100644
--- a/net/third_party/quic/core/quic_connection_test.cc
+++ b/net/third_party/quic/core/quic_connection_test.cc
@@ -363,10 +363,6 @@
     return WriteResult(WRITE_STATUS_OK, last_packet_size_);
   }
 
-  bool IsWriteBlockedDataBuffered() const override {
-    return is_write_blocked_data_buffered_;
-  }
-
   bool ShouldWriteFail() { return write_should_fail_; }
 
   bool IsWriteBlocked() const override { return write_blocked_; }
diff --git a/net/third_party/quic/core/quic_default_packet_writer.cc b/net/third_party/quic/core/quic_default_packet_writer.cc
index cfd37f7a..16de174 100644
--- a/net/third_party/quic/core/quic_default_packet_writer.cc
+++ b/net/third_party/quic/core/quic_default_packet_writer.cc
@@ -30,10 +30,6 @@
   return result;
 }
 
-bool QuicDefaultPacketWriter::IsWriteBlockedDataBuffered() const {
-  return false;
-}
-
 bool QuicDefaultPacketWriter::IsWriteBlocked() const {
   return write_blocked_;
 }
diff --git a/net/third_party/quic/core/quic_default_packet_writer.h b/net/third_party/quic/core/quic_default_packet_writer.h
index 55c02eb8..a28d9e4 100644
--- a/net/third_party/quic/core/quic_default_packet_writer.h
+++ b/net/third_party/quic/core/quic_default_packet_writer.h
@@ -30,7 +30,6 @@
                           const QuicIpAddress& self_address,
                           const QuicSocketAddress& peer_address,
                           PerPacketOptions* options) override;
-  bool IsWriteBlockedDataBuffered() const override;
   bool IsWriteBlocked() const override;
   void SetWritable() override;
   QuicByteCount GetMaxPacketSize(
diff --git a/net/third_party/quic/core/quic_packet_writer.h b/net/third_party/quic/core/quic_packet_writer.h
index 1957a68a..0382f7a4 100644
--- a/net/third_party/quic/core/quic_packet_writer.h
+++ b/net/third_party/quic/core/quic_packet_writer.h
@@ -84,11 +84,6 @@
                                   const QuicSocketAddress& peer_address,
                                   PerPacketOptions* options) = 0;
 
-  // Returns true if the writer buffers and subsequently rewrites data
-  // when an attempt to write results in the underlying socket becoming
-  // write blocked.
-  virtual bool IsWriteBlockedDataBuffered() const = 0;
-
   // Returns true if the network socket is not writable.
   virtual bool IsWriteBlocked() const = 0;
 
diff --git a/net/third_party/quic/core/quic_packet_writer_wrapper.cc b/net/third_party/quic/core/quic_packet_writer_wrapper.cc
index 6ff9eae9..187ef7ab 100644
--- a/net/third_party/quic/core/quic_packet_writer_wrapper.cc
+++ b/net/third_party/quic/core/quic_packet_writer_wrapper.cc
@@ -24,10 +24,6 @@
                               options);
 }
 
-bool QuicPacketWriterWrapper::IsWriteBlockedDataBuffered() const {
-  return writer_->IsWriteBlockedDataBuffered();
-}
-
 bool QuicPacketWriterWrapper::IsWriteBlocked() const {
   return writer_->IsWriteBlocked();
 }
diff --git a/net/third_party/quic/core/quic_packet_writer_wrapper.h b/net/third_party/quic/core/quic_packet_writer_wrapper.h
index e490097cb..623fdcc0 100644
--- a/net/third_party/quic/core/quic_packet_writer_wrapper.h
+++ b/net/third_party/quic/core/quic_packet_writer_wrapper.h
@@ -30,7 +30,6 @@
                           const QuicIpAddress& self_address,
                           const QuicSocketAddress& peer_address,
                           PerPacketOptions* options) override;
-  bool IsWriteBlockedDataBuffered() const override;
   bool IsWriteBlocked() const override;
   void SetWritable() override;
   QuicByteCount GetMaxPacketSize(
diff --git a/net/third_party/quic/core/quic_session_test.cc b/net/third_party/quic/core/quic_session_test.cc
index 198993c2..5ea178a 100644
--- a/net/third_party/quic/core/quic_session_test.cc
+++ b/net/third_party/quic/core/quic_session_test.cc
@@ -913,8 +913,6 @@
   MockPacketWriter* writer = static_cast<MockPacketWriter*>(
       QuicConnectionPeer::GetWriter(session_.connection()));
   EXPECT_CALL(*writer, IsWriteBlocked()).WillRepeatedly(Return(true));
-  EXPECT_CALL(*writer, IsWriteBlockedDataBuffered())
-      .WillRepeatedly(Return(true));
   EXPECT_CALL(*writer, WritePacket(_, _, _, _, _)).Times(0);
 
   TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
diff --git a/net/third_party/quic/core/quic_time_wait_list_manager_test.cc b/net/third_party/quic/core/quic_time_wait_list_manager_test.cc
index 762548ff..5781797 100644
--- a/net/third_party/quic/core/quic_time_wait_list_manager_test.cc
+++ b/net/third_party/quic/core/quic_time_wait_list_manager_test.cc
@@ -144,8 +144,6 @@
   void SetUp() override {
     EXPECT_CALL(writer_, IsWriteBlocked())
         .WillRepeatedly(ReturnPointee(&writer_is_blocked_));
-    EXPECT_CALL(writer_, IsWriteBlockedDataBuffered())
-        .WillRepeatedly(Return(false));
   }
 
   void AddConnectionId(QuicConnectionId connection_id,
diff --git a/net/third_party/quic/platform/impl/batch_writer/quic_batch_writer_base.h b/net/third_party/quic/platform/impl/batch_writer/quic_batch_writer_base.h
index 1eb9f3d5..36d91bb 100644
--- a/net/third_party/quic/platform/impl/batch_writer/quic_batch_writer_base.h
+++ b/net/third_party/quic/platform/impl/batch_writer/quic_batch_writer_base.h
@@ -30,8 +30,6 @@
                           const QuicSocketAddress& peer_address,
                           PerPacketOptions* options) override;
 
-  bool IsWriteBlockedDataBuffered() const final { return false; }
-
   bool IsWriteBlocked() const final { return write_blocked_; }
 
   void SetWritable() final { write_blocked_ = false; }
diff --git a/net/third_party/quic/quartc/quartc_packet_writer.cc b/net/third_party/quic/quartc/quartc_packet_writer.cc
index 5063815..755a8ed 100644
--- a/net/third_party/quic/quartc/quartc_packet_writer.cc
+++ b/net/third_party/quic/quartc/quartc_packet_writer.cc
@@ -31,10 +31,6 @@
   return WriteResult(WRITE_STATUS_OK, bytes_written);
 }
 
-bool QuartcPacketWriter::IsWriteBlockedDataBuffered() const {
-  return false;
-}
-
 bool QuartcPacketWriter::IsWriteBlocked() const {
   return !writable_;
 }
diff --git a/net/third_party/quic/quartc/quartc_packet_writer.h b/net/third_party/quic/quartc/quartc_packet_writer.h
index 9d43ac5..45173c98 100644
--- a/net/third_party/quic/quartc/quartc_packet_writer.h
+++ b/net/third_party/quic/quartc/quartc_packet_writer.h
@@ -67,9 +67,6 @@
                           const QuicSocketAddress& peer_address,
                           PerPacketOptions* options) override;
 
-  // This is always set to false so that QuicConnection buffers unsent packets.
-  bool IsWriteBlockedDataBuffered() const override;
-
   // Whether the underneath |transport_| is blocked. If this returns true,
   // outgoing QUIC packets are queued by QuicConnection until SetWritable() is
   // called.
diff --git a/net/third_party/quic/quartc/quartc_stream_test.cc b/net/third_party/quic/quartc/quartc_stream_test.cc
index f75fdb0..525be329 100644
--- a/net/third_party/quic/quartc/quartc_stream_test.cc
+++ b/net/third_party/quic/quartc/quartc_stream_test.cc
@@ -137,8 +137,6 @@
     return WriteResult(WRITE_STATUS_ERROR, 0);
   }
 
-  bool IsWriteBlockedDataBuffered() const override { return false; }
-
   bool IsWriteBlocked() const override { return false; };
 
   void SetWritable() override {}
diff --git a/net/third_party/quic/test_tools/quic_test_utils.h b/net/third_party/quic/test_tools/quic_test_utils.h
index 81e4efb..25c8d5c 100644
--- a/net/third_party/quic/test_tools/quic_test_utils.h
+++ b/net/third_party/quic/test_tools/quic_test_utils.h
@@ -869,7 +869,6 @@
                            const QuicIpAddress& self_address,
                            const QuicSocketAddress& peer_address,
                            PerPacketOptions* options));
-  MOCK_CONST_METHOD0(IsWriteBlockedDataBuffered, bool());
   MOCK_CONST_METHOD0(IsWriteBlocked, bool());
   MOCK_METHOD0(SetWritable, void());
   MOCK_CONST_METHOD1(GetMaxPacketSize,
diff --git a/net/third_party/quic/test_tools/simulator/quic_endpoint.cc b/net/third_party/quic/test_tools/simulator/quic_endpoint.cc
index 13e17da..dce9559e 100644
--- a/net/third_party/quic/test_tools/simulator/quic_endpoint.cc
+++ b/net/third_party/quic/test_tools/simulator/quic_endpoint.cc
@@ -311,10 +311,6 @@
   return WriteResult(WRITE_STATUS_OK, buf_len);
 }
 
-bool QuicEndpoint::Writer::IsWriteBlockedDataBuffered() const {
-  return false;
-}
-
 bool QuicEndpoint::Writer::IsWriteBlocked() const {
   return is_blocked_;
 }
diff --git a/net/third_party/quic/test_tools/simulator/quic_endpoint.h b/net/third_party/quic/test_tools/simulator/quic_endpoint.h
index fc87e459..173ad13 100644
--- a/net/third_party/quic/test_tools/simulator/quic_endpoint.h
+++ b/net/third_party/quic/test_tools/simulator/quic_endpoint.h
@@ -141,7 +141,6 @@
                             const QuicIpAddress& self_address,
                             const QuicSocketAddress& peer_address,
                             PerPacketOptions* options) override;
-    bool IsWriteBlockedDataBuffered() const override;
     bool IsWriteBlocked() const override;
     void SetWritable() override;
     QuicByteCount GetMaxPacketSize(
diff --git a/net/tools/quic/quic_simple_per_connection_packet_writer.cc b/net/tools/quic/quic_simple_per_connection_packet_writer.cc
index d57af46a..7098aa5 100644
--- a/net/tools/quic/quic_simple_per_connection_packet_writer.cc
+++ b/net/tools/quic/quic_simple_per_connection_packet_writer.cc
@@ -35,10 +35,6 @@
                  weak_factory_.GetWeakPtr()));
 }
 
-bool QuicSimplePerConnectionPacketWriter::IsWriteBlockedDataBuffered() const {
-  return shared_writer_->IsWriteBlockedDataBuffered();
-}
-
 bool QuicSimplePerConnectionPacketWriter::IsWriteBlocked() const {
   return shared_writer_->IsWriteBlocked();
 }
diff --git a/net/tools/quic/quic_simple_per_connection_packet_writer.h b/net/tools/quic/quic_simple_per_connection_packet_writer.h
index 08d615b..bdcdcf7 100644
--- a/net/tools/quic/quic_simple_per_connection_packet_writer.h
+++ b/net/tools/quic/quic_simple_per_connection_packet_writer.h
@@ -40,7 +40,6 @@
                                 const quic::QuicIpAddress& self_address,
                                 const quic::QuicSocketAddress& peer_address,
                                 quic::PerPacketOptions* options) override;
-  bool IsWriteBlockedDataBuffered() const override;
   bool IsWriteBlocked() const override;
   void SetWritable() override;
   quic::QuicByteCount GetMaxPacketSize(
diff --git a/net/tools/quic/quic_simple_server_packet_writer.cc b/net/tools/quic/quic_simple_server_packet_writer.cc
index c369659..c66b0f5 100644
--- a/net/tools/quic/quic_simple_server_packet_writer.cc
+++ b/net/tools/quic/quic_simple_server_packet_writer.cc
@@ -54,11 +54,6 @@
   dispatcher_->OnCanWrite();
 }
 
-bool QuicSimpleServerPacketWriter::IsWriteBlockedDataBuffered() const {
-  // UDPServerSocket::SendTo buffers the data until the Write is permitted.
-  return true;
-}
-
 bool QuicSimpleServerPacketWriter::IsWriteBlocked() const {
   return write_blocked_;
 }
diff --git a/net/tools/quic/quic_simple_server_packet_writer.h b/net/tools/quic/quic_simple_server_packet_writer.h
index 1ff9988..24cecef 100644
--- a/net/tools/quic/quic_simple_server_packet_writer.h
+++ b/net/tools/quic/quic_simple_server_packet_writer.h
@@ -53,7 +53,6 @@
   void OnWriteComplete(int rv);
 
   // quic::QuicPacketWriter implementation:
-  bool IsWriteBlockedDataBuffered() const override;
   bool IsWriteBlocked() const override;
   void SetWritable() override;
   quic::QuicByteCount GetMaxPacketSize(
diff --git a/services/identity/public/cpp/identity_manager.cc b/services/identity/public/cpp/identity_manager.cc
index 22d59ba..8550420 100644
--- a/services/identity/public/cpp/identity_manager.cc
+++ b/services/identity/public/cpp/identity_manager.cc
@@ -443,6 +443,12 @@
   }
 }
 
+void IdentityManager::OnGaiaCookieDeletedByUserAction() {
+  for (auto& observer : observer_list_) {
+    observer.OnAccountsCookieDeletedByUserAction();
+  }
+}
+
 void IdentityManager::OnAccessTokenRequested(
     const std::string& account_id,
     const std::string& consumer_id,
diff --git a/services/identity/public/cpp/identity_manager.h b/services/identity/public/cpp/identity_manager.h
index 999cd20..2577b48 100644
--- a/services/identity/public/cpp/identity_manager.h
+++ b/services/identity/public/cpp/identity_manager.h
@@ -148,6 +148,10 @@
     virtual void OnSetAccountsInCookieCompleted(
         const GoogleServiceAuthError& error) {}
 
+    // Called when the Gaia cookie has been deleted explicitly by a user
+    // action, e.g. from the settings or by an extension.
+    virtual void OnAccountsCookieDeletedByUserAction() {}
+
     // Called before a batch of refresh token state changes is started.
     virtual void OnStartBatchOfRefreshTokenStateChanges() {}
 
@@ -482,6 +486,7 @@
       const GoogleServiceAuthError& error) override;
   void OnSetAccountsInCookieCompleted(
       const GoogleServiceAuthError& error) override;
+  void OnGaiaCookieDeletedByUserAction() override;
 
   // OAuth2TokenService::DiagnosticsObserver:
   void OnAccessTokenRequested(
diff --git a/services/identity/public/cpp/identity_manager_unittest.cc b/services/identity/public/cpp/identity_manager_unittest.cc
index 7289cb8..27b43fb 100644
--- a/services/identity/public/cpp/identity_manager_unittest.cc
+++ b/services/identity/public/cpp/identity_manager_unittest.cc
@@ -93,6 +93,43 @@
   base::OnceClosure on_access_token_invalidated_callback_;
 };
 
+class FakeCookieManager : public network::mojom::CookieManager {
+ public:
+  void SetCanonicalCookie(const net::CanonicalCookie& cookie,
+                          bool secure_source,
+                          bool modify_http_only,
+                          SetCanonicalCookieCallback callback) override {
+    std::move(callback).Run(false);
+  }
+  void GetAllCookies(GetAllCookiesCallback callback) override {}
+  void GetCookieList(const GURL& url,
+                     const net::CookieOptions& cookie_options,
+                     GetCookieListCallback callback) override {}
+  void DeleteCanonicalCookie(const net::CanonicalCookie& cookie,
+                             DeleteCanonicalCookieCallback callback) override {}
+  void DeleteCookies(network::mojom::CookieDeletionFilterPtr filter,
+                     DeleteCookiesCallback callback) override {}
+  void AddCookieChangeListener(
+      const GURL& url,
+      const std::string& name,
+      network::mojom::CookieChangeListenerPtr listener) override {
+    listener_ = std::move(listener);
+  }
+  void AddGlobalChangeListener(
+      network::mojom::CookieChangeListenerPtr notification_pointer) override {}
+  void CloneInterface(
+      network::mojom::CookieManagerRequest new_interface) override {}
+  void FlushCookieStore(FlushCookieStoreCallback callback) override {}
+  void SetContentSettings(
+      const std::vector<::ContentSettingPatternSource>& settings) override {}
+  void SetForceKeepSessionState() override {}
+  void BlockThirdPartyCookies(bool block) override {}
+
+ private:
+  // The observer receiving change notifications.
+  network::mojom::CookieChangeListenerPtr listener_;
+};
+
 class AccountTrackerServiceForTest : public AccountTrackerService {
  public:
   void SetAccountInfoFromUserInfo(const std::string& account_id,
@@ -219,6 +256,9 @@
       base::OnceClosure callback) {
     on_primary_account_signin_failed_callback_ = std::move(callback);
   }
+  void set_on_cookie_deleted_by_user_callback(base::OnceClosure callback) {
+    on_cookie_deleted_by_user_callback_ = std::move(callback);
+  }
 
   const AccountInfo& primary_account_from_set_callback() {
     return primary_account_from_set_callback_;
@@ -368,6 +408,9 @@
       const GoogleServiceAuthError& error) override {
     error_from_set_accounts_in_cookie_completed_callback_ = error;
   }
+  void OnAccountsCookieDeletedByUserAction() override {
+    std::move(on_cookie_deleted_by_user_callback_).Run();
+  }
 
   void OnStartBatchOfRefreshTokenStateChanges() override {
     EXPECT_FALSE(is_inside_batch_);
@@ -395,6 +438,7 @@
   base::OnceClosure on_primary_account_cleared_callback_;
   base::OnceClosure on_primary_account_signin_failed_callback_;
   base::OnceClosure on_refresh_token_updated_callback_;
+  base::OnceClosure on_cookie_deleted_by_user_callback_;
   base::RepeatingCallback<void(const std::string&)>
       on_refresh_token_removed_callback_;
   base::OnceClosure on_error_state_of_refresh_token_updated_callback_;
@@ -500,8 +544,11 @@
     SigninManagerBase::RegisterProfilePrefs(pref_service_.registry());
     SigninManagerBase::RegisterPrefs(pref_service_.registry());
 
+    signin_client_.set_cookie_manager(std::make_unique<FakeCookieManager>());
     account_tracker_.Initialize(&pref_service_, base::FilePath());
 
+    gaia_cookie_manager_service_.InitCookieListener();
+
     RecreateSigninAndIdentityManager(
         signin::AccountConsistencyMethod::kDisabled,
         SigninManagerSetup::kWithAuthenticatedAccout);
@@ -608,6 +655,13 @@
     consumer->OnMergeSessionFailure(error);
   }
 
+  void SimulateCookieDeletedByUser(
+      network::mojom::CookieChangeListener* listener,
+      const net::CanonicalCookie& cookie) {
+    listener->OnCookieChange(cookie,
+                             network::mojom::CookieChangeCause::EXPLICIT);
+  }
+
   void SimulateOAuthMultiloginFinished(GaiaAuthConsumer* consumer,
                                        const OAuthMultiloginResult& result) {
     consumer->OnOAuthMultiloginFinished(result);
@@ -2181,6 +2235,49 @@
             error);
 }
 
+TEST_F(IdentityManagerTest, CallbackSentOnAccountsCookieDeletedByUserAction) {
+  const char kTestAccountId[] = "account_id";
+  const char kTestAccountId2[] = "account_id2";
+  const std::vector<std::string> account_ids = {kTestAccountId,
+                                                kTestAccountId2};
+
+  // Needed to insert request in the queue.
+  gaia_cookie_manager_service()->SetAccountsInCookie(account_ids,
+                                                     gaia::GaiaSource::kChrome);
+
+  // Sample success cookie response.
+  std::string data =
+      R"()]}'
+      {
+        "status": "OK",
+        "cookies":[
+        {
+            "name":"APISID",
+            "value":"vAlUe1",
+            "domain":".google.com",
+            "path":"/",
+            "isSecure":true,
+            "isHttpOnly":false,
+            "priority":"HIGH",
+            "maxAge":63070000
+          }
+        ]
+      }
+    )";
+  OAuthMultiloginResult result(data);
+
+  SimulateOAuthMultiloginFinished(gaia_cookie_manager_service(), result);
+  base::RunLoop().RunUntilIdle();
+
+  base::RunLoop run_loop;
+  identity_manager_observer()->set_on_cookie_deleted_by_user_callback(
+      run_loop.QuitClosure());
+
+  const std::vector<net::CanonicalCookie>& cookies = result.cookies();
+  SimulateCookieDeletedByUser(gaia_cookie_manager_service(), cookies[0]);
+  run_loop.Run();
+}
+
 TEST_F(IdentityManagerTest,
        BatchChangeObserversAreNotifiedOnCredentialsUpdate) {
   signin_manager()->SetAuthenticatedAccountInfo(kTestGaiaId, kTestEmail);
diff --git a/services/identity/public/cpp/identity_test_environment.cc b/services/identity/public/cpp/identity_test_environment.cc
index a2b025ee..c3d0b4fda 100644
--- a/services/identity/public/cpp/identity_test_environment.cc
+++ b/services/identity/public/cpp/identity_test_environment.cc
@@ -511,4 +511,9 @@
       accounts_are_fresh);
 }
 
+void IdentityTestEnvironment::
+    EnableOnAccountUpdatedAndOnAccountRemovedWithInfoCallbacks() {
+  account_fetcher_service_->EnableNetworkFetchesForTest();
+}
+
 }  // namespace identity
diff --git a/services/identity/public/cpp/identity_test_environment.h b/services/identity/public/cpp/identity_test_environment.h
index 9df6f55..98e23ae3 100644
--- a/services/identity/public/cpp/identity_test_environment.h
+++ b/services/identity/public/cpp/identity_test_environment.h
@@ -257,6 +257,9 @@
   // need to be updated.
   void SetFreshnessOfAccountsInGaiaCookie(bool accounts_are_fresh);
 
+  // Enable interaction with AccountFetcherService in testing context.
+  void EnableOnAccountUpdatedAndOnAccountRemovedWithInfoCallbacks();
+
  private:
   friend class ::IdentityTestEnvironmentChromeBrowserStateAdaptor;
   friend class ::IdentityTestEnvironmentProfileAdaptor;
diff --git a/services/media_session/public/cpp/BUILD.gn b/services/media_session/public/cpp/BUILD.gn
index 71d68723..e598fe1 100644
--- a/services/media_session/public/cpp/BUILD.gn
+++ b/services/media_session/public/cpp/BUILD.gn
@@ -8,6 +8,8 @@
   sources = [
     "features.cc",
     "features.h",
+    "media_image.cc",
+    "media_image.h",
     "media_image_manager.cc",
     "media_image_manager.h",
     "media_metadata.cc",
@@ -23,7 +25,10 @@
   configs += [ "//build/config/compiler:wexit_time_destructors" ]
 
   if (is_android) {
-    sources += [ "media_metadata_android.cc" ]
+    sources += [
+      "media_image_android.cc",
+      "media_metadata_android.cc",
+    ]
     deps += [ "android:media_session_jni_headers" ]
   }
 
diff --git a/services/media_session/public/cpp/android/BUILD.gn b/services/media_session/public/cpp/android/BUILD.gn
index c7de4d2a..46857b0 100644
--- a/services/media_session/public/cpp/android/BUILD.gn
+++ b/services/media_session/public/cpp/android/BUILD.gn
@@ -4,8 +4,10 @@
 
 import("//build/config/android/rules.gni")
 
-_jni_sources =
-    [ "java/src/org/chromium/services/media_session/MediaMetadata.java" ]
+_jni_sources = [
+  "java/src/org/chromium/services/media_session/MediaImage.java",
+  "java/src/org/chromium/services/media_session/MediaMetadata.java",
+]
 
 generate_jni("media_session_jni_headers") {
   sources = _jni_sources
diff --git a/services/media_session/public/cpp/android/java/src/org/chromium/services/media_session/MediaImage.java b/services/media_session/public/cpp/android/java/src/org/chromium/services/media_session/MediaImage.java
new file mode 100644
index 0000000..60d6d0d
--- /dev/null
+++ b/services/media_session/public/cpp/android/java/src/org/chromium/services/media_session/MediaImage.java
@@ -0,0 +1,121 @@
+// 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.
+
+package org.chromium.services.media_session;
+
+import android.graphics.Rect;
+import android.support.annotation.NonNull;
+import android.text.TextUtils;
+
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The MediaImage class carries the artwork information in MediaMetadata. It is the Java
+ * counterpart of media_session::MediaImage.
+ */
+@JNINamespace("media_session")
+public final class MediaImage {
+    @NonNull
+    private String mSrc;
+
+    private String mType;
+
+    @NonNull
+    private List<Rect> mSizes = new ArrayList<Rect>();
+
+    /**
+     * Creates a new MediaImage.
+     */
+    public MediaImage(@NonNull String src, @NonNull String type, @NonNull List<Rect> sizes) {
+        mSrc = src;
+        mType = type;
+        mSizes = sizes;
+    }
+
+    /**
+     * @return The URL of this MediaImage.
+     */
+    @NonNull
+    public String getSrc() {
+        return mSrc;
+    }
+
+    /**
+     * @return The MIME type of this MediaImage.
+     */
+    public String getType() {
+        return mType;
+    }
+
+    /**
+     * @return The hinted sizes of this MediaImage.
+     */
+    public List<Rect> getSizes() {
+        return mSizes;
+    }
+
+    /**
+     * Sets the URL of this MediaImage.
+     */
+    public void setSrc(@NonNull String src) {
+        mSrc = src;
+    }
+
+    /**
+     * Sets the MIME type of this MediaImage.
+     */
+    public void setType(@NonNull String type) {
+        mType = type;
+    }
+
+    /**
+     * Sets the sizes of this MediaImage.
+     */
+    public void setSizes(@NonNull List<Rect> sizes) {
+        mSizes = sizes;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) return true;
+        if (!(obj instanceof MediaImage)) return false;
+
+        MediaImage other = (MediaImage) obj;
+        return TextUtils.equals(mSrc, other.mSrc) && TextUtils.equals(mType, other.mType)
+                && mSizes.equals(other.mSizes);
+    }
+
+    /**
+     * @return The hash code of this {@link MediaImage}. The method uses the same algorithm in
+     * {@link java.util.List} for combinine hash values.
+     */
+    @Override
+    public int hashCode() {
+        int result = mSrc.hashCode();
+        result = 31 * result + mType.hashCode();
+        result = 31 * result + mSizes.hashCode();
+        return result;
+    }
+
+    /**
+     * Create a new {@link MediaImage} from the C++ code.
+     * @param src The URL of the image.
+     * @param type The MIME type of the image.
+     * @param flattenedSizes The flattened array of image sizes. In native code, it is of type
+     *         `std::vector<gfx::Size>` before flattening.
+     */
+    @CalledByNative
+    private static MediaImage create(String src, String type, int[] flattenedSizes) {
+        assert (flattenedSizes.length % 2) == 0;
+        List<Rect> sizes = new ArrayList<Rect>();
+        for (int i = 0; (i + 1) < flattenedSizes.length; i += 2) {
+            sizes.add(new Rect(0, 0, flattenedSizes[i], flattenedSizes[i + 1]));
+        }
+        return new MediaImage(src, type, sizes);
+    }
+}
diff --git a/services/media_session/public/cpp/android/java/src/org/chromium/services/media_session/MediaMetadata.java b/services/media_session/public/cpp/android/java/src/org/chromium/services/media_session/MediaMetadata.java
index ce06aae..f8754d3 100644
--- a/services/media_session/public/cpp/android/java/src/org/chromium/services/media_session/MediaMetadata.java
+++ b/services/media_session/public/cpp/android/java/src/org/chromium/services/media_session/MediaMetadata.java
@@ -4,7 +4,6 @@
 
 package org.chromium.services.media_session;
 
-import android.graphics.Rect;
 import android.support.annotation.NonNull;
 import android.text.TextUtils;
 
@@ -20,94 +19,6 @@
  */
 @JNINamespace("media_session")
 public final class MediaMetadata {
-    /**
-     * The MediaImage class carries the artwork information in MediaMetadata. It is the Java
-     * counterpart of media_session::MediaMetadata::MediaImage.
-     */
-    public static final class MediaImage {
-        @NonNull
-        private String mSrc;
-
-        private String mType;
-
-        @NonNull
-        private List<Rect> mSizes = new ArrayList<Rect>();
-
-        /**
-         * Creates a new MediaImage.
-         */
-        public MediaImage(@NonNull String src, @NonNull String type, @NonNull List<Rect> sizes) {
-            mSrc = src;
-            mType = type;
-            mSizes = sizes;
-        }
-
-        /**
-         * @return The URL of this MediaImage.
-         */
-        @NonNull
-        public String getSrc() {
-            return mSrc;
-        }
-
-        /**
-         * @return The MIME type of this MediaImage.
-         */
-        public String getType() {
-            return mType;
-        }
-
-        /**
-         * @return The hinted sizes of this MediaImage.
-         */
-        public List<Rect> getSizes() {
-            return mSizes;
-        }
-
-        /**
-         * Sets the URL of this MediaImage.
-         */
-        public void setSrc(@NonNull String src) {
-            mSrc = src;
-        }
-
-        /**
-         * Sets the MIME type of this MediaImage.
-         */
-        public void setType(@NonNull String type) {
-            mType = type;
-        }
-
-        /**
-         * Sets the sizes of this MediaImage.
-         */
-        public void setSizes(@NonNull List<Rect> sizes) {
-            mSizes = sizes;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj == this) return true;
-            if (!(obj instanceof MediaImage)) return false;
-
-            MediaImage other = (MediaImage) obj;
-            return TextUtils.equals(mSrc, other.mSrc) && TextUtils.equals(mType, other.mType)
-                    && mSizes.equals(other.mSizes);
-        }
-
-        /**
-         * @return The hash code of this {@link MediaImage}. The method uses the same algorithm in
-         * {@link java.util.List} for combinine hash values.
-         */
-        @Override
-        public int hashCode() {
-            int result = mSrc.hashCode();
-            result = 31 * result + mType.hashCode();
-            result = 31 * result + mSizes.hashCode();
-            return result;
-        }
-    }
-
     @NonNull
     private String mTitle;
 
@@ -170,20 +81,11 @@
     }
 
     /**
-     * Create a new {@link MediaImage} from the C++ code, and add it to the Metadata.
-     * @param src The URL of the image.
-     * @param type The MIME type of the image.
-     * @param flattenedSizes The flattened array of image sizes. In native code, it is of type
-     *         `std::vector<gfx::Size>` before flattening.
+     * Adds an image to the MediaMetadata. This is called from the C++ code.
      */
     @CalledByNative
-    private void createAndAddMediaImage(String src, String type, int[] flattenedSizes) {
-        assert(flattenedSizes.length % 2) == 0;
-        List<Rect> sizes = new ArrayList<Rect>();
-        for (int i = 0; (i + 1) < flattenedSizes.length; i += 2) {
-            sizes.add(new Rect(0, 0, flattenedSizes[i], flattenedSizes[i + 1]));
-        }
-        mArtwork.add(new MediaImage(src, type, sizes));
+    private void addImage(MediaImage image) {
+        mArtwork.add(image);
     }
 
     /**
diff --git a/services/media_session/public/cpp/media_image.cc b/services/media_session/public/cpp/media_image.cc
new file mode 100644
index 0000000..b44d9df
--- /dev/null
+++ b/services/media_session/public/cpp/media_image.cc
@@ -0,0 +1,19 @@
+// 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 "services/media_session/public/cpp/media_image.h"
+
+namespace media_session {
+
+MediaImage::MediaImage() = default;
+
+MediaImage::MediaImage(const MediaImage& other) = default;
+
+MediaImage::~MediaImage() = default;
+
+bool MediaImage::operator==(const MediaImage& other) const {
+  return src == other.src && type == other.type && sizes == other.sizes;
+}
+
+}  // namespace media_session
diff --git a/services/media_session/public/cpp/media_image.h b/services/media_session/public/cpp/media_image.h
new file mode 100644
index 0000000..8ed0462
--- /dev/null
+++ b/services/media_session/public/cpp/media_image.h
@@ -0,0 +1,58 @@
+// 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 SERVICES_MEDIA_SESSION_PUBLIC_CPP_MEDIA_IMAGE_H_
+#define SERVICES_MEDIA_SESSION_PUBLIC_CPP_MEDIA_IMAGE_H_
+
+#include <vector>
+
+#include "base/component_export.h"
+#include "base/strings/string16.h"
+#include "build/build_config.h"
+#include "ui/gfx/geometry/size.h"
+#include "url/gurl.h"
+
+#if defined(OS_ANDROID)
+
+#include <jni.h>
+
+#include "base/android/scoped_java_ref.h"
+
+#endif  // defined(OS_ANDROID)
+
+namespace media_session {
+
+// Structure representing an MediaImage as per the MediaSession API, see:
+// https://wicg.github.io/mediasession/#dictdef-mediaimage
+struct COMPONENT_EXPORT(MEDIA_SESSION_CPP) MediaImage {
+  MediaImage();
+  MediaImage(const MediaImage& other);
+  ~MediaImage();
+
+  bool operator==(const MediaImage& other) const;
+
+#if defined(OS_ANDROID)
+  // Creates a Java MediaMetadata instance and returns the JNI ref.
+  base::android::ScopedJavaLocalRef<jobject> CreateJavaObject(
+      JNIEnv* env) const;
+#endif
+
+  // MUST be a valid url. If an icon doesn't have a valid URL, it will not be
+  // successfully parsed, thus will not be represented in the Manifest.
+  GURL src;
+
+  // Empty if the parsing failed or the field was not present. The type can be
+  // any string and doesn't have to be a valid image MIME type at this point.
+  // It is up to the consumer of the object to check if the type matches a
+  // supported type.
+  base::string16 type;
+
+  // Empty if the parsing failed, the field was not present or empty.
+  // The special value "any" is represented by gfx::Size(0, 0).
+  std::vector<gfx::Size> sizes;
+};
+
+}  // namespace media_session
+
+#endif  // SERVICES_MEDIA_SESSION_PUBLIC_CPP_MEDIA_IMAGE_H_
diff --git a/services/media_session/public/cpp/media_image_android.cc b/services/media_session/public/cpp/media_image_android.cc
new file mode 100644
index 0000000..15a0633c
--- /dev/null
+++ b/services/media_session/public/cpp/media_image_android.cc
@@ -0,0 +1,45 @@
+// 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 "services/media_session/public/cpp/media_image.h"
+
+#include <string>
+#include <vector>
+
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "jni/MediaImage_jni.h"
+
+using base::android::ScopedJavaLocalRef;
+
+namespace media_session {
+
+namespace {
+
+std::vector<int> GetFlattenedSizeArray(const std::vector<gfx::Size>& sizes) {
+  std::vector<int> flattened_array;
+  flattened_array.reserve(2 * sizes.size());
+  for (const auto& size : sizes) {
+    flattened_array.push_back(size.width());
+    flattened_array.push_back(size.height());
+  }
+  return flattened_array;
+}
+
+}  // anonymous namespace
+
+base::android::ScopedJavaLocalRef<jobject> MediaImage::CreateJavaObject(
+    JNIEnv* env) const {
+  std::string src_spec = src.spec();
+  ScopedJavaLocalRef<jstring> j_src(
+      base::android::ConvertUTF8ToJavaString(env, src_spec));
+  ScopedJavaLocalRef<jstring> j_type(
+      base::android::ConvertUTF16ToJavaString(env, type));
+  ScopedJavaLocalRef<jintArray> j_sizes(
+      base::android::ToJavaIntArray(env, GetFlattenedSizeArray(sizes)));
+
+  return Java_MediaImage_create(env, j_src, j_type, j_sizes);
+}
+
+}  // namespace media_session
diff --git a/services/media_session/public/cpp/media_image_manager.cc b/services/media_session/public/cpp/media_image_manager.cc
index a87eb840..b0f312b 100644
--- a/services/media_session/public/cpp/media_image_manager.cc
+++ b/services/media_session/public/cpp/media_image_manager.cc
@@ -44,9 +44,9 @@
 
 MediaImageManager::~MediaImageManager() = default;
 
-base::Optional<MediaMetadata::MediaImage> MediaImageManager::SelectImage(
-    const std::vector<MediaMetadata::MediaImage>& images) {
-  base::Optional<MediaMetadata::MediaImage> selected;
+base::Optional<MediaImage> MediaImageManager::SelectImage(
+    const std::vector<MediaImage>& images) {
+  base::Optional<MediaImage> selected;
 
   double best_score = 0;
   for (auto& image : images) {
@@ -60,8 +60,7 @@
   return selected;
 }
 
-double MediaImageManager::GetImageScore(
-    const MediaMetadata::MediaImage& image) const {
+double MediaImageManager::GetImageScore(const MediaImage& image) const {
   double best_size_score = 0;
 
   if (image.sizes.empty()) {
diff --git a/services/media_session/public/cpp/media_image_manager.h b/services/media_session/public/cpp/media_image_manager.h
index 5043a08..be2285e5 100644
--- a/services/media_session/public/cpp/media_image_manager.h
+++ b/services/media_session/public/cpp/media_image_manager.h
@@ -11,7 +11,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/optional.h"
-#include "services/media_session/public/cpp/media_metadata.h"
+#include "services/media_session/public/cpp/media_image.h"
 
 namespace gfx {
 class Size;
@@ -53,15 +53,14 @@
 
   // Select the best image from the |images|. If an image could not be selected
   // then will return null.
-  base::Optional<MediaMetadata::MediaImage> SelectImage(
-      const std::vector<MediaMetadata::MediaImage>& images);
+  base::Optional<MediaImage> SelectImage(const std::vector<MediaImage>& images);
 
  private:
   FRIEND_TEST_ALL_PREFIXES(MediaImageManagerTest,
                            CheckExpectedImageExtensionHashes);
   FRIEND_TEST_ALL_PREFIXES(MediaImageManagerTest, CheckExpectedImageTypeHashes);
 
-  double GetImageScore(const MediaMetadata::MediaImage& image) const;
+  double GetImageScore(const MediaImage& image) const;
 
   double GetImageSizeScore(const gfx::Size& size) const;
 
diff --git a/services/media_session/public/cpp/media_image_manager_unittest.cc b/services/media_session/public/cpp/media_image_manager_unittest.cc
index b461c898..b0f9014 100644
--- a/services/media_session/public/cpp/media_image_manager_unittest.cc
+++ b/services/media_session/public/cpp/media_image_manager_unittest.cc
@@ -66,14 +66,14 @@
 }
 
 TEST_F(MediaImageManagerTest, PickImageFromMimeType) {
-  std::vector<MediaMetadata::MediaImage> images;
+  std::vector<MediaImage> images;
 
-  media_session::MediaMetadata::MediaImage image1;
+  MediaImage image1;
   image1.type = base::ASCIIToUTF16("image/bmp");
   image1.sizes.push_back(gfx::Size(kIdealSize, kIdealSize));
   images.push_back(image1);
 
-  media_session::MediaMetadata::MediaImage image2;
+  MediaImage image2;
   image2.type = base::ASCIIToUTF16("image/png");
   image2.sizes.push_back(gfx::Size(kIdealSize, kIdealSize));
   images.push_back(image2);
@@ -82,19 +82,19 @@
 }
 
 TEST_F(MediaImageManagerTest, PickImageFromExtension) {
-  std::vector<MediaMetadata::MediaImage> images;
+  std::vector<MediaImage> images;
 
-  media_session::MediaMetadata::MediaImage image1;
+  MediaImage image1;
   image1.src = GURL("https://www.example.com/test.bmp");
   image1.sizes.push_back(gfx::Size(kIdealSize, kIdealSize));
   images.push_back(image1);
 
-  media_session::MediaMetadata::MediaImage image2;
+  MediaImage image2;
   image2.src = GURL("https://www.example.com/test.PNG");
   image2.sizes.push_back(gfx::Size(kIdealSize, kIdealSize));
   images.push_back(image2);
 
-  media_session::MediaMetadata::MediaImage image3;
+  MediaImage image3;
   image3.src = GURL("https://www.example.com/test");
   image3.sizes.push_back(gfx::Size(kIdealSize, kIdealSize));
   images.push_back(image3);
@@ -103,9 +103,9 @@
 }
 
 TEST_F(MediaImageManagerTest, IgnoreImageTooSmall) {
-  std::vector<MediaMetadata::MediaImage> images;
+  std::vector<MediaImage> images;
 
-  media_session::MediaMetadata::MediaImage image;
+  MediaImage image;
   image.sizes.push_back(gfx::Size(1, 1));
   images.push_back(image);
 
@@ -113,14 +113,14 @@
 }
 
 TEST_F(MediaImageManagerTest, PickImageUseDefaultScoreIfNoSize) {
-  std::vector<MediaMetadata::MediaImage> images;
+  std::vector<MediaImage> images;
 
-  media_session::MediaMetadata::MediaImage image1;
+  MediaImage image1;
   image1.src = GURL("https://www.example.com/test.bmp");
   image1.sizes.push_back(gfx::Size(kIdealSize, kIdealSize));
   images.push_back(image1);
 
-  media_session::MediaMetadata::MediaImage image2;
+  MediaImage image2;
   image2.src = GURL("https://www.example.com/test.PNG");
   images.push_back(image2);
 
@@ -128,13 +128,13 @@
 }
 
 TEST_F(MediaImageManagerTest, PickImageCloserToIdeal) {
-  std::vector<MediaMetadata::MediaImage> images;
+  std::vector<MediaImage> images;
 
-  media_session::MediaMetadata::MediaImage image1;
+  MediaImage image1;
   image1.sizes.push_back(gfx::Size(kIdealSize, kIdealSize));
   images.push_back(image1);
 
-  media_session::MediaMetadata::MediaImage image2;
+  MediaImage image2;
   image2.sizes.push_back(gfx::Size(kMinSize, kMinSize));
   images.push_back(image2);
 
@@ -142,13 +142,13 @@
 }
 
 TEST_F(MediaImageManagerTest, PickImageWithMultipleSizes) {
-  std::vector<MediaMetadata::MediaImage> images;
+  std::vector<MediaImage> images;
 
-  media_session::MediaMetadata::MediaImage image1;
+  MediaImage image1;
   image1.sizes.push_back(gfx::Size(kIdealSize - 5, kIdealSize - 5));
   images.push_back(image1);
 
-  media_session::MediaMetadata::MediaImage image2;
+  MediaImage image2;
   image2.sizes.push_back(gfx::Size(kMinSize, kMinSize));
   image2.sizes.push_back(gfx::Size(kIdealSize, kIdealSize));
   images.push_back(image2);
@@ -157,13 +157,13 @@
 }
 
 TEST_F(MediaImageManagerTest, PickImageWithBetterAspectRatio) {
-  std::vector<MediaMetadata::MediaImage> images;
+  std::vector<MediaImage> images;
 
-  media_session::MediaMetadata::MediaImage image1;
+  MediaImage image1;
   image1.sizes.push_back(gfx::Size(kIdealSize, kIdealSize));
   images.push_back(image1);
 
-  media_session::MediaMetadata::MediaImage image2;
+  MediaImage image2;
   image2.sizes.push_back(gfx::Size(kIdealSize, kMinSize));
   images.push_back(image2);
 
diff --git a/services/media_session/public/cpp/media_metadata.cc b/services/media_session/public/cpp/media_metadata.cc
index 42ed11b..8dff7650 100644
--- a/services/media_session/public/cpp/media_metadata.cc
+++ b/services/media_session/public/cpp/media_metadata.cc
@@ -4,22 +4,10 @@
 
 #include "services/media_session/public/cpp/media_metadata.h"
 
-#include <algorithm>
-#include <iterator>
+#include "services/media_session/public/cpp/media_image.h"
 
 namespace media_session {
 
-MediaMetadata::MediaImage::MediaImage() = default;
-
-MediaMetadata::MediaImage::MediaImage(const MediaImage& other) = default;
-
-MediaMetadata::MediaImage::~MediaImage() = default;
-
-bool MediaMetadata::MediaImage::operator==(
-    const MediaMetadata::MediaImage& other) const {
-  return src == other.src && type == other.type && sizes == other.sizes;
-}
-
 MediaMetadata::MediaMetadata() = default;
 
 MediaMetadata::~MediaMetadata() = default;
diff --git a/services/media_session/public/cpp/media_metadata.h b/services/media_session/public/cpp/media_metadata.h
index f209927c..ae24bca 100644
--- a/services/media_session/public/cpp/media_metadata.h
+++ b/services/media_session/public/cpp/media_metadata.h
@@ -10,7 +10,6 @@
 #include "base/component_export.h"
 #include "base/strings/string16.h"
 #include "build/build_config.h"
-#include "ui/gfx/geometry/size.h"
 #include "url/gurl.h"
 
 #if defined(OS_ANDROID)
@@ -23,33 +22,11 @@
 
 namespace media_session {
 
+struct MediaImage;
+
 // The MediaMetadata is a structure carrying information associated to a
 // MediaSession.
 struct COMPONENT_EXPORT(MEDIA_SESSION_CPP) MediaMetadata {
-  // Structure representing an MediaImage as per the MediaSession API, see:
-  // https://wicg.github.io/mediasession/#dictdef-mediaimage
-  struct COMPONENT_EXPORT(MEDIA_SESSION_CPP) MediaImage {
-    MediaImage();
-    MediaImage(const MediaImage& other);
-    ~MediaImage();
-
-    bool operator==(const MediaImage& other) const;
-
-    // MUST be a valid url. If an icon doesn't have a valid URL, it will not be
-    // successfully parsed, thus will not be represented in the Manifest.
-    GURL src;
-
-    // Empty if the parsing failed or the field was not present. The type can be
-    // any string and doesn't have to be a valid image MIME type at this point.
-    // It is up to the consumer of the object to check if the type matches a
-    // supported type.
-    base::string16 type;
-
-    // Empty if the parsing failed, the field was not present or empty.
-    // The special value "any" is represented by gfx::Size(0, 0).
-    std::vector<gfx::Size> sizes;
-  };
-
   MediaMetadata();
   ~MediaMetadata();
 
diff --git a/services/media_session/public/cpp/media_metadata_android.cc b/services/media_session/public/cpp/media_metadata_android.cc
index 5323cbea..20b69f4 100644
--- a/services/media_session/public/cpp/media_metadata_android.cc
+++ b/services/media_session/public/cpp/media_metadata_android.cc
@@ -4,31 +4,15 @@
 
 #include "services/media_session/public/cpp/media_metadata.h"
 
-#include <string>
-#include <vector>
-
 #include "base/android/jni_array.h"
 #include "base/android/jni_string.h"
 #include "jni/MediaMetadata_jni.h"
+#include "services/media_session/public/cpp/media_image.h"
 
 using base::android::ScopedJavaLocalRef;
 
 namespace media_session {
 
-namespace {
-
-std::vector<int> GetFlattenedSizeArray(const std::vector<gfx::Size>& sizes) {
-  std::vector<int> flattened_array;
-  flattened_array.reserve(2 * sizes.size());
-  for (const auto& size : sizes) {
-    flattened_array.push_back(size.width());
-    flattened_array.push_back(size.height());
-  }
-  return flattened_array;
-}
-
-}  // anonymous namespace
-
 base::android::ScopedJavaLocalRef<jobject> MediaMetadata::CreateJavaObject(
     JNIEnv* env) const {
   ScopedJavaLocalRef<jstring> j_title(
@@ -42,16 +26,8 @@
       Java_MediaMetadata_create(env, j_title, j_artist, j_album);
 
   for (const auto& image : artwork) {
-    std::string src = image.src.spec();
-    ScopedJavaLocalRef<jstring> j_src(
-        base::android::ConvertUTF8ToJavaString(env, src));
-    ScopedJavaLocalRef<jstring> j_type(
-        base::android::ConvertUTF16ToJavaString(env, image.type));
-    ScopedJavaLocalRef<jintArray> j_sizes(
-        base::android::ToJavaIntArray(env, GetFlattenedSizeArray(image.sizes)));
-
-    Java_MediaMetadata_createAndAddMediaImage(env, j_metadata, j_src, j_type,
-                                              j_sizes);
+    ScopedJavaLocalRef<jobject> j_image = image.CreateJavaObject(env);
+    Java_MediaMetadata_addImage(env, j_metadata, j_image);
   }
 
   return j_metadata;
diff --git a/services/media_session/public/cpp/media_session.typemap b/services/media_session/public/cpp/media_session.typemap
index 94b58a9..0eec57c 100644
--- a/services/media_session/public/cpp/media_session.typemap
+++ b/services/media_session/public/cpp/media_session.typemap
@@ -3,7 +3,10 @@
 # found in the LICENSE file.
 
 mojom = "//services/media_session/public/mojom/media_session.mojom"
-public_headers = [ "//services/media_session/public/cpp/media_metadata.h" ]
+public_headers = [
+  "//services/media_session/public/cpp/media_image.h",
+  "//services/media_session/public/cpp/media_metadata.h",
+]
 traits_headers =
     [ "//services/media_session/public/cpp/media_session_mojom_traits.h" ]
 public_deps = [
@@ -13,7 +16,7 @@
   "//ui/gfx/geometry/mojo:struct_traits",
 ]
 type_mappings = [
-  "media_session.mojom.MediaImage=media_session::MediaMetadata::MediaImage",
+  "media_session.mojom.MediaImage=media_session::MediaImage",
   "media_session.mojom.MediaMetadata=media_session::MediaMetadata",
 ]
 sources = [
diff --git a/services/media_session/public/cpp/media_session_mojom_traits.cc b/services/media_session/public/cpp/media_session_mojom_traits.cc
index cfddaea1..bdbf0b4 100644
--- a/services/media_session/public/cpp/media_session_mojom_traits.cc
+++ b/services/media_session/public/cpp/media_session_mojom_traits.cc
@@ -12,9 +12,9 @@
 
 // static
 bool StructTraits<media_session::mojom::MediaImageDataView,
-                  media_session::MediaMetadata::MediaImage>::
+                  media_session::MediaImage>::
     Read(media_session::mojom::MediaImageDataView data,
-         media_session::MediaMetadata::MediaImage* out) {
+         media_session::MediaImage* out) {
   if (!data.ReadSrc(&out->src))
     return false;
   if (!data.ReadType(&out->type))
diff --git a/services/media_session/public/cpp/media_session_mojom_traits.h b/services/media_session/public/cpp/media_session_mojom_traits.h
index e96b276..a877f50f 100644
--- a/services/media_session/public/cpp/media_session_mojom_traits.h
+++ b/services/media_session/public/cpp/media_session_mojom_traits.h
@@ -5,30 +5,30 @@
 #ifndef SERVICES_MEDIA_SESSION_PUBLIC_CPP_MEDIA_SESSION_MOJOM_TRAITS_H_
 #define SERVICES_MEDIA_SESSION_PUBLIC_CPP_MEDIA_SESSION_MOJOM_TRAITS_H_
 
+#include <vector>
+
 #include "services/media_session/public/mojom/media_session.mojom.h"
 
 namespace mojo {
 
 template <>
 struct StructTraits<media_session::mojom::MediaImageDataView,
-                    media_session::MediaMetadata::MediaImage> {
-  static const GURL& src(
-      const media_session::MediaMetadata::MediaImage& image) {
+                    media_session::MediaImage> {
+  static const GURL& src(const media_session::MediaImage& image) {
     return image.src;
   }
 
-  static const base::string16& type(
-      const media_session::MediaMetadata::MediaImage& image) {
+  static const base::string16& type(const media_session::MediaImage& image) {
     return image.type;
   }
 
   static const std::vector<gfx::Size>& sizes(
-      const media_session::MediaMetadata::MediaImage& image) {
+      const media_session::MediaImage& image) {
     return image.sizes;
   }
 
   static bool Read(media_session::mojom::MediaImageDataView data,
-                   media_session::MediaMetadata::MediaImage* out);
+                   media_session::MediaImage* out);
 };
 
 template <>
@@ -49,7 +49,7 @@
     return metadata.album;
   }
 
-  static const std::vector<media_session::MediaMetadata::MediaImage>& artwork(
+  static const std::vector<media_session::MediaImage>& artwork(
       const media_session::MediaMetadata& metadata) {
     return metadata.artwork;
   }
diff --git a/services/service_manager/BUILD.gn b/services/service_manager/BUILD.gn
index e55963d..161671d 100644
--- a/services/service_manager/BUILD.gn
+++ b/services/service_manager/BUILD.gn
@@ -2,15 +2,12 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//mojo/public/tools/bindings/mojom.gni")
 import("//testing/test.gni")
 
 group("all") {
   testonly = true
   deps = [
     ":service_manager",
-    "//services/service_manager/background",
-    "//services/service_manager/standalone",
   ]
 
   if (!is_ios) {
@@ -24,10 +21,14 @@
 
 source_set("service_manager") {
   sources = [
+    "background_service_manager.cc",
+    "background_service_manager.h",
     "connect_params.cc",
     "connect_params.h",
     "service_manager.cc",
     "service_manager.h",
+    "service_process_launcher_delegate.h",
+    "service_process_launcher_factory.h",
     "switches.cc",
     "switches.h",
   ]
@@ -41,11 +42,25 @@
   public_deps = [
     "//base",
     "//mojo/public/cpp/bindings",
+    "//services/catalog:constants",
     "//services/catalog:lib",
     "//services/catalog/public/mojom:constants",
     "//services/service_manager/public/cpp",
     "//services/service_manager/public/mojom",
-    "//services/service_manager/runner/host:lib",
+    "//services/service_manager/runner/common",
     "//services/service_manager/sandbox",
   ]
+
+  if (!is_ios) {
+    sources += [
+      "service_process_launcher.cc",
+      "service_process_launcher.h",
+    ]
+
+    deps += [ "//mojo/core/embedder" ]
+  }
+
+  if (is_linux) {
+    deps += [ "//sandbox/linux:sandbox_services" ]
+  }
 }
diff --git a/services/service_manager/DEPS b/services/service_manager/DEPS
index 3fd6080b..a73a7c9 100644
--- a/services/service_manager/DEPS
+++ b/services/service_manager/DEPS
@@ -1,3 +1,4 @@
 include_rules = [
+  "+sandbox",
   "+services/catalog",
 ]
diff --git a/services/service_manager/background/BUILD.gn b/services/service_manager/background/BUILD.gn
deleted file mode 100644
index a1ab9985..0000000
--- a/services/service_manager/background/BUILD.gn
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-group("background") {
-  testonly = true
-  deps = [
-    ":lib",
-  ]
-}
-
-source_set("lib") {
-  sources = [
-    "background_service_manager.cc",
-    "background_service_manager.h",
-  ]
-  deps = [
-    "//base",
-    "//services/catalog:constants",
-    "//services/catalog:lib",
-    "//services/service_manager",
-    "//services/service_manager/public/cpp",
-    "//services/service_manager/runner:init",
-    "//services/service_manager/runner/host:lib",
-    "//services/service_manager/standalone",
-  ]
-}
diff --git a/services/service_manager/background/DEPS b/services/service_manager/background/DEPS
deleted file mode 100644
index 3fd6080b..0000000
--- a/services/service_manager/background/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
-  "+services/catalog",
-]
diff --git a/services/service_manager/background/background_service_manager.cc b/services/service_manager/background/background_service_manager.cc
deleted file mode 100644
index 6e718c4..0000000
--- a/services/service_manager/background/background_service_manager.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/service_manager/background/background_service_manager.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_pump_default.h"
-#include "base/path_service.h"
-#include "base/run_loop.h"
-#include "base/sequenced_task_runner.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/simple_thread.h"
-#include "services/catalog/store.h"
-#include "services/service_manager/connect_params.h"
-#include "services/service_manager/public/cpp/service.h"
-#include "services/service_manager/service_manager.h"
-#include "services/service_manager/standalone/context.h"
-
-namespace service_manager {
-
-BackgroundServiceManager::BackgroundServiceManager(
-    ServiceProcessLauncherDelegate* launcher_delegate,
-    const std::vector<Manifest>& manifests)
-    : background_thread_("service_manager") {
-  background_thread_.Start();
-  background_thread_.task_runner()->PostTask(
-      FROM_HERE,
-      base::BindOnce(&BackgroundServiceManager::InitializeOnBackgroundThread,
-                     base::Unretained(this), launcher_delegate, manifests));
-}
-
-BackgroundServiceManager::~BackgroundServiceManager() {
-  base::WaitableEvent done_event(
-      base::WaitableEvent::ResetPolicy::MANUAL,
-      base::WaitableEvent::InitialState::NOT_SIGNALED);
-  background_thread_.task_runner()->PostTask(
-      FROM_HERE,
-      base::Bind(&BackgroundServiceManager::ShutDownOnBackgroundThread,
-                 base::Unretained(this), &done_event));
-  done_event.Wait();
-  DCHECK(!context_);
-}
-
-void BackgroundServiceManager::RegisterService(
-    const Identity& identity,
-    mojom::ServicePtr service,
-    mojom::PIDReceiverRequest pid_receiver_request) {
-  mojom::ServicePtrInfo service_info = service.PassInterface();
-  background_thread_.task_runner()->PostTask(
-      FROM_HERE,
-      base::Bind(&BackgroundServiceManager::RegisterServiceOnBackgroundThread,
-                 base::Unretained(this), identity, base::Passed(&service_info),
-                 base::Passed(&pid_receiver_request)));
-}
-
-void BackgroundServiceManager::InitializeOnBackgroundThread(
-    ServiceProcessLauncherDelegate* launcher_delegate,
-    const std::vector<Manifest>& manifests) {
-  context_ = std::make_unique<Context>(launcher_delegate, manifests);
-}
-
-void BackgroundServiceManager::ShutDownOnBackgroundThread(
-    base::WaitableEvent* done_event) {
-  context_.reset();
-  done_event->Signal();
-}
-
-void BackgroundServiceManager::RegisterServiceOnBackgroundThread(
-    const Identity& identity,
-    mojom::ServicePtrInfo service_info,
-    mojom::PIDReceiverRequest pid_receiver_request) {
-  mojom::ServicePtr service;
-  service.Bind(std::move(service_info));
-  context_->service_manager()->RegisterService(
-      identity, std::move(service), std::move(pid_receiver_request));
-}
-
-}  // namespace service_manager
diff --git a/services/service_manager/background/tests/BUILD.gn b/services/service_manager/background/tests/BUILD.gn
deleted file mode 100644
index c571e68..0000000
--- a/services/service_manager/background/tests/BUILD.gn
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//mojo/public/tools/bindings/mojom.gni")
-import("//services/service_manager/public/cpp/service_executable.gni")
-import("//testing/test.gni")
-
-source_set("unittests") {
-  testonly = true
-  sources = [
-    "background_service_manager_unittest.cc",
-  ]
-
-  deps = [
-    ":test_service_interfaces",
-    "//base",
-    "//base/test:test_support",
-    "//services/service_manager/background:lib",
-    "//services/service_manager/public/cpp",
-    "//testing/gtest",
-    "//url",
-  ]
-
-  data_deps = [
-    ":background_service_manager_test_service",
-  ]
-}
-
-mojom("test_service_interfaces") {
-  testonly = true
-  sources = [
-    "background.test-mojom",
-  ]
-}
-
-service_executable("background_service_manager_test_service") {
-  testonly = true
-  sources = [
-    "test_service.cc",
-  ]
-
-  deps = [
-    ":test_service_interfaces",
-    "//base",
-    "//services/service_manager/public/cpp",
-    "//services/service_manager/public/mojom",
-  ]
-}
diff --git a/services/service_manager/background_service_manager.cc b/services/service_manager/background_service_manager.cc
new file mode 100644
index 0000000..d8cacde66
--- /dev/null
+++ b/services/service_manager/background_service_manager.cc
@@ -0,0 +1,112 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/service_manager/background_service_manager.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/message_loop/message_pump_default.h"
+#include "base/path_service.h"
+#include "base/run_loop.h"
+#include "base/sequenced_task_runner.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/simple_thread.h"
+#include "services/catalog/store.h"
+#include "services/service_manager/connect_params.h"
+#include "services/service_manager/public/cpp/service.h"
+#include "services/service_manager/service_manager.h"
+
+#if !defined(OS_IOS)
+#include "services/service_manager/service_process_launcher.h"
+#include "services/service_manager/service_process_launcher_factory.h"
+#endif
+
+namespace service_manager {
+
+namespace {
+
+#if !defined(OS_IOS)
+// Used to ensure we only init once.
+class ServiceProcessLauncherFactoryImpl : public ServiceProcessLauncherFactory {
+ public:
+  ServiceProcessLauncherFactoryImpl() = default;
+
+ private:
+  std::unique_ptr<ServiceProcessLauncher> Create(
+      const base::FilePath& service_path) override {
+    return std::make_unique<ServiceProcessLauncher>(nullptr, service_path);
+  }
+};
+#endif
+
+}  // namespace
+
+BackgroundServiceManager::BackgroundServiceManager(
+    const std::vector<Manifest>& manifests)
+    : background_thread_("service_manager") {
+  background_thread_.Start();
+  background_thread_.task_runner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&BackgroundServiceManager::InitializeOnBackgroundThread,
+                     base::Unretained(this), manifests));
+}
+
+BackgroundServiceManager::~BackgroundServiceManager() {
+  base::WaitableEvent done_event(
+      base::WaitableEvent::ResetPolicy::MANUAL,
+      base::WaitableEvent::InitialState::NOT_SIGNALED);
+  background_thread_.task_runner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&BackgroundServiceManager::ShutDownOnBackgroundThread,
+                     base::Unretained(this), &done_event));
+  done_event.Wait();
+  DCHECK(!service_manager_);
+}
+
+void BackgroundServiceManager::RegisterService(
+    const Identity& identity,
+    mojom::ServicePtr service,
+    mojom::PIDReceiverRequest pid_receiver_request) {
+  mojom::ServicePtrInfo service_info = service.PassInterface();
+  background_thread_.task_runner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          &BackgroundServiceManager::RegisterServiceOnBackgroundThread,
+          base::Unretained(this), identity, base::Passed(&service_info),
+          base::Passed(&pid_receiver_request)));
+}
+
+void BackgroundServiceManager::InitializeOnBackgroundThread(
+    const std::vector<Manifest>& manifests) {
+  std::unique_ptr<ServiceProcessLauncherFactory> process_launcher_factory;
+#if !defined(OS_IOS)
+  process_launcher_factory =
+      std::make_unique<ServiceProcessLauncherFactoryImpl>();
+#endif
+
+  service_manager_ = std::make_unique<ServiceManager>(
+      std::move(process_launcher_factory), manifests);
+}
+
+void BackgroundServiceManager::ShutDownOnBackgroundThread(
+    base::WaitableEvent* done_event) {
+  service_manager_.reset();
+  done_event->Signal();
+}
+
+void BackgroundServiceManager::RegisterServiceOnBackgroundThread(
+    const Identity& identity,
+    mojom::ServicePtrInfo service_info,
+    mojom::PIDReceiverRequest pid_receiver_request) {
+  mojom::ServicePtr service;
+  service.Bind(std::move(service_info));
+  service_manager_->RegisterService(identity, std::move(service),
+                                    std::move(pid_receiver_request));
+}
+
+}  // namespace service_manager
diff --git a/services/service_manager/background/background_service_manager.h b/services/service_manager/background_service_manager.h
similarity index 64%
rename from services/service_manager/background/background_service_manager.h
rename to services/service_manager/background_service_manager.h
index 8260d0c..a5621253a 100644
--- a/services/service_manager/background/background_service_manager.h
+++ b/services/service_manager/background_service_manager.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 SERVICES_SERVICE_MANAGER_BACKGROUND_BACKGROUND_SERVICE_MANAGER_H_
-#define SERVICES_SERVICE_MANAGER_BACKGROUND_BACKGROUND_SERVICE_MANAGER_H_
+#ifndef SERVICES_SERVICE_MANAGER_BACKGROUND_SERVICE_MANAGER_H_
+#define SERVICES_SERVICE_MANAGER_BACKGROUND_SERVICE_MANAGER_H_
 
 #include <memory>
 #include <vector>
@@ -14,7 +14,6 @@
 #include "services/service_manager/public/cpp/manifest.h"
 #include "services/service_manager/public/mojom/connector.mojom.h"
 #include "services/service_manager/public/mojom/service.mojom.h"
-#include "services/service_manager/runner/host/service_process_launcher_delegate.h"
 
 namespace base {
 class WaitableEvent;
@@ -22,16 +21,19 @@
 
 namespace service_manager {
 
-class Context;
 class Identity;
 class ServiceManager;
 
-// BackgroundServiceManager runs a Service Manager on a dedicated background
-// thread.
+// BackgroundServiceManager is a helper class that be can used to instantiate a
+// ServiceManager instance on a dedicated background thread. This is only
+// slightly more convenient than simply running your own background thread and
+// instantiating ServiceManager there yourself.
+//
+// TODO(https://crbug.com/904240): Consider deleting this class since it has
+// such limited use and is trivial to replicate.
 class BackgroundServiceManager {
  public:
-  BackgroundServiceManager(ServiceProcessLauncherDelegate* launcher_delegate,
-                           const std::vector<Manifest>& manifests);
+  explicit BackgroundServiceManager(const std::vector<Manifest>& manifests);
   ~BackgroundServiceManager();
 
   // Creates a service instance for |identity|. This is intended for use by the
@@ -45,9 +47,7 @@
                        mojom::PIDReceiverRequest pid_receiver_request);
 
  private:
-  void InitializeOnBackgroundThread(
-      ServiceProcessLauncherDelegate* launcher_delegate,
-      const std::vector<Manifest>& manifests);
+  void InitializeOnBackgroundThread(const std::vector<Manifest>& manifests);
   void ShutDownOnBackgroundThread(base::WaitableEvent* done_event);
   void RegisterServiceOnBackgroundThread(
       const Identity& identity,
@@ -56,12 +56,12 @@
 
   base::Thread background_thread_;
 
-  // The ServiceManager context. Must only be used on the background thread.
-  std::unique_ptr<Context> context_;
+  // Must only be used on the background thread.
+  std::unique_ptr<ServiceManager> service_manager_;
 
   DISALLOW_COPY_AND_ASSIGN(BackgroundServiceManager);
 };
 
 }  // namespace service_manager
 
-#endif  // SERVICES_SERVICE_MANAGER_BACKGROUND_BACKGROUND_SERVICE_MANAGER_H_
+#endif  // SERVICES_SERVICE_MANAGER_BACKGROUND_SERVICE_MANAGER_H_
diff --git a/services/service_manager/embedder/BUILD.gn b/services/service_manager/embedder/BUILD.gn
index feeac1e2..2c0d006 100644
--- a/services/service_manager/embedder/BUILD.gn
+++ b/services/service_manager/embedder/BUILD.gn
@@ -45,7 +45,7 @@
       ":embedder_switches",
       "//base",
       "//mojo/core/embedder",
-      "//services/service_manager/background:lib",
+      "//services/service_manager",
       "//services/service_manager/public/cpp",
       "//services/service_manager/public/cpp/service_executable:support",
       "//services/service_manager/public/mojom",
diff --git a/services/service_manager/embedder/main.cc b/services/service_manager/embedder/main.cc
index 06e6247..febe7676 100644
--- a/services/service_manager/embedder/main.cc
+++ b/services/service_manager/embedder/main.cc
@@ -76,34 +76,6 @@
 // service manager embedder process.
 constexpr size_t kMaximumMojoMessageSize = 128 * 1024 * 1024;
 
-class ServiceProcessLauncherDelegateImpl
-    : public service_manager::ServiceProcessLauncherDelegate {
- public:
-  explicit ServiceProcessLauncherDelegateImpl(MainDelegate* main_delegate)
-      : main_delegate_(main_delegate) {}
-  ~ServiceProcessLauncherDelegateImpl() override {}
-
- private:
-  // service_manager::ServiceProcessLauncherDelegate:
-  void AdjustCommandLineArgumentsForTarget(
-      const service_manager::Identity& target,
-      base::CommandLine* command_line) override {
-    if (main_delegate_->ShouldLaunchAsServiceProcess(target)) {
-      command_line->AppendSwitchASCII(switches::kProcessType,
-                                      switches::kProcessTypeService);
-#if defined(OS_WIN)
-      command_line->AppendArg(switches::kDefaultServicePrefetchArgument);
-#endif
-    }
-
-    main_delegate_->AdjustServiceProcessCommandLine(target, command_line);
-  }
-
-  MainDelegate* const main_delegate_;
-
-  DISALLOW_COPY_AND_ASSIGN(ServiceProcessLauncherDelegateImpl);
-};
-
 #if defined(OS_POSIX) && !defined(OS_ANDROID)
 
 // Setup signal-handling state: resanitize most signals, ignore SIGPIPE.
@@ -232,10 +204,8 @@
       ipc_thread.task_runner(),
       mojo::core::ScopedIPCSupport::ShutdownPolicy::FAST);
 
-  ServiceProcessLauncherDelegateImpl service_process_launcher_delegate(
-      delegate);
   service_manager::BackgroundServiceManager background_service_manager(
-      &service_process_launcher_delegate, delegate->GetServiceManifests());
+      delegate->GetServiceManifests());
 
   base::RunLoop run_loop;
   delegate->OnServiceManagerInitialized(run_loop.QuitClosure(),
diff --git a/services/service_manager/embedder/main_delegate.h b/services/service_manager/embedder/main_delegate.h
index ba3589a5..aed554fd 100644
--- a/services/service_manager/embedder/main_delegate.h
+++ b/services/service_manager/embedder/main_delegate.h
@@ -13,7 +13,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/single_thread_task_runner.h"
 #include "mojo/core/embedder/configuration.h"
-#include "services/service_manager/background/background_service_manager.h"
+#include "services/service_manager/background_service_manager.h"
 #include "services/service_manager/embedder/process_type.h"
 #include "services/service_manager/public/cpp/identity.h"
 #include "services/service_manager/public/cpp/manifest.h"
diff --git a/services/service_manager/public/cpp/service_binding.cc b/services/service_manager/public/cpp/service_binding.cc
index 28356da..1658e0e 100644
--- a/services/service_manager/public/cpp/service_binding.cc
+++ b/services/service_manager/public/cpp/service_binding.cc
@@ -11,7 +11,7 @@
 #include "base/synchronization/lock.h"
 #include "services/service_manager/public/cpp/service.h"
 #include "services/tracing/public/cpp/traced_process.h"
-#include "services/tracing/public/mojom/tracing.mojom.h"
+#include "services/tracing/public/mojom/traced_process.mojom.h"
 
 namespace service_manager {
 
diff --git a/services/service_manager/public/cpp/test/BUILD.gn b/services/service_manager/public/cpp/test/BUILD.gn
index 63babbc..53edf5d 100644
--- a/services/service_manager/public/cpp/test/BUILD.gn
+++ b/services/service_manager/public/cpp/test/BUILD.gn
@@ -17,7 +17,6 @@
   public_deps = [
     "//base",
     "//services/service_manager",
-    "//services/service_manager/background:lib",
     "//services/service_manager/public/cpp",
     "//services/service_manager/public/mojom",
   ]
diff --git a/services/service_manager/public/cpp/test/test_service_manager.cc b/services/service_manager/public/cpp/test/test_service_manager.cc
index cbc3430a..ca72829 100644
--- a/services/service_manager/public/cpp/test/test_service_manager.cc
+++ b/services/service_manager/public/cpp/test/test_service_manager.cc
@@ -4,8 +4,7 @@
 
 #include "services/service_manager/public/cpp/test/test_service_manager.h"
 
-#include "services/service_manager/background/background_service_manager.h"
-#include "services/service_manager/service_manager.h"
+#include "services/service_manager/background_service_manager.h"
 
 namespace service_manager {
 
@@ -14,7 +13,7 @@
 
 TestServiceManager::TestServiceManager(const std::vector<Manifest>& manifests)
     : background_service_manager_(
-          std::make_unique<BackgroundServiceManager>(nullptr, manifests)) {}
+          std::make_unique<BackgroundServiceManager>(manifests)) {}
 
 TestServiceManager::~TestServiceManager() = default;
 
diff --git a/services/service_manager/runner/host/BUILD.gn b/services/service_manager/runner/host/BUILD.gn
deleted file mode 100644
index 234fd8a..0000000
--- a/services/service_manager/runner/host/BUILD.gn
+++ /dev/null
@@ -1,77 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//mojo/public/tools/bindings/mojom.gni")
-import("//services/service_manager/public/cpp/service_executable.gni")
-import("//testing/test.gni")
-
-source_set("lib") {
-  sources = [
-    # These interfaces are shared between iOS and other platforms to minimize
-    # the amount of iddef'ing necessary to handle the fact that iOS does not
-    # support ServiceProcessLauncher.
-    "service_process_launcher_delegate.h",
-    "service_process_launcher_factory.h",
-  ]
-
-  deps = [
-    "//base:base_static",
-    "//base:i18n",
-    "//services/service_manager/public/cpp",
-    "//services/service_manager/runner:init",
-    "//services/service_manager/runner/common",
-    "//services/service_manager/sandbox",
-  ]
-
-  public_deps = [
-    "//base",
-    "//mojo/public/cpp/platform",
-    "//mojo/public/cpp/system",
-  ]
-
-  if (is_linux) {
-    deps += [ "//sandbox/linux:sandbox_services" ]
-  }
-
-  if (!is_ios) {
-    sources += [
-      # iOS does not support launching services in their own processes.
-      "service_process_launcher.cc",
-      "service_process_launcher.h",
-    ]
-
-    deps += [ "//mojo/core/embedder" ]
-  }
-}
-
-if (!is_ios) {
-  # The below targets rely on the host_test_service service binary. Service
-  # binaries are not supported on iOS.
-  source_set("unittests") {
-    testonly = true
-    sources = [
-      "service_process_launcher_unittest.cc",
-    ]
-
-    deps = [
-      ":lib",
-      "//base",
-      "//base/test:test_support",
-      "//services/service_manager",
-      "//services/service_manager/runner:init",
-      "//services/service_manager/runner/common",
-      "//testing/gtest",
-    ]
-
-    data_deps = [
-      ":host_test_service",
-    ]
-  }
-
-  service_executable("host_test_service") {
-    sources = [
-      "host_test_service_main.cc",
-    ]
-  }
-}
diff --git a/services/service_manager/runner/host/DEPS b/services/service_manager/runner/host/DEPS
deleted file mode 100644
index ec69c8f..0000000
--- a/services/service_manager/runner/host/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
-  "+sandbox",
-]
diff --git a/services/service_manager/runner/host/OWNERS b/services/service_manager/runner/host/OWNERS
deleted file mode 100644
index 90a1836b..0000000
--- a/services/service_manager/runner/host/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-per-file linux_sandbox*=rickyz@chromium.org
-
diff --git a/services/service_manager/service_manager.cc b/services/service_manager/service_manager.cc
index 6cb2005..d4f2d8f 100644
--- a/services/service_manager/service_manager.cc
+++ b/services/service_manager/service_manager.cc
@@ -41,7 +41,7 @@
 #include "services/service_manager/sandbox/sandbox_type.h"
 
 #if !defined(OS_IOS)
-#include "services/service_manager/runner/host/service_process_launcher.h"
+#include "services/service_manager/service_process_launcher.h"
 #endif
 
 namespace service_manager {
diff --git a/services/service_manager/service_manager.h b/services/service_manager/service_manager.h
index 8bf2428..793d0570 100644
--- a/services/service_manager/service_manager.h
+++ b/services/service_manager/service_manager.h
@@ -27,7 +27,7 @@
 #include "services/service_manager/public/mojom/service.mojom.h"
 #include "services/service_manager/public/mojom/service_factory.mojom.h"
 #include "services/service_manager/public/mojom/service_manager.mojom.h"
-#include "services/service_manager/runner/host/service_process_launcher_factory.h"
+#include "services/service_manager/service_process_launcher_factory.h"
 
 namespace service_manager {
 
diff --git a/services/service_manager/runner/host/service_process_launcher.cc b/services/service_manager/service_process_launcher.cc
similarity index 98%
rename from services/service_manager/runner/host/service_process_launcher.cc
rename to services/service_manager/service_process_launcher.cc
index be7b170..46a4932f 100644
--- a/services/service_manager/runner/host/service_process_launcher.cc
+++ b/services/service_manager/service_process_launcher.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 "services/service_manager/runner/host/service_process_launcher.h"
+#include "services/service_manager/service_process_launcher.h"
 
 #include <utility>
 
diff --git a/services/service_manager/runner/host/service_process_launcher.h b/services/service_manager/service_process_launcher.h
similarity index 87%
rename from services/service_manager/runner/host/service_process_launcher.h
rename to services/service_manager/service_process_launcher.h
index 2c2f283..e69cfa2d 100644
--- a/services/service_manager/runner/host/service_process_launcher.h
+++ b/services/service_manager/service_process_launcher.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 SERVICES_SERVICE_MANAGER_RUNNER_HOST_SERVICE_PROCESS_LAUNCHER_H_
-#define SERVICES_SERVICE_MANAGER_RUNNER_HOST_SERVICE_PROCESS_LAUNCHER_H_
+#ifndef SERVICES_SERVICE_MANAGER_SERVICE_PROCESS_LAUNCHER_H_
+#define SERVICES_SERVICE_MANAGER_SERVICE_PROCESS_LAUNCHER_H_
 
 #include <memory>
 #include <string>
@@ -16,8 +16,8 @@
 #include "base/process/process.h"
 #include "base/sequenced_task_runner.h"
 #include "services/service_manager/public/mojom/service_factory.mojom.h"
-#include "services/service_manager/runner/host/service_process_launcher_delegate.h"
 #include "services/service_manager/sandbox/sandbox_type.h"
+#include "services/service_manager/service_process_launcher_delegate.h"
 
 namespace service_manager {
 
@@ -60,4 +60,4 @@
 
 }  // namespace service_manager
 
-#endif  // SERVICES_SERVICE_MANAGER_RUNNER_HOST_SERVICE_PROCESS_LAUNCHER_H_
+#endif  // SERVICES_SERVICE_MANAGER_SERVICE_PROCESS_LAUNCHER_H_
diff --git a/services/service_manager/runner/host/service_process_launcher_delegate.h b/services/service_manager/service_process_launcher_delegate.h
similarity index 72%
rename from services/service_manager/runner/host/service_process_launcher_delegate.h
rename to services/service_manager/service_process_launcher_delegate.h
index 2eee3db..6e00578 100644
--- a/services/service_manager/runner/host/service_process_launcher_delegate.h
+++ b/services/service_manager/service_process_launcher_delegate.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SERVICES_SERVICE_MANAGER_RUNNER_HOST_SERVICE_PROCESS_LAUNCHER_DELEGATE_H_
-#define SERVICES_SERVICE_MANAGER_RUNNER_HOST_SERVICE_PROCESS_LAUNCHER_DELEGATE_H_
+#ifndef SERVICES_SERVICE_MANAGER_SERVICE_PROCESS_LAUNCHER_DELEGATE_H_
+#define SERVICES_SERVICE_MANAGER_SERVICE_PROCESS_LAUNCHER_DELEGATE_H_
 
 namespace base {
 class CommandLine;
@@ -27,4 +27,4 @@
 
 }  // namespace service_manager
 
-#endif  // SERVICES_SERVICE_MANAGER_RUNNER_HOST_SERVICE_PROCESS_LAUNCHER_DELEGATE_H_
+#endif  // SERVICES_SERVICE_MANAGER_SERVICE_PROCESS_LAUNCHER_DELEGATE_H_
diff --git a/services/service_manager/runner/host/service_process_launcher_factory.h b/services/service_manager/service_process_launcher_factory.h
similarity index 67%
rename from services/service_manager/runner/host/service_process_launcher_factory.h
rename to services/service_manager/service_process_launcher_factory.h
index ab11fd1a..3fce130 100644
--- a/services/service_manager/runner/host/service_process_launcher_factory.h
+++ b/services/service_manager/service_process_launcher_factory.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SERVICES_SERVICE_MANAGER_RUNNER_HOST_SERVICE_PROCESS_LAUNCHER_FACTORY_H_
-#define SERVICES_SERVICE_MANAGER_RUNNER_HOST_SERVICE_PROCESS_LAUNCHER_FACTORY_H_
+#ifndef SERVICES_SERVICE_MANAGER_SERVICE_PROCESS_LAUNCHER_FACTORY_H_
+#define SERVICES_SERVICE_MANAGER_SERVICE_PROCESS_LAUNCHER_FACTORY_H_
 
 #include <memory>
 
@@ -22,4 +22,4 @@
 
 }  // namespace service_manager
 
-#endif  // SERVICES_SERVICE_MANAGER_RUNNER_HOST_SERVICE_PROCESS_LAUNCHER_FACTORY_H_
+#endif  // SERVICES_SERVICE_MANAGER_SERVICE_PROCESS_LAUNCHER_FACTORY_H_
diff --git a/services/service_manager/standalone/BUILD.gn b/services/service_manager/standalone/BUILD.gn
deleted file mode 100644
index 164a77a..0000000
--- a/services/service_manager/standalone/BUILD.gn
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//mojo/public/tools/bindings/mojom.gni")
-import("//testing/test.gni")
-
-source_set("standalone") {
-  sources = [
-    "context.cc",
-    "context.h",
-  ]
-
-  deps = [
-    "//base",
-    "//base/third_party/dynamic_annotations",
-    "//mojo/public/cpp/system",
-    "//services/catalog:lib",
-    "//services/service_manager",
-    "//services/service_manager/public/cpp",
-    "//services/service_manager/runner/common",
-    "//services/service_manager/runner/host:lib",
-    "//url",
-  ]
-}
diff --git a/services/service_manager/standalone/DEPS b/services/service_manager/standalone/DEPS
deleted file mode 100644
index 3fd6080b..0000000
--- a/services/service_manager/standalone/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
-  "+services/catalog",
-]
diff --git a/services/service_manager/standalone/context.cc b/services/service_manager/standalone/context.cc
deleted file mode 100644
index 12594f8..0000000
--- a/services/service_manager/standalone/context.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/service_manager/standalone/context.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/json/json_file_value_serializer.h"
-#include "base/macros.h"
-#include "base/path_service.h"
-#include "base/process/process_info.h"
-#include "base/run_loop.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/trace_event/trace_event.h"
-#include "build/build_config.h"
-#include "services/catalog/catalog.h"
-#include "services/service_manager/connect_params.h"
-#include "services/service_manager/public/cpp/constants.h"
-#include "services/service_manager/public/cpp/service_filter.h"
-#include "services/service_manager/runner/common/switches.h"
-#include "services/service_manager/runner/host/service_process_launcher_factory.h"
-#include "services/service_manager/service_manager.h"
-#include "services/service_manager/switches.h"
-
-#if !defined(OS_IOS)
-#include "services/service_manager/runner/host/service_process_launcher.h"
-#endif
-
-namespace service_manager {
-namespace {
-
-#if !defined(OS_IOS)
-// Used to ensure we only init once.
-class ServiceProcessLauncherFactoryImpl : public ServiceProcessLauncherFactory {
- public:
-  ServiceProcessLauncherFactoryImpl(ServiceProcessLauncherDelegate* delegate)
-      : delegate_(delegate) {}
-
- private:
-   std::unique_ptr<ServiceProcessLauncher> Create(
-      const base::FilePath& service_path) override {
-     return std::make_unique<ServiceProcessLauncher>(delegate_, service_path);
-  }
-
-  ServiceProcessLauncherDelegate* delegate_;
-};
-#endif  // !defined(OS_IOS)
-
-void OnInstanceQuit(const std::string& name,
-                    base::RepeatingClosure on_quit,
-                    const Identity& identity) {
-  if (name == identity.name())
-    on_quit.Run();
-}
-
-const char kService[] = "service";
-
-}  // namespace
-
-Context::Context(
-    ServiceProcessLauncherDelegate* service_process_launcher_delegate,
-    const std::vector<Manifest>& manifests) {
-  TRACE_EVENT0("service_manager", "Context::Context");
-
-  std::unique_ptr<ServiceProcessLauncherFactory>
-      service_process_launcher_factory;
-
-// iOS does not support launching services in their own processes (and does
-// not build ServiceProcessLauncher).
-#if !defined(OS_IOS)
-  service_process_launcher_factory =
-      std::make_unique<ServiceProcessLauncherFactoryImpl>(
-          service_process_launcher_delegate);
-#endif
-  service_manager_ = std::make_unique<ServiceManager>(
-      std::move(service_process_launcher_factory), manifests);
-}
-
-Context::~Context() = default;
-
-void Context::RunCommandLineApplication(base::RepeatingClosure on_quit) {
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(kService))
-    Run(command_line->GetSwitchValueASCII(kService), std::move(on_quit));
-  else
-    std::move(on_quit).Run();
-}
-
-void Context::Run(const std::string& name, base::RepeatingClosure on_quit) {
-  service_manager_->SetInstanceQuitCallback(
-      base::BindRepeating(&OnInstanceQuit, name, std::move(on_quit)));
-
-  auto params = std::make_unique<ConnectParams>();
-  params->set_source(GetServiceManagerInstanceIdentity());
-  params->set_target(ServiceFilter::ByNameInGroup(name, kSystemInstanceGroup));
-  service_manager_->Connect(std::move(params));
-}
-
-}  // namespace service_manager
diff --git a/services/service_manager/standalone/context.h b/services/service_manager/standalone/context.h
deleted file mode 100644
index 234a9aa..0000000
--- a/services/service_manager/standalone/context.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SERVICES_SERVICE_MANAGER_STANDALONE_CONTEXT_H_
-#define SERVICES_SERVICE_MANAGER_STANDALONE_CONTEXT_H_
-
-#include <memory>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/time/time.h"
-#include "services/service_manager/public/cpp/manifest.h"
-#include "services/service_manager/runner/host/service_process_launcher_delegate.h"
-
-namespace service_manager {
-
-class ServiceManager;
-
-// The "global" context for the service manager's main process.
-class Context {
- public:
-  Context(ServiceProcessLauncherDelegate* launcher_delegate,
-          const std::vector<Manifest>& manifests);
-  ~Context();
-
-  // Run the application specified on the command line, and run |on_quit| when
-  // the application instance quits.
-  void RunCommandLineApplication(base::RepeatingClosure on_quit);
-
-  ServiceManager* service_manager() { return service_manager_.get(); }
-
- private:
-  // Runs the app specified by |name|.
-  void Run(const std::string& name, base::RepeatingClosure on_quit);
-
-  std::unique_ptr<ServiceManager> service_manager_;
-  base::Time main_entry_time_;
-
-  DISALLOW_COPY_AND_ASSIGN(Context);
-};
-
-}  // namespace service_manager
-
-#endif  // SERVICES_SERVICE_MANAGER_STANDALONE_CONTEXT_H_
diff --git a/services/service_manager/tests/BUILD.gn b/services/service_manager/tests/BUILD.gn
index 95f56b0e..e9906e5 100644
--- a/services/service_manager/tests/BUILD.gn
+++ b/services/service_manager/tests/BUILD.gn
@@ -15,6 +15,7 @@
 
 test("service_manager_unittests") {
   sources = [
+    "background_service_manager_unittest.cc",
     "test_support_unittest.cc",
   ]
 
@@ -27,13 +28,10 @@
     "//mojo/public/cpp/system",
     "//services/catalog:lib",
     "//services/service_manager",
-    "//services/service_manager/background:lib",
-    "//services/service_manager/background/tests:unittests",
     "//services/service_manager/public/cpp",
     "//services/service_manager/public/cpp:unittests",
     "//services/service_manager/public/cpp/test:test_support",
     "//services/service_manager/public/mojom",
-    "//services/service_manager/runner/host:unittests",
     "//services/service_manager/tests/connect",
     "//services/service_manager/tests/lifecycle",
     "//services/service_manager/tests/sandbox",
@@ -41,11 +39,22 @@
     "//services/service_manager/tests/shutdown",
     "//testing/gtest",
   ]
+
+  data_deps = [
+    ":background_service_manager_test_service",
+  ]
+
+  if (!is_ios) {
+    sources += [ "service_process_launcher_unittest.cc" ]
+
+    data_deps += [ ":service_process_launcher_test_service" ]
+  }
 }
 
 mojom("interfaces") {
   testonly = true
   sources = [
+    "background.test-mojom",
     "test_support.test-mojom",
   ]
 }
@@ -65,3 +74,27 @@
     "//services/service_manager/runner/common",
   ]
 }
+
+service_executable("background_service_manager_test_service") {
+  testonly = true
+
+  sources = [
+    "background_service_manager_test_service_main.cc",
+  ]
+
+  deps = [
+    ":interfaces",
+    "//base",
+    "//mojo/public/cpp/bindings",
+    "//services/service_manager/public/cpp",
+    "//services/service_manager/public/mojom",
+  ]
+}
+
+service_executable("service_process_launcher_test_service") {
+  testonly = true
+
+  sources = [
+    "service_process_launcher_test_service_main.cc",
+  ]
+}
diff --git a/services/service_manager/background/tests/background.test-mojom b/services/service_manager/tests/background.test-mojom
similarity index 100%
rename from services/service_manager/background/tests/background.test-mojom
rename to services/service_manager/tests/background.test-mojom
diff --git a/services/service_manager/background/tests/test_service.cc b/services/service_manager/tests/background_service_manager_test_service_main.cc
similarity index 85%
rename from services/service_manager/background/tests/test_service.cc
rename to services/service_manager/tests/background_service_manager_test_service_main.cc
index f366b88ed..0cd954d4 100644
--- a/services/service_manager/background/tests/test_service.cc
+++ b/services/service_manager/tests/background_service_manager_test_service_main.cc
@@ -6,23 +6,22 @@
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
-#include "services/service_manager/background/tests/background.test-mojom.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "services/service_manager/public/cpp/service.h"
 #include "services/service_manager/public/cpp/service_binding.h"
 #include "services/service_manager/public/mojom/service.mojom.h"
+#include "services/service_manager/tests/background.test-mojom.h"
 
 namespace service_manager {
 
 // A service that exports a simple interface for testing. Used to test the
 // parent background service manager.
-class TestClient : public Service,
-                   public mojom::TestService {
+class TestClient : public Service, public mojom::TestService {
  public:
   TestClient(mojom::ServiceRequest request)
       : service_binding_(this, std::move(request)) {
-    registry_.AddInterface(base::Bind(&TestClient::BindTestServiceRequest,
-                                      base::Unretained(this)));
+    registry_.AddInterface(base::BindRepeating(
+        &TestClient::BindTestServiceRequest, base::Unretained(this)));
   }
 
   ~TestClient() override = default;
diff --git a/services/service_manager/background/tests/background_service_manager_unittest.cc b/services/service_manager/tests/background_service_manager_unittest.cc
similarity index 86%
rename from services/service_manager/background/tests/background_service_manager_unittest.cc
rename to services/service_manager/tests/background_service_manager_unittest.cc
index 8f607c16..e651f6d2 100644
--- a/services/service_manager/background/tests/background_service_manager_unittest.cc
+++ b/services/service_manager/tests/background_service_manager_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 "services/service_manager/background/background_service_manager.h"
+#include "services/service_manager/background_service_manager.h"
 
 #include <memory>
 #include <vector>
@@ -12,13 +12,14 @@
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/values.h"
-#include "services/service_manager/background/tests/background.test-mojom.h"
+#include "build/build_config.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/constants.h"
 #include "services/service_manager/public/cpp/manifest.h"
 #include "services/service_manager/public/cpp/manifest_builder.h"
 #include "services/service_manager/public/cpp/service.h"
 #include "services/service_manager/public/cpp/service_binding.h"
+#include "services/service_manager/tests/background.test-mojom.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace service_manager {
@@ -58,9 +59,9 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceImpl);
 };
 
-void SetFlagAndRunClosure(bool* flag, const base::Closure& closure) {
+void SetFlagAndRunClosure(bool* flag, base::OnceClosure closure) {
   *flag = true;
-  closure.Run();
+  std::move(closure).Run();
 }
 
 // Uses BackgroundServiceManager to start the service manager in the background
@@ -75,8 +76,7 @@
 #endif
 TEST(BackgroundServiceManagerTest, MAYBE_Basic) {
   base::test::ScopedTaskEnvironment scoped_task_environment;
-  BackgroundServiceManager background_service_manager(nullptr,
-                                                      GetTestManifests());
+  BackgroundServiceManager background_service_manager(GetTestManifests());
   mojom::ServicePtr service;
   ServiceImpl service_impl(mojo::MakeRequest(&service));
   background_service_manager.RegisterService(
@@ -89,8 +89,8 @@
                                           &test_service);
   base::RunLoop run_loop;
   bool got_result = false;
-  test_service->Test(
-      base::Bind(&SetFlagAndRunClosure, &got_result, run_loop.QuitClosure()));
+  test_service->Test(base::BindOnce(&SetFlagAndRunClosure, &got_result,
+                                    run_loop.QuitClosure()));
   run_loop.Run();
   EXPECT_TRUE(got_result);
 }
diff --git a/services/service_manager/runner/host/host_test_service_main.cc b/services/service_manager/tests/service_process_launcher_test_service_main.cc
similarity index 100%
rename from services/service_manager/runner/host/host_test_service_main.cc
rename to services/service_manager/tests/service_process_launcher_test_service_main.cc
diff --git a/services/service_manager/runner/host/service_process_launcher_unittest.cc b/services/service_manager/tests/service_process_launcher_unittest.cc
similarity index 95%
rename from services/service_manager/runner/host/service_process_launcher_unittest.cc
rename to services/service_manager/tests/service_process_launcher_unittest.cc
index 0b91049..4b0f080 100644
--- a/services/service_manager/runner/host/service_process_launcher_unittest.cc
+++ b/services/service_manager/tests/service_process_launcher_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 "services/service_manager/runner/host/service_process_launcher.h"
+#include "services/service_manager/service_process_launcher.h"
 
 #include <memory>
 #include <utility>
@@ -23,7 +23,7 @@
 namespace service_manager {
 namespace {
 
-const char kTestServiceName[] = "host_test_service";
+const char kTestServiceName[] = "service_process_launcher_test_service";
 
 #if defined(OS_WIN)
 const base::FilePath::CharType kServiceExtension[] =
@@ -82,7 +82,7 @@
   base::PathService::Get(base::DIR_EXE, &test_service_path);
 #endif
   test_service_path = test_service_path.AppendASCII(kTestServiceName)
-      .AddExtension(kServiceExtension);
+                          .AddExtension(kServiceExtension);
 
   ServiceProcessLauncherDelegateImpl service_process_launcher_delegate;
   base::Optional<ServiceProcessLauncher> launcher(
diff --git a/services/tracing/manifest.cc b/services/tracing/manifest.cc
index 80af37f..97a56b0 100644
--- a/services/tracing/manifest.cc
+++ b/services/tracing/manifest.cc
@@ -8,6 +8,7 @@
 #include "services/service_manager/public/cpp/manifest_builder.h"
 #include "services/tracing/public/mojom/constants.mojom.h"
 #include "services/tracing/public/mojom/perfetto_service.mojom.h"
+#include "services/tracing/public/mojom/traced_process.mojom.h"
 #include "services/tracing/public/mojom/tracing.mojom.h"
 
 namespace tracing {
diff --git a/services/tracing/perfetto/producer_host.cc b/services/tracing/perfetto/producer_host.cc
index 92da8a32..27a97cd 100644
--- a/services/tracing/perfetto/producer_host.cc
+++ b/services/tracing/perfetto/producer_host.cc
@@ -105,41 +105,11 @@
 // sanitization here because ProducerEndpoint::CommitData() (And any other
 // ProducerEndpoint methods) are designed to deal with malformed / malicious
 // inputs.
-void ProducerHost::CommitData(mojom::CommitDataRequestPtr data_request) {
-  perfetto::CommitDataRequest native_data_request;
-
-  // TODO(oysteine): Set up a TypeTrait for this instead of manual conversion.
-  native_data_request.set_flush_request_id(data_request->flush_request_id);
-
-  for (auto& chunk : data_request->chunks_to_move) {
-    auto* new_chunk = native_data_request.add_chunks_to_move();
-    new_chunk->set_page(chunk->page);
-    new_chunk->set_chunk(chunk->chunk);
-    new_chunk->set_target_buffer(chunk->target_buffer);
-  }
-
-  for (auto& chunk_patch : data_request->chunks_to_patch) {
-    auto* new_chunk_patch = native_data_request.add_chunks_to_patch();
-    new_chunk_patch->set_target_buffer(chunk_patch->target_buffer);
-    new_chunk_patch->set_writer_id(chunk_patch->writer_id);
-    new_chunk_patch->set_chunk_id(chunk_patch->chunk_id);
-
-    for (auto& patch : chunk_patch->patches) {
-      auto* new_patch = new_chunk_patch->add_patches();
-      new_patch->set_offset(patch->offset);
-      new_patch->set_data(patch->data);
-    }
-
-    new_chunk_patch->set_has_more_patches(chunk_patch->has_more_patches);
-  }
-
+void ProducerHost::CommitData(const perfetto::CommitDataRequest& data_request) {
   if (on_commit_callback_for_testing_) {
-    on_commit_callback_for_testing_.Run(native_data_request);
+    on_commit_callback_for_testing_.Run(data_request);
   }
-
-  // TODO(oysteine): Pass through an optional callback for
-  // tests to know when a commit is completed.
-  producer_endpoint_->CommitData(native_data_request);
+  producer_endpoint_->CommitData(data_request);
 }
 
 void ProducerHost::RegisterDataSource(
diff --git a/services/tracing/perfetto/producer_host.h b/services/tracing/perfetto/producer_host.h
index 9819457..7e0becb 100644
--- a/services/tracing/perfetto/producer_host.h
+++ b/services/tracing/perfetto/producer_host.h
@@ -66,7 +66,7 @@
   // This interface gets called by the per-process ProducerClients
   // to signal that there's changes to be committed to the
   // Shared Memory buffer (like finished chunks).
-  void CommitData(mojom::CommitDataRequestPtr data_request) override;
+  void CommitData(const perfetto::CommitDataRequest& data_request) override;
 
   // Called by the ProducerClient to signal the Host that it can
   // provide a specific data source.
diff --git a/services/tracing/public/cpp/perfetto/producer_client.cc b/services/tracing/public/cpp/perfetto/producer_client.cc
index 5058045f..3c249d3 100644
--- a/services/tracing/public/cpp/perfetto/producer_client.cc
+++ b/services/tracing/public/cpp/perfetto/producer_client.cc
@@ -242,39 +242,6 @@
 
 void ProducerClient::CommitData(const perfetto::CommitDataRequest& commit,
                                 CommitDataCallback callback) {
-  // The CommitDataRequest which the SharedMemoryArbiter uses to
-  // signal Perfetto that individual chunks have finished being
-  // written and is ready for consumption, needs to be serialized
-  // into the corresponding Mojo class and sent over to the
-  // service-side.
-  auto new_data_request = mojom::CommitDataRequest::New();
-
-  new_data_request->flush_request_id = commit.flush_request_id();
-  for (auto& chunk : commit.chunks_to_move()) {
-    auto new_chunk = mojom::ChunksToMove::New();
-    new_chunk->page = chunk.page();
-    new_chunk->chunk = chunk.chunk();
-    new_chunk->target_buffer = chunk.target_buffer();
-    new_data_request->chunks_to_move.push_back(std::move(new_chunk));
-  }
-
-  for (auto& chunk_patch : commit.chunks_to_patch()) {
-    auto new_chunk_patch = mojom::ChunksToPatch::New();
-    new_chunk_patch->target_buffer = chunk_patch.target_buffer();
-    new_chunk_patch->writer_id = chunk_patch.writer_id();
-    new_chunk_patch->chunk_id = chunk_patch.chunk_id();
-
-    for (auto& patch : chunk_patch.patches()) {
-      auto new_patch = mojom::ChunkPatch::New();
-      new_patch->offset = patch.offset();
-      new_patch->data = patch.data();
-      new_chunk_patch->patches.push_back(std::move(new_patch));
-    }
-
-    new_chunk_patch->has_more_patches = chunk_patch.has_more_patches();
-    new_data_request->chunks_to_patch.push_back(std::move(new_chunk_patch));
-  }
-
   // TODO(oysteine): Remove the PostTask once Perfetto is fixed to always call
   // CommitData on its provided TaskRunner, right now it'll call it on whatever
   // thread is requesting a new chunk when the SharedMemoryBuffer is full. Until
@@ -282,18 +249,18 @@
   // ProducerClient gets destroyed) but should be okay while the Perfetto
   // integration is behind a flag.
   if (GetTaskRunner()->RunsTasksInCurrentSequence()) {
-    producer_host_->CommitData(std::move(new_data_request));
+    producer_host_->CommitData(commit);
   } else {
     GetTaskRunner()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&ProducerClient::CommitDataOnSequence,
-                       base::Unretained(this), std::move(new_data_request)));
+        FROM_HERE, base::BindOnce(&ProducerClient::CommitDataOnSequence,
+                                  base::Unretained(this), commit));
   }
 }
 
-void ProducerClient::CommitDataOnSequence(mojom::CommitDataRequestPtr request) {
+void ProducerClient::CommitDataOnSequence(
+    const perfetto::CommitDataRequest& request) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  producer_host_->CommitData(std::move(request));
+  producer_host_->CommitData(request);
 }
 
 perfetto::SharedMemory* ProducerClient::shared_memory() const {
diff --git a/services/tracing/public/cpp/perfetto/producer_client.h b/services/tracing/public/cpp/perfetto/producer_client.h
index 89ffca32..a154ed8 100644
--- a/services/tracing/public/cpp/perfetto/producer_client.h
+++ b/services/tracing/public/cpp/perfetto/producer_client.h
@@ -146,7 +146,7 @@
  private:
   friend class base::NoDestructor<ProducerClient>;
 
-  void CommitDataOnSequence(mojom::CommitDataRequestPtr request);
+  void CommitDataOnSequence(const perfetto::CommitDataRequest& request);
   void AddDataSourceOnSequence(DataSourceBase*);
   void RegisterDataSourceWithHost(DataSourceBase* data_source);
 
diff --git a/services/tracing/public/cpp/traced_process.h b/services/tracing/public/cpp/traced_process.h
index 3e29463..94f586b 100644
--- a/services/tracing/public/cpp/traced_process.h
+++ b/services/tracing/public/cpp/traced_process.h
@@ -5,7 +5,7 @@
 #ifndef SERVICES_TRACING_PUBLIC_CPP_TRACED_PROCESS_H_
 #define SERVICES_TRACING_PUBLIC_CPP_TRACED_PROCESS_H_
 
-#include "services/tracing/public/mojom/tracing.mojom.h"
+#include "services/tracing/public/mojom/traced_process.mojom.h"
 
 namespace tracing {
 
diff --git a/services/tracing/public/cpp/traced_process_impl.h b/services/tracing/public/cpp/traced_process_impl.h
index 1522fdf..351228ef 100644
--- a/services/tracing/public/cpp/traced_process_impl.h
+++ b/services/tracing/public/cpp/traced_process_impl.h
@@ -12,6 +12,7 @@
 #include "base/sequence_checker.h"
 #include "base/synchronization/lock.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "services/tracing/public/mojom/traced_process.mojom.h"
 #include "services/tracing/public/mojom/tracing.mojom.h"
 
 namespace tracing {
diff --git a/services/tracing/public/mojom/BUILD.gn b/services/tracing/public/mojom/BUILD.gn
index 9958f38..3ace30d 100644
--- a/services/tracing/public/mojom/BUILD.gn
+++ b/services/tracing/public/mojom/BUILD.gn
@@ -9,11 +9,18 @@
   macro_prefix = "TRACING_MOJOM"
 
   sources = [
-    "constants.mojom",
-    "perfetto_service.mojom",
-    "tracing.mojom",
+    "traced_process.mojom",
   ]
 
+  if (!is_nacl && !is_ios) {
+    enabled_features = [ "is_perfetto_supported_os" ]
+    sources += [
+      "constants.mojom",
+      "perfetto_service.mojom",
+      "tracing.mojom",
+    ]
+  }
+
   public_deps = [
     "//mojo/public/mojom/base",
   ]
diff --git a/services/tracing/public/mojom/OWNERS b/services/tracing/public/mojom/OWNERS
index 08850f4..2c44a46 100644
--- a/services/tracing/public/mojom/OWNERS
+++ b/services/tracing/public/mojom/OWNERS
@@ -1,2 +1,6 @@
 per-file *.mojom=set noparent
 per-file *.mojom=file://ipc/SECURITY_OWNERS
+per-file *_struct_traits*.*=set noparent
+per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
+per-file *.typemap=set noparent
+per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/services/tracing/public/mojom/commit_data_request_struct_traits.cc b/services/tracing/public/mojom/commit_data_request_struct_traits.cc
new file mode 100644
index 0000000..6446ea8
--- /dev/null
+++ b/services/tracing/public/mojom/commit_data_request_struct_traits.cc
@@ -0,0 +1,73 @@
+// 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 "services/tracing/public/mojom/commit_data_request_struct_traits.h"
+
+#include <utility>
+
+namespace mojo {
+// static
+bool StructTraits<tracing::mojom::ChunksToMoveDataView,
+                  perfetto::CommitDataRequest::ChunksToMove>::
+    Read(tracing::mojom::ChunksToMoveDataView data,
+         perfetto::CommitDataRequest::ChunksToMove* out) {
+  out->set_page(data.page());
+  out->set_chunk(data.chunk());
+  out->set_target_buffer(data.target_buffer());
+  return true;
+}
+
+// static
+bool StructTraits<tracing::mojom::ChunkPatchDataView,
+                  perfetto::CommitDataRequest::ChunkToPatch::Patch>::
+    Read(tracing::mojom::ChunkPatchDataView data,
+         perfetto::CommitDataRequest::ChunkToPatch::Patch* out) {
+  std::string data_str;
+  if (!data.ReadData(&data_str)) {
+    return false;
+  }
+  out->set_offset(data.offset());
+  out->set_data(data_str);
+  return true;
+}
+
+// static
+bool StructTraits<tracing::mojom::ChunksToPatchDataView,
+                  perfetto::CommitDataRequest::ChunkToPatch>::
+    Read(tracing::mojom::ChunksToPatchDataView data,
+         perfetto::CommitDataRequest::ChunkToPatch* out) {
+  std::vector<perfetto::CommitDataRequest::ChunkToPatch::Patch> patches;
+  if (!data.ReadPatches(&patches)) {
+    return false;
+  }
+  out->set_target_buffer(data.target_buffer());
+  out->set_writer_id(data.writer_id());
+  out->set_chunk_id(data.chunk_id());
+  for (auto&& patch : patches) {
+    *out->add_patches() = std::move(patch);
+  }
+  out->set_has_more_patches(data.has_more_patches());
+  return true;
+}
+
+// static
+bool StructTraits<tracing::mojom::CommitDataRequestDataView,
+                  perfetto::CommitDataRequest>::
+    Read(tracing::mojom::CommitDataRequestDataView data,
+         perfetto::CommitDataRequest* out) {
+  std::vector<perfetto::CommitDataRequest::ChunkToPatch> patches;
+  std::vector<perfetto::CommitDataRequest::ChunksToMove> moves;
+  if (!data.ReadChunksToMove(&moves) || !data.ReadChunksToPatch(&patches)) {
+    return false;
+  }
+  for (auto&& move : moves) {
+    *out->add_chunks_to_move() = std::move(move);
+  }
+  for (auto&& patch : patches) {
+    *out->add_chunks_to_patch() = std::move(patch);
+  }
+  out->set_flush_request_id(data.flush_request_id());
+  return true;
+}
+}  // namespace mojo
diff --git a/services/tracing/public/mojom/commit_data_request_struct_traits.h b/services/tracing/public/mojom/commit_data_request_struct_traits.h
new file mode 100644
index 0000000..216a50d
--- /dev/null
+++ b/services/tracing/public/mojom/commit_data_request_struct_traits.h
@@ -0,0 +1,110 @@
+// 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.
+
+// This defines mappings from mojom IPC representations to their native perfetto
+// equivalents.
+
+#ifndef SERVICES_TRACING_PUBLIC_MOJOM_COMMIT_DATA_REQUEST_STRUCT_TRAITS_H_
+#define SERVICES_TRACING_PUBLIC_MOJOM_COMMIT_DATA_REQUEST_STRUCT_TRAITS_H_
+
+#include <string>
+#include <vector>
+
+#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "services/tracing/public/mojom/perfetto_service.mojom.h"
+#include "third_party/perfetto/include/perfetto/tracing/core/commit_data_request.h"
+
+namespace mojo {
+
+// ChunksToMove
+template <>
+class StructTraits<tracing::mojom::ChunksToMoveDataView,
+                   perfetto::CommitDataRequest::ChunksToMove> {
+ public:
+  static uint32_t page(const perfetto::CommitDataRequest::ChunksToMove& src) {
+    return src.page();
+  }
+  static uint32_t chunk(const perfetto::CommitDataRequest::ChunksToMove& src) {
+    return src.chunk();
+  }
+  static uint32_t target_buffer(
+      const perfetto::CommitDataRequest::ChunksToMove& src) {
+    return src.target_buffer();
+  }
+
+  static bool Read(tracing::mojom::ChunksToMoveDataView data,
+                   perfetto::CommitDataRequest::ChunksToMove* out);
+};
+
+// ChunkPatch
+template <>
+class StructTraits<tracing::mojom::ChunkPatchDataView,
+                   perfetto::CommitDataRequest::ChunkToPatch::Patch> {
+ public:
+  static uint32_t offset(
+      const perfetto::CommitDataRequest::ChunkToPatch::Patch& src) {
+    return src.offset();
+  }
+  static const std::string& data(
+      const perfetto::CommitDataRequest::ChunkToPatch::Patch& src) {
+    return src.data();
+  }
+
+  static bool Read(tracing::mojom::ChunkPatchDataView data,
+                   perfetto::CommitDataRequest::ChunkToPatch::Patch* out);
+};
+
+// ChunkToPatch
+template <>
+class StructTraits<tracing::mojom::ChunksToPatchDataView,
+                   perfetto::CommitDataRequest::ChunkToPatch> {
+ public:
+  static uint32_t target_buffer(
+      const perfetto::CommitDataRequest::ChunkToPatch& src) {
+    return src.target_buffer();
+  }
+  static uint32_t writer_id(
+      const perfetto::CommitDataRequest::ChunkToPatch& src) {
+    return src.writer_id();
+  }
+  static uint32_t chunk_id(
+      const perfetto::CommitDataRequest::ChunkToPatch& src) {
+    return src.chunk_id();
+  }
+  static const std::vector<perfetto::CommitDataRequest::ChunkToPatch::Patch>&
+  patches(const perfetto::CommitDataRequest::ChunkToPatch& src) {
+    return src.patches();
+  }
+
+  static bool has_more_patches(
+      const perfetto::CommitDataRequest::ChunkToPatch& src) {
+    return src.has_more_patches();
+  }
+
+  static bool Read(tracing::mojom::ChunksToPatchDataView data,
+                   perfetto::CommitDataRequest::ChunkToPatch* out);
+};
+
+// CommitDataRequest
+template <>
+class StructTraits<tracing::mojom::CommitDataRequestDataView,
+                   perfetto::CommitDataRequest> {
+ public:
+  static const std::vector<perfetto::CommitDataRequest::ChunksToMove>&
+  chunks_to_move(const perfetto::CommitDataRequest& src) {
+    return src.chunks_to_move();
+  }
+  static const std::vector<perfetto::CommitDataRequest::ChunkToPatch>&
+  chunks_to_patch(const perfetto::CommitDataRequest& src) {
+    return src.chunks_to_patch();
+  }
+  static uint64_t flush_request_id(const perfetto::CommitDataRequest& src) {
+    return src.flush_request_id();
+  }
+
+  static bool Read(tracing::mojom::CommitDataRequestDataView data,
+                   perfetto::CommitDataRequest* out);
+};
+}  // namespace mojo
+#endif  // SERVICES_TRACING_PUBLIC_MOJOM_COMMIT_DATA_REQUEST_STRUCT_TRAITS_H_
diff --git a/services/tracing/public/mojom/perfetto_service.typemap b/services/tracing/public/mojom/perfetto_service.typemap
new file mode 100644
index 0000000..c19a6e3
--- /dev/null
+++ b/services/tracing/public/mojom/perfetto_service.typemap
@@ -0,0 +1,19 @@
+mojom = "//services/tracing/public/mojom/perfetto_service.mojom"
+public_headers = [
+  "//third_party/perfetto/include/perfetto/tracing/core/commit_data_request.h",
+]
+traits_headers =
+    [ "//services/tracing/public/mojom/commit_data_request_struct_traits.h" ]
+sources = [
+  "//services/tracing/public/mojom/commit_data_request_struct_traits.cc",
+  "//services/tracing/public/mojom/commit_data_request_struct_traits.h",
+]
+public_deps = [
+  "//third_party/perfetto:libperfetto",
+]
+type_mappings = [
+  "tracing.mojom.CommitDataRequest=perfetto::CommitDataRequest",
+  "tracing.mojom.ChunksToMove=perfetto::CommitDataRequest::ChunksToMove",
+  "tracing.mojom.ChunkPatch=perfetto::CommitDataRequest::ChunkToPatch::Patch",
+  "tracing.mojom.ChunkToPatch=perfetto::CommitDataRequest::ChunkToPatch",
+]
diff --git a/services/tracing/public/mojom/traced_process.mojom b/services/tracing/public/mojom/traced_process.mojom
new file mode 100644
index 0000000..b1d80409
--- /dev/null
+++ b/services/tracing/public/mojom/traced_process.mojom
@@ -0,0 +1,26 @@
+// 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 tracing.mojom;
+
+[EnableIf=is_perfetto_supported_os]
+import "services/tracing/public/mojom/perfetto_service.mojom";
+[EnableIf=is_perfetto_supported_os]
+import "services/tracing/public/mojom/tracing.mojom";
+
+struct ConnectToTracingRequest {
+[EnableIf=is_perfetto_supported_os]
+  PerfettoService perfetto_service;
+[EnableIf=is_perfetto_supported_os]
+  AgentRegistry agent_registry;
+};
+
+// The tracing service will bind this interface on every other service,
+// and pass it pointers to the interfaces within the tracing service
+// that the other services should register themselves with.
+interface TracedProcess {
+  ConnectToTracingService(ConnectToTracingRequest request);
+};
+
+
diff --git a/services/tracing/public/mojom/tracing.mojom b/services/tracing/public/mojom/tracing.mojom
index 41d170d..8c081774 100644
--- a/services/tracing/public/mojom/tracing.mojom
+++ b/services/tracing/public/mojom/tracing.mojom
@@ -9,18 +9,6 @@
 import "mojo/public/mojom/base/values.mojom";
 import "services/tracing/public/mojom/perfetto_service.mojom";
 
-struct ConnectToTracingRequest {
-  PerfettoService perfetto_service;
-  AgentRegistry agent_registry;
-};
-
-// The tracing service will bind this interface on every other service,
-// and pass it pointers to the interfaces within the tracing service
-// that the other services should register themselves with.
-interface TracedProcess {
-  ConnectToTracingService(ConnectToTracingRequest request);
-};
-
 // The JSON type of data coming from a tracing agents.
 //
 // - All agents with the same label should have the same type.
diff --git a/services/tracing/public/mojom/typemaps.gni b/services/tracing/public/mojom/typemaps.gni
new file mode 100644
index 0000000..1544fb1
--- /dev/null
+++ b/services/tracing/public/mojom/typemaps.gni
@@ -0,0 +1 @@
+typemaps = [ "//services/tracing/public/mojom/perfetto_service.typemap" ]
diff --git a/services/tracing/tracing_service.cc b/services/tracing/tracing_service.cc
index 628ce84..23c4f31 100644
--- a/services/tracing/tracing_service.cc
+++ b/services/tracing/tracing_service.cc
@@ -15,6 +15,7 @@
 #include "services/tracing/perfetto/perfetto_service.h"
 #include "services/tracing/perfetto/perfetto_tracing_coordinator.h"
 #include "services/tracing/public/cpp/tracing_features.h"
+#include "services/tracing/public/mojom/traced_process.mojom.h"
 
 namespace tracing {
 
diff --git a/third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h b/third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h
index ff914d46..8eaaf0c 100644
--- a/third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h
+++ b/third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h
@@ -18,6 +18,11 @@
 
 class WebThreadScheduler;
 
+// Creates simple scheduling infrastructure for unit tests.
+// It allows creation of FrameSchedulers and PageSchedulers, but doesn't provide
+// any task running infrastructure, relying on the presence of
+// ThreadTaskRunnerHandle::Get() instead, meaning that the users also have to
+// create base::debug::ScopedTaskEnvironment.
 std::unique_ptr<WebThreadScheduler> CreateWebMainThreadSchedulerForTests();
 
 void RunIdleTasksForTesting(WebThreadScheduler* scheduler,
diff --git a/third_party/blink/public/platform/web_feature.mojom b/third_party/blink/public/platform/web_feature.mojom
index f01e5cdf..15fed44 100644
--- a/third_party/blink/public/platform/web_feature.mojom
+++ b/third_party/blink/public/platform/web_feature.mojom
@@ -2216,6 +2216,9 @@
   kCustomCursorIntersectsViewport = 2776,
   kClientHintsLang = 2777,
   kLinkRelPreloadImageSrcset = 2778,
+  kV8HTMLMediaElement_Remote_AttributeGetter = 2779,
+  kV8RemotePlayback_WatchAvailability_Method = 2780,
+  kV8RemotePlayback_Prompt_Method = 2781,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/platform/web_font.h b/third_party/blink/public/platform/web_font.h
index a20b962..ffe57a8 100644
--- a/third_party/blink/public/platform/web_font.h
+++ b/third_party/blink/public/platform/web_font.h
@@ -21,7 +21,6 @@
 struct WebFloatPoint;
 struct WebFloatRect;
 struct WebFontDescription;
-struct WebRect;
 struct WebTextRun;
 
 class WebFont {
@@ -38,8 +37,7 @@
   BLINK_PLATFORM_EXPORT void DrawText(cc::PaintCanvas*,
                                       const WebTextRun&,
                                       const WebFloatPoint& left_baseline,
-                                      SkColor,
-                                      const WebRect& clip) const;
+                                      SkColor) const;
   BLINK_PLATFORM_EXPORT int CalculateWidth(const WebTextRun&) const;
   BLINK_PLATFORM_EXPORT int OffsetForPosition(const WebTextRun&,
                                               float position) const;
diff --git a/third_party/blink/renderer/controller/dev_tools_frontend_impl.cc b/third_party/blink/renderer/controller/dev_tools_frontend_impl.cc
index c1d68eb9..e877aad8 100644
--- a/third_party/blink/renderer/controller/dev_tools_frontend_impl.cc
+++ b/third_party/blink/renderer/controller/dev_tools_frontend_impl.cc
@@ -84,7 +84,10 @@
     v8::Local<v8::Value> devtools_host_obj =
         ToV8(devtools_host_.Get(), global, script_state->GetIsolate());
     DCHECK(!devtools_host_obj.IsEmpty());
-    global->Set(V8AtomicString(isolate, "DevToolsHost"), devtools_host_obj);
+    global
+        ->Set(script_state->GetContext(),
+              V8AtomicString(isolate, "DevToolsHost"), devtools_host_obj)
+        .Check();
   }
 
   if (!api_script_.IsEmpty()) {
diff --git a/third_party/blink/renderer/core/css/threaded/text_renderer_threaded_test.cc b/third_party/blink/renderer/core/css/threaded/text_renderer_threaded_test.cc
index 93c338284..a5dc952 100644
--- a/third_party/blink/renderer/core/css/threaded/text_renderer_threaded_test.cc
+++ b/third_party/blink/renderer/core/css/threaded/text_renderer_threaded_test.cc
@@ -79,24 +79,13 @@
     Font font = Font(font_description);
     font.Update(nullptr);
 
-    const SimpleFontData* font_data = font.PrimaryFont();
-    ASSERT_TRUE(font_data);
-
-    const FontMetrics& font_metrics = font_data->GetFontMetrics();
-
     FloatPoint location(0, 0);
     TextRun text_run(text, 0, 0, TextRun::kAllowTrailingExpansion,
                      TextDirection::kLtr, false);
     text_run.SetNormalizeSpace(true);
-    float width = font.Width(text_run);
 
     TextRunPaintInfo text_run_paint_info(text_run);
 
-    text_run_paint_info.bounds =
-        FloatRect(location.X() - font_metrics.Height() / 2,
-                  location.Y() - font_metrics.Ascent() - font_metrics.LineGap(),
-                  width + font_metrics.Height(), font_metrics.LineSpacing());
-
     MockPaintCanvas mpc;
     PaintFlags flags;
 
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
index 0c25f499..0e71f25 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -702,7 +702,11 @@
 
   // Otherwise, fallback on just checking style.
   auto* style = element_->GetComputedStyle();
-  return style && style->ContainsStyle() && style->ContainsLayout();
+  // Note that if for whatever reason we don't have computed style, then
+  // optimistically assume that we have containment.
+  // TODO(vmpstr): Perhaps we need to add render=lockable which will ensure
+  // containment.
+  return !style || (style->ContainsStyle() && style->ContainsLayout());
 }
 
 // Scoped objects implementation
diff --git a/third_party/blink/renderer/core/events/wheel_event.cc b/third_party/blink/renderer/core/events/wheel_event.cc
index 2fa4989a..1ed4ab7d3 100644
--- a/third_party/blink/renderer/core/events/wheel_event.cc
+++ b/third_party/blink/renderer/core/events/wheel_event.cc
@@ -83,10 +83,12 @@
 WheelEvent::WheelEvent(const AtomicString& type,
                        const WheelEventInit* initializer)
     : MouseEvent(type, initializer),
-      wheel_delta_(initializer->wheelDeltaX() ? initializer->wheelDeltaX()
-                                              : -initializer->deltaX(),
-                   initializer->wheelDeltaY() ? initializer->wheelDeltaY()
-                                              : -initializer->deltaY()),
+      wheel_delta_(initializer->wheelDeltaX()
+                       ? initializer->wheelDeltaX()
+                       : NegateIfPossible(-initializer->deltaX()),
+                   initializer->wheelDeltaY()
+                       ? initializer->wheelDeltaY()
+                       : NegateIfPossible(-initializer->deltaY())),
       delta_x_(initializer->deltaX()
                    ? initializer->deltaX()
                    : NegateIfPossible(initializer->wheelDeltaX())),
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc
index c111ec7a..611b344 100644
--- a/third_party/blink/renderer/core/exported/web_frame_test.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -6516,7 +6516,8 @@
     ASSERT_NE(selection.end, cc::LayerSelectionBound());
 
     blink::Node* layer_owner_node_for_start = V8Node::ToImplWithTypeCheck(
-        v8::Isolate::GetCurrent(), expected_result.Get(0));
+        v8::Isolate::GetCurrent(),
+        expected_result.Get(context, 0).ToLocalChecked());
     ASSERT_TRUE(layer_owner_node_for_start);
     EXPECT_EQ(GetExpectedLayerForSelection(layer_owner_node_for_start)
                   ->CcLayer()
diff --git a/third_party/blink/renderer/core/layout/layout_inline.h b/third_party/blink/renderer/core/layout/layout_inline.h
index 8dfcc41..0677db9 100644
--- a/third_party/blink/renderer/core/layout/layout_inline.h
+++ b/third_party/blink/renderer/core/layout/layout_inline.h
@@ -213,8 +213,8 @@
   using LayoutBoxModelObject::SetContinuation;
 
   bool AlwaysCreateLineBoxes() const {
-    DCHECK(!IsInLayoutNGInlineFormattingContext());
-    return AlwaysCreateLineBoxesForLayoutInline();
+    return AlwaysCreateLineBoxesForLayoutInline() &&
+           !IsInLayoutNGInlineFormattingContext();
   }
   void SetAlwaysCreateLineBoxes(bool always_create_line_boxes = true) {
     DCHECK(!IsInLayoutNGInlineFormattingContext());
@@ -224,10 +224,11 @@
 
   // True if this inline box should force creation of NGPhysicalBoxFragment.
   bool ShouldCreateBoxFragment() const {
-    DCHECK(IsInLayoutNGInlineFormattingContext());
-    return AlwaysCreateLineBoxesForLayoutInline();
+    return AlwaysCreateLineBoxesForLayoutInline() &&
+           IsInLayoutNGInlineFormattingContext();
   }
   void SetShouldCreateBoxFragment(bool value = true) {
+    DCHECK(IsInLayoutNGInlineFormattingContext());
     SetAlwaysCreateLineBoxesForLayoutInline(value);
   }
   void UpdateShouldCreateBoxFragment();
diff --git a/third_party/blink/renderer/core/layout/layout_text.cc b/third_party/blink/renderer/core/layout/layout_text.cc
index 1c80c99..2497e88 100644
--- a/third_party/blink/renderer/core/layout/layout_text.cc
+++ b/third_party/blink/renderer/core/layout/layout_text.cc
@@ -1626,22 +1626,26 @@
   LayoutUnit offset_left = ContainingBlock()->LogicalLeftOffsetForContent();
   LayoutUnit available_space = ContainingBlock()->ContentLogicalWidth();
 
-  switch (StyleRef().GetTextAlign(true)) {
-    case ETextAlign::kLeft:
-    case ETextAlign::kWebkitLeft:
-    case ETextAlign::kJustify:
-    case ETextAlign::kStart:
-      // Do nothing.
-      break;
-    case ETextAlign::kRight:
-    case ETextAlign::kWebkitRight:
-    case ETextAlign::kEnd:
-      offset_left += available_space - text_width;
-      break;
-    case ETextAlign::kCenter:
-    case ETextAlign::kWebkitCenter:
-      offset_left += (available_space - text_width) / 2;
-      break;
+  // If |text_width| is bigger than |available_space| it's because the text
+  // doesn't wrap so we don't need to align anything.
+  if (text_width < available_space) {
+    switch (StyleRef().GetTextAlign(true)) {
+      case ETextAlign::kLeft:
+      case ETextAlign::kWebkitLeft:
+      case ETextAlign::kJustify:
+      case ETextAlign::kStart:
+        // Do nothing.
+        break;
+      case ETextAlign::kRight:
+      case ETextAlign::kWebkitRight:
+      case ETextAlign::kEnd:
+        offset_left += available_space - text_width;
+        break;
+      case ETextAlign::kCenter:
+      case ETextAlign::kWebkitCenter:
+        offset_left += (available_space - text_width) / 2;
+        break;
+    }
   }
 
   FirstTextBox()->SetLogicalLeft(offset_left);
@@ -2174,7 +2178,13 @@
     return Position();
   DCHECK(node->IsTextNode());
   // TODO(layout-dev): Support offset change due to text-transform.
-  return Position(node, offset);
+#if DCHECK_IS_ON()
+  // Ensures that the clamping hack kicks in only with text-transform.
+  if (StyleRef().TextTransform() == ETextTransform::kNone)
+    DCHECK_LE(offset, ToText(node)->length());
+#endif
+  const unsigned clamped_offset = std::min(offset, ToText(node)->length());
+  return Position(node, clamped_offset);
 }
 
 base::Optional<unsigned> LayoutText::CaretOffsetForPosition(
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
index a449fd0..7f7e9f45 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
@@ -629,9 +629,9 @@
   const String& text = Text();
   float min_width = 0;
   unsigned last_end_offset = 0;
-  while (true) {
-    unsigned end_offset =
-        break_iterator_.NextBreakOpportunity(start_offset + 1);
+  while (start_offset < item.EndOffset()) {
+    unsigned end_offset = break_iterator_.NextBreakOpportunity(
+        start_offset + 1, item.EndOffset());
     if (end_offset >= item.EndOffset())
       break;
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
index 4a5a1783..01005a2 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
@@ -498,6 +498,24 @@
             LayoutUnit(10) * data.trailing_space_width);
 }
 
+TEST_F(NGLineBreakerTest, MinMaxWithTrailingSpaces) {
+  LoadAhem();
+  NGInlineNode node = CreateInlineNode(R"HTML(
+    <!DOCTYPE html>
+    <style>
+    #container {
+      font: 10px/1 Ahem;
+      white-space: pre-wrap;
+    }
+    </style>
+    <div id=container>12345 6789 </div>
+  )HTML");
+
+  auto size = node.ComputeMinMaxSize(WritingMode::kHorizontalTb, {});
+  EXPECT_EQ(size.min_size, LayoutUnit(60));
+  EXPECT_EQ(size.max_size, LayoutUnit(110));
+}
+
 #undef MAYBE_OverflowAtomicInline
 }  // namespace
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc
index 3f8e3ca..91494106 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 #include "third_party/blink/renderer/core/dom/node.h"
+#include "third_party/blink/renderer/core/dom/node_computed_style.h"
 #include "third_party/blink/renderer/core/dom/text.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
 #include "third_party/blink/renderer/core/editing/ephemeral_range.h"
@@ -34,8 +35,18 @@
 }
 
 Position CreatePositionForOffsetMapping(const Node& node, unsigned dom_offset) {
-  if (node.IsTextNode())
-    return Position(&node, dom_offset);
+  if (node.IsTextNode()) {
+    // 'text-transform' may make the rendered text length longer than the
+    // original text node, in which case we clamp the offset to avoid crashing.
+    // TODO(crbug.com/750990): Support 'text-transform' to remove this hack.
+#if DCHECK_IS_ON()
+    // Ensures that the clamping hack kicks in only with text-transform.
+    if (node.ComputedStyleRef().TextTransform() == ETextTransform::kNone)
+      DCHECK_LE(dom_offset, ToText(node).length());
+#endif
+    const unsigned clamped_offset = std::min(dom_offset, ToText(node).length());
+    return Position(&node, clamped_offset);
+  }
   // For non-text-anchored position, the offset must be either 0 or 1.
   DCHECK_LE(dom_offset, 1u);
   return dom_offset ? Position::AfterNode(node) : Position::BeforeNode(node);
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index 183dfaa..fea2371 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -66,8 +66,10 @@
 #include "third_party/blink/renderer/core/loader/frame_resource_fetcher_properties.h"
 #include "third_party/blink/renderer/core/loader/idleness_detector.h"
 #include "third_party/blink/renderer/core/loader/interactive_detector.h"
+#include "third_party/blink/renderer/core/loader/mixed_content_checker.h"
 #include "third_party/blink/renderer/core/loader/network_hints_interface.h"
 #include "third_party/blink/renderer/core/loader/preload_helper.h"
+#include "third_party/blink/renderer/core/loader/private/frame_client_hints_preferences_context.h"
 #include "third_party/blink/renderer/core/loader/progress_tracker.h"
 #include "third_party/blink/renderer/core/loader/subresource_filter.h"
 #include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
@@ -1155,16 +1157,35 @@
     HandleRedirect(redirect_response.CurrentRequestUrl());
   }
 
-  // TODO(dgozman): get rid of fake request, we only use it for
-  // DispatchDidReceiveResponse.
-  ResourceRequest fake_request;
-  fake_request.SetFrameType(
-      frame_->IsMainFrame() ? network::mojom::RequestContextFrameType::kTopLevel
-                            : network::mojom::RequestContextFrameType::kNested);
-  fake_request.SetRequestContext(mojom::RequestContextType::HYPERLINK);
-  fetcher_->Context().DispatchDidReceiveResponse(
-      main_resource_identifier_, fake_request, final_response, nullptr,
-      FetchContext::ResourceResponseType::kNotFromMemoryCache);
+  if (!frame_->IsMainFrame() && final_response.GetCTPolicyCompliance() ==
+                                    ResourceResponse::kCTPolicyDoesNotComply) {
+    // Exclude main-frame navigations; those are tracked elsewhere.
+    GetUseCounter().Count(
+        WebFeature::kCertificateTransparencyNonCompliantResourceInSubframe,
+        GetFrame());
+  }
+  MixedContentChecker::CheckMixedPrivatePublic(
+      GetFrame(), final_response.RemoteIPAddress());
+  ParseAndPersistClientHints(final_response);
+  PreloadHelper::LoadLinksFromHeader(
+      final_response.HttpHeaderField(http_names::kLink),
+      final_response.CurrentRequestUrl(), *GetFrame(), nullptr,
+      NetworkHintsInterfaceImpl(), PreloadHelper::kDoNotLoadResources,
+      PreloadHelper::kLoadAll, nullptr);
+  if (!frame_->IsMainFrame() && final_response.HasMajorCertificateErrors()) {
+    MixedContentChecker::HandleCertificateError(
+        GetFrame(), final_response, mojom::RequestContextType::HYPERLINK);
+  }
+  GetFrameLoader().Progress().IncrementProgress(main_resource_identifier_,
+                                                final_response);
+  // TODO(dgozman): remove this client call, it is only used in tests.
+  GetLocalFrameClient().DispatchDidReceiveResponse(final_response);
+  probe::didReceiveResourceResponse(probe::ToCoreProbeSink(GetFrame()),
+                                    main_resource_identifier_, this,
+                                    final_response, nullptr /* resource */);
+  frame_->Console().ReportResourceResponseReceived(
+      this, main_resource_identifier_, final_response);
+
   if (!HandleResponse(final_response))
     return;
 
@@ -1200,6 +1221,8 @@
     document->SetStateForNewFormElements(history_item_->GetDocumentState());
 
   DCHECK(document->GetFrame());
+  // TODO(dgozman): modify frame's client hints directly once we commit
+  // synchronously.
   document->GetFrame()->GetClientHintsPreferences().UpdateFrom(
       client_hints_preferences_);
 
@@ -1593,6 +1616,48 @@
       "https://www.chromestatus.com/feature/5148050062311424");
 }
 
+void DocumentLoader::ParseAndPersistClientHints(
+    const ResourceResponse& response) {
+  const KURL& url = response.CurrentRequestUrl();
+
+  // The accept-ch-lifetime header is honored only on the navigation responses
+  // from a top level frame or with an origin matching the origin of the top
+  // level frame.
+  if (!frame_->IsMainFrame()) {
+    bool is_first_party_origin =
+        frame_->Tree()
+            .Top()
+            .GetSecurityContext()
+            ->GetSecurityOrigin()
+            ->IsSameSchemeHostPort(SecurityOrigin::Create(url).get());
+    if (!is_first_party_origin)
+      return;
+  }
+
+  FrameClientHintsPreferencesContext hints_context(GetFrame());
+  client_hints_preferences_.UpdateFromAcceptClientHintsLifetimeHeader(
+      response.HttpHeaderField(http_names::kAcceptCHLifetime), url,
+      &hints_context);
+  client_hints_preferences_.UpdateFromAcceptClientHintsHeader(
+      response.HttpHeaderField(http_names::kAcceptCH), url, &hints_context);
+
+  // Notify content settings client of persistent client hints.
+  if (client_hints_preferences_.GetPersistDuration().InSeconds() <= 0)
+    return;
+
+  auto* settings_client = frame_->GetContentSettingsClient();
+  if (!settings_client)
+    return;
+
+  // Do not persist client hint preferences if the JavaScript is disabled.
+  bool allow_script = frame_->GetSettings()->GetScriptEnabled();
+  if (!settings_client->AllowScriptFromSource(allow_script, url))
+    return;
+  settings_client->PersistClientHints(
+      client_hints_preferences_.GetWebEnabledClientHints(),
+      client_hints_preferences_.GetPersistDuration(), url);
+}
+
 DEFINE_WEAK_IDENTIFIER_MAP(DocumentLoader);
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/loader/document_loader.h b/third_party/blink/renderer/core/loader/document_loader.h
index 44646d62..c99f8d0 100644
--- a/third_party/blink/renderer/core/loader/document_loader.h
+++ b/third_party/blink/renderer/core/loader/document_loader.h
@@ -348,6 +348,11 @@
                            bool should_report_corb_blocking,
                            const base::Optional<WebURLError>& error) override;
 
+  // Checks if the origin requested persisting the client hints, and notifies
+  // the |WebContentSettingsClient| with the list of client hints and the
+  // persistence duration.
+  void ParseAndPersistClientHints(const ResourceResponse&);
+
   // These fields are copied from WebNavigationParams, see there for definition.
   KURL url_;
   AtomicString http_method_;
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
index 32c9ecf..296256b 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -81,7 +81,6 @@
 #include "third_party/blink/renderer/core/loader/mixed_content_checker.h"
 #include "third_party/blink/renderer/core/loader/network_hints_interface.h"
 #include "third_party/blink/renderer/core/loader/ping_loader.h"
-#include "third_party/blink/renderer/core/loader/private/frame_client_hints_preferences_context.h"
 #include "third_party/blink/renderer/core/loader/progress_tracker.h"
 #include "third_party/blink/renderer/core/loader/subresource_filter.h"
 #include "third_party/blink/renderer/core/page/page.h"
@@ -124,26 +123,6 @@
     "AllowClientHintsToThirdParty", base::FEATURE_DISABLED_BY_DEFAULT};
 #endif
 
-void MaybeRecordCTPolicyComplianceUseCounter(
-    LocalFrame* frame,
-    bool is_main_resource,
-    ResourceResponse::CTPolicyCompliance compliance,
-    DocumentLoader* loader) {
-  if (compliance != ResourceResponse::kCTPolicyDoesNotComply)
-    return;
-  // Exclude main-frame navigation requests; those are tracked elsewhere.
-  if (!frame->Tree().Parent() && is_main_resource)
-    return;
-  if (loader) {
-    loader->GetUseCounter().Count(
-        frame->Tree().Parent()
-            ? WebFeature::kCertificateTransparencyNonCompliantResourceInSubframe
-            : WebFeature::
-                  kCertificateTransparencyNonCompliantSubresourceInMainFrame,
-        frame);
-  }
-}
-
 // Determines FetchCacheMode for |frame|. This FetchCacheMode should be a base
 // policy to consider one of each resource belonging to the frame, and should
 // not count resource specific conditions in.
@@ -486,17 +465,18 @@
   if (GetResourceFetcherProperties().IsDetached())
     return;
 
-  // Note: resource is null if and only if this is a navigation response.
-  bool is_main_resource = !resource;
-
-  if (GetSubresourceFilter() && resource &&
-      resource->GetResourceRequest().IsAdResource()) {
+  if (GetSubresourceFilter() && resource->GetResourceRequest().IsAdResource())
     GetSubresourceFilter()->ReportAdRequestId(response.RequestId());
-  }
 
-  MaybeRecordCTPolicyComplianceUseCounter(GetFrame(), is_main_resource,
-                                          response.GetCTPolicyCompliance(),
-                                          MasterDocumentLoader());
+  if (response.GetCTPolicyCompliance() ==
+      ResourceResponse::kCTPolicyDoesNotComply) {
+    CountUsage(
+        GetFrame()->IsMainFrame()
+            ? WebFeature::
+                  kCertificateTransparencyNonCompliantSubresourceInMainFrame
+            : WebFeature::
+                  kCertificateTransparencyNonCompliantResourceInSubframe);
+  }
 
   if (response_type == ResourceResponseType::kFromMemoryCache) {
     GetLocalFrameClient()->DispatchDidLoadResourceFromMemoryCache(
@@ -510,29 +490,11 @@
 
   MixedContentChecker::CheckMixedPrivatePublic(GetFrame(),
                                                response.RemoteIPAddress());
+
   PreloadHelper::CanLoadResources resource_loading_policy =
       response_type == ResourceResponseType::kFromMemoryCache
           ? PreloadHelper::kDoNotLoadResources
           : PreloadHelper::kLoadResourcesAndPreconnect;
-  if (GetDocumentLoader() &&
-      GetDocumentLoader() == GetDocumentLoader()
-                                 ->GetFrame()
-                                 ->Loader()
-                                 .GetProvisionalDocumentLoader()) {
-    // When response is received with a provisional docloader, the resource
-    // haven't committed yet, and we cannot load resources, only preconnect.
-    resource_loading_policy = PreloadHelper::kDoNotLoadResources;
-  }
-
-  // The accept-ch-lifetime header is honored only on the navigation responses.
-  // Further, the navigation response should be from a top level frame (i.e.,
-  // main frame) or the origin of the response should match the origin of the
-  // top level frame.
-  if (is_main_resource && (GetResourceFetcherProperties().IsMainFrame() ||
-                           IsFirstPartyOrigin(response.CurrentRequestUrl()))) {
-    ParseAndPersistClientHints(response);
-  }
-
   PreloadHelper::LoadLinksFromHeader(
       response.HttpHeaderField(http_names::kLink), response.CurrentRequestUrl(),
       *GetFrame(), frame_or_imported_document_->GetDocument(),
@@ -547,20 +509,13 @@
   }
 
   if (response.IsLegacySymantecCert()) {
-    if (!is_main_resource) {
-      // Main resources are counted in DocumentLoader.
-      UseCounter::Count(GetFrame(),
-                        WebFeature::kLegacySymantecCertInSubresource);
-    }
+    UseCounter::Count(GetFrame(), WebFeature::kLegacySymantecCertInSubresource);
     GetLocalFrameClient()->ReportLegacySymantecCert(
         response.CurrentRequestUrl(), false /* did_fail */);
   }
 
   if (response.IsLegacyTLSVersion()) {
-    if (!is_main_resource) {
-      // Main resources are counted in DocumentLoader.
-      UseCounter::Count(GetFrame(), WebFeature::kLegacyTLSVersionInSubresource);
-    }
+    UseCounter::Count(GetFrame(), WebFeature::kLegacyTLSVersionInSubresource);
     GetLocalFrameClient()->ReportLegacyTLSVersion(response.CurrentRequestUrl());
   }
 
@@ -1158,42 +1113,6 @@
          hints_preferences.ShouldSend(type) || enabled_hints.IsEnabled(type);
 }
 
-void FrameFetchContext::ParseAndPersistClientHints(
-    const ResourceResponse& response) {
-  FrameClientHintsPreferencesContext hints_context(GetFrame());
-
-  GetDocumentLoader()
-      ->GetClientHintsPreferences()
-      .UpdateFromAcceptClientHintsLifetimeHeader(
-          response.HttpHeaderField(http_names::kAcceptCHLifetime),
-          response.CurrentRequestUrl(), &hints_context);
-
-  GetDocumentLoader()
-      ->GetClientHintsPreferences()
-      .UpdateFromAcceptClientHintsHeader(
-          response.HttpHeaderField(http_names::kAcceptCH),
-          response.CurrentRequestUrl(), &hints_context);
-
-  // Notify content settings client of persistent client hints.
-  TimeDelta persist_duration =
-      GetDocumentLoader()->GetClientHintsPreferences().GetPersistDuration();
-  if (persist_duration.InSeconds() <= 0)
-    return;
-
-  WebEnabledClientHints enabled_client_hints = GetDocumentLoader()
-                                                   ->GetClientHintsPreferences()
-                                                   .GetWebEnabledClientHints();
-  if (!AllowScriptFromSourceWithoutNotifying(response.CurrentRequestUrl())) {
-    // Do not persist client hint preferences if the JavaScript is disabled.
-    return;
-  }
-
-  if (auto* settings_client = GetContentSettingsClient()) {
-    settings_client->PersistClientHints(enabled_client_hints, persist_duration,
-                                        response.CurrentRequestUrl());
-  }
-}
-
 FetchContext* FrameFetchContext::Detach() {
   if (GetResourceFetcherProperties().IsDetached())
     return this;
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.h b/third_party/blink/renderer/core/loader/frame_fetch_context.h
index 93a0759..56c3e956 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.h
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.h
@@ -96,7 +96,6 @@
       const ResourceResponse& redirect_response,
       ResourceType,
       const FetchInitiatorInfo& = FetchInitiatorInfo()) override;
-  // Resource* is null if and only if this is a navigation response.
   void DispatchDidReceiveResponse(unsigned long identifier,
                                   const ResourceRequest&,
                                   const ResourceResponse&,
@@ -207,10 +206,6 @@
   bool ShouldSendClientHint(mojom::WebClientHintsType,
                             const ClientHintsPreferences&,
                             const WebEnabledClientHints&) const;
-  // Checks if the origin requested persisting the client hints, and notifies
-  // the |WebContentSettingsClient| with the list of client hints and the
-  // persistence duration.
-  void ParseAndPersistClientHints(const ResourceResponse&);
   void SetFirstPartyCookie(ResourceRequest&);
 
   // Returns true if execution of scripts from the url are allowed. Compared to
diff --git a/third_party/blink/renderer/core/paint/embedded_object_painter.cc b/third_party/blink/renderer/core/paint/embedded_object_painter.cc
index e506970c..450dba2 100644
--- a/third_party/blink/renderer/core/paint/embedded_object_painter.cc
+++ b/third_party/blink/renderer/core/paint/embedded_object_painter.cc
@@ -84,7 +84,6 @@
   FloatRect text_rect(FloatPoint(), text_geometry);
   text_rect.Move(FloatPoint(content_rect.Center()) - text_rect.Center());
   TextRunPaintInfo run_info(text_run);
-  run_info.bounds = float_background_rect;
   context.SetFillColor(ScaleAlpha(Color::kBlack, kReplacementTextTextOpacity));
   context.DrawBidiText(font, run_info,
                        text_rect.Location() +
diff --git a/third_party/blink/renderer/core/paint/file_upload_control_painter.cc b/third_party/blink/renderer/core/paint/file_upload_control_painter.cc
index 024c736e..5dfade7 100644
--- a/third_party/blink/renderer/core/paint/file_upload_control_painter.cc
+++ b/third_party/blink/renderer/core/paint/file_upload_control_painter.cc
@@ -69,16 +69,6 @@
           kPositionOnContainingLine));
     TextRunPaintInfo text_run_paint_info(text_run);
 
-    const SimpleFontData* font_data =
-        layout_file_upload_control_.StyleRef().GetFont().PrimaryFont();
-    if (!font_data)
-      return;
-    // FIXME: Shouldn't these offsets be rounded? crbug.com/350474
-    text_run_paint_info.bounds =
-        FloatRect(text_x.ToFloat(),
-                  text_y.ToFloat() - font_data->GetFontMetrics().Ascent(),
-                  text_width, font_data->GetFontMetrics().Height());
-
     // Draw the filename.
     DrawingRecorder recorder(paint_info.context, layout_file_upload_control_,
                              paint_info.phase);
diff --git a/third_party/blink/renderer/core/paint/list_marker_painter.cc b/third_party/blink/renderer/core/paint/list_marker_painter.cc
index 4653f90..859bbcbb 100644
--- a/third_party/blink/renderer/core/paint/list_marker_painter.cc
+++ b/third_party/blink/renderer/core/paint/list_marker_painter.cc
@@ -133,7 +133,6 @@
   }
 
   TextRunPaintInfo text_run_paint_info(text_run);
-  text_run_paint_info.bounds = FloatRect(EnclosingIntRect(marker));
   const SimpleFontData* font_data =
       layout_list_marker_.StyleRef().GetFont().PrimaryFont();
   FloatPoint text_origin =
@@ -164,7 +163,6 @@
       ConstructTextRun(font, suffix_str, 2, layout_list_marker_.StyleRef(),
                        layout_list_marker_.StyleRef().Direction());
   TextRunPaintInfo suffix_run_info(suffix_run);
-  suffix_run_info.bounds = FloatRect(EnclosingIntRect(marker));
 
   if (layout_list_marker_.StyleRef().IsLeftToRightDirection()) {
     context.DrawText(font, text_run_paint_info, text_origin);
diff --git a/third_party/blink/renderer/core/paint/nine_piece_image_grid.cc b/third_party/blink/renderer/core/paint/nine_piece_image_grid.cc
index a16feadb..2e44c5f 100644
--- a/third_party/blink/renderer/core/paint/nine_piece_image_grid.cc
+++ b/third_party/blink/renderer/core/paint/nine_piece_image_grid.cc
@@ -26,12 +26,31 @@
                        ValueForLength(slice, LayoutUnit(maximum)).Round());
 }
 
+// Scale the width of the |start| and |end| edges using |scale_factor|.
+// Always round the width of |start|. Based on available space (|box_extent|),
+// the width of |end| is either rounded or floored. This should keep abutting
+// edges flush, while not producing potentially "uneven" widths for a
+// non-overlapping case.
+static void ScaleEdgeWidths(NinePieceImageGrid::Edge& start,
+                            NinePieceImageGrid::Edge& end,
+                            int box_extent,
+                            float scale_factor) {
+  LayoutUnit start_width(start.width);
+  start_width *= scale_factor;
+  LayoutUnit end_width(end.width);
+  end_width *= scale_factor;
+  start.width = start_width.Round();
+  int remaining = box_extent - start.width;
+  int rounded_end = end_width.Round();
+  end.width = rounded_end > remaining ? end_width.Floor() : rounded_end;
+}
+
 NinePieceImageGrid::NinePieceImageGrid(const NinePieceImage& nine_piece_image,
                                        IntSize image_size,
                                        IntRect border_image_area,
                                        const IntRectOutsets& border_widths,
                                        bool include_left_edge,
-                                       bool include_rigt_edge)
+                                       bool include_right_edge)
     : border_image_area_(border_image_area),
       image_size_(image_size),
       horizontal_tile_rule_(nine_piece_image.HorizontalRule()),
@@ -46,10 +65,12 @@
   left_.slice = ComputeEdgeSlice(nine_piece_image.ImageSlices().Left(),
                                  image_size.Width());
 
+  // TODO(fs): Compute edge widths to LayoutUnit, and then only round to
+  // integer at the end - after (potential) compensation for overlapping edges.
   top_.width = ComputeEdgeWidth(nine_piece_image.BorderSlices().Top(),
                                 border_widths.Top(), top_.slice,
                                 border_image_area.Height());
-  right_.width = include_rigt_edge
+  right_.width = include_right_edge
                      ? ComputeEdgeWidth(nine_piece_image.BorderSlices().Right(),
                                         border_widths.Right(), right_.slice,
                                         border_image_area.Width())
@@ -73,10 +94,10 @@
       std::min((float)border_image_area.Width() / border_side_width,
                (float)border_image_area.Height() / border_side_height);
   if (border_side_scale_factor < 1) {
-    top_.width *= border_side_scale_factor;
-    right_.width *= border_side_scale_factor;
-    bottom_.width *= border_side_scale_factor;
-    left_.width *= border_side_scale_factor;
+    ScaleEdgeWidths(top_, bottom_, border_image_area.Height(),
+                    border_side_scale_factor);
+    ScaleEdgeWidths(left_, right_, border_image_area.Width(),
+                    border_side_scale_factor);
   }
 }
 
diff --git a/third_party/blink/renderer/core/paint/nine_piece_image_grid_test.cc b/third_party/blink/renderer/core/paint/nine_piece_image_grid_test.cc
index ddee76a4..4089594 100644
--- a/third_party/blink/renderer/core/paint/nine_piece_image_grid_test.cc
+++ b/third_party/blink/renderer/core/paint/nine_piece_image_grid_test.cc
@@ -136,6 +136,45 @@
     else
       EXPECT_TRUE(draw_info.destination.Size().IsEmpty());
   }
+
+  // Like above, but also make sure to get a scale-down factor that requires
+  // rounding to pick the larger value on one of the edges. (A 1:3, 2:3 split.)
+  BorderImageLength top_left(10);
+  BorderImageLength bottom_right(20);
+  nine_piece.SetBorderSlices(
+      BorderImageLengthBox(top_left, bottom_right, bottom_right, top_left));
+  grid = NinePieceImageGrid(nine_piece, image_size, border_image_area,
+                            border_widths);
+  NinePieceImageGrid::NinePieceDrawInfo draw_info =
+      grid.GetNinePieceDrawInfo(kTopLeftPiece, 1);
+  EXPECT_EQ(draw_info.destination.Size(), FloatSize(33, 33));
+  draw_info = grid.GetNinePieceDrawInfo(kTopRightPiece, 1);
+  EXPECT_EQ(draw_info.destination.Size(), FloatSize(67, 33));
+  draw_info = grid.GetNinePieceDrawInfo(kBottomLeftPiece, 1);
+  EXPECT_EQ(draw_info.destination.Size(), FloatSize(33, 67));
+  draw_info = grid.GetNinePieceDrawInfo(kBottomRightPiece, 1);
+  EXPECT_EQ(draw_info.destination.Size(), FloatSize(67, 67));
+
+  // Set border slices that overlap in one dimension but not in the other, and
+  // where the resulting width in the non-overlapping dimension will round to a
+  // larger width.
+  BorderImageLength top_bottom(10);
+  BorderImageLength left_right(Length(11, kFixed));
+  nine_piece.SetBorderSlices(
+      BorderImageLengthBox(top_bottom, left_right, top_bottom, left_right));
+  grid = NinePieceImageGrid(nine_piece, image_size, border_image_area,
+                            border_widths);
+  NinePieceImageGrid::NinePieceDrawInfo tl_info =
+      grid.GetNinePieceDrawInfo(kTopLeftPiece, 1);
+  EXPECT_EQ(tl_info.destination.Size(), FloatSize(6, 50));
+  // The top-right, bottom-left and bottom-right pieces are the same size as
+  // the top-left piece.
+  draw_info = grid.GetNinePieceDrawInfo(kTopRightPiece, 1);
+  EXPECT_EQ(tl_info.destination.Size(), draw_info.destination.Size());
+  draw_info = grid.GetNinePieceDrawInfo(kBottomLeftPiece, 1);
+  EXPECT_EQ(tl_info.destination.Size(), draw_info.destination.Size());
+  draw_info = grid.GetNinePieceDrawInfo(kBottomRightPiece, 1);
+  EXPECT_EQ(tl_info.destination.Size(), draw_info.destination.Size());
 }
 
 TEST_F(NinePieceImageGridTest, NinePieceImagePainting) {
diff --git a/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.cc b/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.cc
index e93430f..d8ae713eb 100644
--- a/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.cc
+++ b/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.cc
@@ -451,13 +451,11 @@
   DCHECK(scaling_factor);
 
   FloatPoint text_origin(fragment.x, fragment.y);
-  FloatSize text_size(fragment.width, fragment.height);
 
   GraphicsContext& context = paint_info.context;
   GraphicsContextStateSaver state_saver(context, false);
   if (scaling_factor != 1) {
     text_origin.Scale(scaling_factor, scaling_factor);
-    text_size.Scale(scaling_factor);
     state_saver.Save();
     context.Scale(1 / scaling_factor, 1 / scaling_factor);
   }
@@ -466,15 +464,6 @@
   text_run_paint_info.from = start_position;
   text_run_paint_info.to = end_position;
 
-  const SimpleFontData* font_data = scaled_font.PrimaryFont();
-  DCHECK(font_data);
-  if (!font_data)
-    return;
-  float baseline = font_data->GetFontMetrics().FloatAscent();
-  text_run_paint_info.bounds =
-      FloatRect(text_origin.X(), text_origin.Y() - baseline, text_size.Width(),
-                text_size.Height());
-
   context.DrawText(scaled_font, text_run_paint_info, text_origin, flags);
   // TODO(npm): Check that there are non-whitespace characters. See
   // crbug.com/788444.
diff --git a/third_party/blink/renderer/core/paint/text_painter.cc b/third_party/blink/renderer/core/paint/text_painter.cc
index 1e91b6d..8560bb6 100644
--- a/third_party/blink/renderer/core/paint/text_painter.cc
+++ b/third_party/blink/renderer/core/paint/text_painter.cc
@@ -79,7 +79,6 @@
                                 unsigned end_offset,
                                 unsigned truncation_point) {
   TextRunPaintInfo text_run_paint_info(run_);
-  text_run_paint_info.bounds = FloatRect(text_bounds_);
   if (start_offset <= end_offset) {
     PaintInternalRun<Step>(text_run_paint_info, start_offset, end_offset);
   } else {
@@ -120,7 +119,6 @@
                                       font_data->GetFontMetrics().Ascent() +
                                       emphasis_mark_offset_);
   TextRunPaintInfo text_run_paint_info(placeholder_text_run);
-  text_run_paint_info.bounds = FloatRect(text_bounds_);
   graphics_context_.ConcatCTM(Rotation(text_bounds_, kClockwise));
   graphics_context_.DrawEmphasisMarks(combined_text_->OriginalFont(),
                                       text_run_paint_info, emphasis_mark_,
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
index 6fc3bfa..547cfe7 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
@@ -867,16 +867,14 @@
       break;
   }
 
-  // The slop built in to this mask rect matches the heuristic used in
-  // FontCGWin.cpp for GDI text.
   TextRunPaintInfo text_run_paint_info(text_run);
-  text_run_paint_info.bounds =
-      FloatRect(location.X() - font_metrics.Height() / 2,
-                location.Y() - font_metrics.Ascent() - font_metrics.LineGap(),
-                clampTo<float>(width + font_metrics.Height()),
-                font_metrics.LineSpacing());
+  FloatRect bounds(
+      location.X() - font_metrics.Height() / 2,
+      location.Y() - font_metrics.Ascent() - font_metrics.LineGap(),
+      clampTo<float>(width + font_metrics.Height()),
+      font_metrics.LineSpacing());
   if (paint_type == CanvasRenderingContext2DState::kStrokePaintType)
-    InflateStrokeRect(text_run_paint_info.bounds);
+    InflateStrokeRect(bounds);
 
   CanvasRenderingContext2DAutoRestoreSkCanvas state_restorer(this);
   if (use_max_width) {
@@ -899,7 +897,7 @@
       },
       [](const SkIRect& rect)  // overdraw test lambda
       { return false; },
-      text_run_paint_info.bounds, paint_type);
+      bounds, paint_type);
 }
 
 const Font& CanvasRenderingContext2D::AccessFont() {
diff --git a/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc
index eddb0b2..67358cd7 100644
--- a/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc
+++ b/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc
@@ -432,15 +432,13 @@
       break;
   }
 
-  // The slop built in to this mask rect matches the heuristic used in
-  // FontCGWin.cpp for GDI text.
   TextRunPaintInfo text_run_paint_info(text_run);
-  text_run_paint_info.bounds =
-      FloatRect(location.X() - font_metrics.Height() / 2,
-                location.Y() - font_metrics.Ascent() - font_metrics.LineGap(),
-                width + font_metrics.Height(), font_metrics.LineSpacing());
+  FloatRect bounds(
+      location.X() - font_metrics.Height() / 2,
+      location.Y() - font_metrics.Ascent() - font_metrics.LineGap(),
+      width + font_metrics.Height(), font_metrics.LineSpacing());
   if (paint_type == CanvasRenderingContext2DState::kStrokePaintType)
-    InflateStrokeRect(text_run_paint_info.bounds);
+    InflateStrokeRect(bounds);
 
   int save_count = c->getSaveCount();
   if (use_max_width) {
@@ -462,7 +460,7 @@
       },
       [](const SkIRect& rect)  // overdraw test lambda
       { return false; },
-      text_run_paint_info.bounds, paint_type);
+      bounds, paint_type);
   c->restoreToCount(save_count);
   ValidateStateStack();
 }
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_test_helper.cc b/third_party/blink/renderer/modules/indexeddb/idb_test_helper.cc
index cf37a961..4b16746 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_test_helper.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_test_helper.cc
@@ -37,9 +37,10 @@
 std::unique_ptr<IDBValue> CreateIDBValueForTesting(v8::Isolate* isolate,
                                                    bool create_wrapped_value) {
   uint32_t element_count = create_wrapped_value ? 16 : 2;
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
   v8::Local<v8::Array> v8_array = v8::Array::New(isolate, element_count);
   for (uint32_t i = 0; i < element_count; ++i)
-    v8_array->Set(i, v8::True(isolate));
+    v8_array->Set(context, i, v8::True(isolate)).Check();
 
   NonThrowableExceptionState non_throwable_exception_state;
   IDBValueWrapper wrapper(isolate, v8_array,
diff --git a/third_party/blink/renderer/modules/payments/payment_response_test.cc b/third_party/blink/renderer/modules/payments/payment_response_test.cc
index 1d39bc9..4cb8af68 100644
--- a/third_party/blink/renderer/modules/payments/payment_response_test.cc
+++ b/third_party/blink/renderer/modules/payments/payment_response_test.cc
@@ -78,8 +78,11 @@
 
   ScriptValue transaction_id(
       scope.GetScriptState(),
-      details.V8Value().As<v8::Object>()->Get(
-          V8String(scope.GetScriptState()->GetIsolate(), "transactionId")));
+      details.V8Value()
+          .As<v8::Object>()
+          ->Get(scope.GetContext(),
+                V8String(scope.GetIsolate(), "transactionId"))
+          .ToLocalChecked());
 
   ASSERT_TRUE(transaction_id.V8Value()->IsNumber());
   EXPECT_EQ(123, transaction_id.V8Value().As<v8::Number>()->Value());
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.cc
index 46819d16..113895b8 100644
--- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.cc
+++ b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_impl.cc
@@ -84,11 +84,6 @@
     return quic::WriteResult(quic::WRITE_STATUS_OK, bytes_written);
   }
 
-  bool IsWriteBlockedDataBuffered() const override {
-    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-    return false;
-  }
-
   bool IsWriteBlocked() const override {
     DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
     return !writable_;
diff --git a/third_party/blink/renderer/modules/remoteplayback/html_media_element_remote_playback.idl b/third_party/blink/renderer/modules/remoteplayback/html_media_element_remote_playback.idl
index d9ef2315..d171627 100644
--- a/third_party/blink/renderer/modules/remoteplayback/html_media_element_remote_playback.idl
+++ b/third_party/blink/renderer/modules/remoteplayback/html_media_element_remote_playback.idl
@@ -7,6 +7,6 @@
 [
     ImplementedAs=HTMLMediaElementRemotePlayback
 ] partial interface HTMLMediaElement {
-    [RuntimeEnabled=RemotePlayback] readonly attribute RemotePlayback remote;
+    [Measure, RuntimeEnabled=RemotePlayback] readonly attribute RemotePlayback remote;
     [CEReactions, Reflect, RuntimeEnabled=RemotePlayback] attribute boolean disableRemotePlayback;
 };
diff --git a/third_party/blink/renderer/modules/remoteplayback/remote_playback.idl b/third_party/blink/renderer/modules/remoteplayback/remote_playback.idl
index 250ab00..752ae0b 100644
--- a/third_party/blink/renderer/modules/remoteplayback/remote_playback.idl
+++ b/third_party/blink/renderer/modules/remoteplayback/remote_playback.idl
@@ -21,7 +21,7 @@
     attribute EventHandler onconnect;
     attribute EventHandler ondisconnect;
 
-    [CallWith=ScriptState] Promise<long> watchAvailability(RemotePlaybackAvailabilityCallback callback);
+    [Measure, CallWith=ScriptState] Promise<long> watchAvailability(RemotePlaybackAvailabilityCallback callback);
     [CallWith=ScriptState] Promise<void> cancelWatchAvailability(optional long id);
-    [CallWith=ScriptState] Promise<void> prompt();
+    [Measure, CallWith=ScriptState] Promise<void> prompt();
 };
diff --git a/third_party/blink/renderer/platform/exported/web_font.cc b/third_party/blink/renderer/platform/exported/web_font.cc
index 4e1dd3c..4c516d5 100644
--- a/third_party/blink/renderer/platform/exported/web_font.cc
+++ b/third_party/blink/renderer/platform/exported/web_font.cc
@@ -80,13 +80,10 @@
 void WebFont::DrawText(cc::PaintCanvas* canvas,
                        const WebTextRun& run,
                        const WebFloatPoint& left_baseline,
-                       SkColor color,
-                       const WebRect& clip) const {
+                       SkColor color) const {
   FontCachePurgePreventer font_cache_purge_preventer;
-  FloatRect text_clip_rect(clip);
   TextRun text_run(run);
   TextRunPaintInfo run_info(text_run);
-  run_info.bounds = text_clip_rect;
 
   PaintRecordBuilder builder;
   GraphicsContext& context = builder.Context();
@@ -95,7 +92,6 @@
     DrawingRecorder recorder(context, builder, DisplayItem::kWebFont);
     context.Save();
     context.SetFillColor(color);
-    context.Clip(text_clip_rect);
     context.DrawText(private_->GetFont(), run_info, left_baseline);
     context.Restore();
   }
diff --git a/third_party/blink/renderer/platform/fonts/font.cc b/third_party/blink/renderer/platform/fonts/font.cc
index 46448d2..804dc25 100644
--- a/third_party/blink/renderer/platform/fonts/font.cc
+++ b/third_party/blink/renderer/platform/fonts/font.cc
@@ -200,7 +200,6 @@
     subrun.SetDirectionalOverride(bidi_run->DirOverride(false));
 
     TextRunPaintInfo subrun_info(subrun);
-    subrun_info.bounds = run_info.bounds;
 
     ShapeResultBloberizer bloberizer(*this, device_scale_factor);
     ShapeResultBuffer buffer;
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc b/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc
index d6864da..ecba2b6 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc
@@ -255,7 +255,8 @@
       return ShapeToEnd(start, first_safe, range_start, range_end);
     }
   }
-  DCHECK_GT(break_opportunity.offset, start);
+  // It is critical to move forward, or callers may end up in an infinite loop.
+  CHECK_GT(break_opportunity.offset, start);
 
   // If the start offset is not at a safe-to-break boundary the content between
   // the start and the next safe-to-break boundary needs to be reshaped and the
@@ -281,50 +282,58 @@
 
   scoped_refptr<const ShapeResult> line_end_result;
   unsigned last_safe = break_opportunity.offset;
-  if (break_opportunity.offset > start) {
-    // If the previous valid break opportunity is not at a safe-to-break
-    // boundary reshape between the safe-to-break offset and the valid break
-    // offset. If the resulting width exceeds the available space the
-    // preceding boundary is tried until the available space is sufficient.
-    while (true) {
-      DCHECK_LE(first_safe, break_opportunity.offset);
-      last_safe = std::max(
-          result_->CachedPreviousSafeToBreakOffset(break_opportunity.offset),
-          first_safe);
-      DCHECK_LE(last_safe, break_opportunity.offset);
-      DCHECK_GE(last_safe, first_safe);
-      if (last_safe == break_opportunity.offset)
-        break;
-      DCHECK_LE(break_opportunity.offset, range_end);
-      if (is_overflow) {
-        line_end_result = Shape(last_safe, break_opportunity.offset);
-        break;
-      }
-      LayoutUnit safe_position = SnapStart(
-          result_->CachedPositionForOffset(last_safe - range_start), direction);
+  // If the previous valid break opportunity is not at a safe-to-break
+  // boundary reshape between the safe-to-break offset and the valid break
+  // offset. If the resulting width exceeds the available space the
+  // preceding boundary is tried until the available space is sufficient.
+  while (true) {
+    DCHECK_LE(first_safe, break_opportunity.offset);
+    last_safe = std::max(
+        result_->CachedPreviousSafeToBreakOffset(break_opportunity.offset),
+        first_safe);
+    DCHECK_LE(last_safe, break_opportunity.offset);
+    DCHECK_GE(last_safe, first_safe);
+    if (last_safe == break_opportunity.offset)
+      break;
+    DCHECK_LE(break_opportunity.offset, range_end);
+    if (is_overflow) {
       line_end_result = Shape(last_safe, break_opportunity.offset);
-      if (line_end_result->SnappedWidth() <=
-          FlipRtl(end_position - safe_position, direction))
-        break;
-
-      // Doesn't fit after the reshape. Try the previous break opportunity.
-      line_end_result = nullptr;
-      break_opportunity =
-          PreviousBreakOpportunity(break_opportunity.offset - 1, start);
-      if (break_opportunity.offset > start)
-        continue;
-
-      // No suitable break opportunity, not exceeding the available space,
-      // found. Any break opportunities beyond candidate_break won't fit
-      // either because the ShapeResult has the full context.
-      // This line will overflow, but there are multiple choices to break,
-      // because none can fit. The one after candidate_break is better for
-      // ligatures, but the one before is better for kernings.
-      break_opportunity = PreviousBreakOpportunity(candidate_break, start);
-      // Loop once more to compute last_safe for the new break opportunity.
-      is_overflow = true;
+      break;
     }
+    LayoutUnit safe_position = SnapStart(
+        result_->CachedPositionForOffset(last_safe - range_start), direction);
+    line_end_result = Shape(last_safe, break_opportunity.offset);
+    if (line_end_result->SnappedWidth() <=
+        FlipRtl(end_position - safe_position, direction))
+      break;
+
+    // Doesn't fit after the reshape. Try the previous break opportunity.
+    line_end_result = nullptr;
+    break_opportunity =
+        PreviousBreakOpportunity(break_opportunity.offset - 1, start);
+    if (break_opportunity.offset > start)
+      continue;
+
+    // No suitable break opportunity, not exceeding the available space,
+    // found. Any break opportunities beyond candidate_break won't fit
+    // either because the ShapeResult has the full context.
+    // This line will overflow, but there are multiple choices to break,
+    // because none can fit. The one after candidate_break is better for
+    // ligatures, but the one before is better for kernings.
+    break_opportunity = PreviousBreakOpportunity(candidate_break, start);
+    if (break_opportunity.offset <= start) {
+      break_opportunity = NextBreakOpportunity(
+          std::max(candidate_break, start + 1), start, range_end);
+      if (break_opportunity.offset >= range_end) {
+        result_out->break_offset = range_end;
+        return ShapeToEnd(start, first_safe, range_start, range_end);
+      }
+    }
+    // Loop once more to compute last_safe for the new break opportunity.
+    is_overflow = true;
   }
+  // It is critical to move forward, or callers may end up in an infinite loop.
+  CHECK_GT(break_opportunity.offset, start);
   DCHECK_GE(break_opportunity.offset, last_safe);
   DCHECK_EQ(break_opportunity.offset - start,
             (line_start_result ? line_start_result->NumCharacters() : 0) +
@@ -344,7 +353,6 @@
     segments[count++] = {line_end_result.get(), last_safe, max_length};
   auto line_result = ShapeResultView::Create(&segments[0], count);
 
-  DCHECK_GT(break_opportunity.offset, start);
   DCHECK_LE(break_opportunity.offset, range_end);
   DCHECK_EQ(break_opportunity.offset - start, line_result->NumCharacters());
 
diff --git a/third_party/blink/renderer/platform/fonts/text_run_paint_info.h b/third_party/blink/renderer/platform/fonts/text_run_paint_info.h
index 01d5332..260fbdb 100644
--- a/third_party/blink/renderer/platform/fonts/text_run_paint_info.h
+++ b/third_party/blink/renderer/platform/fonts/text_run_paint_info.h
@@ -21,7 +21,6 @@
   const TextRun& run;
   unsigned from;
   unsigned to;
-  FloatRect bounds;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index a3aa06fc..1914510 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -597,7 +597,6 @@
     },
     {
       name: "HeapUnifiedGarbageCollection",
-      status: "stable",
     },
     {
       name: "HrefTranslate",
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.cc b/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.cc
index b879587..0ee47f42 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.cc
@@ -14,11 +14,8 @@
 
 namespace {
 
-using QueueType = MainThreadTaskQueue::QueueType;
-
 #define FRAME_STATUS_PREFIX \
   "RendererScheduler.ExpectedQueueingTimeByFrameStatus2."
-#define TASK_QUEUE_PREFIX "RendererScheduler.ExpectedQueueingTimeByTaskQueue2."
 
 // On Windows, when a computer sleeps, we may end up getting extremely long
 // tasks or idling. We'll ignore tasks longer than |kInvalidPeriodThreshold|.
@@ -147,8 +144,6 @@
 
 void QueueingTimeEstimator::Calculator::UpdateStatusFromTaskQueue(
     MainThreadTaskQueue* queue) {
-  current_queue_type_ =
-      queue ? queue->queue_type() : MainThreadTaskQueue::QueueType::kOther;
   FrameScheduler* scheduler = queue ? queue->GetFrameScheduler() : nullptr;
   current_frame_status_ =
       scheduler ? GetFrameStatus(scheduler) : FrameStatus::kNone;
@@ -157,7 +152,6 @@
 void QueueingTimeEstimator::Calculator::AddQueueingTime(
     base::TimeDelta queueing_time) {
   step_expected_queueing_time_ += queueing_time;
-  eqt_by_queue_type_[static_cast<int>(current_queue_type_)] += queueing_time;
   eqt_by_frame_status_[static_cast<int>(current_frame_status_)] +=
       queueing_time;
 }
@@ -178,31 +172,6 @@
   if (!sliding_window_.IndexIsZero())
     return;
 
-// Report splits by task queue type.
-#define REPORT_BY_TASK_QUEUE(queue)                               \
-  client->OnReportFineGrainedExpectedQueueingTime(                \
-      TASK_QUEUE_PREFIX #queue,                                   \
-      eqt_by_queue_type_[static_cast<int>(QueueType::k##queue)] / \
-          steps_per_window_);
-  REPORT_BY_TASK_QUEUE(Default)
-  REPORT_BY_TASK_QUEUE(Unthrottled)
-  REPORT_BY_TASK_QUEUE(FrameLoading)
-  REPORT_BY_TASK_QUEUE(Compositor)
-  REPORT_BY_TASK_QUEUE(FrameThrottleable)
-  REPORT_BY_TASK_QUEUE(FramePausable)
-#undef REPORT_BY_TASK_QUEUE
-  client->OnReportFineGrainedExpectedQueueingTime(
-      TASK_QUEUE_PREFIX "Other",
-      (eqt_by_queue_type_[static_cast<int>(QueueType::kControl)] +
-       eqt_by_queue_type_[static_cast<int>(QueueType::kIdle)] +
-       eqt_by_queue_type_[static_cast<int>(QueueType::kTest)] +
-       eqt_by_queue_type_[static_cast<int>(QueueType::kFrameLoadingControl)] +
-       eqt_by_queue_type_[static_cast<int>(QueueType::kFrameDeferrable)] +
-       eqt_by_queue_type_[static_cast<int>(QueueType::kFrameUnpausable)] +
-       eqt_by_queue_type_[static_cast<int>(QueueType::kV8)] +
-       eqt_by_queue_type_[static_cast<int>(QueueType::kOther)]) /
-          steps_per_window_);
-
 // Report splits by frame status.
 #define REPORT_BY_FRAME_TYPE(frame)                                            \
   client->OnReportFineGrainedExpectedQueueingTime(                             \
@@ -236,8 +205,6 @@
       (eqt_by_frame_status_[static_cast<int>(FrameStatus::kNone)] +
        eqt_by_frame_status_[static_cast<int>(FrameStatus::kDetached)]) /
           steps_per_window_);
-  std::fill(eqt_by_queue_type_.begin(), eqt_by_queue_type_.end(),
-            base::TimeDelta());
   std::fill(eqt_by_frame_status_.begin(), eqt_by_frame_status_.end(),
             base::TimeDelta());
 }
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h b/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h
index ec1d4da..d8554dd 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h
@@ -92,13 +92,6 @@
     base::TimeDelta step_expected_queueing_time_;
     RunningAverage sliding_window_;
 
-    // Variables to split Expected Queueing Time by task queue type.
-    std::array<base::TimeDelta,
-               static_cast<int>(MainThreadTaskQueue::QueueType::kCount)>
-        eqt_by_queue_type_;
-    MainThreadTaskQueue::QueueType current_queue_type_ =
-        MainThreadTaskQueue::QueueType::kOther;
-
     // Variables to split Expected Queueing Time by frame type.
     std::array<base::TimeDelta, static_cast<int>(FrameStatus::kCount)>
         eqt_by_frame_status_;
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator_unittest.cc
index 1d435fa..2706ac2 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator_unittest.cc
@@ -58,8 +58,6 @@
       // Add up the reported split EQTs for that window.
       for (const auto& entry : client.split_eqts())
         sum += entry.second[window - 1];
-      // Divide sum by two because we're also adding the split by frame type.
-      sum /= 2.0;
       // Compare the split sum and the reported EQT for the disjoint window.
       EXPECT_EQ(expected_sums[window - 1], sum);
       EXPECT_EQ(expected_sums[window - 1],
@@ -544,185 +542,6 @@
 }
 
 // Split ExpectedQueueingTime only reports once per disjoint window. The
-// following is a detailed explanation of EQT per window and task queue:
-// Window 1: A 3000ms default queue task contributes 900 to that EQT.
-// Window 2: After 3000ms, the first 2000ms from a 3000ms default task: 800 EQT
-// for that.
-// Window 3: The remaining 100 EQT for default type. Also 1000ms tasks (which
-// contribute 100) for FrameLoading, FrameThrottleable, and Unthrottled.
-// Window 4: 600 ms tasks (which contribute 36) for each of the buckets except
-// other. Two 300 ms (each contributing 9) and one 200 ms tasks (contributes 4)
-// for the other bucket.
-TEST_F(QueueingTimeEstimatorTest, SplitEQTByTaskQueueType) {
-  QueueingTimeEstimatorForTest estimator(
-      &client, base::TimeDelta::FromSeconds(5), 5, time);
-  time += base::TimeDelta::FromMilliseconds(5000);
-  // Dummy task to initialize the estimator.
-  estimator.OnExecutionStarted(time, nullptr);
-  estimator.OnExecutionStopped(time);
-
-  // Beginning of window 1.
-  time += base::TimeDelta::FromMilliseconds(500);
-  scoped_refptr<MainThreadTaskQueueForTest> default_queue(
-      new MainThreadTaskQueueForTest(QueueType::kDefault));
-  estimator.OnExecutionStarted(time, default_queue.get());
-  time += base::TimeDelta::FromMilliseconds(3000);
-  estimator.OnExecutionStopped(time);
-
-  time += base::TimeDelta::FromMilliseconds(1500);
-
-  // Beginning of window 2.
-  time += base::TimeDelta::FromMilliseconds(3000);
-  estimator.OnExecutionStarted(time, default_queue.get());
-  time += base::TimeDelta::FromMilliseconds(3000);
-  // 1000 ms after beginning of window 3.
-  estimator.OnExecutionStopped(time);
-
-  time += base::TimeDelta::FromMilliseconds(1000);
-  scoped_refptr<MainThreadTaskQueueForTest> frame_loading_queue(
-      new MainThreadTaskQueueForTest(QueueType::kFrameLoading));
-  scoped_refptr<MainThreadTaskQueueForTest> frame_throttleable_queue(
-      new MainThreadTaskQueueForTest(QueueType::kFrameThrottleable));
-  scoped_refptr<MainThreadTaskQueueForTest> unthrottled_queue(
-      new MainThreadTaskQueueForTest(QueueType::kUnthrottled));
-  MainThreadTaskQueue* queues_for_thousand[] = {frame_loading_queue.get(),
-                                                frame_throttleable_queue.get(),
-                                                unthrottled_queue.get()};
-  for (auto* queue : queues_for_thousand) {
-    estimator.OnExecutionStarted(time, queue);
-    time += base::TimeDelta::FromMilliseconds(1000);
-    estimator.OnExecutionStopped(time);
-  }
-
-  // Beginning of window 4.
-  scoped_refptr<MainThreadTaskQueueForTest> frame_pausable_queue(
-      new MainThreadTaskQueueForTest(QueueType::kFramePausable));
-  scoped_refptr<MainThreadTaskQueueForTest> compositor_queue(
-      new MainThreadTaskQueueForTest(QueueType::kCompositor));
-  MainThreadTaskQueue* queues_for_six_hundred[] = {
-      default_queue.get(),
-      frame_loading_queue.get(),
-      frame_throttleable_queue.get(),
-      frame_pausable_queue.get(),
-      unthrottled_queue.get(),
-      compositor_queue.get()};
-  for (auto* queue : queues_for_six_hundred) {
-    estimator.OnExecutionStarted(time, queue);
-    time += base::TimeDelta::FromMilliseconds(600);
-    estimator.OnExecutionStopped(time);
-  }
-  time += base::TimeDelta::FromMilliseconds(600);
-
-  // The following task contributes to "Other" because kControl is not a
-  // supported queue type.
-  scoped_refptr<MainThreadTaskQueueForTest> control_queue(
-      new MainThreadTaskQueueForTest(QueueType::kControl));
-  estimator.OnExecutionStarted(time, control_queue.get());
-  time += base::TimeDelta::FromMilliseconds(300);
-  estimator.OnExecutionStopped(time);
-
-  // The following task contributes to "Other" because kTest is not a supported
-  // queue type.
-  scoped_refptr<MainThreadTaskQueueForTest> test_queue(
-      new MainThreadTaskQueueForTest(QueueType::kTest));
-  estimator.OnExecutionStarted(time, test_queue.get());
-  time += base::TimeDelta::FromMilliseconds(300);
-  estimator.OnExecutionStopped(time);
-
-  // The following task contributes to "Other" because there is no task queue.
-  estimator.OnExecutionStarted(time, nullptr);
-  time += base::TimeDelta::FromMilliseconds(200);
-  estimator.OnExecutionStopped(time);
-
-  // End of window 4. Now check the vectors per task queue type.
-  EXPECT_THAT(client.QueueTypeValues(QueueType::kDefault),
-              testing::ElementsAre(base::TimeDelta::FromMilliseconds(900),
-                                   base::TimeDelta::FromMilliseconds(800),
-                                   base::TimeDelta::FromMilliseconds(100),
-                                   base::TimeDelta::FromMilliseconds(36)));
-  // The 800 and 900 values get grouped into a single bucket.
-  std::vector<BucketExpectation> expected = {{36, 1}, {100, 1}, {800, 2}};
-  TestHistogram("RendererScheduler.ExpectedQueueingTimeByTaskQueue2.Default", 4,
-                GetFineGrained(expected));
-
-  EXPECT_THAT(client.QueueTypeValues(QueueType::kFrameLoading),
-              testing::ElementsAre(base::TimeDelta::FromMilliseconds(0),
-                                   base::TimeDelta::FromMilliseconds(0),
-                                   base::TimeDelta::FromMilliseconds(100),
-                                   base::TimeDelta::FromMilliseconds(36)));
-  expected = {{0, 2}, {36, 1}, {100, 1}};
-  TestHistogram(
-      "RendererScheduler.ExpectedQueueingTimeByTaskQueue2.FrameLoading", 4,
-      GetFineGrained(expected));
-
-  EXPECT_THAT(client.QueueTypeValues(QueueType::kFrameThrottleable),
-              testing::ElementsAre(base::TimeDelta::FromMilliseconds(0),
-                                   base::TimeDelta::FromMilliseconds(0),
-                                   base::TimeDelta::FromMilliseconds(100),
-                                   base::TimeDelta::FromMilliseconds(36)));
-  expected = {{0, 2}, {36, 1}, {100, 1}};
-  TestHistogram(
-      "RendererScheduler.ExpectedQueueingTimeByTaskQueue2.FrameThrottleable", 4,
-      GetFineGrained(expected));
-
-  EXPECT_THAT(client.QueueTypeValues(QueueType::kFramePausable),
-              testing::ElementsAre(base::TimeDelta::FromMilliseconds(0),
-                                   base::TimeDelta::FromMilliseconds(0),
-                                   base::TimeDelta::FromMilliseconds(0),
-                                   base::TimeDelta::FromMilliseconds(36)));
-  expected = {{0, 3}, {36, 1}};
-  TestHistogram(
-      "RendererScheduler.ExpectedQueueingTimeByTaskQueue2.FramePausable", 4,
-      GetFineGrained(expected));
-
-  EXPECT_THAT(client.QueueTypeValues(QueueType::kUnthrottled),
-              testing::ElementsAre(base::TimeDelta::FromMilliseconds(0),
-                                   base::TimeDelta::FromMilliseconds(0),
-                                   base::TimeDelta::FromMilliseconds(100),
-                                   base::TimeDelta::FromMilliseconds(36)));
-  expected = {{0, 2}, {36, 1}, {100, 1}};
-  TestHistogram(
-      "RendererScheduler.ExpectedQueueingTimeByTaskQueue2.Unthrottled", 4,
-      GetFineGrained(expected));
-
-  EXPECT_THAT(client.QueueTypeValues(QueueType::kCompositor),
-              testing::ElementsAre(base::TimeDelta::FromMilliseconds(0),
-                                   base::TimeDelta::FromMilliseconds(0),
-                                   base::TimeDelta::FromMilliseconds(0),
-                                   base::TimeDelta::FromMilliseconds(36)));
-  expected = {{0, 3}, {36, 1}};
-  TestHistogram("RendererScheduler.ExpectedQueueingTimeByTaskQueue2.Compositor",
-                4, GetFineGrained(expected));
-
-  EXPECT_THAT(client.QueueTypeValues(QueueType::kOther),
-              testing::ElementsAre(base::TimeDelta::FromMilliseconds(0),
-                                   base::TimeDelta::FromMilliseconds(0),
-                                   base::TimeDelta::FromMilliseconds(0),
-                                   base::TimeDelta::FromMilliseconds(22)));
-  expected = {{0, 3}, {22, 1}};
-  TestHistogram("RendererScheduler.ExpectedQueueingTimeByTaskQueue2.Other", 4,
-                GetFineGrained(expected));
-
-  // Check that the sum of split EQT equals the total EQT for each window.
-  base::TimeDelta expected_sums[] = {base::TimeDelta::FromMilliseconds(900),
-                                     base::TimeDelta::FromMilliseconds(800),
-                                     base::TimeDelta::FromMilliseconds(400),
-                                     base::TimeDelta::FromMilliseconds(238)};
-  EXPECT_THAT(client.FrameStatusValues(FrameStatus::kNone),
-              testing::ElementsAreArray(expected_sums));
-  expected = {{238, 1}, {400, 1}, {800, 1}, {900, 1}};
-  // The 800 and 900 values end up grouped up in the fine-grained version.
-  std::vector<BucketExpectation> fine_grained = {
-      {238 * 1000, 1}, {400 * 1000, 1}, {800 * 1000, 2}};
-  TestHistogram("RendererScheduler.ExpectedQueueingTimeByFrameStatus2.Other", 4,
-                fine_grained);
-  TestHistogram("RendererScheduler.ExpectedTaskQueueingDuration", 4, expected);
-  TestHistogram("RendererScheduler.ExpectedTaskQueueingDuration3", 4,
-                fine_grained);
-  TestSplitSumsTotal(expected_sums, 5);
-}
-
-// Split ExpectedQueueingTime only reports once per disjoint window. The
 // following is a detailed explanation of EQT per window and frame type:
 // Window 1: A 3000ms task in a background main frame contributes 900 to that
 // EQT.
@@ -745,7 +564,7 @@
   estimator.OnExecutionStarted(time, nullptr);
   estimator.OnExecutionStopped(time);
   scoped_refptr<MainThreadTaskQueueForTest> queue1(
-      new MainThreadTaskQueueForTest(QueueType::kTest));
+      new MainThreadTaskQueueForTest(MainThreadTaskQueue::QueueType::kTest));
 
   // Beginning of window 1.
   time += base::TimeDelta::FromMilliseconds(500);
@@ -774,7 +593,7 @@
   estimator.OnExecutionStopped(time);
 
   scoped_refptr<MainThreadTaskQueueForTest> queue2(
-      new MainThreadTaskQueueForTest(QueueType::kTest));
+      new MainThreadTaskQueueForTest(MainThreadTaskQueue::QueueType::kTest));
   queue2->SetFrameSchedulerForTest(frame2.get());
   time += base::TimeDelta::FromMilliseconds(1000);
   estimator.OnExecutionStarted(time, queue2.get());
@@ -973,22 +792,18 @@
   TestHistogram("RendererScheduler.ExpectedQueueingTimeByFrameStatus2.Other", 5,
                 GetFineGrained(expected));
 
+  expected = {{226, 1}, {400, 1}, {800, 1}, {900, 1}, {1700, 1}};
+  std::vector<BucketExpectation> fine_grained = {
+      {226 * 1000, 1}, {400 * 1000, 1}, {800 * 1000, 2}, {1700 * 1000, 1}};
+  TestHistogram("RendererScheduler.ExpectedTaskQueueingDuration", 5, expected);
+  TestHistogram("RendererScheduler.ExpectedTaskQueueingDuration3", 5,
+                fine_grained);
   // Check that the sum of split EQT equals the total EQT for each window.
   base::TimeDelta expected_sums[] = {base::TimeDelta::FromMilliseconds(900),
                                      base::TimeDelta::FromMilliseconds(800),
                                      base::TimeDelta::FromMilliseconds(1700),
                                      base::TimeDelta::FromMilliseconds(400),
                                      base::TimeDelta::FromMilliseconds(226)};
-  EXPECT_THAT(client.QueueTypeValues(QueueType::kOther),
-              testing::ElementsAreArray(expected_sums));
-  expected = {{226, 1}, {400, 1}, {800, 1}, {900, 1}, {1700, 1}};
-  std::vector<BucketExpectation> fine_grained = {
-      {226 * 1000, 1}, {400 * 1000, 1}, {800 * 1000, 2}, {1700 * 1000, 1}};
-  TestHistogram("RendererScheduler.ExpectedQueueingTimeByTaskQueue2.Other", 5,
-                fine_grained);
-  TestHistogram("RendererScheduler.ExpectedTaskQueueingDuration", 5, expected);
-  TestHistogram("RendererScheduler.ExpectedTaskQueueingDuration3", 5,
-                fine_grained);
   TestSplitSumsTotal(expected_sums, 6);
 }
 
diff --git a/third_party/blink/renderer/platform/scheduler/test/renderer_scheduler_test_support.cc b/third_party/blink/renderer/platform/scheduler/test/renderer_scheduler_test_support.cc
index e1027b1..e7ffead 100644
--- a/third_party/blink/renderer/platform/scheduler/test/renderer_scheduler_test_support.cc
+++ b/third_party/blink/renderer/platform/scheduler/test/renderer_scheduler_test_support.cc
@@ -7,21 +7,212 @@
 #include <memory>
 
 #include "base/single_thread_task_runner.h"
-#include "base/task/sequence_manager/test/lazy_thread_controller_for_test.h"
 #include "base/task/sequence_manager/test/sequence_manager_for_test.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/page_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
 
 namespace blink {
 namespace scheduler {
 
+namespace {
+
+// TODO(altimin,yutak): Merge with SimpleThread in platform.cc.
+class SimpleThread : public Thread {
+ public:
+  explicit SimpleThread(ThreadScheduler* scheduler) : scheduler_(scheduler) {}
+  ~SimpleThread() override {}
+
+  scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() const override {
+    return base::ThreadTaskRunnerHandle::Get();
+  }
+
+  ThreadScheduler* Scheduler() override { return scheduler_; }
+
+  void Init() override {}
+  bool IsCurrentThread() const { return WTF::IsMainThread(); }
+
+ private:
+  ThreadScheduler* scheduler_;
+
+  DISALLOW_COPY_AND_ASSIGN(SimpleThread);
+};
+
+class SimpleFrameScheduler : public FrameScheduler {
+ public:
+  explicit SimpleFrameScheduler(PageScheduler* page_scheduler)
+      : page_scheduler_(page_scheduler) {}
+  ~SimpleFrameScheduler() override {}
+
+  scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) override {
+    DCHECK(WTF::IsMainThread());
+    return base::ThreadTaskRunnerHandle::Get();
+  }
+
+  PageScheduler* GetPageScheduler() const override { return page_scheduler_; }
+
+  void SetFrameVisible(bool) override {}
+  bool IsFrameVisible() const override { return true; }
+  bool IsPageVisible() const override { return true; }
+  void SetPaused(bool) override {}
+  void SetCrossOrigin(bool) override {}
+  bool IsCrossOrigin() const override { return false; }
+  void SetIsAdFrame() override {}
+  bool IsAdFrame() const override { return false; }
+  void TraceUrlChange(const String&) override {}
+  FrameType GetFrameType() const override { return FrameType::kMainFrame; }
+  WebScopedVirtualTimePauser CreateWebScopedVirtualTimePauser(
+      const String& name,
+      WebScopedVirtualTimePauser::VirtualTaskDuration) override {
+    return WebScopedVirtualTimePauser();
+  }
+  void DidStartProvisionalLoad(bool is_main_frame) override {}
+  void DidCommitProvisionalLoad(bool, bool, bool) override {}
+  void OnFirstMeaningfulPaint() override {}
+  bool IsExemptFromBudgetBasedThrottling() const override { return false; }
+  std::unique_ptr<blink::mojom::blink::PauseSubresourceLoadingHandle>
+  GetPauseSubresourceLoadingHandle() override {
+    return nullptr;
+  }
+  std::unique_ptr<ActiveConnectionHandle> OnActiveConnectionCreated() override {
+    return nullptr;
+  }
+  std::unique_ptr<WebResourceLoadingTaskRunnerHandle>
+  CreateResourceLoadingTaskRunnerHandle() override {
+    return WebResourceLoadingTaskRunnerHandle::CreateUnprioritized(
+        base::ThreadTaskRunnerHandle::Get());
+  }
+  ukm::SourceId GetUkmSourceId() override { return ukm::kInvalidSourceId; }
+
+ private:
+  PageScheduler* page_scheduler_;
+
+  DISALLOW_COPY_AND_ASSIGN(SimpleFrameScheduler);
+};
+
+class SimplePageScheduler : public PageScheduler {
+ public:
+  SimplePageScheduler() {}
+  ~SimplePageScheduler() override {}
+
+  std::unique_ptr<FrameScheduler> CreateFrameScheduler(
+      FrameScheduler::Delegate* delegate,
+      BlameContext*,
+      FrameScheduler::FrameType) override {
+    return std::make_unique<SimpleFrameScheduler>(this);
+  }
+
+  void SetPageVisible(bool) override {}
+  void SetPageFrozen(bool) override {}
+  void SetKeepActive(bool) override {}
+  bool IsMainFrameLocal() const override { return true; }
+  void SetIsMainFrameLocal(bool) override {}
+  base::TimeTicks EnableVirtualTime() override { return base::TimeTicks(); }
+  void DisableVirtualTimeForTesting() override {}
+  bool VirtualTimeAllowedToAdvance() const override { return true; }
+  void SetInitialVirtualTime(base::Time) override {}
+  void SetInitialVirtualTimeOffset(base::TimeDelta) override {}
+  void SetVirtualTimePolicy(VirtualTimePolicy) override {}
+  void GrantVirtualTimeBudget(base::TimeDelta, base::OnceClosure) override {}
+  void SetMaxVirtualTimeTaskStarvationCount(int) override {}
+  void AudioStateChanged(bool is_audio_playing) override {}
+  bool IsAudioPlaying() const override { return false; }
+  bool IsExemptFromBudgetBasedThrottling() const override { return false; }
+  bool HasActiveConnectionForTest() const override { return false; }
+  bool RequestBeginMainFrameNotExpected(bool) override { return false; }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SimplePageScheduler);
+};
+
+class SimpleMainThreadScheduler : public WebThreadScheduler,
+                                  public ThreadScheduler {
+ public:
+  SimpleMainThreadScheduler() {}
+  ~SimpleMainThreadScheduler() override {}
+
+  // WebThreadScheduler implementation:
+  void Shutdown() override {}
+
+  scoped_refptr<base::SingleThreadTaskRunner> DefaultTaskRunner() override {
+    DCHECK(WTF::IsMainThread());
+    return base::ThreadTaskRunnerHandle::Get();
+  }
+
+  scoped_refptr<base::SingleThreadTaskRunner> DeprecatedDefaultTaskRunner()
+      override {
+    DCHECK(WTF::IsMainThread());
+    return base::ThreadTaskRunnerHandle::Get();
+  }
+
+  scoped_refptr<base::SingleThreadTaskRunner> CompositorTaskRunner() override {
+    DCHECK(WTF::IsMainThread());
+    return base::ThreadTaskRunnerHandle::Get();
+  }
+
+  scoped_refptr<base::SingleThreadTaskRunner> InputTaskRunner() override {
+    DCHECK(WTF::IsMainThread());
+    return base::ThreadTaskRunnerHandle::Get();
+  }
+
+  scoped_refptr<base::SingleThreadTaskRunner> IPCTaskRunner() override {
+    DCHECK(WTF::IsMainThread());
+    return base::ThreadTaskRunnerHandle::Get();
+  }
+
+  scoped_refptr<base::SingleThreadTaskRunner> CleanupTaskRunner() override {
+    DCHECK(WTF::IsMainThread());
+    return base::ThreadTaskRunnerHandle::Get();
+  }
+
+  scoped_refptr<base::SingleThreadTaskRunner> V8TaskRunner() override {
+    DCHECK(WTF::IsMainThread());
+    return base::ThreadTaskRunnerHandle::Get();
+  }
+
+  std::unique_ptr<Thread> CreateMainThread() override {
+    return std::make_unique<SimpleThread>(this);
+  }
+
+  std::unique_ptr<PageScheduler> CreatePageScheduler(
+      PageScheduler::Delegate*) override {
+    return std::make_unique<SimplePageScheduler>();
+  }
+
+  // ThreadScheduler implementation:
+  bool ShouldYieldForHighPriorityWork() override { return false; }
+  bool CanExceedIdleDeadlineIfRequired() const override { return false; }
+  void PostIdleTask(const base::Location&, Thread::IdleTask) override {
+    // NOTREACHED();
+  }
+  void PostNonNestableIdleTask(const base::Location&,
+                               Thread::IdleTask) override {
+    // NOTREACHED();
+  }
+  void AddRAILModeObserver(WebRAILModeObserver*) override {}
+  std::unique_ptr<WebThreadScheduler::RendererPauseHandle> PauseScheduler()
+      override {
+    return nullptr;
+  }
+  base::TimeTicks MonotonicallyIncreasingVirtualTime() override {
+    return base::TimeTicks::Now();
+  }
+  void AddTaskObserver(base::MessageLoop::TaskObserver*) override {}
+  void RemoveTaskObserver(base::MessageLoop::TaskObserver*) override {}
+  NonMainThreadSchedulerImpl* AsNonMainThreadScheduler() override {
+    return nullptr;
+  }
+};
+
+}  // namespace
+
 std::unique_ptr<WebThreadScheduler> CreateWebMainThreadSchedulerForTests() {
-  return std::make_unique<scheduler::MainThreadSchedulerImpl>(
-      base::sequence_manager::SequenceManagerForTest::Create(
-          std::make_unique<
-              base::sequence_manager::LazyThreadControllerForTest>()),
-      base::nullopt);
+  return std::make_unique<SimpleMainThreadScheduler>();
 }
 
 void RunIdleTasksForTesting(WebThreadScheduler* scheduler,
diff --git a/third_party/blink/renderer/platform/scheduler/test/test_queueing_time_estimator_client.cc b/third_party/blink/renderer/platform/scheduler/test/test_queueing_time_estimator_client.cc
index 20bb1b5..22489f2 100644
--- a/third_party/blink/renderer/platform/scheduler/test/test_queueing_time_estimator_client.cc
+++ b/third_party/blink/renderer/platform/scheduler/test/test_queueing_time_estimator_client.cc
@@ -16,38 +16,6 @@
 // This is a duplicate of the defines in queueing_time_estimator.cc.
 #define FRAME_STATUS_PREFIX \
   "RendererScheduler.ExpectedQueueingTimeByFrameStatus2."
-#define TASK_QUEUE_PREFIX "RendererScheduler.ExpectedQueueingTimeByTaskQueue2."
-
-const char* GetReportingMessageFromQueueType(
-    MainThreadTaskQueue::QueueType queue_type) {
-  switch (queue_type) {
-    case MainThreadTaskQueue::QueueType::kDefault:
-      return TASK_QUEUE_PREFIX "Default";
-    case MainThreadTaskQueue::QueueType::kUnthrottled:
-      return TASK_QUEUE_PREFIX "Unthrottled";
-    case MainThreadTaskQueue::QueueType::kFrameLoading:
-      return TASK_QUEUE_PREFIX "FrameLoading";
-    case MainThreadTaskQueue::QueueType::kCompositor:
-      return TASK_QUEUE_PREFIX "Compositor";
-    case MainThreadTaskQueue::QueueType::kFrameThrottleable:
-      return TASK_QUEUE_PREFIX "FrameThrottleable";
-    case MainThreadTaskQueue::QueueType::kFramePausable:
-      return TASK_QUEUE_PREFIX "FramePausable";
-    case MainThreadTaskQueue::QueueType::kControl:
-    case MainThreadTaskQueue::QueueType::kIdle:
-    case MainThreadTaskQueue::QueueType::kTest:
-    case MainThreadTaskQueue::QueueType::kFrameLoadingControl:
-    case MainThreadTaskQueue::QueueType::kFrameDeferrable:
-    case MainThreadTaskQueue::QueueType::kFrameUnpausable:
-    case MainThreadTaskQueue::QueueType::kV8:
-    case MainThreadTaskQueue::QueueType::kOther:
-    case MainThreadTaskQueue::QueueType::kCount:
-    // Using default here as well because there are some values less than COUNT
-    // that have been removed and do not correspond to any QueueType.
-    default:
-      return TASK_QUEUE_PREFIX "Other";
-  }
-}
 
 const char* GetReportingMessageFromFrameStatus(FrameStatus frame_status) {
   switch (frame_status) {
@@ -127,11 +95,6 @@
 }
 
 const std::vector<base::TimeDelta>&
-TestQueueingTimeEstimatorClient::QueueTypeValues(QueueType queue_type) {
-  return split_eqts_[GetReportingMessageFromQueueType(queue_type)];
-}
-
-const std::vector<base::TimeDelta>&
 TestQueueingTimeEstimatorClient::FrameStatusValues(FrameStatus frame_status) {
   return split_eqts_[GetReportingMessageFromFrameStatus(frame_status)];
 }
diff --git a/third_party/blink/renderer/platform/scheduler/test/test_queueing_time_estimator_client.h b/third_party/blink/renderer/platform/scheduler/test/test_queueing_time_estimator_client.h
index c324567..a37aa3d 100644
--- a/third_party/blink/renderer/platform/scheduler/test/test_queueing_time_estimator_client.h
+++ b/third_party/blink/renderer/platform/scheduler/test/test_queueing_time_estimator_client.h
@@ -13,8 +13,6 @@
 namespace blink {
 namespace scheduler {
 
-using QueueType = MainThreadTaskQueue::QueueType;
-
 class TestQueueingTimeEstimatorClient : public QueueingTimeEstimator::Client {
  public:
   // QueueingTimeEstimator::Client implementation:
@@ -30,7 +28,6 @@
   const std::map<std::string, std::vector<base::TimeDelta>>& split_eqts() {
     return split_eqts_;
   }
-  const std::vector<base::TimeDelta>& QueueTypeValues(QueueType queue_type);
   const std::vector<base::TimeDelta>& FrameStatusValues(
       FrameStatus frame_status);
 
diff --git a/third_party/blink/renderer/platform/text/text_break_iterator.cc b/third_party/blink/renderer/platform/text/text_break_iterator.cc
index 731a525..5f61280 100644
--- a/third_party/blink/renderer/platform/text/text_break_iterator.cc
+++ b/third_party/blink/renderer/platform/text/text_break_iterator.cc
@@ -303,6 +303,7 @@
     int len) const {
   DCHECK_GE(pos, 0);
   DCHECK_GE(static_cast<unsigned>(pos), start_offset_);
+  DCHECK_LE(pos, len);
   int next_break = -1;
   UChar last_last_ch = pos > 1 ? str[pos - 2] : SecondToLastCharacter();
   UChar last_ch = pos > 0 ? str[pos - 1] : LastCharacter();
@@ -446,6 +447,7 @@
 }
 
 unsigned LazyLineBreakIterator::NextBreakOpportunity(unsigned offset) const {
+  DCHECK_LE(offset, string_.length());
   int next_break = NextBreakablePosition(offset, break_type_);
   DCHECK_GE(next_break, 0);
   return next_break;
@@ -453,6 +455,7 @@
 
 unsigned LazyLineBreakIterator::NextBreakOpportunity(unsigned offset,
                                                      unsigned len) const {
+  DCHECK_LE(offset, string_.length());
   DCHECK_LE(len, string_.length());
   int next_break = NextBreakablePosition(offset, break_type_, len);
   DCHECK_GE(next_break, 0);
diff --git a/third_party/blink/renderer/platform/wtf/text/string_impl.h b/third_party/blink/renderer/platform/wtf/text/string_impl.h
index 4a6a7a1b..9857e9b 100644
--- a/third_party/blink/renderer/platform/wtf/text/string_impl.h
+++ b/third_party/blink/renderer/platform/wtf/text/string_impl.h
@@ -450,12 +450,6 @@
         .ValueOrDie();
   }
 
-  template <>
-  size_t AllocationSize<LChar>(wtf_size_t length) {
-    static_assert(sizeof(LChar) == 1, "sizeof(LChar) should be 1.");
-    return base::CheckAdd(sizeof(StringImpl), length).ValueOrDie();
-  }
-
   scoped_refptr<StringImpl> Replace(UChar pattern,
                                     const LChar* replacement,
                                     wtf_size_t replacement_length);
@@ -513,6 +507,14 @@
   return Characters16();
 }
 
+// The following template specialization can be moved to the class declaration
+// once we officially switch to C++17 (we need C++ DR727 to be implemented).
+template <>
+ALWAYS_INLINE size_t StringImpl::AllocationSize<LChar>(wtf_size_t length) {
+  static_assert(sizeof(LChar) == 1, "sizeof(LChar) should be 1.");
+  return base::CheckAdd(sizeof(StringImpl), length).ValueOrDie();
+}
+
 WTF_EXPORT bool Equal(const StringImpl*, const StringImpl*);
 WTF_EXPORT bool Equal(const StringImpl*, const LChar*);
 inline bool Equal(const StringImpl* a, const char* b) {
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
index c11c0aa..d6e3678 100644
--- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
+++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
@@ -167,7 +167,6 @@
 Bug(none) fast/webgl/pixelated.html [ Failure ]
 Bug(none) images/color-profile-svg-foreign-object.html [ Failure ]
 Bug(none) fast/multicol/insane-column-count-and-padding-nested-crash.html [ Crash ]
-Bug(none) fast/scroll-behavior/overflow-scroll-root-frame-animates.html [ Timeout ]
 Bug(none) fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer.html [ Failure ]
 Bug(none) fast/sub-pixel/should-not-repaint-subpixel-composited-layer.html [ Failure ]
 Bug(none) fast/sub-pixel/transformed-iframe-copy-on-scroll.html [ Failure ]
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
index ce8dd06..ca32327a 100644
--- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=LayoutNG
@@ -33,6 +33,7 @@
 
 # New passes
 crbug.com/774229 editing/pasteboard/copy-paste-white-space.html [ Pass ]
+crbug.com/899868 editing/selection/mouse/drag_over_text_transform.html [ Pass ]
 crbug.com/591099 external/wpt/css/CSS2/floats-clear/no-clearance-adjoining-opposite-float.html [ Pass ]
 crbug.com/591099 external/wpt/css/CSS2/floats-clear/no-clearance-due-to-large-margin-after-left-right.html [ Pass ]
 crbug.com/877946 external/wpt/css/CSS2/linebox/anonymous-inline-inherit-001.html [ Pass ]
@@ -324,7 +325,6 @@
 crbug.com/591099 scrollbars/auto-scrollbar-fit-content.html [ Failure ]
 crbug.com/927467 svg/dom/parent-view-layout-crash.html [ Crash Pass ]
 crbug.com/591099 svg/zoom/page/zoom-svg-float-border-padding.xml [ Pass ]
-crbug.com/927467 tables/mozilla/bugs/bug113235-3.html [ Crash ]
 crbug.com/591099 tables/mozilla/bugs/bug14159-1.html [ Pass ]
 crbug.com/591099 virtual/android/rootscroller/set-root-scroller.html [ Pass ]
 crbug.com/591099 virtual/android/rootscroller/set-rootscroller-before-load.html [ Pass ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 29c95536..93601924 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -640,6 +640,7 @@
 
 # Tests for LayoutNG to pass, but not planned to fix for pre-LayoutNG.
 crbug.com/774229 editing/pasteboard/copy-paste-white-space.html [ Failure ]
+crbug.com/899868 editing/selection/mouse/drag_over_text_transform.html [ Crash Failure ]
 crbug.com/855279 fast/css/text-overflow-ellipsis-vertical-hittest.html [ Failure ]
 crbug.com/591099 fast/css-intrinsic-dimensions/height-positioned.html [ Failure ]
 crbug.com/899902 fast/text/ellipsis-with-self-painting-layer.html [ Failure ]
@@ -3111,7 +3112,6 @@
 crbug.com/626703 external/wpt/referrer-policy/generic/sandboxed-iframe-with-opaque-origin.html [ Timeout ]
 crbug.com/626703 virtual/outofblink-cors-ns/external/wpt/referrer-policy/generic/sandboxed-iframe-with-opaque-origin.html [ Timeout ]
 crbug.com/626703 external/wpt/css/css-values/vh-support-atviewport.html [ Failure ]
-crbug.com/626703 external/wpt/css/css-backgrounds/border-image-calc.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/boundary-shaping/boundary-shaping-005.html [ Failure ]
 crbug.com/626703 external/wpt/css/CSS2/text/white-space-nowrap-attribute-001.xht [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/boundary-shaping/boundary-shaping-010.html [ Failure ]
@@ -5981,7 +5981,6 @@
 # Race: The RTCIceConnectionState can become "connected" before getStats()
 # returns candidate-pair whose state is "succeeded", this sounds like a
 # contradiction.
-crbug.com/926170 external/wpt/webrtc/RTCIceConnectionState-candidate-pair.https.html [ Pass Timeout ]
 crbug.com/926170 virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCIceConnectionState-candidate-pair.https.html [ Pass Timeout ]
 
 # Sheriff 2019-01-18
diff --git a/third_party/blink/web_tests/editing/selection/mouse/drag_over_text_transform.html b/third_party/blink/web_tests/editing/selection/mouse/drag_over_text_transform.html
new file mode 100644
index 0000000..0ca0de69
--- /dev/null
+++ b/third_party/blink/web_tests/editing/selection/mouse/drag_over_text_transform.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+
+<style>
+#target { text-transform: uppercase; }
+</style>
+
+<p id="target">&#xDF;abc</p>
+
+<script>
+// Drag through text with 'text-transform'. Shouldn't crash.
+
+function dragThrough(x1, x2, y) {
+  return new Promise((resolve, reject) => {
+    assert_own_property(window, 'chrome');
+    assert_own_property(window.chrome, 'gpuBenchmarking');
+
+    chrome.gpuBenchmarking.pointerActionSequence([{
+      source: 'mouse',
+      actions: [
+        {name: 'pointerDown', x: x1, y: y},
+        {name: 'pointerMove', x: x2, y:y},
+        {name: 'pointerUp'}
+      ]}], resolve);
+  });
+}
+
+promise_test(async () => {
+  const target = document.getElementById('target');
+  const x1 = target.offsetLeft;
+  const x2 = x1 + target.offsetWidth;
+  const y = target.offsetTop + target.offsetHeight;
+
+  await dragThrough(x1, x2, y);
+
+  const selection = getSelection();
+  const text = target.firstChild;
+  assert_false(selection.isCollapsed);
+  assert_equals(selection.anchorNode, text);
+  assert_equals(selection.anchorOffset, 0);
+  assert_equals(selection.focusNode, text);
+  assert_equals(selection.focusOffset, 4);
+});
+
+</script>
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
index df99dcd..e613778 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
@@ -188996,6 +188996,11 @@
      {}
     ]
    ],
+   "webrtc/RTCPeerConnection-iceConnectionState-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "webrtc/RTCPeerConnection-iceConnectionState.https-expected.txt": [
     [
      {}
@@ -202360,12 +202365,6 @@
      {}
     ]
    ],
-   "animation-worklet/playback-rate.https.html": [
-    [
-     "/animation-worklet/playback-rate.https.html",
-     {}
-    ]
-   ],
    "animation-worklet/scroll-timeline-writing-modes.https.html": [
     [
      "/animation-worklet/scroll-timeline-writing-modes.https.html",
@@ -286058,14 +286057,6 @@
      {}
     ]
    ],
-   "webrtc/RTCIceConnectionState-candidate-pair.https.html": [
-    [
-     "/webrtc/RTCIceConnectionState-candidate-pair.https.html",
-     {
-      "timeout": "long"
-     }
-    ]
-   ],
    "webrtc/RTCIceTransport-extension.https.html": [
     [
      "/webrtc/RTCIceTransport-extension.https.html",
@@ -286162,9 +286153,9 @@
      {}
     ]
    ],
-   "webrtc/RTCPeerConnection-iceConnectionState.https.html": [
+   "webrtc/RTCPeerConnection-iceConnectionState.html": [
     [
-     "/webrtc/RTCPeerConnection-iceConnectionState.https.html",
+     "/webrtc/RTCPeerConnection-iceConnectionState.html",
      {}
     ]
    ],
@@ -307233,10 +307224,6 @@
    "f73208c2a3c700d03ea1d39322a3e061b5caa5f7",
    "support"
   ],
-  "animation-worklet/playback-rate.https.html": [
-   "9c975814f1ed09b3e78493df177c3c0eddf74cdd",
-   "testharness"
-  ],
   "animation-worklet/resources/animator-iframe.html": [
    "e30cc281fcdefd8d029e7bf0ea92a1a9cd7af7e7",
    "support"
@@ -308498,19 +308485,19 @@
    "support"
   ],
   "client-hints/echo_client_hints_received.py": [
-   "f7debdb7b0b7073ec1878ffc17a9816a61f5f4c3",
+   "8f2ccaa2884f0382bdc4ef48b82b9c18b6093171",
    "support"
   ],
   "client-hints/http_equiv_accept_ch.tentative.http.html": [
-   "03c5799908b971ec6e6057fb8e5325e1bc2e203d",
+   "2bdced2ece762d71a13f2322325ef225fe2d489b",
    "testharness"
   ],
   "client-hints/http_equiv_accept_ch.tentative.https.html": [
-   "74eea344e90879e24568a76ba8e1197f6e9cede5",
+   "3e4d638ffc320e5e460b3923881c2e002eb26baa",
    "testharness"
   ],
   "client-hints/http_equiv_accept_ch.tentative.sub.https.html": [
-   "16617dccaf8c9c99011849b48d93e41f35ca374a",
+   "459b00e973bc1c69b3010146171683af12e33eb4",
    "testharness"
   ],
   "client-hints/http_equiv_accept_ch_lifetime.tentative.https.html": [
@@ -420610,7 +420597,7 @@
    "support"
   ],
   "interfaces/webrtc.idl": [
-   "dc51e2f2f3ae8f33b2cde6aa005efa34f46648aa",
+   "d60139ad946ee625ed61f598a96f71d0680511c2",
    "support"
   ],
   "interfaces/webusb.idl": [
@@ -423322,7 +423309,7 @@
    "support"
   ],
   "mixed-content/imageset.https.sub.html": [
-   "1f3d0471fbd2b38649894619494750ef221d72c9",
+   "dd371566161dcf4a22fd14bd2cd02ef0b06462a9",
    "testharness"
   ],
   "mixed-content/img-tag/http-csp/cross-origin-http/top-level/keep-scheme-redirect/optionally-blockable/opt-in-blocks.https.html": [
@@ -434062,11 +434049,11 @@
    "support"
   ],
   "preload/avoid-delaying-onload-link-preload.html": [
-   "a1b19c81c6783477f8914bf94d8e58d8644e06f3",
+   "77838c37741990153df68bdf746bd93b63d3d7a1",
    "testharness"
   ],
   "preload/delaying-onload-link-preload-after-discovery.html": [
-   "1c856d16d409479746f4c18c65028c38a026fbba",
+   "095d89ad90ca15eac57a142d051f60207cf94f92",
    "testharness"
   ],
   "preload/download-resources-expected.txt": [
@@ -434074,15 +434061,15 @@
    "support"
   ],
   "preload/download-resources.html": [
-   "510ebb480457e9e1b0d6ea788a8bd36c825bc634",
+   "dc2b4693cf11fe224e599b97ba8556894a9e0240",
    "testharness"
   ],
   "preload/dynamic-adding-preload-imagesrcset.tentative.html": [
-   "e1b8431d7bcaca618014496342055d533ba7399c",
+   "be8f0afcd5bdcc7daa61fa2666220780acf37ebf",
    "testharness"
   ],
   "preload/dynamic-adding-preload-nonce.html": [
-   "19e09472eef3813c9fb25ff7b6549477615c760e",
+   "10dae6b99586450367852cf5bb006d8511cf2865",
    "testharness"
   ],
   "preload/dynamic-adding-preload-nonce.html.headers": [
@@ -434090,15 +434077,15 @@
    "support"
   ],
   "preload/dynamic-adding-preload.html": [
-   "0cecc1983eaa50fbaa00b7d70031c8b11b84c4e7",
+   "2a299bd8446bf049d7e29b69c7fa6e0249f9ae6d",
    "testharness"
   ],
   "preload/link-header-on-subresource.html": [
-   "087a3429e649348d2b35fd92bf03ebc6307c72dc",
+   "a02bc7c819eb7c5049788b493556f8e34cc15091",
    "testharness"
   ],
   "preload/link-header-preload-delay-onload.html": [
-   "a445d800a586357a6eb5d0ef11778b55fbc301d4",
+   "7f38f8c9ee53d27614b20df9a76a493f3b4aabcf",
    "testharness"
   ],
   "preload/link-header-preload-delay-onload.html.headers": [
@@ -434106,7 +434093,7 @@
    "support"
   ],
   "preload/link-header-preload-nonce.html": [
-   "dc1ec100776916319a637daa0397589a05a23804",
+   "240d6f11dd5979457ed8a4d6ab3c97e9d1ce9f9c",
    "testharness"
   ],
   "preload/link-header-preload-nonce.html.headers": [
@@ -434114,7 +434101,7 @@
    "support"
   ],
   "preload/link-header-preload-srcset.tentative.html": [
-   "8d057549a1930dea4502ef7400f44c9113ec3e62",
+   "024da965796fb5960bc43cdf4de1806fbef74ffe",
    "testharness"
   ],
   "preload/link-header-preload-srcset.tentative.html.headers": [
@@ -434122,7 +434109,7 @@
    "support"
   ],
   "preload/link-header-preload.html": [
-   "0ca364bdef71ad98fcf12db36e8e71c414745b57",
+   "94a731bdcebb0eea04e5fe09152dfc013bb37afa",
    "testharness"
   ],
   "preload/link-header-preload.html.headers": [
@@ -434138,7 +434125,7 @@
    "support"
   ],
   "preload/onerror-event.html": [
-   "8190be87a4b7caf69ba07d07d239ff8143be3b05",
+   "5fae70d3bcab22bf50448c817f856c4b90f110a0",
    "testharness"
   ],
   "preload/onload-event-expected.txt": [
@@ -434146,15 +434133,15 @@
    "support"
   ],
   "preload/onload-event.html": [
-   "f9348b8ceb392117a2da6560e64118df2482dfdf",
+   "6af2d64a1c1d73adb8a6504a300cb35de9807038",
    "testharness"
   ],
   "preload/preload-csp.sub.html": [
-   "7fe06eb079133a245472c085068bb311dabebc68",
+   "8e5e45b9a1cdac572650bfa270a57930154e7bbc",
    "testharness"
   ],
   "preload/preload-default-csp.sub.html": [
-   "7813e36d4d8ada4bd4e5f79a583f2ff89519c5eb",
+   "cb080e62ba3efecbd86139c3952f3b4461735a51",
    "testharness"
   ],
   "preload/preload-strict-dynamic.html": [
@@ -434166,7 +434153,7 @@
    "support"
   ],
   "preload/preload-with-type.html": [
-   "83eafc5848b9c514e9136cbedfc64df6665d5aa9",
+   "8578143a23495e1828d313ddc6a9310df75fcdb0",
    "testharness"
   ],
   "preload/reflected-as-value-expected.txt": [
@@ -434246,7 +434233,7 @@
    "support"
   ],
   "preload/resources/preload_helper.js": [
-   "f464908fa513353917901d49af150d53cfd99945",
+   "b2cf8323db0145fa4876fb40d0d1ed3ff1c6413b",
    "support"
   ],
   "preload/resources/sound_5.oga": [
@@ -434278,11 +434265,11 @@
    "support"
   ],
   "preload/single-download-late-used-preload.html": [
-   "51533ba71445cc5b9edb235aaf28215671a1ca62",
+   "5549cb84fdb9ff03e348c6d005b5850b7294536b",
    "testharness"
   ],
   "preload/single-download-preload.html": [
-   "16d893ca7e54adde5fec3744b95a14f7e2cf3f34",
+   "e8f261787107ff976b9df36b408c9dc5ce2a50ac",
    "testharness"
   ],
   "presentation-api/META.yml": [
@@ -453926,7 +453913,7 @@
    "support"
   ],
   "web-animations/testcommon.js": [
-   "e6dad7cbf8d42b67660753fc5932e44ac531893c",
+   "5dbf6fd7f29f4985d3f2fbce4407f6594d80fac7",
    "support"
   ],
   "web-animations/timing-model/animation-effects/active-time.html": [
@@ -456161,10 +456148,6 @@
    "344007ded2b4d4496171402896d738817cdde12e",
    "testharness"
   ],
-  "webrtc/RTCIceConnectionState-candidate-pair.https.html": [
-   "7280d040856370f448796a4de2f92f82f9c78c53",
-   "testharness"
-  ],
   "webrtc/RTCIceTransport-expected.txt": [
    "8fcf2e214bb23a9f5f023c4d69398c918ca8e49d",
    "support"
@@ -456282,17 +456265,21 @@
    "testharness"
   ],
   "webrtc/RTCPeerConnection-helper.js": [
-   "1ff5f54015e6a65a47cd4a277818acb9c57318bc",
+   "d1056d90f393d06713feeccb04d589c41690089e",
    "support"
   ],
+  "webrtc/RTCPeerConnection-iceConnectionState-expected.txt": [
+   "b28601423de0b987c27db05d4b4061ece60f0129",
+   "support"
+  ],
+  "webrtc/RTCPeerConnection-iceConnectionState.html": [
+   "b647b3d3e35e31f16b33422f67cb30b917d1d0af",
+   "testharness"
+  ],
   "webrtc/RTCPeerConnection-iceConnectionState.https-expected.txt": [
    "c5fd94e3f5ca952dc8b0fa85c50b56c6b8ecc8ed",
    "support"
   ],
-  "webrtc/RTCPeerConnection-iceConnectionState.https.html": [
-   "8acabf49766ba08999b8857d8cb6589d1587c843",
-   "testharness"
-  ],
   "webrtc/RTCPeerConnection-iceGatheringState-expected.txt": [
    "cf325d504c3bb9819ed291c8aade04daea91877f",
    "support"
@@ -456422,7 +456409,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-track-stats.https.html": [
-   "e394e63e50d78b96dd8b6815700a0cc8408ce239",
+   "2d45c343d861f0b62a7d3d1f979ff7702862e5d7",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-transceivers.https.html": [
@@ -456506,7 +456493,7 @@
    "support"
   ],
   "webrtc/RTCRtpReceiver-getSynchronizationSources.https.html": [
-   "82ce3bd8467b6a29e4b40a105151b50314b5bf46",
+   "36460b479903231e15427f303f15c3b6a3de16e8",
    "testharness"
   ],
   "webrtc/RTCRtpSender-getCapabilities.html": [
@@ -456634,7 +456621,7 @@
    "testharness"
   ],
   "webrtc/idlharness.https.window-expected.txt": [
-   "e8123d1f8d18fab140b1b1fe50614cbed7035274",
+   "8191ea2a7c9656895284311205ac3e942e2448a0",
    "support"
   ],
   "webrtc/idlharness.https.window.js": [
diff --git a/third_party/blink/web_tests/external/wpt/animation-worklet/playback-rate.https.html b/third_party/blink/web_tests/external/wpt/animation-worklet/playback-rate.https.html
deleted file mode 100644
index 9c97581..0000000
--- a/third_party/blink/web_tests/external/wpt/animation-worklet/playback-rate.https.html
+++ /dev/null
@@ -1,140 +0,0 @@
-<!DOCTYPE html>
-<meta charset=utf-8>
-<title>The playback rate of a worklet animation</title>
-<link rel="help" href="https://drafts.css-houdini.org/css-animationworklet/">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script>
-'use strict';
-// Presence of playback rate adds FP operations to calculating start_time
-// and current_time of animations. That's why it's needed to increase FP error
-// for comparing times in these tests.
-window.assert_times_equal = (actual, expected, description) => {
-  assert_approx_equals(actual, expected, 0.002, description);
-};
-</script>
-<script src="/web-animations/testcommon.js"></script>
-<script src="common.js"></script>
-<body>
-<div id="log"></div>
-<script>
-'use strict';
-
-function InstantiateWorkletAnimation(test) {
-  const DURATION = 10000; // ms
-  const KEYFRAMES = { height : ['100px', '50px'] };
-  return new WorkletAnimation('passthrough', new KeyframeEffect(createDiv(test),
-        KEYFRAMES, DURATION), document.timeline);
-}
-
-promise_test(async t => {
-  await registerPassthroughAnimator();
-  const animation = InstantiateWorkletAnimation(t);
-
-  animation.playbackRate = 0.5;
-  animation.play();
-  assert_equals(animation.currentTime, 0,
-    'Zero current time is not affected by playbackRate.');
-}, 'Zero current time is not affected by playbackRate set while the animation is in idle state.');
-
-promise_test(async t => {
-  await registerPassthroughAnimator();
-  const animation = InstantiateWorkletAnimation(t);
-
-  animation.play();
-  animation.playbackRate = 0.5;
-  assert_equals(animation.currentTime, 0,
-    'Zero current time is not affected by playbackRate.');
-}, 'Zero current time is not affected by playbackRate set while the animation is in play-pending state.');
-
-promise_test(async t => {
-  await registerPassthroughAnimator();
-  const animation = InstantiateWorkletAnimation(t);
-  const playbackRate = 2;
-
-  animation.play();
-
-  await waitForNextFrame();
-
-  // Set playback rate while the animation is playing.
-  const prevCurrentTime = animation.currentTime;
-  animation.playbackRate = playbackRate;
-
-  assert_times_equal(animation.currentTime, prevCurrentTime,
-    'The current time should stay unaffected by setting playback rate.');
-}, 'Non zero current time is not affected by playbackRate set while the animation is in play state.');
-
-promise_test(async t => {
-  await registerPassthroughAnimator();
-  const animation = InstantiateWorkletAnimation(t);
-  const playbackRate = 2;
-
-  animation.play();
-
-  await waitForNextFrame();
-
-  // Set playback rate while the animation is playing
-  const prevCurrentTime = animation.currentTime;
-  const prevTimelineTime = document.timeline.currentTime;
-  animation.playbackRate = playbackRate;
-
-  // Play the animation some more.
-  await waitForNextFrame();
-
-  const currentTime = animation.currentTime;
-  const currentTimelineTime = document.timeline.currentTime;
-
-  assert_times_equal(currentTime - prevCurrentTime, (currentTimelineTime - prevTimelineTime) * playbackRate,
-    'The current time should increase two times faster than timeline.');
-
-}, 'The playback rate affects the rate of progress of the current time.');
-
-promise_test(async t => {
-  await registerPassthroughAnimator();
-  const animation = InstantiateWorkletAnimation(t);;
-  const playbackRate = 2;
-
-  // Set playback rate while the animation is in 'idle' state.
-  animation.playbackRate = playbackRate;
-  animation.play();
-  const prevTimelineTime = document.timeline.currentTime;
-
-  await waitForNextFrame();
-
-  const currentTime = animation.currentTime;
-  const timelineTime = document.timeline.currentTime;
-  assert_times_equal(currentTime, (timelineTime - prevTimelineTime) * playbackRate,
-    'The current time should increase two times faster than timeline.');
-}, 'The playback rate set before the animation started playing affects the ' +
-   'rate of progress of the current time');
-
-promise_test(async t => {
-  await registerPassthroughAnimator();
-  const timing = { duration: 100,
-                   easing: 'linear',
-                   fill: 'none',
-                   iterations: 1
-                 };
-  const target = createDiv(t);
-  const keyframeEffect = new KeyframeEffect(target, { opacity: [0, 1] }, timing);
-  const animation = new WorkletAnimation('passthrough', keyframeEffect, document.timeline);
-  const playbackRate = 2;
-
-  animation.play();
-  animation.playbackRate = playbackRate;
-
-  await waitForNextFrame();
-
-  assert_times_equal(keyframeEffect.getComputedTiming().localTime, animation.currentTime,
-    'When playback rate is set on WorkletAnimation, the underlying effect\'s timing should be properly updated.');
-
-  assert_approx_equals(Number(getComputedStyle(target).opacity),
-    animation.currentTime / 100, 0.001,
-    'When playback rate is set on WorkletAnimation, the underlying effect should produce correct visual result.');
-
-}, 'When playback rate is updated, the underlying effect is properly updated ' +
-   'with the current time of its WorkletAnimation and produces correct ' +
-   'visual result.');
-
-</script>
-</body>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/client-hints/echo_client_hints_received.py b/third_party/blink/web_tests/external/wpt/client-hints/echo_client_hints_received.py
index f7debdb..8f2ccaa 100644
--- a/third_party/blink/web_tests/external/wpt/client-hints/echo_client_hints_received.py
+++ b/third_party/blink/web_tests/external/wpt/client-hints/echo_client_hints_received.py
@@ -18,5 +18,3 @@
             response.headers.set("downlink-received", request.headers.get("downlink"))
     if "ect" in request.headers:
             response.headers.set("ect-received", request.headers.get("ect"))
-    if "Sec-CH-Lang" in request.headers:
-            response.headers.set("lang-received", request.headers.get("Sec-CH-Lang"))
diff --git a/third_party/blink/web_tests/external/wpt/client-hints/http_equiv_accept_ch.tentative.http.html b/third_party/blink/web_tests/external/wpt/client-hints/http_equiv_accept_ch.tentative.http.html
index 03c5799..2bdced2 100644
--- a/third_party/blink/web_tests/external/wpt/client-hints/http_equiv_accept_ch.tentative.http.html
+++ b/third_party/blink/web_tests/external/wpt/client-hints/http_equiv_accept_ch.tentative.http.html
@@ -1,5 +1,5 @@
 <html>
-<meta http-equiv="Accept-CH" content="DPR, Width, Viewport-Width, Device-Memory, rtt, downlink, ect, lang">
+<meta http-equiv="Accept-CH" content="DPR, Width, Viewport-Width, Device-Memory, rtt, downlink, ect">
 <title>Accept-CH http-equiv insecure transport test</title>
 <body>
 <script src="/resources/testharness.js"></script>
@@ -27,7 +27,6 @@
     assert_false(r.headers.has("rtt-received"), "rtt-received");
     assert_false(r.headers.has("downlink-received"), "downlink-received");
     assert_false(r.headers.has("ect-received"), "ect-received");
-    assert_false(r.headers.has("lang-received"), "lang-received");
   });
 }, "Accept-CH http-equiv test over insecure transport");
 
diff --git a/third_party/blink/web_tests/external/wpt/client-hints/http_equiv_accept_ch.tentative.https.html b/third_party/blink/web_tests/external/wpt/client-hints/http_equiv_accept_ch.tentative.https.html
index 74eea34..3e4d638 100644
--- a/third_party/blink/web_tests/external/wpt/client-hints/http_equiv_accept_ch.tentative.https.html
+++ b/third_party/blink/web_tests/external/wpt/client-hints/http_equiv_accept_ch.tentative.https.html
@@ -1,5 +1,5 @@
 <html>
-<meta http-equiv="Accept-CH" content="DPR, Width, Viewport-Width, Device-Memory, rtt, downlink, ect, lang">
+<meta http-equiv="Accept-CH" content="DPR, Width, Viewport-Width, Device-Memory, rtt, downlink, ect">
 <title>Accept-CH http-equiv cross-navigation test</title>
 <body>
 <script src="/resources/testharness.js"></script>
@@ -39,9 +39,9 @@
 // not persisted for the origin.
 window.open("resources/do_not_expect_client_hints_headers.html");
 async_test(t => {
-  window.addEventListener('message', t.step_func_done(e => {
-    assert_equals(e.data, 'PASS');
-  }));
+window.addEventListener('message', function(event) {
+  t.done();
+})
 }, "Loading of resources/do_not_expect_client_hints_headers.html did not finish.");
 
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/client-hints/http_equiv_accept_ch.tentative.sub.https.html b/third_party/blink/web_tests/external/wpt/client-hints/http_equiv_accept_ch.tentative.sub.https.html
index 16617dc..459b00e 100644
--- a/third_party/blink/web_tests/external/wpt/client-hints/http_equiv_accept_ch.tentative.sub.https.html
+++ b/third_party/blink/web_tests/external/wpt/client-hints/http_equiv_accept_ch.tentative.sub.https.html
@@ -1,5 +1,5 @@
 <html>
-<meta http-equiv="Accept-CH" content="DPR, Width, Viewport-Width, Device-Memory, rtt, downlink, ect, lang">
+<meta http-equiv="Accept-CH" content="DPR, Width, Viewport-Width, Device-Memory, rtt, downlink, ect">
 <title>Accept-CH http-equiv same-origin and cross-origin test</title>
 <body>
 <script src="/resources/testharness.js"></script>
@@ -38,8 +38,6 @@
 
     assert_in_array(r.headers.get("ect-received"), ["slow-2g", "2g",
           "3g", "4g"], 'ect-received is unexpected');
-
-    assert_true(r.headers.has("lang-received"), "lang-received");
   });
 }, "Same origin Accept-CH http-equiv test");
 
@@ -54,7 +52,6 @@
     assert_false(r.headers.has("rtt-received"), "rtt-received");
     assert_false(r.headers.has("downlink-received"), "downlink-received");
     assert_false(r.headers.has("ect-received"), "ect-received");
-    assert_false(r.headers.has("lang-received"), "lang-received");
   });
 }, "Cross-Origin Accept-CH http-equiv test");
 
diff --git a/third_party/blink/web_tests/external/wpt/mixed-content/imageset.https.sub.html b/third_party/blink/web_tests/external/wpt/mixed-content/imageset.https.sub.html
index 1f3d047..dd37156 100644
--- a/third_party/blink/web_tests/external/wpt/mixed-content/imageset.https.sub.html
+++ b/third_party/blink/web_tests/external/wpt/mixed-content/imageset.https.sub.html
@@ -21,9 +21,9 @@
   <img srcset="http://{{domains[]}}:{{ports[http][0]}}/images/smiley.png?img_srcset">
   <script>
     window.addEventListener("load", t.step_func(function() {
-        verifyNumberOfResourceTimingEntries("http://{{domains[]}}:{{ports[http][0]}}/images/smiley.png?img_src", 1);
-        verifyNumberOfResourceTimingEntries("http://{{domains[]}}:{{ports[http][0]}}/images/smiley.png?picture", 0);
-        verifyNumberOfResourceTimingEntries("http://{{domains[]}}:{{ports[http][0]}}/images/smiley.png?img_srcset", 0);
+        verifyNumberOfDownloads("http://{{domains[]}}:{{ports[http][0]}}/images/smiley.png?img_src", 1);
+        verifyNumberOfDownloads("http://{{domains[]}}:{{ports[http][0]}}/images/smiley.png?picture", 0);
+        verifyNumberOfDownloads("http://{{domains[]}}:{{ports[http][0]}}/images/smiley.png?img_srcset", 0);
         t.done();
     }));
   </script>
diff --git a/third_party/blink/web_tests/external/wpt/preload/avoid-delaying-onload-link-preload.html b/third_party/blink/web_tests/external/wpt/preload/avoid-delaying-onload-link-preload.html
index a1b19c8..77838c3 100644
--- a/third_party/blink/web_tests/external/wpt/preload/avoid-delaying-onload-link-preload.html
+++ b/third_party/blink/web_tests/external/wpt/preload/avoid-delaying-onload-link-preload.html
@@ -9,7 +9,7 @@
 <script>
     window.addEventListener("load", t.step_func(function() {
         verifyPreloadAndRTSupport();
-        verifyNumberOfResourceTimingEntries("/resources/dummy.js?pipe=trickle(d5)", 0);
+        verifyNumberOfDownloads("/resources/dummy.js?pipe=trickle(d5)", 0);
         t.done();
     }));
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/preload/delaying-onload-link-preload-after-discovery.html b/third_party/blink/web_tests/external/wpt/preload/delaying-onload-link-preload-after-discovery.html
index 1c856d16..095d89ad 100644
--- a/third_party/blink/web_tests/external/wpt/preload/delaying-onload-link-preload-after-discovery.html
+++ b/third_party/blink/web_tests/external/wpt/preload/delaying-onload-link-preload-after-discovery.html
@@ -11,8 +11,8 @@
 <script>
     window.addEventListener("load", t.step_func(function() {
         verifyPreloadAndRTSupport();
-        verifyLoadedAndNoDoubleDownload("resources/dummy.js?pipe=trickle(d5)");
-        verifyLoadedAndNoDoubleDownload("resources/square.png?pipe=trickle(d5)");
+        verifyNumberOfDownloads("resources/dummy.js?pipe=trickle(d5)", 1);
+        verifyNumberOfDownloads("resources/square.png?pipe=trickle(d5)", 1);
         t.done();
     }));
     var script = document.createElement("script");
diff --git a/third_party/blink/web_tests/external/wpt/preload/download-resources.html b/third_party/blink/web_tests/external/wpt/preload/download-resources.html
index 510ebb4..dc2b4693 100644
--- a/third_party/blink/web_tests/external/wpt/preload/download-resources.html
+++ b/third_party/blink/web_tests/external/wpt/preload/download-resources.html
@@ -16,21 +16,20 @@
 <link rel=preload href="resources/dummy.xml?novalue">
 <link rel=preload href="resources/dummy.xml" as="fetch">
 <body>
+<script src="resources/dummy.js?pipe=trickle(d5)&download-resources"></script>
 <script>
     window.addEventListener("load", t.step_func(function() {
-        t.step_timeout(function() {
-            verifyPreloadAndRTSupport()
-            verifyNumberOfResourceTimingEntries("resources/dummy.js", 1);
-            verifyNumberOfResourceTimingEntries("resources/dummy.css", 1);
-            verifyNumberOfResourceTimingEntries("/fonts/CanvasTest.ttf", 1);
-            verifyNumberOfResourceTimingEntries("resources/white.mp4", 1);
-            verifyNumberOfResourceTimingEntries("resources/sound_5.oga", 1);
-            verifyNumberOfResourceTimingEntries("resources/foo.vtt", 1);
-            verifyNumberOfResourceTimingEntries("resources/dummy.xml?foo=bar", 0);
-            verifyNumberOfResourceTimingEntries("resources/dummy.xml?novalue", 0);
-            verifyNumberOfResourceTimingEntries("resources/dummy.xml", 1);
-            t.done();
-        }, 5000);
+        verifyPreloadAndRTSupport()
+        verifyNumberOfDownloads("resources/dummy.js", 1);
+        verifyNumberOfDownloads("resources/dummy.css", 1);
+        verifyNumberOfDownloads("/fonts/CanvasTest.ttf", 1);
+        verifyNumberOfDownloads("resources/white.mp4", 1);
+        verifyNumberOfDownloads("resources/sound_5.oga", 1);
+        verifyNumberOfDownloads("resources/foo.vtt", 1);
+        verifyNumberOfDownloads("resources/dummy.xml?foo=bar", 0);
+        verifyNumberOfDownloads("resources/dummy.xml?novalue", 0);
+        verifyNumberOfDownloads("resources/dummy.xml", 1);
+        t.done();
     }));
 </script>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/preload/dynamic-adding-preload-imagesrcset.tentative.html b/third_party/blink/web_tests/external/wpt/preload/dynamic-adding-preload-imagesrcset.tentative.html
index e1b8431..be8f0af 100644
--- a/third_party/blink/web_tests/external/wpt/preload/dynamic-adding-preload-imagesrcset.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/preload/dynamic-adding-preload-imagesrcset.tentative.html
@@ -17,14 +17,15 @@
         link.imageSizes = "400px";
         link.onload = t.step_func(function() {
             t.step_timeout(function() {
-                verifyNumberOfResourceTimingEntries("resources/square.png?default", 0);
-                verifyNumberOfResourceTimingEntries("resources/square.png?200", 0);
-                verifyNumberOfResourceTimingEntries("resources/square.png?400", 1);
-                verifyNumberOfResourceTimingEntries("resources/square.png?800", 0);
+                verifyNumberOfDownloads("resources/square.png?default", 0);
+                verifyNumberOfDownloads("resources/square.png?200", 0);
+                verifyNumberOfDownloads("resources/square.png?400", 1);
+                verifyNumberOfDownloads("resources/square.png?800", 0);
                 t.done();
             }, 0);
         });
         document.body.appendChild(link);
     });
 </script>
+<script src="resources/dummy.js?pipe=trickle(d5)&dynamic-adding-preload"></script>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/preload/dynamic-adding-preload-nonce.html b/third_party/blink/web_tests/external/wpt/preload/dynamic-adding-preload-nonce.html
index 19e09472e..10dae6b9 100644
--- a/third_party/blink/web_tests/external/wpt/preload/dynamic-adding-preload-nonce.html
+++ b/third_party/blink/web_tests/external/wpt/preload/dynamic-adding-preload-nonce.html
@@ -14,7 +14,7 @@
     link.nonce = "abc";
     link.onload = link.onerror = t.step_func(function() {
         t.step_timeout(function() {
-            verifyNumberOfResourceTimingEntries("resources/dummy.js?with-nonce", 1);
+            verifyNumberOfDownloads("resources/dummy.js?with-nonce", 1);
             t.done();
         }, 0);
     });
@@ -29,7 +29,7 @@
     link.href = "resources/dummy.js?without-nonce";
     link.onload = link.onerror = t.step_func(function() {
         t.step_timeout(function() {
-            verifyNumberOfResourceTimingEntries("resources/dummy.js?without-nonce", 0);
+            verifyNumberOfDownloads("resources/dummy.js?without-nonce", 0);
             t.done();
         }, 0);
     });
diff --git a/third_party/blink/web_tests/external/wpt/preload/dynamic-adding-preload.html b/third_party/blink/web_tests/external/wpt/preload/dynamic-adding-preload.html
index 0cecc198..2a299bd 100644
--- a/third_party/blink/web_tests/external/wpt/preload/dynamic-adding-preload.html
+++ b/third_party/blink/web_tests/external/wpt/preload/dynamic-adding-preload.html
@@ -15,11 +15,12 @@
         link.href = "resources/dummy.js?dynamic-adding-preload";
         link.onload = t.step_func(function() {
             t.step_timeout(function() {
-                verifyNumberOfResourceTimingEntries("resources/dummy.js?dynamic-adding-preload", 1);
+                verifyNumberOfDownloads("resources/dummy.js?dynamic-adding-preload", 1);
                 t.done();
             }, 0);
         });
         document.body.appendChild(link);
     });
 </script>
+<script src="resources/dummy.js?pipe=trickle(d5)&dynamic-adding-preload"></script>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/preload/link-header-on-subresource.html b/third_party/blink/web_tests/external/wpt/preload/link-header-on-subresource.html
index 087a342..a02bc7c 100644
--- a/third_party/blink/web_tests/external/wpt/preload/link-header-on-subresource.html
+++ b/third_party/blink/web_tests/external/wpt/preload/link-header-on-subresource.html
@@ -6,13 +6,12 @@
     var t = async_test('Makes sure that Link headers on subresources preload resources');
 </script>
 <link rel=stylesheet href="resources/dummy-preloads-subresource.css?link-header-on-subresource">
+<script src="resources/dummy.js?pipe=trickle(d5)&link-header-on-subresources"></script>
 <script>
     window.addEventListener("load", t.step_func(function() {
-        t.step_timeout(function() {
-            verifyPreloadAndRTSupport();
-            verifyNumberOfResourceTimingEntries("/fonts/CanvasTest.ttf?link-header-on-subresource", 1);
-            t.done();
-        }, 5000);
+        verifyPreloadAndRTSupport();
+        verifyNumberOfDownloads("/fonts/CanvasTest.ttf?link-header-on-subresource", 1);
+        t.done();
     }));
 </script>
 
diff --git a/third_party/blink/web_tests/external/wpt/preload/link-header-preload-delay-onload.html b/third_party/blink/web_tests/external/wpt/preload/link-header-preload-delay-onload.html
index a445d80..7f38f8c 100644
--- a/third_party/blink/web_tests/external/wpt/preload/link-header-preload-delay-onload.html
+++ b/third_party/blink/web_tests/external/wpt/preload/link-header-preload-delay-onload.html
@@ -31,10 +31,10 @@
             }
         }
         assert_true(found_background_first);
-        verifyLoadedAndNoDoubleDownload("resources/square.png?link-header-preload-delay-onload");
-        verifyLoadedAndNoDoubleDownload("resources/square.png?background");
-        verifyLoadedAndNoDoubleDownload("resources/dummy.js?link-header-preload-delay-onload");
-        verifyLoadedAndNoDoubleDownload("resources/dummy.css?link-header-preload-delay-onload");
+        verifyNumberOfDownloads("resources/square.png?link-header-preload-delay-onload", 1);
+        verifyNumberOfDownloads("resources/square.png?background", 1);
+        verifyNumberOfDownloads("resources/dummy.js?link-header-preload-delay-onload", 1);
+        verifyNumberOfDownloads("resources/dummy.css?link-header-preload-delay-onload", 1);
         t.done();
     }));
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/preload/link-header-preload-nonce.html b/third_party/blink/web_tests/external/wpt/preload/link-header-preload-nonce.html
index dc1ec10..240d6f1 100644
--- a/third_party/blink/web_tests/external/wpt/preload/link-header-preload-nonce.html
+++ b/third_party/blink/web_tests/external/wpt/preload/link-header-preload-nonce.html
@@ -5,13 +5,12 @@
 <script nonce="abc">
     var t = async_test('Makes sure that Link headers preload resources with CSP nonce');
 </script>
+<script nonce="abc" src="resources/dummy.js?pipe=trickle(d5)&link-header-preload-nonce"></script>
 <script nonce="abc">
     window.addEventListener('load', t.step_func(function() {
-        t.step_timeout(function() {
-            verifyPreloadAndRTSupport();
-            verifyNumberOfResourceTimingEntries("resources/dummy.js?from-header&without-nonce", 0);
-            verifyNumberOfResourceTimingEntries("resources/dummy.js?from-header&with-nonce", 1);
-            t.done();
-        }, 5000);
+        verifyPreloadAndRTSupport();
+        verifyNumberOfResourceTimingEntries("resources/dummy.js?from-header&without-nonce", 0);
+        verifyNumberOfResourceTimingEntries("resources/dummy.js?from-header&with-nonce", 1);
+        t.done();
     }));
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/preload/link-header-preload-srcset.tentative.html b/third_party/blink/web_tests/external/wpt/preload/link-header-preload-srcset.tentative.html
index 8d057549..024da96 100644
--- a/third_party/blink/web_tests/external/wpt/preload/link-header-preload-srcset.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/preload/link-header-preload-srcset.tentative.html
@@ -7,22 +7,21 @@
     var t = async_test('Makes sure that Link headers preload images with (experimental) imagesrcset/imagesizes attributes.');
 </script>
 <body>
+<script src="resources/dummy.js?pipe=trickle(d3)&link-header-preload-srcset"></script>
 <script>
     window.addEventListener("load", t.step_func(function() {
-        t.step_timeout(function() {
-            verifyPreloadAndRTSupport();
-            verifyNumberOfResourceTimingEntries('resources/square.png?from-header&1x', 1);
-            verifyNumberOfResourceTimingEntries('resources/square.png?from-header&2x', 0);
-            verifyNumberOfResourceTimingEntries('resources/square.png?from-header&3x', 0);
-            verifyNumberOfResourceTimingEntries('resources/square.png?from-header&base', 0);
-            verifyNumberOfResourceTimingEntries('resources/square.png?from-header&200', 0);
-            verifyNumberOfResourceTimingEntries('resources/square.png?from-header&400', 1);
-            verifyNumberOfResourceTimingEntries('resources/square.png?from-header&800', 0);
-            verifyNumberOfResourceTimingEntries('resources/square.png?from-header&150', 0);
-            verifyNumberOfResourceTimingEntries('resources/square.png?from-header&300', 1);
-            verifyNumberOfResourceTimingEntries('resources/square.png?from-header&600', 0);
-            t.done();
-        }, 3000);
+        verifyPreloadAndRTSupport();
+        verifyNumberOfResourceTimingEntries('resources/square.png?from-header&1x', 1);
+        verifyNumberOfResourceTimingEntries('resources/square.png?from-header&2x', 0);
+        verifyNumberOfResourceTimingEntries('resources/square.png?from-header&3x', 0);
+        verifyNumberOfResourceTimingEntries('resources/square.png?from-header&base', 0);
+        verifyNumberOfResourceTimingEntries('resources/square.png?from-header&200', 0);
+        verifyNumberOfResourceTimingEntries('resources/square.png?from-header&400', 1);
+        verifyNumberOfResourceTimingEntries('resources/square.png?from-header&800', 0);
+        verifyNumberOfResourceTimingEntries('resources/square.png?from-header&150', 0);
+        verifyNumberOfResourceTimingEntries('resources/square.png?from-header&300', 1);
+        verifyNumberOfResourceTimingEntries('resources/square.png?from-header&600', 0);
+        t.done();
     }));
 </script>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/preload/link-header-preload.html b/third_party/blink/web_tests/external/wpt/preload/link-header-preload.html
index 0ca364b..94a731b 100644
--- a/third_party/blink/web_tests/external/wpt/preload/link-header-preload.html
+++ b/third_party/blink/web_tests/external/wpt/preload/link-header-preload.html
@@ -6,15 +6,14 @@
     var t = async_test('Makes sure that Link headers preload resources');
 </script>
 <body>
+<script src="resources/dummy.js?pipe=trickle(d5)&link-header-preload"></script>
 <script>
     window.addEventListener("load", t.step_func(function() {
-        t.step_timeout(function() {
-            verifyPreloadAndRTSupport();
-            verifyNumberOfResourceTimingEntries("resources/square.png?link-header-preload", 1);
-            verifyNumberOfResourceTimingEntries("resources/dummy.js?link-header-preload", 1);
-            verifyNumberOfResourceTimingEntries("resources/dummy.css?link-header-preload", 1);
-            t.done();
-        }, 5000);
+        verifyPreloadAndRTSupport();
+        verifyNumberOfDownloads("resources/square.png?link-header-preload", 1);
+        verifyNumberOfDownloads("resources/dummy.js?link-header-preload", 1);
+        verifyNumberOfDownloads("resources/dummy.css?link-header-preload", 1);
+        t.done();
     }));
 </script>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/preload/onerror-event.html b/third_party/blink/web_tests/external/wpt/preload/onerror-event.html
index 8190be87..5fae70d 100644
--- a/third_party/blink/web_tests/external/wpt/preload/onerror-event.html
+++ b/third_party/blink/web_tests/external/wpt/preload/onerror-event.html
@@ -28,22 +28,21 @@
 <link rel=preload href="non-existent/dummy.xml?foo" as=foobarxmlthing onerror="gibberishFailed = true;">
 <link rel=preload href="non-existent/dummy.xml?fetch" as=fetch onerror="fetchFailed = true;">
 <link rel=preload href="non-existent/dummy.xml?empty" onerror="emptyFailed = true;">
+<script src="resources/dummy.js?pipe=trickle(d5)&onerror-event"></script>
 <script>
     window.onload = t.step_func(function() {
-        t.step_timeout(function() {
-            verifyPreloadAndRTSupport();
-            assert_true(styleFailed, "style triggered error event");
-            assert_true(scriptFailed, "script triggered error event");
-            assert_true(imageFailed, "image triggered error event");
-            assert_true(fontFailed, "font triggered error event");
-            assert_true(videoFailed, "video triggered error event");
-            assert_true(audioFailed, "audio triggered error event");
-            assert_true(trackFailed, "track triggered error event");
-            assert_false(gibberishFailed, "gibberish as value did not trigger error event");
-            assert_true(fetchFailed, "fetch as triggered error event");
-            assert_false(emptyFailed, "empty as triggered error event");
-            t.done();
-        }, 5000);
+        verifyPreloadAndRTSupport();
+        assert_true(styleFailed, "style triggered error event");
+        assert_true(scriptFailed, "script triggered error event");
+        assert_true(imageFailed, "image triggered error event");
+        assert_true(fontFailed, "font triggered error event");
+        assert_true(videoFailed, "video triggered error event");
+        assert_true(audioFailed, "audio triggered error event");
+        assert_true(trackFailed, "track triggered error event");
+        assert_false(gibberishFailed, "gibberish as value did not trigger error event");
+        assert_true(fetchFailed, "fetch as triggered error event");
+        assert_false(emptyFailed, "empty as triggered error event");
+        t.done();
     });
 </script>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/preload/onload-event.html b/third_party/blink/web_tests/external/wpt/preload/onload-event.html
index f9348b8c..6af2d64a 100644
--- a/third_party/blink/web_tests/external/wpt/preload/onload-event.html
+++ b/third_party/blink/web_tests/external/wpt/preload/onload-event.html
@@ -27,23 +27,22 @@
 <link rel=preload href="resources/dummy.xml?fetch" as=fetch onload="fetchLoaded = true;">
 <link rel=preload href="resources/dummy.xml" onload="noTypeLoaded = true;">
 <body>
+<script src="resources/dummy.js?pipe=trickle(d5)&onload-event"></script>
 <script>
     window.onload = t.step_func(function() {
-        t.step_timeout(function() {
-            verifyPreloadAndRTSupport();
-            assert_true(styleLoaded, "style triggered load event");
-            assert_true(scriptLoaded, "script triggered load event");
-            assert_true(imageLoaded, "image triggered load event");
-            assert_true(fontLoaded, "font triggered load event");
-            assert_true(videoLoaded, "video triggered load event");
-            assert_true(audioLoaded, "audio triggered load event");
-            assert_true(trackLoaded, "track triggered load event");
-            assert_false(gibberishLoaded, "gibberish as value triggered load event");
-            assert_false(gibberishErrored, "gibberish as value triggered error event");
-            assert_true(fetchLoaded, "fetch as value triggered load event");
-            assert_false(noTypeLoaded, "empty as triggered load event");
-            t.done();
-        }, 5000);
+        verifyPreloadAndRTSupport();
+        assert_true(styleLoaded, "style triggered load event");
+        assert_true(scriptLoaded, "script triggered load event");
+        assert_true(imageLoaded, "image triggered load event");
+        assert_true(fontLoaded, "font triggered load event");
+        assert_true(videoLoaded, "video triggered load event");
+        assert_true(audioLoaded, "audio triggered load event");
+        assert_true(trackLoaded, "track triggered load event");
+        assert_false(gibberishLoaded, "gibberish as value triggered load event");
+        assert_false(gibberishErrored, "gibberish as value triggered error event");
+        assert_true(fetchLoaded, "fetch as value triggered load event");
+        assert_false(noTypeLoaded, "empty as triggered load event");
+        t.done();
     });
 </script>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/preload/preload-csp.sub.html b/third_party/blink/web_tests/external/wpt/preload/preload-csp.sub.html
index 7fe06eb0..8e5e45b 100644
--- a/third_party/blink/web_tests/external/wpt/preload/preload-csp.sub.html
+++ b/third_party/blink/web_tests/external/wpt/preload/preload-csp.sub.html
@@ -16,20 +16,19 @@
 <link rel=preload href="resources/dummy.xml?foo=bar" as=foobarxmlthing>
 <link rel=preload href="resources/dummy.xml">
 <body>
+<script src="resources/dummy.js?pipe=trickle(d5)&preload-csp"></script>
 <script>
     window.onload = t.step_func(function() {
-        t.step_timeout(function() {
-            verifyPreloadAndRTSupport();
-            verifyNumberOfResourceTimingEntries("{{host}}:{{ports[http][1]}}/preload/resources/dummy.js", 0);
-            verifyNumberOfResourceTimingEntries("resources/dummy.css", 0);
-            verifyNumberOfResourceTimingEntries("resources/square.png", 0);
-            verifyNumberOfResourceTimingEntries("/fonts/CanvasTest.ttf", 0);
-            verifyNumberOfResourceTimingEntries("resources/white.mp4", 0);
-            verifyNumberOfResourceTimingEntries("resources/sound_5.oga", 0);
-            verifyNumberOfResourceTimingEntries("resources/foo.vtt", 0);
-            verifyNumberOfResourceTimingEntries("resources/dummy.xml", 0);
-            t.done();
-        }, 5000);
+        verifyPreloadAndRTSupport();
+        verifyNumberOfDownloads("{{host}}:{{ports[http][1]}}/preload/resources/dummy.js", 0);
+        verifyNumberOfDownloads("resources/dummy.css", 0);
+        verifyNumberOfDownloads("resources/square.png", 0);
+        verifyNumberOfDownloads("/fonts/CanvasTest.ttf", 0);
+        verifyNumberOfDownloads("resources/white.mp4", 0);
+        verifyNumberOfDownloads("resources/sound_5.oga", 0);
+        verifyNumberOfDownloads("resources/foo.vtt", 0);
+        verifyNumberOfDownloads("resources/dummy.xml", 0);
+        t.done();
     });
 </script>
 
diff --git a/third_party/blink/web_tests/external/wpt/preload/preload-default-csp.sub.html b/third_party/blink/web_tests/external/wpt/preload/preload-default-csp.sub.html
index 7813e36..cb080e6 100644
--- a/third_party/blink/web_tests/external/wpt/preload/preload-default-csp.sub.html
+++ b/third_party/blink/web_tests/external/wpt/preload/preload-default-csp.sub.html
@@ -16,20 +16,19 @@
 <link rel=preload href="resources/dummy.xml?foo=bar" as=foobarxmlthing>
 <link rel=preload href="resources/dummy.xml">
 <body>
+<script src="resources/dummy.js?pipe=trickle(d5)&preload-default-csp"></script>
 <script>
     window.onload = t.step_func(function() {
-        t.step_timeout(function() {
-            verifyPreloadAndRTSupport();
-            verifyNumberOfResourceTimingEntries("{{host}}:{{ports[http][1]}}/preload/resources/dummy.js", 0);
-            verifyNumberOfResourceTimingEntries("resources/dummy.css", 0);
-            verifyNumberOfResourceTimingEntries("resources/square.png", 0);
-            verifyNumberOfResourceTimingEntries("/fonts/CanvasTest.ttf", 0);
-            verifyNumberOfResourceTimingEntries("resources/white.mp4", 0);
-            verifyNumberOfResourceTimingEntries("resources/sound_5.oga", 0);
-            verifyNumberOfResourceTimingEntries("resources/foo.vtt", 0);
-            verifyNumberOfResourceTimingEntries("resources/dummy.xml", 0);
-            t.done();
-        }, 5000);
+        verifyPreloadAndRTSupport();
+        verifyNumberOfDownloads("{{host}}:{{ports[http][1]}}/preload/resources/dummy.js", 0);
+        verifyNumberOfDownloads("resources/dummy.css", 0);
+        verifyNumberOfDownloads("resources/square.png", 0);
+        verifyNumberOfDownloads("/fonts/CanvasTest.ttf", 0);
+        verifyNumberOfDownloads("resources/white.mp4", 0);
+        verifyNumberOfDownloads("resources/sound_5.oga", 0);
+        verifyNumberOfDownloads("resources/foo.vtt", 0);
+        verifyNumberOfDownloads("resources/dummy.xml", 0);
+        t.done();
     });
 </script>
 
diff --git a/third_party/blink/web_tests/external/wpt/preload/preload-with-type.html b/third_party/blink/web_tests/external/wpt/preload/preload-with-type.html
index 83eafc5..8578143 100644
--- a/third_party/blink/web_tests/external/wpt/preload/preload-with-type.html
+++ b/third_party/blink/web_tests/external/wpt/preload/preload-with-type.html
@@ -47,20 +47,19 @@
 </script>
 <link rel=preload href="resources/foo.vtt" as=track type="text/foobar" onload="gibberishLoaded++;">
 <body>
+<script src="resources/dummy.js?pipe=trickle(d5)&preload-with-type"></script>
 <script>
     window.onload = t.step_func(function() {
-        t.step_timeout(function() {
-            verifyPreloadAndRTSupport();
-            assert_true(styleLoaded, "style triggered load event");
-            assert_true(scriptLoaded, "script triggered load event");
-            assert_true(imageLoaded, "image triggered load event");
-            assert_true(fontLoaded, "font triggered load event");
-            assert_true(videoLoaded, "video triggered load event");
-            assert_true(audioLoaded, "audio triggered load event");
-            assert_true(trackLoaded, "track triggered load event");
-            assert_equals(gibberishLoaded, 0, "resources with gibberish type should not be loaded");
-            t.done();
-        }, 5000);
+        verifyPreloadAndRTSupport();
+        assert_true(styleLoaded, "style triggered load event");
+        assert_true(scriptLoaded, "script triggered load event");
+        assert_true(imageLoaded, "image triggered load event");
+        assert_true(fontLoaded, "font triggered load event");
+        assert_true(videoLoaded, "video triggered load event");
+        assert_true(audioLoaded, "audio triggered load event");
+        assert_true(trackLoaded, "track triggered load event");
+        assert_equals(gibberishLoaded, 0, "resources with gibberish type should not be loaded");
+        t.done();
     });
 </script>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/preload/resources/preload_helper.js b/third_party/blink/web_tests/external/wpt/preload/resources/preload_helper.js
index f464908..b2cf832 100644
--- a/third_party/blink/web_tests/external/wpt/preload/resources/preload_helper.js
+++ b/third_party/blink/web_tests/external/wpt/preload/resources/preload_helper.js
@@ -10,32 +10,19 @@
     return new URL(url, location.href).href;
 }
 
-function verifyNumberOfResourceTimingEntries(url, number)
+function verifyNumberOfDownloads(url, number)
 {
-    var numEntries = performance.getEntriesByName(getAbsoluteURL(url)).length;
-    assert_equals(numEntries, number, url);
-}
-
-// Verifies that the resource is loaded, but not downloaded from network
-// more than once. This can be used to verify that a preloaded resource is
-// not downloaded again when used.
-function verifyLoadedAndNoDoubleDownload(url) {
-    var entries = performance.getEntriesByName(getAbsoluteURL(url));
-    // UA may create separate RT entries for preload and normal load,
-    // so we just check (entries.length > 0).
-    assert_greater_than(entries.length, 0, url + ' should be loaded');
-
     var numDownloads = 0;
-    entries.forEach(entry => {
-        // transferSize is zero if the resource is loaded from cache.
+    performance.getEntriesByName(getAbsoluteURL(url)).forEach(entry => {
         if (entry.transferSize > 0) {
             numDownloads++;
         }
     });
-    // numDownloads can be zero if the resource was already cached before running
-    // the test (for example, when the test is running repeatedly without
-    // clearing cache between runs).
-    assert_less_than_equal(
-        numDownloads, 1,
-        url + ' should be downloaded from network at most once');
+    assert_equals(numDownloads, number, url);
+}
+
+function verifyNumberOfResourceTimingEntries(url, number)
+{
+    var numEntries = performance.getEntriesByName(getAbsoluteURL(url)).length;
+    assert_equals(numEntries, number, url);
 }
diff --git a/third_party/blink/web_tests/external/wpt/preload/single-download-late-used-preload.html b/third_party/blink/web_tests/external/wpt/preload/single-download-late-used-preload.html
index 51533ba..5549cb8 100644
--- a/third_party/blink/web_tests/external/wpt/preload/single-download-late-used-preload.html
+++ b/third_party/blink/web_tests/external/wpt/preload/single-download-late-used-preload.html
@@ -9,11 +9,11 @@
     assert_equals(link.as, "image");
     link.addEventListener("load", () => {
         verifyPreloadAndRTSupport();
-        verifyNumberOfResourceTimingEntries("resources/square.png?pipe=trickle(d1)", 1);
+        verifyNumberOfDownloads("resources/square.png?pipe=trickle(d1)", 1);
         var img = document.createElement("img");
         img.src = "resources/square.png?pipe=trickle(d1)";
         img.onload = () => {
-            verifyLoadedAndNoDoubleDownload("resources/square.png?pipe=trickle(d1)");
+            verifyNumberOfDownloads("resources/square.png?pipe=trickle(d1)", 1);
             done();
         };
         document.body.appendChild(img);
diff --git a/third_party/blink/web_tests/external/wpt/preload/single-download-preload.html b/third_party/blink/web_tests/external/wpt/preload/single-download-preload.html
index 16d893c..e8f2617 100644
--- a/third_party/blink/web_tests/external/wpt/preload/single-download-preload.html
+++ b/third_party/blink/web_tests/external/wpt/preload/single-download-preload.html
@@ -16,6 +16,7 @@
 <link rel=preload href="resources/dummy.xml?foo=bar" as=foobarxmlthing>
 <link rel=preload href="resources/dummy.xml?single-download-preload">
 <body>
+<script src="resources/dummy.js?pipe=trickle(d3)&single-download-preload"></script>
 <style>
     #background {
         width: 200px;
@@ -44,17 +45,17 @@
     window.addEventListener("load", t.step_func(function() {
         verifyPreloadAndRTSupport();
         setTimeout(t.step_func(function() {
-            verifyLoadedAndNoDoubleDownload("resources/dummy.js?single-download-preload");
-            verifyLoadedAndNoDoubleDownload("resources/dummy.css?single-download-preload");
-            verifyLoadedAndNoDoubleDownload("resources/square.png?single-download-preload");
-            verifyLoadedAndNoDoubleDownload("resources/square.png?background&single-download-preload");
-            verifyLoadedAndNoDoubleDownload("/fonts/CanvasTest.ttf?single-download-preload");
-            verifyNumberOfResourceTimingEntries("resources/dummy.xml?foobar", 0);
-            verifyLoadedAndNoDoubleDownload("resources/foo.vtt?single-download-preload");
-            verifyLoadedAndNoDoubleDownload("resources/dummy.xml?single-download-preload");
+            verifyNumberOfDownloads("resources/dummy.js?single-download-preload", 1);
+            verifyNumberOfDownloads("resources/dummy.css?single-download-preload", 1);
+            verifyNumberOfDownloads("resources/square.png?single-download-preload", 1);
+            verifyNumberOfDownloads("resources/square.png?background&single-download-preload", 1);
+            verifyNumberOfDownloads("/fonts/CanvasTest.ttf?single-download-preload", 1);
+            verifyNumberOfDownloads("resources/dummy.xml?foobar", 0);
+            verifyNumberOfDownloads("resources/foo.vtt?single-download-preload", 1);
+            verifyNumberOfDownloads("resources/dummy.xml?single-download-preload", 1);
             // FIXME: We should verify for video and audio as well, but they seem to (flakily?) trigger multiple partial requests.
             t.done();
-        }), 3000);
+        }), 0);
     }));
 </script>
 <span>PASS - this text is here just so that the browser will download the font.</span>
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/testcommon.js b/third_party/blink/web_tests/external/wpt/web-animations/testcommon.js
index e6dad7c..5dbf6fd7 100644
--- a/third_party/blink/web_tests/external/wpt/web-animations/testcommon.js
+++ b/third_party/blink/web_tests/external/wpt/web-animations/testcommon.js
@@ -191,13 +191,13 @@
 function waitForNextFrame() {
   const timeAtStart = document.timeline.currentTime;
   return new Promise(resolve => {
-   (function handleFrame() {
-    if (timeAtStart === document.timeline.currentTime) {
-      window.requestAnimationFrame(handleFrame);
-    } else {
-      resolve();
-    }
-  }());
+    window.requestAnimationFrame(() => {
+      if (timeAtStart === document.timeline.currentTime) {
+        window.requestAnimationFrame(resolve);
+      } else {
+        resolve();
+      }
+    });
   });
 }
 
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCIceConnectionState-candidate-pair.https.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCIceConnectionState-candidate-pair.https.html
deleted file mode 100644
index 7280d040..0000000
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCIceConnectionState-candidate-pair.https.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<!doctype html>
-<meta charset=utf-8>
-<meta name="timeout" content="long">
-<title>RTCIceConnectionState and RTCIceCandidatePair</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="RTCPeerConnection-helper.js"></script>
-<script>
-'use strict';
-
-promise_test(async t => {
-  const caller = new RTCPeerConnection();
-  t.add_cleanup(() => caller.close());
-  const callee = new RTCPeerConnection();
-  t.add_cleanup(() => callee.close());
-
-  const stream = await navigator.mediaDevices.getUserMedia({audio:true});
-  const [track] = stream.getTracks();
-  caller.addTrack(track, stream);
-  exchangeIceCandidates(caller, callee);
-  await doSignalingHandshake(caller, callee);
-  await listenToIceConnected(t, caller);
-
-  const report = await caller.getStats();
-  let succeededPairFound = false;
-  report.forEach(stats => {
-    if (stats.type == 'candidate-pair' && stats.state == 'succeeded')
-      succeededPairFound = true;
-  });
-  assert_true(succeededPairFound, 'A succeeded candidate-pair should exist');
-}, 'On ICE connected, getStats() contains a connected candidate-pair');
-
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-helper.js b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-helper.js
index 1ff5f540..d1056d90f3 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-helper.js
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-helper.js
@@ -205,55 +205,6 @@
   await localPc.setRemoteDescription(answer);
 }
 
-// Returns a promise that resolves when |pc.iceConnectionState| is 'connected'
-// or 'completed'.
-function listenToIceConnected(pc) {
-  return new Promise((resolve) => {
-    function isConnected(pc) {
-      return pc.iceConnectionState == 'connected' ||
-            pc.iceConnectionState == 'completed';
-    }
-    if (isConnected(pc)) {
-      resolve();
-      return;
-    }
-    pc.oniceconnectionstatechange = () => {
-      if (isConnected(pc))
-        resolve();
-    };
-  });
-}
-
-// Returns a promise that resolves when |pc.connectionState| is 'connected'.
-function listenToConnected(pc) {
-  return new Promise((resolve) => {
-    if (pc.connectionState == 'connected') {
-      resolve();
-      return;
-    }
-    pc.onconnectionstatechange = () => {
-      if (pc.connectionState == 'connected')
-        resolve();
-    };
-  });
-}
-
-// Resolves when RTP packets have been received.
-function listenForSSRCs(t, receiver) {
-  return new Promise((resolve) => {
-    function listen() {
-      const ssrcs = receiver.getSynchronizationSources();
-      assert_true(ssrcs != undefined);
-      if (ssrcs.length > 0) {
-        resolve(ssrcs);
-        return;
-      }
-      t.step_timeout(listen, 0);
-    };
-    listen();
-  });
-}
-
 // Helper function to create a pair of connected data channel.
 // On success the promise resolves to an array with two data channels.
 // It does the heavy lifting of performing signaling handshake,
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-iceConnectionState-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-iceConnectionState-expected.txt
new file mode 100644
index 0000000..b2860142
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-iceConnectionState-expected.txt
@@ -0,0 +1,7 @@
+This is a testharness.js-based test.
+PASS Initial iceConnectionState should be new
+PASS Closing the connection should set iceConnectionState to closed
+PASS connection with one data channel should eventually have connected or completed connection state
+FAIL connection with one data channel should eventually have connected connection state Cannot read property 'transport' of undefined
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-iceConnectionState.https.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-iceConnectionState.html
similarity index 91%
rename from third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-iceConnectionState.https.html
rename to third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-iceConnectionState.html
index 8acabf4..b647b3d3 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-iceConnectionState.https.html
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-iceConnectionState.html
@@ -182,26 +182,6 @@
   }, 'connection with one data channel should eventually ' +
      'have connected connection state');
 
-  promise_test(async t => {
-    const caller = new RTCPeerConnection();
-    t.add_cleanup(() => caller.close());
-    const callee = new RTCPeerConnection();
-    t.add_cleanup(() => callee.close());
-
-    caller.addTransceiver('audio', {direction:'recvonly'});
-    const stream = await navigator.mediaDevices.getUserMedia({audio:true});
-    const [track] = stream.getTracks();
-    callee.addTrack(track, stream);
-    exchangeIceCandidates(caller, callee);
-    await doSignalingHandshake(caller, callee);
-
-    assert_equals(caller.getTransceivers().length, 1);
-    const [transceiver] = caller.getTransceivers();
-    assert_equals(transceiver.currentDirection, 'recvonly');
-
-    await listenToIceConnected(caller);
-  }, 'ICE can connect in a recvonly usecase');
-
   /*
     TODO
     4.4.4 RTCIceConnectionState Enum
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-track-stats.https.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-track-stats.https.html
index e394e63e..2d45c34 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-track-stats.https.html
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-track-stats.https.html
@@ -404,7 +404,7 @@
     callee.addTrack(tracks[1], streams[1]);
     exchangeIceCandidates(caller, callee);
     await doSignalingHandshake(caller, callee);
-    await listenToConnected(caller);
+    await onIceConnectionStateCompleted(caller);
     let receiver = caller.getReceivers()[0];
 
     // Obtain inbound and outbound RTP stream stats on a full stats report.
@@ -452,7 +452,7 @@
     callee.addTrack(tracks[1], streams[1]);
     exchangeIceCandidates(caller, callee);
     await doSignalingHandshake(caller, callee);
-    await listenToConnected(caller);
+    await onIceConnectionStateCompleted(caller);
     let receiver = caller.getReceivers()[0];
 
     // Obtain inbound and outbound RTP stream stats on a full stats report.
@@ -500,7 +500,7 @@
     callee.addTrack(tracks[1], streams[1]);
     exchangeIceCandidates(caller, callee);
     await doSignalingHandshake(caller, callee);
-    await listenToIceConnected(caller);
+    await onIceConnectionStateCompleted(caller);
 
     // Wait until RTCP has arrived so that it can not arrive between
     // the two get stats calls.
@@ -531,7 +531,7 @@
     callee.addTrack(tracks[1], streams[1]);
     exchangeIceCandidates(caller, callee);
     await doSignalingHandshake(caller, callee);
-    await listenToIceConnected(caller);
+    await onIceConnectionStateCompleted(caller);
     let receiver = caller.getReceivers()[0];
 
     // Wait until RTCP has arrived so that it can not arrive between
@@ -603,6 +603,24 @@
     return stats;
   }
 
+  // Returns a promise that is resolved when pc.iceConnectionState reaches the
+  // 'connected' or 'completed' state. This is when transport stats can be
+  // expected to have its selectedCandidatePairId defined.
+  async function onIceConnectionStateCompleted(pc) {
+    if (pc.iceConnectionState == 'connected' ||
+        pc.iceConnectionState == 'completed') {
+      return Promise.resolve();
+    }
+    let resolver = new Resolver();
+    pc.oniceconnectionstatechange = e => {
+      if (pc.iceConnectionState == 'connected' ||
+          pc.iceConnectionState == 'completed') {
+        resolver.resolve();
+      }
+    };
+    return resolver;
+  }
+
   // Explores the stats graph starting from |stat|, validating each stat
   // (validateRtcStats) and asserting that all stats of the report were visited.
   function validateStatsGraph(report, stat) {
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpReceiver-getSynchronizationSources.https.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpReceiver-getSynchronizationSources.https.html
index 82ce3bd..36460b4 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpReceiver-getSynchronizationSources.https.html
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpReceiver-getSynchronizationSources.https.html
@@ -26,6 +26,21 @@
   return trackEvent.receiver;
 }
 
+function listenForSSRCs(t, receiver) {
+  return new Promise((resolve) => {
+    function listen() {
+      const ssrcs = receiver.getSynchronizationSources();
+      assert_true(ssrcs != undefined);
+      if (ssrcs.length > 0) {
+        resolve(ssrcs);
+        return;
+      }
+      t.step_timeout(listen, 0);
+    };
+    listen();
+  });
+}
+
 for (const kind of ['audio', 'video']) {
   promise_test(async t => {
     const receiver = await initiateSingleTrackCallAndReturnReceiver(t, kind);
diff --git a/third_party/blink/web_tests/fast/css/containment/change-text-node-data-nowrap-align-expected.html b/third_party/blink/web_tests/fast/css/containment/change-text-node-data-nowrap-align-expected.html
new file mode 100644
index 0000000..6507833
--- /dev/null
+++ b/third_party/blink/web_tests/fast/css/containment/change-text-node-data-nowrap-align-expected.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<style>
+div {
+  display: inline-block;
+  float: left;
+  background: silver;
+  width: 100px;
+  height: 100px;
+  margin: 20px;
+  font-size: 25px;
+  overflow: hidden;
+  line-height: 1;
+  white-space: nowrap;
+  text-align: right;
+}
+</style>
+<div>Hello world! Hello world!</div>
+<div>Hheelloo-wwoorrlldd!! Hheelloo-wwoorrlldd!! Hheelloo-wwoorrlldd!!</div>
+<div>Hello</div>
+<div>Hi</div>
diff --git a/third_party/blink/web_tests/fast/css/containment/change-text-node-data-nowrap-align.html b/third_party/blink/web_tests/fast/css/containment/change-text-node-data-nowrap-align.html
new file mode 100644
index 0000000..dfcc3928
--- /dev/null
+++ b/third_party/blink/web_tests/fast/css/containment/change-text-node-data-nowrap-align.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<link rel="match" href="change-text-node-data-expected.html">
+<style>
+div {
+  display: inline-block;
+  float: left;
+  background: silver;
+  width: 100px;
+  height: 100px;
+  margin: 20px;
+  font-size: 25px;
+  overflow: hidden;
+  contain: layout size;
+  line-height: 1;
+  white-space: nowrap;
+  text-align: right;
+}
+</style>
+<script>
+  const originalValues = [
+    "f",
+    "foo",
+    "foo foo foo foo foo",
+    "foofoofoo foofoofoo foofoofoo foofoofoo foofoofoo"
+  ];
+  const newValues = [
+    "Hello world! Hello world!",
+    "Hheelloo-wwoorrlldd!! Hheelloo-wwoorrlldd!! Hheelloo-wwoorrlldd!!",
+    "Hello",
+    "Hi"
+  ];
+
+  function setupTest() {
+    originalValues.forEach((text) => {
+      let div = document.createElement("div");
+      div.appendChild(document.createTextNode(text));
+      document.body.appendChild(div);
+    });
+  }
+
+  function changeTextNodeData() {
+    let divs = document.getElementsByTagName("div");
+    for (let i = 0; i < divs.length; i++) {
+      divs[i].childNodes[0].data = newValues[i % newValues.length];
+    }
+  }
+
+  function runTest() {
+    setupTest();
+    document.body.offsetLeft;
+    changeTextNodeData();
+  }
+</script>
+<body onload="runTest();">
+</body>
diff --git a/third_party/blink/web_tests/fast/xpath/xpath-iterator-result-should-mark-its-nodeset-expected.txt b/third_party/blink/web_tests/fast/xpath/xpath-iterator-result-should-mark-its-nodeset-expected.txt
index 1be5545..1498fba5 100644
--- a/third_party/blink/web_tests/fast/xpath/xpath-iterator-result-should-mark-its-nodeset-expected.txt
+++ b/third_party/blink/web_tests/fast/xpath/xpath-iterator-result-should-mark-its-nodeset-expected.txt
@@ -2,6 +2,6 @@
 For this test to PASS you should see 2 PASS below.
 
 
-PASS
-PASS
+undefined
+undefined
 
diff --git a/third_party/blink/web_tests/fast/xpath/xpath-other-nodeset-result-should-mark-its-nodeset-expected.txt b/third_party/blink/web_tests/fast/xpath/xpath-other-nodeset-result-should-mark-its-nodeset-expected.txt
index 33d3e3e..55e8936a 100644
--- a/third_party/blink/web_tests/fast/xpath/xpath-other-nodeset-result-should-mark-its-nodeset-expected.txt
+++ b/third_party/blink/web_tests/fast/xpath/xpath-other-nodeset-result-should-mark-its-nodeset-expected.txt
@@ -2,6 +2,6 @@
 For this test to PASS you should see 2 PASS below.
 
 
-PASS
-PASS
+undefined
+undefined
 
diff --git a/third_party/blink/web_tests/fast/xpath/xpath-snapshot-result-should-mark-its-nodeset-expected.txt b/third_party/blink/web_tests/fast/xpath/xpath-snapshot-result-should-mark-its-nodeset-expected.txt
index 33d3e3e..55e8936a 100644
--- a/third_party/blink/web_tests/fast/xpath/xpath-snapshot-result-should-mark-its-nodeset-expected.txt
+++ b/third_party/blink/web_tests/fast/xpath/xpath-snapshot-result-should-mark-its-nodeset-expected.txt
@@ -2,6 +2,6 @@
 For this test to PASS you should see 2 PASS below.
 
 
-PASS
-PASS
+undefined
+undefined
 
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/overflow/border-radius-above-composited-subframe-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/overflow/border-radius-above-composited-subframe-expected.png
deleted file mode 100644
index b2e1c50..0000000
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/overflow/border-radius-above-composited-subframe-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/overflow/border-radius-composited-subframe-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/overflow/border-radius-composited-subframe-expected.png
index 3689c37..474301c 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/overflow/border-radius-composited-subframe-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/overflow/border-radius-composited-subframe-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/overflow/mask-with-small-content-rect-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/overflow/mask-with-small-content-rect-expected.png
index f97851a..f083d86 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/overflow/mask-with-small-content-rect-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/overflow/mask-with-small-content-rect-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/video/video-controls-layer-creation-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/video/video-controls-layer-creation-expected.png
index 7f05b3a..ddc2879 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/video/video-controls-layer-creation-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/compositing/video/video-controls-layer-creation-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/backgrounds/size/contain-and-cover-zoomed-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/backgrounds/size/contain-and-cover-zoomed-expected.png
deleted file mode 100644
index 2d2afc5..0000000
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/backgrounds/size/contain-and-cover-zoomed-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/border-inner-bleed-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/border-inner-bleed-expected.png
index d8ca013..609f5fe 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/border-inner-bleed-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/border-inner-bleed-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-expected.png
index 450c5e1ce..611bded 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png
index eda6e52..c8358206 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/scrollbars/border-box-rect-clips-scrollbars-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/scrollbars/border-box-rect-clips-scrollbars-expected.png
index 45e07f6..7db5e62f9 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/scrollbars/border-box-rect-clips-scrollbars-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/scrollbars/border-box-rect-clips-scrollbars-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/scrollbars/custom-scrollbar-display-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/scrollbars/custom-scrollbar-display-expected.png
index f92870e..be0ea2c7 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/scrollbars/custom-scrollbar-display-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/scrollbars/custom-scrollbar-display-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
index 16ca30b..3468c10 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/as-background-image/background-image-preserveaspectRatio-support-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/as-background-image/background-repeat-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/as-background-image/background-repeat-expected.png
index b6c86ec..1de3e50 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/as-background-image/background-repeat-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/as-background-image/background-repeat-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/batik/masking/maskRegions-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/batik/masking/maskRegions-expected.png
index 0c48d72..aab916b 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/batik/masking/maskRegions-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/batik/masking/maskRegions-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/batik/text/textEffect2-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/batik/text/textEffect2-expected.png
index 7c8cf9c2..8e76814 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/batik/text/textEffect2-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/batik/text/textEffect2-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/batik/text/textProperties-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/batik/text/textProperties-expected.png
index 7fa9e1f..bf80b965 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/batik/text/textProperties-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/svg/batik/text/textProperties-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
index 2390119..c0e325c 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/tables/mozilla_expected_failures/marvin/backgr_fixed-bg-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/prefer_compositing_to_lcd_text/scrollbars/border-box-rect-clips-scrollbars-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/prefer_compositing_to_lcd_text/scrollbars/border-box-rect-clips-scrollbars-expected.png
index 45e07f6..7db5e62f9 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/prefer_compositing_to_lcd_text/scrollbars/border-box-rect-clips-scrollbars-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/prefer_compositing_to_lcd_text/scrollbars/border-box-rect-clips-scrollbars-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor150/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor150/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
index e3b3b9b7..52188d22 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor150/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor150/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
index 40d4675..62f30708 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
index 40d4675..62f30708 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=CompositeAfterPaint/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/borders/inline-mask-overlay-image-outset-expected.png b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/borders/inline-mask-overlay-image-outset-expected.png
index 1600eaf..7eb5023 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/borders/inline-mask-overlay-image-outset-expected.png
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/fast/borders/inline-mask-overlay-image-outset-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/borders/inline-mask-overlay-image-outset-expected.png b/third_party/blink/web_tests/platform/linux/fast/borders/inline-mask-overlay-image-outset-expected.png
index f99555d..a56535e 100644
--- a/third_party/blink/web_tests/platform/linux/fast/borders/inline-mask-overlay-image-outset-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/borders/inline-mask-overlay-image-outset-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png b/third_party/blink/web_tests/platform/linux/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png
index 711ae3b..d901e3ff 100644
--- a/third_party/blink/web_tests/platform/linux/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/borders/border-image-side-reduction-expected.png b/third_party/blink/web_tests/platform/mac/fast/borders/border-image-side-reduction-expected.png
index f2fc9d7..1410f56 100644
--- a/third_party/blink/web_tests/platform/mac/fast/borders/border-image-side-reduction-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/borders/border-image-side-reduction-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/borders/border-image-side-reduction-expected.png b/third_party/blink/web_tests/platform/win/fast/borders/border-image-side-reduction-expected.png
index 30e1c799..b0b8011 100644
--- a/third_party/blink/web_tests/platform/win/fast/borders/border-image-side-reduction-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/borders/border-image-side-reduction-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/borders/inline-mask-overlay-image-outset-expected.png b/third_party/blink/web_tests/platform/win/fast/borders/inline-mask-overlay-image-outset-expected.png
index 44adbc1..239e188 100644
--- a/third_party/blink/web_tests/platform/win/fast/borders/inline-mask-overlay-image-outset-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/borders/inline-mask-overlay-image-outset-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png b/third_party/blink/web_tests/platform/win/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png
index af5c0d5..70caec5 100644
--- a/third_party/blink/web_tests/platform/win/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/borders/inline-mask-overlay-image-outset-vertical-rl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/external/wpt/webrtc/RTCPeerConnection-track-stats.https-expected.txt b/third_party/blink/web_tests/platform/win7/external/wpt/webrtc/RTCPeerConnection-track-stats.https-expected.txt
new file mode 100644
index 0000000..1a6478f
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/external/wpt/webrtc/RTCPeerConnection-track-stats.https-expected.txt
@@ -0,0 +1,21 @@
+This is a testharness.js-based test.
+PASS addTrack() without setLocalDescription() yields track stats
+PASS addTrack() without setLocalDescription() yields media stream stats
+PASS addTrack() with setLocalDescription() yields track stats
+PASS addTrack() with setLocalDescription() yields media stream stats
+PASS addTrack(): Media stream stats references track stats
+PASS Media stream stats references track stats
+PASS O/A exchange yields outbound RTP stream stats for sending track
+PASS O/A exchange yields inbound RTP stream stats for receiving track
+PASS replaceTrack() before offer: new track attachment stats present
+PASS replaceTrack() after offer, before answer: new track attachment stats present
+PASS replaceTrack() after answer: new track attachment stats present
+FAIL replaceTrack(): original track attachment stats present after replacing assert_true: Has stats for original track expected true got false
+PASS RTCRtpSender.getStats() contains only outbound-rtp and related stats
+FAIL RTCRtpReceiver.getStats() contains only inbound-rtp and related stats assert_equals: receiverReport should contain candidate-pair stats expected 1 but got 0
+PASS RTCPeerConnection.getStats(sendingTrack) is the same as RTCRtpSender.getStats()
+PASS RTCPeerConnection.getStats(receivingTrack) is the same as RTCRtpReceiver.getStats()
+PASS RTCPeerConnection.getStats(track) throws InvalidAccessError when there are zero senders or receivers for the track
+PASS RTCPeerConnection.getStats(track) throws InvalidAccessError when there are multiple senders for the track
+Harness: the test ran to completion.
+
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 9fa6beb..7ac9633 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -2165,6 +2165,15 @@
   <description>Please enter the description of this user action.</description>
 </action>
 
+<action name="AppList_ShowZeroStateSuggestions">
+  <owner>jennyz@chromium.org</owner>
+  <owner>newcomer@chromium.org</owner>
+  <description>
+    Cros Launcher shows zero state suggestions to user when user activate the
+    search box.
+  </description>
+</action>
+
 <action name="AppList_VoiceSearchCanceled">
   <obsolete>App list doesn't have voice search anymore.</obsolete>
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index dc29cbc..9af803d 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -3878,6 +3878,7 @@
   <int value="210" label="RFH_DETACH_MAIN_FRAME"/>
   <int value="211" label="RFH_DOCUMENT_INTERFACE_BROKER_MISSING"/>
   <int value="212" label="RFPH_POST_MESSAGE_INVALID_SOURCE_ORIGIN"/>
+  <int value="213" label="INVALID_INITIATOR_ORIGIN"/>
 </enum>
 
 <enum name="BadMessageReasonExtensions">
@@ -21501,6 +21502,9 @@
   <int value="2776" label="CustomCursorIntersectsViewport"/>
   <int value="2777" label="ClientHintsLang"/>
   <int value="2778" label="LinkRelPreloadImageSrcset"/>
+  <int value="2779" label="V8HTMLMediaElement_Remote_AttributeGetter"/>
+  <int value="2780" label="V8RemotePlayback_WatchAvailability_Method"/>
+  <int value="2781" label="V8RemotePlayback_Prompt_Method"/>
 </enum>
 
 <enum name="FeaturePolicyFeature">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 843bcb98..441a872 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -3456,6 +3456,80 @@
   <summary>Interactions with the App Launcher promo dialog.</summary>
 </histogram>
 
+<histogram name="Apps.AppList.AnswerCardSearchProvider.SearchAnswerLoadingTime"
+    units="ms" expires_after="2019-12-31">
+  <owner>jennyz@chriomium.org</owner>
+  <owner>newcomer@chromium.org</owner>
+  <summary>
+    The time between sending an answer card request and receiving the
+    notification that answer card has finished loading.
+  </summary>
+</histogram>
+
+<histogram
+    name="Apps.AppList.AnswerCardSearchProvider.SearchAnswerNavigationTime"
+    units="ms" expires_after="2019-12-31">
+  <owner>jennyz@chriomium.org</owner>
+  <owner>newcomer@chromium.org</owner>
+  <summary>
+    The time between sending an answer card request and receiving the
+    notification navigation has been finished with a valid answer card.
+  </summary>
+</histogram>
+
+<histogram name="Apps.AppList.AppSearchProvider.QueryTime" units="ms"
+    expires_after="2019-12-31">
+  <owner>jennyz@chromium.org</owner>
+  <owner>newcomer@chromium.org</owner>
+  <summary>
+    The time between sending a non-empty query to AppSearchProvider and
+    receiving results back.
+  </summary>
+</histogram>
+
+<histogram name="Apps.AppList.AppSearchProvider.ZeroStateLatency" units="ms"
+    expires_after="2019-12-31">
+  <owner>jennyz@chromium.org</owner>
+  <owner>newcomer@chromium.org</owner>
+  <summary>
+    The time between sending an empty query to AppSearchProvider and receiving
+    Zero State recommendation results back.
+  </summary>
+</histogram>
+
+<histogram name="Apps.AppList.LauncherSearchProvider.QueryTime" units="ms"
+    expires_after="2019-12-31">
+  <owner>jennyz@chriomium.org</owner>
+  <owner>newcomer@chromium.org</owner>
+  <summary>
+    The time between sending a non-empty query and receiving results back from
+    the extension which performs the file search.
+  </summary>
+</histogram>
+
+<histogram name="Apps.AppList.OmniboxProvider.QueryTime" units="ms"
+    expires_after="2019-12-31">
+  <owner>jennyz@chriomium.org</owner>
+  <owner>newcomer@chromium.org</owner>
+  <summary>
+    The time between sending an non-empty query and receiving search results
+    back from OmniboxProvider which queries chrome AutocompelteController's
+    search providers to get the results.
+  </summary>
+</histogram>
+
+<histogram name="Apps.AppList.OmniboxProvider.ZeroStateLatency" units="ms"
+    expires_after="2019-12-31">
+  <owner>jennyz@chriomium.org</owner>
+  <owner>newcomer@chromium.org</owner>
+  <summary>
+    The time between sending an empty query and receiving zero state
+    recommendations back from OmniboxProvider which queries chrome
+    ZeroStateProvider and gets recent queries back from Google Autocomplete
+    server.
+  </summary>
+</histogram>
+
 <histogram name="Apps.AppList.ZeroStateSearchResultUserActionType"
     enum="AppListZeroStateSearchResultUserActionType"
     expires_after="2019-12-31">
@@ -92695,6 +92769,9 @@
 <histogram base="true"
     name="RendererScheduler.ExpectedQueueingTimeByTaskQueue2"
     units="microseconds">
+  <obsolete>
+    Removed February 2019.
+  </obsolete>
   <owner>npm@chromium.org</owner>
   <owner>tdresser@chromium.org</owner>
   <summary>
@@ -114807,7 +114884,7 @@
 </histogram>
 
 <histogram name="Sync.ModelTypeOrphanMetadata" enum="SyncModelTypes"
-    expires_after="2019-03-01">
+    expires_after="2019-09-01">
   <owner>jkrcal@chromium.org</owner>
   <owner>mastiz@chromium.org</owner>
   <summary>
@@ -114818,7 +114895,7 @@
 </histogram>
 
 <histogram name="Sync.ModelTypeRedundantPut" enum="SyncModelTypes"
-    expires_after="2019-03-01">
+    expires_after="2019-09-01">
   <owner>mastiz@chromium.org</owner>
   <owner>jkrcal@chromium.org</owner>
   <summary>
@@ -141718,6 +141795,9 @@
 
 <histogram_suffixes
     name="RendererScheduler.ExpectedQueueingTime.TaskQueueSplit" separator=".">
+  <obsolete>
+    Removed Febrary 2019.
+  </obsolete>
   <suffix name="Compositor"
       label="Expected Queueing Time from the compositor task queue."/>
   <suffix name="Default"
diff --git a/ui/android/java/res/values-v17/styles.xml b/ui/android/java/res/values-v17/styles.xml
index 2c4aa52..edb3d3d7 100644
--- a/ui/android/java/res/values-v17/styles.xml
+++ b/ui/android/java/res/values-v17/styles.xml
@@ -32,7 +32,6 @@
         <item name="android:focusable">true</item>
         <item name="android:clickable">true</item>
         <item name="android:gravity">center_vertical|center_horizontal</item>
-        <item name="android:filterTouchesWhenObscured">true</item>
     </style>
     <style name="FilledButton" parent="ButtonCompatBase" tools:ignore="UnusedResources">
         <item name="android:paddingStart">24dp</item>
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn
index d385261..37e49d7 100644
--- a/ui/aura/BUILD.gn
+++ b/ui/aura/BUILD.gn
@@ -193,6 +193,7 @@
     "//ui/base",
     "//ui/base/clipboard",
     "//ui/base/ime",
+    "//ui/base/user_activity",
     "//ui/display",
     "//ui/events",
     "//ui/events:dom_keyboard_layout",
@@ -429,6 +430,7 @@
     "//ui/aura_extra:tests",
     "//ui/base:test_support",
     "//ui/base/clipboard:clipboard_types",
+    "//ui/base/user_activity",
     "//ui/compositor:test_support",
     "//ui/compositor_extra",
     "//ui/display:test_support",
diff --git a/ui/aura/event_injector.cc b/ui/aura/event_injector.cc
index f67d1fe..ac7df55 100644
--- a/ui/aura/event_injector.cc
+++ b/ui/aura/event_injector.cc
@@ -4,6 +4,9 @@
 
 #include "ui/aura/event_injector.h"
 
+#include <utility>
+
+#include "base/bind.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/ws/public/mojom/constants.mojom.h"
 #include "ui/aura/env.h"
@@ -15,19 +18,41 @@
 
 namespace aura {
 
+namespace {
+
+void RunCallback(base::OnceClosure callback, bool processed) {
+  if (!callback)
+    return;
+
+  std::move(callback).Run();
+}
+
+}  // namespace
+
 EventInjector::EventInjector() {}
 
-EventInjector::~EventInjector() {}
+EventInjector::~EventInjector() {
+  // |event_injector_| should not be waiting for responses. Otherwise, the
+  // pending callback would not happen because the mojo channel is closed.
+  DCHECK(!has_pending_callback_ || !event_injector_.IsExpectingResponse());
+}
 
 ui::EventDispatchDetails EventInjector::Inject(WindowTreeHost* host,
-                                               ui::Event* event) {
+                                               ui::Event* event,
+                                               base::OnceClosure callback) {
   DCHECK(host);
   Env* env = host->window()->env();
   DCHECK(env);
   DCHECK(event);
 
-  if (env->mode() == Env::Mode::LOCAL)
-    return host->event_sink()->OnEventFromSource(event);
+  if (env->mode() == Env::Mode::LOCAL) {
+    ui::EventDispatchDetails details =
+        host->event_sink()->OnEventFromSource(event);
+    RunCallback(std::move(callback), /*processed=*/true);
+    return details;
+  }
+
+  has_pending_callback_ |= !callback.is_null();
 
   if (event->IsLocatedEvent()) {
     // The ui-service expects events coming in to have a location matching the
@@ -42,8 +67,9 @@
     env->window_tree_client_->connector()->BindInterface(
         ws::mojom::kServiceName, &event_injector_);
   }
-  event_injector_->InjectEventNoAck(host->GetDisplayId(),
-                                    ui::Event::Clone(*event));
+  event_injector_->InjectEvent(
+      host->GetDisplayId(), ui::Event::Clone(*event),
+      base::BindOnce(&RunCallback, std::move(callback)));
   return ui::EventDispatchDetails();
 }
 
diff --git a/ui/aura/event_injector.h b/ui/aura/event_injector.h
index 1ec082a..babe83c 100644
--- a/ui/aura/event_injector.h
+++ b/ui/aura/event_injector.h
@@ -5,6 +5,7 @@
 #ifndef UI_AURA_EVENT_INJECTOR_H_
 #define UI_AURA_EVENT_INJECTOR_H_
 
+#include "base/callback.h"
 #include "services/ws/public/mojom/event_injector.mojom.h"
 #include "ui/aura/aura_export.h"
 
@@ -25,10 +26,18 @@
   EventInjector();
   ~EventInjector();
 
-  ui::EventDispatchDetails Inject(WindowTreeHost* host, ui::Event* event);
+  // Inject |event| to |host|. |callback| is optional that gets invoked after
+  // the event is processed by |host|. In LOCAL mode,  |callback| is invoked
+  // synchronously. In MUS mode, it is invoked after a response is received
+  // from window-server (via mojo).
+  ui::EventDispatchDetails Inject(
+      WindowTreeHost* host,
+      ui::Event* event,
+      base::OnceClosure callback = base::OnceClosure());
 
  private:
   ws::mojom::EventInjectorPtr event_injector_;
+  bool has_pending_callback_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(EventInjector);
 };
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index f913d76..cc59e98 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -249,9 +249,6 @@
     "ui_base_switches_util.h",
     "ui_base_types.cc",
     "ui_base_types.h",
-    "user_activity/user_activity_detector.cc",
-    "user_activity/user_activity_detector.h",
-    "user_activity/user_activity_observer.h",
     "view_prop.cc",
     "view_prop.h",
     "webui/i18n_source_stream.cc",
@@ -870,9 +867,7 @@
       sources += [ "ime/composition_text_util_pango_unittest.cc" ]
     }
     if (is_chromeos || use_ozone) {
-      sources += [
-        "ime/character_composer_unittest.cc",
-      ]
+      sources += [ "ime/character_composer_unittest.cc" ]
     }
   }
 
@@ -893,6 +888,7 @@
     "//ui/base:ui_data_pack",
     "//ui/base/clipboard:clipboard_test",
     "//ui/base/clipboard:clipboard_types",
+    "//ui/base/user_activity",
     "//ui/display",
     "//ui/events:events_base",
     "//ui/events:test_support",
diff --git a/ui/base/idle/BUILD.gn b/ui/base/idle/BUILD.gn
index bfa6e5d..5311a54a 100644
--- a/ui/base/idle/BUILD.gn
+++ b/ui/base/idle/BUILD.gn
@@ -52,6 +52,7 @@
     deps += [
       "//chromeos",
       "//chromeos/dbus",
+      "//ui/base/user_activity",
     ]
     sources -= [ "idle_linux.cc" ]
   }
diff --git a/ui/base/user_activity/BUILD.gn b/ui/base/user_activity/BUILD.gn
new file mode 100644
index 0000000..5cad24f
--- /dev/null
+++ b/ui/base/user_activity/BUILD.gn
@@ -0,0 +1,29 @@
+# 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("//build/config/jumbo.gni")
+import("//build/config/ui.gni")
+import("//testing/test.gni")
+
+if (is_android) {
+  import("//build/config/android/rules.gni")
+} else if (is_mac) {
+  import("//build/config/mac/rules.gni")
+}
+
+jumbo_component("user_activity") {
+  output_name = "ui_user_activity"
+
+  defines = [ "IS_UI_BASE_USER_ACTIVITY_IMPL" ]
+
+  sources = [
+    "user_activity_detector.cc",
+    "user_activity_detector.h",
+    "user_activity_observer.h",
+  ]
+
+  deps = [
+    "//ui/events:events",
+  ]
+}
diff --git a/ui/base/user_activity/user_activity_detector.h b/ui/base/user_activity/user_activity_detector.h
index 0f2a9a9e..6828dfd 100644
--- a/ui/base/user_activity/user_activity_detector.h
+++ b/ui/base/user_activity/user_activity_detector.h
@@ -6,10 +6,10 @@
 #define UI_BASE_USER_ACTIVITY_USER_ACTIVITY_DETECTOR_H_
 
 #include "base/compiler_specific.h"
+#include "base/component_export.h"
 #include "base/macros.h"
 #include "base/observer_list.h"
 #include "base/time/time.h"
-#include "ui/base/ui_base_export.h"
 #include "ui/events/event.h"
 #include "ui/events/platform/platform_event_observer.h"
 
@@ -18,7 +18,8 @@
 class UserActivityObserver;
 
 // Watches for input events and notifies observers that the user is active.
-class UI_BASE_EXPORT UserActivityDetector : public PlatformEventObserver {
+class COMPONENT_EXPORT(UI_BASE_USER_ACTIVITY) UserActivityDetector
+    : public PlatformEventObserver {
  public:
   // Minimum amount of time between notifications to observers.
   static const int kNotifyIntervalMs;
diff --git a/ui/base/user_activity/user_activity_observer.h b/ui/base/user_activity/user_activity_observer.h
index f6b98d21..0d1786a 100644
--- a/ui/base/user_activity/user_activity_observer.h
+++ b/ui/base/user_activity/user_activity_observer.h
@@ -5,8 +5,8 @@
 #ifndef UI_BASE_USER_ACTIVITY_USER_ACTIVITY_OBSERVER_H_
 #define UI_BASE_USER_ACTIVITY_USER_ACTIVITY_OBSERVER_H_
 
+#include "base/component_export.h"
 #include "base/macros.h"
-#include "ui/base/ui_base_export.h"
 
 namespace ui {
 class Event;
@@ -16,7 +16,7 @@
 
 // Interface for classes that want to be notified about user activity.
 // Implementations should register themselves with UserActivityDetector.
-class UI_BASE_EXPORT UserActivityObserver {
+class COMPONENT_EXPORT(UI_BASE_USER_ACTIVITY) UserActivityObserver {
  public:
   // Invoked periodically while the user is active (i.e. generating input
   // events). |event| is the event that triggered the notification; it may
diff --git a/ui/chromeos/BUILD.gn b/ui/chromeos/BUILD.gn
index d1075fc..d3c1128 100644
--- a/ui/chromeos/BUILD.gn
+++ b/ui/chromeos/BUILD.gn
@@ -43,6 +43,7 @@
     "//ui/aura",
     "//ui/base",
     "//ui/base/ime",
+    "//ui/base/user_activity",
     "//ui/chromeos/resources",
     "//ui/chromeos/strings",
     "//ui/display",
diff --git a/ui/display/manager/BUILD.gn b/ui/display/manager/BUILD.gn
index fda805f..201de69 100644
--- a/ui/display/manager/BUILD.gn
+++ b/ui/display/manager/BUILD.gn
@@ -62,6 +62,7 @@
     "//base",
     "//third_party/re2",
     "//ui/base",
+    "//ui/base/user_activity",
     "//ui/display/mojo:interfaces",
     "//ui/display/util",
     "//ui/events:platform_event",
diff --git a/ui/ozone/platform/wayland/DEPS b/ui/ozone/platform/wayland/DEPS
index 1bdd1df..b15ab08f 100644
--- a/ui/ozone/platform/wayland/DEPS
+++ b/ui/ozone/platform/wayland/DEPS
@@ -2,6 +2,7 @@
   "+ui/base/buildflags.h",  # Doesn't bring in all of ui/base.
   "+ui/base/hit_test.h", # UI hit test doesn't bring in all of ui/base.
   "+ui/base/ui_base_features.h",
+  "+ui/base/ime/character_composer.h",
   "+ui/base/ime/composition_text.h",
   "+ui/base/ime/linux/linux_input_method_context.h",
   "+ui/base/ime/linux/linux_input_method_context_factory.h",
diff --git a/ui/ozone/platform/wayland/wayland_input_method_context.cc b/ui/ozone/platform/wayland/wayland_input_method_context.cc
index 959a8e3..f5e57bb 100644
--- a/ui/ozone/platform/wayland/wayland_input_method_context.cc
+++ b/ui/ozone/platform/wayland/wayland_input_method_context.cc
@@ -70,10 +70,19 @@
 
 bool WaylandInputMethodContext::DispatchKeyEvent(
     const ui::KeyEvent& key_event) {
-  return false;
+  if (key_event.type() != ET_KEY_PRESSED ||
+      !character_composer_.FilterKeyPress(key_event))
+    return false;
+
+  // TODO(nickdiego): Handle preedit string
+  auto composed = character_composer_.composed_character();
+  if (!composed.empty())
+    delegate_->OnCommit(composed);
+  return true;
 }
 
 void WaylandInputMethodContext::Reset() {
+  character_composer_.Reset();
   if (text_input_)
     text_input_->Reset();
 }
diff --git a/ui/ozone/platform/wayland/wayland_input_method_context.h b/ui/ozone/platform/wayland/wayland_input_method_context.h
index 1023ecc..7fd0e94 100644
--- a/ui/ozone/platform/wayland/wayland_input_method_context.h
+++ b/ui/ozone/platform/wayland/wayland_input_method_context.h
@@ -6,6 +6,7 @@
 #define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_INPUT_METHOD_CONTEXT_H_
 
 #include "base/macros.h"
+#include "ui/base/ime/character_composer.h"
 #include "ui/base/ime/linux/linux_input_method_context.h"
 #include "ui/events/ozone/evdev/event_dispatch_callback.h"
 #include "ui/ozone/platform/wayland/zwp_text_input_wrapper.h"
@@ -51,6 +52,10 @@
 
   std::unique_ptr<ZWPTextInputWrapper> text_input_;
 
+  // An object to compose a character from a sequence of key presses
+  // including dead key etc.
+  CharacterComposer character_composer_;
+
   DISALLOW_COPY_AND_ASSIGN(WaylandInputMethodContext);
 };
 
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index 4decb88..35e0140e 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -914,7 +914,7 @@
     ]
 
     deps += [
-      "//services/service_manager/background:lib",
+      "//services/service_manager",
       "//services/service_manager/public/cpp",
       "//services/service_manager/public/mojom",
       "//services/ws/common",
diff --git a/ui/views/DEPS b/ui/views/DEPS
index 58ce51c..d6c4afa4 100644
--- a/ui/views/DEPS
+++ b/ui/views/DEPS
@@ -40,7 +40,6 @@
   ],
   "views_test_base\.cc": [
     "+mojo/core/embedder",
-    "+services/service_manager/background",
     "+services/service_manager/public",
     "+services/ws",
     "+ui/gl",
diff --git a/ui/views/mus/desktop_window_tree_host_mus.cc b/ui/views/mus/desktop_window_tree_host_mus.cc
index f48d31b..d12dbd9 100644
--- a/ui/views/mus/desktop_window_tree_host_mus.cc
+++ b/ui/views/mus/desktop_window_tree_host_mus.cc
@@ -52,14 +52,6 @@
     if (MusClient::Get()->use_remote_accessibility_host())
       GetViewAccessibility().OverrideIsIgnored(true);
 
-    // Initialize kTopViewInset to a default value. Further updates will come
-    // from Ash. This is necessary so that during app window creation,
-    // GetWindowBoundsForClientBounds() can calculate correctly.
-    const auto& values = WindowManagerFrameValues::instance();
-    widget->GetNativeWindow()->SetProperty(aura::client::kTopViewInset,
-                                           widget->IsMaximized()
-                                               ? values.maximized_insets.top()
-                                               : values.normal_insets.top());
     observed_.Add(window());
   }
   ~ClientSideNonClientFrameView() override {}
@@ -829,6 +821,10 @@
   if (!ShouldSendClientAreaToServer())
     return nullptr;
 
+  // Initialize kTopViewInset to a default value. Further updates will come
+  // from Ash. This is necessary so that during app window creation,
+  // GetWindowBoundsForClientBounds() can calculate correctly.
+  SetTopViewInsetToDefault();
   return new ClientSideNonClientFrameView(native_widget_delegate_->AsWidget());
 }
 
@@ -848,7 +844,24 @@
   if (IsFullscreen() == fullscreen)
     return;  // Nothing to do.
 
+  // Retrieve restore bounds before leaving fullscreen.
+  gfx::Rect restore_bounds;
+  if (!fullscreen)
+    restore_bounds = GetRestoredBounds();
+
+  // Change the fullscreen state.
   wm::SetWindowFullscreen(window(), fullscreen);
+
+  // Preset bounds with heuristic size to provide synchronous bounds change
+  // after the switch to/from fullscreen.
+  if (fullscreen) {
+    window()->SetProperty(aura::client::kRestoreBoundsKey,
+                          new gfx::Rect(GetWindowBoundsInScreen()));
+    SetBoundsInDIP(GetDisplay().bounds());
+  } else {
+    SetTopViewInsetToDefault();
+    SetBoundsInDIP(restore_bounds);
+  }
 }
 
 bool DesktopWindowTreeHostMus::IsFullscreen() const {
@@ -1026,6 +1039,13 @@
   observed_client_view_.Remove(observed_view);
 }
 
+void DesktopWindowTreeHostMus::SetTopViewInsetToDefault() {
+  const auto& values = WindowManagerFrameValues::instance();
+  window()->SetProperty(aura::client::kTopViewInset,
+                        IsMaximized() ? values.maximized_insets.top()
+                                      : values.normal_insets.top());
+}
+
 aura::Window* DesktopWindowTreeHostMus::content_window() {
   return desktop_native_widget_aura_->content_window();
 }
diff --git a/ui/views/mus/desktop_window_tree_host_mus.h b/ui/views/mus/desktop_window_tree_host_mus.h
index a95e38e..ed0ba6c 100644
--- a/ui/views/mus/desktop_window_tree_host_mus.h
+++ b/ui/views/mus/desktop_window_tree_host_mus.h
@@ -8,14 +8,14 @@
 #include <memory>
 #include <set>
 
-#include "base/scoped_observer.h"
 #include "base/macros.h"
+#include "base/scoped_observer.h"
 #include "ui/aura/mus/focus_synchronizer_observer.h"
 #include "ui/aura/mus/window_tree_host_mus.h"
 #include "ui/aura/window_observer.h"
 #include "ui/views/mus/mus_client_observer.h"
-#include "ui/views/view_observer.h"
 #include "ui/views/mus/mus_export.h"
+#include "ui/views/view_observer.h"
 #include "ui/views/widget/desktop_aura/desktop_window_tree_host.h"
 #include "ui/views/widget/widget.h"
 
@@ -173,6 +173,11 @@
   void OnViewBoundsChanged(views::View* observed_view) override;
   void OnViewIsDeleting(View* observed_view) override;
 
+  // Sets kTopViewInset to the default value as a heuristic to assist with
+  // reducing the number of bounds changes during window creation or
+  // entering/exiting fullscreen.
+  void SetTopViewInsetToDefault();
+
   // Accessor for DesktopNativeWidgetAura::content_window().
   aura::Window* content_window();
 
diff --git a/ui/views/mus/desktop_window_tree_host_mus_unittest.cc b/ui/views/mus/desktop_window_tree_host_mus_unittest.cc
index a0e976c56..1e83dbb8 100644
--- a/ui/views/mus/desktop_window_tree_host_mus_unittest.cc
+++ b/ui/views/mus/desktop_window_tree_host_mus_unittest.cc
@@ -36,6 +36,7 @@
 #include "ui/views/mus/mus_client.h"
 #include "ui/views/mus/mus_client_test_api.h"
 #include "ui/views/mus/screen_mus.h"
+#include "ui/views/mus/window_manager_frame_values.h"
 #include "ui/views/test/native_widget_factory.h"
 #include "ui/views/test/views_test_base.h"
 #include "ui/views/widget/widget.h"
@@ -430,6 +431,37 @@
   }
 }
 
+TEST_F(DesktopWindowTreeHostMusTest, SynchronousBoundsWhenTogglingFullscreen) {
+  const gfx::Rect display_bounds =
+      display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
+
+  const Widget::InitParams::Type kWidgetTypes[] = {
+      Widget::InitParams::TYPE_WINDOW,
+      Widget::InitParams::TYPE_WINDOW_FRAMELESS,
+  };
+
+  for (auto widget_type : kWidgetTypes) {
+    Widget widget;
+    Widget::InitParams params = CreateParams(widget_type);
+    params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+    widget.Init(params);
+
+    const gfx::Rect restore_bounds = widget.GetWindowBoundsInScreen();
+
+    // Entering fullscreen synchronously set show state and bounds.
+    widget.SetFullscreen(true);
+    EXPECT_TRUE(widget.IsFullscreen())
+        << "Enter fullscreen failed for type=" << widget_type;
+    EXPECT_EQ(display_bounds, widget.GetWindowBoundsInScreen());
+
+    // Leaving fullscreen synchronously set show state and bounds.
+    widget.SetFullscreen(false);
+    EXPECT_FALSE(widget.IsFullscreen())
+        << "Leave fullscreen failed for type=" << widget_type;
+    EXPECT_EQ(restore_bounds, widget.GetWindowBoundsInScreen());
+  }
+}
+
 TEST_F(DesktopWindowTreeHostMusTest, ClientWindowHasContent) {
   // Opaque window has content.
   {
@@ -737,6 +769,39 @@
   EXPECT_FALSE(widget->IsMaximized());
 }
 
+// Tests that toggling fullscreen synchronously updates kTopViewInset (via its
+// effect on client bounds).
+TEST_F(DesktopWindowTreeHostMusTest, FullscreenTopViewInset) {
+  WindowManagerFrameValues frame_values;
+  frame_values.normal_insets = gfx::Insets(7, 0, 0, 0);
+  WindowManagerFrameValues::SetInstance(frame_values);
+
+  std::unique_ptr<Widget> widget(CreateWidget());
+  widget->Show();
+  EXPECT_TRUE(widget->IsActive());
+
+  gfx::Rect before_fullscreen_client_bounds = widget->client_view()->bounds();
+  gfx::Rect frame_bounds = widget->non_client_view()->bounds();
+  EXPECT_EQ(frame_values.normal_insets,
+            frame_bounds.InsetsFrom(before_fullscreen_client_bounds));
+
+  widget->SetFullscreen(true);
+
+  gfx::Rect fullscreen_client_bounds = widget->client_view()->bounds();
+  frame_bounds = widget->non_client_view()->bounds();
+  EXPECT_EQ(fullscreen_client_bounds, frame_bounds);
+
+  widget->SetFullscreen(false);
+
+  gfx::Rect after_fullscreen_client_bounds = widget->client_view()->bounds();
+  frame_bounds = widget->non_client_view()->bounds();
+  EXPECT_EQ(frame_values.normal_insets,
+            frame_bounds.InsetsFrom(after_fullscreen_client_bounds));
+
+  EXPECT_EQ(before_fullscreen_client_bounds, after_fullscreen_client_bounds);
+  EXPECT_NE(fullscreen_client_bounds, after_fullscreen_client_bounds);
+}
+
 // TransferTouchEventsCounter observes the GestureRecognizer and counts how many
 // times TransferEventsTo() is invoked for testing.
 class TransferTouchEventsCounter : public ui::GestureRecognizerObserver {
diff --git a/ui/views/test/DEPS b/ui/views/test/DEPS
index 2ba6d7d..752d09c 100644
--- a/ui/views/test/DEPS
+++ b/ui/views/test/DEPS
@@ -4,7 +4,7 @@
 
 specific_include_rules = {
   "platform_test_helper_mus.cc": [
-    "+services/service_manager/background/background_service_manager.h",
+    "+services/service_manager/background_service_manager.h",
     "+services/service_manager/public",
     "+services/ws/ime/test_ime_driver/manifest.h",
     "+services/ws/test_ws/test_manifest.h",
diff --git a/ui/views/test/platform_test_helper_mus.cc b/ui/views/test/platform_test_helper_mus.cc
index 0c2766d..72e1386b 100644
--- a/ui/views/test/platform_test_helper_mus.cc
+++ b/ui/views/test/platform_test_helper_mus.cc
@@ -8,7 +8,7 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/threading/simple_thread.h"
-#include "services/service_manager/background/background_service_manager.h"
+#include "services/service_manager/background_service_manager.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/constants.h"
 #include "services/service_manager/public/cpp/manifest_builder.h"
@@ -116,13 +116,13 @@
 
     background_service_manager_ =
         std::make_unique<service_manager::BackgroundServiceManager>(
-            nullptr, std::vector<service_manager::Manifest>{
-                         test_ws::GetManifest(), test_ime_driver::GetManifest(),
-                         service_manager::ManifestBuilder()
-                             .WithServiceName(kServiceName)
-                             .RequireCapability("*", "app")
-                             .RequireCapability("*", "test")
-                             .Build()});
+            std::vector<service_manager::Manifest>{
+                test_ws::GetManifest(), test_ime_driver::GetManifest(),
+                service_manager::ManifestBuilder()
+                    .WithServiceName(kServiceName)
+                    .RequireCapability("*", "app")
+                    .RequireCapability("*", "test")
+                    .Build()});
 
     service_manager::mojom::ServicePtr service;
     default_service_binding_.Bind(mojo::MakeRequest(&service));