diff --git a/BUILD.gn b/BUILD.gn
index f445ca9..4e777ab 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -462,7 +462,6 @@
         "//media/cast:generate_timecode_audio",
         "//net:crash_cache",
         "//net:dns_fuzz_stub",
-        "//net:gdig",
         "//net:net_watcher",  # TODO(GYP): This should be conditional on use_v8_in_net
         "//net:run_testserver",
         "//net:stress_cache",
diff --git a/DEPS b/DEPS
index 64f3a11..5000e0e 100644
--- a/DEPS
+++ b/DEPS
@@ -105,11 +105,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '0b0043392bfdf13f74ed64ba729f9c1e0fbae94f',
+  'skia_revision': 'df795638b9bd23d03bea7aafb4ecae221172631a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '8766d3dde17ccd5412c6931c0367c6b89f554b5b',
+  'v8_revision': 'd7b61abe7b48928aed739f02bf7695732d359e7e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -129,7 +129,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': 'fda907f4ac7ee9589f52d6c13e4bc555f8216c52',
+  'pdfium_revision': 'b907757c0db1d5e4ede21709c9e97cbeefc1e03a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -165,7 +165,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': 'ddcfa34d6ad43fceb291a000fa013ad159dc731e',
+  'catapult_revision': '9e8a0b2b37d966544401445b117d192e1ec7f114',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -539,7 +539,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'c3bfa61aedfbf47d6d7b6d524ac1037ecc9c2134',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '2c7a5d6a83b6dc798b44fa6b7eae99e75939fb61',
       'condition': 'checkout_linux',
   },
 
@@ -564,7 +564,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '60b9b6fb9147c8cd512c886bf3969ea114358a56',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '7e3c67f2c3322f146e8e81fabb8d85dde1d04a3c',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -1031,10 +1031,10 @@
     Var('chromium_git') + '/external/selenium/py.git' + '@' + '5fd78261a75fe08d27ca4835fb6c5ce4b42275bd',
 
   'src/third_party/webgl/src':
-    Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'a5c263cc63ffc2cc189b5214074c8792067c1853',
+    Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '21dbf06b5aa6c7dc8cf56314d4a3f96f57956c53',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '881fe53d1faefe135c0d6959794da91a25e247f2',
+    Var('webrtc_git') + '/src.git' + '@' + '94ef424b3160262f0f8298b8abd47c29bb9ee3da',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1068,7 +1068,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@9cf0f36d349f5a09b7a11970eb7342f455436845',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@74ff6430d6c49ea128b77cb514b7db0e174b19a3',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java b/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java
index f70531e..2893a8d 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java
@@ -52,6 +52,7 @@
 
     public void setContainerView(View containerView) {
         mContainerView = containerView;
+        mContainerView.setClickable(true);
     }
 
     @Override
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsContainerViewTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsContainerViewTest.java
new file mode 100644
index 0000000..e40243e
--- /dev/null
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsContainerViewTest.java
@@ -0,0 +1,40 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.android_webview.test;
+
+import android.support.test.filters.SmallTest;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.test.util.Feature;
+
+/**
+ * AwContents container view tests.
+ */
+@RunWith(AwJUnit4ClassRunner.class)
+public class AwContentsContainerViewTest {
+    @Rule
+    public AwActivityTestRule mActivityTestRule = new AwActivityTestRule();
+
+    private TestAwContentsClient mContentsClient;
+    private AwTestContainerView mContainerView;
+
+    @Before
+    public void setUp() throws Exception {
+        mContentsClient = new TestAwContentsClient();
+        mContainerView = mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient);
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"AndroidWebView"})
+    public void testContainerViewClickable() throws Throwable {
+        Assert.assertTrue(mContainerView.isClickable());
+    }
+}
diff --git a/android_webview/renderer/aw_content_renderer_client.cc b/android_webview/renderer/aw_content_renderer_client.cc
index e0d61e8..51338987 100644
--- a/android_webview/renderer/aw_content_renderer_client.cc
+++ b/android_webview/renderer/aw_content_renderer_client.cc
@@ -26,7 +26,6 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/printing/renderer/print_render_frame_helper.h"
-#include "components/safe_browsing/renderer/websocket_sb_handshake_throttle.h"
 #include "components/supervised_user_error_page/gin_wrapper.h"
 #include "components/supervised_user_error_page/supervised_user_error_page_android.h"
 #include "components/visitedlink/renderer/visitedlink_slave.h"
@@ -284,18 +283,6 @@
   AwAddKeySystems(key_systems);
 }
 
-// TODO(nhiroki): Remove this once the off-main-thread WebSocket is enabled by
-// default (https://crbug.com/825740).
-std::unique_ptr<blink::WebSocketHandshakeThrottle>
-AwContentRendererClient::CreateWebSocketHandshakeThrottle() {
-  if (!UsingSafeBrowsingMojoService())
-    return nullptr;
-  // This is called only for Shared Worker and Service Worker that don't have a
-  // real frame, so we specify MSG_ROUTING_NONE here.
-  return std::make_unique<safe_browsing::WebSocketSBHandshakeThrottle>(
-      safe_browsing_.get(), MSG_ROUTING_NONE);
-}
-
 std::unique_ptr<content::WebSocketHandshakeThrottleProvider>
 AwContentRendererClient::CreateWebSocketHandshakeThrottleProvider() {
   return std::make_unique<AwWebSocketHandshakeThrottleProvider>();
@@ -364,16 +351,4 @@
       interface_name, std::move(interface_pipe));
 }
 
-// TODO(nhiroki): Remove this once the off-main-thread WebSocket is enabled by
-// default (https://crbug.com/825740).
-bool AwContentRendererClient::UsingSafeBrowsingMojoService() {
-  if (safe_browsing_)
-    return true;
-  if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
-    return false;
-  RenderThread::Get()->GetConnector()->BindInterface(
-      content::mojom::kBrowserServiceName, &safe_browsing_);
-  return true;
-}
-
 }  // namespace android_webview
diff --git a/android_webview/renderer/aw_content_renderer_client.h b/android_webview/renderer/aw_content_renderer_client.h
index 509e0f8..8b8bf37a 100644
--- a/android_webview/renderer/aw_content_renderer_client.h
+++ b/android_webview/renderer/aw_content_renderer_client.h
@@ -11,7 +11,6 @@
 #include "android_webview/renderer/aw_render_thread_observer.h"
 #include "base/compiler_specific.h"
 #include "base/memory/weak_ptr.h"
-#include "components/safe_browsing/common/safe_browsing.mojom.h"
 #include "components/spellcheck/spellcheck_buildflags.h"
 #include "components/web_restrictions/interfaces/web_restrictions.mojom.h"
 #include "content/public/renderer/content_renderer_client.h"
@@ -49,8 +48,6 @@
   void AddSupportedKeySystems(
       std::vector<std::unique_ptr<::media::KeySystemProperties>>* key_systems)
       override;
-  std::unique_ptr<blink::WebSocketHandshakeThrottle>
-  CreateWebSocketHandshakeThrottle() override;
   std::unique_ptr<content::WebSocketHandshakeThrottleProvider>
   CreateWebSocketHandshakeThrottleProvider() override;
   bool HandleNavigation(content::RenderFrame* render_frame,
@@ -71,14 +68,9 @@
   void GetInterface(const std::string& name,
                     mojo::ScopedMessagePipeHandle request_handle) override;
 
-  // Returns |true| if we should use the SafeBrowsing mojo service. Initialises
-  // |safe_browsing_| on the first call as a side-effect.
-  bool UsingSafeBrowsingMojoService();
-
   std::unique_ptr<AwRenderThreadObserver> aw_render_thread_observer_;
   std::unique_ptr<visitedlink::VisitedLinkSlave> visited_link_slave_;
   web_restrictions::mojom::WebRestrictionsPtr web_restrictions_service_;
-  safe_browsing::mojom::SafeBrowsingPtr safe_browsing_;
 
 #if BUILDFLAG(ENABLE_SPELLCHECK)
   std::unique_ptr<SpellCheck> spellcheck_;
diff --git a/android_webview/test/BUILD.gn b/android_webview/test/BUILD.gn
index 32343b5..31fead04 100644
--- a/android_webview/test/BUILD.gn
+++ b/android_webview/test/BUILD.gn
@@ -172,6 +172,7 @@
     "../javatests/src/org/chromium/android_webview/test/AwContentsClientShouldInterceptRequestTest.java",
     "../javatests/src/org/chromium/android_webview/test/AwContentsClientShouldOverrideUrlLoadingTest.java",
     "../javatests/src/org/chromium/android_webview/test/AwContentsClientVisitedHistoryTest.java",
+    "../javatests/src/org/chromium/android_webview/test/AwContentsContainerViewTest.java",
     "../javatests/src/org/chromium/android_webview/test/AwContentsGarbageCollectionTest.java",
     "../javatests/src/org/chromium/android_webview/test/AwContentsLifecycleNotifierTest.java",
     "../javatests/src/org/chromium/android_webview/test/AwContentsRenderTest.java",
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index 736ea9d..5c8cd6c 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -1408,13 +1408,13 @@
         Managed by <ph name="DOMAIN">$1<ex>yourdomain.com</ex></ph>
       </message>
       <message name="IDS_ASH_LOGIN_PUBLIC_ACCOUNT_MONITORING_WARNING" desc="Template for text shown in the public account user pod, informing the user that this is a public, managed account.">
-        The device admin may be able to monitor your activity.
+        The device manager may be able to monitor your activity.
       </message>
       <message name="IDS_ASH_LOGIN_PUBLIC_ACCOUNT_SIGNOUT_REMINDER" desc="Text shown in the public account user pod, reminding the user to log out.">
-        Your information will be removed when you sign out. <ph name="LEARN_MORE">$1<ex>Learn more</ex></ph>
+        Your session will be cleared when you sign out. <ph name="LEARN_MORE">$1<ex>Learn more</ex></ph>
       </message>
       <message name="IDS_ASH_LOGIN_PUBLIC_SESSION_LANGUAGE_AND_INPUT" desc="Link in public session pod that shows a section which allows the user to change the UI language and keyboard layout.">
-        Language and input
+        Choose language and input
       </message>
       <message name="IDS_ASH_LOGIN_LANGUAGE_SELECTION_SELECT" desc="Label for language selection dropdown">
         Set your language
diff --git a/ash/display/display_prefs.cc b/ash/display/display_prefs.cc
index 2800af8..c1f14ae 100644
--- a/ash/display/display_prefs.cc
+++ b/ash/display/display_prefs.cc
@@ -898,15 +898,22 @@
   LoadDisplayMixedMirrorModeParams(local_state);
   LoadDisplayRotationState(local_state);
   LoadDisplayTouchAssociations(local_state);
-  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+
+  // Ensure that we have a reasonable initial display power state if
+  // powerd fails to send us one over D-Bus. Otherwise, we won't restore
+  // displays correctly after retaking control when changing virtual terminals.
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           chromeos::switches::kFirstExecAfterBoot)) {
-    // Restore DisplayPowerState:
-    std::string value =
-        local_state->Get(prefs::kDisplayPowerState)->GetString();
-    chromeos::DisplayPowerState power_state;
-    if (GetDisplayPowerStateFromString(value, &power_state))
-      Shell::Get()->display_configurator()->SetInitialDisplayPower(power_state);
+    Shell::Get()->display_configurator()->InitializeDisplayPowerState();
+    return;
   }
+
+  // Restore DisplayPowerState:
+  const std::string value =
+      local_state->Get(prefs::kDisplayPowerState)->GetString();
+  chromeos::DisplayPowerState power_state;
+  if (GetDisplayPowerStateFromString(value, &power_state))
+    Shell::Get()->display_configurator()->SetInitialDisplayPower(power_state);
 }
 
 void DisplayPrefs::StoreDisplayRotationPrefsForTest(
diff --git a/ash/display/display_prefs_unittest.cc b/ash/display/display_prefs_unittest.cc
index 583de592..a8955848 100644
--- a/ash/display/display_prefs_unittest.cc
+++ b/ash/display/display_prefs_unittest.cc
@@ -285,6 +285,13 @@
       chromeos::switches::kFirstExecAfterBoot);
   LoadDisplayPreferences();
 
+  // requested_power_state_ should be chromeos::DISPLAY_POWER_ALL_ON at boot
+  const base::Optional<chromeos::DisplayPowerState> requested_power_state =
+      ash::Shell::Get()
+          ->display_configurator()
+          ->GetRequestedPowerStateForTest();
+  ASSERT_NE(base::nullopt, requested_power_state);
+  EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, *requested_power_state);
   // DisplayPowerState should be ignored at boot.
   EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, GetRequestedPowerState());
 
diff --git a/ash/login/ui/login_expanded_public_account_view.cc b/ash/login/ui/login_expanded_public_account_view.cc
index 456eafb3..866042a7 100644
--- a/ash/login/ui/login_expanded_public_account_view.cc
+++ b/ash/login/ui/login_expanded_public_account_view.cc
@@ -4,6 +4,10 @@
 
 #include "ash/login/ui/login_expanded_public_account_view.h"
 
+#include <memory>
+#include <utility>
+#include <vector>
+
 #include "ash/login/login_screen_controller.h"
 #include "ash/login/ui/arrow_button_view.h"
 #include "ash/login/ui/login_bubble.h"
@@ -14,6 +18,7 @@
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "base/strings/utf_string_conversions.h"
+#include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/paint_vector_icon.h"
@@ -53,7 +58,7 @@
 
 constexpr int kDropDownIconSizeDp = 16;
 constexpr int kArrowButtonSizeDp = 40;
-constexpr int kAdvancedViewButtonWidthDp = 132;
+constexpr int kAdvancedViewButtonWidthDp = 174;
 constexpr int kAdvancedViewButtonHeightDp = 16;
 constexpr int kSelectionBoxWidthDp = 178;
 constexpr int kSelectionBoxHeightDp = 28;
@@ -69,6 +74,10 @@
 constexpr int kNonEmptyWidth = 1;
 constexpr int kNonEmptyHeight = 1;
 
+constexpr char kMonitoringWarningClassName[] = "MonitoringWarning";
+constexpr int kSpacingBetweenMonitoringWarningIconAndLabelDp = 8;
+constexpr int kMonitoringWarningIconSizeDp = 20;
+
 views::Label* CreateLabel(const base::string16& text, SkColor color) {
   auto* label = new views::Label(text);
   label->SetSubpixelRenderingEnabled(false);
@@ -173,6 +182,36 @@
   DISALLOW_COPY_AND_ASSIGN(SelectionButtonView);
 };
 
+// Container for the device monitoring warning.  Contains the warning icon on
+// the left side, and text on the right side.
+class MonitoringWarningView : public NonAccessibleView {
+ public:
+  MonitoringWarningView() : NonAccessibleView(kMonitoringWarningClassName) {
+    SetLayoutManager(std::make_unique<views::BoxLayout>(
+        views::BoxLayout::kHorizontal, gfx::Insets(),
+        kSpacingBetweenMonitoringWarningIconAndLabelDp));
+
+    views::ImageView* image = new views::ImageView();
+    image->SetImage(gfx::CreateVectorIcon(
+        vector_icons::kWarningIcon, kMonitoringWarningIconSizeDp, SK_ColorRED));
+    image->SetPreferredSize(
+        gfx::Size(kMonitoringWarningIconSizeDp, kMonitoringWarningIconSizeDp));
+    AddChildView(image);
+
+    const base::string16 label_text = l10n_util::GetStringUTF16(
+        IDS_ASH_LOGIN_PUBLIC_ACCOUNT_MONITORING_WARNING);
+    views::Label* label = CreateLabel(label_text, SK_ColorWHITE);
+    label->SetMultiLine(true);
+    label->SetLineHeight(kTextLineHeightDp);
+    AddChildView(label);
+  }
+
+  ~MonitoringWarningView() override = default;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MonitoringWarningView);
+};
+
 // Implements the right part of the expanded public session view.
 class RightPaneView : public NonAccessibleView,
                       public views::ButtonListener,
@@ -192,12 +231,8 @@
         views::BoxLayout::kVertical, gfx::Insets(), kSpacingBetweenLabelsDp));
     AddChildView(labels_view_);
 
-    views::Label* top_label =
-        CreateLabel(l10n_util::GetStringUTF16(
-                        IDS_ASH_LOGIN_PUBLIC_ACCOUNT_MONITORING_WARNING),
-                    SK_ColorWHITE);
-    top_label->SetMultiLine(true);
-    top_label->SetLineHeight(kTextLineHeightDp);
+    auto* top_container = new MonitoringWarningView();
+    labels_view_->AddChildView(top_container);
 
     const base::string16 link = l10n_util::GetStringUTF16(IDS_ASH_LEARN_MORE);
     size_t offset;
@@ -217,8 +252,6 @@
     bottom_label->AddStyleRange(gfx::Range(offset, offset + link.length()),
                                 link_style);
     bottom_label->set_auto_color_readability_enabled(false);
-
-    labels_view_->AddChildView(top_label);
     labels_view_->AddChildView(bottom_label);
 
     // Create button to show/hide advanced view.
diff --git a/ash/message_center/message_center_controller.cc b/ash/message_center/message_center_controller.cc
index a5dece58..426b5078 100644
--- a/ash/message_center/message_center_controller.cc
+++ b/ash/message_center/message_center_controller.cc
@@ -118,6 +118,7 @@
                                        &kNotificationGoogleIcon,
                                        &kNotificationImageIcon,
                                        &kNotificationInstalledIcon,
+                                       &kNotificationLinuxIcon,
                                        &kNotificationMultiDeviceSetupIcon,
                                        &kNotificationMobileDataIcon,
                                        &kNotificationMobileDataOffIcon,
diff --git a/ash/public/cpp/vector_icons/BUILD.gn b/ash/public/cpp/vector_icons/BUILD.gn
index 1b8a1b9..aab0436 100644
--- a/ash/public/cpp/vector_icons/BUILD.gn
+++ b/ash/public/cpp/vector_icons/BUILD.gn
@@ -17,6 +17,7 @@
     "notification_google.icon",
     "notification_image.icon",
     "notification_installed.icon",
+    "notification_linux.icon",
     "notification_mobile_data.icon",
     "notification_mobile_data_off.icon",
     "notification_multi_device_setup.icon",
diff --git a/ash/public/cpp/vector_icons/notification_linux.icon b/ash/public/cpp/vector_icons/notification_linux.icon
new file mode 100644
index 0000000..a19a0e7
--- /dev/null
+++ b/ash/public/cpp/vector_icons/notification_linux.icon
@@ -0,0 +1,58 @@
+// 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.
+
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 4.91f, 13.94f,
+R_CUBIC_TO, -1.71f, -0.71f, -2.81f, -2.15f, -2.85f, -4.66f,
+R_CUBIC_TO, -0.17f, 0.09f, -0.37f, 0.11f, -0.6f, 0.02f,
+R_CUBIC_TO, -0.65f, -0.24f, -0.5f, -1.06f, -0.27f, -1.78f,
+R_CUBIC_TO, 0.2f, -0.6f, 0.87f, -1.04f, 1.2f, -1.13f,
+CUBIC_TO, 3.17f, 3.37f, 4.97f, 1, 8, 1,
+R_CUBIC_TO, 3.07f, 0, 4.88f, 2.27f, 5.63f, 5.39f,
+R_CUBIC_TO, 0.34f, 0.11f, 0.98f, 0.54f, 1.17f, 1.12f,
+R_CUBIC_TO, 0.24f, 0.72f, 0.38f, 1.54f, -0.27f, 1.78f,
+R_CUBIC_TO, -0.23f, 0.08f, -0.42f, 0.07f, -0.6f, -0.02f,
+R_CUBIC_TO, -0.03f, 2.53f, -1.13f, 3.96f, -2.85f, 4.67f,
+R_CUBIC_TO, 0.03f, 0.06f, 0.04f, 0.12f, 0.04f, 0.19f,
+R_CUBIC_TO, 0, 0.48f, 0.23f, 0.87f, -1.44f, 0.87f,
+R_CUBIC_TO, -1.21f, 0, -1.42f, -0.26f, -1.45f, -0.55f,
+R_CUBIC_TO, -0.08f, -0.05f, -0.16f, -0.13f, -0.24f, -0.13f,
+R_CUBIC_TO, -0.08f, 0, -0.16f, 0.08f, -0.24f, 0.14f,
+CUBIC_TO, 7.73f, 14.74f, 7.52f, 15, 6.31f, 15,
+R_CUBIC_TO, -1.66f, 0, -1.44f, -0.39f, -1.44f, -0.87f,
+R_CUBIC_TO, 0, -0.07f, 0.01f, -0.14f, 0.04f, -0.19f,
+CLOSE,
+MOVE_TO, 8, 12.86f,
+R_CUBIC_TO, 3.2f, 0, 4.35f, -1.4f, 4.35f, -4.51f,
+R_CUBIC_TO, 0, -2.57f, -1.05f, -4.94f, -2.79f, -5.33f,
+CUBIC_TO, 9, 2.9f, 8.61f, 4.27f, 8, 4.27f,
+R_CUBIC_TO, -0.61f, 0, -1.06f, -1.38f, -1.56f, -1.25f,
+R_CUBIC_TO, -1.75f, 0.44f, -2.79f, 2.9f, -2.79f, 5.33f,
+R_CUBIC_TO, 0, 2.93f, 1.15f, 4.51f, 4.35f, 4.51f,
+CLOSE,
+MOVE_TO, 5.83f, 6.83f,
+R_CUBIC_TO, -0.4f, 0, -0.72f, -0.33f, -0.72f, -0.74f,
+R_CUBIC_TO, 0, -0.41f, 0.32f, -0.74f, 0.72f, -0.74f,
+R_CUBIC_TO, 0.4f, 0, 0.72f, 0.33f, 0.72f, 0.74f,
+R_CUBIC_TO, 0, 0.41f, -0.32f, 0.74f, -0.72f, 0.74f,
+CLOSE,
+R_MOVE_TO, 4.34f, 0,
+R_CUBIC_TO, -0.4f, 0, -0.72f, -0.33f, -0.72f, -0.74f,
+R_CUBIC_TO, 0, -0.41f, 0.32f, -0.74f, 0.72f, -0.74f,
+R_CUBIC_TO, 0.4f, 0, 0.72f, 0.33f, 0.72f, 0.74f,
+R_CUBIC_TO, 0, 0.41f, -0.32f, 0.74f, -0.72f, 0.74f,
+CLOSE,
+R_MOVE_TO, -2.04f, 0.4f,
+R_LINE_TO, 0.99f, 0.45f,
+R_CUBIC_TO, 0.17f, 0.08f, 0.25f, 0.28f, 0.17f, 0.46f,
+R_ARC_TO, 0.35f, 0.35f, 0, 0, 1, -0.06f, 0.09f,
+LINE_TO, 8.25f, 9.32f,
+R_CUBIC_TO, -0.13f, 0.14f, -0.34f, 0.15f, -0.48f, 0.02f,
+R_ARC_TO, 0.34f, 0.34f, 0, 0, 1, -0.02f, -0.02f,
+LINE_TO, 6.76f, 8.23f,
+R_CUBIC_TO, -0.13f, -0.14f, -0.12f, -0.36f, 0.02f, -0.49f,
+R_ARC_TO, 0.34f, 0.34f, 0, 0, 1, 0.09f, -0.06f,
+R_LINE_TO, 0.98f, -0.45f,
+R_ARC_TO, 0.34f, 0.34f, 0, 0, 1, 0.28f, 0,
+CLOSE
diff --git a/ash/wm/non_client_frame_controller.cc b/ash/wm/non_client_frame_controller.cc
index d1e8402..1f22b10 100644
--- a/ash/wm/non_client_frame_controller.cc
+++ b/ash/wm/non_client_frame_controller.cc
@@ -421,6 +421,10 @@
   return window_ && window_->GetProperty(aura::client::kTitleShownKey);
 }
 
+void NonClientFrameController::DeleteDelegate() {
+  delete this;
+}
+
 views::Widget* NonClientFrameController::GetWidget() {
   return widget_;
 }
diff --git a/ash/wm/non_client_frame_controller.h b/ash/wm/non_client_frame_controller.h
index 6752a1c4..33f2c352 100644
--- a/ash/wm/non_client_frame_controller.h
+++ b/ash/wm/non_client_frame_controller.h
@@ -86,6 +86,7 @@
   bool CanMinimize() const override;
   bool CanActivate() const override;
   bool ShouldShowWindowTitle() const override;
+  void DeleteDelegate() override;
   views::Widget* GetWidget() override;
   const views::Widget* GetWidget() const override;
   views::View* GetContentsView() override;
diff --git a/base/containers/span.h b/base/containers/span.h
index f1e0000..0666159 100644
--- a/base/containers/span.h
+++ b/base/containers/span.h
@@ -79,6 +79,27 @@
                      ContainerHasConvertibleData<Container, T>::value &&
                      ContainerHasIntegralSize<Container>::value>;
 
+// A helper template for storing the size of a span. Spans with static extents
+// don't require additional storage, since the extent itself is specified in the
+// template parameter.
+template <size_t Extent>
+class ExtentStorage {
+ public:
+  constexpr explicit ExtentStorage(size_t size) noexcept {}
+  constexpr size_t size() const noexcept { return Extent; }
+};
+
+// Specialization of ExtentStorage for dynamic extents, which do require
+// explicit storage for the size.
+template <>
+struct ExtentStorage<dynamic_extent> {
+  constexpr explicit ExtentStorage(size_t size) noexcept : size_(size) {}
+  constexpr size_t size() const noexcept { return size_; }
+
+ private:
+  size_t size_;
+};
+
 }  // namespace internal
 
 // A span is a value type that represents an array of elements of type T. Since
@@ -167,7 +188,10 @@
 
 // [span], class template span
 template <typename T, size_t Extent>
-class span {
+class span : public internal::ExtentStorage<Extent> {
+ private:
+  using ExtentStorage = internal::ExtentStorage<Extent>;
+
  public:
   using element_type = T;
   using value_type = std::remove_cv_t<T>;
@@ -182,11 +206,12 @@
   static constexpr index_type extent = Extent;
 
   // [span.cons], span constructors, copy, assignment, and destructor
-  constexpr span() noexcept : data_(nullptr), size_(0) {
+  constexpr span() noexcept : ExtentStorage(0), data_(nullptr) {
     static_assert(Extent == dynamic_extent || Extent == 0, "Invalid Extent");
   }
 
-  constexpr span(T* data, size_t size) noexcept : data_(data), size_(size) {
+  constexpr span(T* data, size_t size) noexcept
+      : ExtentStorage(size), data_(data) {
     CHECK(Extent == dynamic_extent || Extent == size);
   }
 
@@ -304,7 +329,7 @@
   }
 
   // [span.obs], span observers
-  constexpr size_t size() const noexcept { return size_; }
+  constexpr size_t size() const noexcept { return ExtentStorage::size(); }
   constexpr size_t size_bytes() const noexcept { return size() * sizeof(T); }
   constexpr bool empty() const noexcept { return size() == 0; }
 
@@ -346,7 +371,6 @@
 
  private:
   T* data_;
-  size_t size_;
 };
 
 // span<T, Extent>::extent can not be declared inline prior to C++17, hence this
diff --git a/base/fuchsia/async_dispatcher.cc b/base/fuchsia/async_dispatcher.cc
index b25b9f7..4896578c 100644
--- a/base/fuchsia/async_dispatcher.cc
+++ b/base/fuchsia/async_dispatcher.cc
@@ -91,13 +91,13 @@
   ops_storage_.v1.set_guest_bell_trap = SetGuestBellTrapOp;
   ops = &ops_storage_;
 
-  DCHECK(!async_get_default());
-  async_set_default(this);
+  DCHECK(!async_get_default_dispatcher());
+  async_set_default_dispatcher(this);
 }
 
 AsyncDispatcher::~AsyncDispatcher() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  DCHECK_EQ(async_get_default(), this);
+  DCHECK_EQ(async_get_default_dispatcher(), this);
 
   // Some waits and tasks may be canceled while the dispatcher is being
   // destroyed, so pop-from-head until none remain.
@@ -116,7 +116,7 @@
     task->handler(this, task, ZX_ERR_CANCELED);
   }
 
-  async_set_default(nullptr);
+  async_set_default_dispatcher(nullptr);
 }
 
 zx_status_t AsyncDispatcher::DispatchOrWaitUntil(zx_time_t deadline) {
@@ -165,34 +165,38 @@
   ZX_DCHECK(status == ZX_OK, status);
 }
 
-zx_time_t AsyncDispatcher::NowOp(async_t* async) {
+zx_time_t AsyncDispatcher::NowOp(async_dispatcher_t* async) {
   DCHECK(async);
   return zx_clock_get(ZX_CLOCK_MONOTONIC);
 }
 
-zx_status_t AsyncDispatcher::BeginWaitOp(async_t* async, async_wait_t* wait) {
+zx_status_t AsyncDispatcher::BeginWaitOp(async_dispatcher_t* async,
+                                         async_wait_t* wait) {
   return static_cast<AsyncDispatcher*>(async)->BeginWait(wait);
 }
 
-zx_status_t AsyncDispatcher::CancelWaitOp(async_t* async, async_wait_t* wait) {
+zx_status_t AsyncDispatcher::CancelWaitOp(async_dispatcher_t* async,
+                                          async_wait_t* wait) {
   return static_cast<AsyncDispatcher*>(async)->CancelWait(wait);
 }
 
-zx_status_t AsyncDispatcher::PostTaskOp(async_t* async, async_task_t* task) {
+zx_status_t AsyncDispatcher::PostTaskOp(async_dispatcher_t* async,
+                                        async_task_t* task) {
   return static_cast<AsyncDispatcher*>(async)->PostTask(task);
 }
 
-zx_status_t AsyncDispatcher::CancelTaskOp(async_t* async, async_task_t* task) {
+zx_status_t AsyncDispatcher::CancelTaskOp(async_dispatcher_t* async,
+                                          async_task_t* task) {
   return static_cast<AsyncDispatcher*>(async)->CancelTask(task);
 }
 
-zx_status_t AsyncDispatcher::QueuePacketOp(async_t* async,
+zx_status_t AsyncDispatcher::QueuePacketOp(async_dispatcher_t* async,
                                            async_receiver_t* receiver,
                                            const zx_packet_user_t* data) {
   return ZX_ERR_NOT_SUPPORTED;
 }
 
-zx_status_t AsyncDispatcher::SetGuestBellTrapOp(async_t* async,
+zx_status_t AsyncDispatcher::SetGuestBellTrapOp(async_dispatcher_t* async,
                                                 async_guest_bell_trap_t* trap,
                                                 zx_handle_t guest,
                                                 zx_vaddr_t addr,
diff --git a/base/fuchsia/async_dispatcher.h b/base/fuchsia/async_dispatcher.h
index e464d30..0d6d59641 100644
--- a/base/fuchsia/async_dispatcher.h
+++ b/base/fuchsia/async_dispatcher.h
@@ -19,7 +19,7 @@
 
 // Implementation of dispatcher for Fuchsia's async library. It's necessary to
 // run Fuchsia's library on chromium threads.
-class BASE_EXPORT AsyncDispatcher : public async_t {
+class BASE_EXPORT AsyncDispatcher : public async_dispatcher_t {
  public:
   AsyncDispatcher();
   ~AsyncDispatcher();
@@ -38,15 +38,17 @@
   class WaitState;
   class TaskState;
 
-  static zx_time_t NowOp(async_t* async);
-  static zx_status_t BeginWaitOp(async_t* async, async_wait_t* wait);
-  static zx_status_t CancelWaitOp(async_t* async, async_wait_t* wait);
-  static zx_status_t PostTaskOp(async_t* async, async_task_t* task);
-  static zx_status_t CancelTaskOp(async_t* async, async_task_t* task);
-  static zx_status_t QueuePacketOp(async_t* async,
+  static zx_time_t NowOp(async_dispatcher_t* async);
+  static zx_status_t BeginWaitOp(async_dispatcher_t* async, async_wait_t* wait);
+  static zx_status_t CancelWaitOp(async_dispatcher_t* async,
+                                  async_wait_t* wait);
+  static zx_status_t PostTaskOp(async_dispatcher_t* async, async_task_t* task);
+  static zx_status_t CancelTaskOp(async_dispatcher_t* async,
+                                  async_task_t* task);
+  static zx_status_t QueuePacketOp(async_dispatcher_t* async,
                                    async_receiver_t* receiver,
                                    const zx_packet_user_t* data);
-  static zx_status_t SetGuestBellTrapOp(async_t* async,
+  static zx_status_t SetGuestBellTrapOp(async_dispatcher_t* async,
                                         async_guest_bell_trap_t* trap,
                                         zx_handle_t guest,
                                         zx_vaddr_t addr,
diff --git a/base/fuchsia/async_dispatcher_unittest.cc b/base/fuchsia/async_dispatcher_unittest.cc
index 351bbedb..74a5ae13 100644
--- a/base/fuchsia/async_dispatcher_unittest.cc
+++ b/base/fuchsia/async_dispatcher_unittest.cc
@@ -25,7 +25,9 @@
     deadline = 0;
   }
 
-  static void TaskProc(async_t* async, async_task_t* task, zx_status_t status);
+  static void TaskProc(async_dispatcher_t* async,
+                       async_task_t* task,
+                       zx_status_t status);
 
   int num_calls = 0;
   int repeats = 1;
@@ -34,10 +36,10 @@
 };
 
 // static
-void TestTask::TaskProc(async_t* async,
+void TestTask::TaskProc(async_dispatcher_t* async,
                         async_task_t* task,
                         zx_status_t status) {
-  EXPECT_EQ(async, async_get_default());
+  EXPECT_EQ(async, async_get_default_dispatcher());
   EXPECT_TRUE(status == ZX_OK || status == ZX_ERR_CANCELED)
       << "status: " << status;
 
@@ -61,7 +63,7 @@
     trigger = signals;
   }
 
-  static void HandleProc(async_t* async,
+  static void HandleProc(async_dispatcher_t* async,
                          async_wait_t* wait,
                          zx_status_t status,
                          const zx_packet_signal_t* signal);
@@ -71,11 +73,11 @@
 };
 
 // static
-void TestWait::HandleProc(async_t* async,
+void TestWait::HandleProc(async_dispatcher_t* async,
                           async_wait_t* wait,
                           zx_status_t status,
                           const zx_packet_signal_t* signal) {
-  EXPECT_EQ(async, async_get_default());
+  EXPECT_EQ(async, async_get_default_dispatcher());
   EXPECT_TRUE(status == ZX_OK || status == ZX_ERR_CANCELED)
       << "status: " << status;
 
@@ -95,7 +97,7 @@
   AsyncDispatcherTest() {
     dispatcher_ = std::make_unique<AsyncDispatcher>();
 
-    async_ = async_get_default();
+    async_ = async_get_default_dispatcher();
     EXPECT_TRUE(async_);
 
     EXPECT_EQ(zx::socket::create(ZX_SOCKET_DATAGRAM, &socket1_, &socket2_),
@@ -117,7 +119,7 @@
  protected:
   std::unique_ptr<AsyncDispatcher> dispatcher_;
 
-  async_t* async_ = nullptr;
+  async_dispatcher_t* async_ = nullptr;
 
   zx::socket socket1_;
   zx::socket socket2_;
diff --git a/base/fuchsia/service_directory.cc b/base/fuchsia/service_directory.cc
index 32eaaa5..52e77c64 100644
--- a/base/fuchsia/service_directory.cc
+++ b/base/fuchsia/service_directory.cc
@@ -18,7 +18,7 @@
 namespace fuchsia {
 
 ServiceDirectory::ServiceDirectory(zx::channel directory_request) {
-  zx_status_t status = svc_dir_create(async_get_default(),
+  zx_status_t status = svc_dir_create(async_get_default_dispatcher(),
                                       directory_request.release(), &svc_dir_);
   ZX_CHECK(status == ZX_OK, status);
 }
diff --git a/base/message_loop/incoming_task_queue.cc b/base/message_loop/incoming_task_queue.cc
index c05c38f..6821730f 100644
--- a/base/message_loop/incoming_task_queue.cc
+++ b/base/message_loop/incoming_task_queue.cc
@@ -72,6 +72,9 @@
   }
 #endif
 
+  if (!delay.is_zero())
+    UMA_HISTOGRAM_LONG_TIMES("MessageLoop.DelayedTaskQueue.PostedDelay", delay);
+
   return PostPendingTask(&pending_task);
 }
 
@@ -82,7 +85,7 @@
 
 void IncomingTaskQueue::ReportMetricsOnIdle() const {
   UMA_HISTOGRAM_COUNTS_1M(
-      "MessageLoop.DelayedTaskQueueForUI.PendingTasksCountOnIdle",
+      "MessageLoop.DelayedTaskQueue.PendingTasksCountOnIdle",
       delayed_tasks_.Size());
 }
 
diff --git a/base/message_loop/message_loop.cc b/base/message_loop/message_loop.cc
index 3723960a..1b76cbb3 100644
--- a/base/message_loop/message_loop.cc
+++ b/base/message_loop/message_loop.cc
@@ -15,6 +15,7 @@
 #include "base/message_loop/message_pump_default.h"
 #include "base/message_loop/message_pump_for_io.h"
 #include "base/message_loop/message_pump_for_ui.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/run_loop.h"
 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
 #include "base/threading/thread_id_name_manager.h"
@@ -35,6 +36,37 @@
   return pump;
 }
 
+enum class ScheduledWakeupResult {
+  // The MessageLoop went to sleep with a timeout and woke up because of that
+  // timeout.
+  kCompleted,
+  // The MessageLoop went to sleep with a timeout but was woken up before it
+  // fired.
+  kInterrupted,
+};
+
+// Reports a ScheduledWakeup's result when waking up from a non-infinite sleep.
+// Reports are using a 14 day spread (maximum examined delay for
+// https://crbug.com/850450#c3), with 50 buckets that still yields 7 buckets
+// under 16ms and hence plenty of resolution.
+void ReportScheduledWakeupResult(ScheduledWakeupResult result,
+                                 TimeDelta intended_sleep) {
+  switch (result) {
+    case ScheduledWakeupResult::kCompleted:
+      UMA_HISTOGRAM_CUSTOM_TIMES("MessageLoop.ScheduledSleep.Completed",
+                                 intended_sleep,
+                                 base::TimeDelta::FromMilliseconds(1),
+                                 base::TimeDelta::FromDays(14), 50);
+      break;
+    case ScheduledWakeupResult::kInterrupted:
+      UMA_HISTOGRAM_CUSTOM_TIMES("MessageLoop.ScheduledSleep.Interrupted",
+                                 intended_sleep,
+                                 base::TimeDelta::FromMilliseconds(1),
+                                 base::TimeDelta::FromDays(14), 50);
+      break;
+  }
+}
+
 }  // namespace
 
 class MessageLoop::Controller : public internal::IncomingTaskQueue::Observer {
@@ -464,6 +496,20 @@
 
   // Execute oldest task.
   while (incoming_task_queue_->triage_tasks().HasTasks()) {
+    if (!scheduled_wakeup_.next_run_time.is_null()) {
+      // While the frontmost task may racily be ripe. The MessageLoop was awaken
+      // without needing the timeout anyways. Since this metric is about
+      // determining whether sleeping for long periods ever succeeds: it's
+      // easier to just consider any untriaged task as an interrupt (this also
+      // makes the logic simpler for untriaged delayed tasks which may alter the
+      // top of the task queue prior to DoDelayedWork() but did cause a wakeup
+      // regardless -- per currently requiring this immediate triage step even
+      // for long delays).
+      ReportScheduledWakeupResult(ScheduledWakeupResult::kInterrupted,
+                                  scheduled_wakeup_.intended_sleep);
+      scheduled_wakeup_ = ScheduledWakeup();
+    }
+
     PendingTask pending_task = incoming_task_queue_->triage_tasks().Pop();
     if (pending_task.task.IsCancelled())
       continue;
@@ -487,9 +533,27 @@
 }
 
 bool MessageLoop::DoDelayedWork(TimeTicks* next_delayed_work_time) {
-  if (!task_execution_allowed_ ||
-      !incoming_task_queue_->delayed_tasks().HasTasks()) {
+  if (!task_execution_allowed_) {
     *next_delayed_work_time = TimeTicks();
+    // |scheduled_wakeup_| isn't used in nested loops that don't process
+    // application tasks.
+    DCHECK(scheduled_wakeup_.next_run_time.is_null());
+    return false;
+  }
+
+  if (!incoming_task_queue_->delayed_tasks().HasTasks()) {
+    *next_delayed_work_time = TimeTicks();
+
+    // It's possible to be woken up by a system event and have it cancel the
+    // upcoming delayed task from under us before DoDelayedWork() -- see comment
+    // under |next_run_time > recent_time_|. This condition covers the special
+    // case where such a system event cancelled *all* pending delayed tasks.
+    if (!scheduled_wakeup_.next_run_time.is_null()) {
+      ReportScheduledWakeupResult(ScheduledWakeupResult::kInterrupted,
+                                  scheduled_wakeup_.intended_sleep);
+      scheduled_wakeup_ = ScheduledWakeup();
+    }
+
     return false;
   }
 
@@ -507,10 +571,36 @@
     recent_time_ = TimeTicks::Now();  // Get a better view of Now();
     if (next_run_time > recent_time_) {
       *next_delayed_work_time = CapAtOneDay(next_run_time);
+
+      // If the loop was woken up early by an untriaged task:
+      // |scheduled_wakeup_| will have been handled already in DoWork(). If it
+      // wasn't, it means the early wake up was caused by a system event (e.g.
+      // MessageLoopForUI or IO).
+      if (!scheduled_wakeup_.next_run_time.is_null()) {
+        // Handling the system event may have resulted in cancelling the
+        // upcoming delayed task (and then it being pruned by
+        // DelayedTaskQueue::HasTasks()); hence, we cannot check for strict
+        // equality here. We can however check that the pending task is either
+        // still there or that a later delay replaced it in front of the queue.
+        // There shouldn't have been new tasks added in |delayed_tasks()| per
+        // DoWork() not having triaged new tasks since the last DoIdleWork().
+        DCHECK_GE(next_run_time, scheduled_wakeup_.next_run_time);
+
+        ReportScheduledWakeupResult(ScheduledWakeupResult::kInterrupted,
+                                    scheduled_wakeup_.intended_sleep);
+        scheduled_wakeup_ = ScheduledWakeup();
+      }
+
       return false;
     }
   }
 
+  if (next_run_time == scheduled_wakeup_.next_run_time) {
+    ReportScheduledWakeupResult(ScheduledWakeupResult::kCompleted,
+                                scheduled_wakeup_.intended_sleep);
+    scheduled_wakeup_ = ScheduledWakeup();
+  }
+
   PendingTask pending_task = incoming_task_queue_->delayed_tasks().Pop();
 
   if (incoming_task_queue_->delayed_tasks().HasTasks()) {
@@ -529,19 +619,43 @@
   bool need_high_res_timers = false;
 #endif
 
-  // Do not report idle metrics if about to quit the loop and/or in a nested
-  // loop where |!task_execution_allowed_|. In the former case, the loop isn't
-  // going to sleep and in the latter case DoDelayedWork() will not actually do
-  // the work this is prepping for.
+  // Do not report idle metrics nor do any logic related to delayed tasks if
+  // about to quit the loop and/or in a nested loop where
+  // |!task_execution_allowed_|. In the former case, the loop isn't going to
+  // sleep and in the latter case DoDelayedWork() will not actually do the work
+  // this is prepping for.
   if (ShouldQuitWhenIdle()) {
     pump_->Quit();
   } else if (task_execution_allowed_) {
-    // Only track idle metrics in MessageLoopForUI to avoid too much contention
-    // logging the histogram (https://crbug.com/860801) -- there's typically
-    // only one UI thread per process and, for practical purposes, restricting
-    // the MessageLoop diagnostic metrics to it yields similar information.
-    if (type_ == TYPE_UI)
-      incoming_task_queue_->ReportMetricsOnIdle();
+    incoming_task_queue_->ReportMetricsOnIdle();
+
+    if (incoming_task_queue_->delayed_tasks().HasTasks()) {
+      TimeTicks scheduled_wakeup_time =
+          incoming_task_queue_->delayed_tasks().Peek().delayed_run_time;
+
+      if (!scheduled_wakeup_.next_run_time.is_null()) {
+        // It's possible for DoIdleWork() to be invoked twice in a row (e.g. if
+        // the MessagePump processed system work and became idle twice in a row
+        // without application tasks in between -- some pumps with a native
+        // message loop do not invoke DoWork() / DoDelayedWork() when awaken for
+        // system work only). As in DoDelayedWork(), we cannot check for strict
+        // equality below as the system work may have cancelled the frontmost
+        // task.
+        DCHECK_GE(scheduled_wakeup_time, scheduled_wakeup_.next_run_time);
+
+        ReportScheduledWakeupResult(ScheduledWakeupResult::kInterrupted,
+                                    scheduled_wakeup_.intended_sleep);
+        scheduled_wakeup_ = ScheduledWakeup();
+      }
+
+      // Store the remaining delay as well as the programmed wakeup time in
+      // order to know next time this MessageLoop wakes up whether it woke up
+      // because of this pending task (is it still the frontmost task in the
+      // queue?) and be able to report the slept delta (which is lost if not
+      // saved here).
+      scheduled_wakeup_ = ScheduledWakeup{
+          scheduled_wakeup_time, scheduled_wakeup_time - TimeTicks::Now()};
+    }
 
 #if defined(OS_WIN)
     // On Windows we activate the high resolution timer so that the wait
diff --git a/base/message_loop/message_loop.h b/base/message_loop/message_loop.h
index 7c31a12..ab49d87 100644
--- a/base/message_loop/message_loop.h
+++ b/base/message_loop/message_loop.h
@@ -287,6 +287,15 @@
   // A recent snapshot of Time::Now(), used to check delayed_work_queue_.
   TimeTicks recent_time_;
 
+  // Non-null when the last thing this MessageLoop did is become idle with
+  // pending delayed tasks. Used to report metrics on the following wake up.
+  struct ScheduledWakeup {
+    // The scheduled time of the next delayed task when this loop became idle.
+    TimeTicks next_run_time;
+    // The delta until |next_run_time| when this loop became idle.
+    TimeDelta intended_sleep;
+  } scheduled_wakeup_;
+
   ObserverList<DestructionObserver> destruction_observers_;
 
   // A boolean which prevents unintentional reentrant task execution (e.g. from
diff --git a/base/message_loop/message_loop_unittest.cc b/base/message_loop/message_loop_unittest.cc
index 202c1d62..1a21fc5 100644
--- a/base/message_loop/message_loop_unittest.cc
+++ b/base/message_loop/message_loop_unittest.cc
@@ -24,7 +24,6 @@
 #include "base/synchronization/waitable_event.h"
 #include "base/task_scheduler/task_scheduler.h"
 #include "base/test/gtest_util.h"
-#include "base/test/metrics/histogram_tester.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/platform_thread.h"
@@ -1759,33 +1758,6 @@
   run_loop.Run();
 }
 
-#if defined(OS_MACOSX)
-// This metric is a bit broken on Mac OS because CFRunLoop doesn't
-// deterministically invoke MessageLoop::DoIdleWork(). This being a temporary
-// diagnosis metric, we let this fly and simply not test it on Mac.
-#define MAYBE_MetricsOnlyFromUILoops DISABLED_MetricsOnlyFromUILoops
-#else
-#define MAYBE_MetricsOnlyFromUILoops MetricsOnlyFromUILoops
-#endif
-
-TEST_P(MessageLoopTypedTest, MAYBE_MetricsOnlyFromUILoops) {
-  MessageLoop loop(GetMessageLoopType());
-
-  const bool histograms_expected = GetMessageLoopType() == MessageLoop::TYPE_UI;
-
-  HistogramTester histogram_tester;
-
-  // Loop that goes idle with one pending task.
-  RunLoop run_loop;
-  loop.task_runner()->PostDelayedTask(FROM_HERE, run_loop.QuitClosure(),
-                                      TimeDelta::FromMilliseconds(1));
-  run_loop.Run();
-
-  histogram_tester.ExpectTotalCount(
-      "MessageLoop.DelayedTaskQueueForUI.PendingTasksCountOnIdle",
-      histograms_expected ? 1 : 0);
-}
-
 INSTANTIATE_TEST_CASE_P(
     ,
     MessageLoopTypedTest,
diff --git a/base/message_loop/message_pump_fuchsia.cc b/base/message_loop/message_pump_fuchsia.cc
index 91585fc..78e9717 100644
--- a/base/message_loop/message_pump_fuchsia.cc
+++ b/base/message_loop/message_pump_fuchsia.cc
@@ -67,7 +67,7 @@
 
 // static
 void MessagePumpFuchsia::ZxHandleWatchController::HandleSignal(
-    async_t* async,
+    async_dispatcher_t* async,
     async_wait_t* wait,
     zx_status_t status,
     const zx_packet_signal_t* signal) {
diff --git a/base/message_loop/message_pump_fuchsia.h b/base/message_loop/message_pump_fuchsia.h
index 514e23f..ebd56e5c 100644
--- a/base/message_loop/message_pump_fuchsia.h
+++ b/base/message_loop/message_pump_fuchsia.h
@@ -50,7 +50,7 @@
 
     virtual bool WaitBegin();
 
-    static void HandleSignal(async_t* async,
+    static void HandleSignal(async_dispatcher_t* async,
                              async_wait_t* wait,
                              zx_status_t status,
                              const zx_packet_signal_t* signal);
diff --git a/base/time/time_win.cc b/base/time/time_win.cc
index 9c6eba03..b3e1c03a 100644
--- a/base/time/time_win.cc
+++ b/base/time/time_win.cc
@@ -511,11 +511,6 @@
   return TimeTicks() + QPCValueToTimeDelta(QPCNowRaw());
 }
 
-bool IsBuggyAthlon(const CPU& cpu) {
-  // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is unreliable.
-  return cpu.vendor_name() == "AuthenticAMD" && cpu.family() == 15;
-}
-
 void InitializeNowFunctionPointer() {
   LARGE_INTEGER ticks_per_sec = {};
   if (!QueryPerformanceFrequency(&ticks_per_sec))
@@ -527,15 +522,13 @@
   // If the QPC implementation is expensive and/or unreliable, TimeTicks::Now()
   // will still use the low-resolution clock. A CPU lacking a non-stop time
   // counter will cause Windows to provide an alternate QPC implementation that
-  // works, but is expensive to use. Certain Athlon CPUs are known to make the
-  // QPC implementation unreliable.
+  // works, but is expensive to use.
   //
   // Otherwise, Now uses the high-resolution QPC clock. As of 21 August 2015,
   // ~72% of users fall within this category.
   TimeTicksNowFunction now_function;
   CPU cpu;
-  if (ticks_per_sec.QuadPart <= 0 ||
-      !cpu.has_non_stop_time_stamp_counter() || IsBuggyAthlon(cpu)) {
+  if (ticks_per_sec.QuadPart <= 0 || !cpu.has_non_stop_time_stamp_counter()) {
     now_function = &RolloverProtectedNow;
   } else {
     now_function = &QPCNow;
@@ -647,8 +640,7 @@
 
 // static
 bool ThreadTicks::IsSupportedWin() {
-  static bool is_supported =
-      CPU().has_non_stop_time_stamp_counter() && !IsBuggyAthlon(CPU());
+  static bool is_supported = CPU().has_non_stop_time_stamp_counter();
   return is_supported;
 }
 
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 959a592..51e8946 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -1482,6 +1482,9 @@
           # TODO(thakis): Only for no_chromium_code? http://crbug.com/505314
           "-Wno-ignored-pragma-optimize",
         ]
+        if (llvm_force_head_revision) {
+          cflags += [ "-Wno-memset-transposed-args" ]
+        }
       }
     }
   }
diff --git a/build/config/sysroot.gni b/build/config/sysroot.gni
index d5daf2d..701c660 100644
--- a/build/config/sysroot.gni
+++ b/build/config/sysroot.gni
@@ -68,10 +68,8 @@
   sysroot = ios_sdk_path
 } else if (is_fuchsia) {
   import("//build/config/fuchsia/config.gni")
-  if (current_cpu == "arm64") {
-    sysroot = fuchsia_sdk + "/sysroot/aarch64-fuchsia"
-  } else if (current_cpu == "x64") {
-    sysroot = fuchsia_sdk + "/sysroot/x86_64-fuchsia"
+  if (current_cpu == "arm64" || current_cpu == "x64") {
+    sysroot = fuchsia_sdk + "/arch/$current_cpu/sysroot"
   } else {
     sysroot = ""
   }
diff --git a/build/fuchsia/sdk.sha1 b/build/fuchsia/sdk.sha1
index 52f580cb..3ab722c2 100644
--- a/build/fuchsia/sdk.sha1
+++ b/build/fuchsia/sdk.sha1
@@ -1 +1 @@
-9b4813214fa05bed350c3beef2650fa7a0604aca
\ No newline at end of file
+6c386aff8be4b0fd98e393b7778a78fd016eb219
\ No newline at end of file
diff --git a/cc/paint/image_transfer_cache_entry.cc b/cc/paint/image_transfer_cache_entry.cc
index c902b64..fe63071a 100644
--- a/cc/paint/image_transfer_cache_entry.cc
+++ b/cc/paint/image_transfer_cache_entry.cc
@@ -75,9 +75,9 @@
   safe_size += sizeof(uint32_t);  // width
   safe_size += sizeof(uint32_t);  // height
   safe_size += sizeof(uint32_t);  // has mips
-  safe_size += sizeof(uint64_t) + alignof(uint64_t);  // pixels size
-  safe_size += target_color_space_size + sizeof(uint64_t) + alignof(uint64_t);
-  safe_size += pixmap_color_space_size + sizeof(uint64_t) + alignof(uint64_t);
+  safe_size += sizeof(size_t);    // pixels size
+  safe_size += target_color_space_size + sizeof(size_t);
+  safe_size += pixmap_color_space_size + sizeof(size_t);
   // Include 4 bytes of padding so we can always align our data pointer to a
   // 4-byte boundary.
   safe_size += 4;
diff --git a/cc/paint/paint_filter.cc b/cc/paint/paint_filter.cc
index 0e0bd00..f410b27 100644
--- a/cc/paint/paint_filter.cc
+++ b/cc/paint/paint_filter.cc
@@ -443,7 +443,7 @@
 size_t AlphaThresholdPaintFilter::SerializedSize() const {
   size_t region_size = region_.writeToMemory(nullptr);
   base::CheckedNumeric<size_t> total_size;
-  total_size = BaseSerializedSize() + sizeof(uint64_t) + region_size +
+  total_size = BaseSerializedSize() + sizeof(region_size) + region_size +
                sizeof(inner_min_) + sizeof(outer_max_);
   total_size += GetFilterSize(input_.get());
   return total_size.ValueOrDefault(0u);
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h
index 909f0cd..c1477a1 100644
--- a/cc/paint/paint_op_buffer.h
+++ b/cc/paint/paint_op_buffer.h
@@ -877,7 +877,9 @@
 class CC_PAINT_EXPORT PaintOpBuffer : public SkRefCnt {
  public:
   enum { kInitialBufferSize = 4096 };
-  static constexpr size_t PaintOpAlign = 8;
+  // It's not necessarily the case that the op with the maximum alignment
+  // requirements is also the biggest op, but for now that's true.
+  static constexpr size_t PaintOpAlign = alignof(DrawDRRectOp);
   static inline size_t ComputeOpSkip(size_t sizeof_op) {
     return MathUtil::UncheckedRoundUp(sizeof_op, PaintOpBuffer::PaintOpAlign);
   }
diff --git a/cc/paint/paint_op_reader.cc b/cc/paint/paint_op_reader.cc
index 99b1d82..ee3301f 100644
--- a/cc/paint/paint_op_reader.cc
+++ b/cc/paint/paint_op_reader.cc
@@ -117,7 +117,7 @@
 template <typename T>
 void PaintOpReader::ReadFlattenable(sk_sp<T>* val) {
   size_t bytes = 0;
-  ReadSize(&bytes);
+  ReadSimple(&bytes);
   if (remaining_bytes_ < bytes)
     SetInvalid();
   if (!valid_)
@@ -154,10 +154,7 @@
 }
 
 void PaintOpReader::ReadSize(size_t* size) {
-  AlignMemory(8);
-  uint64_t size64;
-  ReadSimple(&size64);
-  *size = size64;
+  ReadSimple(size);
 }
 
 void PaintOpReader::Read(SkScalar* data) {
@@ -215,13 +212,19 @@
   ReadSimple(&flags->blend_mode_);
   ReadSimple(&flags->bitfields_uint_);
 
+  // Flattenables must be read at 4-byte boundary, which should be the case
+  // here.
+  AlignMemory(4);
   ReadFlattenable(&flags->path_effect_);
+  AlignMemory(4);
   ReadFlattenable(&flags->mask_filter_);
+  AlignMemory(4);
   ReadFlattenable(&flags->color_filter_);
 
+  AlignMemory(4);
   if (enable_security_constraints_) {
     size_t bytes = 0;
-    ReadSize(&bytes);
+    ReadSimple(&bytes);
     if (bytes != 0u) {
       SetInvalid();
       return;
@@ -328,7 +331,7 @@
 
 void PaintOpReader::Read(sk_sp<SkData>* data) {
   size_t bytes = 0;
-  ReadSize(&bytes);
+  ReadSimple(&bytes);
   if (remaining_bytes_ < bytes)
     SetInvalid();
   if (!valid_)
@@ -375,7 +378,7 @@
 
 void PaintOpReader::Read(scoped_refptr<PaintTextBlob>* paint_blob) {
   size_t data_bytes = 0u;
-  ReadSize(&data_bytes);
+  ReadSimple(&data_bytes);
   if (remaining_bytes_ < data_bytes || data_bytes == 0u)
     SetInvalid();
   if (!valid_)
@@ -455,7 +458,7 @@
     shader_size = post_size - pre_size + record_size;
   }
   decltype(ref.colors_)::size_type colors_size = 0;
-  ReadSize(&colors_size);
+  ReadSimple(&colors_size);
 
   // If there are too many colors, abort.
   if (colors_size > kMaxShaderColorsSupported) {
@@ -471,7 +474,7 @@
   ReadData(colors_bytes, ref.colors_.data());
 
   decltype(ref.positions_)::size_type positions_size = 0;
-  ReadSize(&positions_size);
+  ReadSimple(&positions_size);
   // Positions are optional. If they exist, they have the same count as colors.
   if (positions_size > 0 && positions_size != colors_size) {
     SetInvalid();
@@ -1185,9 +1188,9 @@
 
 size_t PaintOpReader::Read(sk_sp<PaintRecord>* record) {
   size_t size_bytes = 0;
-  ReadSize(&size_bytes);
-
+  ReadSimple(&size_bytes);
   AlignMemory(PaintOpBuffer::PaintOpAlign);
+
   if (enable_security_constraints_) {
     // Validate that the record was not serialized if security constraints are
     // enabled.
@@ -1216,7 +1219,7 @@
 
 void PaintOpReader::Read(SkRegion* region) {
   size_t region_bytes = 0;
-  ReadSize(&region_bytes);
+  ReadSimple(&region_bytes);
   if (region_bytes == 0 || region_bytes > kMaxRegionByteSize)
     SetInvalid();
   if (!valid_)
diff --git a/cc/paint/paint_op_writer.cc b/cc/paint/paint_op_writer.cc
index afba0a6..9426b0d 100644
--- a/cc/paint/paint_op_writer.cc
+++ b/cc/paint/paint_op_writer.cc
@@ -39,7 +39,7 @@
 size_t PaintOpWriter::GetFlattenableSize(const SkFlattenable* flattenable) {
   // The first bit is always written to indicate the serialized size of the
   // flattenable, or zero if it doesn't exist.
-  size_t total_size = sizeof(uint64_t) + alignof(uint64_t);
+  size_t total_size = sizeof(size_t);
   if (!flattenable)
     return total_size;
 
@@ -60,7 +60,7 @@
     image_size += sizeof(info.colorType());
     image_size += sizeof(info.width());
     image_size += sizeof(info.height());
-    image_size += sizeof(uint64_t) + alignof(uint64_t);
+    image_size += sizeof(size_t);
     image_size += info.computeMinByteSize();
   }
   return image_size;
@@ -72,7 +72,7 @@
   // TODO(khushalsagar): Querying the size of a PaintRecord is not supported.
   // This works only for security constrained serialization which ignores
   // records.
-  return sizeof(uint64_t);
+  return sizeof(size_t);
 }
 
 PaintOpWriter::PaintOpWriter(void* memory,
@@ -104,13 +104,14 @@
 }
 
 void PaintOpWriter::WriteFlattenable(const SkFlattenable* val) {
-  AlignMemory(8);
+  DCHECK(SkIsAlign4(reinterpret_cast<uintptr_t>(memory_)))
+      << "Flattenable must start writing at 4 byte alignment.";
   if (!val) {
     WriteSize(static_cast<size_t>(0u));
     return;
   }
 
-  size_t size_offset = sizeof(uint64_t);
+  size_t size_offset = sizeof(size_t);
   EnsureBytes(size_offset);
   if (!valid_)
     return;
@@ -124,14 +125,13 @@
     valid_ = false;
     return;
   }
-  reinterpret_cast<uint64_t*>(size_memory)[0] = bytes_written;
+  reinterpret_cast<size_t*>(size_memory)[0] = bytes_written;
   memory_ += bytes_written;
   remaining_bytes_ -= bytes_written;
 }
 
 void PaintOpWriter::WriteSize(size_t size) {
-  AlignMemory(8);
-  WriteSimple<uint64_t>(size);
+  WriteSimple(size);
 }
 
 void PaintOpWriter::Write(SkScalar data) {
@@ -185,10 +185,16 @@
   WriteSimple(flags.blend_mode_);
   WriteSimple(flags.bitfields_uint_);
 
+  // Flattenables must be written starting at a 4 byte boundary, which should be
+  // the case here.
+  AlignMemory(4);
   WriteFlattenable(flags.path_effect_.get());
+  AlignMemory(4);
   WriteFlattenable(flags.mask_filter_.get());
+  AlignMemory(4);
   WriteFlattenable(flags.color_filter_.get());
 
+  AlignMemory(4);
   if (enable_security_constraints_)
     WriteSize(static_cast<size_t>(0u));
   else
@@ -295,10 +301,8 @@
   if (!valid_)
     return;
 
-  AlignMemory(8);
-
   const auto& blob = paint_blob->ToSkTextBlob();
-  size_t size_offset = sizeof(uint64_t);
+  size_t size_offset = sizeof(size_t);
   EnsureBytes(size_offset);
   if (!valid_)
     return;
@@ -321,7 +325,7 @@
     valid_ = false;
     return;
   }
-  reinterpret_cast<uint64_t*>(size_memory)[0] = bytes_written;
+  reinterpret_cast<size_t*>(size_memory)[0] = bytes_written;
   memory_ += bytes_written;
   remaining_bytes_ -= bytes_written;
 }
@@ -417,10 +421,10 @@
     Write(false);
   }
 
-  WriteSize(shader->colors_.size());
+  WriteSimple(shader->colors_.size());
   WriteData(shader->colors_.size() * sizeof(SkColor), shader->colors_.data());
 
-  WriteSize(shader->positions_.size());
+  WriteSimple(shader->positions_.size());
   WriteData(shader->positions_.size() * sizeof(SkScalar),
             shader->positions_.data());
   // Explicitly don't write the cached_shader_ because that can be regenerated
@@ -732,12 +736,10 @@
                           const gfx::Rect& playback_rect,
                           const gfx::SizeF& post_scale,
                           const SkMatrix& post_matrix_for_analysis) {
-  AlignMemory(PaintOpBuffer::PaintOpAlign);
-
   // We need to record how many bytes we will serialize, but we don't know this
   // information until we do the serialization. So, skip the amount needed
   // before writing.
-  size_t size_offset = sizeof(uint64_t);
+  size_t size_offset = sizeof(size_t);
   EnsureBytes(size_offset);
   if (!valid_)
     return;
@@ -746,6 +748,7 @@
 
   memory_ += size_offset;
   remaining_bytes_ -= size_offset;
+  AlignMemory(PaintOpBuffer::PaintOpAlign);
   if (!valid_)
     return;
 
@@ -774,7 +777,7 @@
 
   // Write the size to the size memory, which preceeds the memory for the
   // record.
-  reinterpret_cast<uint64_t*>(size_memory)[0] = serializer.written();
+  reinterpret_cast<size_t*>(size_memory)[0] = serializer.written();
 
   // The serializer should have failed if it ran out of space. DCHECK to verify
   // that it wrote at most as many bytes as we had left.
@@ -789,7 +792,7 @@
   size_t bytes_written = region.writeToMemory(data.get());
   DCHECK_EQ(bytes_required, bytes_written);
 
-  WriteSize(bytes_written);
+  WriteSimple(bytes_written);
   WriteData(bytes_written, data.get());
 }
 
diff --git a/cc/paint/paint_typeface_transfer_cache_entry.cc b/cc/paint/paint_typeface_transfer_cache_entry.cc
index 41c4d39..34def03d 100644
--- a/cc/paint/paint_typeface_transfer_cache_entry.cc
+++ b/cc/paint/paint_typeface_transfer_cache_entry.cc
@@ -90,13 +90,13 @@
       writer->WriteSimple(typeface_.ttc_index());
       break;
     case PaintTypeface::Type::kFilenameAndTtcIndex:
-      writer->template WriteSimple<uint64_t>(typeface_.filename().size());
+      writer->WriteSimple(typeface_.filename().size());
       writer->WriteData(typeface_.filename().size(),
                         typeface_.filename().data());
       writer->WriteSimple(typeface_.ttc_index());
       break;
     case PaintTypeface::Type::kFamilyNameAndFontStyle:
-      writer->template WriteSimple<uint64_t>(typeface_.family_name().size());
+      writer->WriteSimple(typeface_.family_name().size());
       writer->WriteData(typeface_.family_name().size(),
                         typeface_.family_name().data());
       writer->WriteSimple(typeface_.font_style().weight());
@@ -151,7 +151,7 @@
     }
     case PaintTypeface::Type::kFilenameAndTtcIndex: {
       size_t size;
-      ReadSize(&size);
+      ReadSimple(&size);
       if (!valid_ || size > kMaxFilenameSize) {
         valid_ = false;
         return false;
@@ -170,7 +170,7 @@
     }
     case PaintTypeface::Type::kFamilyNameAndFontStyle: {
       size_t size;
-      ReadSize(&size);
+      ReadSimple(&size);
       if (!valid_ || size > kMaxFamilyNameSize) {
         valid_ = false;
         return false;
@@ -212,12 +212,6 @@
   data_ = data_.subspan(sizeof(T));
 }
 
-void ServicePaintTypefaceTransferCacheEntry::ReadSize(size_t* size) {
-  uint64_t size64;
-  ReadSimple(&size64);
-  *size = size64;
-}
-
 void ServicePaintTypefaceTransferCacheEntry::ReadData(size_t bytes,
                                                       void* data) {
   if (data_.size() < bytes)
diff --git a/cc/paint/paint_typeface_transfer_cache_entry.h b/cc/paint/paint_typeface_transfer_cache_entry.h
index 294df15..f1c1e75 100644
--- a/cc/paint/paint_typeface_transfer_cache_entry.h
+++ b/cc/paint/paint_typeface_transfer_cache_entry.h
@@ -44,7 +44,6 @@
  private:
   template <typename T>
   void ReadSimple(T* val);
-  void ReadSize(size_t* size);
 
   void ReadData(size_t bytes, void* data);
 
diff --git a/chrome/VERSION b/chrome/VERSION
index 2446765..2dc3113 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=70
 MINOR=0
-BUILD=3498
+BUILD=3501
 PATCH=0
diff --git a/chrome/android/java/res/layout/downloads_empty_view.xml b/chrome/android/java/res/layout/downloads_empty_view.xml
new file mode 100644
index 0000000..a15ffa7
--- /dev/null
+++ b/chrome/android/java/res/layout/downloads_empty_view.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
+
+    <TextView
+        android:id="@+id/empty_view"
+        android:layout_marginTop="100dp"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center"
+        android:drawablePadding="3dp"
+        android:textAppearance="@style/BlackDisabledText1"/>
+
+</FrameLayout>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java
index f00bbe01d..6388313 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java
@@ -13,7 +13,6 @@
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.TextView;
 
 import org.chromium.base.ObserverList;
 import org.chromium.base.metrics.RecordHistogram;
@@ -56,7 +55,6 @@
     private boolean mMuteFilterChanges;
     private boolean mIsSeparateActivity;
     private int mSearchMenuId;
-    private TextView mEmptyView;
 
     private SelectionDelegate<ListItem> mSelectionDelegate;
 
@@ -89,7 +87,10 @@
                 (ViewGroup) LayoutInflater.from(mActivity).inflate(R.layout.download_main, null);
         mSelectableListLayout =
                 (SelectableListLayout<ListItem>) mMainView.findViewById(R.id.selectable_list);
-        mEmptyView = mSelectableListLayout.initializeEmptyView(
+
+        // TODO(shaktisahu): Maybe refactor SelectableListLayout to work without supplying empty
+        // view.
+        mSelectableListLayout.initializeEmptyView(
                 VectorDrawableCompat.create(
                         mActivity.getResources(), R.drawable.downloads_big, mActivity.getTheme()),
                 R.string.download_manager_ui_empty, R.string.download_manager_no_results);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListCoordinator.java
index 3ccddde..6fc68d6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListCoordinator.java
@@ -44,7 +44,7 @@
     }
 
     private final FilterCoordinator mFilterCoordinator;
-
+    private final EmptyViewCoordinator mEmptyViewCoordinator;
     private final DateOrderedListMediator mMediator;
     private final DateOrderedListView mView;
 
@@ -74,6 +74,10 @@
                 : new FilterCoordinatorWithNoTabs(context, mMediator.getFilterSource());
         mFilterCoordinator.addObserver(mMediator::onFilterTypeSelected);
         mFilterCoordinator.addObserver(filterObserver);
+
+        mEmptyViewCoordinator =
+                new EmptyViewCoordinator(context, decoratedModel, mMediator.getFilterSource());
+        mFilterCoordinator.addObserver(mEmptyViewCoordinator::onFilterTypeSelected);
         decoratedModel.setHeader(new ViewListItem(Long.MAX_VALUE, mFilterCoordinator.getView()));
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DecoratedListItemModel.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DecoratedListItemModel.java
index f7ff29c70..2ef08103 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DecoratedListItemModel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DecoratedListItemModel.java
@@ -21,6 +21,7 @@
     private final ListItemModel mModel;
 
     private ViewListItem mHeaderItem;
+    private ViewListItem mEmptyViewItem;
 
     /** Creates a {@link DecoratedListItemModel} instance that wraos {@code model}. */
     public DecoratedListItemModel(ListItemModel model) {
@@ -49,15 +50,41 @@
         }
     }
 
+    /**
+     * Adds {@code item} as a empty view for the list.  Clears the empty view if it is {@code
+     * null}. Empty view must be the second item in the list after the header. If there is no
+     * header, it must be the first item in the list.
+     */
+    public void setEmptyView(ViewListItem item) {
+        if (mEmptyViewItem == item) return;
+
+        int index = mHeaderItem == null ? 0 : 1;
+
+        ViewListItem oldEmptyView = mEmptyViewItem;
+        mEmptyViewItem = item;
+
+        if (oldEmptyView != null && item == null) {
+            notifyItemRemoved(index);
+        } else if (oldEmptyView == null && item != null) {
+            notifyItemInserted(index);
+        } else {
+            notifyItemRangeChanged(index, 1);
+        }
+    }
+
     // SimpleList implementation.
     @Override
     public int size() {
-        return mModel.size() + (mHeaderItem == null ? 0 : 1);
+        return mModel.size() + (mHeaderItem == null ? 0 : 1) + (mEmptyViewItem == null ? 0 : 1);
     }
 
     @Override
     public ListItem get(int index) {
-        if (index == 0 && mHeaderItem != null) return mHeaderItem;
+        if (mHeaderItem != null || mEmptyViewItem != null) {
+            if (index == 0) return mHeaderItem != null ? mHeaderItem : mEmptyViewItem;
+            if (index == 1 && mEmptyViewItem != null) return mEmptyViewItem;
+        }
+
         return mModel.get(convertIndexForSource(index));
     }
 
@@ -80,10 +107,12 @@
     }
 
     private int convertIndexForSource(int index) {
-        return mHeaderItem == null ? index : index - 1;
+        int offset = (mHeaderItem == null ? 0 : 1) + (mEmptyViewItem == null ? 0 : 1);
+        return index - offset;
     }
 
     private int convertIndexFromSource(int index) {
-        return mHeaderItem == null ? index : index + 1;
+        int offset = (mHeaderItem == null ? 0 : 1) + (mEmptyViewItem == null ? 0 : 1);
+        return index + offset;
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/EmptyViewCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/EmptyViewCoordinator.java
new file mode 100644
index 0000000..53e34ba0
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/EmptyViewCoordinator.java
@@ -0,0 +1,105 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.download.home.list;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.support.graphics.drawable.VectorDrawableCompat;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.download.home.filter.Filters;
+import org.chromium.chrome.browser.download.home.filter.OfflineItemFilterObserver;
+import org.chromium.chrome.browser.download.home.filter.OfflineItemFilterSource;
+import org.chromium.chrome.browser.download.home.list.ListItem.ViewListItem;
+import org.chromium.components.offline_items_collection.OfflineItem;
+
+import java.util.Collection;
+
+/**
+ * A class that determines whether an empty view should be shown and inserts into the model.
+ */
+class EmptyViewCoordinator implements OfflineItemFilterObserver {
+    private final Context mContext;
+    private final DecoratedListItemModel mDecoratedModel;
+    private final OfflineItemFilterSource mSource;
+    private final Handler mHandler = new Handler();
+
+    private ViewListItem mEmptyViewItem;
+
+    private @Filters.FilterType int mCurrentFilter;
+
+    /** Creates a {@link EmptyViewCoordinator} instance that wraos {@code model}. */
+    public EmptyViewCoordinator(Context context, DecoratedListItemModel decoratedModel,
+            OfflineItemFilterSource source) {
+        mContext = context;
+        mDecoratedModel = decoratedModel;
+        mSource = source;
+        mSource.addObserver(this);
+        mHandler.post(() -> onFilterTypeSelected(mCurrentFilter));
+    }
+
+    public void onFilterTypeSelected(@Filters.FilterType int filter) {
+        boolean hasEmptyView = mEmptyViewItem != null;
+        if (filter == mCurrentFilter && hasEmptyView == isEmpty()) return;
+
+        mCurrentFilter = filter;
+        updateForEmptyView();
+    }
+
+    private boolean isEmpty() {
+        boolean showingPrefetch = mCurrentFilter == Filters.FilterType.PREFETCHED;
+        for (OfflineItem item : mSource.getItems()) {
+            if (showingPrefetch && item.isSuggested) return false;
+            if (!showingPrefetch && !item.isSuggested) return false;
+        }
+
+        return true;
+    }
+
+    private void updateForEmptyView() {
+        mEmptyViewItem = isEmpty() ? createEmptyView() : null;
+        mDecoratedModel.setEmptyView(mEmptyViewItem);
+    }
+
+    private ViewListItem createEmptyView() {
+        boolean showingPrefetch = mCurrentFilter == Filters.FilterType.PREFETCHED;
+        // TODO(shaktisahu): Supply correct value for prefetch settings.
+        boolean prefetchEnabled = true;
+        View emptyView = LayoutInflater.from(mContext).inflate(R.layout.downloads_empty_view, null);
+
+        Drawable emptyDrawable = VectorDrawableCompat.create(mContext.getResources(),
+                showingPrefetch ? R.drawable.ic_library_news_feed : R.drawable.downloads_big,
+                mContext.getTheme());
+
+        TextView emptyTextView = emptyView.findViewById(R.id.empty_view);
+        emptyTextView.setText(showingPrefetch
+                        ? (prefetchEnabled ? R.string.download_manager_prefetch_tab_empty
+                                           : R.string.download_manager_enable_prefetch_message)
+                        : R.string.download_manager_ui_empty);
+        emptyTextView.setCompoundDrawablesWithIntrinsicBounds(null, emptyDrawable, null, null);
+
+        return new ViewListItem(Long.MAX_VALUE - 1, emptyView);
+    }
+
+    // OfflineItemFilterObserver implementation.
+    @Override
+    public void onItemsAdded(Collection<OfflineItem> items) {
+        mHandler.post(() -> onFilterTypeSelected(mCurrentFilter));
+    }
+
+    @Override
+    public void onItemsRemoved(Collection<OfflineItem> items) {
+        mHandler.post(() -> onFilterTypeSelected(mCurrentFilter));
+    }
+
+    @Override
+    public void onItemUpdated(OfflineItem oldItem, OfflineItem item) {
+        mHandler.post(() -> onFilterTypeSelected(mCurrentFilter));
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/PreferenceUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/PreferenceUtils.java
index d47d5603..11a58db 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/PreferenceUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/PreferenceUtils.java
@@ -4,15 +4,19 @@
 
 package org.chromium.chrome.browser.preferences;
 
+import android.app.Activity;
 import android.content.Context;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
 import android.os.StrictMode;
 import android.preference.PreferenceFragment;
 import android.support.annotation.DrawableRes;
+import android.support.annotation.Nullable;
 import android.support.annotation.XmlRes;
 import android.support.v7.content.res.AppCompatResources;
+import android.support.v7.widget.ActionMenuView;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.ViewTreeObserver.OnScrollChangedListener;
 
 import org.chromium.base.ApiCompatibilityUtils;
@@ -70,4 +74,29 @@
                 PorterDuff.Mode.SRC_IN);
         return icon;
     }
+
+    /**
+     * A helper that is used to set the visibility of the overflow menu view in a given activity.
+     *
+     * @param activity The Activity containing the action bar with the menu.
+     * @param visibility The new visibility of the overflow menu view.
+     * @return True if the visibility could be set, false otherwise (e.g. because no menu exists).
+     */
+    public static boolean setOverflowMenuVisibility(@Nullable Activity activity, int visibility) {
+        if (activity == null) return false;
+        ViewGroup actionBar = activity.findViewById(org.chromium.chrome.R.id.action_bar);
+        int i = actionBar.getChildCount();
+        ActionMenuView menuView = null;
+        while (i-- > 0) {
+            if (actionBar.getChildAt(i) instanceof ActionMenuView) {
+                menuView = (ActionMenuView) actionBar.getChildAt(i);
+                break;
+            }
+        }
+        if (menuView == null) return false;
+        View overflowButton = menuView.getChildAt(menuView.getChildCount() - 1);
+        if (overflowButton == null) return false;
+        overflowButton.setVisibility(visibility);
+        return true;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/Preferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/Preferences.java
index 65278a9..843fcc9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/Preferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/Preferences.java
@@ -238,6 +238,8 @@
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
+        Fragment activeFragment = getFragmentManager().findFragmentById(android.R.id.content);
+        if (activeFragment != null && activeFragment.onOptionsItemSelected(item)) return true;
         if (item.getItemId() == android.R.id.home) {
             finish();
             return true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchUtils.java
new file mode 100644
index 0000000..3e935451
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/SearchUtils.java
@@ -0,0 +1,123 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.preferences;
+
+import android.support.annotation.NonNull;
+import android.support.v7.widget.SearchView;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.inputmethod.EditorInfo;
+import android.widget.ImageView;
+
+import javax.annotation.Nullable;
+
+/**
+ * A helper class for applying the default search behavior to search items in Chromium settings.
+ */
+public class SearchUtils {
+    /**
+     * This interface allows to react to changed search queries when initialized with
+     * {@link SearchUtils#initializeSearchView(MenuItem, String, QueryChangeListener)}.
+     */
+    public interface QueryChangeListener {
+        /**
+         * Called whenever the search query changes. This usually is immediately after a user types
+         * and doesn't wait for submission of the whole query.
+         * @param query Current query as entered by the user. Can be a partial query or empty.
+         */
+        void onQueryTextChange(String query);
+    }
+
+    /**
+     * Initializes an Android default search item by setting listeners and default states of the
+     * search icon, box and close icon.
+     * @param searchItem The existing item that can trigger the search action view.
+     * @param initialQuery The query that the search field should be opened with.
+     * @param changeListener The listener to be notified when the user changes the query.
+     */
+    public static void initializeSearchView(@NonNull MenuItem searchItem,
+            @Nullable String initialQuery, @NonNull QueryChangeListener changeListener) {
+        SearchView searchView = getSearchView(searchItem);
+        searchView.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN);
+
+        // Restore the search view if a query was recovered.
+        if (initialQuery != null) {
+            searchItem.expandActionView();
+            searchView.setIconified(false);
+            searchView.setQuery(initialQuery, false);
+        }
+
+        // Clicking the menu item hides the clear button and triggers search for an empty query.
+        searchItem.setOnMenuItemClickListener((MenuItem m) -> {
+            updateSearchClearButtonVisibility(searchItem, "");
+            changeListener.onQueryTextChange("");
+            return false; // Continue with the default action.
+        });
+
+        // Make the close button a clear button.
+        searchView.findViewById(org.chromium.chrome.R.id.search_close_btn)
+                .setOnClickListener((View v) -> {
+                    searchView.setQuery("", false);
+                    updateSearchClearButtonVisibility(searchItem, "");
+                    changeListener.onQueryTextChange("");
+                });
+
+        // Ensure that a changed search view triggers the search - independent from use code path.
+        searchView.setOnSearchClickListener(view -> {
+            updateSearchClearButtonVisibility(searchItem, "");
+            changeListener.onQueryTextChange("");
+        });
+        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+            @Override
+            public boolean onQueryTextSubmit(String query) {
+                return true; // Consume event.
+            }
+
+            @Override
+            public boolean onQueryTextChange(String query) {
+                // TODO(fhorschig) Exit early if a tracked query indicates no changes.
+                updateSearchClearButtonVisibility(searchItem, query);
+                changeListener.onQueryTextChange(query);
+                return true; // Consume event.
+            }
+        });
+    }
+
+    /**
+     * Handles an item in {@link android.support.v4.app.Fragment#onOptionsItemSelected(MenuItem)} if
+     * it is a search item and returns true. If it is not applicable, it returns false.
+     * @param selectedItem The user-selected menu item.
+     * @param searchItem The menu item known to contain the search view.
+     * @param query The current search query.
+     * @return Returns true if the item is a search item and could be handled. False otherwise.
+     */
+    public static boolean handleSearchNavigation(
+            @NonNull MenuItem selectedItem, @NonNull MenuItem searchItem, @Nullable String query) {
+        if (selectedItem.getItemId() != android.R.id.home || query == null) return false;
+        SearchView searchView = (SearchView) searchItem.getActionView();
+        searchView.setQuery(null, false);
+        searchView.setIconified(true);
+        searchItem.collapseActionView();
+        return true;
+    }
+
+    /**
+     * Shorthand to easily access a search item's action view.
+     * @param searchItem The menu item containing search item.
+     * @return The search view associated with the menu item.
+     */
+    public static SearchView getSearchView(MenuItem searchItem) {
+        return (SearchView) searchItem.getActionView();
+    }
+
+    private static void updateSearchClearButtonVisibility(MenuItem searchItem, String query) {
+        ImageView clearButton = findSearchClearButton(getSearchView(searchItem));
+        clearButton.setVisibility(query == null || query.equals("") ? View.GONE : View.VISIBLE);
+    }
+
+    private static ImageView findSearchClearButton(SearchView searchView) {
+        return searchView.findViewById(org.chromium.chrome.R.id.search_close_btn);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java
index 52829ceb..b2cd0e35 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferences.java
@@ -7,9 +7,6 @@
 import android.app.Activity;
 import android.app.FragmentManager;
 import android.content.Intent;
-import android.graphics.Color;
-import android.graphics.PorterDuff;
-import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
 import android.preference.Preference;
@@ -18,14 +15,13 @@
 import android.preference.PreferenceFragment;
 import android.preference.PreferenceGroup;
 import android.preference.PreferenceScreen;
-import android.support.v7.widget.SearchView;
+import android.support.v7.widget.Toolbar;
 import android.text.SpannableString;
 import android.text.style.ForegroundColorSpan;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
-import android.view.inputmethod.EditorInfo;
 
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.VisibleForTesting;
@@ -36,8 +32,10 @@
 import org.chromium.chrome.browser.preferences.ChromeBasePreference;
 import org.chromium.chrome.browser.preferences.ChromeSwitchPreference;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
+import org.chromium.chrome.browser.preferences.PreferenceUtils;
 import org.chromium.chrome.browser.preferences.Preferences;
 import org.chromium.chrome.browser.preferences.PreferencesLauncher;
+import org.chromium.chrome.browser.preferences.SearchUtils;
 import org.chromium.chrome.browser.preferences.TextMessagePreference;
 import org.chromium.ui.text.SpanApplier;
 
@@ -84,6 +82,7 @@
     private boolean mNoPasswordExceptions;
 
     private MenuItem mHelpItem;
+    private MenuItem mSearchItem;
 
     private String mSearchQuery;
     private Preference mLinkPref;
@@ -91,7 +90,7 @@
     private ChromeBaseCheckBoxPreference mAutoSignInSwitch;
     private TextMessagePreference mEmptyView;
     private boolean mSearchRecorded;
-    private Menu mMenuForTesting;
+    private Menu mMenu;
 
     /**
      * For controlling the UX flow of exporting passwords.
@@ -138,54 +137,19 @@
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         menu.clear();
-        mMenuForTesting = menu;
+        mMenu = menu;
         inflater.inflate(R.menu.save_password_preferences_action_bar_menu, menu);
         menu.findItem(R.id.export_passwords).setVisible(ExportFlow.providesPasswordExport());
         menu.findItem(R.id.export_passwords).setEnabled(false);
-        MenuItem searchItem = menu.findItem(R.id.menu_id_search);
-        searchItem.setVisible(providesPasswordSearch());
+        mSearchItem = menu.findItem(R.id.menu_id_search);
+        mSearchItem.setVisible(providesPasswordSearch());
         if (providesPasswordSearch()) {
             mHelpItem = menu.findItem(R.id.menu_id_general_help);
-            setUpSearchAction(searchItem);
-        }
-    }
-
-    /**
-     * Prepares the searchItem's icon and searchView. Sets up listeners to clicks and interactions
-     * with the searchItem or its searchView.
-     * @param searchItem the item containing the SearchView. Must not be null.
-     */
-    private void setUpSearchAction(MenuItem searchItem) {
-        SearchView searchView = (SearchView) searchItem.getActionView();
-        searchView.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN);
-        searchItem.setIcon(convertToPlainWhite(searchItem.getIcon()));
-        if (mSearchQuery != null) { // If a query was recovered, restore the search view.
-            searchItem.expandActionView();
-            searchView.setIconified(false);
-            searchView.setQuery(mSearchQuery, false);
-        }
-        searchItem.setOnMenuItemClickListener((MenuItem m) -> {
-            filterPasswords("");
-            return false; // Continue with the default action.
-        });
-        searchView.findViewById(R.id.search_close_btn).setOnClickListener((View v) -> {
-            searchView.setQuery(null, false);
-            searchView.setIconified(true);
-            filterPasswords(null); // Reset filter to bring back all preferences.
-        });
-        searchView.setOnSearchClickListener(view -> filterPasswords(""));
-        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
-            @Override
-            public boolean onQueryTextSubmit(String query) {
-                return true; // Continue with default action - nothing.
-            }
-
-            @Override
-            public boolean onQueryTextChange(String query) {
+            SearchUtils.initializeSearchView(mSearchItem, mSearchQuery, (query) -> {
                 maybeRecordTriggeredPasswordSearch(true);
-                return filterPasswords(query);
-            }
-        });
+                filterPasswords(query);
+            });
+        }
     }
 
     /**
@@ -214,16 +178,23 @@
             mExportFlow.startExporting();
             return true;
         }
+        if (SearchUtils.handleSearchNavigation(item, mSearchItem, mSearchQuery)) {
+            filterPasswords(null);
+            return true;
+        }
         return super.onOptionsItemSelected(item);
     }
 
-    private boolean filterPasswords(String query) {
+    private void filterPasswords(String query) {
         mSearchQuery = query;
-        // Hide the help option. It's not useful during search but might be clicked by accident.
-        mHelpItem.setShowAsAction(mSearchQuery != null ? MenuItem.SHOW_AS_ACTION_NEVER
-                                                       : MenuItem.SHOW_AS_ACTION_IF_ROOM);
+        if (mSearchQuery == null) {
+            mHelpItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+            PreferenceUtils.setOverflowMenuVisibility(getActivity(), View.VISIBLE);
+        } else {
+            mHelpItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
+            PreferenceUtils.setOverflowMenuVisibility(getActivity(), View.GONE);
+        }
         rebuildPasswordLists();
-        return false; // Query has been handled. Don't trigger default action of SearchView.
     }
 
     /**
@@ -430,19 +401,6 @@
         return true;
     }
 
-    /**
-     * Convert a given icon to a plain white version by applying the MATRIX_TRANSFORM_TO_WHITE color
-     * filter. The resulting drawable will be brighter than a usual grayscale conversion.
-     *
-     * For grayscale conversion, use the function ColorMatrix#setSaturation(0) instead.
-     * @param icon The drawable to be converted.
-     * @return Returns the bright white version of the passed drawable.
-     */
-    private static Drawable convertToPlainWhite(Drawable icon) {
-        icon.mutate().setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);
-        return icon;
-    }
-
     private void createSavePasswordsSwitch() {
         if (mSearchQuery != null) {
             return; // Don't create this option when the preferences are filtered for passwords.
@@ -530,6 +488,11 @@
 
     @VisibleForTesting
     Menu getMenuForTesting() {
-        return mMenuForTesting;
+        return mMenu;
+    }
+
+    @VisibleForTesting
+    Toolbar getToolbarForTesting() {
+        return getActivity().findViewById(R.id.action_bar);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java
index 40433e8..565f122 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.preferences.website;
 
+import static org.chromium.chrome.browser.preferences.SearchUtils.handleSearchNavigation;
+
 import android.content.DialogInterface;
 import android.content.res.Resources;
 import android.os.Build;
@@ -15,9 +17,7 @@
 import android.preference.PreferenceGroup;
 import android.preference.PreferenceScreen;
 import android.support.graphics.drawable.VectorDrawableCompat;
-import android.support.v4.view.MenuItemCompat;
 import android.support.v7.app.AlertDialog;
-import android.support.v7.widget.SearchView;
 import android.text.Spannable;
 import android.text.SpannableStringBuilder;
 import android.text.format.Formatter;
@@ -29,7 +29,6 @@
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.inputmethod.EditorInfo;
 import android.widget.Button;
 import android.widget.ListView;
 import android.widget.TextView;
@@ -51,6 +50,7 @@
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.preferences.PreferenceUtils;
 import org.chromium.chrome.browser.preferences.ProtectedContentResetCredentialConfirmDialogFragment;
+import org.chromium.chrome.browser.preferences.SearchUtils;
 import org.chromium.chrome.browser.preferences.website.Website.StoredDataClearedCallback;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.ui.widget.Toast;
@@ -80,14 +80,14 @@
 
     // The view to show when the list is empty.
     private TextView mEmptyView;
-    // The view for searching the list of items.
-    private SearchView mSearchView;
+    // The item for searching the list of items.
+    private MenuItem mSearchItem;
     // The clear button displayed in the Storage view.
     private Button mClearButton;
     // The Site Settings Category we are showing.
     private SiteSettingsCategory mCategory;
     // If not blank, represents a substring to use to search for site names.
-    private String mSearch = "";
+    private String mSearch;
     // Whether to group by allowed/blocked list.
     private boolean mGroupByAllowBlock;
     // Whether the Blocked list should be shown expanded.
@@ -327,26 +327,11 @@
         menu.clear();
         inflater.inflate(R.menu.website_preferences_menu, menu);
 
-        MenuItem searchItem = menu.findItem(R.id.search);
-        mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
-        mSearchView.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN);
-        SearchView.OnQueryTextListener queryTextListener =
-                new SearchView.OnQueryTextListener() {
-                    @Override
-                    public boolean onQueryTextSubmit(String query) {
-                        return true;
-                    }
-
-                    @Override
-                    public boolean onQueryTextChange(String query) {
-                        if (query.equals(mSearch)) return true;
-
-                        mSearch = query;
-                        getInfoForOrigins();
-                        return true;
-                    }
-                };
-        mSearchView.setOnQueryTextListener(queryTextListener);
+        mSearchItem = menu.findItem(R.id.search);
+        SearchUtils.initializeSearchView(mSearchItem, mSearch, (query) -> {
+            mSearch = query;
+            getInfoForOrigins();
+        });
 
         if (mCategory.showSites(SiteSettingsCategory.Type.PROTECTED_MEDIA)) {
             // Add a menu item to reset protected media identifier device credentials.
@@ -380,6 +365,11 @@
                     getActivity(), getString(helpContextResId), Profile.getLastUsedProfile(), null);
             return true;
         }
+        if (handleSearchNavigation(item, mSearchItem, mSearch)) {
+            mSearch = null;
+            getInfoForOrigins();
+            return true;
+        }
         return false;
     }
 
@@ -392,11 +382,11 @@
             return false;
         }
 
-        if (!mSearch.isEmpty()) {
+        if (mSearch != null) {
             // Clear out any lingering searches, so that the full list is shown
             // when coming back to this page.
-            mSearch = "";
-            mSearchView.setQuery("", false);
+            mSearch = null;
+            SearchUtils.getSearchView(mSearchItem).setQuery("", false);
         }
 
         if (preference instanceof WebsitePreference) {
@@ -605,7 +595,7 @@
 
         // Find origins matching the current search.
         for (Website site : sites) {
-            if (mSearch.isEmpty() || site.getTitle().contains(mSearch)) {
+            if (mSearch == null || mSearch.isEmpty() || site.getTitle().contains(mSearch)) {
                 websites.add(new WebsitePreference(getActivity(), site, mCategory));
             }
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java
index c68434c..52d2219 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java
@@ -192,11 +192,11 @@
         // This loop looks expensive, but the amount of data is likely to be relatively small
         // because most sites have very few permissions.
         for (Website other : websites) {
-            if (merged.getContentSettingPermission(ContentSettingException.Type.ADS) == null
-                    && other.getContentSettingPermission(ContentSettingException.Type.ADS) != null
+            if (merged.getContentSettingException(ContentSettingException.Type.ADS) == null
+                    && other.getContentSettingException(ContentSettingException.Type.ADS) != null
                     && other.compareByAddressTo(merged) == 0) {
-                merged.setContentSettingPermission(ContentSettingException.Type.ADS,
-                        other.getContentSettingPermission(ContentSettingException.Type.ADS));
+                merged.setContentSettingException(ContentSettingException.Type.ADS,
+                        other.getContentSettingException(ContentSettingException.Type.ADS));
             }
             for (@PermissionInfo.Type int type = 0; type < PermissionInfo.Type.NUM_ENTRIES;
                     type++) {
@@ -230,10 +230,10 @@
                             || type == ContentSettingException.Type.COOKIE) {
                         continue;
                     }
-                    if (merged.getContentSettingPermission(type) == null
-                            && other.getContentSettingPermission(type) != null) {
-                        merged.setContentSettingPermission(
-                                type, other.getContentSettingPermission(type));
+                    if (merged.getContentSettingException(type) == null
+                            && other.getContentSettingException(type) != null) {
+                        merged.setContentSettingException(
+                                type, other.getContentSettingException(type));
                     }
                 }
             }
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index c1b8c0e..0e09659 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -2432,6 +2432,12 @@
       <message name="IDS_DOWNLOAD_MANAGER_PREFETCH_CAPTION" desc="Text containing the prefetched article description.">
         <ph name="DESCRIPTION">%1$s<ex>www.example.com</ex></ph> - <ph name="FILE_SIZE">%2$s<ex>1.56 MB</ex></ph>
       </message>
+      <message name="IDS_DOWNLOAD_MANAGER_PREFETCH_TAB_EMPTY" desc="Tab text indicating that there is no prefetched content.">
+        No content here
+      </message>
+      <message name="IDS_DOWNLOAD_MANAGER_ENABLE_PREFETCH_MESSAGE" desc="Tab text indicating that users can enable prefetch to allow chrome to download articles on Wi-Fi.">
+        Allow Chrome to download articles for you when on Wi-Fi under settings.
+      </message>
       <message name="IDS_DOWNLOAD_MANAGER_N_HOURS" desc="How many hours ago an item was downloaded (if downloaded on the same day). [ICU Syntax]">
         {HOURS, plural, =1 {# hr} other {# hrs}}
       </message>
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index 4450c90..6a017e8 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -475,6 +475,7 @@
   "java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListView.java",
   "java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListViewAdapter.java",
   "java/src/org/chromium/chrome/browser/download/home/list/DecoratedListItemModel.java",
+  "java/src/org/chromium/chrome/browser/download/home/list/EmptyViewCoordinator.java",
   "java/src/org/chromium/chrome/browser/download/home/list/ItemUtils.java",
   "java/src/org/chromium/chrome/browser/download/home/list/ListItem.java",
   "java/src/org/chromium/chrome/browser/download/home/list/ListItemModel.java",
@@ -1088,6 +1089,7 @@
   "java/src/org/chromium/chrome/browser/preferences/ProtectedContentResetCredentialConfirmDialogFragment.java",
   "java/src/org/chromium/chrome/browser/preferences/SearchEngineAdapter.java",
   "java/src/org/chromium/chrome/browser/preferences/SearchEnginePreference.java",
+  "java/src/org/chromium/chrome/browser/preferences/SearchUtils.java",
   "java/src/org/chromium/chrome/browser/preferences/SeekBarLinkedCheckBoxPreference.java",
   "java/src/org/chromium/chrome/browser/preferences/SeekBarPreference.java",
   "java/src/org/chromium/chrome/browser/preferences/SigninExpandablePreferenceGroup.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java
index 962eef1..0d91baf 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java
@@ -39,6 +39,9 @@
 import static org.hamcrest.Matchers.sameInstance;
 import static org.hamcrest.Matchers.startsWith;
 
+import static org.chromium.chrome.test.util.ViewUtils.VIEW_GONE;
+import static org.chromium.chrome.test.util.ViewUtils.VIEW_INVISIBLE;
+import static org.chromium.chrome.test.util.ViewUtils.VIEW_NULL;
 import static org.chromium.chrome.test.util.ViewUtils.waitForView;
 
 import android.app.Activity;
@@ -1596,7 +1599,8 @@
 
         // Trigger the search, close it and wait for UI to be restored.
         Espresso.onView(withSearchMenuIdOrText()).perform(click());
-        Espresso.onView(withId(R.id.search_close_btn)).perform(click());
+        Espresso.onView(withContentDescription(R.string.abc_action_bar_up_description))
+                .perform(click());
         Espresso.onView(isRoot()).check(
                 (root, e)
                         -> waitForView(
@@ -1737,7 +1741,9 @@
         Espresso.onView(withText(R.string.section_saved_passwords_exceptions))
                 .check(doesNotExist());
 
-        Espresso.onView(withId(R.id.search_close_btn)).perform(click()); // Close search view.
+        Espresso.onView(withContentDescription(R.string.abc_action_bar_up_description))
+                .perform(click());
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync(); // Close search view.
 
         Espresso.onView(withText(R.string.section_saved_passwords_exceptions)).perform(scrollTo());
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
@@ -1754,17 +1760,43 @@
     @EnableFeatures(ChromeFeatureList.PASSWORD_SEARCH)
     public void testSearchIconClickedHidesGeneralPrefs() throws Exception {
         setPasswordSource(ZEUS_ON_EARTH);
-        PreferencesTest.startPreferences(InstrumentationRegistry.getInstrumentation(),
-                SavePasswordsPreferences.class.getName());
+        final SavePasswordsPreferences prefs =
+                (SavePasswordsPreferences) PreferencesTest
+                        .startPreferences(InstrumentationRegistry.getInstrumentation(),
+                                SavePasswordsPreferences.class.getName())
+                        .getFragmentForTest();
+        final AtomicReference<Boolean> menuInitiallyVisible = new AtomicReference<>();
+        ThreadUtils.runOnUiThreadBlocking(
+                ()
+                        -> menuInitiallyVisible.set(
+                                prefs.getToolbarForTesting().isOverflowMenuShowing()));
 
         Espresso.onView(withText(R.string.passwords_auto_signin_title))
                 .check(matches(isDisplayed()));
         Espresso.onView(withText(startsWith("View and manage"))).check(matches(isDisplayed()));
+        if (menuInitiallyVisible.get()) { // Check overflow menu only on large screens that have it.
+            Espresso.onView(withContentDescription(R.string.abc_action_menu_overflow_description))
+                    .check(matches(isDisplayed()));
+        }
 
         Espresso.onView(withSearchMenuIdOrText()).perform(click());
 
         Espresso.onView(withText(R.string.passwords_auto_signin_title)).check(doesNotExist());
         Espresso.onView(withText(startsWith("View and manage"))).check(doesNotExist());
+        Espresso.onView(isRoot()).check(
+                (root, e)
+                        -> waitForView((ViewGroup) root,
+                                withContentDescription(
+                                        R.string.abc_action_menu_overflow_description),
+                                VIEW_INVISIBLE | VIEW_GONE | VIEW_NULL));
+
+        Espresso.onView(withContentDescription(R.string.abc_action_bar_up_description))
+                .perform(click());
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+        if (menuInitiallyVisible.get()) { // If the overflow menu was there, it should be restored.
+            Espresso.onView(withContentDescription(R.string.abc_action_menu_overflow_description))
+                    .check(matches(isDisplayed()));
+        }
     }
 
     /**
@@ -1786,13 +1818,47 @@
         Espresso.onView(withText(R.string.passwords_auto_signin_title)).check(doesNotExist());
         Espresso.onView(withText(startsWith("View and manage"))).check(doesNotExist());
 
-        Espresso.pressBack(); // Close keyboard.
+        Espresso.onView(withContentDescription(R.string.abc_action_bar_up_description))
+                .perform(click());
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
-        Espresso.onView(withId(R.id.search_close_btn)).perform(click());
 
         Espresso.onView(withText(R.string.passwords_auto_signin_title))
                 .check(matches(isDisplayed()));
         Espresso.onView(withText(startsWith("View and manage"))).check(matches(isDisplayed()));
+        Espresso.onView(withId(R.id.menu_id_search)).check(matches(isDisplayed()));
+    }
+
+    /**
+     * Check that clearing the search also hides the clear button.
+     */
+    @Test
+    @SmallTest
+    @Feature({"Preferences"})
+    @EnableFeatures(ChromeFeatureList.PASSWORD_SEARCH)
+    public void testSearchViewCloseIconExistsOnlyToClearQueries() throws Exception {
+        setPasswordSourceWithMultipleEntries(GREEK_GODS);
+        PreferencesTest.startPreferences(InstrumentationRegistry.getInstrumentation(),
+                SavePasswordsPreferences.class.getName());
+
+        // Trigger search which shouldn't have the button yet.
+        Espresso.onView(withSearchMenuIdOrText()).perform(click());
+        Espresso.onView(isRoot()).check(
+                (root, e)
+                        -> waitForView((ViewGroup) root, withId(R.id.search_close_btn),
+                                VIEW_INVISIBLE | VIEW_GONE | VIEW_NULL));
+
+        // Type something and see the button appear.
+        Espresso.onView(withId(R.id.search_src_text))
+                // Trigger search which shouldn't have the button yet.
+                .perform(click(), typeText("Zeu"), closeSoftKeyboard());
+        Espresso.onView(withId(R.id.search_close_btn)).check(matches(isDisplayed()));
+
+        // Clear the search which should hide the button again.
+        Espresso.onView(withId(R.id.search_close_btn)).perform(click()); // Clear search.
+        Espresso.onView(isRoot()).check(
+                (root, e)
+                        -> waitForView((ViewGroup) root, withId(R.id.search_close_btn),
+                                VIEW_INVISIBLE | VIEW_GONE | VIEW_NULL));
     }
 
     /**
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index 689f4ad6f..d8953d8 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-69.0.3497.0_rc-r1.afdo.bz2
\ No newline at end of file
+chromeos-chrome-amd64-70.0.3500.0_rc-r1.afdo.bz2
\ No newline at end of file
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd
index 3ec42e4..d3d5d68a 100644
--- a/chrome/app/chromium_strings.grd
+++ b/chrome/app/chromium_strings.grd
@@ -839,6 +839,11 @@
 Please check your email at <ph name="ACCOUNT_EMAIL">$2<ex>jane.doe@example.com</ex></ph> for further instructions.
         </message>
 
+        <!-- Supervised users deprecation infobar -->
+        <message name="IDS_SUPERVISED_USERS_DEPRECATED_MESSAGE" desc="A message displayed on an at-launch infobar warning supervised users that this feature is deprecated and will be removed.">
+          Supervised user profiles will no longer be available starting with Chromium 70.
+        </message>
+
         <!-- User pod remove sync warning text -->
         <message name="IDS_LOGIN_POD_USER_REMOVE_WARNING_SYNC" desc="Main text shown as a warning when attempting to remove an user.">
           This person's browsing data will be deleted from this device. To recover the data, sign in to Chrome as $2.
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd
index 8f4e0e48..4552b231 100644
--- a/chrome/app/google_chrome_strings.grd
+++ b/chrome/app/google_chrome_strings.grd
@@ -850,6 +850,11 @@
 Please check your email at <ph name="ACCOUNT_EMAIL">$2<ex>jane.doe@example.com</ex></ph> for further instructions.
         </message>
 
+        <!-- Supervised users deprecation infobar -->
+        <message name="IDS_SUPERVISED_USERS_DEPRECATED_MESSAGE" desc="A message displayed on an at-launch infobar warning supervised users that this feature is deprecated and will be removed.">
+          Supervised user profiles will no longer be available starting with Google Chrome 70.
+        </message>
+
         <!-- User pod remove sync warning text -->
         <message name="IDS_LOGIN_POD_USER_REMOVE_WARNING_SYNC" desc="Main text shown as a warning when attempting to remove an user.">
           This person's browsing data will be deleted from this device. To recover the data, sign in to Chrome as $2.
diff --git a/chrome/browser/android/download/download_manager_service.cc b/chrome/browser/android/download/download_manager_service.cc
index 76a3f5a0..ab82acdc 100644
--- a/chrome/browser/android/download/download_manager_service.cc
+++ b/chrome/browser/android/download/download_manager_service.cc
@@ -206,6 +206,13 @@
   }
 }
 
+download::InProgressDownloadManager*
+DownloadManagerService::RetriveInProgressDownloadManager(
+    content::BrowserContext* context) {
+  // TODO(qinmin): return pre-created InProgressDownloadManager here.
+  return nullptr;
+}
+
 void DownloadManagerService::OpenDownload(download::DownloadItem* download,
                                           int source) {
   JNIEnv* env = base::android::AttachCurrentThread();
diff --git a/chrome/browser/android/download/download_manager_service.h b/chrome/browser/android/download/download_manager_service.h
index 2f6ce51..316d8ac 100644
--- a/chrome/browser/android/download/download_manager_service.h
+++ b/chrome/browser/android/download/download_manager_service.h
@@ -16,6 +16,7 @@
 #include "chrome/browser/android/download/download_controller.h"
 #include "chrome/browser/download/download_history.h"
 #include "components/download/content/public/all_download_item_notifier.h"
+#include "components/download/public/common/in_progress_download_manager.h"
 #include "content/public/browser/download_manager.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
@@ -134,6 +135,10 @@
                const content::NotificationSource& source,
                const content::NotificationDetails& details) override;
 
+  // Retrives the in-progress manager and give up the ownership.
+  download::InProgressDownloadManager* RetriveInProgressDownloadManager(
+      content::BrowserContext* context);
+
  protected:
   // Called to get the content::DownloadManager instance.
   virtual content::DownloadManager* GetDownloadManager(bool is_off_the_record);
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
index af54b0e..8ef6c21 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -1010,8 +1010,9 @@
   }
 
   void RemoveAllBrowsingData(int data_type_mask) override {
-    RemoveBrowsingData(data_type_mask,
-                       base::RepeatingCallback<bool(const GURL&)>());
+    ++remove_all_calls_;
+    last_data_type_mask_ = data_type_mask;
+    last_origin_filter_ = base::RepeatingCallback<bool(const GURL&)>();
   }
 
   int GetUploadDepth(const net::URLRequest& request) override {
@@ -1026,6 +1027,7 @@
   }
 
   int remove_calls() const { return remove_calls_; }
+  int remove_all_calls() const { return remove_all_calls_; }
   int last_data_type_mask() const { return last_data_type_mask_; }
   const base::RepeatingCallback<bool(const GURL&)>& last_origin_filter() const {
     return last_origin_filter_;
@@ -1033,6 +1035,7 @@
 
  private:
   int remove_calls_ = 0;
+  int remove_all_calls_ = 0;
   int last_data_type_mask_ = 0;
   base::RepeatingCallback<bool(const GURL&)> last_origin_filter_;
 
@@ -1059,16 +1062,7 @@
     request_context->set_reporting_service(old_service_);
   }
 
-  void GetMockInfo(
-      int* remove_calls_out,
-      int* last_data_type_mask_out,
-      base::RepeatingCallback<bool(const GURL&)>* last_origin_filter_out) {
-    DCHECK_NE(nullptr, service_.get());
-
-    *remove_calls_out = service_->remove_calls();
-    *last_data_type_mask_out = service_->last_data_type_mask();
-    *last_origin_filter_out = service_->last_origin_filter();
-  }
+  const MockReportingService& mock() { return *service_; }
 
  private:
   TestingProfile* profile_;
@@ -1099,17 +1093,19 @@
   }
 
   void RemoveAllBrowsingData() override {
-    ++remove_calls_;
+    ++remove_all_calls_;
     last_origin_filter_ = base::RepeatingCallback<bool(const GURL&)>();
   }
 
   int remove_calls() const { return remove_calls_; }
+  int remove_all_calls() const { return remove_all_calls_; }
   const base::RepeatingCallback<bool(const GURL&)>& last_origin_filter() const {
     return last_origin_filter_;
   }
 
  private:
   int remove_calls_ = 0;
+  int remove_all_calls_ = 0;
   base::RepeatingCallback<bool(const GURL&)> last_origin_filter_;
 
   DISALLOW_COPY_AND_ASSIGN(MockNetworkErrorLoggingService);
@@ -1135,14 +1131,7 @@
     request_context->set_network_error_logging_service(nullptr);
   }
 
-  void GetMockInfo(
-      int* remove_calls_out,
-      base::RepeatingCallback<bool(const GURL&)>* last_origin_filter_out) {
-    DCHECK_NE(nullptr, service_.get());
-
-    *remove_calls_out = service_->remove_calls();
-    *last_origin_filter_out = service_->last_origin_filter();
-  }
+  const MockNetworkErrorLoggingService& mock() { return *service_; };
 
  private:
   TestingProfile* profile_;
@@ -2780,16 +2769,12 @@
       base::Time(), base::Time::Max(),
       ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY, true);
 
-  int remove_count;
-  int data_type_mask;
-  base::RepeatingCallback<bool(const GURL&)> origin_filter;
-  tester.GetMockInfo(&remove_count, &data_type_mask, &origin_filter);
-
-  EXPECT_EQ(1, remove_count);
+  EXPECT_EQ(0, tester.mock().remove_calls());
+  EXPECT_EQ(1, tester.mock().remove_all_calls());
   EXPECT_EQ(net::ReportingBrowsingDataRemover::DATA_TYPE_REPORTS,
-            data_type_mask);
-  EXPECT_TRUE(ProbablySameFilters(BrowsingDataFilterBuilder::BuildNoopFilter(),
-                                  origin_filter));
+            tester.mock().last_data_type_mask());
+  EXPECT_TRUE(ProbablySameFilters(base::RepeatingCallback<bool(const GURL&)>(),
+                                  tester.mock().last_origin_filter()));
 }
 
 // TODO(crbug.com/589586): Disabled, since history is not yet marked as
@@ -2806,16 +2791,12 @@
       base::Time(), base::Time::Max(),
       ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY, builder->Copy());
 
-  int remove_count;
-  int data_type_mask;
-  base::RepeatingCallback<bool(const GURL&)> origin_filter;
-  tester.GetMockInfo(&remove_count, &data_type_mask, &origin_filter);
-
-  EXPECT_EQ(1, remove_count);
+  EXPECT_EQ(1, tester.mock().remove_calls());
+  EXPECT_EQ(0, tester.mock().remove_all_calls());
   EXPECT_EQ(net::ReportingBrowsingDataRemover::DATA_TYPE_REPORTS,
-            data_type_mask);
-  EXPECT_TRUE(
-      ProbablySameFilters(builder->BuildGeneralFilter(), origin_filter));
+            tester.mock().last_data_type_mask());
+  EXPECT_TRUE(ProbablySameFilters(builder->BuildGeneralFilter(),
+                                  tester.mock().last_origin_filter()));
 }
 
 TEST_F(ChromeBrowsingDataRemoverDelegateTest, NetworkErrorLogging_NoDelegate) {
@@ -2837,13 +2818,10 @@
       base::Time(), base::Time::Max(),
       ChromeBrowsingDataRemoverDelegate::DATA_TYPE_HISTORY, true);
 
-  int remove_count;
-  base::RepeatingCallback<bool(const GURL&)> origin_filter;
-  tester.GetMockInfo(&remove_count, &origin_filter);
-
-  EXPECT_EQ(1, remove_count);
-  EXPECT_TRUE(ProbablySameFilters(BrowsingDataFilterBuilder::BuildNoopFilter(),
-                                  origin_filter));
+  EXPECT_EQ(0, tester.mock().remove_calls());
+  EXPECT_EQ(1, tester.mock().remove_all_calls());
+  EXPECT_TRUE(ProbablySameFilters(base::RepeatingCallback<bool(const GURL&)>(),
+                                  tester.mock().last_origin_filter()));
 }
 #endif  // BUILDFLAG(ENABLE_REPORTING)
 
diff --git a/chrome/browser/chromeos/crostini/crostini_package_installer_notification.cc b/chrome/browser/chromeos/crostini/crostini_package_installer_notification.cc
index 2e8a4a7..1f3510a 100644
--- a/chrome/browser/chromeos/crostini/crostini_package_installer_notification.cc
+++ b/chrome/browser/chromeos/crostini/crostini_package_installer_notification.cc
@@ -4,12 +4,11 @@
 
 #include "chrome/browser/chromeos/crostini/crostini_package_installer_notification.h"
 
+#include "ash/public/cpp/vector_icons/vector_icons.h"
 #include "chrome/browser/chromeos/crostini/crostini_package_installer_service.h"
 #include "chrome/browser/notifications/notification_display_service.h"
-#include "chrome/grit/chrome_unscaled_resources.h"
 #include "chrome/grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
 #include "ui/message_center/public/cpp/message_center_constants.h"
 #include "ui/message_center/public/cpp/notification.h"
 #include "ui/message_center/public/cpp/notification_delegate.h"
@@ -31,10 +30,7 @@
       profile_(profile),
       weak_ptr_factory_(this) {
   message_center::RichNotificationData rich_notification_data;
-  // TODO(timloh): This is probably not the right icon...
-  rich_notification_data.small_image =
-      ui::ResourceBundle::GetSharedInstance().GetImageNamed(
-          IDR_LOGO_CROSTINI_DEFAULT);
+  rich_notification_data.vector_small_image = &ash::kNotificationLinuxIcon;
   rich_notification_data.never_timeout = true;
   rich_notification_data.accent_color =
       message_center::kSystemNotificationColorNormal;
diff --git a/chrome/browser/chromeos/file_manager/audio_player_browsertest.cc b/chrome/browser/chromeos/file_manager/audio_player_browsertest.cc
index 3d3035c..164dd25 100644
--- a/chrome/browser/chromeos/file_manager/audio_player_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/audio_player_browsertest.cc
@@ -18,6 +18,10 @@
     return test_case_name_.c_str();
   }
 
+  std::string GetFullTestCaseName() const override {
+    return test_case_name_;
+  }
+
   const char* GetTestExtensionManifestName() const override {
     return "audio_player_test_manifest.json";
   }
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
index 40701a47..cbb6012 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -53,6 +53,25 @@
     return *this;
   }
 
+  static std::string GetFullTestCaseName(const TestCase& test) {
+    std::string name(test.test_case_name);
+
+    CHECK(!name.empty()) << "FATAL: no test case name.";
+
+    if (test.guest_mode == IN_GUEST_MODE)
+      name.append("_GuestMode");
+    else if (test.guest_mode == IN_INCOGNITO)
+      name.append("_Incognito");
+
+    if (test.tablet_mode)
+      name.append("_TabletMode");
+
+    if (test.enable_drivefs)
+      name.append("_DriveFs");
+
+    return name;
+  }
+
   const char* test_case_name = nullptr;
   GuestMode guest_mode = NOT_IN_GUEST_MODE;
   bool trusted_events = false;
@@ -92,19 +111,25 @@
   }
 
   GuestMode GetGuestMode() const override { return GetParam().guest_mode; }
-  bool GetEnableDriveFs() const override { return GetParam().enable_drivefs; }
-  bool GetRequiresStartupBrowser() const override {
-    return GetParam().with_browser;
-  }
 
   const char* GetTestCaseName() const override {
     return GetParam().test_case_name;
   }
 
+  std::string GetFullTestCaseName() const override {
+    return TestCase::GetFullTestCaseName(GetParam());
+  }
+
   const char* GetTestExtensionManifestName() const override {
     return "file_manager_test_manifest.json";
   }
 
+  bool GetEnableDriveFs() const override { return GetParam().enable_drivefs; }
+
+  bool GetRequiresStartupBrowser() const override {
+    return GetParam().with_browser;
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(FilesAppBrowserTest);
 };
@@ -122,22 +147,7 @@
   INSTANTIATE_TEST_CASE_P(prefix, test_class, generator, &PostTestCaseName)
 
 std::string PostTestCaseName(const ::testing::TestParamInfo<TestCase>& test) {
-  std::string name(test.param.test_case_name);
-
-  CHECK(!name.empty()) << "FATAL: a test case name is required";
-
-  if (test.param.guest_mode == IN_GUEST_MODE)
-    name.append("_GuestMode");
-  else if (test.param.guest_mode == IN_INCOGNITO)
-    name.append("_Incognito");
-
-  if (test.param.tablet_mode)
-    name.append("_TabletMode");
-
-  if (test.param.enable_drivefs)
-    name.append("_DriveFs");
-
-  return name;
+  return TestCase::GetFullTestCaseName(test.param);
 }
 
 WRAPPED_INSTANTIATE_TEST_CASE_P(
@@ -614,6 +624,10 @@
     return test_case_name_.c_str();
   }
 
+  std::string GetFullTestCaseName() const override {
+    return test_case_name_;
+  }
+
   const char* GetTestExtensionManifestName() const override {
     return "file_manager_test_manifest.json";
   }
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
index 830b39d..39f5615 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.cc
@@ -1040,7 +1040,7 @@
 }
 
 void FileManagerBrowserTestBase::StartTest() {
-  LOG(INFO) << "FileManagerBrowserTest::StartTest " << GetTestCaseName();
+  LOG(INFO) << "FileManagerBrowserTest::StartTest " << GetFullTestCaseName();
   static const base::FilePath test_extension_dir =
       base::FilePath(FILE_PATH_LITERAL("ui/file_manager/integration_tests"));
   LaunchExtension(test_extension_dir, GetTestExtensionManifestName());
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.h b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.h
index 1b06f15..58ad1af 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.h
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest_base.h
@@ -31,7 +31,7 @@
   FileManagerBrowserTestBase();
   ~FileManagerBrowserTestBase() override;
 
-  // ExtensionApiTest overrides.
+  // extensions::ExtensionApiTest:
   void SetUp() override;
   void SetUpCommandLine(base::CommandLine* command_line) override;
   bool SetUpUserDataDirectory() override;
@@ -40,10 +40,11 @@
 
   // Overrides for each FileManagerBrowserTest test extension type.
   virtual GuestMode GetGuestMode() const = 0;
+  virtual const char* GetTestCaseName() const = 0;
+  virtual std::string GetFullTestCaseName() const = 0;
+  virtual const char* GetTestExtensionManifestName() const = 0;
   virtual bool GetEnableDriveFs() const;
   virtual bool GetRequiresStartupBrowser() const;
-  virtual const char* GetTestCaseName() const = 0;
-  virtual const char* GetTestExtensionManifestName() const = 0;
 
   // Launches the test extension from GetTestExtensionManifestName() and uses
   // it to drive the testing the actual FileManager component extension under
diff --git a/chrome/browser/chromeos/file_manager/gallery_browsertest.cc b/chrome/browser/chromeos/file_manager/gallery_browsertest.cc
index 485422c..0b167e7326b 100644
--- a/chrome/browser/chromeos/file_manager/gallery_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/gallery_browsertest.cc
@@ -18,6 +18,10 @@
     return test_case_name_.c_str();
   }
 
+  std::string GetFullTestCaseName() const override {
+    return test_case_name_;
+  }
+
   const char* GetTestExtensionManifestName() const override {
     return "gallery_test_manifest.json";
   }
diff --git a/chrome/browser/chromeos/file_manager/video_player_browsertest.cc b/chrome/browser/chromeos/file_manager/video_player_browsertest.cc
index 008c2a8..45ec08e 100644
--- a/chrome/browser/chromeos/file_manager/video_player_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/video_player_browsertest.cc
@@ -27,6 +27,10 @@
     return test_case_name_.c_str();
   }
 
+  std::string GetFullTestCaseName() const override {
+    return test_case_name_;
+  }
+
   const char* GetTestExtensionManifestName() const override {
     return "video_player_test_manifest.json";
   }
diff --git a/chrome/browser/dom_distiller/lazy_dom_distiller_service.cc b/chrome/browser/dom_distiller/lazy_dom_distiller_service.cc
index 90419f6..9fb7a9fe 100644
--- a/chrome/browser/dom_distiller/lazy_dom_distiller_service.cc
+++ b/chrome/browser/dom_distiller/lazy_dom_distiller_service.cc
@@ -43,10 +43,6 @@
   delete this;
 }
 
-syncer::SyncableService* LazyDomDistillerService::GetSyncableService() const {
-  return instance()->GetSyncableService();
-}
-
 bool LazyDomDistillerService::HasEntry(const std::string& entry_id) {
   return instance()->HasEntry(entry_id);
 }
diff --git a/chrome/browser/dom_distiller/lazy_dom_distiller_service.h b/chrome/browser/dom_distiller/lazy_dom_distiller_service.h
index 0a4bf96..e68c670 100644
--- a/chrome/browser/dom_distiller/lazy_dom_distiller_service.h
+++ b/chrome/browser/dom_distiller/lazy_dom_distiller_service.h
@@ -36,7 +36,6 @@
 
  public:
   // DomDistillerServiceInterface implementation:
-  syncer::SyncableService* GetSyncableService() const override;
   const std::string AddToList(
       const GURL& url,
       std::unique_ptr<DistillerPage> distiller_page,
diff --git a/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc b/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc
index 175291d..06d3e41 100644
--- a/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc
+++ b/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc
@@ -186,6 +186,8 @@
   void VerifyAllSubresourcesFetched() const {
     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
+    base::RunLoop().RunUntilIdle();
+
     for (const auto& expect : subresource_expected_) {
       EXPECT_FALSE(expect.second);
     }
@@ -196,6 +198,8 @@
 
  private:
   void TearDownOnMainThread() override {
+    EXPECT_TRUE(https_server_->ShutdownAndWaitUntilComplete());
+    EXPECT_TRUE(http_server_->ShutdownAndWaitUntilComplete());
     VerifyAllSubresourcesFetched();
 
     InProcessBrowserTest::TearDownOnMainThread();
@@ -278,9 +282,9 @@
 };
 
 // Previews InfoBar (which these tests triggers) does not work on Mac.
-// See crbug.com/782322 for details. Also occasional flakes on win7
-// (crbug.com/789542).
-#if !defined(OS_MACOSX) && !defined(OS_WIN)
+// See crbug.com/782322 for details. Also occasional flakes on win7/linux
+// (crbug.com/789542, crbug.com/866212).
+#if !defined(OS_MACOSX) && !defined(OS_WIN) && !defined(OS_LINUX)
 #define MAYBE_ResourceLoadingHintsHttpsWhitelisted \
   ResourceLoadingHintsHttpsWhitelisted
 #define MAYBE_ResourceLoadingHintsHttpsWhitelistedRedirectToHttps \
diff --git a/chrome/browser/printing/print_preview_data_service.cc b/chrome/browser/printing/print_preview_data_service.cc
index 7c4605b..ab0b698 100644
--- a/chrome/browser/printing/print_preview_data_service.cc
+++ b/chrome/browser/printing/print_preview_data_service.cc
@@ -12,6 +12,22 @@
 #include "base/stl_util.h"
 #include "printing/print_job_constants.h"
 
+namespace {
+
+#if DCHECK_IS_ON()
+void ValidatePreviewData(const scoped_refptr<base::RefCountedMemory>& data) {
+  // PDFs are generally much bigger. This is just a sanity check on size.
+  DCHECK(data);
+  DCHECK_GE(data->size(), 50U);
+
+  static const char kPdfHeader[] = "%PDF-";
+  const char* content = data->front_as<const char>();
+  DCHECK_EQ(0, memcmp(content, kPdfHeader, strlen(kPdfHeader)));
+}
+#endif
+
+}  // namespace
+
 // PrintPreviewDataStore stores data for preview workflow and preview printing
 // workflow.
 //
@@ -50,6 +66,10 @@
     if (IsInvalidIndex(index))
       return;
 
+#if DCHECK_IS_ON()
+    ValidatePreviewData(data);
+#endif
+
     page_data_map_[index] = std::move(data);
   }
 
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index f2c243a..9bab63f6 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -174,7 +174,9 @@
 
 #endif
 
-#if !defined(OS_ANDROID)
+#if defined(OS_ANDROID)
+#include "chrome/browser/android/download/download_manager_service.h"
+#else
 #include "chrome/browser/apps/foundation/app_service/app_service.h"
 #include "chrome/browser/apps/foundation/app_service/public/mojom/constants.mojom.h"
 #include "components/zoom/zoom_event_manager.h"
@@ -1211,6 +1213,16 @@
   return media_device_id_salt_->GetSalt();
 }
 
+download::InProgressDownloadManager*
+ProfileImpl::RetriveInProgressDownloadManager() {
+#if defined(OS_ANDROID)
+  return DownloadManagerService::GetInstance()
+      ->RetriveInProgressDownloadManager(this);
+#else
+  return nullptr;
+#endif
+}
+
 bool ProfileImpl::IsSameProfile(Profile* profile) {
   if (profile == static_cast<Profile*>(this))
     return true;
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h
index 1ec337a..7a57e58b 100644
--- a/chrome/browser/profiles/profile_impl.h
+++ b/chrome/browser/profiles/profile_impl.h
@@ -105,6 +105,8 @@
       bool in_memory) override;
   void RegisterInProcessServices(StaticServiceMap* services) override;
   std::string GetMediaDeviceIDSalt() override;
+  download::InProgressDownloadManager* RetriveInProgressDownloadManager()
+      override;
 
   // Profile implementation:
   scoped_refptr<base::SequencedTaskRunner> GetIOTaskRunner() override;
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index 20f74be..90a4d37 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -516,6 +516,19 @@
   }
 }
 
+bool DoesInputFieldTypeSupportEmoji(
+    blink::WebContextMenuData::InputFieldType text_input_type) {
+  // Disable emoji for input types that definitely do not support emoji.
+  switch (text_input_type) {
+    case blink::WebContextMenuData::kInputFieldTypeNumber:
+    case blink::WebContextMenuData::kInputFieldTypeTelephone:
+    case blink::WebContextMenuData::kInputFieldTypeOther:
+      return false;
+    default:
+      return true;
+  }
+}
+
 }  // namespace
 
 // static
@@ -1447,7 +1460,9 @@
     AppendSearchProvider();
     menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
   }
-  if (params_.misspelled_word.empty() && ui::IsEmojiPanelSupported()) {
+  if (params_.misspelled_word.empty() &&
+      DoesInputFieldTypeSupportEmoji(params_.input_field_type) &&
+      ui::IsEmojiPanelSupported()) {
     menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_EMOJI,
                                     IDS_CONTENT_CONTEXT_EMOJI);
     menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
diff --git a/chrome/browser/resources/chromeos/login/hd-iron-icon.html b/chrome/browser/resources/chromeos/login/hd-iron-icon.html
index 13d2c0b4..19a818f 100644
--- a/chrome/browser/resources/chromeos/login/hd-iron-icon.html
+++ b/chrome/browser/resources/chromeos/login/hd-iron-icon.html
@@ -3,6 +3,7 @@
      found in the LICENSE file. -->
 
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
 
 <!--
   <iron-icon> that automatically displays one of the two icond depending on
@@ -17,9 +18,10 @@
       'icon2x' - a name of icon from material design set to show on button.
 -->
 <dom-module id="hd-iron-icon">
-  <link rel="stylesheet" href="hd-iron-icon.css">
   <template>
-    <div>
+    <style include="iron-flex iron-flex-alignment iron-positioning"></style>
+    <link rel="stylesheet" href="hd-iron-icon.css">
+    <div class="flex layout vertical center">
       <iron-icon id="icon1x" icon="[[icon1x]]"></iron-icon>
       <iron-icon id="icon2x" icon="[[icon2x]]"></iron-icon>
     </div>
diff --git a/chrome/browser/resources/chromeos/login/oobe_back_button.css b/chrome/browser/resources/chromeos/login/oobe_back_button.css
index 8a5ec6a..3ef030a 100644
--- a/chrome/browser/resources/chromeos/login/oobe_back_button.css
+++ b/chrome/browser/resources/chromeos/login/oobe_back_button.css
@@ -7,10 +7,7 @@
   -webkit-padding-start: 8px;
 }
 
-:host ::slotted(*) {
-  -webkit-padding-start: 4px;
-}
-
 hd-iron-icon {
+  -webkit-padding-start: 4px; /* transform(180deg) will make it padding-end. */
   transform: rotate(180deg);
 }
diff --git a/chrome/browser/resources/chromeos/login/oobe_buttons.html b/chrome/browser/resources/chromeos/login/oobe_buttons.html
index f6fbb9e..237cc07 100644
--- a/chrome/browser/resources/chromeos/login/oobe_buttons.html
+++ b/chrome/browser/resources/chromeos/login/oobe_buttons.html
@@ -54,9 +54,8 @@
 -->
 <dom-module id="oobe-text-button">
   <template>
-    <style
-        include="iron-flex iron-flex-alignment iron-positioning paper-button-style cr-icons cr-shared-style">
-    </style>
+    <style include="iron-flex iron-flex-alignment iron-positioning"></style>
+    <style include="paper-button-style cr-icons cr-shared-style"></style>
     <link rel="stylesheet" href="oobe_text_buttons.css">
     <paper-button id="textButton" on-tap="onClick_" disabled="[[disabled]]"
         inverse$="[[inverse]]" aria-label$="[[labelForAria]]"
@@ -91,8 +90,8 @@
   <template>
     <style include="iron-flex iron-flex-alignment iron-positioning"></style>
     <style include="paper-button-style cr-icons cr-shared-style"></style>
-    <link rel="stylesheet" href="oobe_text_buttons.css">
     <link rel="stylesheet" href="oobe_back_button.css">
+    <link rel="stylesheet" href="oobe_text_buttons.css">
     <paper-button id="button" on-tap="onClick_" disabled="[[disabled]]"
         aria-label$="[[labelForAria]]" class="action-button">
       <div class="flex horizontal layout start center">
@@ -112,8 +111,8 @@
   <template>
     <style include="iron-flex iron-flex-alignment iron-positioning"></style>
     <style include="paper-button-style cr-icons cr-shared-style"></style>
-    <link rel="stylesheet" href="oobe_text_buttons.css">
     <link rel="stylesheet" href="oobe_next_button.css">
+    <link rel="stylesheet" href="oobe_text_buttons.css">
     <paper-button id="button" on-tap="onClick_" disabled="[[disabled]]"
         class="action-button">
       <div class="flex horizontal layout start center">
diff --git a/chrome/browser/resources/chromeos/login/oobe_next_button.css b/chrome/browser/resources/chromeos/login/oobe_next_button.css
index e521ae7..2ec7d01 100644
--- a/chrome/browser/resources/chromeos/login/oobe_next_button.css
+++ b/chrome/browser/resources/chromeos/login/oobe_next_button.css
@@ -7,10 +7,6 @@
   -webkit-padding-start: 16px;
 }
 
-slot {
-  -webkit-padding-end: 4px;
-}
-
 hd-iron-icon {
   -webkit-padding-start: 4px;
 }
diff --git a/chrome/browser/resources/chromeos/login/oobe_text_buttons.css b/chrome/browser/resources/chromeos/login/oobe_text_buttons.css
index e9e7ac7f..6f257bbc 100644
--- a/chrome/browser/resources/chromeos/login/oobe_text_buttons.css
+++ b/chrome/browser/resources/chromeos/login/oobe_text_buttons.css
@@ -6,6 +6,10 @@
   margin: 0 4px; /* So that two adjacent buttons are 8px separated. */
 }
 
-:host ::slotted(*) {
+/* Default slot data is not selected by ::slotted() selector, see
+ * https://crbug.com/703984.
+ */
+:host ::slotted(*),
+#text {
   font-size: 12px;
 }
diff --git a/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_manager.js b/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_manager.js
index f77fcbd..bd5674a6 100644
--- a/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_manager.js
+++ b/chrome/browser/resources/chromeos/wallpaper_manager/js/wallpaper_manager.js
@@ -1267,12 +1267,10 @@
     this.wallpaperRequest_ = null;
   }
 
-  var wallpaperUrl = selectedItem.highResolutionURL ?
-      selectedItem.highResolutionURL :
-      selectedItem.baseURL + str('highResolutionSuffix');
   var selectedGridItem = this.wallpaperGrid_.getListItem(selectedItem);
   chrome.wallpaperPrivate.setWallpaperIfExists(
-      wallpaperUrl, selectedItem.layout, previewMode, exists => {
+      selectedItem.highResolutionURL, selectedItem.layout, previewMode,
+      exists => {
         if (exists) {
           successCallback();
           return;
@@ -1286,7 +1284,8 @@
             xhr => {
               var image = xhr.response;
               chrome.wallpaperPrivate.setWallpaper(
-                  image, selectedItem.layout, wallpaperUrl, previewMode, () => {
+                  image, selectedItem.layout, selectedItem.highResolutionURL,
+                  previewMode, () => {
                     this.progressManager_.hideProgressBar(selectedGridItem);
 
                     if (chrome.runtime.lastError != undefined &&
@@ -1310,7 +1309,7 @@
           failureCallback();
         };
         WallpaperUtil.fetchURL(
-            wallpaperUrl, 'arraybuffer', onSuccess, onFailure,
+            selectedItem.highResolutionURL, 'arraybuffer', onSuccess, onFailure,
             this.wallpaperRequest_);
       });
 };
@@ -2093,6 +2092,8 @@
         var wallpaperInfo = {
           wallpaperId: i,
           baseURL: this.manifest_.wallpaper_list[i].base_url,
+          highResolutionURL: this.manifest_.wallpaper_list[i].base_url +
+              str('highResolutionSuffix'),
           layout: this.manifest_.wallpaper_list[i].default_layout,
           source: Constants.WallpaperSourceEnum.Online,
           availableOffline: false,
@@ -2107,9 +2108,7 @@
           wallpaperInfo.availableOffline = true;
         }
         wallpapersDataModel.push(wallpaperInfo);
-        var url = this.manifest_.wallpaper_list[i].base_url +
-            str('highResolutionSuffix');
-        if (url == this.currentWallpaper_) {
+        if (wallpaperInfo.highResolutionURL == this.currentWallpaper_) {
           selectedItem = wallpaperInfo;
         }
       }
diff --git a/chrome/browser/resources/pdf/pdf.js b/chrome/browser/resources/pdf/pdf.js
index 6de1c5c..84ac5072 100644
--- a/chrome/browser/resources/pdf/pdf.js
+++ b/chrome/browser/resources/pdf/pdf.js
@@ -106,7 +106,7 @@
   this.delayedScriptingMessages_ = [];
 
   this.isPrintPreview_ = location.origin === 'chrome://print';
-  this.isPrintPreviewLoaded_ = false;
+  this.isPrintPreviewLoadingFinished_ = false;
   this.isUserInitiatedEvent_ = true;
 
   /**
@@ -521,7 +521,7 @@
   sendDocumentLoadedMessage_: function() {
     if (this.loadState_ == LoadState.LOADING)
       return;
-    if (this.isPrintPreview_ && !this.isPrintPreviewLoaded_)
+    if (this.isPrintPreview_ && !this.isPrintPreviewLoadingFinished_)
       return;
     this.sendScriptingMessage_(
         {type: 'documentLoaded', load_state: this.loadState_});
@@ -598,6 +598,7 @@
         this.passwordScreen_.close();
       }
       this.loadState_ = LoadState.FAILED;
+      this.isPrintPreviewLoadingFinished_ = true;
       this.sendDocumentLoadedMessage_();
     } else if (progress == 100) {
       // Document load complete.
@@ -718,7 +719,7 @@
         }
         break;
       case 'printPreviewLoaded':
-        this.isPrintPreviewLoaded_ = true;
+        this.isPrintPreviewLoadingFinished_ = true;
         this.sendDocumentLoadedMessage_();
         break;
       case 'setScrollPosition':
diff --git a/chrome/browser/resources/print_preview/new/preview_area.js b/chrome/browser/resources/print_preview/new/preview_area.js
index 665c3fb8..5119875 100644
--- a/chrome/browser/resources/print_preview/new/preview_area.js
+++ b/chrome/browser/resources/print_preview/new/preview_area.js
@@ -421,10 +421,15 @@
    * Called when the plugin loads. This is a consequence of calling
    * plugin.reload(). Certain plugin state can only be set after the plugin
    * has loaded.
+   * @param {boolean} success Whether the plugin load succeeded or not.
    * @private
    */
-  onPluginLoad_: function() {
-    this.pluginLoaded_ = true;
+  onPluginLoad_: function(success) {
+    if (success) {
+      this.pluginLoaded_ = true;
+    } else {
+      this.previewState = print_preview_new.PreviewAreaState.PREVIEW_FAILED;
+    }
   },
 
   /**
diff --git a/chrome/browser/resources/settings/people_page/sync_account_control.html b/chrome/browser/resources/settings/people_page/sync_account_control.html
index fa9129c..fc1875c 100644
--- a/chrome/browser/resources/settings/people_page/sync_account_control.html
+++ b/chrome/browser/resources/settings/people_page/sync_account_control.html
@@ -130,10 +130,6 @@
       :host([showing-promo]) #promo-separator {
         @apply --promo-separator;
       }
-
-      :host([always-show-promo]) #turn-off {
-        display: none;
-      }
     </style>
     <div id="banner" hidden="[[syncStatus.signedIn]]"></div>
     <div class="settings-box first two-line" id="promo-header"
@@ -193,17 +189,25 @@
           </button>
         </paper-icon-button-light>
         <div class="separator" hidden="[[syncStatus.signedIn]]"></div>
-        <paper-button class="action-button" on-click="onSyncButtonTap_"
-            hidden="[[syncStatus.signedIn]]"
+        <paper-button id="sync-button" class="action-button"
+            hidden="[[syncStatus.signedIn]]" on-click="onSyncButtonTap_"
             disabled="[[syncStatus.setupInProgress]]">
           [[getSubstituteLabel_(
               '$i18nPolymer{syncAsName}', shownAccount_.givenName)]]
         </paper-button>
-        <paper-button class="secondary-button" on-click="onTurnOffButtonTap_"
-            hidden="[[!syncStatus.signedIn]]" id="turn-off"
+        <paper-button id="turn-off" class="secondary-button"
+            hidden="[[!shouldShowTurnOffButton_(syncStatus.signedIn)]]"
+            on-click="onTurnOffButtonTap_"
             disabled="[[syncStatus.setupInProgress]]">
           $i18n{turnOffSync}
         </paper-button>
+        <paper-button id="sync-paused-button" class="action-button"
+            hidden="[[!shouldShowSigninAgainButton_(
+                syncStatus.signedIn, syncStatus.hasError,
+                syncStatus.statusAction)]]"
+            on-click="onSigninTap_" disabled="[[syncStatus.setupInProgress]]">
+          $i18n{signInAgain}
+        </paper-button>
       </div>
       <template is="dom-if" if="[[!syncStatus.signedIn]]" restamp>
         <cr-action-menu id="menu" auto-reposition>
diff --git a/chrome/browser/resources/settings/people_page/sync_account_control.js b/chrome/browser/resources/settings/people_page/sync_account_control.js
index 1a5f4b10..294ad84 100644
--- a/chrome/browser/resources/settings/people_page/sync_account_control.js
+++ b/chrome/browser/resources/settings/people_page/sync_account_control.js
@@ -58,7 +58,7 @@
 
     // This property should be set by the parent only and should not change
     // after the element is created.
-    alwaysShowPromo: {
+    embeddedInSubpage: {
       type: Boolean,
       reflectToAttribute: true,
     },
@@ -123,7 +123,7 @@
 
   /** @private */
   onSignedInChanged_: function() {
-    if (this.alwaysShowPromo) {
+    if (this.embeddedInSubpage) {
       this.showingPromo = true;
       return;
     }
@@ -252,6 +252,24 @@
   },
 
   /**
+   * @return {boolean}
+   * @private
+   */
+  shouldShowTurnOffButton_: function() {
+    return !!this.syncStatus.signedIn && !this.embeddedInSubpage;
+  },
+
+  /**
+   * @return {boolean}
+   * @private
+   */
+  shouldShowSigninAgainButton_: function() {
+    return !!this.syncStatus.signedIn && this.embeddedInSubpage &&
+        !!this.syncStatus.hasError &&
+        this.syncStatus.statusAction == settings.StatusAction.REAUTHENTICATE;
+  },
+
+  /**
    * @param {!Array<!settings.StoredAccount>} accounts
    * @private
    */
diff --git a/chrome/browser/resources/settings/people_page/sync_page.html b/chrome/browser/resources/settings/people_page/sync_page.html
index 9abaa4ef..952dba95 100644
--- a/chrome/browser/resources/settings/people_page/sync_page.html
+++ b/chrome/browser/resources/settings/people_page/sync_page.html
@@ -80,7 +80,7 @@
     <template is="dom-if" if="[[shouldShowSyncAccountControl_(diceEnabled,
         unifiedConsentEnabled, syncStatus.syncSystemEnabled,
         syncStatus.signinAllowed)]]">
-      <settings-sync-account-control always-show-promo
+      <settings-sync-account-control embedded-in-subpage
           sync-status="[[syncStatus]]"
           promo-label-with-account="$i18n{peopleSignInPrompt}"
           promo-label-with-no-account="$i18n{peopleSignInPrompt}"
diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
index f5a36f7..992b172 100644
--- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
@@ -203,7 +203,6 @@
 
 enum class JsRequestType {
   kWebSocket,
-  kOffMainThreadWebSocket,
   // Load a URL using the Fetch API.
   kFetch
 };
@@ -235,7 +234,6 @@
 std::string JsRequestTypeToString(JsRequestType request_type) {
   switch (request_type) {
     case JsRequestType::kWebSocket:
-    case JsRequestType::kOffMainThreadWebSocket:
       return "websocket";
     case JsRequestType::kFetch:
       return "fetch";
@@ -269,7 +267,6 @@
 GURL ConstructJsRequestURL(const GURL& base_url, JsRequestType request_type) {
   switch (request_type) {
     case JsRequestType::kWebSocket:
-    case JsRequestType::kOffMainThreadWebSocket:
       return ConstructWebSocketURL(base_url);
     case JsRequestType::kFetch:
       return base_url.Resolve(kMalwarePage);
@@ -1831,23 +1828,11 @@
     : public ::testing::WithParamInterface<JsRequestTestParam>,
       public SafeBrowsingServiceTest {
  public:
-  void SetUp() override {
-    JsRequestTestParam param = GetParam();
-    if (param.request_type == JsRequestType::kWebSocket) {
-      scoped_feature_list_.InitAndDisableFeature(
-          features::kOffMainThreadWebSocket);
-    }
-    SafeBrowsingServiceTest::SetUp();
-  }
-
   void MarkAsMalware(const GURL& url) {
     SBFullHashResult uws_full_hash;
     GenUrlFullHashResult(url, MALWARE, &uws_full_hash);
     SetupResponseForUrl(url, uws_full_hash);
   }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 using SafeBrowsingServiceJsRequestInterstitialTest =
@@ -1889,10 +1874,6 @@
     ::testing::Values(
         JsRequestTestParam(ContextType::kWindow, JsRequestType::kWebSocket),
         JsRequestTestParam(ContextType::kWorker, JsRequestType::kWebSocket),
-        JsRequestTestParam(ContextType::kWindow,
-                           JsRequestType::kOffMainThreadWebSocket),
-        JsRequestTestParam(ContextType::kWorker,
-                           JsRequestType::kOffMainThreadWebSocket),
         JsRequestTestParam(ContextType::kWindow, JsRequestType::kFetch),
         JsRequestTestParam(ContextType::kWorker, JsRequestType::kFetch)));
 
@@ -1925,10 +1906,6 @@
                            JsRequestType::kWebSocket),
         JsRequestTestParam(ContextType::kServiceWorker,
                            JsRequestType::kWebSocket),
-        JsRequestTestParam(ContextType::kSharedWorker,
-                           JsRequestType::kOffMainThreadWebSocket),
-        JsRequestTestParam(ContextType::kServiceWorker,
-                           JsRequestType::kOffMainThreadWebSocket),
         JsRequestTestParam(ContextType::kSharedWorker, JsRequestType::kFetch),
         JsRequestTestParam(ContextType::kServiceWorker,
                            JsRequestType::kFetch)));
@@ -1955,14 +1932,6 @@
                            JsRequestType::kWebSocket),
         JsRequestTestParam(ContextType::kServiceWorker,
                            JsRequestType::kWebSocket),
-        JsRequestTestParam(ContextType::kWindow,
-                           JsRequestType::kOffMainThreadWebSocket),
-        JsRequestTestParam(ContextType::kWorker,
-                           JsRequestType::kOffMainThreadWebSocket),
-        JsRequestTestParam(ContextType::kSharedWorker,
-                           JsRequestType::kOffMainThreadWebSocket),
-        JsRequestTestParam(ContextType::kServiceWorker,
-                           JsRequestType::kOffMainThreadWebSocket),
         JsRequestTestParam(ContextType::kWindow, JsRequestType::kFetch),
         JsRequestTestParam(ContextType::kWorker, JsRequestType::kFetch),
         JsRequestTestParam(ContextType::kSharedWorker, JsRequestType::kFetch),
@@ -2732,10 +2701,6 @@
     ::testing::Values(
         JsRequestTestParam(ContextType::kWindow, JsRequestType::kWebSocket),
         JsRequestTestParam(ContextType::kWorker, JsRequestType::kWebSocket),
-        JsRequestTestParam(ContextType::kWindow,
-                           JsRequestType::kOffMainThreadWebSocket),
-        JsRequestTestParam(ContextType::kWorker,
-                           JsRequestType::kOffMainThreadWebSocket),
         JsRequestTestParam(ContextType::kWindow, JsRequestType::kFetch),
         JsRequestTestParam(ContextType::kWorker, JsRequestType::kFetch)));
 
@@ -2768,10 +2733,6 @@
                            JsRequestType::kWebSocket),
         JsRequestTestParam(ContextType::kServiceWorker,
                            JsRequestType::kWebSocket),
-        JsRequestTestParam(ContextType::kSharedWorker,
-                           JsRequestType::kOffMainThreadWebSocket),
-        JsRequestTestParam(ContextType::kServiceWorker,
-                           JsRequestType::kOffMainThreadWebSocket),
         JsRequestTestParam(ContextType::kSharedWorker, JsRequestType::kFetch),
         JsRequestTestParam(ContextType::kServiceWorker,
                            JsRequestType::kFetch)));
@@ -2802,14 +2763,6 @@
                            JsRequestType::kWebSocket),
         JsRequestTestParam(ContextType::kServiceWorker,
                            JsRequestType::kWebSocket),
-        JsRequestTestParam(ContextType::kWindow,
-                           JsRequestType::kOffMainThreadWebSocket),
-        JsRequestTestParam(ContextType::kWorker,
-                           JsRequestType::kOffMainThreadWebSocket),
-        JsRequestTestParam(ContextType::kSharedWorker,
-                           JsRequestType::kOffMainThreadWebSocket),
-        JsRequestTestParam(ContextType::kServiceWorker,
-                           JsRequestType::kOffMainThreadWebSocket),
         JsRequestTestParam(ContextType::kWindow, JsRequestType::kFetch),
         JsRequestTestParam(ContextType::kWorker, JsRequestType::kFetch),
         JsRequestTestParam(ContextType::kSharedWorker, JsRequestType::kFetch),
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc
index 928a79d..62fa3cb 100644
--- a/chrome/browser/sync/chrome_sync_client.cc
+++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -551,14 +551,6 @@
       return base::WeakPtr<syncer::SyncableService>();
     }
 #endif  // BUILDFLAG(ENABLE_SUPERVISED_USERS)
-    case syncer::ARTICLES: {
-      dom_distiller::DomDistillerService* service =
-          dom_distiller::DomDistillerServiceFactory::GetForBrowserContext(
-              profile_);
-      if (service)
-        return service->GetSyncableService()->AsWeakPtr();
-      return base::WeakPtr<syncer::SyncableService>();
-    }
     case syncer::SESSIONS: {
       return ProfileSyncServiceFactory::GetForProfile(profile_)->
           GetSessionsSyncableService()->AsWeakPtr();
diff --git a/chrome/browser/sync/sync_startup_tracker_unittest.cc b/chrome/browser/sync/sync_startup_tracker_unittest.cc
index d60026f..aa84504 100644
--- a/chrome/browser/sync/sync_startup_tracker_unittest.cc
+++ b/chrome/browser/sync/sync_startup_tracker_unittest.cc
@@ -9,12 +9,12 @@
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/sync/profile_sync_test_util.h"
 #include "chrome/test/base/testing_profile.h"
+#include "components/browser_sync/profile_sync_service_mock.h"
 #include "content/public/test/test_browser_thread_bundle.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;
@@ -23,8 +23,8 @@
 
 class MockObserver : public SyncStartupTracker::Observer {
  public:
-  MOCK_METHOD0(SyncStartupCompleted, void(void));
-  MOCK_METHOD0(SyncStartupFailed, void(void));
+  MOCK_METHOD0(SyncStartupCompleted, void());
+  MOCK_METHOD0(SyncStartupFailed, void());
 };
 
 class SyncStartupTrackerTest : public testing::Test {
@@ -38,12 +38,7 @@
         ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
             profile_.get(), BuildMockProfileSyncService));
 
-    // Make gmock not spam the output with information about these uninteresting
-    // calls.
-    EXPECT_CALL(*mock_pss_, AddObserver(_)).Times(AnyNumber());
-    EXPECT_CALL(*mock_pss_, RemoveObserver(_)).Times(AnyNumber());
-    EXPECT_CALL(*mock_pss_, GetAuthError()).
-        WillRepeatedly(ReturnRef(no_error_));
+    ON_CALL(*mock_pss_, GetAuthError()).WillByDefault(ReturnRef(no_error_));
     ON_CALL(*mock_pss_, GetRegisteredDataTypes())
         .WillByDefault(Return(syncer::ModelTypeSet()));
     mock_pss_->Initialize();
@@ -52,25 +47,25 @@
   void TearDown() override { profile_.reset(); }
 
   void SetupNonInitializedPSS() {
-    EXPECT_CALL(*mock_pss_, GetAuthError())
-        .WillRepeatedly(ReturnRef(no_error_));
-    EXPECT_CALL(*mock_pss_, IsEngineInitialized())
-        .WillRepeatedly(Return(false));
-    EXPECT_CALL(*mock_pss_, GetDisableReasons())
-        .WillRepeatedly(Return(syncer::SyncService::DISABLE_REASON_NONE));
+    ON_CALL(*mock_pss_, GetAuthError()).WillByDefault(ReturnRef(no_error_));
+    ON_CALL(*mock_pss_, GetDisableReasons())
+        .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
+    ON_CALL(*mock_pss_, GetState())
+        .WillByDefault(Return(syncer::SyncService::State::INITIALIZING));
   }
 
   content::TestBrowserThreadBundle thread_bundle_;
-  GoogleServiceAuthError no_error_;
+  const GoogleServiceAuthError no_error_;
   std::unique_ptr<TestingProfile> profile_;
   browser_sync::ProfileSyncServiceMock* mock_pss_;
   MockObserver observer_;
 };
 
 TEST_F(SyncStartupTrackerTest, SyncAlreadyInitialized) {
-  EXPECT_CALL(*mock_pss_, IsEngineInitialized()).WillRepeatedly(Return(true));
-  EXPECT_CALL(*mock_pss_, GetDisableReasons())
-      .WillRepeatedly(Return(syncer::SyncService::DISABLE_REASON_NONE));
+  ON_CALL(*mock_pss_, GetDisableReasons())
+      .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
+  ON_CALL(*mock_pss_, GetState())
+      .WillByDefault(Return(syncer::SyncService::State::ACTIVE));
   EXPECT_CALL(observer_, SyncStartupCompleted());
   SyncStartupTracker tracker(profile_.get(), &observer_);
 }
@@ -78,10 +73,10 @@
 TEST_F(SyncStartupTrackerTest, SyncNotSignedIn) {
   // Make sure that we get a SyncStartupFailed() callback if sync is not logged
   // in.
-  EXPECT_CALL(*mock_pss_, IsEngineInitialized()).WillRepeatedly(Return(false));
-  EXPECT_CALL(*mock_pss_, GetDisableReasons())
-      .WillRepeatedly(
-          Return(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN));
+  ON_CALL(*mock_pss_, GetDisableReasons())
+      .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN));
+  ON_CALL(*mock_pss_, GetState())
+      .WillByDefault(Return(syncer::SyncService::State::DISABLED));
   EXPECT_CALL(observer_, SyncStartupFailed());
   SyncStartupTracker tracker(profile_.get(), &observer_);
 }
@@ -89,12 +84,13 @@
 TEST_F(SyncStartupTrackerTest, SyncAuthError) {
   // Make sure that we get a SyncStartupFailed() callback if sync gets an auth
   // error.
-  EXPECT_CALL(*mock_pss_, IsEngineInitialized()).WillRepeatedly(Return(false));
-  EXPECT_CALL(*mock_pss_, GetDisableReasons())
-      .WillRepeatedly(Return(syncer::SyncService::DISABLE_REASON_NONE));
+  ON_CALL(*mock_pss_, GetDisableReasons())
+      .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
+  ON_CALL(*mock_pss_, GetState())
+      .WillByDefault(Return(syncer::SyncService::State::INITIALIZING));
   GoogleServiceAuthError error(
       GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
-  EXPECT_CALL(*mock_pss_, GetAuthError()).WillRepeatedly(ReturnRef(error));
+  ON_CALL(*mock_pss_, GetAuthError()).WillByDefault(ReturnRef(error));
   EXPECT_CALL(observer_, SyncStartupFailed());
   SyncStartupTracker tracker(profile_.get(), &observer_);
 }
@@ -107,7 +103,8 @@
   SyncStartupTracker tracker(profile_.get(), &observer_);
   Mock::VerifyAndClearExpectations(&observer_);
   // Now, mark the PSS as initialized.
-  EXPECT_CALL(*mock_pss_, IsEngineInitialized()).WillRepeatedly(Return(true));
+  ON_CALL(*mock_pss_, GetState())
+      .WillByDefault(Return(syncer::SyncService::State::ACTIVE));
   EXPECT_CALL(observer_, SyncStartupCompleted());
   tracker.OnStateChanged(mock_pss_);
 }
@@ -122,12 +119,13 @@
   Mock::VerifyAndClearExpectations(mock_pss_);
 
   // Now, mark the PSS as having an auth error.
-  EXPECT_CALL(*mock_pss_, IsEngineInitialized()).WillRepeatedly(Return(false));
-  EXPECT_CALL(*mock_pss_, GetDisableReasons())
-      .WillRepeatedly(Return(syncer::SyncService::DISABLE_REASON_NONE));
+  ON_CALL(*mock_pss_, GetDisableReasons())
+      .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
+  ON_CALL(*mock_pss_, GetState())
+      .WillByDefault(Return(syncer::SyncService::State::INITIALIZING));
   GoogleServiceAuthError error(
       GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
-  EXPECT_CALL(*mock_pss_, GetAuthError()).WillRepeatedly(ReturnRef(error));
+  ON_CALL(*mock_pss_, GetAuthError()).WillByDefault(ReturnRef(error));
   EXPECT_CALL(observer_, SyncStartupFailed());
   tracker.OnStateChanged(mock_pss_);
 }
@@ -142,12 +140,11 @@
   Mock::VerifyAndClearExpectations(mock_pss_);
 
   // Now, mark the PSS as having an unrecoverable error.
-  EXPECT_CALL(*mock_pss_, IsEngineInitialized()).WillRepeatedly(Return(false));
-  EXPECT_CALL(*mock_pss_, GetDisableReasons())
-      .WillRepeatedly(Return(syncer::SyncService::DISABLE_REASON_NONE));
-  GoogleServiceAuthError error(
-      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
-  EXPECT_CALL(*mock_pss_, GetAuthError()).WillRepeatedly(ReturnRef(error));
+  ON_CALL(*mock_pss_, GetDisableReasons())
+      .WillByDefault(
+          Return(syncer::SyncService::DISABLE_REASON_UNRECOVERABLE_ERROR));
+  ON_CALL(*mock_pss_, GetState())
+      .WillByDefault(Return(syncer::SyncService::State::DISABLED));
   EXPECT_CALL(observer_, SyncStartupFailed());
   tracker.OnStateChanged(mock_pss_);
 }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index c96dfe1..7338d95 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1778,6 +1778,13 @@
     }
   }
 
+  if (enable_supervised_users && !is_android && !is_chromeos) {
+    sources += [
+      "startup/supervised_users_deprecated_infobar_delegate.cc",
+      "startup/supervised_users_deprecated_infobar_delegate.h",
+    ]
+  }
+
   if (is_chromeos) {
     assert(enable_extensions)
     assert(toolkit_views)
@@ -3147,7 +3154,6 @@
         "views/bubble_anchor_util_views.cc",
         "views/certificate_selector.cc",
         "views/certificate_selector.h",
-        "views/chrome_javascript_native_dialog_factory_views.cc",
         "views/chrome_web_dialog_view.cc",
         "views/constrained_web_dialog_delegate_views.cc",
         "views/download/download_feedback_dialog_view.cc",
@@ -3916,6 +3922,7 @@
     }
     if (use_aura) {
       sources += [
+        "views/chrome_javascript_native_dialog_factory_views.cc",
         "views/extensions/extension_popup_aura.cc",
         "views/extensions/extension_popup_aura.h",
       ]
diff --git a/chrome/browser/ui/cocoa/spinner_view.mm b/chrome/browser/ui/cocoa/spinner_view.mm
index 098ac95..cf92e2e 100644
--- a/chrome/browser/ui/cocoa/spinner_view.mm
+++ b/chrome/browser/ui/cocoa/spinner_view.mm
@@ -12,7 +12,6 @@
 #include "chrome/browser/ui/cocoa/spinner_util.h"
 #include "skia/ext/skia_utils_mac.h"
 #include "ui/base/theme_provider.h"
-#include "ui/gfx/geometry/angle_conversions.h"
 #include "ui/native_theme/native_theme.h"
 
 using cocoa_spinner_util::kDegrees90;
diff --git a/chrome/browser/ui/cocoa/tabs/tab_view.mm b/chrome/browser/ui/cocoa/tabs/tab_view.mm
index 58889963..fc0c940 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_view.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_view.mm
@@ -11,6 +11,7 @@
 #include "base/strings/sys_string_conversions.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/themes/theme_service.h"
+#include "chrome/browser/ui/cocoa/cocoa_util.h"
 #include "chrome/browser/ui/cocoa/l10n_util.h"
 #import "chrome/browser/ui/cocoa/tabs/alert_indicator_button_cocoa.h"
 #import "chrome/browser/ui/cocoa/tabs/tab_controller.h"
@@ -185,12 +186,6 @@
   }
 }
 
-CGFloat LineWidthFromContext(CGContextRef context) {
-  CGRect unitRect = CGRectMake(0.0, 0.0, 1.0, 1.0);
-  CGRect deviceRect = CGContextConvertRectToDeviceSpace(context, unitRect);
-  return 1.0 / deviceRect.size.height;
-}
-
 }  // namespace
 
 @interface TabViewCocoa (Private)
@@ -930,7 +925,7 @@
   }
 
   // The line width is always 1px.
-  CGFloat lineWidth = LineWidthFromContext(context);
+  CGFloat lineWidth = cocoa_util::LineWidthFromContext(context);
   [bezierPath setLineWidth:lineWidth];
 
   // Screen pixels lay between integral coordinates in user space. If you draw
@@ -972,7 +967,7 @@
 
   CGContextRef context = static_cast<CGContextRef>(
       [[NSGraphicsContext currentContext] graphicsPort]);
-  CGFloat lineWidth = LineWidthFromContext(context);
+  CGFloat lineWidth = cocoa_util::LineWidthFromContext(context);
 
   // Line width is always 1px.
   [middleEdgePath setLineWidth:lineWidth];
diff --git a/chrome/browser/ui/passwords/password_manager_presenter.cc b/chrome/browser/ui/passwords/password_manager_presenter.cc
index 693675b6..46cc748 100644
--- a/chrome/browser/ui/passwords/password_manager_presenter.cc
+++ b/chrome/browser/ui/passwords/password_manager_presenter.cc
@@ -50,9 +50,8 @@
 // from |duplicates|.
 void RemoveDuplicates(const autofill::PasswordForm& form,
                       password_manager::DuplicatesMap* duplicates,
-                      PasswordStore* store,
-                      password_manager::PasswordEntryType entry_type) {
-  std::string key = password_manager::CreateSortKey(form, entry_type);
+                      PasswordStore* store) {
+  std::string key = password_manager::CreateSortKey(form);
   std::pair<password_manager::DuplicatesMap::iterator,
             password_manager::DuplicatesMap::iterator>
       dups = duplicates->equal_range(key);
@@ -193,8 +192,7 @@
     return;
 
   const autofill::PasswordForm& password_entry = *password_list_[index];
-  RemoveDuplicates(password_entry, &password_duplicates_, store,
-                   password_manager::PasswordEntryType::SAVED);
+  RemoveDuplicates(password_entry, &password_duplicates_, store);
   RemoveLogin(password_entry);
   base::RecordAction(
       base::UserMetricsAction("PasswordManager_RemoveSavedPassword"));
@@ -215,7 +213,7 @@
   const autofill::PasswordForm& password_exception_entry =
       *password_exception_list_[index];
   RemoveDuplicates(password_exception_entry, &password_exception_duplicates_,
-                   store, password_manager::PasswordEntryType::BLACKLISTED);
+                   store);
   RemoveLogin(password_exception_entry);
   base::RecordAction(
       base::UserMetricsAction("PasswordManager_RemovePasswordException"));
@@ -346,9 +344,8 @@
 void PasswordManagerPresenter::PasswordListPopulater::OnGetPasswordStoreResults(
     std::vector<std::unique_ptr<autofill::PasswordForm>> results) {
   page_->password_list_ = std::move(results);
-  password_manager::SortEntriesAndHideDuplicates(
-      &page_->password_list_, &page_->password_duplicates_,
-      password_manager::PasswordEntryType::SAVED);
+  password_manager::SortEntriesAndHideDuplicates(&page_->password_list_,
+                                                 &page_->password_duplicates_);
   page_->SetPasswordList();
 }
 
@@ -372,7 +369,6 @@
         std::vector<std::unique_ptr<autofill::PasswordForm>> results) {
   page_->password_exception_list_ = std::move(results);
   password_manager::SortEntriesAndHideDuplicates(
-      &page_->password_exception_list_, &page_->password_exception_duplicates_,
-      password_manager::PasswordEntryType::BLACKLISTED);
+      &page_->password_exception_list_, &page_->password_exception_duplicates_);
   page_->SetPasswordExceptionList();
 }
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
index 7af4b02f..c2868b5 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -101,6 +101,11 @@
 #include "components/rlz/rlz_tracker.h"  // nogncheck
 #endif
 
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS) && !defined(OS_ANDROID) && \
+    !defined(OS_CHROMEOS)
+#include "chrome/browser/ui/startup/supervised_users_deprecated_infobar_delegate.h"
+#endif
+
 using content::ChildProcessSecurityPolicy;
 using content::WebContents;
 using extensions::Extension;
@@ -924,6 +929,11 @@
           !local_state->GetBoolean(prefs::kSuppressUnsupportedOSWarning))
         ObsoleteSystemInfoBarDelegate::Create(infobar_service);
     }
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS) && !defined(OS_ANDROID) && \
+    !defined(OS_CHROMEOS)
+    if (profile_->IsLegacySupervised())
+      SupervisedUsersDeprecatedInfoBarDelegate::Create(infobar_service);
+#endif
 
 #if !defined(OS_CHROMEOS)
     if (!command_line_.HasSwitch(switches::kNoDefaultBrowserCheck)) {
diff --git a/chrome/browser/ui/startup/supervised_users_deprecated_infobar_delegate.cc b/chrome/browser/ui/startup/supervised_users_deprecated_infobar_delegate.cc
new file mode 100644
index 0000000..acd18f1d
--- /dev/null
+++ b/chrome/browser/ui/startup/supervised_users_deprecated_infobar_delegate.cc
@@ -0,0 +1,58 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/startup/supervised_users_deprecated_infobar_delegate.h"
+
+#include "chrome/browser/infobars/infobar_service.h"
+#include "chrome/grit/chromium_strings.h"
+#include "components/infobars/core/infobar.h"
+#include "components/strings/grit/components_strings.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+constexpr char kSupervisedUsersDeprecatedLearnMoreLink[] =
+    "https://support.google.com.com/chrome?p=supervised_users";
+}  // namespace
+
+// static
+void SupervisedUsersDeprecatedInfoBarDelegate::Create(
+    InfoBarService* infobar_service) {
+  infobar_service->AddInfoBar(infobar_service->CreateConfirmInfoBar(
+      base::WrapUnique(static_cast<ConfirmInfoBarDelegate*>(
+          new SupervisedUsersDeprecatedInfoBarDelegate()))));
+}
+
+SupervisedUsersDeprecatedInfoBarDelegate::
+    SupervisedUsersDeprecatedInfoBarDelegate()
+    : ConfirmInfoBarDelegate() {}
+
+SupervisedUsersDeprecatedInfoBarDelegate::
+    ~SupervisedUsersDeprecatedInfoBarDelegate() {}
+
+infobars::InfoBarDelegate::InfoBarIdentifier
+SupervisedUsersDeprecatedInfoBarDelegate::GetIdentifier() const {
+  return SUPERVISED_USERS_DEPRECATED_INFOBAR_DELEGATE;
+}
+
+base::string16 SupervisedUsersDeprecatedInfoBarDelegate::GetMessageText()
+    const {
+  return l10n_util::GetStringUTF16(IDS_SUPERVISED_USERS_DEPRECATED_MESSAGE);
+}
+
+int SupervisedUsersDeprecatedInfoBarDelegate::GetButtons() const {
+  return BUTTON_NONE;
+}
+
+base::string16 SupervisedUsersDeprecatedInfoBarDelegate::GetLinkText() const {
+  return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
+}
+
+GURL SupervisedUsersDeprecatedInfoBarDelegate::GetLinkURL() const {
+  return GURL(kSupervisedUsersDeprecatedLearnMoreLink);
+}
+
+bool SupervisedUsersDeprecatedInfoBarDelegate::ShouldExpire(
+    const NavigationDetails& navigation_details) const {
+  return false;
+}
diff --git a/chrome/browser/ui/startup/supervised_users_deprecated_infobar_delegate.h b/chrome/browser/ui/startup/supervised_users_deprecated_infobar_delegate.h
new file mode 100644
index 0000000..329c7c3
--- /dev/null
+++ b/chrome/browser/ui/startup/supervised_users_deprecated_infobar_delegate.h
@@ -0,0 +1,37 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_STARTUP_SUPERVISED_USERS_DEPRECATED_INFOBAR_DELEGATE_H_
+#define CHROME_BROWSER_UI_STARTUP_SUPERVISED_USERS_DEPRECATED_INFOBAR_DELEGATE_H_
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/strings/string16.h"
+#include "components/infobars/core/confirm_infobar_delegate.h"
+#include "url/gurl.h"
+
+class InfoBarService;
+
+// An infobar that displays a message saying that supervised users is obsolete,
+// along with a "Learn More" link.
+class SupervisedUsersDeprecatedInfoBarDelegate : public ConfirmInfoBarDelegate {
+ public:
+  static void Create(InfoBarService* infobar_service);
+
+ private:
+  SupervisedUsersDeprecatedInfoBarDelegate();
+  ~SupervisedUsersDeprecatedInfoBarDelegate() override;
+
+  // ConfirmInfoBarDelegate implementation.
+  infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
+  base::string16 GetMessageText() const override;
+  int GetButtons() const override;
+  base::string16 GetLinkText() const override;
+  GURL GetLinkURL() const override;
+  bool ShouldExpire(const NavigationDetails& navigation_details) const override;
+
+  DISALLOW_COPY_AND_ASSIGN(SupervisedUsersDeprecatedInfoBarDelegate);
+};
+
+#endif  // CHROME_BROWSER_UI_STARTUP_SUPERVISED_USERS_DEPRECATED_INFOBAR_DELEGATE_H_
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
index 73c49bf..95fdbba 100644
--- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
+++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
@@ -72,18 +72,6 @@
   if (!visible())
     return;
 
-  if (!layer())
-    SetPaintToLayer();
-  layer()->SetFillsBoundsOpaquely(false);
-
-  // When using focus rings are visible we should hide the separator instantly
-  // when the IconLabelBubbleView is focused. Otherwise we should follow the
-  // inkdrop.
-  if (views::PlatformStyle::kPreferFocusRings && owner_->is_focused()) {
-    layer()->SetOpacity(0.0f);
-    return;
-  }
-
   views::InkDrop* ink_drop = owner_->GetInkDrop();
   DCHECK(ink_drop);
 
@@ -100,6 +88,10 @@
     duration = kFadeInDurationMs;
   }
 
+  if (!layer())
+    SetPaintToLayer();
+  layer()->SetFillsBoundsOpaquely(false);
+
   if (disable_animation_for_test_) {
     layer()->SetOpacity(opacity);
   } else {
@@ -385,18 +377,6 @@
   OnActivate(event);
 }
 
-void IconLabelBubbleView::OnFocus() {
-  is_focused_ = true;
-  separator_view_->UpdateOpacity();
-  Button::OnFocus();
-}
-
-void IconLabelBubbleView::OnBlur() {
-  is_focused_ = false;
-  separator_view_->UpdateOpacity();
-  Button::OnBlur();
-}
-
 void IconLabelBubbleView::OnWidgetDestroying(views::Widget* widget) {
   widget->RemoveObserver(this);
 }
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h
index 3194df4..4d3254d 100644
--- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h
+++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.h
@@ -87,8 +87,6 @@
 
   void OnBubbleCreated(views::Widget* bubble_widget);
 
-  bool is_focused() const { return is_focused_; }
-
  protected:
   static constexpr int kOpenTimeMS = 150;
 
@@ -156,8 +154,6 @@
   bool IsTriggerableEvent(const ui::Event& event) override;
   bool ShouldUpdateInkDropOnClickCanceled() const override;
   void NotifyClick(const ui::Event& event) override;
-  void OnFocus() override;
-  void OnBlur() override;
 
   // views::WidgetObserver:
   void OnWidgetDestroying(views::Widget* widget) override;
@@ -192,7 +188,6 @@
   views::Label* label_;
   views::InkDropContainerView* ink_drop_container_;
   SeparatorView* separator_view_;
-  bool is_focused_ = false;
 
   // The padding of the element that will be displayed after |this|. This value
   // is relevant for calculating the amount of space to reserve after the
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui_unittest.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui_unittest.cc
index 4f8c397..a8b5019 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_ui_unittest.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_ui_unittest.cc
@@ -31,7 +31,7 @@
 
 scoped_refptr<base::RefCountedBytes> CreateTestData() {
   const unsigned char blob1[] =
-      "12346102356120394751634516591348710478123649165419234519234512349134";
+      "%PDF-1.4123461023561203947516345165913487104781236491654192345192345";
   std::vector<unsigned char> preview_data(blob1, blob1 + sizeof(blob1));
   return base::MakeRefCounted<base::RefCountedBytes>(preview_data);
 }
@@ -105,11 +105,6 @@
   EXPECT_EQ(dummy_data->size(), data->size());
   EXPECT_EQ(dummy_data.get(), data.get());
 
-  // This should not cause any memory leaks.
-  dummy_data = base::MakeRefCounted<base::RefCountedBytes>();
-  preview_ui->SetPrintPreviewDataForIndex(printing::FIRST_PAGE_INDEX,
-                                          dummy_data.get());
-
   // Clear the preview data.
   preview_ui->ClearAllPreviewData();
 
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 745ab481..6b81541a 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
@@ -1610,6 +1610,7 @@
     {"syncAsName", IDS_SETTINGS_PEOPLE_SYNC_AS_NAME},
     {"syncingTo", IDS_SETTINGS_PEOPLE_SYNCING_TO_ACCOUNT},
     {"turnOffSync", IDS_SETTINGS_PEOPLE_SYNC_TURN_OFF},
+    {"signInAgain", IDS_SYNC_ERROR_USER_MENU_SIGNIN_AGAIN_BUTTON},
     {"syncNotWorking", IDS_SETTINGS_PEOPLE_SYNC_NOT_WORKING},
     {"syncPaused", IDS_SETTINGS_PEOPLE_SYNC_PAUSED},
     {"syncSignInPromptWithAccount",
diff --git a/chrome/browser/ui/webui/settings/people_handler_unittest.cc b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
index c52c479..7355f1f 100644
--- a/chrome/browser/ui/webui/settings/people_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
@@ -253,7 +253,8 @@
     // An initialized ProfileSyncService will have already completed sync setup
     // and will have an initialized sync engine.
     ASSERT_TRUE(mock_signin_->IsInitialized());
-    ON_CALL(*mock_pss_, IsEngineInitialized()).WillByDefault(Return(true));
+    ON_CALL(*mock_pss_, GetState())
+        .WillByDefault(Return(syncer::SyncService::State::ACTIVE));
   }
 
   void ExpectPageStatusResponse(const std::string& expected_status) {
@@ -396,7 +397,8 @@
       .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
   ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(false));
   error_ = GoogleServiceAuthError::AuthErrorNone();
-  ON_CALL(*mock_pss_, IsEngineInitialized()).WillByDefault(Return(false));
+  ON_CALL(*mock_pss_, GetState())
+      .WillByDefault(Return(syncer::SyncService::State::INITIALIZING));
   EXPECT_CALL(*mock_pss_, RequestStart());
 
   // We're simulating a user setting up sync, which would cause the engine to
@@ -422,7 +424,9 @@
       .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
   error_ = GoogleServiceAuthError::AuthErrorNone();
   // Sync engine is stopped initially, and will start up.
-  ON_CALL(*mock_pss_, IsEngineInitialized()).WillByDefault(Return(false));
+  ON_CALL(*mock_pss_, GetState())
+      .WillByDefault(
+          Return(syncer::SyncService::State::WAITING_FOR_START_REQUEST));
   EXPECT_CALL(*mock_pss_, RequestStart());
   SetDefaultExpectationsForConfigPage();
 
@@ -434,7 +438,8 @@
   Mock::VerifyAndClearExpectations(mock_pss_);
   // Now, act as if the ProfileSyncService has started up.
   SetDefaultExpectationsForConfigPage();
-  ON_CALL(*mock_pss_, IsEngineInitialized()).WillByDefault(Return(true));
+  ON_CALL(*mock_pss_, GetState())
+      .WillByDefault(Return(syncer::SyncService::State::ACTIVE));
   error_ = GoogleServiceAuthError::AuthErrorNone();
   ON_CALL(*mock_pss_, GetAuthError()).WillByDefault(ReturnRef(error_));
   handler_->SyncStartupCompleted();
@@ -459,9 +464,9 @@
       .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
   ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(false));
   error_ = GoogleServiceAuthError::AuthErrorNone();
-  EXPECT_CALL(*mock_pss_, IsEngineInitialized())
-      .WillOnce(Return(false))
-      .WillRepeatedly(Return(true));
+  EXPECT_CALL(*mock_pss_, GetState())
+      .WillOnce(Return(syncer::SyncService::State::INITIALIZING))
+      .WillRepeatedly(Return(syncer::SyncService::State::ACTIVE));
   EXPECT_CALL(*mock_pss_, RequestStart());
   SetDefaultExpectationsForConfigPage();
   handler_->HandleShowSetupUI(nullptr);
@@ -483,7 +488,8 @@
       .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
   ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(false));
   error_ = GoogleServiceAuthError::AuthErrorNone();
-  ON_CALL(*mock_pss_, IsEngineInitialized()).WillByDefault(Return(false));
+  ON_CALL(*mock_pss_, GetState())
+      .WillByDefault(Return(syncer::SyncService::State::INITIALIZING));
   EXPECT_CALL(*mock_pss_, RequestStart());
 
   handler_->HandleShowSetupUI(nullptr);
@@ -503,7 +509,8 @@
 // Tests that signals not related to user intention to configure sync don't
 // trigger sync engine start.
 TEST_F(PeopleHandlerTest, OnlyStartEngineWhenConfiguringSync) {
-  ON_CALL(*mock_pss_, IsEngineInitialized()).WillByDefault(Return(false));
+  ON_CALL(*mock_pss_, GetState())
+      .WillByDefault(Return(syncer::SyncService::State::INITIALIZING));
   EXPECT_CALL(*mock_pss_, RequestStart()).Times(0);
   NotifySyncStateChanged();
 }
@@ -767,7 +774,8 @@
   ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false));
   ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase())
       .WillByDefault(Return(false));
-  ON_CALL(*mock_pss_, IsEngineInitialized()).WillByDefault(Return(false));
+  ON_CALL(*mock_pss_, GetState())
+      .WillByDefault(Return(syncer::SyncService::State::INITIALIZING));
 
 #if defined(OS_CHROMEOS)
   // On ChromeOS, auth errors are ignored - instead we just try to start the
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 cfd7e7c..0af314b 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
@@ -262,8 +262,8 @@
     EXPECT_CALL(*sync_service_mock, GetSetupInProgressHandle()).Times(1);
     ON_CALL(*sync_service_mock, GetDisableReasons())
         .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
-    ON_CALL(*sync_service_mock, IsEngineInitialized())
-        .WillByDefault(Return(true));
+    ON_CALL(*sync_service_mock, GetState())
+        .WillByDefault(Return(syncer::SyncService::State::ACTIVE));
   }
 
   void SetExpectationsForSyncStartupPending() {
@@ -272,8 +272,8 @@
     EXPECT_CALL(*sync_service_mock, GetSetupInProgressHandle()).Times(1);
     ON_CALL(*sync_service_mock, GetDisableReasons())
         .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
-    ON_CALL(*sync_service_mock, IsEngineInitialized())
-        .WillByDefault(Return(false));
+    ON_CALL(*sync_service_mock, GetState())
+        .WillByDefault(Return(syncer::SyncService::State::INITIALIZING));
     ON_CALL(*sync_service_mock, GetAuthError())
         .WillByDefault(ReturnRef(kNoAuthError));
   }
diff --git a/chrome/browser/ui/webui/sync_internals_message_handler.cc b/chrome/browser/ui/webui/sync_internals_message_handler.cc
index 49fe3b3..814a413 100644
--- a/chrome/browser/ui/webui/sync_internals_message_handler.cc
+++ b/chrome/browser/ui/webui/sync_internals_message_handler.cc
@@ -292,7 +292,7 @@
   if (!service)
     return;
 
-  service->RequestStop(SyncService::KEEP_DATA);
+  service->RequestStop(SyncService::CLEAR_DATA);
 }
 
 void SyncInternalsMessageHandler::HandleTriggerRefresh(
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 2951ee28..6107cff 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -80,7 +80,6 @@
 #include "components/network_hints/renderer/prescient_networking_dispatcher.h"
 #include "components/pdf/renderer/pepper_pdf_host.h"
 #include "components/safe_browsing/renderer/threat_dom_details.h"
-#include "components/safe_browsing/renderer/websocket_sb_handshake_throttle.h"
 #include "components/services/heap_profiling/public/cpp/allocator_shim.h"
 #include "components/spellcheck/spellcheck_buildflags.h"
 #include "components/startup_metric_utils/common/startup_metric.mojom.h"
@@ -1379,17 +1378,6 @@
 }
 #endif
 
-// TODO(nhiroki): Remove this once the off-main-thread WebSocket is enabled by
-// default (https://crbug.com/825740).
-std::unique_ptr<blink::WebSocketHandshakeThrottle>
-ChromeContentRendererClient::CreateWebSocketHandshakeThrottle() {
-  InitSafeBrowsingIfNecessary();
-  // This is called only for Shared Worker and Service Worker that don't have a
-  // real frame, so we specify MSG_ROUTING_NONE here.
-  return std::make_unique<safe_browsing::WebSocketSBHandshakeThrottle>(
-      safe_browsing_.get(), MSG_ROUTING_NONE);
-}
-
 std::unique_ptr<content::WebSocketHandshakeThrottleProvider>
 ChromeContentRendererClient::CreateWebSocketHandshakeThrottleProvider() {
   return std::make_unique<WebSocketHandshakeThrottleProviderImpl>();
@@ -1678,15 +1666,6 @@
   return task_scheduler_util::GetTaskSchedulerInitParamsForRenderer();
 }
 
-// TODO(nhiroki): Remove this once the off-main-thread WebSocket is enabled by
-// default (https://crbug.com/825740).
-void ChromeContentRendererClient::InitSafeBrowsingIfNecessary() {
-  if (safe_browsing_)
-    return;
-  RenderThread::Get()->GetConnector()->BindInterface(
-      content::mojom::kBrowserServiceName, &safe_browsing_);
-}
-
 bool ChromeContentRendererClient::OverrideLegacySymantecCertConsoleMessage(
     const GURL& url,
     std::string* console_message) {
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h
index 5b8b730..811b2f2 100644
--- a/chrome/renderer/chrome_content_renderer_client.h
+++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -20,7 +20,6 @@
 #include "chrome/renderer/media/chrome_key_systems_provider.h"
 #include "components/nacl/common/buildflags.h"
 #include "components/rappor/public/interfaces/rappor_recorder.mojom.h"
-#include "components/safe_browsing/common/safe_browsing.mojom.h"
 #include "components/spellcheck/spellcheck_buildflags.h"
 #include "content/public/renderer/content_renderer_client.h"
 #include "content/public/renderer/render_thread.h"
@@ -173,8 +172,6 @@
       blink::mojom::PageVisibilityState* override_state) override;
   bool IsExternalPepperPlugin(const std::string& module_name) override;
   bool IsOriginIsolatedPepperPlugin(const base::FilePath& plugin_path) override;
-  std::unique_ptr<blink::WebSocketHandshakeThrottle>
-  CreateWebSocketHandshakeThrottle() override;
   std::unique_ptr<content::WebSocketHandshakeThrottleProvider>
   CreateWebSocketHandshakeThrottleProvider() override;
   std::unique_ptr<blink::WebSpeechSynthesizer> OverrideSpeechSynthesizer(
@@ -274,9 +271,6 @@
   void GetInterface(const std::string& name,
                     mojo::ScopedMessagePipeHandle request_handle) override;
 
-  // Initialises |safe_browsing_| if it is not already initialised.
-  void InitSafeBrowsingIfNecessary();
-
   void PrepareErrorPageInternal(content::RenderFrame* render_frame,
                                 const blink::WebURLRequest& failed_request,
                                 const error_page::Error& error,
@@ -316,8 +310,6 @@
 
   ChromeKeySystemsProvider key_systems_provider_;
 
-  safe_browsing::mojom::SafeBrowsingPtr safe_browsing_;
-
 #if BUILDFLAG(ENABLE_SPELLCHECK)
   std::unique_ptr<SpellCheck> spellcheck_;
 #endif
diff --git a/chrome/test/data/extensions/api_test/mime_handler_view/index.js b/chrome/test/data/extensions/api_test/mime_handler_view/index.js
index c727e316..72d5e7c9 100644
--- a/chrome/test/data/extensions/api_test/mime_handler_view/index.js
+++ b/chrome/test/data/extensions/api_test/mime_handler_view/index.js
@@ -249,14 +249,14 @@
 
   function testBeforeUnloadNoDialog() {
     checkStreamDetails('testBeforeUnloadNoDialog.csv', false);
-    chrome.mimeHandlerPrivate.setShowBeforeUnloadDialog(false);
-    chrome.test.succeed();
+    chrome.mimeHandlerPrivate.setShowBeforeUnloadDialog(
+        false, chrome.test.succeed);
   },
 
   function testBeforeUnloadShowDialog() {
     checkStreamDetails('testBeforeUnloadShowDialog.csv', false);
-    chrome.mimeHandlerPrivate.setShowBeforeUnloadDialog(true);
-    chrome.test.succeed();
+    chrome.mimeHandlerPrivate.setShowBeforeUnloadDialog(
+        true, chrome.test.succeed);
   },
 ];
 
diff --git a/chrome/test/data/webui/OWNERS b/chrome/test/data/webui/OWNERS
index c6b374e..7c9f94f 100644
--- a/chrome/test/data/webui/OWNERS
+++ b/chrome/test/data/webui/OWNERS
@@ -1,5 +1,5 @@
-dpapad@chromium.org
-michaelpg@chromium.org
+file://ui/webui/PLATFORM_OWNERS
+rbpotter@chromium.org
 
 per-file *.mojom=set noparent
 per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chrome/test/data/webui/print_preview/plugin_stub.js b/chrome/test/data/webui/print_preview/plugin_stub.js
index d2d000d..e743e3e 100644
--- a/chrome/test/data/webui/print_preview/plugin_stub.js
+++ b/chrome/test/data/webui/print_preview/plugin_stub.js
@@ -78,7 +78,7 @@
      */
     loadPreviewPage(previewUid, pageIndex, index) {
       if (this.loadCallback_)
-        this.loadCallback_();
+        this.loadCallback_(true);
     }
   }
 
diff --git a/chrome/test/data/webui/settings/sync_account_control_test.js b/chrome/test/data/webui/settings/sync_account_control_test.js
index 5a8bc9b..198069f 100644
--- a/chrome/test/data/webui/settings/sync_account_control_test.js
+++ b/chrome/test/data/webui/settings/sync_account_control_test.js
@@ -122,7 +122,7 @@
       ]);
 
       const userInfo = testElement.$$('#user-info');
-      const syncButton = testElement.$$('#avatar-row .action-button');
+      const syncButton = testElement.$$('#sync-button');
 
       // Avatar row shows the right account.
       assertVisible(testElement.$$('#promo-header'), true);
@@ -145,7 +145,7 @@
       // "sync to" button is showing the correct name and syncs with the
       // correct account when clicked.
       assertVisible(syncButton, true);
-      assertVisible(testElement.$$('#avatar-row .secondary-button'), false);
+      assertVisible(testElement.$$('#turn-off'), false);
       assertTrue(syncButton.textContent.includes('foo'));
       assertFalse(syncButton.textContent.includes('bar'));
       syncButton.click();
@@ -230,8 +230,9 @@
       assertFalse(userInfo.textContent.includes('fooName'));
       assertFalse(userInfo.textContent.includes('foo@foo.com'));
 
-      assertVisible(testElement.$$('#avatar-row .action-button'), false);
-      assertVisible(testElement.$$('#avatar-row .secondary-button'), true);
+      assertVisible(testElement.$$('#sync-button'), false);
+      assertVisible(testElement.$$('#turn-off'), true);
+      assertVisible(testElement.$$('#sync-paused-button'), false);
 
       testElement.$$('#avatar-row .secondary-button').click();
       Polymer.dom.flush();
@@ -268,6 +269,8 @@
       assertFalse(displayedText.includes('barName'));
       assertFalse(displayedText.includes('fooName'));
       assertTrue(displayedText.includes('Sync is paused'));
+      // Not embedded in a subpage, so there is no sync-paused button.
+      assertVisible(testElement.$$('#sync-paused-button'), false);
 
       testElement.syncStatus = {
         signedIn: true,
@@ -287,7 +290,7 @@
     });
 
     test('embedded in another page', function() {
-      testElement.alwaysShowPromo = true;
+      testElement.embeddedInSubpage = true;
       forcePromoResetWithCount(100, false);
       const banner = testElement.$$('#banner');
       assertVisible(banner, true);
@@ -301,6 +304,18 @@
       };
 
       assertVisible(testElement.$$('#turn-off'), false);
+      assertVisible(testElement.$$('#sync-paused-button'), false);
+
+      testElement.embeddedInSubpage = true;
+      testElement.syncStatus = {
+        signedIn: true,
+        signedInUsername: 'bar@bar.com',
+        hasError: true,
+        statusAction: settings.StatusAction.REAUTHENTICATE,
+        disabled: false,
+      };
+      assertVisible(testElement.$$('#turn-off'), false);
+      assertVisible(testElement.$$('#sync-paused-button'), true);
     });
   });
 });
diff --git a/components/autofill/core/browser/test_sync_service.cc b/components/autofill/core/browser/test_sync_service.cc
index c1680e2..afe8e86 100644
--- a/components/autofill/core/browser/test_sync_service.cc
+++ b/components/autofill/core/browser/test_sync_service.cc
@@ -30,10 +30,6 @@
   return data_types_;
 }
 
-bool TestSyncService::IsEngineInitialized() const {
-  return is_engine_initialized_;
-}
-
 bool TestSyncService::IsFirstSetupComplete() const {
   return true;
 }
diff --git a/components/autofill/core/browser/test_sync_service.h b/components/autofill/core/browser/test_sync_service.h
index 2be40aa..f3dea07 100644
--- a/components/autofill/core/browser/test_sync_service.h
+++ b/components/autofill/core/browser/test_sync_service.h
@@ -19,7 +19,6 @@
   int GetDisableReasons() const override;
   syncer::ModelTypeSet GetPreferredDataTypes() const override;
   syncer::ModelTypeSet GetActiveDataTypes() const override;
-  bool IsEngineInitialized() const override;
   bool IsFirstSetupComplete() const override;
   bool IsUsingSecondaryPassphrase() const override;
   syncer::SyncCycleSnapshot GetLastCycleSnapshot() const override;
@@ -34,10 +33,6 @@
     data_types_ = data_types;
   }
 
-  void SetIsEngineInitialized(bool is_engine_initialized) {
-    is_engine_initialized_ = is_engine_initialized;
-  }
-
   void SetIsUsingSecondaryPassphrase(bool is_using_secondary_passphrase) {
     is_using_secondary_passphrase_ = is_using_secondary_passphrase;
   }
@@ -50,7 +45,6 @@
   int disable_reasons_ = DISABLE_REASON_NONE;
   // Used as both "preferred" and "active" data types.
   syncer::ModelTypeSet data_types_;
-  bool is_engine_initialized_ = true;
   bool is_using_secondary_passphrase_ = false;
   bool sync_cycle_complete_ = true;
   GoogleServiceAuthError auth_error_;
diff --git a/components/browser_sync/profile_sync_components_factory_impl.cc b/components/browser_sync/profile_sync_components_factory_impl.cc
index 6a78faf..0cec2e2 100644
--- a/components/browser_sync/profile_sync_components_factory_impl.cc
+++ b/components/browser_sync/profile_sync_components_factory_impl.cc
@@ -250,13 +250,6 @@
         syncer::GROUP_UI, ui_thread_));
   }
 
-  // Article sync is disabled by default.  Register only if explicitly enabled.
-  if (dom_distiller::IsEnableSyncArticlesSet()) {
-    controllers.push_back(std::make_unique<AsyncDirectoryTypeController>(
-        syncer::ARTICLES, error_callback, sync_client_, syncer::GROUP_UI,
-        ui_thread_));
-  }
-
 #if defined(OS_CHROMEOS)
   if (!disabled_types.Has(syncer::PRINTERS)) {
     controllers.push_back(std::make_unique<ModelTypeController>(
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc
index 54c4bfa..5fe883f3 100644
--- a/components/browser_sync/profile_sync_service.cc
+++ b/components/browser_sync/profile_sync_service.cc
@@ -774,7 +774,7 @@
   // Typically, Sync won't start until the initial setup is at least in
   // progress. StartupController::TryStartImmediately bypasses the first setup
   // check though, so we first have to check whether the engine is initialized.
-  if (!IsEngineInitialized()) {
+  if (!engine_initialized_) {
     switch (startup_controller_->GetState()) {
       case syncer::StartupController::State::NOT_STARTED:
         DCHECK(!engine_);
@@ -826,7 +826,7 @@
 void ProfileSyncService::SetFirstSetupComplete() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sync_prefs_.SetFirstSetupComplete();
-  if (IsEngineInitialized()) {
+  if (engine_initialized_) {
     ReconfigureDatatypeManager();
   }
 }
@@ -1319,11 +1319,6 @@
   return !GetAuthenticatedAccountInfo().account_id.empty();
 }
 
-bool ProfileSyncService::IsEngineInitialized() const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return engine_initialized_;
-}
-
 bool ProfileSyncService::IsPassphraseRequired() const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return crypto_->passphrase_required_reason() !=
@@ -1750,7 +1745,7 @@
     const std::vector<gaia::ListedAccount>& accounts,
     const base::Closure& callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (!IsEngineInitialized())
+  if (!engine_initialized_)
     return;
 
   bool cookie_jar_mismatch = HasCookieJarMismatch(accounts);
@@ -2187,7 +2182,7 @@
   if (--outstanding_setup_in_progress_handles_ != 0)
     return;
 
-  if (IsEngineInitialized())
+  if (engine_initialized_)
     ReconfigureDatatypeManager();
   NotifyObservers();
 }
diff --git a/components/browser_sync/profile_sync_service.h b/components/browser_sync/profile_sync_service.h
index 3049c15..c1e4767a 100644
--- a/components/browser_sync/profile_sync_service.h
+++ b/components/browser_sync/profile_sync_service.h
@@ -252,7 +252,6 @@
       override;
   bool IsSetupInProgress() const override;
   const GoogleServiceAuthError& GetAuthError() const override;
-  bool IsEngineInitialized() const override;
   sync_sessions::OpenTabsUIDelegate* GetOpenTabsUIDelegate() override;
   bool IsPassphraseRequiredForDecryption() const override;
   base::Time GetExplicitPassphraseTime() const override;
diff --git a/components/browser_sync/profile_sync_service_mock.h b/components/browser_sync/profile_sync_service_mock.h
index 11b42e1..b68d823f 100644
--- a/components/browser_sync/profile_sync_service_mock.h
+++ b/components/browser_sync/profile_sync_service_mock.h
@@ -76,7 +76,6 @@
   MOCK_CONST_METHOD0(GetAuthError, const GoogleServiceAuthError&());
   MOCK_CONST_METHOD0(IsSetupInProgress, bool());
   MOCK_CONST_METHOD0(GetLastSyncedTime, base::Time());
-  MOCK_CONST_METHOD0(IsEngineInitialized, bool());
   MOCK_CONST_METHOD0(IsSyncConfirmationNeeded, bool());
   MOCK_METHOD1(OnActionableError, void(const syncer::SyncProtocolError&));
   MOCK_CONST_METHOD1(IsDataTypeControllerRunning, bool(syncer::ModelType));
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc
index 7272010a..93063bb 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.cc
@@ -247,10 +247,12 @@
                                  const std::string& pref_dst,
                                  const std::string& pref_src) {
   DictionaryPrefUpdate pref_update_dst(pref_service, pref_dst);
+  base::DictionaryValue* pref_dict_dst = pref_update_dst.Get();
   DictionaryPrefUpdate pref_update_src(pref_service, pref_src);
-  pref_update_dst->Clear();
-  pref_update_dst->Swap(pref_update_src.Get());
-  DCHECK(pref_update_src->empty());
+  base::DictionaryValue* pref_dict_src = pref_update_src.Get();
+  pref_dict_dst->Clear();
+  pref_dict_dst->Swap(pref_dict_src);
+  DCHECK(pref_dict_src->empty());
 }
 
 void MaybeInitWeeklyAggregateDataUsePrefs(const base::Time& now,
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
index 75ba84f..9149d4ea 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
@@ -357,10 +357,10 @@
 
   ui_task_runner_->PostTask(
       FROM_HERE,
-      base::BindOnce(&DataReductionProxyService::UpdateContentLengths, service_,
-                     data_used, original_size, data_reduction_proxy_enabled,
-                     request_type, mime_type, is_user_traffic, content_type,
-                     service_hash_code));
+      base::BindRepeating(&DataReductionProxyService::UpdateContentLengths,
+                          service_, data_used, original_size,
+                          data_reduction_proxy_enabled, request_type, mime_type,
+                          is_user_traffic, content_type, service_hash_code));
 }
 
 void DataReductionProxyIOData::AddEvent(std::unique_ptr<base::Value> event) {
diff --git a/components/dom_distiller/core/dom_distiller_features.cc b/components/dom_distiller/core/dom_distiller_features.cc
index 3d44ddf..8c01dd1 100644
--- a/components/dom_distiller/core/dom_distiller_features.cc
+++ b/components/dom_distiller/core/dom_distiller_features.cc
@@ -16,9 +16,4 @@
           switches::kEnableDomDistiller);
 }
 
-bool IsEnableSyncArticlesSet() {
-  return base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableSyncArticles);
-}
-
 }  // namespace dom_distiller
diff --git a/components/dom_distiller/core/dom_distiller_service.cc b/components/dom_distiller/core/dom_distiller_service.cc
index 06443b5..eb1d639 100644
--- a/components/dom_distiller/core/dom_distiller_service.cc
+++ b/components/dom_distiller/core/dom_distiller_service.cc
@@ -55,13 +55,6 @@
 DomDistillerService::~DomDistillerService() {
 }
 
-syncer::SyncableService* DomDistillerService::GetSyncableService() const {
-  if (!store_) {
-    return nullptr;
-  }
-  return store_->GetSyncableService();
-}
-
 std::unique_ptr<DistillerPage> DomDistillerService::CreateDefaultDistillerPage(
     const gfx::Size& render_view_size) {
   return distiller_page_factory_->CreateDistillerPage(render_view_size);
diff --git a/components/dom_distiller/core/dom_distiller_service.h b/components/dom_distiller/core/dom_distiller_service.h
index 1e9eb71..a7677072 100644
--- a/components/dom_distiller/core/dom_distiller_service.h
+++ b/components/dom_distiller/core/dom_distiller_service.h
@@ -18,10 +18,6 @@
 
 class GURL;
 
-namespace syncer {
-class SyncableService;
-}
-
 namespace dom_distiller {
 
 class DistilledArticleProto;
@@ -42,8 +38,6 @@
   typedef base::Callback<void(bool)> ArticleAvailableCallback;
   virtual ~DomDistillerServiceInterface() {}
 
-  virtual syncer::SyncableService* GetSyncableService() const = 0;
-
   // Distill the article at |url| and add the resulting entry to the DOM
   // distiller list. |article_cb| is always invoked, and the bool argument to it
   // represents whether the article is available offline.
@@ -123,7 +117,6 @@
   ~DomDistillerService() override;
 
   // DomDistillerServiceInterface implementation.
-  syncer::SyncableService* GetSyncableService() const override;
   const std::string AddToList(
       const GURL& url,
       std::unique_ptr<DistillerPage> distiller_page,
diff --git a/components/dom_distiller/core/dom_distiller_store.cc b/components/dom_distiller/core/dom_distiller_store.cc
index a3e7d1c..9e08c65 100644
--- a/components/dom_distiller/core/dom_distiller_store.cc
+++ b/components/dom_distiller/core/dom_distiller_store.cc
@@ -67,11 +67,6 @@
 
 DomDistillerStore::~DomDistillerStore() {}
 
-// DomDistillerStoreInterface implementation.
-syncer::SyncableService* DomDistillerStore::GetSyncableService() {
-  return this;
-}
-
 bool DomDistillerStore::GetEntryById(const std::string& entry_id,
                                      ArticleEntry* entry) {
   return model_.GetEntryById(entry_id, entry);
@@ -127,7 +122,6 @@
   DCHECK_EQ(size_t(0), changes_missing.size());
   DCHECK_EQ(size_t(1), changes_applied.size());
 
-  ApplyChangesToSync(FROM_HERE, changes_applied);
   ApplyChangesToDatabase(changes_applied);
 
   return true;
@@ -145,49 +139,6 @@
   return model_.GetEntries();
 }
 
-// syncer::SyncableService implementation.
-SyncMergeResult DomDistillerStore::MergeDataAndStartSyncing(
-    ModelType type,
-    const SyncDataList& initial_sync_data,
-    std::unique_ptr<syncer::SyncChangeProcessor> sync_processor,
-    std::unique_ptr<syncer::SyncErrorFactory> error_handler) {
-  DCHECK_EQ(syncer::ARTICLES, type);
-  DCHECK(!sync_processor_);
-  DCHECK(!error_factory_);
-  sync_processor_ = std::move(sync_processor);
-  error_factory_ = std::move(error_handler);
-
-  SyncChangeList database_changes;
-  SyncChangeList sync_changes;
-  SyncMergeResult result =
-      MergeDataWithModel(initial_sync_data, &database_changes, &sync_changes);
-  ApplyChangesToDatabase(database_changes);
-  ApplyChangesToSync(FROM_HERE, sync_changes);
-
-  return result;
-}
-
-void DomDistillerStore::StopSyncing(ModelType type) {
-  sync_processor_.reset();
-  error_factory_.reset();
-}
-
-SyncDataList DomDistillerStore::GetAllSyncData(ModelType type) const {
-  return model_.GetAllSyncData();
-}
-
-SyncError DomDistillerStore::ProcessSyncChanges(
-    const base::Location& from_here,
-    const SyncChangeList& change_list) {
-  DCHECK(database_loaded_);
-  SyncChangeList database_changes;
-  SyncChangeList sync_changes;
-  ApplyChangesToModel(change_list, &database_changes, &sync_changes);
-  ApplyChangesToDatabase(database_changes);
-  DCHECK_EQ(size_t(0), sync_changes.size());
-  return SyncError();
-}
-
 void DomDistillerStore::NotifyObservers(const syncer::SyncChangeList& changes) {
   if (observers_.might_have_observers() && changes.size() > 0) {
     std::vector<DomDistillerObserver::ArticleUpdate> article_changes;
@@ -254,7 +205,6 @@
   SyncChangeList database_changes_needed;
   MergeDataWithModel(data, &changes_applied, &database_changes_needed);
   ApplyChangesToDatabase(database_changes_needed);
-  ApplyChangesToSync(FROM_HERE, changes_applied);
 }
 
 void DomDistillerStore::OnDatabaseSave(bool success) {
@@ -263,27 +213,9 @@
              << " Disabling modifications and sync.";
     database_.reset();
     database_loaded_ = false;
-    StopSyncing(syncer::ARTICLES);
   }
 }
 
-bool DomDistillerStore::ApplyChangesToSync(const base::Location& from_here,
-                                           const SyncChangeList& change_list) {
-  if (!sync_processor_) {
-    return false;
-  }
-  if (change_list.empty()) {
-    return true;
-  }
-
-  SyncError error = sync_processor_->ProcessSyncChanges(from_here, change_list);
-  if (error.IsSet()) {
-    StopSyncing(syncer::ARTICLES);
-    return false;
-  }
-  return true;
-}
-
 bool DomDistillerStore::ApplyChangesToDatabase(
     const SyncChangeList& change_list) {
   if (!database_loaded_) {
@@ -322,7 +254,7 @@
   DCHECK(changes_applied);
   DCHECK(changes_missing);
 
-  SyncMergeResult result(syncer::ARTICLES);
+  SyncMergeResult result(syncer::DEPRECATED_ARTICLES);
   result.set_num_items_before_association(model_.GetNumEntries());
 
   SyncChangeList changes_to_apply;
diff --git a/components/dom_distiller/core/dom_distiller_store.h b/components/dom_distiller/core/dom_distiller_store.h
index a42140ba..c1358b3 100644
--- a/components/dom_distiller/core/dom_distiller_store.h
+++ b/components/dom_distiller/core/dom_distiller_store.h
@@ -35,9 +35,6 @@
  public:
   virtual ~DomDistillerStoreInterface() {}
 
-  // Gets the syncable service for this store or null if it is not synced.
-  virtual syncer::SyncableService* GetSyncableService() = 0;
-
   virtual bool AddEntry(const ArticleEntry& entry) = 0;
   // Returns false if |entry| is not present or |entry| was not updated.
   virtual bool UpdateEntry(const ArticleEntry& entry) = 0;
@@ -72,8 +69,7 @@
 // 4. send messages (possibly handled asynchronously) containing changes_applied
 // to the other (i.e. non-source) two models.
 // TODO(cjhopman): Support deleting entries.
-class DomDistillerStore : public syncer::SyncableService,
-                          public DomDistillerStoreInterface {
+class DomDistillerStore : public DomDistillerStoreInterface {
  public:
   typedef std::vector<ArticleEntry> EntryVector;
 
@@ -93,9 +89,6 @@
 
   ~DomDistillerStore() override;
 
-  // DomDistillerStoreInterface implementation.
-  syncer::SyncableService* GetSyncableService() override;
-
   bool AddEntry(const ArticleEntry& entry) override;
   bool UpdateEntry(const ArticleEntry& entry) override;
   bool RemoveEntry(const ArticleEntry& entry) override;
@@ -107,18 +100,6 @@
   void AddObserver(DomDistillerObserver* observer) override;
   void RemoveObserver(DomDistillerObserver* observer) override;
 
-  // syncer::SyncableService implementation.
-  syncer::SyncMergeResult MergeDataAndStartSyncing(
-      syncer::ModelType type,
-      const syncer::SyncDataList& initial_sync_data,
-      std::unique_ptr<syncer::SyncChangeProcessor> sync_processor,
-      std::unique_ptr<syncer::SyncErrorFactory> error_handler) override;
-  void StopSyncing(syncer::ModelType type) override;
-  syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override;
-  syncer::SyncError ProcessSyncChanges(
-      const base::Location& from_here,
-      const syncer::SyncChangeList& change_list) override;
-
  private:
   void OnDatabaseInit(bool success);
   void OnDatabaseLoad(bool success, std::unique_ptr<EntryVector> entries);
@@ -139,8 +120,6 @@
                                 syncer::SyncChangeList* changes_to_apply,
                                 syncer::SyncChangeList* changes_missing);
 
-  bool ApplyChangesToSync(const base::Location& from_here,
-                          const syncer::SyncChangeList& change_list);
   bool ApplyChangesToDatabase(const syncer::SyncChangeList& change_list);
 
   // Applies the changes to |model_|. If the model returns an error, disables
diff --git a/components/dom_distiller/core/dom_distiller_store_unittest.cc b/components/dom_distiller/core/dom_distiller_store_unittest.cc
index ce2a0fc..5521797 100644
--- a/components/dom_distiller/core/dom_distiller_store_unittest.cc
+++ b/components/dom_distiller/core/dom_distiller_store_unittest.cc
@@ -44,8 +44,6 @@
 
 namespace {
 
-const ModelType kDomDistillerModelType = syncer::ARTICLES;
-
 typedef std::map<std::string, ArticleEntry> EntryMap;
 
 void AddEntry(const ArticleEntry& e, EntryMap* map) {
@@ -139,7 +137,6 @@
   void TearDown() override {
     store_.reset();
     fake_db_ = nullptr;
-    fake_sync_processor_ = nullptr;
   }
 
   // Creates a simple DomDistillerStore initialized with |store_model_| and
@@ -149,15 +146,6 @@
     store_.reset(test::util::CreateStoreWithFakeDB(fake_db_, store_model_));
   }
 
-  void StartSyncing() {
-    fake_sync_processor_ = new FakeSyncChangeProcessor(&sync_model_);
-
-    store_->MergeDataAndStartSyncing(
-        kDomDistillerModelType, SyncDataFromEntryMap(sync_model_),
-        base::WrapUnique<SyncChangeProcessor>(fake_sync_processor_),
-        std::unique_ptr<SyncErrorFactory>(new FakeSyncErrorFactory()));
-  }
-
  protected:
   SyncData CreateSyncData(const ArticleEntry& entry) {
     EntitySpecifics specifics = SpecificsFromEntry(entry);
@@ -183,7 +171,6 @@
 
   // Both owned by |store_|.
   FakeDB<ArticleEntry>* fake_db_;
-  FakeSyncChangeProcessor* fake_sync_processor_;
 
   int64_t next_sync_id_;
 };
@@ -309,173 +296,6 @@
   EXPECT_FALSE(store_->UpdateEntry(GetSampleEntry(0)));
 }
 
-TEST_F(DomDistillerStoreTest, TestSyncMergeWithEmptyDatabase) {
-  AddEntry(GetSampleEntry(0), &sync_model_);
-  AddEntry(GetSampleEntry(1), &sync_model_);
-  AddEntry(GetSampleEntry(2), &sync_model_);
-
-  CreateStore();
-  fake_db_->InitCallback(true);
-  fake_db_->LoadCallback(true);
-
-  StartSyncing();
-
-  EXPECT_TRUE(AreEntriesEqual(store_->GetEntries(), sync_model_));
-  EXPECT_TRUE(AreEntryMapsEqual(db_model_, sync_model_));
-}
-
-TEST_F(DomDistillerStoreTest, TestSyncMergeAfterDatabaseLoad) {
-  AddEntry(GetSampleEntry(0), &db_model_);
-  AddEntry(GetSampleEntry(1), &db_model_);
-  AddEntry(GetSampleEntry(2), &db_model_);
-
-  AddEntry(GetSampleEntry(2), &sync_model_);
-  AddEntry(GetSampleEntry(3), &sync_model_);
-  AddEntry(GetSampleEntry(4), &sync_model_);
-
-  EntryMap expected_model(db_model_);
-  AddEntry(GetSampleEntry(3), &expected_model);
-  AddEntry(GetSampleEntry(4), &expected_model);
-
-  CreateStore();
-  fake_db_->InitCallback(true);
-  fake_db_->LoadCallback(true);
-
-  EXPECT_TRUE(AreEntriesEqual(store_->GetEntries(), db_model_));
-
-  StartSyncing();
-
-  EXPECT_TRUE(AreEntriesEqual(store_->GetEntries(), expected_model));
-  EXPECT_TRUE(AreEntryMapsEqual(db_model_, expected_model));
-  EXPECT_TRUE(AreEntryMapsEqual(sync_model_, expected_model));
-}
-
-TEST_F(DomDistillerStoreTest, TestDatabaseLoadAfterSyncMerge) {
-  AddEntry(GetSampleEntry(0), &db_model_);
-  AddEntry(GetSampleEntry(1), &db_model_);
-  AddEntry(GetSampleEntry(2), &db_model_);
-
-  AddEntry(GetSampleEntry(2), &sync_model_);
-  AddEntry(GetSampleEntry(3), &sync_model_);
-  AddEntry(GetSampleEntry(4), &sync_model_);
-
-  EntryMap expected_model(db_model_);
-  AddEntry(GetSampleEntry(3), &expected_model);
-  AddEntry(GetSampleEntry(4), &expected_model);
-
-  CreateStore();
-  StartSyncing();
-
-  EXPECT_TRUE(AreEntriesEqual(store_->GetEntries(), sync_model_));
-
-  fake_db_->InitCallback(true);
-  fake_db_->LoadCallback(true);
-
-  EXPECT_TRUE(AreEntriesEqual(store_->GetEntries(), expected_model));
-  EXPECT_TRUE(AreEntryMapsEqual(db_model_, expected_model));
-  EXPECT_TRUE(AreEntryMapsEqual(sync_model_, expected_model));
-}
-
-TEST_F(DomDistillerStoreTest, TestGetAllSyncData) {
-  AddEntry(GetSampleEntry(0), &db_model_);
-  AddEntry(GetSampleEntry(1), &db_model_);
-  AddEntry(GetSampleEntry(2), &db_model_);
-
-  AddEntry(GetSampleEntry(2), &sync_model_);
-  AddEntry(GetSampleEntry(3), &sync_model_);
-  AddEntry(GetSampleEntry(4), &sync_model_);
-
-  EntryMap expected_model(db_model_);
-  AddEntry(GetSampleEntry(3), &expected_model);
-  AddEntry(GetSampleEntry(4), &expected_model);
-
-  CreateStore();
-
-  fake_db_->InitCallback(true);
-  fake_db_->LoadCallback(true);
-
-  StartSyncing();
-
-  SyncDataList data = store_->GetAllSyncData(kDomDistillerModelType);
-  DomDistillerStore::EntryVector entries;
-  for (SyncDataList::iterator it = data.begin(); it != data.end(); ++it) {
-    entries.push_back(EntryFromSpecifics(it->GetSpecifics()));
-  }
-  EXPECT_TRUE(AreEntriesEqual(entries, expected_model));
-}
-
-TEST_F(DomDistillerStoreTest, TestProcessSyncChanges) {
-  AddEntry(GetSampleEntry(0), &db_model_);
-  AddEntry(GetSampleEntry(1), &db_model_);
-  sync_model_ = db_model_;
-
-  EntryMap expected_model(db_model_);
-  AddEntry(GetSampleEntry(2), &expected_model);
-  AddEntry(GetSampleEntry(3), &expected_model);
-
-  CreateStore();
-
-  fake_db_->InitCallback(true);
-  fake_db_->LoadCallback(true);
-
-  StartSyncing();
-
-  SyncChangeList changes;
-  changes.push_back(SyncChange(FROM_HERE, SyncChange::ACTION_ADD,
-                               CreateSyncData(GetSampleEntry(2))));
-  changes.push_back(SyncChange(FROM_HERE, SyncChange::ACTION_ADD,
-                               CreateSyncData(GetSampleEntry(3))));
-
-  store_->ProcessSyncChanges(FROM_HERE, changes);
-
-  EXPECT_TRUE(AreEntriesEqual(store_->GetEntries(), expected_model));
-  EXPECT_TRUE(AreEntryMapsEqual(db_model_, expected_model));
-}
-
-TEST_F(DomDistillerStoreTest, TestSyncMergeWithSecondDomDistillerStore) {
-  AddEntry(GetSampleEntry(0), &db_model_);
-  AddEntry(GetSampleEntry(1), &db_model_);
-  AddEntry(GetSampleEntry(2), &db_model_);
-
-  EntryMap other_db_model;
-  AddEntry(GetSampleEntry(2), &other_db_model);
-  AddEntry(GetSampleEntry(3), &other_db_model);
-  AddEntry(GetSampleEntry(4), &other_db_model);
-
-  EntryMap expected_model(db_model_);
-  AddEntry(GetSampleEntry(3), &expected_model);
-  AddEntry(GetSampleEntry(4), &expected_model);
-
-  CreateStore();
-
-  fake_db_->InitCallback(true);
-  fake_db_->LoadCallback(true);
-
-  FakeDB<ArticleEntry>* other_fake_db =
-      new FakeDB<ArticleEntry>(&other_db_model);
-  std::unique_ptr<DomDistillerStore> owned_other_store(new DomDistillerStore(
-      std::unique_ptr<leveldb_proto::ProtoDatabase<ArticleEntry>>(
-          other_fake_db),
-      std::vector<ArticleEntry>(),
-      base::FilePath(FILE_PATH_LITERAL("/fake/other/path"))));
-  DomDistillerStore* other_store = owned_other_store.get();
-  other_fake_db->InitCallback(true);
-  other_fake_db->LoadCallback(true);
-
-  EXPECT_FALSE(AreEntriesEqual(store_->GetEntries(), expected_model));
-  EXPECT_FALSE(AreEntriesEqual(other_store->GetEntries(), expected_model));
-  ASSERT_TRUE(AreEntriesEqual(other_store->GetEntries(), other_db_model));
-
-  FakeSyncErrorFactory* other_error_factory = new FakeSyncErrorFactory();
-  store_->MergeDataAndStartSyncing(
-      kDomDistillerModelType, SyncDataFromEntryMap(other_db_model),
-      std::move(owned_other_store),
-      base::WrapUnique<SyncErrorFactory>(other_error_factory));
-
-  EXPECT_TRUE(AreEntriesEqual(store_->GetEntries(), expected_model));
-  EXPECT_TRUE(AreEntriesEqual(other_store->GetEntries(), expected_model));
-}
-
 TEST_F(DomDistillerStoreTest, TestObserver) {
   CreateStore();
   MockDistillerObserver observer;
@@ -507,31 +327,6 @@
   EXPECT_CALL(observer, ArticleEntriesUpdated(
                             test::util::HasExpectedUpdates(expected_updates)));
   store_->RemoveEntry(GetSampleEntry(0));
-
-  // Add entry_id = 3 and update entry_id = 1.
-  expected_updates.clear();
-  SyncDataList change_data;
-  change_data.push_back(CreateSyncData(GetSampleEntry(3)));
-  ArticleEntry updated_entry(GetSampleEntry(1));
-  updated_entry.set_title("changed_title");
-  change_data.push_back(CreateSyncData(updated_entry));
-  update.entry_id = GetSampleEntry(3).entry_id();
-  update.update_type = DomDistillerObserver::ArticleUpdate::ADD;
-  expected_updates.push_back(update);
-  update.entry_id = GetSampleEntry(1).entry_id();
-  update.update_type = DomDistillerObserver::ArticleUpdate::UPDATE;
-  expected_updates.push_back(update);
-  EXPECT_CALL(observer, ArticleEntriesUpdated(
-                            test::util::HasExpectedUpdates(expected_updates)));
-
-  FakeSyncErrorFactory* fake_error_factory = new FakeSyncErrorFactory();
-  EntryMap fake_model;
-  FakeSyncChangeProcessor* fake_sync_change_processor =
-      new FakeSyncChangeProcessor(&fake_model);
-  store_->MergeDataAndStartSyncing(
-      kDomDistillerModelType, change_data,
-      base::WrapUnique<SyncChangeProcessor>(fake_sync_change_processor),
-      base::WrapUnique<SyncErrorFactory>(fake_error_factory));
 }
 
 }  // namespace dom_distiller
diff --git a/components/dom_distiller/core/dom_distiller_switches.cc b/components/dom_distiller/core/dom_distiller_switches.cc
index 0d3976b..42c47e4 100644
--- a/components/dom_distiller/core/dom_distiller_switches.cc
+++ b/components/dom_distiller/core/dom_distiller_switches.cc
@@ -8,7 +8,6 @@
 
 const char kEnableDistillabilityService[] = "enable-distillability-service";
 const char kEnableDomDistiller[] = "enable-dom-distiller";
-const char kEnableSyncArticles[] = "enable-sync-articles";
 const char kReaderModeHeuristics[] = "reader-mode-heuristics";
 const char kReaderModeFeedback[] = "reader-mode-feedback";
 
diff --git a/components/dom_distiller/core/dom_distiller_switches.h b/components/dom_distiller/core/dom_distiller_switches.h
index 688e4aef0..1ed7288d 100644
--- a/components/dom_distiller/core/dom_distiller_switches.h
+++ b/components/dom_distiller/core/dom_distiller_switches.h
@@ -15,9 +15,6 @@
 // Switch to enable the DOM distiller.
 extern const char kEnableDomDistiller[];
 
-// Switch to enable synced articles.
-extern const char kEnableSyncArticles[];
-
 // Switch to enable specific heuristics for detecting if a page is distillable
 // or not.
 extern const char kReaderModeHeuristics[];
diff --git a/components/dom_distiller/core/viewer_unittest.cc b/components/dom_distiller/core/viewer_unittest.cc
index e7bfd5a..5ae2ead 100644
--- a/components/dom_distiller/core/viewer_unittest.cc
+++ b/components/dom_distiller/core/viewer_unittest.cc
@@ -28,7 +28,6 @@
   TestDomDistillerService() {}
   ~TestDomDistillerService() override {}
 
-  MOCK_CONST_METHOD0(GetSyncableService, syncer::SyncableService*());
   MOCK_METHOD3(AddToList,
                const std::string(const GURL&,
                                  DistillerPage*,
diff --git a/components/download/public/common/in_progress_download_manager.h b/components/download/public/common/in_progress_download_manager.h
index aea1033..1b695711 100644
--- a/components/download/public/common/in_progress_download_manager.h
+++ b/components/download/public/common/in_progress_download_manager.h
@@ -147,6 +147,11 @@
 
   void set_delegate(Delegate* delegate) { delegate_ = delegate; }
 
+  void set_is_origin_secure_cb(
+      const IsOriginSecureCallback& is_origin_secure_cb) {
+    is_origin_secure_cb_ = is_origin_secure_cb;
+  }
+
  private:
   void Initialize(const base::FilePath& metadata_cache_dir);
 
diff --git a/components/infobars/core/infobar_delegate.h b/components/infobars/core/infobar_delegate.h
index dc9debd..98f4963 100644
--- a/components/infobars/core/infobar_delegate.h
+++ b/components/infobars/core/infobar_delegate.h
@@ -153,6 +153,7 @@
     DOWNLOAD_PROGRESS_INFOBAR_ANDROID = 82,
     AR_CORE_UPGRADE_ANDROID = 83,
     BLOATED_RENDERER_INFOBAR_DELEGATE = 84,
+    SUPERVISED_USERS_DEPRECATED_INFOBAR_DELEGATE = 85,
   };
 
   // Describes navigation events, used to decide whether infobars should be
diff --git a/components/password_manager/core/browser/password_list_sorter.cc b/components/password_manager/core/browser/password_list_sorter.cc
index be993ab..a1c029a 100644
--- a/components/password_manager/core/browser/password_list_sorter.cc
+++ b/components/password_manager/core/browser/password_list_sorter.cc
@@ -27,8 +27,7 @@
 
 }  // namespace
 
-std::string CreateSortKey(const autofill::PasswordForm& form,
-                          PasswordEntryType entry_type) {
+std::string CreateSortKey(const autofill::PasswordForm& form) {
   std::string shown_origin;
   GURL link_url;
   std::tie(shown_origin, link_url) = GetShownOriginAndLinkUrl(form);
@@ -61,7 +60,7 @@
   key += is_android_uri ? facet_uri.canonical_spec()
                         : SplitByDotAndReverse(shown_origin);
 
-  if (entry_type == PasswordEntryType::SAVED) {
+  if (!form.blacklisted_by_user) {
     key += kSortKeyPartsSeparator + base::UTF16ToUTF8(form.username_value) +
            kSortKeyPartsSeparator + base::UTF16ToUTF8(form.password_value);
 
@@ -78,13 +77,12 @@
 
 void SortEntriesAndHideDuplicates(
     std::vector<std::unique_ptr<autofill::PasswordForm>>* list,
-    DuplicatesMap* duplicates,
-    PasswordEntryType entry_type) {
+    DuplicatesMap* duplicates) {
   std::vector<std::pair<std::string, std::unique_ptr<autofill::PasswordForm>>>
       keys_to_forms;
   keys_to_forms.reserve(list->size());
   for (auto& form : *list) {
-    std::string key = CreateSortKey(*form, entry_type);
+    std::string key = CreateSortKey(*form);
     keys_to_forms.emplace_back(std::move(key), std::move(form));
   }
 
diff --git a/components/password_manager/core/browser/password_list_sorter.h b/components/password_manager/core/browser/password_list_sorter.h
index 4e89da8..4130d7b 100644
--- a/components/password_manager/core/browser/password_list_sorter.h
+++ b/components/password_manager/core/browser/password_list_sorter.h
@@ -16,8 +16,6 @@
 
 namespace password_manager {
 
-enum class PasswordEntryType { SAVED, BLACKLISTED };
-
 // Multimap from sort key to password forms.
 using DuplicatesMap =
     std::multimap<std::string, std::unique_ptr<autofill::PasswordForm>>;
@@ -25,21 +23,20 @@
 // Creates key for sorting password or password exception entries. The key is
 // eTLD+1 followed by the reversed list of domains (e.g.
 // secure.accounts.example.com => example.com.com.example.accounts.secure) and
-// the scheme. If |entry_type == SAVED|, username, password and federation are
-// appended to the key. For Android credentials the canocial spec is included.
-std::string CreateSortKey(const autofill::PasswordForm& form,
-                          PasswordEntryType entry_type);
+// the scheme. If |form| is not blacklisted, username, password and federation
+// are appended to the key. If not, no further information is added. For Android
+// credentials the canocial spec is included.
+std::string CreateSortKey(const autofill::PasswordForm& form);
 
 // Sort entries of |list| based on sort key. The key is the concatenation of
 // origin, entry type (non-Android credential, Android w/ affiliated web realm
-// or Android w/o affiliated web realm). If |entry_type == SAVED|,
-// username, password and federation are also included in sort key. If there
-// are several forms with the same key, all such forms but the first one are
-// stored in |duplicates| instead of |list|.
+// or Android w/o affiliated web realm). If a form in |list| is not blacklisted,
+// username, password and federation are also included in sort key. If there are
+// several forms with the same key, all such forms but the first one are stored
+// in |duplicates| instead of |list|.
 void SortEntriesAndHideDuplicates(
     std::vector<std::unique_ptr<autofill::PasswordForm>>* list,
-    DuplicatesMap* duplicates,
-    PasswordEntryType entry_type);
+    DuplicatesMap* duplicates);
 
 }  // namespace password_manager
 
diff --git a/components/password_manager/core/browser/password_list_sorter_unittest.cc b/components/password_manager/core/browser/password_list_sorter_unittest.cc
index d69ffb5..23c28b58 100644
--- a/components/password_manager/core/browser/password_list_sorter_unittest.cc
+++ b/components/password_manager/core/browser/password_list_sorter_unittest.cc
@@ -21,18 +21,19 @@
   const char* const password;
   const char* const app_display_name;
   const char* const federation;
+  const bool is_blacklisted;
   const int expected_position;
 };
 
-void SortAndCheckPositions(const std::vector<SortEntry>& test_entries,
-                           PasswordEntryType entry_type) {
+void SortAndCheckPositions(const std::vector<SortEntry>& test_entries) {
   std::vector<std::unique_ptr<autofill::PasswordForm>> list;
   size_t expected_number_of_unique_entries = 0;
   for (const SortEntry& entry : test_entries) {
     auto form = std::make_unique<autofill::PasswordForm>();
     form->signon_realm = entry.origin;
     form->origin = GURL(entry.origin);
-    if (entry_type == PasswordEntryType::SAVED) {
+    form->blacklisted_by_user = entry.is_blacklisted;
+    if (!entry.is_blacklisted) {
       form->username_value = base::ASCIIToUTF16(entry.username);
       form->password_value = base::ASCIIToUTF16(entry.password);
       if (entry.federation != nullptr)
@@ -46,8 +47,7 @@
   }
 
   DuplicatesMap duplicates;
-  password_manager::SortEntriesAndHideDuplicates(&list, &duplicates,
-                                                 entry_type);
+  password_manager::SortEntriesAndHideDuplicates(&list, &duplicates);
 
   ASSERT_EQ(expected_number_of_unique_entries, list.size());
   ASSERT_EQ(test_entries.size() - expected_number_of_unique_entries,
@@ -57,7 +57,7 @@
       SCOPED_TRACE(testing::Message("position in sorted list: ")
                    << entry.expected_position);
       EXPECT_EQ(GURL(entry.origin), list[entry.expected_position]->origin);
-      if (entry_type == PasswordEntryType::SAVED) {
+      if (!entry.is_blacklisted) {
         EXPECT_EQ(base::ASCIIToUTF16(entry.username),
                   list[entry.expected_position]->username_value);
         EXPECT_EQ(base::ASCIIToUTF16(entry.password),
@@ -74,115 +74,119 @@
 
 TEST(PasswordListSorterTest, Sorting_DifferentOrigins) {
   const std::vector<SortEntry> test_cases = {
-      {"http://example-b.com", "user_a", "pwd", nullptr, nullptr, 2},
-      {"http://example-a.com", "user_a1", "pwd", nullptr, nullptr, 0},
-      {"http://example-a.com", "user_a2", "pwd", nullptr, nullptr, 1},
-      {"http://example-c.com", "user_a", "pwd", nullptr, nullptr, 3}};
-  SortAndCheckPositions(test_cases, PasswordEntryType::SAVED);
+      {"http://example-b.com", "user_a", "pwd", nullptr, nullptr, false, 2},
+      {"http://example-a.com", "user_a1", "pwd", nullptr, nullptr, false, 0},
+      {"http://example-a.com", "user_a2", "pwd", nullptr, nullptr, false, 1},
+      {"http://example-c.com", "user_a", "pwd", nullptr, nullptr, false, 3}};
+  SortAndCheckPositions(test_cases);
 }
 
 TEST(PasswordListSorterTest, Sorting_DifferentUsernames) {
   const std::vector<SortEntry> test_cases = {
-      {"http://example.com", "user_a", "pwd", nullptr, nullptr, 0},
-      {"http://example.com", "user_c", "pwd", nullptr, nullptr, 2},
-      {"http://example.com", "user_b", "pwd", nullptr, nullptr, 1}};
-  SortAndCheckPositions(test_cases, PasswordEntryType::SAVED);
+      {"http://example.com", "user_a", "pwd", nullptr, nullptr, false, 0},
+      {"http://example.com", "user_c", "pwd", nullptr, nullptr, false, 2},
+      {"http://example.com", "user_b", "pwd", nullptr, nullptr, false, 1}};
+  SortAndCheckPositions(test_cases);
 }
 
 TEST(PasswordListSorterTest, Sorting_DifferentPasswords) {
   const std::vector<SortEntry> test_cases = {
-      {"http://example.com", "user_a", "1", nullptr, nullptr, 0},
-      {"http://example.com", "user_a", "2", nullptr, nullptr, 1},
-      {"http://example.com", "user_a", "3", nullptr, nullptr, 2}};
-  SortAndCheckPositions(test_cases, PasswordEntryType::SAVED);
+      {"http://example.com", "user_a", "1", nullptr, nullptr, false, 0},
+      {"http://example.com", "user_a", "2", nullptr, nullptr, false, 1},
+      {"http://example.com", "user_a", "3", nullptr, nullptr, false, 2}};
+  SortAndCheckPositions(test_cases);
 }
 
 TEST(PasswordListSorterTest, Sorting_DifferentSchemes) {
   const std::vector<SortEntry> test_cases = {
-      {"https://example.com", "user", "1", nullptr, nullptr, 1},
-      {"https://example.com", "user", "1", nullptr, nullptr, -1},  // Hide it.
-      {"http://example.com", "user", "1", nullptr, nullptr, 0}};
-  SortAndCheckPositions(test_cases, PasswordEntryType::SAVED);
+      {"https://example.com", "user", "1", nullptr, nullptr, false, 1},
+      {"https://example.com", "user", "1", nullptr, nullptr, false,
+       -1},  // Hide it.
+      {"http://example.com", "user", "1", nullptr, nullptr, false, 0}};
+  SortAndCheckPositions(test_cases);
 }
 
 TEST(PasswordListSorterTest, Sorting_HideDuplicates) {
   const std::vector<SortEntry> test_cases = {
-      {"http://example.com", "user_a", "pwd", nullptr, nullptr, 0},
+      {"http://example.com", "user_a", "pwd", nullptr, nullptr, false, 0},
       // Different username.
-      {"http://example.com", "user_b", "pwd", nullptr, nullptr, 2},
+      {"http://example.com", "user_b", "pwd", nullptr, nullptr, false, 2},
       // Different password.
-      {"http://example.com", "user_a", "secret", nullptr, nullptr, 1},
+      {"http://example.com", "user_a", "secret", nullptr, nullptr, false, 1},
       // Different origin.
-      {"http://sub1.example.com", "user_a", "pwd", nullptr, nullptr, 3},
-      {"http://example.com", "user_a", "pwd", nullptr, nullptr, -1}  // Hide it.
+      {"http://sub1.example.com", "user_a", "pwd", nullptr, nullptr, false, 3},
+      {"http://example.com", "user_a", "pwd", nullptr, nullptr, false,
+       -1}  // Hide it.
   };
-  SortAndCheckPositions(test_cases, PasswordEntryType::SAVED);
+  SortAndCheckPositions(test_cases);
 }
 
 TEST(PasswordListSorterTest, Sorting_Subdomains) {
   const std::vector<SortEntry> test_cases = {
-      {"http://example.com", "u", "p", nullptr, nullptr, 0},
-      {"http://b.example.com", "u", "p", nullptr, nullptr, 6},
-      {"http://a.example.com", "u", "p", nullptr, nullptr, 1},
-      {"http://1.a.example.com", "u", "p", nullptr, nullptr, 2},
-      {"http://2.a.example.com", "u", "p", nullptr, nullptr, 3},
-      {"http://x.2.a.example.com", "u", "p", nullptr, nullptr, 4},
-      {"http://y.2.a.example.com", "u", "p", nullptr, nullptr, 5},
+      {"http://example.com", "u", "p", nullptr, nullptr, false, 0},
+      {"http://b.example.com", "u", "p", nullptr, nullptr, false, 6},
+      {"http://a.example.com", "u", "p", nullptr, nullptr, false, 1},
+      {"http://1.a.example.com", "u", "p", nullptr, nullptr, false, 2},
+      {"http://2.a.example.com", "u", "p", nullptr, nullptr, false, 3},
+      {"http://x.2.a.example.com", "u", "p", nullptr, nullptr, false, 4},
+      {"http://y.2.a.example.com", "u", "p", nullptr, nullptr, false, 5},
   };
-  SortAndCheckPositions(test_cases, PasswordEntryType::SAVED);
+  SortAndCheckPositions(test_cases);
 }
 
 TEST(PasswordListSorterTest, Sorting_PasswordExceptions) {
   const std::vector<SortEntry> test_cases = {
-      {"http://example-b.com", nullptr, nullptr, nullptr, nullptr, 1},
-      {"http://example-a.com", nullptr, nullptr, nullptr, nullptr, 0},
-      {"http://example-a.com", nullptr, nullptr, nullptr, nullptr,
+      {"http://example-b.com", nullptr, nullptr, nullptr, nullptr, true, 1},
+      {"http://example-a.com", nullptr, nullptr, nullptr, nullptr, true, 0},
+      {"http://example-a.com", nullptr, nullptr, nullptr, nullptr, true,
        -1},  // Hide it.
-      {"http://example-c.com", nullptr, nullptr, nullptr, nullptr, 2}};
-  SortAndCheckPositions(test_cases, PasswordEntryType::BLACKLISTED);
+      {"http://example-c.com", nullptr, nullptr, nullptr, nullptr, true, 2}};
+  SortAndCheckPositions(test_cases);
 }
 
 TEST(PasswordListSorterTest, Sorting_AndroidCredentials) {
   const std::vector<SortEntry> test_cases = {
       // Regular Web Credential.
-      {"https://alpha.example.com", "user", "secret", nullptr, nullptr, 3},
+      {"https://alpha.example.com", "user", "secret", nullptr, nullptr, false,
+       3},
       // First Android Credential.
       {"android://hash@com.example.alpha", "user", "secret", nullptr, nullptr,
-       0},
+       false, 0},
       // App display name is irrelevant, this should be hidden as a duplicate
       // of the first one.
       {"android://hash@com.example.alpha", "user", "secret", "Example App",
-       nullptr, -1},
+       nullptr, false, -1},
       // Apps with different package names are distinct.
       {"android://hash@com.example.beta", "user", "secret", nullptr, nullptr,
-       1},
+       false, 1},
       // Apps with same package name but different hashes are distinct.
       {"android://hash_different@com.example.alpha", "user", "secret", nullptr,
-       nullptr, 2}};
-  SortAndCheckPositions(test_cases, PasswordEntryType::SAVED);
+       nullptr, false, 2}};
+  SortAndCheckPositions(test_cases);
 }
 
 TEST(PasswordListSorterTest, Sorting_Federations) {
   const std::vector<SortEntry> test_cases = {
-      {"https://example.com", "user", "secret", nullptr, nullptr, 0},
-      {"https://example.com", "user", "secret", nullptr, "https://fed1.com", 1},
+      {"https://example.com", "user", "secret", nullptr, nullptr, false, 0},
+      {"https://example.com", "user", "secret", nullptr, "https://fed1.com",
+       false, 1},
       {"https://example.com", "user", "secret", nullptr, "https://fed2.com",
-       2}};
-  SortAndCheckPositions(test_cases, PasswordEntryType::SAVED);
+       false, 2}};
+  SortAndCheckPositions(test_cases);
 }
 
 TEST(PasswordListSorterTest, Sorting_SpecialCharacters) {
   // URLs with encoded special characters should not cause crash during sorting.
   const std::vector<SortEntry> test_cases = {
-      {"https://xn--bea5m6d.com/", "user_a", "pwd", nullptr, nullptr, 4},
-      {"https://uoy.com/", "user_a", "pwd", nullptr, nullptr, 1},
-      {"https://zrc.com/", "user_a", "pwd", nullptr, nullptr, 6},
-      {"https://abc.com/", "user_a", "pwd", nullptr, nullptr, 0},
-      {"https://xn--ab-fma.com/", "user_a", "pwd", nullptr, nullptr, 2},
-      {"https://xn--bc-lia.com/", "user_a", "pwd", nullptr, nullptr, 3},
-      {"https://xn--ndalk.com/", "user_a", "pwd", nullptr, nullptr, 5},
+      {"https://xn--bea5m6d.com/", "user_a", "pwd", nullptr, nullptr, false, 4},
+      {"https://uoy.com/", "user_a", "pwd", nullptr, nullptr, false, 1},
+      {"https://zrc.com/", "user_a", "pwd", nullptr, nullptr, false, 6},
+      {"https://abc.com/", "user_a", "pwd", nullptr, nullptr, false, 0},
+      {"https://xn--ab-fma.com/", "user_a", "pwd", nullptr, nullptr, false, 2},
+      {"https://xn--bc-lia.com/", "user_a", "pwd", nullptr, nullptr, false, 3},
+      {"https://xn--ndalk.com/", "user_a", "pwd", nullptr, nullptr, false, 5},
   };
-  SortAndCheckPositions(test_cases, PasswordEntryType::SAVED);
+  SortAndCheckPositions(test_cases);
 }
 
 }  // namespace password_manager
diff --git a/components/printing/browser/print_manager_utils.cc b/components/printing/browser/print_manager_utils.cc
index 0bd4f44..4721f188 100644
--- a/components/printing/browser/print_manager_utils.cc
+++ b/components/printing/browser/print_manager_utils.cc
@@ -66,8 +66,9 @@
   params->display_header_footer = settings.display_header_footer();
   params->title = settings.title();
   params->url = settings.url();
-  params->printed_doc_type =
-      IsOopifEnabled() ? SkiaDocumentType::MSKP : SkiaDocumentType::PDF;
+  params->printed_doc_type = IsOopifEnabled() && settings.is_modifiable()
+                                 ? SkiaDocumentType::MSKP
+                                 : SkiaDocumentType::PDF;
   params->pages_per_sheet = settings.pages_per_sheet();
 }
 
diff --git a/components/signin/core/browser/chrome_connected_header_helper.cc b/components/signin/core/browser/chrome_connected_header_helper.cc
index 4c5173b..3a39e08 100644
--- a/components/signin/core/browser/chrome_connected_header_helper.cc
+++ b/components/signin/core/browser/chrome_connected_header_helper.cc
@@ -51,7 +51,7 @@
 
 ChromeConnectedHeaderHelper::ChromeConnectedHeaderHelper(
     AccountConsistencyMethod account_consistency)
-    : account_consistency_(account_consistency) {}
+    : SigninHeaderHelper("Mirror"), account_consistency_(account_consistency) {}
 
 // static
 std::string ChromeConnectedHeaderHelper::BuildRequestCookieIfPossible(
diff --git a/components/signin/core/browser/dice_header_helper.cc b/components/signin/core/browser/dice_header_helper.cc
index b6746b31..fb51916 100644
--- a/components/signin/core/browser/dice_header_helper.cc
+++ b/components/signin/core/browser/dice_header_helper.cc
@@ -52,7 +52,8 @@
 
 DiceHeaderHelper::DiceHeaderHelper(bool signed_in_with_auth_error,
                                    AccountConsistencyMethod account_consistency)
-    : signed_in_with_auth_error_(signed_in_with_auth_error),
+    : SigninHeaderHelper("Dice"),
+      signed_in_with_auth_error_(signed_in_with_auth_error),
       account_consistency_(account_consistency) {}
 
 // static
diff --git a/components/signin/core/browser/signin_header_helper.cc b/components/signin/core/browser/signin_header_helper.cc
index 196dc5a..4a0cc964 100644
--- a/components/signin/core/browser/signin_header_helper.cc
+++ b/components/signin/core/browser/signin_header_helper.cc
@@ -8,6 +8,7 @@
 
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/strings/string_split.h"
 #include "components/google/core/browser/google_util.h"
 #include "components/signin/core/browser/chrome_connected_header_helper.h"
@@ -21,6 +22,16 @@
 
 namespace signin {
 
+namespace {
+// Buckes of the |Signin.RequestHeaderOperation.Dice| and
+// |SigninRequestHeaderOperation.Mirror| histograms.
+enum class RequestHeaderOperation {
+  kHeaderAdded = 0,
+  kHeaderRemoved = 1,
+  kMaxValue = kHeaderRemoved
+};
+}  // namespace
+
 const char kChromeConnectedHeader[] = "X-Chrome-Connected";
 const char kDiceRequestHeader[] = "X-Chrome-ID-Consistency-Request";
 const char kDiceResponseHeader[] = "X-Chrome-ID-Consistency-Response";
@@ -95,6 +106,10 @@
       url, account_id, account_consistency, cookie_settings, profile_mode_mask);
 }
 
+SigninHeaderHelper::SigninHeaderHelper(const std::string& histogram_suffix)
+    : histogram_suffix_(histogram_suffix){};
+SigninHeaderHelper::~SigninHeaderHelper() = default;
+
 bool SigninHeaderHelper::AppendOrRemoveRequestHeader(
     RequestAdapter* request,
     const GURL& redirect_url,
@@ -107,10 +122,16 @@
     if (!redirect_url.is_empty() && request->HasHeader(header_name) &&
         IsUrlEligibleForRequestHeader(request->GetUrl()) &&
         !IsUrlEligibleForRequestHeader(redirect_url)) {
+      base::UmaHistogramEnumeration(
+          GetSuffixedHistogramName("Signin.RequestHeaderOperation"),
+          RequestHeaderOperation::kHeaderRemoved);
       request->RemoveRequestHeaderByName(header_name);
     }
     return false;
   }
+  base::UmaHistogramEnumeration(
+      GetSuffixedHistogramName("Signin.RequestHeaderOperation"),
+      RequestHeaderOperation::kHeaderAdded);
   request->SetExtraHeaderByName(header_name, header_value);
   return true;
 }
@@ -138,6 +159,11 @@
   return dictionary;
 }
 
+std::string SigninHeaderHelper::GetSuffixedHistogramName(
+    const std::string& histogram_name) {
+  return histogram_name + "." + histogram_suffix_;
+}
+
 void AppendOrRemoveMirrorRequestHeader(
     RequestAdapter* request,
     const GURL& redirect_url,
diff --git a/components/signin/core/browser/signin_header_helper.h b/components/signin/core/browser/signin_header_helper.h
index 18c3a32..1eea262 100644
--- a/components/signin/core/browser/signin_header_helper.h
+++ b/components/signin/core/browser/signin_header_helper.h
@@ -180,8 +180,8 @@
       const content_settings::CookieSettings* cookie_settings) = 0;
 
  protected:
-  SigninHeaderHelper() {}
-  virtual ~SigninHeaderHelper() {}
+  explicit SigninHeaderHelper(const std::string& histogram_suffix);
+  virtual ~SigninHeaderHelper();
 
   // Dictionary of fields in a account consistency response header.
   using ResponseHeaderDictionary = std::multimap<std::string, std::string>;
@@ -194,6 +194,15 @@
  private:
   // Returns whether the url is eligible for the request header.
   virtual bool IsUrlEligibleForRequestHeader(const GURL& url) = 0;
+
+  // Returns a string that can be used as a histogram name. Its value ios
+  // "|histogram_name|.|histogram_suffix_|".
+  std::string GetSuffixedHistogramName(const std::string& histogram_name);
+
+  // Suffix to be used by the histograms recodered by this SigninHeaderHelper.
+  std::string histogram_suffix_;
+
+  DISALLOW_COPY_AND_ASSIGN(SigninHeaderHelper);
 };
 
 
diff --git a/components/suggestions/suggestions_service_impl_unittest.cc b/components/suggestions/suggestions_service_impl_unittest.cc
index a89a3ff..59a105d 100644
--- a/components/suggestions/suggestions_service_impl_unittest.cc
+++ b/components/suggestions/suggestions_service_impl_unittest.cc
@@ -86,9 +86,7 @@
   MockSyncService() {}
   ~MockSyncService() override {}
   MOCK_CONST_METHOD0(GetDisableReasons, int());
-  MOCK_CONST_METHOD0(IsEngineInitialized, bool());
-  MOCK_CONST_METHOD0(IsFirstSetupComplete, bool());
-  MOCK_CONST_METHOD0(ConfigurationDone, bool());
+  MOCK_CONST_METHOD0(GetState, State());
   MOCK_CONST_METHOD0(IsLocalSyncEnabled, bool());
   MOCK_CONST_METHOD0(IsUsingSecondaryPassphrase, bool());
   MOCK_CONST_METHOD0(GetPreferredDataTypes, syncer::ModelTypeSet());
@@ -157,15 +155,9 @@
     EXPECT_CALL(*sync_service(), GetDisableReasons())
         .Times(AnyNumber())
         .WillRepeatedly(Return(syncer::SyncService::DISABLE_REASON_NONE));
-    EXPECT_CALL(*sync_service(), IsEngineInitialized())
+    EXPECT_CALL(*sync_service(), GetState())
         .Times(AnyNumber())
-        .WillRepeatedly(Return(true));
-    EXPECT_CALL(*sync_service(), IsFirstSetupComplete())
-        .Times(AnyNumber())
-        .WillRepeatedly(Return(true));
-    EXPECT_CALL(*sync_service(), ConfigurationDone())
-        .Times(AnyNumber())
-        .WillRepeatedly(Return(true));
+        .WillRepeatedly(Return(syncer::SyncService::State::ACTIVE));
     EXPECT_CALL(*sync_service(), IsLocalSyncEnabled())
         .Times(AnyNumber())
         .WillRepeatedly(Return(false));
@@ -348,8 +340,8 @@
 // This should *not* result in an automatic fetch.
 TEST_F(SuggestionsServiceTest, DoesNotFetchOnStartup) {
   // The sync service starts out inactive.
-  EXPECT_CALL(*sync_service(), IsEngineInitialized())
-      .WillRepeatedly(Return(false));
+  EXPECT_CALL(*sync_service(), GetState())
+      .WillRepeatedly(Return(syncer::SyncService::State::INITIALIZING));
   static_cast<SyncServiceObserver*>(suggestions_service())
       ->OnStateChanged(sync_service());
 
@@ -357,8 +349,8 @@
   ASSERT_FALSE(suggestions_service()->HasPendingRequestForTesting());
 
   // Sync getting enabled should not result in a fetch.
-  EXPECT_CALL(*sync_service(), IsEngineInitialized())
-      .WillRepeatedly(Return(true));
+  EXPECT_CALL(*sync_service(), GetState())
+      .WillRepeatedly(Return(syncer::SyncService::State::ACTIVE));
   static_cast<SyncServiceObserver*>(suggestions_service())
       ->OnStateChanged(sync_service());
 
@@ -391,8 +383,8 @@
 }
 
 TEST_F(SuggestionsServiceTest, FetchSuggestionsDataSyncNotInitializedEnabled) {
-  EXPECT_CALL(*sync_service(), IsEngineInitialized())
-      .WillRepeatedly(Return(false));
+  EXPECT_CALL(*sync_service(), GetState())
+      .WillRepeatedly(Return(syncer::SyncService::State::INITIALIZING));
   static_cast<SyncServiceObserver*>(suggestions_service())
       ->OnStateChanged(sync_service());
 
@@ -418,6 +410,8 @@
   EXPECT_CALL(*sync_service(), GetDisableReasons())
       .Times(AnyNumber())
       .WillRepeatedly(Return(syncer::SyncService::DISABLE_REASON_USER_CHOICE));
+  EXPECT_CALL(*sync_service(), GetState())
+      .WillRepeatedly(Return(syncer::SyncService::State::DISABLED));
 
   base::MockCallback<SuggestionsService::ResponseCallback> callback;
   auto subscription = suggestions_service()->AddCallback(callback.Get());
diff --git a/components/sync/base/data_type_histogram.h b/components/sync/base/data_type_histogram.h
index 170e3c84..e59031c 100644
--- a/components/sync/base/data_type_histogram.h
+++ b/components/sync/base/data_type_histogram.h
@@ -122,7 +122,7 @@
       case ::syncer::DEPRECATED_SUPERVISED_USER_SHARED_SETTINGS: \
         PER_DATA_TYPE_MACRO("ManagedUserSharedSetting");         \
         break;                                                   \
-      case ::syncer::ARTICLES:                                   \
+      case ::syncer::DEPRECATED_ARTICLES:                        \
         PER_DATA_TYPE_MACRO("Article");                          \
         break;                                                   \
       case ::syncer::APP_LIST:                                   \
diff --git a/components/sync/base/model_type.h b/components/sync/base/model_type.h
index 1865763..7903bba9 100644
--- a/components/sync/base/model_type.h
+++ b/components/sync/base/model_type.h
@@ -114,7 +114,7 @@
   DEPRECATED_SUPERVISED_USERS,
   DEPRECATED_SUPERVISED_USER_SHARED_SETTINGS,
   // Distilled articles.
-  ARTICLES,
+  DEPRECATED_ARTICLES,
   // App List items
   APP_LIST,
   // WiFi credentials. Each item contains the information for connecting to one
@@ -202,18 +202,18 @@
 // representations. This distinguishes them from Proxy types, which have no
 // protocol representation and are never sent to the server.
 constexpr ModelTypeSet ProtocolTypes() {
-  return ModelTypeSet(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,
-                      SUPERVISED_USER_SETTINGS, DEPRECATED_SUPERVISED_USERS,
-                      DEPRECATED_SUPERVISED_USER_SHARED_SETTINGS, ARTICLES,
-                      APP_LIST, WIFI_CREDENTIALS, SUPERVISED_USER_WHITELISTS,
-                      ARC_PACKAGE, PRINTERS, READING_LIST, USER_EVENTS, NIGORI,
-                      EXPERIMENTS, MOUNTAIN_SHARES, USER_CONSENTS);
+  return ModelTypeSet(
+      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,
+      SUPERVISED_USER_SETTINGS, DEPRECATED_SUPERVISED_USERS,
+      DEPRECATED_SUPERVISED_USER_SHARED_SETTINGS, DEPRECATED_ARTICLES, APP_LIST,
+      WIFI_CREDENTIALS, SUPERVISED_USER_WHITELISTS, ARC_PACKAGE, PRINTERS,
+      READING_LIST, USER_EVENTS, NIGORI, EXPERIMENTS, MOUNTAIN_SHARES,
+      USER_CONSENTS);
 }
 
 // These are the normal user-controlled types. This is to distinguish from
diff --git a/components/sync/base/sync_prefs.cc b/components/sync/base/sync_prefs.cc
index f9455ee..cb39560 100644
--- a/components/sync/base/sync_prefs.cc
+++ b/components/sync/base/sync_prefs.cc
@@ -393,7 +393,7 @@
       return prefs::kSyncSupervisedUsers;
     case DEPRECATED_SUPERVISED_USER_SHARED_SETTINGS:
       return prefs::kSyncSupervisedUserSharedSettings;
-    case ARTICLES:
+    case DEPRECATED_ARTICLES:
       return prefs::kSyncArticles;
     case APP_LIST:
       return prefs::kSyncAppList;
diff --git a/components/sync/driver/fake_sync_service.cc b/components/sync/driver/fake_sync_service.cc
index a595a8c..a23790f 100644
--- a/components/sync/driver/fake_sync_service.cc
+++ b/components/sync/driver/fake_sync_service.cc
@@ -49,11 +49,6 @@
   }
   // From this point on, Sync can start in principle.
   DCHECK(CanSyncStart());
-  // Note: We don't distinguish here if the engine doesn't exist at all, or
-  // exists but hasn't finished initializing.
-  if (!IsEngineInitialized()) {
-    return State::INITIALIZING;
-  }
   if (!IsFirstSetupComplete()) {
     return State::PENDING_DESIRED_CONFIGURATION;
   }
@@ -117,10 +112,6 @@
   return error_;
 }
 
-bool FakeSyncService::IsEngineInitialized() const {
-  return false;
-}
-
 sync_sessions::OpenTabsUIDelegate* FakeSyncService::GetOpenTabsUIDelegate() {
   return nullptr;
 }
diff --git a/components/sync/driver/fake_sync_service.h b/components/sync/driver/fake_sync_service.h
index 2f21e64..80ef4e7 100644
--- a/components/sync/driver/fake_sync_service.h
+++ b/components/sync/driver/fake_sync_service.h
@@ -60,7 +60,6 @@
       override;
   bool IsSetupInProgress() const override;
   const GoogleServiceAuthError& GetAuthError() const override;
-  bool IsEngineInitialized() const override;
   sync_sessions::OpenTabsUIDelegate* GetOpenTabsUIDelegate() override;
   bool IsPassphraseRequiredForDecryption() const override;
   base::Time GetExplicitPassphraseTime() const override;
diff --git a/components/sync/driver/model_association_manager.cc b/components/sync/driver/model_association_manager.cc
index 35628bb..77b26047 100644
--- a/components/sync/driver/model_association_manager.cc
+++ b/components/sync/driver/model_association_manager.cc
@@ -40,9 +40,9 @@
     ARC_PACKAGE, READING_LIST, THEMES, SEARCH_ENGINES, SESSIONS,
     APP_NOTIFICATIONS, DICTIONARY, FAVICON_IMAGES, FAVICON_TRACKING, PRINTERS,
     USER_CONSENTS, USER_EVENTS, SUPERVISED_USER_SETTINGS,
-    SUPERVISED_USER_WHITELISTS, ARTICLES, WIFI_CREDENTIALS,
-    DEPRECATED_SUPERVISED_USERS, MOUNTAIN_SHARES,
-    DEPRECATED_SUPERVISED_USER_SHARED_SETTINGS};
+    SUPERVISED_USER_WHITELISTS, WIFI_CREDENTIALS, DEPRECATED_SUPERVISED_USERS,
+    MOUNTAIN_SHARES, DEPRECATED_SUPERVISED_USER_SHARED_SETTINGS,
+    DEPRECATED_ARTICLES};
 
 static_assert(arraysize(kStartOrder) ==
                   MODEL_TYPE_COUNT - FIRST_REAL_MODEL_TYPE,
diff --git a/components/sync/driver/sync_service.cc b/components/sync/driver/sync_service.cc
index 5272ae7..2ec82a3 100644
--- a/components/sync/driver/sync_service.cc
+++ b/components/sync/driver/sync_service.cc
@@ -22,9 +22,36 @@
          !HasDisableReason(DISABLE_REASON_ENTERPRISE_POLICY);
 }
 
+bool SyncService::IsEngineInitialized() const {
+  switch (GetState()) {
+    case State::DISABLED:
+    case State::WAITING_FOR_START_REQUEST:
+    case State::START_DEFERRED:
+    case State::INITIALIZING:
+      return false;
+    case State::PENDING_DESIRED_CONFIGURATION:
+    case State::CONFIGURING:
+    case State::ACTIVE:
+      return true;
+  }
+  NOTREACHED();
+  return false;
+}
+
 bool SyncService::IsSyncActive() const {
-  State state = GetState();
-  return state == State::CONFIGURING || state == State::ACTIVE;
+  switch (GetState()) {
+    case State::DISABLED:
+    case State::WAITING_FOR_START_REQUEST:
+    case State::START_DEFERRED:
+    case State::INITIALIZING:
+    case State::PENDING_DESIRED_CONFIGURATION:
+      return false;
+    case State::CONFIGURING:
+    case State::ACTIVE:
+      return true;
+  }
+  NOTREACHED();
+  return false;
 }
 
 bool SyncService::IsFirstSetupInProgress() const {
diff --git a/components/sync/driver/sync_service.h b/components/sync/driver/sync_service.h
index bb5eac1..43be67c 100644
--- a/components/sync/driver/sync_service.h
+++ b/components/sync/driver/sync_service.h
@@ -265,9 +265,10 @@
   // Equivalent to "HasDisableReason(DISABLE_REASON_UNRECOVERABLE_ERROR)".
   bool HasUnrecoverableError() const;
 
-  // Returns true if the SyncEngine has told us it's ready to accept changes.
-  // DEPRECATED! Use GetState instead.
-  virtual bool IsEngineInitialized() const = 0;
+  // DEPRECATED! Use GetState instead. Equivalent to
+  // "GetState() == State::PENDING_DESIRED_CONFIGURATION ||
+  // GetState() == State::CONFIGURING || GetState() == State::ACTIVE".
+  bool IsEngineInitialized() const;
 
   // Return the active OpenTabsUIDelegate. If open/proxy tabs is not enabled or
   // not currently syncing, returns nullptr.
diff --git a/components/sync/driver/sync_service_utils_unittest.cc b/components/sync/driver/sync_service_utils_unittest.cc
index aa29e80..ec7cab8 100644
--- a/components/sync/driver/sync_service_utils_unittest.cc
+++ b/components/sync/driver/sync_service_utils_unittest.cc
@@ -14,15 +14,13 @@
 
 class TestSyncService : public FakeSyncService {
  public:
-  TestSyncService() { SetConfigurationDone(false); }
+  TestSyncService() = default;
   ~TestSyncService() override = default;
 
   void SetDisableReasons(int disable_reasons) {
     disable_reasons_ = disable_reasons;
   }
-  void SetEngineInitialized(bool initialized) {
-    engine_initialized_ = initialized;
-  }
+  void SetState(State state) { state_ = state; }
   void SetLocalSyncEnabled(bool local) { local_sync_enabled_ = local; }
   void SetPreferredDataTypes(const ModelTypeSet& types) {
     preferred_data_types_ = types;
@@ -37,7 +35,7 @@
 
   // SyncService implementation.
   int GetDisableReasons() const override { return disable_reasons_; }
-  bool IsEngineInitialized() const override { return engine_initialized_; }
+  State GetState() const override { return state_; }
   bool IsLocalSyncEnabled() const override { return local_sync_enabled_; }
   bool IsFirstSetupComplete() const override { return true; }
   ModelTypeSet GetPreferredDataTypes() const override {
@@ -78,7 +76,7 @@
 
  private:
   int disable_reasons_ = DISABLE_REASON_PLATFORM_OVERRIDE;
-  bool engine_initialized_ = false;
+  State state_ = State::DISABLED;
   bool sync_cycle_complete_ = false;
   bool local_sync_enabled_ = false;
   ModelTypeSet preferred_data_types_;
@@ -89,12 +87,11 @@
 TEST(SyncServiceUtilsTest, UploadToGoogleDisabledIfSyncNotAllowed) {
   TestSyncService service;
 
-  // If sync is not allowed, uploading should never be enabled, even if
-  // configuration is done and all the data types are enabled.
+  // If sync is not allowed, uploading should never be enabled, even if all the
+  // data types are enabled.
   service.SetDisableReasons(
       syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY);
 
-  service.SetConfigurationDone(true);
   service.SetPreferredDataTypes(ProtocolTypes());
   service.SetActiveDataTypes(ProtocolTypes());
 
@@ -104,6 +101,7 @@
   // Once sync gets allowed (e.g. policy is updated), uploading should not be
   // disabled anymore (though not necessarily active yet).
   service.SetDisableReasons(syncer::SyncService::DISABLE_REASON_NONE);
+  service.SetState(syncer::SyncService::State::WAITING_FOR_START_REQUEST);
 
   EXPECT_NE(UploadState::NOT_ACTIVE,
             GetUploadToGoogleState(&service, syncer::BOOKMARKS));
@@ -113,6 +111,7 @@
      UploadToGoogleInitializingUntilConfiguredAndActiveAndSyncCycleComplete) {
   TestSyncService service;
   service.SetDisableReasons(syncer::SyncService::DISABLE_REASON_NONE);
+  service.SetState(syncer::SyncService::State::WAITING_FOR_START_REQUEST);
   service.SetPreferredDataTypes(ProtocolTypes());
   service.SetActiveDataTypes(ProtocolTypes());
 
@@ -121,15 +120,11 @@
             GetUploadToGoogleState(&service, syncer::BOOKMARKS));
 
   // Finished configuration is not enough, still INITIALIZING.
-  service.SetConfigurationDone(true);
+  service.SetState(syncer::SyncService::State::ACTIVE);
   EXPECT_EQ(UploadState::INITIALIZING,
             GetUploadToGoogleState(&service, syncer::BOOKMARKS));
 
-  service.SetEngineInitialized(true);
-  EXPECT_EQ(UploadState::INITIALIZING,
-            GetUploadToGoogleState(&service, syncer::BOOKMARKS));
-
-  // Only after sync is both configured and active is upload actually ACTIVE.
+  // Only after a sync cycle has been completed is upload actually ACTIVE.
   service.SetSyncCycleComplete(true);
   EXPECT_EQ(UploadState::ACTIVE,
             GetUploadToGoogleState(&service, syncer::BOOKMARKS));
@@ -138,8 +133,7 @@
 TEST(SyncServiceUtilsTest, UploadToGoogleDisabledForModelType) {
   TestSyncService service;
   service.SetDisableReasons(syncer::SyncService::DISABLE_REASON_NONE);
-  service.SetConfigurationDone(true);
-  service.SetEngineInitialized(true);
+  service.SetState(syncer::SyncService::State::ACTIVE);
   service.SetSyncCycleComplete(true);
 
   // Sync is enabled only for a specific model type.
@@ -162,8 +156,7 @@
      UploadToGoogleDisabledForModelTypeThatFailedToStart) {
   TestSyncService service;
   service.SetDisableReasons(syncer::SyncService::DISABLE_REASON_NONE);
-  service.SetConfigurationDone(true);
-  service.SetEngineInitialized(true);
+  service.SetState(syncer::SyncService::State::ACTIVE);
   service.SetSyncCycleComplete(true);
 
   // Sync is enabled for some model types.
@@ -186,8 +179,7 @@
   service.SetDisableReasons(syncer::SyncService::DISABLE_REASON_NONE);
   service.SetPreferredDataTypes(ProtocolTypes());
   service.SetActiveDataTypes(ProtocolTypes());
-  service.SetEngineInitialized(true);
-  service.SetConfigurationDone(true);
+  service.SetState(syncer::SyncService::State::ACTIVE);
   service.SetSyncCycleComplete(true);
 
   // Sanity check: Upload is active now.
@@ -207,8 +199,7 @@
   service.SetDisableReasons(syncer::SyncService::DISABLE_REASON_NONE);
   service.SetPreferredDataTypes(ProtocolTypes());
   service.SetActiveDataTypes(ProtocolTypes());
-  service.SetEngineInitialized(true);
-  service.SetConfigurationDone(true);
+  service.SetState(syncer::SyncService::State::ACTIVE);
   service.SetSyncCycleComplete(true);
 
   // Sanity check: Upload is active now.
@@ -237,6 +228,7 @@
   // Once the auth error is resolved (e.g. user re-authenticated), uploading is
   // active again.
   service.set_auth_error(GoogleServiceAuthError(GoogleServiceAuthError::NONE));
+  service.SetState(syncer::SyncService::State::ACTIVE);
 
   EXPECT_EQ(UploadState::ACTIVE,
             GetUploadToGoogleState(&service, syncer::BOOKMARKS));
@@ -247,8 +239,7 @@
   service.SetDisableReasons(syncer::SyncService::DISABLE_REASON_NONE);
   service.SetPreferredDataTypes(ProtocolTypes());
   service.SetActiveDataTypes(ProtocolTypes());
-  service.SetEngineInitialized(true);
-  service.SetConfigurationDone(true);
+  service.SetState(syncer::SyncService::State::ACTIVE);
   service.SetSyncCycleComplete(true);
 
   // Sanity check: Upload is ACTIVE, even for data types that are always
diff --git a/components/sync/engine_impl/directory_commit_contribution_unittest.cc b/components/sync/engine_impl/directory_commit_contribution_unittest.cc
index 406ee2b..b2645dc0 100644
--- a/components/sync/engine_impl/directory_commit_contribution_unittest.cc
+++ b/components/sync/engine_impl/directory_commit_contribution_unittest.cc
@@ -29,7 +29,6 @@
     syncable::WriteTransaction trans(FROM_HERE, syncable::UNITTEST, dir());
     CreateTypeRoot(&trans, dir(), PREFERENCES);
     CreateTypeRoot(&trans, dir(), EXTENSIONS);
-    CreateTypeRoot(&trans, dir(), ARTICLES);
     CreateTypeRoot(&trans, dir(), BOOKMARKS);
   }
 
diff --git a/components/sync/engine_impl/directory_update_handler_unittest.cc b/components/sync/engine_impl/directory_update_handler_unittest.cc
index 684e568a..363a630 100644
--- a/components/sync/engine_impl/directory_update_handler_unittest.cc
+++ b/components/sync/engine_impl/directory_update_handler_unittest.cc
@@ -542,7 +542,7 @@
         passive_worker_(new FakeModelWorker(GROUP_PASSIVE)),
         bookmarks_emitter_(BOOKMARKS, &type_observers_),
         passwords_emitter_(PASSWORDS, &type_observers_),
-        articles_emitter_(ARTICLES, &type_observers_) {}
+        articles_emitter_(DEPRECATED_ARTICLES, &type_observers_) {}
 
   void SetUp() override {
     dir_maker_.SetUp();
@@ -556,9 +556,6 @@
         PASSWORDS,
         std::make_unique<DirectoryUpdateHandler>(
             directory(), PASSWORDS, password_worker_, &passwords_emitter_)));
-    update_handler_map_.insert(std::make_pair(
-        ARTICLES, std::make_unique<DirectoryUpdateHandler>(
-                      directory(), ARTICLES, ui_worker_, &articles_emitter_)));
   }
 
   void TearDown() override { dir_maker_.TearDown(); }
@@ -584,10 +581,6 @@
     update_handler_map_.find(PASSWORDS)->second->ApplyUpdates(status);
   }
 
-  void ApplyArticlesUpdates(StatusController* status) {
-    update_handler_map_.find(ARTICLES)->second->ApplyUpdates(status);
-  }
-
   TestEntryFactory* entry_factory() { return entry_factory_.get(); }
 
   syncable::Directory* directory() { return dir_maker_.directory(); }
diff --git a/components/sync/engine_impl/sync_manager_impl_unittest.cc b/components/sync/engine_impl/sync_manager_impl_unittest.cc
index 8001939..46b80a2f63 100644
--- a/components/sync/engine_impl/sync_manager_impl_unittest.cc
+++ b/components/sync/engine_impl/sync_manager_impl_unittest.cc
@@ -1009,7 +1009,6 @@
     enabled_types.Put(PASSWORDS);
     enabled_types.Put(PREFERENCES);
     enabled_types.Put(PRIORITY_PREFERENCES);
-    enabled_types.Put(ARTICLES);
 
     return enabled_types;
   }
diff --git a/components/sync/syncable/model_type.cc b/components/sync/syncable/model_type.cc
index 0da7c30..b3b23a6 100644
--- a/components/sync/syncable/model_type.cc
+++ b/components/sync/syncable/model_type.cc
@@ -121,8 +121,8 @@
     {DEPRECATED_SUPERVISED_USER_SHARED_SETTINGS, "MANAGED_USER_SHARED_SETTING",
      "managed_user_shared_settings", "Managed User Shared Settings",
      sync_pb::EntitySpecifics::kManagedUserSharedSettingFieldNumber, 30},
-    {ARTICLES, "ARTICLE", "articles", "Articles",
-     sync_pb::EntitySpecifics::kArticleFieldNumber, 28},
+    {DEPRECATED_ARTICLES, "ARTICLE", "deprecated_articles",
+     "Deprecated Articles", sync_pb::EntitySpecifics::kArticleFieldNumber, 28},
     {APP_LIST, "APP_LIST", "app_list", "App List",
      sync_pb::EntitySpecifics::kAppListFieldNumber, 29},
     {WIFI_CREDENTIALS, "WIFI_CREDENTIAL", "wifi_credentials",
@@ -250,7 +250,7 @@
     case DEPRECATED_SUPERVISED_USER_SHARED_SETTINGS:
       specifics->mutable_managed_user_shared_setting();
       break;
-    case ARTICLES:
+    case DEPRECATED_ARTICLES:
       specifics->mutable_article();
       break;
     case APP_LIST:
@@ -403,7 +403,7 @@
   if (specifics.has_managed_user_shared_setting())
     return DEPRECATED_SUPERVISED_USER_SHARED_SETTINGS;
   if (specifics.has_article())
-    return ARTICLES;
+    return DEPRECATED_ARTICLES;
   if (specifics.has_app_list())
     return APP_LIST;
   if (specifics.has_wifi_credential())
diff --git a/components/sync/syncable/nigori_util.cc b/components/sync/syncable/nigori_util.cc
index d96dd455..96e6f99 100644
--- a/components/sync/syncable/nigori_util.cc
+++ b/components/sync/syncable/nigori_util.cc
@@ -267,7 +267,7 @@
   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));
-  nigori->set_encrypt_articles(encrypted_types.Has(ARTICLES));
+  nigori->set_encrypt_articles(encrypted_types.Has(DEPRECATED_ARTICLES));
   nigori->set_encrypt_app_list(encrypted_types.Has(APP_LIST));
   nigori->set_encrypt_arc_package(encrypted_types.Has(ARC_PACKAGE));
   nigori->set_encrypt_printers(encrypted_types.Has(PRINTERS));
@@ -318,7 +318,7 @@
   if (nigori.encrypt_favicon_tracking())
     encrypted_types.Put(FAVICON_TRACKING);
   if (nigori.encrypt_articles())
-    encrypted_types.Put(ARTICLES);
+    encrypted_types.Put(DEPRECATED_ARTICLES);
   if (nigori.encrypt_app_list())
     encrypted_types.Put(APP_LIST);
   if (nigori.encrypt_arc_package())
diff --git a/components/sync/user_events/user_event_service_impl_unittest.cc b/components/sync/user_events/user_event_service_impl_unittest.cc
index 6c3be25..301f84b 100644
--- a/components/sync/user_events/user_event_service_impl_unittest.cc
+++ b/components/sync/user_events/user_event_service_impl_unittest.cc
@@ -80,7 +80,10 @@
         is_using_secondary_passphrase_(is_using_secondary_passphrase),
         preferred_data_types_(preferred_data_types) {}
 
-  bool IsEngineInitialized() const override { return is_engine_initialized_; }
+  State GetState() const override {
+    return is_engine_initialized_ ? State::ACTIVE : State::INITIALIZING;
+  }
+
   bool IsUsingSecondaryPassphrase() const override {
     return is_using_secondary_passphrase_;
   }
diff --git a/components/ukm/observers/sync_disable_observer_unittest.cc b/components/ukm/observers/sync_disable_observer_unittest.cc
index f75fd2df..9c9722b57 100644
--- a/components/ukm/observers/sync_disable_observer_unittest.cc
+++ b/components/ukm/observers/sync_disable_observer_unittest.cc
@@ -53,7 +53,9 @@
   void RemoveObserver(syncer::SyncServiceObserver* observer) override {
     observers_.RemoveObserver(observer);
   }
-  bool IsEngineInitialized() const override { return initialized_; }
+  State GetState() const override {
+    return initialized_ ? State::ACTIVE : State::INITIALIZING;
+  }
   bool IsUsingSecondaryPassphrase() const override { return has_passphrase_; }
   syncer::ModelTypeSet GetPreferredDataTypes() const override {
     return preferred_data_types_;
diff --git a/components/unified_consent/unified_consent_service.cc b/components/unified_consent/unified_consent_service.cc
index eb7036d0..4747e0d 100644
--- a/components/unified_consent/unified_consent_service.cc
+++ b/components/unified_consent/unified_consent_service.cc
@@ -97,6 +97,7 @@
   // services.
   pref_service_->SetBoolean(prefs::kUrlKeyedAnonymizedDataCollectionEnabled,
                             false);
+  service_client_->SetSafeBrowsingExtendedReportingEnabled(false);
   service_client_->SetSpellCheckEnabled(false);
 
   switch (GetMigrationState()) {
diff --git a/components/unified_consent/unified_consent_service_unittest.cc b/components/unified_consent/unified_consent_service_unittest.cc
index be8948c..fd2a2f1 100644
--- a/components/unified_consent/unified_consent_service_unittest.cc
+++ b/components/unified_consent/unified_consent_service_unittest.cc
@@ -22,8 +22,8 @@
 class TestSyncService : public syncer::FakeSyncService {
  public:
   int GetDisableReasons() const override { return DISABLE_REASON_NONE; }
+  State GetState() const override { return state_; }
   bool IsFirstSetupComplete() const override { return true; }
-  bool IsEngineInitialized() const override { return engine_initialized_; }
   void AddObserver(syncer::SyncServiceObserver* observer) override {
     observer_ = observer;
   }
@@ -32,9 +32,7 @@
     is_syncing_everything_ = sync_everything;
   }
 
-  void SetEngineInitialized(bool engine_initialized) {
-    engine_initialized_ = engine_initialized;
-  }
+  void SetState(State state) { state_ = state; }
   void FireStateChanged() {
     if (observer_)
       observer_->OnStateChanged(this);
@@ -46,7 +44,7 @@
 
  private:
   syncer::SyncServiceObserver* observer_ = nullptr;
-  bool engine_initialized_ = true;
+  State state_ = State::ACTIVE;
   bool is_syncing_everything_ = false;
 };
 
@@ -167,7 +165,7 @@
   EXPECT_FALSE(consent_service_->IsUnifiedConsentGiven());
 
   // Make sure sync is not active.
-  sync_service_.SetEngineInitialized(false);
+  sync_service_.SetState(syncer::SyncService::State::INITIALIZING);
   EXPECT_FALSE(sync_service_.IsEngineInitialized());
   EXPECT_NE(sync_service_.GetState(), syncer::SyncService::State::ACTIVE);
 
@@ -179,8 +177,7 @@
   EXPECT_FALSE(sync_service_.IsSyncingEverything());
 
   // Initalize sync engine and therefore activate sync.
-  sync_service_.SetEngineInitialized(true);
-  EXPECT_EQ(sync_service_.GetState(), syncer::SyncService::State::ACTIVE);
+  sync_service_.SetState(syncer::SyncService::State::ACTIVE);
   sync_service_.FireStateChanged();
 
   // UnifiedConsentService starts syncing everything.
@@ -253,13 +250,13 @@
   EXPECT_FALSE(pref_service_.GetBoolean(
       prefs::kUrlKeyedAnonymizedDataCollectionEnabled));
   EXPECT_FALSE(spell_check_enabled_);
+  EXPECT_FALSE(safe_browsing_extended_reporting_enabled_);
 
   // Consent is not revoked for the following services.
   EXPECT_TRUE(alternate_error_pages_enabled_);
   EXPECT_TRUE(metrics_reporting_enabled_);
   EXPECT_TRUE(network_predictions_enabled_);
   EXPECT_TRUE(safe_browsing_enabled_);
-  EXPECT_TRUE(safe_browsing_extended_reporting_enabled_);
   EXPECT_TRUE(search_suggest_enabled_);
 }
 #endif  // !defined(OS_CHROMEOS)
diff --git a/components/unified_consent/url_keyed_data_collection_consent_helper_unittest.cc b/components/unified_consent/url_keyed_data_collection_consent_helper_unittest.cc
index 0bc74ee..a83653c 100644
--- a/components/unified_consent/url_keyed_data_collection_consent_helper_unittest.cc
+++ b/components/unified_consent/url_keyed_data_collection_consent_helper_unittest.cc
@@ -31,12 +31,12 @@
 
   // syncer::FakeSyncService:
   int GetDisableReasons() const override { return DISABLE_REASON_NONE; }
+  State GetState() const override { return State::ACTIVE; }
   syncer::ModelTypeSet GetPreferredDataTypes() const override {
     return syncer::ModelTypeSet(syncer::ModelType::HISTORY_DELETE_DIRECTIVES,
                                 syncer::ModelType::USER_EVENTS);
   }
   bool IsFirstSetupComplete() const override { return true; }
-  bool IsEngineInitialized() const override { return true; }
 
   syncer::SyncCycleSnapshot GetLastCycleSnapshot() const override {
     if (!sync_initialized_)
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
index 6b489aa..92ac07e 100644
--- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
+++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
@@ -447,6 +447,10 @@
                       frame_metadata.root_scroll_offset.x());
   metadata->SetDouble(VideoFrameMetadata::ROOT_SCROLL_OFFSET_Y,
                       frame_metadata.root_scroll_offset.y());
+  metadata->SetDouble(VideoFrameMetadata::TOP_CONTROLS_HEIGHT,
+                      frame_metadata.top_controls_height);
+  metadata->SetDouble(VideoFrameMetadata::TOP_CONTROLS_SHOWN_RATIO,
+                      frame_metadata.top_controls_shown_ratio);
 
   oracle_.RecordCapture(utilization);
   const int64_t frame_number = next_capture_frame_number_++;
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 132917c..d8b7416 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -789,6 +789,8 @@
     "fileapi/file_system_url_loader_factory.h",
     "fileapi/fileapi_message_filter.cc",
     "fileapi/fileapi_message_filter.h",
+    "find_in_page_client.cc",
+    "find_in_page_client.h",
     "find_request_manager.cc",
     "find_request_manager.h",
     "font_list_async.cc",
diff --git a/content/browser/browser_context.cc b/content/browser/browser_context.cc
index 199a676..0ff903d 100644
--- a/content/browser/browser_context.cc
+++ b/content/browser/browser_context.cc
@@ -694,4 +694,9 @@
   return decode_history;
 }
 
+download::InProgressDownloadManager*
+BrowserContext::RetriveInProgressDownloadManager() {
+  return nullptr;
+}
+
 }  // namespace content
diff --git a/content/browser/browsing_data/browsing_data_filter_builder_impl.cc b/content/browser/browsing_data/browsing_data_filter_builder_impl.cc
index cba9445..e569410d 100644
--- a/content/browser/browsing_data/browsing_data_filter_builder_impl.cc
+++ b/content/browser/browsing_data/browsing_data_filter_builder_impl.cc
@@ -128,6 +128,8 @@
 
 network::mojom::ClearDataFilterPtr
 BrowsingDataFilterBuilderImpl::BuildNetworkServiceFilter() const {
+  if (IsEmptyBlacklist())
+    return nullptr;
   network::mojom::ClearDataFilterPtr filter =
       network::mojom::ClearDataFilter::New();
   filter->type = (mode_ == Mode::WHITELIST)
diff --git a/content/browser/browsing_data/browsing_data_remover_impl.cc b/content/browser/browsing_data/browsing_data_remover_impl.cc
index 3226847..d59e3ddb 100644
--- a/content/browser/browsing_data/browsing_data_remover_impl.cc
+++ b/content/browser/browsing_data/browsing_data_remover_impl.cc
@@ -303,7 +303,7 @@
 
     network::mojom::ClearDataFilterPtr service_filter =
         filter_builder.BuildNetworkServiceFilter();
-    DCHECK(service_filter->origins.empty())
+    DCHECK(!service_filter || service_filter->origins.empty())
         << "Origin-based deletion is not suitable for channel IDs.";
 
     BrowserContext::GetDefaultStoragePartition(browser_context_)
diff --git a/content/browser/code_cache/generated_code_cache.cc b/content/browser/code_cache/generated_code_cache.cc
index c74c9a3..8aa175c0 100644
--- a/content/browser/code_cache/generated_code_cache.cc
+++ b/content/browser/code_cache/generated_code_cache.cc
@@ -58,50 +58,85 @@
 // being initialized.
 class GeneratedCodeCache::PendingOperation {
  public:
-  PendingOperation(Operation op,
-                   std::string key,
-                   scoped_refptr<net::IOBufferWithSize>);
-  PendingOperation(Operation op, std::string key, const ReadDataCallback&);
-  PendingOperation(Operation op, std::string key);
+  static std::unique_ptr<PendingOperation> CreateWritePendingOp(
+      std::string key,
+      scoped_refptr<net::IOBufferWithSize>);
+  static std::unique_ptr<PendingOperation> CreateFetchPendingOp(
+      std::string key,
+      const ReadDataCallback&);
+  static std::unique_ptr<PendingOperation> CreateDeletePendingOp(
+      std::string key);
+  static std::unique_ptr<PendingOperation> CreateClearCachePendingOp(
+      net::CompletionCallback callback);
 
   ~PendingOperation();
 
   Operation operation() const { return op_; }
   const std::string& key() const { return key_; }
   const scoped_refptr<net::IOBufferWithSize> data() const { return data_; }
-  const ReadDataCallback& callback() const { return callback_; }
+  ReadDataCallback ReleaseReadCallback() { return std::move(read_callback_); }
+  net::CompletionCallback ReleaseCallback() { return std::move(callback_); }
 
  private:
+  PendingOperation(Operation op,
+                   std::string key,
+                   scoped_refptr<net::IOBufferWithSize>,
+                   const ReadDataCallback&,
+                   net::CompletionCallback);
+
   const Operation op_;
   const std::string key_;
   const scoped_refptr<net::IOBufferWithSize> data_;
-  const ReadDataCallback callback_;
+  ReadDataCallback read_callback_;
+  net::CompletionCallback callback_;
 };
 
+std::unique_ptr<GeneratedCodeCache::PendingOperation>
+GeneratedCodeCache::PendingOperation::CreateWritePendingOp(
+    std::string key,
+    scoped_refptr<net::IOBufferWithSize> buffer) {
+  return base::WrapUnique(
+      new PendingOperation(Operation::kWrite, std::move(key), buffer,
+                           ReadDataCallback(), net::CompletionCallback()));
+}
+
+std::unique_ptr<GeneratedCodeCache::PendingOperation>
+GeneratedCodeCache::PendingOperation::CreateFetchPendingOp(
+    std::string key,
+    const ReadDataCallback& read_callback) {
+  return base::WrapUnique(new PendingOperation(
+      Operation::kFetch, std::move(key), scoped_refptr<net::IOBufferWithSize>(),
+      read_callback, net::CompletionCallback()));
+}
+
+std::unique_ptr<GeneratedCodeCache::PendingOperation>
+GeneratedCodeCache::PendingOperation::CreateDeletePendingOp(std::string key) {
+  return base::WrapUnique(
+      new PendingOperation(Operation::kDelete, std::move(key),
+                           scoped_refptr<net::IOBufferWithSize>(),
+                           ReadDataCallback(), net::CompletionCallback()));
+}
+
+std::unique_ptr<GeneratedCodeCache::PendingOperation>
+GeneratedCodeCache::PendingOperation::CreateClearCachePendingOp(
+    net::CompletionCallback callback) {
+  return base::WrapUnique(
+      new PendingOperation(Operation::kClearCache, std::string(),
+                           scoped_refptr<net::IOBufferWithSize>(),
+                           ReadDataCallback(), std::move(callback)));
+}
+
 GeneratedCodeCache::PendingOperation::PendingOperation(
     Operation op,
     std::string key,
-    scoped_refptr<net::IOBufferWithSize> buffer)
+    scoped_refptr<net::IOBufferWithSize> buffer,
+    const ReadDataCallback& read_callback,
+    net::CompletionCallback callback)
     : op_(op),
       key_(std::move(key)),
       data_(buffer),
-      callback_(ReadDataCallback()) {}
-
-GeneratedCodeCache::PendingOperation::PendingOperation(
-    Operation op,
-    std::string key,
-    const ReadDataCallback& callback)
-    : op_(op),
-      key_(std::move(key)),
-      data_(scoped_refptr<net::IOBufferWithSize>()),
-      callback_(callback) {}
-
-GeneratedCodeCache::PendingOperation::PendingOperation(Operation op,
-                                                       std::string key)
-    : op_(op),
-      key_(std::move(key)),
-      data_(scoped_refptr<net::IOBufferWithSize>()),
-      callback_(ReadDataCallback()) {}
+      read_callback_(read_callback),
+      callback_(std::move(callback)) {}
 
 GeneratedCodeCache::PendingOperation::~PendingOperation() = default;
 
@@ -131,8 +166,9 @@
   if (backend_state_ != kInitialized) {
     // Insert it into the list of pending operations while the backend is
     // still being opened.
-    pending_ops_.push_back(std::make_unique<PendingOperation>(
-        Operation::kWrite, std::move(key), buffer));
+    pending_ops_.push_back(
+        GeneratedCodeCache::PendingOperation::CreateWritePendingOp(
+            std::move(key), buffer));
     return;
   }
 
@@ -159,8 +195,9 @@
   if (backend_state_ != kInitialized) {
     // Insert it into the list of pending operations while the backend is
     // still being opened.
-    pending_ops_.push_back(std::make_unique<PendingOperation>(
-        Operation::kFetch, std::move(key), read_data_callback));
+    pending_ops_.push_back(
+        GeneratedCodeCache::PendingOperation::CreateFetchPendingOp(
+            std::move(key), read_data_callback));
     return;
   }
 
@@ -183,13 +220,29 @@
     // Insert it into the list of pending operations while the backend is
     // still being opened.
     pending_ops_.push_back(
-        std::make_unique<PendingOperation>(Operation::kDelete, std::move(key)));
+        GeneratedCodeCache::PendingOperation::CreateDeletePendingOp(
+            std::move(key)));
     return;
   }
 
   DeleteEntryImpl(key);
 }
 
+int GeneratedCodeCache::ClearCache(net::CompletionCallback callback) {
+  if (backend_state_ == kFailed) {
+    return net::ERR_FAILED;
+  }
+
+  if (backend_state_ != kInitialized) {
+    pending_ops_.push_back(
+        GeneratedCodeCache::PendingOperation::CreateClearCachePendingOp(
+            std::move(callback)));
+    return net::ERR_IO_PENDING;
+  }
+
+  return backend_->DoomAllEntries(std::move(callback));
+}
+
 GeneratedCodeCache::GeneratedCodeCache(const base::FilePath& path,
                                        int max_size_bytes)
     : backend_state_(kUnInitialized),
@@ -242,7 +295,7 @@
   for (auto const& op : pending_ops_) {
     switch (op->operation()) {
       case kFetch:
-        FetchEntryImpl(op->key(), op->callback());
+        FetchEntryImpl(op->key(), op->ReleaseReadCallback());
         break;
       case kWrite:
         WriteDataImpl(op->key(), op->data());
@@ -250,6 +303,9 @@
       case kDelete:
         DeleteEntryImpl(op->key());
         break;
+      case kClearCache:
+        DoPendingClearCache(op->ReleaseCallback());
+        break;
     }
   }
   pending_ops_.clear();
@@ -380,4 +436,14 @@
   backend_->DoomEntry(key, net::LOWEST, net::CompletionOnceCallback());
 }
 
+void GeneratedCodeCache::DoPendingClearCache(
+    net::CompletionCallback user_callback) {
+  int result = backend_->DoomAllEntries(user_callback);
+  if (result != net::ERR_IO_PENDING) {
+    // Call the callback here because we returned ERR_IO_PENDING for initial
+    // request.
+    std::move(user_callback).Run(result);
+  }
+}
+
 }  // namespace content
diff --git a/content/browser/code_cache/generated_code_cache.h b/content/browser/code_cache/generated_code_cache.h
index 57e92b76..a84b307 100644
--- a/content/browser/code_cache/generated_code_cache.h
+++ b/content/browser/code_cache/generated_code_cache.h
@@ -9,6 +9,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "content/common/content_export.h"
+#include "net/base/completion_callback.h"
 #include "net/base/io_buffer.h"
 #include "net/disk_cache/disk_cache.h"
 #include "url/origin.h"
@@ -53,6 +54,13 @@
   // Delete the entry corresponding to <url, origin>
   void DeleteEntry(const GURL& url, const url::Origin& origin);
 
+  // Clear code cache.
+  // TODO(mythria): Add support to conditional clearing based on URL
+  // and time range.
+  // TODO(mythria): Also check if we can avoid retruning an error code and
+  // always call the callback to be consistent with other methods.
+  int ClearCache(net::CompletionCallback callback);
+
   const base::FilePath& path() const { return path_; }
 
  private:
@@ -63,7 +71,7 @@
   enum BackendState { kUnInitialized, kInitializing, kInitialized, kFailed };
 
   // The operation requested.
-  enum Operation { kFetch, kWrite, kDelete };
+  enum Operation { kFetch, kWrite, kDelete, kClearCache };
 
   // Data streams corresponding to each entry.
   enum { kDataIndex = 1 };
@@ -107,6 +115,9 @@
   // Delete entry from cache
   void DeleteEntryImpl(const std::string& key);
 
+  void DoPendingClearCache(net::CompletionCallback callback);
+  void PendingClearComplete(net::CompletionCallback callback, int rv);
+
   std::unique_ptr<disk_cache::Backend> backend_;
   BackendState backend_state_;
 
diff --git a/content/browser/code_cache/generated_code_cache_unittest.cc b/content/browser/code_cache/generated_code_cache_unittest.cc
index 45ea2246..e3ee349 100644
--- a/content/browser/code_cache/generated_code_cache_unittest.cc
+++ b/content/browser/code_cache/generated_code_cache_unittest.cc
@@ -73,6 +73,13 @@
     generated_code_cache_->FetchEntry(url, origin, callback);
   }
 
+  void ClearCache() {
+    generated_code_cache_->ClearCache(base::BindRepeating(
+        &GeneratedCodeCacheTest::ClearCacheComplete, base::Unretained(this)));
+  }
+
+  void ClearCacheComplete(int rv) {}
+
   void FetchEntryCallback(scoped_refptr<net::IOBufferWithSize> buffer) {
     if (!buffer || !buffer->data()) {
       received_ = true;
@@ -273,6 +280,7 @@
 
   FetchFromCache(url, origin);
   scoped_task_environment_.RunUntilIdle();
+
   ASSERT_TRUE(received_);
   ASSERT_TRUE(received_null_);
 }
@@ -290,4 +298,18 @@
   ASSERT_TRUE(received_);
   ASSERT_TRUE(received_null_);
 }
+
+TEST_F(GeneratedCodeCacheTest, ClearCache) {
+  GURL url("http://example.com/script.js");
+  url::Origin origin = url::Origin::Create(GURL("http://example.com"));
+
+  InitializeCache();
+  ClearCache();
+  scoped_task_environment_.RunUntilIdle();
+  FetchFromCache(url, origin);
+  scoped_task_environment_.RunUntilIdle();
+
+  ASSERT_TRUE(received_);
+  ASSERT_TRUE(received_null_);
+}
 }  // namespace content
diff --git a/content/browser/devtools/protocol/page_handler.cc b/content/browser/devtools/protocol/page_handler.cc
index 00b744e..60452b0ae 100644
--- a/content/browser/devtools/protocol/page_handler.cc
+++ b/content/browser/devtools/protocol/page_handler.cc
@@ -153,11 +153,12 @@
   return gfx::ToRoundedSize(gfx::ScaleSize(gfx::SizeF(surface_size), scale));
 }
 
-#if !defined(OS_ANDROID)
 void GetMetadataFromFrame(const media::VideoFrame& frame,
                           double* device_scale_factor,
                           double* page_scale_factor,
-                          gfx::Vector2dF* root_scroll_offset) {
+                          gfx::Vector2dF* root_scroll_offset,
+                          double* top_controls_height,
+                          double* top_controls_shown_ratio) {
   // Get metadata from |frame| and ensure that no metadata is missing.
   bool success = true;
   double root_scroll_offset_x, root_scroll_offset_y;
@@ -169,12 +170,16 @@
       media::VideoFrameMetadata::ROOT_SCROLL_OFFSET_X, &root_scroll_offset_x);
   success &= frame.metadata()->GetDouble(
       media::VideoFrameMetadata::ROOT_SCROLL_OFFSET_Y, &root_scroll_offset_y);
+  success &= frame.metadata()->GetDouble(
+      media::VideoFrameMetadata::TOP_CONTROLS_HEIGHT, top_controls_height);
+  success &= frame.metadata()->GetDouble(
+      media::VideoFrameMetadata::TOP_CONTROLS_SHOWN_RATIO,
+      top_controls_shown_ratio);
   DCHECK(success);
 
   root_scroll_offset->set_x(root_scroll_offset_x);
   root_scroll_offset->set_y(root_scroll_offset_y);
 }
-#endif  // !defined(OS_ANDROID)
 
 }  // namespace
 
@@ -191,15 +196,12 @@
       session_id_(0),
       frame_counter_(0),
       frames_in_flight_(0),
-#if !defined(OS_ANDROID)
       video_consumer_(nullptr),
       last_surface_size_(gfx::Size()),
-#endif  // !defined(OS_ANDROID)
       host_(nullptr),
       emulation_handler_(emulation_handler),
       observer_(this),
       weak_factory_(this) {
-#if !defined(OS_ANDROID)
   if (base::FeatureList::IsEnabled(features::kVizDisplayCompositor) ||
       base::FeatureList::IsEnabled(
           features::kUseVideoCaptureApiForDevToolsSnapshots)) {
@@ -207,7 +209,6 @@
         base::BindRepeating(&PageHandler::OnFrameFromVideoConsumer,
                             weak_factory_.GetWeakPtr()));
   }
-#endif  // !defined(OS_ANDROID)
   DCHECK(emulation_handler_);
 }
 
@@ -252,12 +253,10 @@
   if (widget_host)
     observer_.Add(widget_host);
 
-#if !defined(OS_ANDROID)
   if (video_consumer_ && frame_host) {
     video_consumer_->SetFrameSinkId(
         frame_host->GetRenderWidgetHost()->GetFrameSinkId());
   }
-#endif  // !defined(OS_ANDROID)
 }
 
 void PageHandler::Wire(UberDispatcher* dispatcher) {
@@ -365,10 +364,8 @@
   enabled_ = false;
   screencast_enabled_ = false;
 
-#if !defined(OS_ANDROID)
   if (video_consumer_)
     video_consumer_->StopCapture();
-#endif  // !defined(OS_ANDROID)
 
   if (!pending_dialog_.is_null()) {
     WebContentsImpl* web_contents = GetWebContents();
@@ -768,7 +765,6 @@
   bool visible = !widget_host->is_hidden();
   NotifyScreencastVisibility(visible);
 
-#if !defined(OS_ANDROID)
   if (video_consumer_) {
     gfx::Size surface_size = gfx::Size();
     RenderWidgetHostViewBase* const view =
@@ -786,7 +782,6 @@
     video_consumer_->StartCapture();
     return Response::FallThrough();
   }
-#endif  // !defined(OS_ANDROID)
 
   if (!visible)
     return Response::FallThrough();
@@ -801,10 +796,8 @@
 
 Response PageHandler::StopScreencast() {
   screencast_enabled_ = false;
-#if !defined(OS_ANDROID)
   if (video_consumer_)
     video_consumer_->StopCapture();
-#endif  // !defined(OS_ANDROID)
   return Response::FallThrough();
 }
 
@@ -968,7 +961,6 @@
   frames_in_flight_++;
 }
 
-#if !defined(OS_ANDROID)
 void PageHandler::OnFrameFromVideoConsumer(
     scoped_refptr<media::VideoFrame> frame) {
   if (!host_)
@@ -994,24 +986,21 @@
   }
 
   double device_scale_factor, page_scale_factor;
+  double top_controls_height, top_controls_shown_ratio;
   gfx::Vector2dF root_scroll_offset;
   GetMetadataFromFrame(*frame, &device_scale_factor, &page_scale_factor,
-                       &root_scroll_offset);
-  // Top controls are only present on Android. Hence use default values of 0.f.
-  // TODO(dgozman): fix this when viz capture is available on Android.
-  const float kTopControlsHeight = 0.f;
-  const float kTopControlsShownRatio = 0.f;
+                       &root_scroll_offset, &top_controls_height,
+                       &top_controls_shown_ratio);
   std::unique_ptr<Page::ScreencastFrameMetadata> page_metadata =
-      BuildScreencastFrameMetadata(surface_size, device_scale_factor,
-                                   page_scale_factor, root_scroll_offset,
-                                   kTopControlsHeight, kTopControlsShownRatio);
+      BuildScreencastFrameMetadata(
+          surface_size, device_scale_factor, page_scale_factor,
+          root_scroll_offset, top_controls_height, top_controls_shown_ratio);
   if (!page_metadata)
     return;
 
   ScreencastFrameCaptured(std::move(page_metadata),
                           DevToolsVideoConsumer::GetSkBitmapFromFrame(frame));
 }
-#endif  // !defined(OS_ANDROID)
 
 void PageHandler::ScreencastFrameCaptured(
     std::unique_ptr<Page::ScreencastFrameMetadata> page_metadata,
diff --git a/content/browser/devtools/protocol/page_handler.h b/content/browser/devtools/protocol/page_handler.h
index c9c0b1f..eb6a09a 100644
--- a/content/browser/devtools/protocol/page_handler.h
+++ b/content/browser/devtools/protocol/page_handler.h
@@ -19,6 +19,7 @@
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "components/viz/common/quads/compositor_frame_metadata.h"
+#include "content/browser/devtools/devtools_video_consumer.h"
 #include "content/browser/devtools/protocol/devtools_domain_handler.h"
 #include "content/browser/devtools/protocol/devtools_download_manager_delegate.h"
 #include "content/browser/devtools/protocol/page.h"
@@ -28,10 +29,6 @@
 #include "third_party/blink/public/mojom/manifest/manifest_manager.mojom.h"
 #include "url/gurl.h"
 
-#if !defined(OS_ANDROID)
-#include "content/browser/devtools/devtools_video_consumer.h"
-#endif  // !defined(OS_ANDROID)
-
 class SkBitmap;
 
 namespace base {
@@ -162,9 +159,7 @@
   WebContentsImpl* GetWebContents();
   void NotifyScreencastVisibility(bool visible);
   void InnerSwapCompositorFrame();
-#if !defined(OS_ANDROID)
   void OnFrameFromVideoConsumer(scoped_refptr<media::VideoFrame> frame);
-#endif  // !defined(OS_ANDROID)
   void ScreencastFrameCaptured(
       std::unique_ptr<Page::ScreencastFrameMetadata> metadata,
       const SkBitmap& bitmap);
@@ -206,7 +201,6 @@
   int frame_counter_;
   int frames_in_flight_;
 
-#if !defined(OS_ANDROID)
   // |video_consumer_| consumes video frames from FrameSinkVideoCapturerImpl,
   // and provides PageHandler with these frames via OnFrameFromVideoConsumer.
   // This is only used if Viz is enabled and if OS is not Android.
@@ -215,7 +209,6 @@
   // The last surface size used to determine if frames with new sizes need
   // to be requested. This changes due to window resizing.
   gfx::Size last_surface_size_;
-#endif  // !defined(OS_ANDROID)
 
   RenderFrameHostImpl* host_;
   EmulationHandler* emulation_handler_;
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index f8c137f..9724de8 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -296,15 +296,27 @@
       in_progress_cache_initialized_(false),
       browser_context_(browser_context),
       delegate_(nullptr),
+      in_progress_manager_(
+          browser_context_->RetriveInProgressDownloadManager()),
       weak_factory_(this) {
   DCHECK(browser_context);
   download::SetIOTaskRunner(
       BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
   if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
     download::UrlDownloadHandlerFactory::Install(new UrlDownloaderFactory());
-  in_progress_manager_ = std::make_unique<download::InProgressDownloadManager>(
-      this, IsOffTheRecord() ? base::FilePath() : browser_context_->GetPath(),
-      base::BindRepeating(&IsOriginSecure));
+
+  if (!in_progress_manager_) {
+    in_progress_manager_ =
+        std::make_unique<download::InProgressDownloadManager>(
+            this,
+            IsOffTheRecord() ? base::FilePath() : browser_context_->GetPath(),
+            base::BindRepeating(&IsOriginSecure));
+  } else {
+    in_progress_manager_->set_delegate(this);
+    in_progress_manager_->set_download_start_observer(nullptr);
+    in_progress_manager_->set_is_origin_secure_cb(
+        base::BindRepeating(&IsOriginSecure));
+  }
   in_progress_manager_->NotifyWhenInitialized(base::BindOnce(
       &DownloadManagerImpl::OnInProgressDownloadManagerInitialized,
       weak_factory_.GetWeakPtr()));
diff --git a/content/browser/find_in_page_client.cc b/content/browser/find_in_page_client.cc
new file mode 100644
index 0000000..6fc87f7
--- /dev/null
+++ b/content/browser/find_in_page_client.cc
@@ -0,0 +1,55 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/find_in_page_client.h"
+
+#include "content/browser/find_request_manager.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+
+namespace content {
+
+FindInPageClient::FindInPageClient(FindRequestManager* find_request_manager,
+                                   RenderFrameHostImpl* rfh)
+    : frame_(rfh), find_request_manager_(find_request_manager), binding_(this) {
+  blink::mojom::FindInPageClientPtr client;
+  binding_.Bind(MakeRequest(&client));
+  frame_->GetFindInPage()->SetClient(std::move(client));
+}
+
+FindInPageClient::~FindInPageClient() {}
+
+void FindInPageClient::SetNumberOfMatches(
+    int request_id,
+    unsigned int number_of_matches,
+    blink::mojom::FindMatchUpdateType update_type) {
+  const int old_matches = number_of_matches_;
+  number_of_matches_ = number_of_matches;
+  find_request_manager_->UpdatedFrameNumberOfMatches(frame_, old_matches,
+                                                     number_of_matches);
+  // If this is the final update for this frame, it might be the final update
+  // for the find request out of all the frames, so we need to handle it.
+  // Otherwise just notify directly while saying this is not the final update
+  // for the request.
+  if (update_type == blink::mojom::FindMatchUpdateType::kFinalUpdate)
+    find_request_manager_->HandleFinalUpdateForFrame(frame_, request_id);
+  else
+    find_request_manager_->NotifyFindReply(request_id,
+                                           false /* final_update */);
+}
+
+void FindInPageClient::SetActiveMatch(int request_id,
+                                      const gfx::Rect& active_match_rect,
+                                      int active_match_ordinal) {
+  find_request_manager_->SetActiveMatchRect(active_match_rect);
+  find_request_manager_->SetActiveMatchOrdinal(frame_, request_id,
+                                               active_match_ordinal);
+  find_request_manager_->HandleFinalUpdateForFrame(frame_, request_id);
+}
+
+void FindInPageClient::ActivateNearestFindResult(int request_id,
+                                                 const gfx::PointF& point) {
+  frame_->GetFindInPage()->ActivateNearestFindResult(request_id, point);
+}
+
+}  // namespace content
diff --git a/content/browser/find_in_page_client.h b/content/browser/find_in_page_client.h
new file mode 100644
index 0000000..ecd3c472
--- /dev/null
+++ b/content/browser/find_in_page_client.h
@@ -0,0 +1,51 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_FIND_IN_PAGE_CLIENT_H_
+#define CONTENT_BROWSER_FIND_IN_PAGE_CLIENT_H_
+
+#include "mojo/public/cpp/bindings/binding.h"
+#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
+
+namespace content {
+
+class RenderFrameHostImpl;
+class FindRequestManager;
+
+// Per-frame client of FindInPage, owned by FindRequestManager.
+// Keeps track of the current match count for the frame.
+class FindInPageClient final : public blink::mojom::FindInPageClient {
+ public:
+  FindInPageClient(FindRequestManager* find_request_manager,
+                   RenderFrameHostImpl* rfh);
+
+  ~FindInPageClient() override;
+
+  void ActivateNearestFindResult(int request_id, const gfx::PointF& point);
+
+  // Current number of matches for this frame.
+  int number_of_matches() { return number_of_matches_; }
+
+  // blink::mojom::FindInPageClient overrides
+
+  void SetNumberOfMatches(int request_id,
+                          unsigned int current_number_of_matches,
+                          blink::mojom::FindMatchUpdateType final_update) final;
+
+  void SetActiveMatch(int request_id,
+                      const gfx::Rect& active_match_rect,
+                      int active_match_ordinal) final;
+
+ private:
+  RenderFrameHostImpl* const frame_;
+  FindRequestManager* const find_request_manager_;
+  mojo::Binding<blink::mojom::FindInPageClient> binding_;
+  int number_of_matches_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(FindInPageClient);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_FIND_IN_PAGE_CLIENT_H_
diff --git a/content/browser/find_request_manager.cc b/content/browser/find_request_manager.cc
index 34c5307..d76e984 100644
--- a/content/browser/find_request_manager.cc
+++ b/content/browser/find_request_manager.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 
 #include "base/containers/queue.h"
+#include "content/browser/find_in_page_client.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/common/associated_interface_provider_impl.h"
@@ -306,68 +307,43 @@
   DCHECK_GE(number_of_matches, -1);
   DCHECK_GE(active_match_ordinal, -1);
 
-  // Check for an update to the number of matches.
-  if (number_of_matches != -1) {
-    DCHECK_GE(number_of_matches, 0);
-    auto matches_per_frame_it = matches_per_frame_.find(rfh);
-    if (int matches_delta = number_of_matches - matches_per_frame_it->second) {
-      // Increment the global number of matches by the number of additional
-      // matches found for this frame.
-      number_of_matches_ += matches_delta;
-      matches_per_frame_it->second = number_of_matches;
-
-      // All matches may have been removed since the last find reply.
-      if (rfh == active_frame_ && !number_of_matches)
-        relative_active_match_ordinal_ = 0;
-
-      // The active match ordinal may need updating since the number of matches
-      // before the active match may have changed.
-      if (rfh != active_frame_ || !number_of_matches)
-        UpdateActiveMatchOrdinal();
-    }
-  }
-
   // Check for an update to the selection rect.
   if (!selection_rect.IsEmpty())
-    selection_rect_ = selection_rect;
+    SetActiveMatchRect(selection_rect);
 
   // Check for an update to the active match ordinal.
-  if (active_match_ordinal > 0) {
-    if (rfh == active_frame_) {
-      active_match_ordinal_ +=
-          active_match_ordinal - relative_active_match_ordinal_;
-      relative_active_match_ordinal_ = active_match_ordinal;
-    } else {
-      if (active_frame_) {
-        // The new active match is in a different frame than the previous, so
-        // the previous active frame needs to be informed (to clear its active
-        // match highlighting).
-        ClearActiveFindMatch();
-      }
-      active_frame_ = rfh;
-      relative_active_match_ordinal_ = active_match_ordinal;
-      UpdateActiveMatchOrdinal();
-    }
-    if (pending_active_match_ordinal_ && request_id == current_request_.id)
-      pending_active_match_ordinal_ = false;
-    AdvanceQueue(request_id);
+  if (active_match_ordinal > 0)
+    SetActiveMatchOrdinal(rfh, request_id, active_match_ordinal);
+
+  if (number_of_matches != -1) {
+    auto client_it = find_in_page_clients_.find(rfh);
+    client_it->second->SetNumberOfMatches(
+        request_id, number_of_matches,
+        final_update ? blink::mojom::FindMatchUpdateType::kFinalUpdate
+                     : blink::mojom::FindMatchUpdateType::kMoreUpdatesComing);
+    // Since |final_update| is handled already in SetNumberOfMatches, we should
+    // return.
+    // TODO(rakina): Remove this confusing part when mojoifying FindInPage::Find
+    return;
   }
 
   if (!final_update) {
     NotifyFindReply(request_id, false /* final_update */);
     return;
   }
+  HandleFinalUpdateForFrame(rfh, request_id);
+}
 
+void FindRequestManager::HandleFinalUpdateForFrame(RenderFrameHostImpl* rfh,
+                                                   int request_id) {
   // This is the final update for this frame for the current find operation.
-
   pending_initial_replies_.erase(rfh);
   if (request_id == current_session_id_ && !pending_initial_replies_.empty()) {
     NotifyFindReply(request_id, false /* final_update */);
     return;
   }
 
-  // This is the final update for the current find operation.
-
+  // This is the final update for all frames for the current find operation.
   if (request_id == current_request_.id && request_id != current_session_id_) {
     DCHECK(current_request_.options.find_next);
     DCHECK_EQ(pending_find_next_reply_, rfh);
@@ -377,17 +353,51 @@
   FinalUpdateReceived(request_id, rfh);
 }
 
-void FindRequestManager::OnActivateNearestFindResultReply(
-    RenderFrameHostImpl* rfh,
-    int request_id,
-    const gfx::Rect& active_match_rect,
-    int number_of_matches,
-    int active_match_ordinal,
-    bool final_update) {
-  if (active_match_ordinal > 0)
-    contents_->SetFocusedFrame(rfh->frame_tree_node(), rfh->GetSiteInstance());
-  OnFindReply(rfh, request_id, number_of_matches, active_match_rect,
-              active_match_ordinal, final_update);
+void FindRequestManager::UpdatedFrameNumberOfMatches(RenderFrameHostImpl* rfh,
+                                                     unsigned int old_count,
+                                                     unsigned int new_count) {
+  if (old_count == new_count)
+    return;
+
+  // Change the number of matches for this frame in the global count.
+  number_of_matches_ -= old_count;
+  number_of_matches_ += new_count;
+
+  // All matches may have been removed since the last find reply.
+  if (rfh == active_frame_ && !new_count)
+    relative_active_match_ordinal_ = 0;
+
+  // The active match ordinal may need updating since the number of matches
+  // before the active match may have changed.
+  UpdateActiveMatchOrdinal();
+}
+
+void FindRequestManager::SetActiveMatchRect(
+    const gfx::Rect& active_match_rect) {
+  selection_rect_ = active_match_rect;
+}
+
+void FindRequestManager::SetActiveMatchOrdinal(RenderFrameHostImpl* rfh,
+                                               int request_id,
+                                               int active_match_ordinal) {
+  if (rfh == active_frame_) {
+    active_match_ordinal_ +=
+        active_match_ordinal - relative_active_match_ordinal_;
+    relative_active_match_ordinal_ = active_match_ordinal;
+  } else {
+    if (active_frame_) {
+      // The new active match is in a different frame than the previous, so
+      // the previous active frame needs to be informed (to clear its active
+      // match highlighting).
+      ClearActiveFindMatch();
+    }
+    active_frame_ = rfh;
+    relative_active_match_ordinal_ = active_match_ordinal;
+    UpdateActiveMatchOrdinal();
+  }
+  if (pending_active_match_ordinal_ && request_id == current_request_.id)
+    pending_active_match_ordinal_ = false;
+  AdvanceQueue(request_id);
 }
 
 void FindRequestManager::RemoveFrame(RenderFrameHost* rfh) {
@@ -396,10 +406,10 @@
 
   // If matches are counted for the frame that is being removed, decrement the
   // match total before erasing that entry.
-  auto it = matches_per_frame_.find(rfh);
-  if (it != matches_per_frame_.end()) {
-    number_of_matches_ -= it->second;
-    matches_per_frame_.erase(it);
+  auto it = find_in_page_clients_.find(rfh);
+  if (it != find_in_page_clients_.end()) {
+    number_of_matches_ -= it->second->number_of_matches();
+    find_in_page_clients_.erase(it);
   }
 
   // Update the active match ordinal, since it may have changed.
@@ -547,7 +557,7 @@
   pending_initial_replies_.clear();
   pending_find_next_reply_ = nullptr;
   pending_active_match_ordinal_ = true;
-  matches_per_frame_.clear();
+  find_in_page_clients_.clear();
   number_of_matches_ = 0;
   active_frame_ = nullptr;
   relative_active_match_ordinal_ = 0;
@@ -659,7 +669,8 @@
     if (!CheckFrame(node->current_frame_host()))
       continue;
     RenderFrameHost* current_rfh = node->current_frame_host();
-    if (!matches_only || matches_per_frame_.find(current_rfh)->second ||
+    if (!matches_only ||
+        find_in_page_clients_.find(current_rfh)->second->number_of_matches() ||
         pending_initial_replies_.count(current_rfh)) {
       // Note that if there is still a pending reply expected for this frame,
       // then it may have unaccounted matches and will not be skipped via
@@ -680,7 +691,8 @@
   // A frame that is already being searched should not normally be added again.
   DCHECK(force || !CheckFrame(rfh));
 
-  matches_per_frame_[rfh] = 0;
+  find_in_page_clients_[rfh] = std::make_unique<FindInPageClient>(
+      this, static_cast<RenderFrameHostImpl*>(rfh));
 
   FindRequest request = current_request_;
   request.id = current_session_id_;
@@ -690,7 +702,7 @@
 }
 
 bool FindRequestManager::CheckFrame(RenderFrameHost* rfh) const {
-  return rfh && matches_per_frame_.count(rfh);
+  return rfh && find_in_page_clients_.count(rfh);
 }
 
 void FindRequestManager::UpdateActiveMatchOrdinal() {
@@ -709,7 +721,7 @@
                            false /* forward */,
                            true /* matches_only */,
                            false /* wrap */)) != nullptr) {
-    active_match_ordinal_ += matches_per_frame_[frame];
+    active_match_ordinal_ += find_in_page_clients_[frame]->number_of_matches();
   }
   active_match_ordinal_ += relative_active_match_ordinal_;
 }
@@ -751,7 +763,8 @@
   } else {
     // Otherwise, the first frame with matches will have the active match.
     target_rfh = GetInitialFrame(current_request_.options.forward);
-    if (!CheckFrame(target_rfh) || !matches_per_frame_[target_rfh]) {
+    if (!CheckFrame(target_rfh) ||
+        !find_in_page_clients_[target_rfh]->number_of_matches()) {
       target_rfh = Traverse(target_rfh,
                             current_request_.options.forward,
                             true /* matches_only */,
@@ -778,14 +791,10 @@
   activate_.pending_replies.erase(it);
   if (activate_.pending_replies.empty() &&
       CheckFrame(activate_.nearest_frame)) {
-    // Lifetime of FindRequestManager > activate_.nearest_frame  > Mojo
-    // connection, so it's safe to bind |this| and |activate_.nearest_frame|
-    activate_.nearest_frame->GetFindInPage()->ActivateNearestFindResult(
-        activate_.point,
-        base::BindOnce(&FindRequestManager::OnActivateNearestFindResultReply,
-                       base::Unretained(this),
-                       base::Unretained(activate_.nearest_frame),
-                       current_session_id_));
+    const auto client_it = find_in_page_clients_.find(activate_.nearest_frame);
+    if (client_it != find_in_page_clients_.end())
+      client_it->second->ActivateNearestFindResult(current_session_id_,
+                                                   activate_.point);
   }
 }
 
diff --git a/content/browser/find_request_manager.h b/content/browser/find_request_manager.h
index ae95c13..788d4f6 100644
--- a/content/browser/find_request_manager.h
+++ b/content/browser/find_request_manager.h
@@ -20,6 +20,7 @@
 
 namespace content {
 
+class FindInPageClient;
 class RenderFrameHost;
 class RenderFrameHostImpl;
 class WebContentsImpl;
@@ -55,13 +56,27 @@
                    int active_match_ordinal,
                    bool final_update);
 
-  // Called when a reply for ActivateNearestFindResult is received.
-  void OnActivateNearestFindResultReply(RenderFrameHostImpl* rfh,
-                                        int request_id,
-                                        const gfx::Rect& active_match_rect,
-                                        int number_of_matches,
-                                        int active_match_ordinal,
-                                        bool final_update);
+  // Handles the final update from |rfh| for the find request with id
+  // |request_id|.
+  void HandleFinalUpdateForFrame(RenderFrameHostImpl* rfh, int request_id);
+
+  // The number of matches on |rfh| has changed from |old_count| to |new_count|.
+  // This method updates the total number of matches and also updates
+  // |active_match_ordinal_| accordingly.
+  void UpdatedFrameNumberOfMatches(RenderFrameHostImpl* rfh,
+                                   unsigned int old_count,
+                                   unsigned int new_count);
+
+  void SetActiveMatchRect(const gfx::Rect& active_match_rect);
+
+  void SetActiveMatchOrdinal(RenderFrameHostImpl* rfh,
+                             int request_id,
+                             int active_match_ordinal);
+
+  // Sends the find results (as they currently are) to the WebContents.
+  // |final_update| is true if we have received all of the updates from
+  // every frame for this request.
+  void NotifyFindReply(int request_id, bool final_update);
 
   // Removes a frame from the set of frames being searched. This should be
   // called whenever a frame is discovered to no longer exist.
@@ -132,9 +147,6 @@
   // associated with |rfh|.
   void SendFindIPC(const FindRequest& request, RenderFrameHost* rfh);
 
-  // Sends the find results (as they currently are) to the WebContents.
-  void NotifyFindReply(int request_id, bool final_update);
-
   // Returns the initial frame in search order. This will be either the first
   // frame, if searching forward, or the last frame, if searching backward.
   RenderFrameHost* GetInitialFrame(bool forward) const;
@@ -283,10 +295,11 @@
   // |current_request_.id| (the latest request).
   bool pending_active_match_ordinal_;
 
-  // The number of matches found in each frame. There will necessarily be
+  // The FindInPageClient associated with each frame. There will necessarily be
   // entries in this map for every frame that is being (or has been) searched in
   // the current find session, and no other frames.
-  std::unordered_map<RenderFrameHost*, int> matches_per_frame_;
+  std::unordered_map<RenderFrameHost*, std::unique_ptr<FindInPageClient>>
+      find_in_page_clients_;
 
   // The total number of matches found in the current find-in-page session. This
   // should always be equal to the sum of all the entries in
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.h b/content/browser/renderer_host/browser_compositor_view_mac.h
index 513e70d2..8c2adbe1 100644
--- a/content/browser/renderer_host/browser_compositor_view_mac.h
+++ b/content/browser/renderer_host/browser_compositor_view_mac.h
@@ -121,6 +121,7 @@
   const viz::LocalSurfaceId& AllocateNewRendererLocalSurfaceId();
   bool UpdateRendererLocalSurfaceIdFromChild(
       const viz::LocalSurfaceId& child_allocated_local_surface_id);
+  void TransformPointToRootSurface(gfx::PointF* point);
 
   // Indicate that the recyclable compositor should be destroyed, and no future
   // compositors should be recycled.
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.mm b/content/browser/renderer_host/browser_compositor_view_mac.mm
index 72ad272b4..1b20500 100644
--- a/content/browser/renderer_host/browser_compositor_view_mac.mm
+++ b/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -472,6 +472,13 @@
       child_allocated_local_surface_id);
 }
 
+void BrowserCompositorMac::TransformPointToRootSurface(gfx::PointF* point) {
+  gfx::Transform transform_to_root;
+  if (parent_ui_layer_)
+    parent_ui_layer_->GetTargetTransformRelativeTo(nullptr, &transform_to_root);
+  transform_to_root.TransformPoint(point);
+}
+
 void BrowserCompositorMac::LayerDestroyed(ui::Layer* layer) {
   DCHECK_EQ(layer, parent_ui_layer_);
   SetParentUiLayer(nullptr);
diff --git a/content/browser/renderer_host/render_process_host_browsertest.cc b/content/browser/renderer_host/render_process_host_browsertest.cc
index ef05c3f..d46596be 100644
--- a/content/browser/renderer_host/render_process_host_browsertest.cc
+++ b/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -741,8 +741,8 @@
   embedded_test_server()->ServeFilesFromSourceDirectory(
       media::GetTestDataPath());
   ASSERT_TRUE(embedded_test_server()->Start());
-  NavigateToURL(shell(),
-                embedded_test_server()->GetURL("/webaudio_oscillator.html"));
+  ASSERT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL("/webaudio_oscillator.html")));
   RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>(
       shell()->web_contents()->GetMainFrame()->GetProcess());
 
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index 714955d9..54866be4 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -1043,8 +1043,7 @@
 }
 
 void RenderWidgetHostViewMac::TransformPointToRootSurface(gfx::PointF* point) {
-  if (display_only_using_parent_ui_layer_)
-    *point += view_bounds_in_window_dip_.OffsetFromOrigin();
+  browser_compositor_->TransformPointToRootSurface(point);
 }
 
 gfx::Rect RenderWidgetHostViewMac::GetBoundsInRootWindow() {
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.cc b/content/browser/service_worker/service_worker_controllee_request_handler.cc
index 216e0ee..bbaeb41 100644
--- a/content/browser/service_worker/service_worker_controllee_request_handler.cc
+++ b/content/browser/service_worker/service_worker_controllee_request_handler.cc
@@ -319,8 +319,8 @@
   // in redirect case, unassociate it now.
   provider_host_->DisassociateRegistration();
 
-  // Also prevent a register job from establishing an association to a new
-  // registration while we're finding an existing registration.
+  // Also prevent a registration from claiming this host while it's not
+  // yet execution ready.
   provider_host_->SetAllowAssociation(false);
 
   stripped_url_ = net::SimplifyUrlForRequest(url);
@@ -457,7 +457,7 @@
 
   if (blink::ServiceWorkerUtils::IsServicificationEnabled() &&
       IsResourceTypeFrame(resource_type_)) {
-    provider_host_->SetServiceWorkerToUpdate(active_version);
+    provider_host_->AddServiceWorkerToUpdate(active_version);
   }
   bool is_forwarded =
       MaybeForwardToServiceWorker(url_job_.get(), active_version.get());
@@ -497,7 +497,7 @@
 
   if (blink::ServiceWorkerUtils::IsServicificationEnabled() &&
       IsResourceTypeFrame(resource_type_)) {
-    provider_host_->SetServiceWorkerToUpdate(version);
+    provider_host_->AddServiceWorkerToUpdate(version);
   }
   MaybeForwardToServiceWorker(url_job_.get(), version.get());
 }
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc
index f29ad925..4f0dd99d 100644
--- a/content/browser/service_worker/service_worker_provider_host.cc
+++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -147,6 +147,41 @@
 
 }  // anonymous namespace
 
+// RAII helper class for keeping track of versions waiting for an update hint
+// from the renderer.
+//
+// This class is move-only.
+class ServiceWorkerProviderHost::PendingUpdateVersion {
+ public:
+  explicit PendingUpdateVersion(scoped_refptr<ServiceWorkerVersion> version)
+      : version_(std::move(version)) {
+    version_->IncrementPendingUpdateHintCount();
+  }
+
+  PendingUpdateVersion(PendingUpdateVersion&& other) {
+    version_ = std::move(other.version_);
+  }
+
+  ~PendingUpdateVersion() {
+    if (version_)
+      version_->DecrementPendingUpdateHintCount();
+  }
+
+  PendingUpdateVersion& operator=(PendingUpdateVersion&& other) {
+    version_ = std::move(other.version_);
+    return *this;
+  }
+
+  // Needed for base::flat_set.
+  bool operator<(const PendingUpdateVersion& other) const {
+    return version_ < other.version_;
+  }
+
+ private:
+  scoped_refptr<ServiceWorkerVersion> version_;
+  DISALLOW_COPY_AND_ASSIGN(PendingUpdateVersion);
+};
+
 // static
 base::WeakPtr<ServiceWorkerProviderHost>
 ServiceWorkerProviderHost::PreCreateNavigationHost(
@@ -294,12 +329,12 @@
   service_worker_object_hosts_.clear();
   registration_object_hosts_.clear();
 
-  // This host is being destroyed before it received the anticipated
+  // This host may be destroyed before it received the anticipated
   // HintToUpdateServiceWorker IPC from the renderer. This can occur on
-  // navigation failure or if the frame closed soon after navigation. Schedule
-  // the update now.
-  if (version_to_update_)
-    version_to_update_->ScheduleUpdate();
+  // navigation failure or if the frame closed soon after navigation. The
+  // PendingVersionUpdate objects decrement the hint count upon destruction.
+  DCHECK(versions_to_update_.empty() ||
+         blink::ServiceWorkerUtils::IsServicificationEnabled());
 }
 
 int ServiceWorkerProviderHost::frame_id() const {
@@ -486,7 +521,10 @@
     bool notify_controllerchange) {
   CHECK(IsContextSecureForServiceWorker());
   DCHECK(IsProviderForClient());
-  DCHECK(CanAssociateRegistration(registration));
+  DCHECK(registration);
+  DCHECK(!associated_registration_);
+  DCHECK(allow_association_);
+
   associated_registration_ = registration;
   AddMatchingRegistration(registration);
   SetControllerVersionAttribute(registration->active_version(),
@@ -563,7 +601,7 @@
   SetControllerVersionAttribute(nullptr, true /* notify_controllerchange */);
 }
 
-void ServiceWorkerProviderHost::SetServiceWorkerToUpdate(
+void ServiceWorkerProviderHost::AddServiceWorkerToUpdate(
     scoped_refptr<ServiceWorkerVersion> version) {
   DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
   // This is only called for windows now, but it should be called for all
@@ -571,7 +609,7 @@
   DCHECK_EQ(provider_type(),
             blink::mojom::ServiceWorkerProviderType::kForWindow);
 
-  version_to_update_ = std::move(version);
+  versions_to_update_.emplace(std::move(version));
 }
 
 std::unique_ptr<ServiceWorkerRequestHandler>
@@ -635,17 +673,6 @@
   return service_worker_object_hosts_[version_id]->AsWeakPtr();
 }
 
-bool ServiceWorkerProviderHost::CanAssociateRegistration(
-    ServiceWorkerRegistration* registration) {
-  if (!context_)
-    return false;
-  if (running_hosted_version_.get())
-    return false;
-  if (!registration || associated_registration_.get() || !allow_association_)
-    return false;
-  return true;
-}
-
 void ServiceWorkerProviderHost::PostMessageToClient(
     ServiceWorkerVersion* version,
     blink::TransferableMessage message) {
@@ -677,10 +704,17 @@
 void ServiceWorkerProviderHost::ClaimedByRegistration(
     ServiceWorkerRegistration* registration) {
   DCHECK(registration->active_version());
+  // TODO(falken): This should just early return, or DCHECK. claim() should have
+  // no effect on a page that's already using the registration.
   if (registration == associated_registration_) {
     SetControllerVersionAttribute(registration->active_version(),
                                   true /* notify_controllerchange */);
-  } else if (allow_association_) {
+    return;
+  }
+
+  // TODO(crbug.com/866353): It shouldn't be necesary to check
+  // |allow_association_|. See the comment for SetAllowAssociation().
+  if (allow_association_) {
     DisassociateRegistration();
     AssociateRegistration(registration, true /* notify_controllerchange */);
   }
@@ -1132,27 +1166,8 @@
     return;
   }
 
-  // It's possible there is an edge case due to claim() where the
-  // page did not have a contoller at main resource request but got
-  // one later and sent this IPC. Since the controller wasn't eligible
-  // to receive the fetch event, it's not necessary to trigger a soft update for
-  // it, so return.
-  if (!version_to_update_)
-    return;
-
-  // Take |version_to_update_| as it's not needed after this returns.  It's safe
-  // to drop the reference to the version even if we call ScheduleUpdate, since
-  // that function internally ensures a reference until the update occurs.
-  scoped_refptr<ServiceWorkerVersion> version = std::move(version_to_update_);
-
-  // When this DevTools option is enabled, the service worker was already
-  // updated during the main resource request, so just return. It is possible
-  // the option was enabled after the main resource request and before we get
-  // here, but that's an edge case we just ignore.
-  if (context_->force_update_on_page_load())
-    return;
-
-  version->ScheduleUpdate();
+  // The destructors notify the ServiceWorkerVersions to update.
+  versions_to_update_.clear();
 }
 
 bool ServiceWorkerProviderHost::IsValidRegisterMessage(
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h
index 03736cb3..1223abf 100644
--- a/content/browser/service_worker/service_worker_provider_host.h
+++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -361,12 +361,15 @@
   base::WeakPtr<ServiceWorkerObjectHost> GetOrCreateServiceWorkerObjectHost(
       scoped_refptr<ServiceWorkerVersion> version);
 
-  // Returns true if |registration| can be associated with this provider.
-  bool CanAssociateRegistration(ServiceWorkerRegistration* registration);
-
-  // For use by the ServiceWorkerControlleeRequestHandler to disallow
-  // new registration association while a navigation is occurring and
-  // an existing registration is being looked for.
+  // For use by the ServiceWorkerControlleeRequestHandler to disallow a
+  // registration claiming this host while its main resource request is
+  // occurring.
+  //
+  // TODO(crbug.com/866353): This should be unneccessary: registration code
+  // already avoids claiming clients that are not execution ready. However
+  // there may be edge cases with shared workers (pre-NetS13nServiceWorker) and
+  // about:blank iframes, since |is_execution_ready_| is initialized true for
+  // them. Try to remove this after S13nServiceWorker.
   void SetAllowAssociation(bool allow) { allow_association_ = allow; }
 
   // Returns true if the context referred to by this host (i.e. |context_|) is
@@ -438,12 +441,11 @@
   void NotifyControllerLost();
 
   // S13nServiceWorker:
-  // For service worker clients. Called when |version| was
-  // eligible to get a fetch event for the main resource request for this
-  // client. Remembers |version| as needing an update. To avoid affecting
-  // page load performance, the update occurs when we get a
-  // HintToUpdateServiceWorker message from the renderer, or when |this| is
-  // destroyed before receiving that message.
+  // For service worker clients. Called when |version| is the active worker upon
+  // the main resource request for this client. Remembers |version| as needing
+  // a Soft Update. To avoid affecting page load performance, the update occurs
+  // when we get a HintToUpdateServiceWorker message from the renderer, or when
+  // |this| is destroyed before receiving that message.
   //
   // Corresponds to the Handle Fetch algorithm:
   // "If request is a non-subresource request...invoke Soft Update algorithm
@@ -451,14 +453,12 @@
   // https://w3c.github.io/ServiceWorker/#on-fetch-request-algorithm
   //
   // This can be called multiple times due to redirects during a main resource
-  // load. Currently we only respect the last redirect, but intermediate
-  // service workers should be updated too.
-  // TODO(falken): Update intermediate service workers too.
+  // load. All service workers are updated.
   //
-  // For non-S13nServiceWorker: The update logic is controlled entirely
-  // by ServiceWorkerControlleeRequestHandler, which sees all resource
-  // request activity and schedules an update at a convenient time.
-  void SetServiceWorkerToUpdate(scoped_refptr<ServiceWorkerVersion> version);
+  // For non-S13nServiceWorker: The update logic is controlled entirely by
+  // ServiceWorkerControlleeRequestHandler, which sees all resource request
+  // activity and schedules an update at a convenient time.
+  void AddServiceWorkerToUpdate(scoped_refptr<ServiceWorkerVersion> version);
 
   bool is_execution_ready() const { return is_execution_ready_; }
 
@@ -694,10 +694,11 @@
   // TODO(crbug.com/838410): Temporary debugging for the linked bug.
   bool in_dtor_ = false;
 
-  // For service worker clients. The service worker that was eligible to receive
-  // the fetch event for the main resource request for this client. This worker
-  // should be updated "soon". See SetServiceWorkerToUpdate documentation.
-  scoped_refptr<ServiceWorkerVersion> version_to_update_;
+  // For service worker clients. The service workers in the chain of redirects
+  // during the main resource request for this client. These workers should be
+  // updated "soon". See AddServiceWorkerToUpdate() documentation.
+  class PendingUpdateVersion;
+  base::flat_set<PendingUpdateVersion> versions_to_update_;
 
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderHost);
 };
diff --git a/content/browser/service_worker/service_worker_provider_host_unittest.cc b/content/browser/service_worker/service_worker_provider_host_unittest.cc
index aaa9034..42b9f0c 100644
--- a/content/browser/service_worker/service_worker_provider_host_unittest.cc
+++ b/content/browser/service_worker/service_worker_provider_host_unittest.cc
@@ -275,12 +275,17 @@
     EXPECT_FALSE(version->update_timer_.IsRunning());
   }
 
-  ServiceWorkerVersion* GetVersionToUpdate(ServiceWorkerProviderHost* host) {
-    return host->version_to_update_.get();
+  bool HasVersionToUpdate(ServiceWorkerProviderHost* host) {
+    return !host->versions_to_update_.empty();
   }
 
-  std::vector<std::string> bad_messages_;
+  // |scoped_feature_list_| must be before |thread_bundle_|, since
+  // the thread bundle's destruction causes service worker-related
+  // objects to destruct, whose destructors need to know whether servicification
+  // is enabled.
+  base::test::ScopedFeatureList scoped_feature_list_;
   TestBrowserThreadBundle thread_bundle_;
+
   std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
   ServiceWorkerContextCore* context_;
   scoped_refptr<ServiceWorkerRegistration> registration1_;
@@ -292,7 +297,7 @@
   ContentBrowserClient* old_content_browser_client_;
   int next_renderer_provided_id_;
   std::vector<ServiceWorkerRemoteProviderEndpoint> remote_endpoints_;
-  base::test::ScopedFeatureList scoped_feature_list_;
+  std::vector<std::string> bad_messages_;
 
  private:
   ServiceWorkerProviderHost* CreateProviderHostInternal(
@@ -961,7 +966,7 @@
 }
 
 // Tests that the service worker involved with a navigation (via
-// SetServiceWorkerToUpdate) is updated when the host for the navigation is
+// AddServiceWorkerToUpdate) is updated when the host for the navigation is
 // destroyed.
 TEST_P(ServiceWorkerProviderHostTest, UpdateServiceWorkerOnDestruction) {
   // This code path only is used in S13nSW.
@@ -980,9 +985,19 @@
       ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
   version1->SetStatus(ServiceWorkerVersion::ACTIVATED);
   registration1_->SetActiveVersion(version1);
-  host->SetServiceWorkerToUpdate(version1);
 
+  auto version2 = base::MakeRefCounted<ServiceWorkerVersion>(
+      registration2_.get(), GURL("https://www.example.com/sw.js"),
+      2 /* version_id */, helper_->context()->AsWeakPtr());
+  version2->set_fetch_handler_existence(
+      ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+  version2->SetStatus(ServiceWorkerVersion::ACTIVATED);
+  registration2_->SetActiveVersion(version1);
+
+  host->AddServiceWorkerToUpdate(version1);
+  host->AddServiceWorkerToUpdate(version2);
   ExpectUpdateIsNotScheduled(version1.get());
+  ExpectUpdateIsNotScheduled(version2.get());
 
   // Destroy the provider host.
   ASSERT_TRUE(remote_endpoints_.back().host_ptr()->is_bound());
@@ -991,6 +1006,7 @@
 
   // The provider host's destructor should have scheduled the update.
   ExpectUpdateIsScheduled(version1.get());
+  ExpectUpdateIsScheduled(version2.get());
 }
 
 // Tests that the service worker involved with a navigation is updated when the
@@ -1012,14 +1028,12 @@
   // Make a window.
   ServiceWorkerProviderHost* host =
       CreateProviderHost(GURL("https://www.example.com/example.html"));
-  host->AssociateRegistration(registration1_.get(),
-                              false /* notify_controllerchange */);
 
   // Mark the service worker as needing update. Update should not be scheduled
   // yet.
-  host->SetServiceWorkerToUpdate(version1);
+  host->AddServiceWorkerToUpdate(version1);
   ExpectUpdateIsNotScheduled(version1.get());
-  EXPECT_EQ(version1.get(), GetVersionToUpdate(host));
+  EXPECT_TRUE(HasVersionToUpdate(host));
 
   // Send the hint from the renderer. Update should be scheduled.
   mojom::ServiceWorkerContainerHostAssociatedPtr* host_ptr =
@@ -1027,7 +1041,7 @@
   (*host_ptr)->HintToUpdateServiceWorker();
   base::RunLoop().RunUntilIdle();
   ExpectUpdateIsScheduled(version1.get());
-  EXPECT_FALSE(GetVersionToUpdate(host));
+  EXPECT_FALSE(HasVersionToUpdate(host));
 }
 
 // Tests that the host receives a HintToUpdateServiceWorker message but
@@ -1053,21 +1067,82 @@
   registration1_->SetActiveVersion(version1);
 
   // Pretend the registration gets associated after the main
-  // resource request, so SetServiceWorkerToUpdate() is not called.
-  host->AssociateRegistration(registration1_.get(),
-                              false /* notify_controllerchange */);
+  // resource request, so AddServiceWorkerToUpdate() is not called.
 
   ExpectUpdateIsNotScheduled(version1.get());
-  EXPECT_FALSE(GetVersionToUpdate(host));
+  EXPECT_FALSE(HasVersionToUpdate(host));
 
   // Send the hint from the renderer. Update should not be scheduled, since
-  // SetServiceWorkerToUpdate() was not called.
+  // AddServiceWorkerToUpdate() was not called.
   mojom::ServiceWorkerContainerHostAssociatedPtr* host_ptr =
       remote_endpoints_.back().host_ptr();
   (*host_ptr)->HintToUpdateServiceWorker();
   base::RunLoop().RunUntilIdle();
   ExpectUpdateIsNotScheduled(version1.get());
-  EXPECT_FALSE(GetVersionToUpdate(host));
+  EXPECT_FALSE(HasVersionToUpdate(host));
+}
+
+TEST_P(ServiceWorkerProviderHostTest, HintToUpdateServiceWorkerMultiple) {
+  // This code path only is used in S13nSW.
+  if (!IsServiceWorkerServicificationEnabled())
+    return;
+
+  // Make active versions.
+  auto version1 = base::MakeRefCounted<ServiceWorkerVersion>(
+      registration1_.get(), GURL("https://www.example.com/sw.js"),
+      1 /* version_id */, helper_->context()->AsWeakPtr());
+  version1->set_fetch_handler_existence(
+      ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+  version1->SetStatus(ServiceWorkerVersion::ACTIVATED);
+  registration1_->SetActiveVersion(version1);
+
+  auto version2 = base::MakeRefCounted<ServiceWorkerVersion>(
+      registration2_.get(), GURL("https://www.example.com/sw.js"),
+      2 /* version_id */, helper_->context()->AsWeakPtr());
+  version2->set_fetch_handler_existence(
+      ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+  version2->SetStatus(ServiceWorkerVersion::ACTIVATED);
+  registration2_->SetActiveVersion(version1);
+
+  auto version3 = base::MakeRefCounted<ServiceWorkerVersion>(
+      registration3_.get(), GURL("https://other.example.com/sw.js"),
+      3 /* version_id */, helper_->context()->AsWeakPtr());
+  version3->set_fetch_handler_existence(
+      ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
+  version3->SetStatus(ServiceWorkerVersion::ACTIVATED);
+  registration3_->SetActiveVersion(version1);
+
+  // Make a window.
+  ServiceWorkerProviderHost* host =
+      CreateProviderHost(GURL("https://www.example.com/example.html"));
+
+  // Mark the service worker as needing update. Update should not be scheduled
+  // yet.
+  host->AddServiceWorkerToUpdate(version1);
+  host->AddServiceWorkerToUpdate(version2);
+  host->AddServiceWorkerToUpdate(version3);
+  ExpectUpdateIsNotScheduled(version1.get());
+  ExpectUpdateIsNotScheduled(version2.get());
+  ExpectUpdateIsNotScheduled(version3.get());
+  EXPECT_TRUE(HasVersionToUpdate(host));
+
+  // Pretend another page also used version3.
+  version3->IncrementPendingUpdateHintCount();
+
+  // Send the hint from the renderer. Update should be scheduled except for
+  // |version3| as it's being used by another page.
+  mojom::ServiceWorkerContainerHostAssociatedPtr* host_ptr =
+      remote_endpoints_.back().host_ptr();
+  (*host_ptr)->HintToUpdateServiceWorker();
+  base::RunLoop().RunUntilIdle();
+  ExpectUpdateIsScheduled(version1.get());
+  ExpectUpdateIsScheduled(version2.get());
+  ExpectUpdateIsNotScheduled(version3.get());
+  EXPECT_FALSE(HasVersionToUpdate(host));
+
+  // Pretend the other page also finished for version3.
+  version3->DecrementPendingUpdateHintCount();
+  ExpectUpdateIsScheduled(version3.get());
 }
 
 INSTANTIATE_TEST_CASE_P(IsServiceWorkerServicificationEnabled,
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index f6153f9b..2a3f066 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -1362,6 +1362,19 @@
   return false;
 }
 
+void ServiceWorkerVersion::IncrementPendingUpdateHintCount() {
+  DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
+  pending_update_hint_count_++;
+}
+
+void ServiceWorkerVersion::DecrementPendingUpdateHintCount() {
+  DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled());
+  DCHECK_GT(pending_update_hint_count_, 0);
+  pending_update_hint_count_--;
+  if (pending_update_hint_count_ == 0)
+    ScheduleUpdate();
+}
+
 void ServiceWorkerVersion::OnPongFromWorker() {
   ping_controller_.OnPongReceived();
 }
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
index 3947ba76..ded989a 100644
--- a/content/browser/service_worker/service_worker_version.h
+++ b/content/browser/service_worker/service_worker_version.h
@@ -485,6 +485,24 @@
 
   static bool IsInstalled(ServiceWorkerVersion::Status status);
 
+  // For scheduling Soft Update after main resource requests. We schedule
+  // a Soft Update to happen "soon" after each main resource request, attempting
+  // to do the update after the page load finished. The renderer sends a hint
+  // when it's a good time to update. This is a count of outstanding expected
+  // hints, to handle multiple main resource requests occurring near the same
+  // time.
+  //
+  // On each request that dispatches a fetch event to this worker (or would
+  // have, in the case of a no-fetch event worker), this count is incremented.
+  // When the browser-side provider host receives a hint from the renderer that
+  // it is a good time to update the service worker, the count is decremented.
+  // It is also decremented when if the provider host is destroyed before
+  // receiving the hint.
+  //
+  // When the count transitions from 1 to 0, update is scheduled.
+  void IncrementPendingUpdateHintCount();
+  void DecrementPendingUpdateHintCount();
+
  private:
   friend class base::RefCounted<ServiceWorkerVersion>;
   friend class ServiceWorkerPingController;
@@ -819,6 +837,10 @@
   ServiceWorkerScriptCacheMap script_cache_map_;
   base::OneShotTimer update_timer_;
 
+  // For scheduling Soft Update after main resource requests. See
+  // IncrementPendingUpdateHintCount() documentation.
+  int pending_update_hint_count_ = 0;
+
   // Starts running in StartWorker and continues until the worker is stopped.
   base::RepeatingTimer timeout_timer_;
   // Holds the time the worker last started being considered idle.
diff --git a/content/browser/shared_worker/shared_worker_host_unittest.cc b/content/browser/shared_worker/shared_worker_host_unittest.cc
index f90a0342..13b4beb 100644
--- a/content/browser/shared_worker/shared_worker_host_unittest.cc
+++ b/content/browser/shared_worker/shared_worker_host_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
+#include "content/browser/appcache/chrome_appcache_service.h"
 #include "content/browser/shared_worker/mock_shared_worker.h"
 #include "content/browser/shared_worker/shared_worker_connector_impl.h"
 #include "content/browser/shared_worker/shared_worker_instance.h"
@@ -34,7 +35,9 @@
  public:
   SharedWorkerHostTest()
       : mock_render_process_host_(&browser_context_),
-        service_(&storage_partition_, nullptr /* service_worker_context */) {
+        service_(&storage_partition_,
+                 nullptr /* service_worker_context */,
+                 nullptr /* appcache_service */) {
     storage_partition_.set_network_context(&network_context_);
   }
 
diff --git a/content/browser/shared_worker/shared_worker_service_impl.cc b/content/browser/shared_worker/shared_worker_service_impl.cc
index 07271046..d6b462f 100644
--- a/content/browser/shared_worker/shared_worker_service_impl.cc
+++ b/content/browser/shared_worker/shared_worker_service_impl.cc
@@ -13,6 +13,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/task_scheduler/post_task.h"
+#include "content/browser/appcache/appcache_navigation_handle.h"
 #include "content/browser/file_url_loader_factory.h"
 #include "content/browser/shared_worker/shared_worker_host.h"
 #include "content/browser/shared_worker/shared_worker_instance.h"
@@ -147,12 +148,18 @@
 
 SharedWorkerServiceImpl::SharedWorkerServiceImpl(
     StoragePartition* storage_partition,
-    scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)
+    scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
+    scoped_refptr<ChromeAppCacheService> appcache_service)
     : storage_partition_(storage_partition),
       service_worker_context_(std::move(service_worker_context)),
-      weak_factory_(this) {}
+      appcache_service_(std::move(appcache_service)),
+      weak_factory_(this) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
 
-SharedWorkerServiceImpl::~SharedWorkerServiceImpl() {}
+SharedWorkerServiceImpl::~SharedWorkerServiceImpl() {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
 
 bool SharedWorkerServiceImpl::TerminateWorker(
     const GURL& url,
@@ -305,6 +312,10 @@
         CreateFactoryBundle(process_id, storage_partition,
                             constructor_uses_file_url);
 
+    // TODO(nhiroki): Create an instance of AppCacheNavigationHandle from
+    // |appcache_service_| and pass its core() to the IO thread in order to set
+    // up an interceptor for AppCache.
+
     BrowserThread::PostTask(
         BrowserThread::IO, FROM_HERE,
         base::BindOnce(
diff --git a/content/browser/shared_worker/shared_worker_service_impl.h b/content/browser/shared_worker/shared_worker_service_impl.h
index 46810fa5..5708610 100644
--- a/content/browser/shared_worker/shared_worker_service_impl.h
+++ b/content/browser/shared_worker/shared_worker_service_impl.h
@@ -27,6 +27,8 @@
 }
 
 namespace content {
+
+class ChromeAppCacheService;
 class SharedWorkerInstance;
 class SharedWorkerHost;
 class StoragePartition;
@@ -36,7 +38,8 @@
  public:
   SharedWorkerServiceImpl(
       StoragePartition* storage_partition,
-      scoped_refptr<ServiceWorkerContextWrapper> service_worker_context);
+      scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
+      scoped_refptr<ChromeAppCacheService> appcache_service);
   ~SharedWorkerServiceImpl() override;
 
   // SharedWorkerService implementation.
@@ -95,6 +98,7 @@
   // |storage_partition_| owns |this|.
   StoragePartition* const storage_partition_;
   scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
+  scoped_refptr<ChromeAppCacheService> appcache_service_;
 
   base::WeakPtrFactory<SharedWorkerServiceImpl> weak_factory_;
 
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index 5740fc2e41..f8acb2e 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -606,11 +606,12 @@
   partition->service_worker_context_ = new ServiceWorkerContextWrapper(context);
   partition->service_worker_context_->set_storage_partition(partition.get());
 
-  partition->shared_worker_service_ = std::make_unique<SharedWorkerServiceImpl>(
-      partition.get(), partition->service_worker_context_);
-
   partition->appcache_service_ =
-      new ChromeAppCacheService(quota_manager_proxy.get());
+      base::MakeRefCounted<ChromeAppCacheService>(quota_manager_proxy.get());
+
+  partition->shared_worker_service_ = std::make_unique<SharedWorkerServiceImpl>(
+      partition.get(), partition->service_worker_context_,
+      partition->appcache_service_);
 
   partition->push_messaging_context_ =
       new PushMessagingContext(context, partition->service_worker_context_);
diff --git a/content/browser/web_package/signed_exchange_loader.cc b/content/browser/web_package/signed_exchange_loader.cc
index 9ede996..0a58a08 100644
--- a/content/browser/web_package/signed_exchange_loader.cc
+++ b/content/browser/web_package/signed_exchange_loader.cc
@@ -30,9 +30,18 @@
 
 namespace {
 
-net::RedirectInfo CreateRedirectInfo(const GURL& new_url) {
+net::RedirectInfo CreateRedirectInfo(const GURL& new_url,
+                                     const GURL& outer_request_url) {
   net::RedirectInfo redirect_info;
-  redirect_info.new_url = new_url;
+  if (outer_request_url.has_ref()) {
+    // Propagate ref fragment from the outer request URL.
+    url::Replacements<char> replacements;
+    base::StringPiece ref = outer_request_url.ref_piece();
+    replacements.SetRef(ref.data(), url::Component(0, ref.length()));
+    redirect_info.new_url = new_url.ReplaceComponents(replacements);
+  } else {
+    redirect_info.new_url = new_url;
+  }
   redirect_info.new_method = "GET";
   redirect_info.status_code = 302;
   redirect_info.new_site_for_cookies = redirect_info.new_url;
@@ -92,7 +101,8 @@
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     URLLoaderThrottlesGetter url_loader_throttles_getter,
     scoped_refptr<net::URLRequestContextGetter> request_context_getter)
-    : outer_response_timing_info_(
+    : outer_request_url_(outer_request_url),
+      outer_response_timing_info_(
           std::make_unique<ResponseTimingInfo>(outer_response)),
       outer_response_(outer_response),
       forwarding_client_(std::move(forwarding_client)),
@@ -107,6 +117,7 @@
       request_context_getter_(std::move(request_context_getter)),
       weak_factory_(this) {
   DCHECK(signed_exchange_utils::IsSignedExchangeHandlingEnabled());
+  DCHECK(outer_request_url_.is_valid());
 
   // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#privacy-considerations
   // This can be difficult to determine when the exchange is being loaded from
@@ -288,7 +299,7 @@
   // TODO(https://crbug.com/803774): Handle no-GET request_method as a error.
   DCHECK(outer_response_timing_info_);
   forwarding_client_->OnReceiveRedirect(
-      CreateRedirectInfo(request_url),
+      CreateRedirectInfo(request_url, outer_request_url_),
       std::move(outer_response_timing_info_)->CreateRedirectResponseHead());
   forwarding_client_.reset();
 
diff --git a/content/browser/web_package/signed_exchange_loader.h b/content/browser/web_package/signed_exchange_loader.h
index 2ab0d3a..ad69d869 100644
--- a/content/browser/web_package/signed_exchange_loader.h
+++ b/content/browser/web_package/signed_exchange_loader.h
@@ -107,6 +107,8 @@
 
   void FinishReadingBody(int result);
 
+  const GURL outer_request_url_;
+
   // This timing info is used to create a dummy redirect response.
   std::unique_ptr<const ResponseTimingInfo> outer_response_timing_info_;
 
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index d82d7ef..717e332 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -440,9 +440,6 @@
   if (base::FeatureList::IsEnabled(features::kSignedHTTPExchange))
     WebRuntimeFeatures::EnablePreloadImageSrcSetEnabled(true);
 
-  WebRuntimeFeatures::EnableOffMainThreadWebSocket(
-      base::FeatureList::IsEnabled(features::kOffMainThreadWebSocket));
-
   WebRuntimeFeatures::EnableNestedWorkers(
       base::FeatureList::IsEnabled(blink::features::kNestedWorkers));
 
diff --git a/content/common/background_fetch/background_fetch_struct_traits_unittest.cc b/content/common/background_fetch/background_fetch_struct_traits_unittest.cc
index a4d4858..d990a54 100644
--- a/content/common/background_fetch/background_fetch_struct_traits_unittest.cc
+++ b/content/common/background_fetch/background_fetch_struct_traits_unittest.cc
@@ -20,7 +20,7 @@
 
 namespace {
 
-// Creates a new IconDefinition object for the given arguments.
+// Creates a new ImageResource object for the given arguments.
 blink::Manifest::ImageResource CreateIcon(const std::string& src,
                                           std::vector<gfx::Size> sizes,
                                           const std::string& type) {
@@ -71,7 +71,7 @@
   EXPECT_EQ(roundtrip_registration.download_total, registration.download_total);
 }
 
-TEST(BackgroundFetchStructTraitsTest, IconDefinitionRoundtrip) {
+TEST(BackgroundFetchStructTraitsTest, ImageResourceRoundtrip) {
   blink::Manifest::ImageResource icon =
       CreateIcon("my_icon.png", {{256, 256}}, "image/png");
 
diff --git a/content/public/browser/browser_context.h b/content/public/browser/browser_context.h
index 4f794e2..b81c3e6 100644
--- a/content/public/browser/browser_context.h
+++ b/content/public/browser/browser_context.h
@@ -32,6 +32,10 @@
 class FilePath;
 }
 
+namespace download {
+class InProgressDownloadManager;
+}
+
 namespace service_manager {
 class Connector;
 }
@@ -329,6 +333,11 @@
   // directly, so privacy is not compromised.
   virtual media::VideoDecodePerfHistory* GetVideoDecodePerfHistory();
 
+  // Retrieves the InProgressDownloadManager associated with this object if
+  // available
+  virtual download::InProgressDownloadManager*
+  RetriveInProgressDownloadManager();
+
  private:
   const std::string unique_id_;
   bool was_notify_will_be_destroyed_called_ = false;
diff --git a/content/public/browser/browsing_data_filter_builder.h b/content/public/browser/browsing_data_filter_builder.h
index e99ffc8..fc290d1 100644
--- a/content/public/browser/browsing_data_filter_builder.h
+++ b/content/public/browser/browsing_data_filter_builder.h
@@ -69,7 +69,7 @@
   // Builds a filter that can be used with the network service. This uses a Mojo
   // struct rather than a predicate function (as used by the rest of the filters
   // built by this class) because we need to be able to pass the filter to the
-  // network service via IPC.
+  // network service via IPC. Returns nullptr if |IsEmptyBlacklist()| is true.
   virtual network::mojom::ClearDataFilterPtr BuildNetworkServiceFilter()
       const = 0;
 
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index bcb5bc7e..12feb84 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -259,10 +259,6 @@
 const base::Feature kNotificationContentImage{"NotificationContentImage",
                                               base::FEATURE_ENABLED_BY_DEFAULT};
 
-// Off-main-thread WebSocket. See https://crbug.com/825740
-const base::Feature kOffMainThreadWebSocket{"OffMainThreadWebSocket",
-                                            base::FEATURE_ENABLED_BY_DEFAULT};
-
 // Origin Policy. See https://crbug.com/751996
 const base::Feature kOriginPolicy{"OriginPolicy",
                                   base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 673ec86..8f0e58ea 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -66,7 +66,6 @@
 CONTENT_EXPORT extern const base::Feature kMojoVideoCapture;
 CONTENT_EXPORT extern const base::Feature kNetworkServiceInProcess;
 CONTENT_EXPORT extern const base::Feature kNotificationContentImage;
-CONTENT_EXPORT extern const base::Feature kOffMainThreadWebSocket;
 CONTENT_EXPORT extern const base::Feature kOriginPolicy;
 CONTENT_EXPORT extern const base::Feature kOriginTrials;
 CONTENT_EXPORT extern const base::Feature kPageLifecycle;
diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc
index 5d904190..1f806686 100644
--- a/content/public/renderer/content_renderer_client.cc
+++ b/content/public/renderer/content_renderer_client.cc
@@ -11,7 +11,6 @@
 #include "third_party/blink/public/platform/web_media_stream_center.h"
 #include "third_party/blink/public/platform/web_rtc_peer_connection_handler.h"
 #include "third_party/blink/public/platform/web_speech_synthesizer.h"
-#include "third_party/blink/public/platform/websocket_handshake_throttle.h"
 #include "ui/gfx/icc_profile.h"
 #include "url/gurl.h"
 
@@ -68,11 +67,6 @@
   return nullptr;
 }
 
-std::unique_ptr<blink::WebSocketHandshakeThrottle>
-ContentRendererClient::CreateWebSocketHandshakeThrottle() {
-  return nullptr;
-}
-
 std::unique_ptr<WebSocketHandshakeThrottleProvider>
 ContentRendererClient::CreateWebSocketHandshakeThrottleProvider() {
   return nullptr;
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h
index a2dc7a8..776822d2 100644
--- a/content/public/renderer/content_renderer_client.h
+++ b/content/public/renderer/content_renderer_client.h
@@ -169,13 +169,6 @@
   // the content layer will provide an engine.
   virtual blink::WebThemeEngine* OverrideThemeEngine();
 
-  // Allows the embedder to provide a WebSocketHandshakeThrottle. If it returns
-  // NULL then none will be used.
-  // TODO(nhiroki): Remove this once the off-main-thread WebSocket is enabled by
-  // default (https://crbug.com/825740).
-  virtual std::unique_ptr<blink::WebSocketHandshakeThrottle>
-  CreateWebSocketHandshakeThrottle();
-
   // Allows the embedder to provide a WebSocketHandshakeThrottleProvider. If it
   // returns NULL then none will be used.
   virtual std::unique_ptr<WebSocketHandshakeThrottleProvider>
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc
index 8e7653a..b913b99 100644
--- a/content/renderer/pepper/pepper_plugin_instance_impl.cc
+++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -2656,8 +2656,8 @@
   if (find_identifier_ == -1)
     return;
   if (render_frame_) {
-    render_frame_->ReportFindInPageMatchCount(find_identifier_, total,
-                                              PP_ToBool(final_result));
+    render_frame_->GetWebFrame()->ReportFindInPageMatchCount(
+        find_identifier_, total, PP_ToBool(final_result));
   }
 }
 
@@ -2665,9 +2665,9 @@
                                                          int32_t index) {
   if (find_identifier_ == -1)
     return;
-  if (render_frame_) {
-    render_frame_->ReportFindInPageSelection(find_identifier_, index + 1,
-                                             blink::WebRect());
+  if (render_frame_ && render_frame_->GetWebFrame()) {
+    render_frame_->GetWebFrame()->ReportFindInPageSelection(
+        find_identifier_, index + 1, blink::WebRect(), false /* final_update*/);
   }
 }
 
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index d7d39dc..7aeee5b 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -5152,24 +5152,6 @@
     observer.DidChangeScrollOffset();
 }
 
-void RenderFrameImpl::ReportFindInPageMatchCount(int request_id,
-                                                 int count,
-                                                 bool final_update) {
-  // -1 here means don't update the active match ordinal.
-  int active_match_ordinal = count ? -1 : 0;
-
-  SendFindReply(request_id, count, active_match_ordinal, gfx::Rect(),
-                final_update);
-}
-
-void RenderFrameImpl::ReportFindInPageSelection(
-    int request_id,
-    int active_match_ordinal,
-    const blink::WebRect& selection_rect) {
-  SendFindReply(request_id, -1 /* match_count */, active_match_ordinal,
-                selection_rect, false /* final_status_update */);
-}
-
 blink::WebPushClient* RenderFrameImpl::PushClient() {
   if (!push_messaging_client_)
     push_messaging_client_ = new PushMessagingClient(this);
@@ -6313,8 +6295,7 @@
     } else if (!plugin->StartFind(WebString::FromUTF16(search_text),
                                   options.match_case, request_id)) {
       // Send "no results".
-      SendFindReply(request_id, 0 /* match_count */, 0 /* ordinal */,
-                    gfx::Rect(), true /* final_status_update */);
+      frame_->ReportFindInPageMatchCount(request_id, 0, true);
     }
     return;
   }
@@ -7202,11 +7183,8 @@
 
   GetRenderWidget()->ConvertViewportToWindow(&converted_rect);
 
-  Send(new FrameHostMsg_Find_Reply(routing_id_,
-                                   request_id,
-                                   match_count,
-                                   converted_rect,
-                                   ordinal,
+  Send(new FrameHostMsg_Find_Reply(routing_id_, request_id, match_count,
+                                   converted_rect, ordinal,
                                    final_status_update));
 }
 
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index efc7005..3bc1e0ef 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -708,12 +708,6 @@
   void WillReleaseScriptContext(v8::Local<v8::Context> context,
                                 int world_id) override;
   void DidChangeScrollOffset() override;
-  void ReportFindInPageMatchCount(int request_id,
-                                  int count,
-                                  bool final_update) override;
-  void ReportFindInPageSelection(int request_id,
-                                 int active_match_ordinal,
-                                 const blink::WebRect& sel) override;
   blink::WebPushClient* PushClient() override;
   blink::WebRelatedAppsFetcher* GetRelatedAppsFetcher() override;
   void WillStartUsingPeerConnectionHandler(
@@ -1220,7 +1214,7 @@
                      int match_count,
                      int ordinal,
                      const blink::WebRect& selection_rect,
-                     bool final_status_update);
+                     bool final_status_update) override;
 
   void InitializeBlameContext(RenderFrameImpl* parent_frame);
 
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index ca6a21b..f5fc373e 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -2274,7 +2274,7 @@
   blink::WebScrollbarTheme::UpdateScrollbarsWithNSDefaults(
       params->initial_button_delay, params->autoscroll_button_delay,
       params->preferred_scroller_style, params->redraw,
-      params->button_placement, params->jump_on_track_click);
+      params->jump_on_track_click);
 
   is_elastic_overscroll_enabled_ = params->scroll_view_rubber_banding;
 #else
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index a9b86c6..7d6f653 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -110,7 +110,6 @@
 #include "third_party/blink/public/platform/web_url_loader_factory.h"
 #include "third_party/blink/public/platform/web_url_request.h"
 #include "third_party/blink/public/platform/web_vector.h"
-#include "third_party/blink/public/platform/websocket_handshake_throttle.h"
 #include "third_party/blink/public/web/web_local_frame.h"
 #include "third_party/sqlite/sqlite3.h"
 #include "url/gurl.h"
@@ -927,13 +926,6 @@
 
 //------------------------------------------------------------------------------
 
-std::unique_ptr<blink::WebSocketHandshakeThrottle>
-RendererBlinkPlatformImpl::CreateWebSocketHandshakeThrottle() {
-  return GetContentClient()->renderer()->CreateWebSocketHandshakeThrottle();
-}
-
-//------------------------------------------------------------------------------
-
 std::unique_ptr<blink::WebSpeechSynthesizer>
 RendererBlinkPlatformImpl::CreateSpeechSynthesizer(
     blink::WebSpeechSynthesizerClient* client) {
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h
index bebcd93..ec0d01e4 100644
--- a/content/renderer/renderer_blink_platform_impl.h
+++ b/content/renderer/renderer_blink_platform_impl.h
@@ -176,8 +176,6 @@
   std::unique_ptr<webrtc::RtpCapabilities> GetRtpReceiverCapabilities(
       const blink::WebString& kind) override;
   void UpdateWebRTCAPICount(blink::WebRTCAPIName api_name) override;
-  std::unique_ptr<blink::WebSocketHandshakeThrottle>
-  CreateWebSocketHandshakeThrottle() override;
   std::unique_ptr<blink::WebGraphicsContext3DProvider>
   CreateOffscreenGraphicsContext3DProvider(
       const blink::Platform::ContextAttributes& attributes,
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
index 962bc5a3..6845e70 100644
--- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -39,6 +39,16 @@
     self.Fail('conformance2/context/incorrect-context-object-behaviour.html',
         bug=857303)
 
+    # Failing new test added in https://github.com/KhronosGroup/WebGL/pull/2665
+    self.Fail('conformance2/textures/misc/tex-subimage3d-canvas-bug.html',
+              ['linux'], bug=859400)
+    self.Fail('conformance2/textures/misc/tex-subimage3d-canvas-bug.html',
+              ['win', 'opengl', 'passthrough'], bug=859400)
+
+    # Failing new test added in https://github.com/KhronosGroup/WebGL/pull/2658
+    self.Fail('conformance2/transform_feedback/' +
+              'same-buffer-two-binding-points.html', bug=866089)
+
     # Need to fix test, which uses a bad interpretation of the spec
     self.Fail('conformance/offscreencanvas/offscreencanvas-resize.html',
         bug=754733)
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_revision.txt b/content/test/gpu/gpu_tests/webgl_conformance_revision.txt
index 4cb3ca12..cee8f07 100644
--- a/content/test/gpu/gpu_tests/webgl_conformance_revision.txt
+++ b/content/test/gpu/gpu_tests/webgl_conformance_revision.txt
@@ -1,3 +1,3 @@
 # AUTOGENERATED FILE - DO NOT EDIT
 # SEE roll_webgl_conformance.py
-Current webgl revision a5c263cc63ffc2cc189b5214074c8792067c1853
+Current webgl revision 21dbf06b5aa6c7dc8cf56314d4a3f96f57956c53
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_browsertest.cc b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_browsertest.cc
index 24a11be..941d84ac 100644
--- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_browsertest.cc
+++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_browsertest.cc
@@ -232,8 +232,12 @@
 
 IN_PROC_BROWSER_TEST_P(MimeHandlerViewTest, BeforeUnload_NoDialog) {
   ASSERT_NO_FATAL_FAILURE(RunTest("testBeforeUnloadNoDialog.csv"));
-  content::PrepContentsForBeforeUnloadTest(
-      browser()->tab_strip_model()->GetWebContentsAt(0));
+  auto* web_contents = browser()->tab_strip_model()->GetWebContentsAt(0);
+  content::PrepContentsForBeforeUnloadTest(web_contents);
+
+  // Wait for a round trip to the outer renderer to ensure any beforeunload
+  // toggle IPC has had time to reach the browser.
+  ExecuteScriptAndGetValue(web_contents->GetMainFrame(), "");
 
   // Try to navigate away from the page. If the beforeunload listener is
   // triggered and a dialog is shown, this navigation will never complete,
@@ -245,11 +249,17 @@
   ASSERT_NO_FATAL_FAILURE(RunTest("testBeforeUnloadShowDialog.csv"));
   auto* web_contents = browser()->tab_strip_model()->GetWebContentsAt(0);
   content::PrepContentsForBeforeUnloadTest(web_contents);
-  web_contents->GetController().Reload(content::ReloadType::NORMAL, false);
+
+  // Wait for a round trip to the outer renderer to ensure the beforeunload
+  // toggle IPC has had time to reach the browser.
+  ExecuteScriptAndGetValue(web_contents->GetMainFrame(), "");
+
+  web_contents->GetController().LoadURL(GURL("about:blank"), {},
+                                        ui::PAGE_TRANSITION_TYPED, "");
 
   app_modal::JavaScriptAppModalDialog* before_unload_dialog =
       ui_test_utils::WaitForAppModalDialog();
   EXPECT_TRUE(before_unload_dialog->is_before_unload_dialog());
-  EXPECT_TRUE(before_unload_dialog->is_reload());
+  EXPECT_FALSE(before_unload_dialog->is_reload());
   before_unload_dialog->OnAccept(base::string16(), false);
 }
diff --git a/extensions/common/image_util.cc b/extensions/common/image_util.cc
index 10f41a56..0a13106 100644
--- a/extensions/common/image_util.cc
+++ b/extensions/common/image_util.cc
@@ -12,6 +12,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "third_party/re2/src/re2/re2.h"
+#include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/utils/SkParse.h"
 #include "ui/gfx/color_utils.h"
@@ -158,5 +159,33 @@
   return true;
 }
 
+bool IsIconSufficientlyVisible(const SkBitmap& bitmap) {
+  // TODO(crbug.com/805600): Currently, we only consider if there are enough
+  // visible pixels that it won't be difficult for the user to see. Future
+  // revisions will consider the background color of the display context.
+
+  // If the alpha value of any pixel is greater than kAlphaThreshold, the
+  // pixmap is not transparent. These values will likely be adjusted, based
+  // on stats and research into visibility thresholds.
+  constexpr unsigned int kAlphaThreshold = 10;
+  // The minimum "percent" of pixels that must be visible for the icon to be
+  // considered OK.
+  constexpr double kMinPercentVisiblePixels = 0.05;
+  const unsigned int total_pixels = bitmap.height() * bitmap.width();
+  unsigned int visible_pixels = 0;
+  for (int y = 0; y < bitmap.width(); ++y) {
+    for (int x = 0; x < bitmap.height(); ++x) {
+      if (SkColorGetA(bitmap.getColor(x, y)) >= kAlphaThreshold) {
+        ++visible_pixels;
+      }
+    }
+  }
+  // TODO(crbug.com/805600): Add UMA stats when we move to a more
+  // sophisticated analysis of the image and the background display
+  // color.
+  return static_cast<double>(visible_pixels) / total_pixels >=
+         kMinPercentVisiblePixels;
+}
+
 }  // namespace image_util
 }  // namespace extensions
diff --git a/extensions/common/image_util.h b/extensions/common/image_util.h
index e09f6c9..92eefc2eb 100644
--- a/extensions/common/image_util.h
+++ b/extensions/common/image_util.h
@@ -7,6 +7,8 @@
 
 #include <string>
 
+class SkBitmap;
+
 typedef unsigned int SkColor;
 
 // This file contains various utility functions for extension images and colors.
@@ -30,6 +32,10 @@
 // Parses hsl() or hsla() string to a SkColor. Returns true for success.
 bool ParseHslColorString(const std::string& color_string, SkColor* result);
 
+// Analyzes an icon image to determine if it will be visible in its display
+// context.
+bool IsIconSufficientlyVisible(const SkBitmap& bitmap);
+
 }  // namespace image_util
 }  // namespace extensions
 
diff --git a/extensions/common/image_util_unittest.cc b/extensions/common/image_util_unittest.cc
index b03bfe4..a05c39c1 100644
--- a/extensions/common/image_util_unittest.cc
+++ b/extensions/common/image_util_unittest.cc
@@ -4,11 +4,31 @@
 
 #include <string>
 
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/path_service.h"
+#include "extensions/common/extension_paths.h"
 #include "extensions/common/image_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/codec/png_codec.h"
 #include "ui/gfx/color_utils.h"
 
+namespace {
+
+bool LoadPngFromFile(const base::FilePath& path, SkBitmap* dst) {
+  std::string png_bytes;
+  if (!base::ReadFileToString(path, &png_bytes)) {
+    return false;
+  }
+  return gfx::PNGCodec::Decode(
+      reinterpret_cast<const unsigned char*>(png_bytes.data()),
+      png_bytes.length(), dst);
+}
+
+}  // namespace
+
 namespace extensions {
 
 void RunPassHexTest(const std::string& css_string, SkColor expected_result) {
@@ -176,4 +196,38 @@
   EXPECT_FALSE(image_util::ParseCssColorString("my_red", &color));
 }
 
+TEST(ImageUtilTest, IsIconSufficientlyVisible) {
+  base::FilePath test_dir;
+  ASSERT_TRUE(base::PathService::Get(DIR_TEST_DATA, &test_dir));
+  base::FilePath icon_path;
+  {
+    // This icon has all transparent pixels, so it will fail.
+    icon_path = test_dir.AppendASCII("transparent_icon.png");
+    SkBitmap transparent_icon;
+    ASSERT_TRUE(LoadPngFromFile(icon_path, &transparent_icon));
+    EXPECT_FALSE(image_util::IsIconSufficientlyVisible(transparent_icon));
+  }
+  {
+    // Test with an icon that has one opaque pixel.
+    icon_path = test_dir.AppendASCII("one_pixel_opaque_icon.png");
+    SkBitmap visible_icon;
+    ASSERT_TRUE(LoadPngFromFile(icon_path, &visible_icon));
+    EXPECT_FALSE(image_util::IsIconSufficientlyVisible(visible_icon));
+  }
+  {
+    // Test with an icon that has one transparent pixel.
+    icon_path = test_dir.AppendASCII("one_pixel_transparent_icon.png");
+    SkBitmap visible_icon;
+    ASSERT_TRUE(LoadPngFromFile(icon_path, &visible_icon));
+    EXPECT_TRUE(image_util::IsIconSufficientlyVisible(visible_icon));
+  }
+  {
+    // Test with an icon that is completely opaque.
+    icon_path = test_dir.AppendASCII("opaque_icon.png");
+    SkBitmap visible_icon;
+    ASSERT_TRUE(LoadPngFromFile(icon_path, &visible_icon));
+    EXPECT_TRUE(image_util::IsIconSufficientlyVisible(visible_icon));
+  }
+}
+
 }  // namespace extensions
diff --git a/extensions/test/data/one_pixel_opaque_icon.png b/extensions/test/data/one_pixel_opaque_icon.png
new file mode 100644
index 0000000..3729d818
--- /dev/null
+++ b/extensions/test/data/one_pixel_opaque_icon.png
Binary files differ
diff --git a/extensions/test/data/one_pixel_transparent_icon.png b/extensions/test/data/one_pixel_transparent_icon.png
new file mode 100644
index 0000000..e0978a32
--- /dev/null
+++ b/extensions/test/data/one_pixel_transparent_icon.png
Binary files differ
diff --git a/extensions/test/data/opaque_icon.png b/extensions/test/data/opaque_icon.png
new file mode 100644
index 0000000..33d003db
--- /dev/null
+++ b/extensions/test/data/opaque_icon.png
Binary files differ
diff --git a/extensions/test/data/transparent_icon.png b/extensions/test/data/transparent_icon.png
new file mode 100644
index 0000000..1f3e609
--- /dev/null
+++ b/extensions/test/data/transparent_icon.png
Binary files differ
diff --git a/gpu/command_buffer/client/client_font_manager.cc b/gpu/command_buffer/client/client_font_manager.cc
index bae68cf..33a62a9 100644
--- a/gpu/command_buffer/client/client_font_manager.cc
+++ b/gpu/command_buffer/client/client_font_manager.cc
@@ -91,7 +91,7 @@
   std::vector<uint8_t> strike_data;
   strike_server_.writeStrikeData(&strike_data);
 
-  const uint64_t num_handles_created =
+  const size_t num_handles_created =
       last_allocated_handle_id_ - last_serialized_handle_id_;
   if (strike_data.size() == 0u && num_handles_created == 0u &&
       locked_handles_.size() == 0u) {
@@ -102,14 +102,14 @@
   // Size requires for serialization.
   size_t bytes_required =
       // Skia data size.
-      +sizeof(uint64_t) + alignof(uint64_t) + strike_data.size() +
-      16
+      +sizeof(size_t) + alignof(size_t) + strike_data.size() +
+      alignof(std::max_align_t)
       // num of handles created + SerializableHandles.
-      + sizeof(uint64_t) + alignof(uint64_t) +
+      + sizeof(size_t) + alignof(size_t) +
       num_handles_created * sizeof(SerializableSkiaHandle) +
       alignof(SerializableSkiaHandle) +
       // num of handles locked + DiscardableHandleIds.
-      +sizeof(uint64_t) + alignof(uint64_t) +
+      +sizeof(size_t) + alignof(size_t) +
       locked_handles_.size() * sizeof(SkDiscardableHandleId) +
       alignof(SkDiscardableHandleId);
 
@@ -123,7 +123,7 @@
   Serializer serializer(reinterpret_cast<char*>(memory), bytes_required);
 
   // Serialize all new handles.
-  serializer.Write<uint64_t>(&num_handles_created);
+  serializer.Write<size_t>(&num_handles_created);
   for (SkDiscardableHandleId handle_id = last_serialized_handle_id_ + 1;
        handle_id <= last_allocated_handle_id_; handle_id++) {
     auto it = discardable_handle_map_.find(handle_id);
@@ -136,15 +136,16 @@
   }
 
   // Serialize all locked handle ids, so the raster unlocks them when done.
-  const uint64_t num_locked_handles = locked_handles_.size();
-  serializer.Write<uint64_t>(&num_locked_handles);
+  const size_t num_locked_handles = locked_handles_.size();
+  serializer.Write<size_t>(&num_locked_handles);
   for (auto handle_id : locked_handles_)
     serializer.Write<SkDiscardableHandleId>(&handle_id);
 
   // Serialize skia data.
-  const uint64_t skia_data_size = strike_data.size();
-  serializer.Write<uint64_t>(&skia_data_size);
-  serializer.WriteData(strike_data.data(), strike_data.size(), 16);
+  const size_t skia_data_size = strike_data.size();
+  serializer.Write<size_t>(&skia_data_size);
+  serializer.WriteData(strike_data.data(), strike_data.size(),
+                       alignof(std::max_align_t));
 
   // Reset all state for what has been serialized.
   last_serialized_handle_id_ = last_allocated_handle_id_;
diff --git a/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.cc b/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.cc
index 919c72fe1..0e31468 100644
--- a/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.cc
+++ b/gpu/command_buffer/service/gles2_cmd_apply_framebuffer_attachment_cmaa_intel.cc
@@ -1847,3 +1847,5 @@
 
 }  // namespace gles2
 }  // namespace gpu
+
+#undef SHADER
diff --git a/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.cc b/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.cc
index 359fac03..cbd7fb66 100644
--- a/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.cc
+++ b/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.cc
@@ -34,6 +34,7 @@
     }
   ),
 };
+#undef SHADER
 
 }  // namespace
 
diff --git a/gpu/command_buffer/service/raster_decoder_context_state.cc b/gpu/command_buffer/service/raster_decoder_context_state.cc
index d313954e..ff5f5a0 100644
--- a/gpu/command_buffer/service/raster_decoder_context_state.cc
+++ b/gpu/command_buffer/service/raster_decoder_context_state.cc
@@ -6,7 +6,6 @@
 
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/memory_dump_manager.h"
-#include "gpu/command_buffer/common/activity_flags.h"
 #include "gpu/command_buffer/service/service_transfer_cache.h"
 #include "gpu/config/gpu_driver_bug_workarounds.h"
 #include "ui/gl/gl_context.h"
@@ -41,11 +40,10 @@
 
 void RasterDecoderContextState::InitializeGrContext(
     const GpuDriverBugWorkarounds& workarounds,
-    GrContextOptions::PersistentCache* cache,
-    GpuProcessActivityFlags* activity_flags) {
+    GrContextOptions::PersistentCache* cache) {
   DCHECK(context->IsCurrent(surface.get()));
 
-  sk_sp<GrGLInterface> interface(
+  sk_sp<const GrGLInterface> interface(
       gl::init::CreateGrGLInterface(*context->GetVersionInfo()));
   if (!interface) {
     LOG(ERROR) << "OOP raster support disabled: GrGLInterface creation "
@@ -53,18 +51,6 @@
     return;
   }
 
-  auto original_func = interface->fFunctions.fProgramBinary;
-  if (activity_flags && original_func && cache) {
-    interface->fFunctions.fProgramBinary = [&activity_flags, &original_func](
-                                               GrGLuint program,
-                                               GrGLenum binaryFormat,
-                                               void* binary, GrGLsizei length) {
-      GpuProcessActivityFlags::ScopedSetFlag scoped_set_flag(
-          activity_flags, ActivityFlagsBase::FLAG_LOADING_PROGRAM_BINARY);
-      return original_func(program, binaryFormat, binary, length);
-    };
-  }
-
   // If you make any changes to the GrContext::Options here that could
   // affect text rendering, make sure to match the capabilities initialized
   // in GetCapabilities and ensuring these are also used by the
diff --git a/gpu/command_buffer/service/raster_decoder_context_state.h b/gpu/command_buffer/service/raster_decoder_context_state.h
index f6bb7d5..daaf1640 100644
--- a/gpu/command_buffer/service/raster_decoder_context_state.h
+++ b/gpu/command_buffer/service/raster_decoder_context_state.h
@@ -20,7 +20,6 @@
 
 namespace gpu {
 class GpuDriverBugWorkarounds;
-class GpuProcessActivityFlags;
 class ServiceTransferCache;
 
 namespace raster {
@@ -34,8 +33,7 @@
                             scoped_refptr<gl::GLContext> context,
                             bool use_virtualized_gl_contexts);
   void InitializeGrContext(const GpuDriverBugWorkarounds& workarounds,
-                           GrContextOptions::PersistentCache* cache,
-                           GpuProcessActivityFlags* activity_flags = nullptr);
+                           GrContextOptions::PersistentCache* cache);
   void PurgeMemory(
       base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
 
diff --git a/gpu/command_buffer/service/service_font_manager.cc b/gpu/command_buffer/service/service_font_manager.cc
index 5809fcd..21eb859 100644
--- a/gpu/command_buffer/service/service_font_manager.cc
+++ b/gpu/command_buffer/service/service_font_manager.cc
@@ -36,7 +36,7 @@
     if (size == 0u)
       return true;
 
-    if (!AlignMemory(size, 16))
+    if (!AlignMemory(size, alignof(std::max_align_t)))
       return false;
 
     if (!strike_client->readStrikeData(memory_, size))
@@ -121,8 +121,8 @@
 
   // All new handles.
   Deserializer deserializer(memory, memory_size);
-  uint64_t new_handles_created;
-  if (!deserializer.Read<uint64_t>(&new_handles_created))
+  size_t new_handles_created;
+  if (!deserializer.Read<size_t>(&new_handles_created))
     return false;
 
   for (size_t i = 0; i < new_handles_created; ++i) {
@@ -143,8 +143,8 @@
   }
 
   // All locked handles
-  uint64_t num_locked_handles;
-  if (!deserializer.Read<uint64_t>(&num_locked_handles))
+  size_t num_locked_handles;
+  if (!deserializer.Read<size_t>(&num_locked_handles))
     return false;
 
   locked_handles->resize(num_locked_handles);
@@ -154,8 +154,8 @@
   }
 
   // Skia font data.
-  uint64_t skia_data_size = 0u;
-  if (!deserializer.Read<uint64_t>(&skia_data_size))
+  size_t skia_data_size = 0u;
+  if (!deserializer.Read<size_t>(&skia_data_size))
     return false;
 
   if (!deserializer.ReadStrikeData(strike_client_.get(), skia_data_size))
diff --git a/gpu/ipc/service/gpu_channel_manager.cc b/gpu/ipc/service/gpu_channel_manager.cc
index 240560a..44bf5892 100644
--- a/gpu/ipc/service/gpu_channel_manager.cc
+++ b/gpu/ipc/service/gpu_channel_manager.cc
@@ -434,7 +434,7 @@
       gpu::kGpuFeatureStatusEnabled;
   if (enable_raster_transport) {
     raster_decoder_context_state_->InitializeGrContext(
-        gpu_driver_bug_workarounds_, gr_shader_cache(), &activity_flags_);
+        gpu_driver_bug_workarounds_, gr_shader_cache());
   }
 
   gr_cache_controller_.emplace(raster_decoder_context_state_.get(),
diff --git a/gpu/ipc/service/image_transport_surface_overlay_mac.h b/gpu/ipc/service/image_transport_surface_overlay_mac.h
index 9d8af282..07d6582 100644
--- a/gpu/ipc/service/image_transport_surface_overlay_mac.h
+++ b/gpu/ipc/service/image_transport_surface_overlay_mac.h
@@ -77,8 +77,7 @@
 
   gfx::SwapResult SwapBuffersInternal(const gfx::Rect& pixel_damage_rect,
                                       const PresentationCallback& callback);
-  void ApplyBackpressure(base::TimeTicks* before_flush_time,
-                         base::TimeTicks* after_flush_before_commit_time);
+  void ApplyBackpressure();
   void BufferPresented(const PresentationCallback& callback,
                        const gfx::PresentationFeedback& feedback);
 
diff --git a/gpu/ipc/service/image_transport_surface_overlay_mac.mm b/gpu/ipc/service/image_transport_surface_overlay_mac.mm
index ded7b19..025bd9d 100644
--- a/gpu/ipc/service/image_transport_surface_overlay_mac.mm
+++ b/gpu/ipc/service/image_transport_surface_overlay_mac.mm
@@ -103,22 +103,49 @@
   return false;
 }
 
-void ImageTransportSurfaceOverlayMac::ApplyBackpressure(
-    base::TimeTicks* before_flush_time,
-    base::TimeTicks* after_flush_before_commit_time) {
+void ImageTransportSurfaceOverlayMac::ApplyBackpressure() {
   TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::ApplyBackpressure");
 
+  // TODO(ccameron): If this fixes the crashes in GLFence::Create, then
+  // determine how we are getting into this situation.
+  // https://crbug.com/863817
+  CGLContextObj current_context = CGLGetCurrentContext();
+  if (!current_context) {
+    LOG(ERROR) << "No context current!";
+    return;
+  }
+
   // If supported, use GLFence to ensure that we haven't gotten more than one
   // frame ahead of GL.
   if (gl::GLFence::IsSupported()) {
     CheckGLErrors("Before fence/flush");
 
+    // All GL writes to IOSurfaces prior to a glFlush will appear when that
+    // IOSurface is next displayed as a CALayer.
+    // TODO(ccameron): This is unnecessary if the below GLFence is a GLFenceARB,
+    // as that will call glFlush after creating the sync object.
+    {
+      TRACE_EVENT0("gpu", "glFlush");
+      base::TimeTicks before_flush_time = base::TimeTicks::Now();
+      glFlush();
+      base::TimeTicks after_flush_time = base::TimeTicks::Now();
+      CheckGLErrors("After fence/flush");
+      UMA_HISTOGRAM_TIMES("GPU.IOSurface.GLFlushTime",
+                          after_flush_time - before_flush_time);
+    }
+
+    // Create a fence for the current frame's work.
+    std::unique_ptr<gl::GLFence> this_frame_fence;
+    {
+      TRACE_EVENT0("gpu", "Create GLFence");
+      this_frame_fence = gl::GLFence::Create();
+    }
+
     // If we have gotten more than one frame ahead of GL, wait for the previous
     // frame to complete.
     bool fence_context_changed = true;
     if (previous_frame_fence_) {
-      fence_context_changed =
-          fence_context_obj_.get() != CGLGetCurrentContext();
+      fence_context_changed = fence_context_obj_.get() != current_context;
       TRACE_EVENT0("gpu", "ClientWait");
 
       // Ensure we are using the context with which the fence was created.
@@ -157,30 +184,14 @@
       // https://crbug.com/863817
       previous_frame_fence_.reset();
     }
-    // Save the context that we will be using for the GLFence object we will
-    // create (or just leave the previously saved one, if it is unchanged).
+
+    // Update the previous fame fence and save the context that we will be
+    // using for the GLFence object we will create (or just leave the
+    // previously saved one, if it is unchanged).
+    previous_frame_fence_ = std::move(this_frame_fence);
     if (fence_context_changed) {
-      fence_context_obj_.reset(CGLGetCurrentContext(),
-                               base::scoped_policy::RETAIN);
+      fence_context_obj_.reset(current_context, base::scoped_policy::RETAIN);
     }
-    *before_flush_time = base::TimeTicks::Now();
-
-    // Create a fence for the current frame's work.
-    {
-      TRACE_EVENT0("gpu", "Create GLFence");
-      previous_frame_fence_ = gl::GLFence::Create();
-    }
-
-    // A glFlush is necessary to ensure correct content appears.
-    {
-      TRACE_EVENT0("gpu", "glFlush");
-      glFlush();
-      CheckGLErrors("After fence/flush");
-    }
-
-    *after_flush_before_commit_time = base::TimeTicks::Now();
-    UMA_HISTOGRAM_TIMES("GPU.IOSurface.GLFlushTime",
-                        *after_flush_before_commit_time - *before_flush_time);
   } else {
     // GLFence isn't supported - issue a glFinish on each frame to ensure
     // there is backpressure from GL.
@@ -188,7 +199,6 @@
     CheckGLErrors("Before finish");
     glFinish();
     CheckGLErrors("After finish");
-    *after_flush_before_commit_time = base::TimeTicks::Now();
   }
 }
 
@@ -207,19 +217,18 @@
   TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::SwapBuffersInternal");
 
   // Do a GL fence for flush to apply back-pressure before drawing.
-  base::TimeTicks before_flush_time;
-  base::TimeTicks after_flush_before_commit_time;
-  ApplyBackpressure(&before_flush_time, &after_flush_before_commit_time);
+  ApplyBackpressure();
 
+  // Update the CALayer tree in the GPU process.
+  base::TimeTicks before_transaction_time = base::TimeTicks::Now();
   {
     TRACE_EVENT0("gpu", "CommitPendingTreesToCA");
     ca_layer_tree_coordinator_->CommitPendingTreesToCA(pixel_damage_rect);
+    base::TimeTicks after_transaction_time = base::TimeTicks::Now();
+    UMA_HISTOGRAM_TIMES("GPU.IOSurface.CATransactionTime",
+                        after_transaction_time - before_transaction_time);
   }
 
-  base::TimeTicks after_transaction_time = base::TimeTicks::Now();
-  UMA_HISTOGRAM_TIMES("GPU.IOSurface.CATransactionTime",
-                      after_transaction_time - after_flush_before_commit_time);
-
   // Populate the swap-complete parameters to send to the browser.
   SwapBuffersCompleteParams params;
   {
@@ -242,8 +251,8 @@
     params.swap_response.swap_id = 0;  // Set later, in DecoderClient.
     params.swap_response.result = gfx::SwapResult::SWAP_ACK;
     // TODO(brianderson): Tie swap_start to before_flush_time.
-    params.swap_response.swap_start = after_flush_before_commit_time;
-    params.swap_response.swap_end = after_flush_before_commit_time;
+    params.swap_response.swap_start = before_transaction_time;
+    params.swap_response.swap_end = before_transaction_time;
     for (auto& query : ca_layer_in_use_queries_) {
       gpu::TextureInUseResponse response;
       response.texture = query.texture;
diff --git a/ios/chrome/browser/gcm/OWNERS b/ios/chrome/browser/gcm/OWNERS
index 2271273..3bf74c4 100644
--- a/ios/chrome/browser/gcm/OWNERS
+++ b/ios/chrome/browser/gcm/OWNERS
@@ -1,7 +1,4 @@
-dimich@chromium.org
-fgorski@chromium.org
-jianli@chromium.org
-zea@chromium.org
+file://chrome/browser/gcm/OWNERS
 
 # COMPONENT: Services>CloudMessaging
 
diff --git a/ios/chrome/browser/prerender/prerender_egtest.mm b/ios/chrome/browser/prerender/prerender_egtest.mm
index f5c381c7..b372c596 100644
--- a/ios/chrome/browser/prerender/prerender_egtest.mm
+++ b/ios/chrome/browser/prerender/prerender_egtest.mm
@@ -82,6 +82,10 @@
   [[EarlGrey
       selectElementWithMatcher:grey_accessibilityID(
                                    ntp_home::FakeOmniboxAccessibilityID())]
+      performAction:grey_tap()];
+  [ChromeEarlGrey
+      waitForElementWithMatcherSufficientlyVisible:chrome_test_util::Omnibox()];
+  [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
       performAction:grey_typeText([pageString stringByAppendingString:@"\n"])];
   [ChromeEarlGrey waitForPageToFinishLoading];
   [[self class] closeAllTabs];
@@ -92,6 +96,10 @@
   [[EarlGrey
       selectElementWithMatcher:grey_accessibilityID(
                                    ntp_home::FakeOmniboxAccessibilityID())]
+      performAction:grey_tap()];
+  [ChromeEarlGrey
+      waitForElementWithMatcherSufficientlyVisible:chrome_test_util::Omnibox()];
+  [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
       performAction:grey_typeText(
                         [pageString substringToIndex:[pageString length] - 6])];
 
diff --git a/ios/chrome/browser/sync/ios_chrome_sync_client.mm b/ios/chrome/browser/sync/ios_chrome_sync_client.mm
index 233563c9..4a63231 100644
--- a/ios/chrome/browser/sync/ios_chrome_sync_client.mm
+++ b/ios/chrome/browser/sync/ios_chrome_sync_client.mm
@@ -305,7 +305,7 @@
       return favicons ? favicons->AsWeakPtr()
                       : base::WeakPtr<syncer::SyncableService>();
     }
-    case syncer::ARTICLES: {
+    case syncer::DEPRECATED_ARTICLES: {
       // DomDistillerService is used in iOS ReadingList. The distilled articles
       // are saved separately and must not be synced.
       // Add a not reached to avoid having ARTICLES sync be enabled silently.
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm
index 0c8b44f..f3bd9731 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm
@@ -48,11 +48,11 @@
     collectionController;
 @property(nonatomic, weak) id<ContentSuggestionsHeaderControlling>
     headerController;
-@property(nonatomic, assign) CFTimeInterval shiftTilesDownStartTime;
+@property(nonatomic, assign) CFTimeInterval shiftTileStartTime;
+@property(nonatomic, strong) ProceduralBlock shiftUpCompletionBlock;
 
 // Tap gesture recognizer when the omnibox is focused.
 @property(nonatomic, strong) UITapGestureRecognizer* tapGestureRecognizer;
-
 @end
 
 @implementation ContentSuggestionsHeaderSynchronizer
@@ -60,9 +60,10 @@
 @synthesize collectionController = _collectionController;
 @synthesize headerController = _headerController;
 @synthesize shouldAnimateHeader = _shouldAnimateHeader;
-@synthesize shiftTilesDownStartTime = _shiftTilesDownStartTime;
+@synthesize shiftTileStartTime = _shiftTileStartTime;
 @synthesize tapGestureRecognizer = _tapGestureRecognizer;
 @synthesize collectionShiftingOffset = _collectionShiftingOffset;
+@synthesize shiftUpCompletionBlock = _shiftUpCompletionBlock;
 
 - (instancetype)
 initWithCollectionController:
@@ -71,7 +72,7 @@
                 (id<ContentSuggestionsHeaderControlling>)headerController {
   self = [super init];
   if (self) {
-    _shiftTilesDownStartTime = -1;
+    _shiftTileStartTime = -1;
     _shouldAnimateHeader = YES;
 
     _tapGestureRecognizer = [[UITapGestureRecognizer alloc]
@@ -142,28 +143,19 @@
 
   self.collectionController.scrolledToTop = YES;
   self.shouldAnimateHeader = YES;
+  self.shiftUpCompletionBlock = completion;
 
-  [UIView animateWithDuration:kShiftTilesUpAnimationDuration
-      animations:^{
-        if (self.collectionView.contentOffset.y < pinnedOffsetY) {
-          // Changing the contentOffset of the collection results in a scroll
-          // and a change in the constraints of the header.
-          self.collectionView.contentOffset = CGPointMake(0, pinnedOffsetY);
-          // Layout the header for the constraints to be animated.
-          [self.headerController layoutHeader];
-          [self.collectionView.collectionViewLayout invalidateLayout];
-        }
-      }
-      completion:^(BOOL finished) {
-        // Check to see if the collection are still scrolled to the top -- it's
-        // possible (and difficult) to unfocus the omnibox and initiate a
-        // -shiftTilesDown before the animation here completes.
-        if (self.collectionController.scrolledToTop) {
-          self.shouldAnimateHeader = NO;
-          if (completion)
-            completion();
-        }
-      }];
+  // Layout the header for the constraints to be animated.
+  [self.headerController layoutHeader];
+  [self.collectionView.collectionViewLayout invalidateLayout];
+
+  // Similar to -shiftTilesDown, also use a CADisplayLink so each contentOffset
+  // tick forces an update for the fake omnibox. Otherwise the fakebox and its
+  // label will be sized incorrectly when tapped.
+  CADisplayLink* link = [CADisplayLink
+      displayLinkWithTarget:self
+                   selector:@selector(shiftTilesUpAnimationDidFire:)];
+  [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
 }
 
 - (void)invalidateLayout {
@@ -231,16 +223,57 @@
 }
 
 // Updates the collection view's scroll view offset for the next frame of the
+// -shiftTilesUpWithCompletionBlock animation.
+- (void)shiftTilesUpAnimationDidFire:(CADisplayLink*)link {
+  // If this is the first frame of the animation, store the starting timestamp
+  // and do nothing.
+  if (self.shiftTileStartTime == -1) {
+    self.shiftTileStartTime = link.timestamp;
+    return;
+  }
+
+  CFTimeInterval timeElapsed = link.timestamp - self.shiftTileStartTime;
+  double percentComplete = timeElapsed / kShiftTilesUpAnimationDuration;
+  // Ensure that the percentage cannot be above 1.0.
+  if (percentComplete > 1.0)
+    percentComplete = 1.0;
+
+  // Find how much the collection view should be scrolled up in the next frame.
+  CGFloat pinnedOffsetY = [self.headerController pinnedOffsetY];
+  CGFloat startingOffset = pinnedOffsetY - self.collectionShiftingOffset;
+  CGFloat yOffset =
+      startingOffset + percentComplete * (pinnedOffsetY - startingOffset);
+  self.collectionView.contentOffset = CGPointMake(0, yOffset);
+
+  if (percentComplete == 1.0) {
+    [link invalidate];
+    // Reset |shiftTileStartTime| to its sentinel value.
+    self.shiftTileStartTime = -1;
+
+    // Check to see if the collection are still scrolled to the top -- it's
+    // possible (and difficult) to initiate a -shiftTilesDown before the
+    // animation here completes.
+    if (self.collectionController.scrolledToTop) {
+      self.shouldAnimateHeader = NO;
+      if (self.shiftUpCompletionBlock) {
+        self.shiftUpCompletionBlock();
+        self.shiftUpCompletionBlock = nil;
+      }
+    }
+  }
+}
+
+// Updates the collection view's scroll view offset for the next frame of the
 // shiftTilesDown animation.
 - (void)shiftTilesDownAnimationDidFire:(CADisplayLink*)link {
   // If this is the first frame of the animation, store the starting timestamp
   // and do nothing.
-  if (self.shiftTilesDownStartTime == -1) {
-    self.shiftTilesDownStartTime = link.timestamp;
+  if (self.shiftTileStartTime == -1) {
+    self.shiftTileStartTime = link.timestamp;
     return;
   }
 
-  CFTimeInterval timeElapsed = link.timestamp - self.shiftTilesDownStartTime;
+  CFTimeInterval timeElapsed = link.timestamp - self.shiftTileStartTime;
   double percentComplete = timeElapsed / kShiftTilesDownAnimationDuration;
   // Ensure that the percentage cannot be above 1.0.
   if (percentComplete > 1.0)
@@ -256,8 +289,8 @@
   if (percentComplete == 1.0) {
     [link invalidate];
     self.collectionShiftingOffset = 0;
-    // Reset |shiftTilesDownStartTime to its sentinel value.
-    self.shiftTilesDownStartTime = -1;
+    // Reset |shiftTileStartTime| to its sentinel value.
+    self.shiftTileStartTime = -1;
   }
 }
 
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm
index a1e3a1f..22d1856 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm
@@ -154,14 +154,17 @@
 - (void)updateFakeOmniboxForOffset:(CGFloat)offset
                        screenWidth:(CGFloat)screenWidth
                     safeAreaInsets:(UIEdgeInsets)safeAreaInsets {
-  if (!IsSplitToolbarMode(self) && IsUIRefreshPhase1Enabled()) {
+  if (self.isShowing && IsUIRefreshPhase1Enabled()) {
     CGFloat progress =
         self.logoIsShowing
             ? [self.headerView searchFieldProgressForOffset:offset
                                              safeAreaInsets:safeAreaInsets]
             : 1;
-    if (self.isShowing) {
+    if (!IsSplitToolbarMode()) {
       [self.toolbarDelegate setScrollProgressForTabletOmnibox:progress];
+    } else {
+      // Ensure omnibox is reset when not a regular tablet.
+      [self.toolbarDelegate setScrollProgressForTabletOmnibox:1];
     }
   }
 
@@ -383,7 +386,11 @@
 }
 
 - (void)fakeOmniboxTapped:(id)sender {
-  [self.dispatcher focusFakebox];
+  if (IsUIRefreshPhase1Enabled()) {
+    [self shiftTilesUp];
+  } else {
+    [self.dispatcher focusFakebox];
+  }
 }
 
 // If Google is not the default search engine, hide the logo, doodle and
@@ -443,6 +450,9 @@
 
 - (void)shiftTilesUp {
   void (^completionBlock)() = ^{
+    if (IsUIRefreshPhase1Enabled()) {
+      [self.dispatcher focusFakebox];
+    }
     if ((IsUIRefreshPhase1Enabled() && IsSplitToolbarMode()) ||
         (!IsUIRefreshPhase1Enabled() &&
          !content_suggestions::IsRegularXRegularSizeClass(self.view))) {
@@ -497,7 +507,9 @@
     return;
 
   self.omniboxFocused = YES;
-  [self shiftTilesUp];
+
+  if (!IsUIRefreshPhase1Enabled() || ![self.delegate isScrolledToTop])
+    [self shiftTilesUp];
 }
 
 - (void)locationBarResignsFirstResponder {
diff --git a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm
index 01c31b3..da22060 100644
--- a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm
+++ b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm
@@ -372,6 +372,8 @@
   [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
                                           FakeOmniboxAccessibilityID())]
       performAction:grey_tap()];
+  [ChromeEarlGrey
+      waitForElementWithMatcherSufficientlyVisible:chrome_test_util::Omnibox()];
 
   // Navigate and come back.
   [[EarlGrey selectElementWithMatcher:
@@ -401,9 +403,14 @@
   const GURL pageURL = self.testServer->GetURL(kPageURL);
 
   NSString* URL = base::SysUTF8ToNSString(pageURL.spec());
-  // Type the URL in the fake omnibox and navigate to the page.
+  // Tap the fake omnibox, type the URL in the real omnibox and navigate to the
+  // page.
   [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
                                           FakeOmniboxAccessibilityID())]
+      performAction:grey_tap()];
+  [ChromeEarlGrey
+      waitForElementWithMatcherSufficientlyVisible:chrome_test_util::Omnibox()];
+  [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
       performAction:grey_typeText([URL stringByAppendingString:@"\n"])];
 
   // Check that the page is loaded.
@@ -432,6 +439,8 @@
   [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
                                           FakeOmniboxAccessibilityID())]
       performAction:grey_tap()];
+  [ChromeEarlGrey
+      waitForElementWithMatcherSufficientlyVisible:chrome_test_util::Omnibox()];
 
   // Check that the page is loaded.
   GREYAssertTrue(tapped, @"The tap on the fakebox was not correctly logged.");
@@ -491,6 +500,8 @@
   [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
                                           FakeOmniboxAccessibilityID())]
       performAction:grey_tap()];
+  [ChromeEarlGrey
+      waitForElementWithMatcherSufficientlyVisible:chrome_test_util::Omnibox()];
 
   // Offset after the fake omnibox has been tapped.
   CGPoint offsetAfterTap = collectionView.contentOffset;
@@ -542,6 +553,8 @@
   [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
                                           FakeOmniboxAccessibilityID())]
       performAction:grey_tap()];
+  [ChromeEarlGrey
+      waitForElementWithMatcherSufficientlyVisible:chrome_test_util::Omnibox()];
 
   // Unfocus the omnibox.
   [[EarlGrey selectElementWithMatcher:chrome_test_util::
diff --git a/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_table_coordinator_unittest.mm b/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_table_coordinator_unittest.mm
index c11fea3..bbb286e 100644
--- a/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_table_coordinator_unittest.mm
+++ b/ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_table_coordinator_unittest.mm
@@ -117,8 +117,8 @@
     ON_CALL(*sync_service, GetRegisteredDataTypes())
         .WillByDefault(Return(syncer::ModelTypeSet()));
     sync_service->Initialize();
-    EXPECT_CALL(*sync_service, IsEngineInitialized())
-        .WillRepeatedly(Return(true));
+    EXPECT_CALL(*sync_service, GetState())
+        .WillRepeatedly(Return(syncer::SyncService::State::ACTIVE));
     EXPECT_CALL(*sync_service, GetOpenTabsUIDelegate())
         .WillRepeatedly(Return(nullptr));
 
diff --git a/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm b/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm
index 88c6d92..1cf7ecc 100644
--- a/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm
+++ b/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm
@@ -118,6 +118,8 @@
       grey_minimumVisiblePercent(0.2), nil);
   [[EarlGrey selectElementWithMatcher:locationbarButton]
       performAction:grey_tap()];
+  [ChromeEarlGrey
+      waitForElementWithMatcherSufficientlyVisible:chrome_test_util::Omnibox()];
 
   // Tap the QR Code scanner button in the keyboard accessory view.
   id<GREYMatcher> matcher =
diff --git a/ios/chrome/browser/ui/settings/passphrase_collection_view_controller_test.mm b/ios/chrome/browser/ui/settings/passphrase_collection_view_controller_test.mm
index 4ba7ef59..5ef31dd9 100644
--- a/ios/chrome/browser/ui/settings/passphrase_collection_view_controller_test.mm
+++ b/ios/chrome/browser/ui/settings/passphrase_collection_view_controller_test.mm
@@ -87,8 +87,8 @@
   // Set up non-default return values for our sync service mock.
   ON_CALL(*fake_sync_service_, IsPassphraseRequired())
       .WillByDefault(Return(true));
-  ON_CALL(*fake_sync_service_, IsEngineInitialized())
-      .WillByDefault(Return(true));
+  ON_CALL(*fake_sync_service_, GetState())
+      .WillByDefault(Return(syncer::SyncService::State::ACTIVE));
 
   ios::FakeChromeIdentityService* identityService =
       ios::FakeChromeIdentityService::GetInstanceFromChromeProvider();
diff --git a/ios/chrome/browser/ui/settings/save_passwords_collection_view_controller.mm b/ios/chrome/browser/ui/settings/save_passwords_collection_view_controller.mm
index 75c0137..e815f2e 100644
--- a/ios/chrome/browser/ui/settings/save_passwords_collection_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/save_passwords_collection_view_controller.mm
@@ -525,12 +525,10 @@
       savedForms_.push_back(std::move(form));
   }
 
+  password_manager::SortEntriesAndHideDuplicates(&savedForms_,
+                                                 &savedPasswordDuplicates_);
   password_manager::SortEntriesAndHideDuplicates(
-      &savedForms_, &savedPasswordDuplicates_,
-      password_manager::PasswordEntryType::SAVED);
-  password_manager::SortEntriesAndHideDuplicates(
-      &blacklistedForms_, &blacklistedPasswordDuplicates_,
-      password_manager::PasswordEntryType::BLACKLISTED);
+      &blacklistedForms_, &blacklistedPasswordDuplicates_);
 
   [self updateEditButton];
   [self reloadData];
@@ -709,15 +707,12 @@
     auto& forms = blacklisted ? blacklistedForms_ : savedForms_;
     auto& duplicates =
         blacklisted ? blacklistedPasswordDuplicates_ : savedPasswordDuplicates_;
-    password_manager::PasswordEntryType entryType =
-        blacklisted ? password_manager::PasswordEntryType::BLACKLISTED
-                    : password_manager::PasswordEntryType::SAVED;
 
     DCHECK_LT(formIndex, forms.size());
     auto formIterator = forms.begin() + formIndex;
 
     std::unique_ptr<autofill::PasswordForm> form = std::move(*formIterator);
-    std::string key = password_manager::CreateSortKey(*form, entryType);
+    std::string key = password_manager::CreateSortKey(*form);
     auto duplicatesRange = duplicates.equal_range(key);
     for (auto iterator = duplicatesRange.first;
          iterator != duplicatesRange.second; ++iterator) {
@@ -800,11 +795,7 @@
   password_manager::DuplicatesMap& duplicates =
       form.blacklisted_by_user ? blacklistedPasswordDuplicates_
                                : savedPasswordDuplicates_;
-  password_manager::PasswordEntryType entryType =
-      form.blacklisted_by_user
-          ? password_manager::PasswordEntryType::BLACKLISTED
-          : password_manager::PasswordEntryType::SAVED;
-  std::string key = password_manager::CreateSortKey(form, entryType);
+  std::string key = password_manager::CreateSortKey(form);
   auto duplicatesRange = duplicates.equal_range(key);
   for (auto iterator = duplicatesRange.first;
        iterator != duplicatesRange.second; ++iterator) {
diff --git a/ios/chrome/browser/ui/settings/sync_encryption_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/sync_encryption_collection_view_controller_unittest.mm
index 543a52a9..ba1fc49 100644
--- a/ios/chrome/browser/ui/settings/sync_encryption_collection_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/sync_encryption_collection_view_controller_unittest.mm
@@ -53,8 +53,8 @@
         static_cast<browser_sync::ProfileSyncServiceMock*>(
             ProfileSyncServiceFactory::GetForBrowserState(
                 chrome_browser_state_.get()));
-    ON_CALL(*mock_profile_sync_service_, IsEngineInitialized())
-        .WillByDefault(Return(true));
+    ON_CALL(*mock_profile_sync_service_, GetState())
+        .WillByDefault(Return(syncer::SyncService::State::ACTIVE));
     ON_CALL(*mock_profile_sync_service_, IsUsingSecondaryPassphrase())
         .WillByDefault(Return(true));
 
diff --git a/ios/chrome/browser/ui/settings/sync_settings_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/sync_settings_collection_view_controller_unittest.mm
index 26cba02..ce8f38c 100644
--- a/ios/chrome/browser/ui/settings/sync_settings_collection_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/sync_settings_collection_view_controller_unittest.mm
@@ -187,8 +187,8 @@
         static_cast<browser_sync::ProfileSyncServiceMock*>(
             ProfileSyncServiceFactory::GetForBrowserState(
                 chrome_browser_state_.get()));
-    ON_CALL(*mock_profile_sync_service_, IsEngineInitialized())
-        .WillByDefault(Return(true));
+    ON_CALL(*mock_profile_sync_service_, GetState())
+        .WillByDefault(Return(syncer::SyncService::State::ACTIVE));
     ON_CALL(*mock_profile_sync_service_, GetRegisteredDataTypes())
         .WillByDefault(Return(syncer::ModelTypeSet()));
     mock_profile_sync_service_->Initialize();
diff --git a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm
index 0cc0d680..e323749 100644
--- a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm
+++ b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm
@@ -523,11 +523,6 @@
 
 - (void)hideTabStrip:(BOOL)hidden {
   self.view.hidden = hidden;
-  if (!hidden) {
-    NamedGuide* tabSwitcherGuide =
-        [NamedGuide guideWithName:kTabStripTabSwitcherGuide view:self.view];
-    tabSwitcherGuide.constrainedView = _tabSwitcherButton;
-  }
 }
 
 #pragma mark - Private
@@ -751,6 +746,21 @@
   return [self modelIndexForIndex:[_tabArray indexOfObject:view]];
 }
 
+// The |tabSwitcherGuide| cannot use constrainedView in the tab strip because
+// here views use CGAffineTransformMakeScale to support RTL, and NamedGuide
+// doesn't honor transforms. Instead we set the tabSwitcherGuide as necessary.
+- (void)updateTabSwitcherGuide {
+  NamedGuide* tabSwitcherGuide =
+      [NamedGuide guideWithName:kTabStripTabSwitcherGuide view:self.view];
+  tabSwitcherGuide.constrainedFrame = _tabSwitcherButton.frame;
+  if (UseRTLLayout()) {
+    CGRect frame = tabSwitcherGuide.constrainedFrame;
+    frame.origin.x =
+        self.view.frame.size.width - _tabSwitcherButton.frame.origin.x;
+    tabSwitcherGuide.constrainedFrame = frame;
+  }
+}
+
 #pragma mark -
 #pragma mark Tab Drag and Drop methods
 
@@ -1392,6 +1402,7 @@
 // Creates TabViews for each Tab in the TabModel and positions them in the
 // correct location onscreen.
 - (void)layoutTabStripSubviews {
+  [self updateTabSwitcherGuide];
   const NSUInteger tabCount = [_tabArray count] - [_closingTabs count];
   if (!tabCount)
     return;
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm b/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm
index edc8d26..a33bbd3 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm
+++ b/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm
@@ -536,6 +536,8 @@
       grey_minimumVisiblePercent(0.2), nil);
   [[EarlGrey selectElementWithMatcher:locationbarButton]
       performAction:grey_tap()];
+  [ChromeEarlGrey
+      waitForElementWithMatcherSufficientlyVisible:chrome_test_util::Omnibox()];
 
   // Tap the "/" keyboard accessory button.
   id<GREYMatcher> slashButtonMatcher = grey_allOf(
diff --git a/media/base/video_frame_metadata.h b/media/base/video_frame_metadata.h
index cabe173..7b4d2cb4 100644
--- a/media/base/video_frame_metadata.h
+++ b/media/base/video_frame_metadata.h
@@ -134,6 +134,8 @@
     PAGE_SCALE_FACTOR,
     ROOT_SCROLL_OFFSET_X,
     ROOT_SCROLL_OFFSET_Y,
+    TOP_CONTROLS_HEIGHT,
+    TOP_CONTROLS_SHOWN_RATIO,
 
     NUM_KEYS
   };
diff --git a/media/capture/video/chromeos/OWNERS b/media/capture/video/chromeos/OWNERS
index ed5b4bc..c1d5fd53 100644
--- a/media/capture/video/chromeos/OWNERS
+++ b/media/capture/video/chromeos/OWNERS
@@ -1,3 +1,5 @@
 jcliang@chromium.org
 wuchengli@chromium.org
 posciak@chromium.org
+shik@chromium.org
+hywu@chromium.org
diff --git a/media/filters/BUILD.gn b/media/filters/BUILD.gn
index 30eb8ec..72ac8bd 100644
--- a/media/filters/BUILD.gn
+++ b/media/filters/BUILD.gn
@@ -249,6 +249,7 @@
 source_set("unit_tests") {
   testonly = true
   sources = [
+    "audio_buffer_stream_unittest.cc",
     "audio_clock_unittest.cc",
     "audio_decoder_selector_unittest.cc",
     "audio_renderer_algorithm_unittest.cc",
diff --git a/media/filters/audio_buffer_stream_unittest.cc b/media/filters/audio_buffer_stream_unittest.cc
new file mode 100644
index 0000000..f674a49
--- /dev/null
+++ b/media/filters/audio_buffer_stream_unittest.cc
@@ -0,0 +1,154 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "media/base/gmock_callback_support.h"
+#include "media/base/media_log.h"
+#include "media/base/mock_filters.h"
+#include "media/filters/decoder_stream.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+using testing::_;
+using testing::DoAll;
+using testing::Invoke;
+using testing::Return;
+using testing::SaveArg;
+
+namespace media {
+
+MATCHER(IsRegularDecoderBuffer, "") {
+  return !arg->end_of_stream();
+}
+
+MATCHER(IsEOSDecoderBuffer, "") {
+  return arg->end_of_stream();
+}
+
+static void OnAudioBufferStreamInitialized(base::OnceClosure closure,
+                                           bool success) {
+  ASSERT_TRUE(success);
+  std::move(closure).Run();
+}
+
+class AudioBufferStreamTest : public testing::Test {
+ public:
+  AudioBufferStreamTest()
+      : audio_buffer_stream_(
+            std::make_unique<AudioBufferStream::StreamTraits>(
+                &media_log_,
+                CHANNEL_LAYOUT_STEREO),
+            task_environment_.GetMainThreadTaskRunner(),
+            base::BindRepeating(&AudioBufferStreamTest::CreateMockAudioDecoder,
+                                base::Unretained(this)),
+            &media_log_) {
+    // Any valid config will do.
+    demuxer_stream_.set_audio_decoder_config(
+        {kCodecAAC, kSampleFormatS16, CHANNEL_LAYOUT_STEREO, 44100, {}, {}});
+    EXPECT_CALL(demuxer_stream_, SupportsConfigChanges())
+        .WillRepeatedly(Return(true));
+
+    base::RunLoop run_loop;
+    audio_buffer_stream_.Initialize(
+        &demuxer_stream_,
+        base::BindOnce(&OnAudioBufferStreamInitialized, run_loop.QuitClosure()),
+        nullptr, base::DoNothing(), base::DoNothing());
+    run_loop.Run();
+  }
+
+  MockDemuxerStream* demuxer_stream() { return &demuxer_stream_; }
+  MockAudioDecoder* decoder() { return decoder_; }
+
+  void ReadAudioBuffer(base::OnceClosure closure) {
+    audio_buffer_stream_.Read(
+        base::BindOnce(&AudioBufferStreamTest::OnAudioBufferReadDone,
+                       base::Unretained(this), std::move(closure)));
+  }
+
+  void ProduceDecoderOutput(scoped_refptr<DecoderBuffer> buffer,
+                            const AudioDecoder::DecodeCB& decode_cb) {
+    // Make sure successive AudioBuffers have increasing timestamps.
+    last_timestamp_ += base::TimeDelta::FromMilliseconds(27);
+    const auto& config = demuxer_stream_.audio_decoder_config();
+    base::SequencedTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(
+            decoder_output_cb_,
+            AudioBuffer::CreateEmptyBuffer(
+                config.channel_layout(), config.channels(),
+                config.samples_per_second(), 1221, last_timestamp_)));
+    base::SequencedTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(decode_cb, DecodeStatus::OK));
+  }
+
+  void RunUntilIdle() { task_environment_.RunUntilIdle(); }
+
+ private:
+  std::vector<std::unique_ptr<AudioDecoder>> CreateMockAudioDecoder() {
+    auto decoder = std::make_unique<MockAudioDecoder>();
+    EXPECT_CALL(*decoder, Initialize(_, _, _, _, _))
+        .WillOnce(DoAll(SaveArg<3>(&decoder_output_cb_), RunCallback<2>(true)));
+    decoder_ = decoder.get();
+
+    std::vector<std::unique_ptr<AudioDecoder>> result;
+    result.push_back(std::move(decoder));
+    return result;
+  }
+
+  void OnAudioBufferReadDone(base::OnceClosure closure,
+                             AudioBufferStream::Status status,
+                             const scoped_refptr<AudioBuffer>& audio_buffer) {
+    std::move(closure).Run();
+  }
+
+  base::test::ScopedTaskEnvironment task_environment_;
+  MediaLog media_log_;
+  testing::NiceMock<MockDemuxerStream> demuxer_stream_{DemuxerStream::AUDIO};
+  AudioBufferStream audio_buffer_stream_;
+
+  MockAudioDecoder* decoder_ = nullptr;
+  AudioDecoder::OutputCB decoder_output_cb_;
+  base::TimeDelta last_timestamp_;
+
+  DISALLOW_COPY_AND_ASSIGN(AudioBufferStreamTest);
+};
+
+TEST_F(AudioBufferStreamTest, FlushOnConfigChange) {
+  MockAudioDecoder* first_decoder = decoder();
+  ASSERT_NE(first_decoder, nullptr);
+
+  // Make a regular DemuxerStream::Read().
+  EXPECT_CALL(*demuxer_stream(), Read(_))
+      .WillOnce(RunCallback<0>(DemuxerStream::kOk, new DecoderBuffer(12)));
+  EXPECT_CALL(*decoder(), Decode(IsRegularDecoderBuffer(), _))
+      .WillOnce(Invoke(this, &AudioBufferStreamTest::ProduceDecoderOutput));
+  base::RunLoop run_loop0;
+  ReadAudioBuffer(run_loop0.QuitClosure());
+  run_loop0.Run();
+
+  // Make a config-change DemuxerStream::Read().
+  // Expect the decoder to be flushed.  Upon flushing, the decoder releases
+  // internally buffered output.
+  EXPECT_CALL(*demuxer_stream(), Read(_))
+      .WillOnce(RunCallback<0>(DemuxerStream::kConfigChanged, nullptr));
+  EXPECT_CALL(*decoder(), Decode(IsEOSDecoderBuffer(), _))
+      .WillOnce(Invoke(this, &AudioBufferStreamTest::ProduceDecoderOutput));
+  base::RunLoop run_loop1;
+  ReadAudioBuffer(run_loop1.QuitClosure());
+  run_loop1.Run();
+
+  // Expect the decoder to be re-initialized when AudioBufferStream finishes
+  // processing the last decode.
+  EXPECT_CALL(*decoder(), Initialize(_, _, _, _, _));
+  RunUntilIdle();
+}
+
+}  // namespace media
diff --git a/media/filters/decoder_stream.cc b/media/filters/decoder_stream.cc
index 09d6173..be0c71f 100644
--- a/media/filters/decoder_stream.cc
+++ b/media/filters/decoder_stream.cc
@@ -688,7 +688,6 @@
     pending_buffers_.clear();
 
     const DecoderConfig& config = traits_->GetDecoderConfig(stream_);
-    traits_->OnConfigChanged(config);
 
     MEDIA_LOG(INFO, media_log_)
         << GetStreamTypeString()
diff --git a/media/filters/decoder_stream_traits.cc b/media/filters/decoder_stream_traits.cc
index 707919d..df6f5f2 100644
--- a/media/filters/decoder_stream_traits.cc
+++ b/media/filters/decoder_stream_traits.cc
@@ -66,6 +66,11 @@
     const DecoderType::WaitingForDecryptionKeyCB&
         waiting_for_decryption_key_cb) {
   DCHECK(config.IsValidConfig());
+
+  if (config_.IsValidConfig() && !config_.Matches(config))
+    OnConfigChanged(config);
+  config_ = config;
+
   stats_.audio_decoder_name = decoder->GetDisplayName();
   decoder->Initialize(config, cdm_context, init_cb, output_cb,
                       waiting_for_decryption_key_cb);
diff --git a/media/filters/decoder_stream_traits.h b/media/filters/decoder_stream_traits.h
index ec3a2d4..62c1732 100644
--- a/media/filters/decoder_stream_traits.h
+++ b/media/filters/decoder_stream_traits.h
@@ -8,19 +8,18 @@
 #include "base/containers/flat_set.h"
 #include "base/time/time.h"
 #include "media/base/audio_decoder.h"
+#include "media/base/audio_decoder_config.h"
 #include "media/base/cdm_context.h"
 #include "media/base/channel_layout.h"
 #include "media/base/demuxer_stream.h"
 #include "media/base/moving_average.h"
 #include "media/base/pipeline_status.h"
 #include "media/base/video_decoder.h"
-#include "media/base/video_decoder_config.h"
 #include "media/filters/audio_timestamp_validator.h"
 
 namespace media {
 
 class AudioBuffer;
-class AudioDecoderConfig;
 class CdmContext;
 class DemuxerStream;
 class VideoDecoderConfig;
@@ -60,9 +59,10 @@
   void OnDecode(const DecoderBuffer& buffer);
   PostDecodeAction OnDecodeDone(const scoped_refptr<OutputType>& buffer);
   void OnStreamReset(DemuxerStream* stream);
-  void OnConfigChanged(const DecoderConfigType& config);
 
  private:
+  void OnConfigChanged(const AudioDecoderConfig& config);
+
   // Validates encoded timestamps match decoded output duration. MEDIA_LOG warns
   // if timestamp gaps are detected. Sufficiently large gaps can lead to AV sync
   // drift.
@@ -72,6 +72,7 @@
   // device changes.
   ChannelLayout initial_hw_layout_;
   PipelineStatistics stats_;
+  AudioDecoderConfig config_;
 };
 
 template <>
@@ -103,7 +104,6 @@
   void OnDecode(const DecoderBuffer& buffer);
   PostDecodeAction OnDecodeDone(const scoped_refptr<OutputType>& buffer);
   void OnStreamReset(DemuxerStream* stream);
-  void OnConfigChanged(const DecoderConfigType& config) {}
 
  private:
   base::TimeDelta last_keyframe_timestamp_;
diff --git a/media/renderers/renderer_impl.cc b/media/renderers/renderer_impl.cc
index 5233ddf..fe5bbdc 100644
--- a/media/renderers/renderer_impl.cc
+++ b/media/renderers/renderer_impl.cc
@@ -271,6 +271,7 @@
       return restarting_audio_time_;
     }
   }
+
   return time_source_->CurrentMediaTime();
 }
 
@@ -619,12 +620,12 @@
     return;
   }
 
-  audio_renderer_->StartPlaying();
   {
     base::AutoLock lock(restarting_audio_lock_);
     audio_playing_ = true;
     pending_audio_track_change_ = false;
   }
+  audio_renderer_->StartPlaying();
   std::move(restart_completed_cb).Run();
 }
 
@@ -646,9 +647,9 @@
     return;
   }
 
-  video_renderer_->StartPlayingFrom(time);
   video_playing_ = true;
   pending_video_track_change_ = false;
+  video_renderer_->StartPlayingFrom(time);
   std::move(restart_completed_cb).Run();
 }
 
@@ -904,15 +905,9 @@
 }
 
 void RendererImpl::CleanUpTrackChange(base::RepeatingClosure on_finished,
-                                      bool* pending_change,
                                       bool* ended,
                                       bool* playing) {
-  {
-    // This lock is required for setting pending_audio_track_change_, and has
-    // no effect when setting pending_video_track_change_.
-    base::AutoLock lock(restarting_audio_lock_);
-    *pending_change = *ended = *playing = false;
-  }
+  *ended = *playing = false;
   std::move(on_finished).Run();
 }
 
@@ -945,8 +940,7 @@
   pending_video_track_change_ = true;
   video_renderer_->Flush(base::BindRepeating(
       &RendererImpl::CleanUpTrackChange, weak_this_,
-      base::Passed(&fix_stream_cb), &pending_video_track_change_, &video_ended_,
-      &video_playing_));
+      base::Passed(&fix_stream_cb), &video_ended_, &video_playing_));
 }
 
 void RendererImpl::OnEnabledAudioTracksChanged(
@@ -987,8 +981,7 @@
 
   audio_renderer_->Flush(base::BindRepeating(
       &RendererImpl::CleanUpTrackChange, weak_this_,
-      base::Passed(&fix_stream_cb), &pending_audio_track_change_, &audio_ended_,
-      &audio_playing_));
+      base::Passed(&fix_stream_cb), &audio_ended_, &audio_playing_));
 }
 
 }  // namespace media
diff --git a/media/renderers/renderer_impl.h b/media/renderers/renderer_impl.h
index d50c928..e33e7268 100644
--- a/media/renderers/renderer_impl.h
+++ b/media/renderers/renderer_impl.h
@@ -148,7 +148,6 @@
 
   // Fix state booleans after the stream switching is finished.
   void CleanUpTrackChange(base::RepeatingClosure on_finished,
-                          bool* pending_change,
                           bool* ended,
                           bool* playing);
 
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 937545e..836f7cb8 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -2817,20 +2817,6 @@
     ]
   }
 
-  executable("gdig") {
-    testonly = true
-    sources = [
-      "tools/gdig/file_net_log.cc",
-      "tools/gdig/file_net_log.h",
-      "tools/gdig/gdig.cc",
-    ]
-    deps = [
-      ":net",
-      "//base",
-      "//build/win:default_exe_manifest",
-    ]
-  }
-
   executable("hpack_example_generator") {
     testonly = true
     sources = [
diff --git a/net/tools/gdig/file_net_log.cc b/net/tools/gdig/file_net_log.cc
deleted file mode 100644
index c160ae3..0000000
--- a/net/tools/gdig/file_net_log.cc
+++ /dev/null
@@ -1,50 +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 "net/tools/gdig/file_net_log.h"
-
-#include <stdio.h>
-
-#include <memory>
-
-#include "base/json/json_string_value_serializer.h"
-#include "base/logging.h"
-#include "base/values.h"
-#include "net/log/net_log_entry.h"
-
-namespace net {
-
-FileNetLogObserver::FileNetLogObserver(FILE* destination)
-    : destination_(destination) {
-  DCHECK(destination != NULL);
-}
-
-FileNetLogObserver::~FileNetLogObserver() = default;
-
-void FileNetLogObserver::OnAddEntry(const net::NetLogEntry& entry) {
-  // Only NetLogWithSources without a NetLog should have an invalid source.
-  DCHECK(entry.source().IsValid());
-
-  const char* source = NetLog::SourceTypeToString(entry.source().type);
-  const char* type = NetLog::EventTypeToString(entry.type());
-
-  std::unique_ptr<base::Value> param_value(entry.ParametersToValue());
-  std::string params;
-  if (param_value.get() != NULL) {
-    JSONStringValueSerializer serializer(&params);
-    bool ret = serializer.Serialize(*param_value);
-    DCHECK(ret);
-  }
-  base::Time now = base::Time::NowFromSystemTime();
-  base::AutoLock lock(lock_);
-  if (first_event_time_.is_null()) {
-    first_event_time_ = now;
-  }
-  base::TimeDelta elapsed_time = now - first_event_time_;
-  fprintf(destination_ , "%u\t%u\t%s\t%s\t%s\n",
-          static_cast<unsigned>(elapsed_time.InMilliseconds()),
-          entry.source().id, source, type, params.c_str());
-}
-
-}  // namespace net
diff --git a/net/tools/gdig/file_net_log.h b/net/tools/gdig/file_net_log.h
deleted file mode 100644
index 4d52f18..0000000
--- a/net/tools/gdig/file_net_log.h
+++ /dev/null
@@ -1,36 +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 NET_TOOLS_GDIG_FILE_NET_LOG_H_
-#define NET_TOOLS_GDIG_FILE_NET_LOG_H_
-
-#include <string>
-
-#include "base/synchronization/lock.h"
-#include "base/time/time.h"
-#include "net/log/net_log.h"
-
-namespace net {
-
-// FileNetLogObserver is a simple implementation of NetLog::ThreadSafeObserver
-// that prints out all the events received into the stream passed
-// to the constructor.
-class FileNetLogObserver : public NetLog::ThreadSafeObserver {
- public:
-  explicit FileNetLogObserver(FILE* destination);
-  ~FileNetLogObserver() override;
-
-  // NetLog::ThreadSafeObserver implementation:
-  void OnAddEntry(const net::NetLogEntry& entry) override;
-
- private:
-  FILE* const destination_;
-  base::Lock lock_;
-
-  base::Time first_event_time_;
-};
-
-}  // namespace net
-
-#endif  // NET_TOOLS_GDIG_FILE_NET_LOG_H_
diff --git a/net/tools/gdig/gdig.cc b/net/tools/gdig/gdig.cc
deleted file mode 100644
index 491744b1..0000000
--- a/net/tools/gdig/gdig.cc
+++ /dev/null
@@ -1,523 +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 <stdio.h>
-
-#include <memory>
-#include <string>
-#include <utility>
-
-#include "base/at_exit.h"
-#include "base/bind.h"
-#include "base/cancelable_callback.h"
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/location.h"
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_current.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "net/base/address_list.h"
-#include "net/base/ip_address.h"
-#include "net/base/ip_endpoint.h"
-#include "net/base/net_errors.h"
-#include "net/base/url_util.h"
-#include "net/dns/dns_client.h"
-#include "net/dns/dns_config_service.h"
-#include "net/dns/dns_protocol.h"
-#include "net/dns/host_cache.h"
-#include "net/dns/host_resolver_impl.h"
-#include "net/log/net_log.h"
-#include "net/log/net_log_capture_mode.h"
-#include "net/log/net_log_source_type.h"
-#include "net/log/net_log_with_source.h"
-#include "net/tools/gdig/file_net_log.h"
-
-#if defined(OS_MACOSX)
-#include "base/mac/scoped_nsautorelease_pool.h"
-#endif
-
-namespace net {
-
-namespace {
-
-bool StringToIPEndPoint(const std::string& ip_address_and_port,
-                        IPEndPoint* ip_end_point) {
-  DCHECK(ip_end_point);
-
-  std::string ip;
-  int port;
-  if (!ParseHostAndPort(ip_address_and_port, &ip, &port))
-    return false;
-  if (port == -1)
-    port = dns_protocol::kDefaultPort;
-
-  net::IPAddress ip_address;
-  if (!ip_address.AssignFromIPLiteral(ip))
-    return false;
-
-  *ip_end_point = net::IPEndPoint(ip_address, static_cast<uint16_t>(port));
-  return true;
-}
-
-// Convert DnsConfig to human readable text omitting the hosts member.
-std::string DnsConfigToString(const DnsConfig& dns_config) {
-  std::string output;
-  output.append("search ");
-  for (size_t i = 0; i < dns_config.search.size(); ++i) {
-    output.append(dns_config.search[i] + " ");
-  }
-  output.append("\n");
-
-  for (size_t i = 0; i < dns_config.nameservers.size(); ++i) {
-    output.append("nameserver ");
-    output.append(dns_config.nameservers[i].ToString()).append("\n");
-  }
-
-  base::StringAppendF(&output, "options ndots:%d\n", dns_config.ndots);
-  base::StringAppendF(&output, "options timeout:%d\n",
-                      static_cast<int>(dns_config.timeout.InMilliseconds()));
-  base::StringAppendF(&output, "options attempts:%d\n", dns_config.attempts);
-  if (dns_config.rotate)
-    output.append("options rotate\n");
-  return output;
-}
-
-// Convert DnsConfig hosts member to a human readable text.
-std::string DnsHostsToString(const DnsHosts& dns_hosts) {
-  std::string output;
-  for (DnsHosts::const_iterator i = dns_hosts.begin();
-       i != dns_hosts.end();
-       ++i) {
-    const DnsHostsKey& key = i->first;
-    std::string host_name = key.first;
-    output.append(IPEndPoint(i->second, 0).ToStringWithoutPort());
-    output.append(" ").append(host_name).append("\n");
-  }
-  return output;
-}
-
-struct ReplayLogEntry {
-  base::TimeDelta start_time;
-  std::string domain_name;
-};
-
-typedef std::vector<ReplayLogEntry> ReplayLog;
-
-// Loads and parses a replay log file and fills |replay_log| with a structured
-// representation. Returns whether the operation was successful. If not, the
-// contents of |replay_log| are undefined.
-//
-// The replay log is a text file where each line contains
-//
-//   timestamp_in_milliseconds domain_name
-//
-// The timestamp_in_milliseconds needs to be an integral delta from start of
-// resolution and is in milliseconds. domain_name is the name to be resolved.
-//
-// The file should be sorted by timestamp in ascending time.
-bool LoadReplayLog(const base::FilePath& file_path, ReplayLog* replay_log) {
-  std::string original_replay_log_contents;
-  if (!base::ReadFileToString(file_path, &original_replay_log_contents)) {
-    fprintf(stderr, "Unable to open replay file %s\n",
-            file_path.MaybeAsASCII().c_str());
-    return false;
-  }
-
-  // Strip out \r characters for Windows files. This isn't as efficient as a
-  // smarter line splitter, but this particular use does not need to target
-  // efficiency.
-  std::string replay_log_contents;
-  base::RemoveChars(original_replay_log_contents, "\r", &replay_log_contents);
-
-  std::vector<std::string> lines = base::SplitString(
-      replay_log_contents, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
-  base::TimeDelta previous_delta;
-  bool bad_parse = false;
-  for (unsigned i = 0; i < lines.size(); ++i) {
-    if (lines[i].empty())
-      continue;
-    std::vector<std::string> time_and_name = base::SplitString(
-        lines[i], " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
-    if (time_and_name.size() != 2) {
-      fprintf(
-          stderr,
-          "[%s %u] replay log should have format 'timestamp domain_name\\n'\n",
-          file_path.MaybeAsASCII().c_str(),
-          i + 1);
-      bad_parse = true;
-      continue;
-    }
-
-    int64_t delta_in_milliseconds;
-    if (!base::StringToInt64(time_and_name[0], &delta_in_milliseconds)) {
-      fprintf(
-          stderr,
-          "[%s %u] replay log should have format 'timestamp domain_name\\n'\n",
-          file_path.MaybeAsASCII().c_str(),
-          i + 1);
-      bad_parse = true;
-      continue;
-    }
-
-    base::TimeDelta delta =
-        base::TimeDelta::FromMilliseconds(delta_in_milliseconds);
-    if (delta < previous_delta) {
-      fprintf(
-          stderr,
-          "[%s %u] replay log should be sorted by time\n",
-          file_path.MaybeAsASCII().c_str(),
-          i + 1);
-      bad_parse = true;
-      continue;
-    }
-
-    previous_delta = delta;
-    ReplayLogEntry entry;
-    entry.start_time = delta;
-    entry.domain_name = time_and_name[1];
-    replay_log->push_back(entry);
-  }
-  return !bad_parse;
-}
-
-class GDig {
- public:
-  GDig();
-  ~GDig();
-
-  enum Result {
-    RESULT_NO_RESOLVE = -3,
-    RESULT_NO_CONFIG = -2,
-    RESULT_WRONG_USAGE = -1,
-    RESULT_OK = 0,
-    RESULT_PENDING = 1,
-  };
-
-  Result Main(int argc, const char* argv[]);
-
- private:
-  bool ParseCommandLine(int argc, const char* argv[]);
-
-  void Start();
-  void Finish(Result);
-
-  void OnDnsConfig(const DnsConfig& dns_config_const);
-  void OnResolveComplete(unsigned index, AddressList* address_list,
-                         base::TimeDelta time_since_start, int val);
-  void OnTimeout();
-  void ReplayNextEntry();
-
-  base::TimeDelta config_timeout_;
-  bool print_config_;
-  bool print_hosts_;
-  net::IPEndPoint nameserver_;
-  base::TimeDelta timeout_;
-  int parallellism_;
-  ReplayLog replay_log_;
-  unsigned replay_log_index_;
-  base::Time start_time_;
-  int active_resolves_;
-  Result result_;
-
-  base::CancelableClosure timeout_closure_;
-  std::unique_ptr<DnsConfigService> dns_config_service_;
-  std::unique_ptr<FileNetLogObserver> log_observer_;
-  std::unique_ptr<NetLog> log_;
-  std::unique_ptr<HostResolver> resolver_;
-  std::unique_ptr<HostResolver::Request> request_;
-
-#if defined(OS_MACOSX)
-  // Without this there will be a mem leak on osx.
-  base::mac::ScopedNSAutoreleasePool scoped_pool_;
-#endif
-
-  // Need AtExitManager to support AsWeakPtr (in NetLog).
-  base::AtExitManager exit_manager_;
-};
-
-GDig::GDig()
-    : config_timeout_(base::TimeDelta::FromSeconds(5)),
-      print_config_(false),
-      print_hosts_(false),
-      parallellism_(6),
-      replay_log_index_(0u),
-      active_resolves_(0) {
-}
-
-GDig::~GDig() {
-  if (log_)
-    log_->RemoveObserver(log_observer_.get());
-}
-
-GDig::Result GDig::Main(int argc, const char* argv[]) {
-  if (!ParseCommandLine(argc, argv)) {
-      fprintf(stderr,
-              "usage: %s [--net_log[=<basic|no_bytes|all>]]"
-              " [--print_config] [--print_hosts]"
-              " [--nameserver=<ip_address[:port]>]"
-              " [--timeout=<milliseconds>]"
-              " [--config_timeout=<seconds>]"
-              " [--j=<parallel resolves>]"
-              " [--replay_file=<path>]"
-              " [domain_name]\n",
-              argv[0]);
-      return RESULT_WRONG_USAGE;
-  }
-
-  base::MessageLoopForIO loop;
-
-  result_ = RESULT_PENDING;
-  Start();
-  if (result_ == RESULT_PENDING)
-    base::RunLoop().Run();
-
-  // Destroy it while MessageLoopForIO is alive.
-  dns_config_service_.reset();
-  return result_;
-}
-
-bool GDig::ParseCommandLine(int argc, const char* argv[]) {
-  base::CommandLine::Init(argc, argv);
-  const base::CommandLine& parsed_command_line =
-      *base::CommandLine::ForCurrentProcess();
-
-  if (parsed_command_line.HasSwitch("config_timeout")) {
-    int timeout_seconds = 0;
-    bool parsed = base::StringToInt(
-        parsed_command_line.GetSwitchValueASCII("config_timeout"),
-        &timeout_seconds);
-    if (parsed && timeout_seconds > 0) {
-      config_timeout_ = base::TimeDelta::FromSeconds(timeout_seconds);
-    } else {
-      fprintf(stderr, "Invalid config_timeout parameter\n");
-      return false;
-    }
-  }
-
-  if (parsed_command_line.HasSwitch("net_log")) {
-    std::string log_param = parsed_command_line.GetSwitchValueASCII("net_log");
-    NetLogCaptureMode capture_mode =
-        NetLogCaptureMode::IncludeCookiesAndCredentials();
-
-    if (log_param.length() > 0) {
-      std::map<std::string, NetLogCaptureMode> capture_modes;
-      capture_modes["all"] = NetLogCaptureMode::IncludeSocketBytes();
-      capture_modes["no_bytes"] =
-          NetLogCaptureMode::IncludeCookiesAndCredentials();
-
-      if (capture_modes.find(log_param) != capture_modes.end()) {
-        capture_mode = capture_modes[log_param];
-      } else {
-        fprintf(stderr, "Invalid net_log parameter\n");
-        return false;
-      }
-    }
-    log_.reset(new NetLog);
-    log_observer_.reset(new FileNetLogObserver(stderr));
-    log_->AddObserver(log_observer_.get(), capture_mode);
-  }
-
-  print_config_ = parsed_command_line.HasSwitch("print_config");
-  print_hosts_ = parsed_command_line.HasSwitch("print_hosts");
-
-  if (parsed_command_line.HasSwitch("nameserver")) {
-    std::string nameserver =
-      parsed_command_line.GetSwitchValueASCII("nameserver");
-    if (!StringToIPEndPoint(nameserver, &nameserver_)) {
-      fprintf(stderr,
-              "Cannot parse the nameserver string into an IPEndPoint\n");
-      return false;
-    }
-  }
-
-  if (parsed_command_line.HasSwitch("timeout")) {
-    int timeout_millis = 0;
-    bool parsed = base::StringToInt(
-        parsed_command_line.GetSwitchValueASCII("timeout"),
-        &timeout_millis);
-    if (parsed && timeout_millis > 0) {
-      timeout_ = base::TimeDelta::FromMilliseconds(timeout_millis);
-    } else {
-      fprintf(stderr, "Invalid timeout parameter\n");
-      return false;
-    }
-  }
-
-  if (parsed_command_line.HasSwitch("replay_file")) {
-    base::FilePath replay_path =
-        parsed_command_line.GetSwitchValuePath("replay_file");
-    if (!LoadReplayLog(replay_path, &replay_log_))
-      return false;
-  }
-
-  if (parsed_command_line.HasSwitch("j")) {
-    int parallellism = 0;
-    bool parsed = base::StringToInt(
-        parsed_command_line.GetSwitchValueASCII("j"),
-        &parallellism);
-    if (parsed && parallellism > 0) {
-      parallellism_ = parallellism;
-    } else {
-      fprintf(stderr, "Invalid parallellism parameter\n");
-    }
-  }
-
-  if (parsed_command_line.GetArgs().size() == 1) {
-    ReplayLogEntry entry;
-    entry.start_time = base::TimeDelta();
-#if defined(OS_WIN)
-    entry.domain_name = base::UTF16ToASCII(parsed_command_line.GetArgs()[0]);
-#else
-    entry.domain_name = parsed_command_line.GetArgs()[0];
-#endif
-    replay_log_.push_back(entry);
-  } else if (parsed_command_line.GetArgs().size() != 0) {
-    return false;
-  }
-  return print_config_ || print_hosts_ || !replay_log_.empty();
-}
-
-void GDig::Start() {
-  if (nameserver_.address().size() > 0) {
-    DnsConfig dns_config;
-    dns_config.attempts = 1;
-    dns_config.nameservers.push_back(nameserver_);
-    OnDnsConfig(dns_config);
-  } else {
-    dns_config_service_ = DnsConfigService::CreateSystemService();
-    dns_config_service_->ReadConfig(base::Bind(&GDig::OnDnsConfig,
-                                               base::Unretained(this)));
-    timeout_closure_.Reset(base::Bind(&GDig::OnTimeout,
-                                      base::Unretained(this)));
-    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-        FROM_HERE, timeout_closure_.callback(), config_timeout_);
-  }
-}
-
-void GDig::Finish(Result result) {
-  DCHECK_NE(RESULT_PENDING, result);
-  result_ = result;
-  if (base::MessageLoopCurrent::Get())
-    base::RunLoop::QuitCurrentWhenIdleDeprecated();
-}
-
-void GDig::OnDnsConfig(const DnsConfig& dns_config_const) {
-  timeout_closure_.Cancel();
-  DCHECK(dns_config_const.IsValid());
-  DnsConfig dns_config = dns_config_const;
-
-  if (timeout_.InMilliseconds() > 0)
-    dns_config.timeout = timeout_;
-  if (print_config_) {
-    printf("# Dns Configuration\n"
-           "%s", DnsConfigToString(dns_config).c_str());
-  }
-  if (print_hosts_) {
-    printf("# Host Database\n"
-           "%s", DnsHostsToString(dns_config.hosts).c_str());
-  }
-
-  if (replay_log_.empty()) {
-    Finish(RESULT_OK);
-    return;
-  }
-
-  std::unique_ptr<DnsClient> dns_client(DnsClient::CreateClient(NULL));
-  dns_client->SetConfig(dns_config);
-  HostResolver::Options options;
-  options.max_concurrent_resolves = parallellism_;
-  options.max_retry_attempts = 1u;
-  std::unique_ptr<HostResolverImpl> resolver(
-      new HostResolverImpl(options, log_.get()));
-  resolver->SetDnsClient(std::move(dns_client));
-  resolver_ = std::move(resolver);
-
-  start_time_ = base::Time::Now();
-
-  ReplayNextEntry();
-}
-
-void GDig::ReplayNextEntry() {
-  DCHECK_LT(replay_log_index_, replay_log_.size());
-
-  base::TimeDelta time_since_start = base::Time::Now() - start_time_;
-  while (replay_log_index_ < replay_log_.size()) {
-    const ReplayLogEntry& entry = replay_log_[replay_log_index_];
-    if (time_since_start < entry.start_time) {
-      // Delay call to next time and return.
-      base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-          FROM_HERE, base::Bind(&GDig::ReplayNextEntry, base::Unretained(this)),
-          entry.start_time - time_since_start);
-      return;
-    }
-
-    HostResolver::RequestInfo info(HostPortPair(entry.domain_name.c_str(), 80));
-    AddressList* addrlist = new AddressList();
-    unsigned current_index = replay_log_index_;
-    CompletionCallback callback = base::Bind(&GDig::OnResolveComplete,
-                                             base::Unretained(this),
-                                             current_index,
-                                             base::Owned(addrlist),
-                                             time_since_start);
-    ++active_resolves_;
-    ++replay_log_index_;
-    int ret = resolver_->Resolve(
-        info, DEFAULT_PRIORITY, addrlist, callback, &request_,
-        NetLogWithSource::Make(log_.get(), net::NetLogSourceType::NONE));
-    if (ret != ERR_IO_PENDING)
-      callback.Run(ret);
-  }
-}
-
-void GDig::OnResolveComplete(unsigned entry_index,
-                             AddressList* address_list,
-                             base::TimeDelta resolve_start_time,
-                             int val) {
-  DCHECK_GT(active_resolves_, 0);
-  DCHECK(address_list);
-  DCHECK_LT(entry_index, replay_log_.size());
-  --active_resolves_;
-  base::TimeDelta resolve_end_time = base::Time::Now() - start_time_;
-  base::TimeDelta resolve_time = resolve_end_time - resolve_start_time;
-  printf("%u %d %d %s %d ",
-         entry_index,
-         static_cast<int>(resolve_end_time.InMilliseconds()),
-         static_cast<int>(resolve_time.InMilliseconds()),
-         replay_log_[entry_index].domain_name.c_str(), val);
-  if (val != OK) {
-    std::string error_string = ErrorToString(val);
-    printf("%s", error_string.c_str());
-  } else {
-    for (size_t i = 0; i < address_list->size(); ++i) {
-      if (i != 0)
-        printf(" ");
-      printf("%s", (*address_list)[i].ToStringWithoutPort().c_str());
-    }
-  }
-  printf("\n");
-  if (active_resolves_ == 0 && replay_log_index_ >= replay_log_.size())
-    Finish(RESULT_OK);
-}
-
-void GDig::OnTimeout() {
-  fprintf(stderr, "Timed out waiting to load the dns config\n");
-  Finish(RESULT_NO_CONFIG);
-}
-
-}  // empty namespace
-
-}  // namespace net
-
-int main(int argc, const char* argv[]) {
-  net::GDig dig;
-  return dig.Main(argc, argv);
-}
diff --git a/pdf/pdf.cc b/pdf/pdf.cc
index 208e5e7..d824a06d 100644
--- a/pdf/pdf.cc
+++ b/pdf/pdf.cc
@@ -6,6 +6,8 @@
 
 #include <stdint.h>
 
+#include <utility>
+
 #if defined(OS_WIN)
 #include <windows.h>
 #endif
@@ -143,4 +145,37 @@
       pdf_buffer, pdf_buffer_size, page_number, settings, bitmap_buffer);
 }
 
+bool ConvertPdfPagesToNupPdf(
+    std::vector<base::span<const uint8_t>> input_buffers,
+    size_t pages_per_sheet,
+    size_t page_size_width,
+    size_t page_size_height,
+    void** dest_pdf_buffer,
+    size_t* dest_pdf_buffer_size) {
+  ScopedSdkInitializer scoped_sdk_initializer;
+  if (!scoped_sdk_initializer.Init())
+    return false;
+
+  PDFEngineExports* engine_exports = PDFEngineExports::Get();
+  return engine_exports->ConvertPdfPagesToNupPdf(
+      std::move(input_buffers), pages_per_sheet, page_size_width,
+      page_size_height, dest_pdf_buffer, dest_pdf_buffer_size);
+}
+
+bool ConvertPdfDocumentToNupPdf(base::span<const uint8_t> input_buffer,
+                                size_t pages_per_sheet,
+                                size_t page_size_width,
+                                size_t page_size_height,
+                                void** dest_pdf_buffer,
+                                size_t* dest_pdf_buffer_size) {
+  ScopedSdkInitializer scoped_sdk_initializer;
+  if (!scoped_sdk_initializer.Init())
+    return false;
+
+  PDFEngineExports* engine_exports = PDFEngineExports::Get();
+  return engine_exports->ConvertPdfDocumentToNupPdf(
+      input_buffer, pages_per_sheet, page_size_width, page_size_height,
+      dest_pdf_buffer, dest_pdf_buffer_size);
+}
+
 }  // namespace chrome_pdf
diff --git a/pdf/pdf.h b/pdf/pdf.h
index ddd286d..bc36bb51 100644
--- a/pdf/pdf.h
+++ b/pdf/pdf.h
@@ -5,6 +5,9 @@
 #ifndef PDF_PDF_H_
 #define PDF_PDF_H_
 
+#include <vector>
+
+#include "base/containers/span.h"
 #include "build/build_config.h"
 
 #if defined(OS_WIN)
@@ -126,6 +129,59 @@
                            bool autorotate,
                            bool use_color);
 
+// Convert multiple PDF pages into a N-up PDF.
+// |input_buffers| is the vector of buffers with each buffer contains a PDF.
+//     If any of the PDFs contains multiple pages, only the first page of the
+//     document is used.
+// |pages_per_sheet| is the number of pages to put on one sheet.
+// |page_size_width| is the width of the output page size, measured in PDF
+//     "user space" units.
+// |page_size_height| is the height of the output page size, measured in PDF
+//     "user space" units.
+// |dest_pdf_buffer| is the output N-up PDF page.  Caller takes ownership, and
+//     needs to free the memory.
+// |dest_pdf_buffer_size| is the size of output N-up PDF page.
+//
+// |page_size_width| and |page_size_height| are the print media size.  The page
+// size of the output N-up PDF is determined by the |pages_per_sheet|, the
+// orientation of the PDF pages contained in the |input_buffers|, and the media
+// page size |page_size_width| and |page_size_height|.  For example, when
+// |page_size_width| = 512, |page_size_height| = 792, |pages_per_sheet| = 2, and
+// the orientation of |input_buffers| = portrait, the output N-up PDF will have
+// |page_size_width| = 792, and |page_size_height| = 512.
+// See printing::NupParameters for more details on how the output page
+// orientation is determined, to understand why |page_size_width| and
+// |page_size_height| may be swapped in some cases.
+bool ConvertPdfPagesToNupPdf(
+    std::vector<base::span<const uint8_t>> input_buffers,
+    size_t pages_per_sheet,
+    size_t page_size_width,
+    size_t page_size_height,
+    void** dest_pdf_buffer,
+    size_t* dest_pdf_buffer_size);
+
+// Convert a PDF document to a N-up PDF document.
+// |input_buffer| is the buffer that contains the entire PDF document to be
+//     converted to a N-up PDF document.
+// |pages_per_sheet| is the number of pages to put on one sheet.
+// |page_size_width| is the width of the media page size, measured in PDF
+//     "user space" units.
+// |page_size_height| is the height of the media page size, measured in PDF
+//     "user space" units.
+// |dest_pdf_buffer| is the output N-up PDF page.  Caller takes ownership, and
+//     needs to free the memory.
+// |dest_pdf_buffer_size| is the size of output N-up PDF document.
+//
+// Refer to the description of ConvertPdfPagesToNupPdf to understand how the
+// output page size |page_size_width| and |page_size_height| will be calculated.
+// The algorithm used to determine the output page size is the same.
+bool ConvertPdfDocumentToNupPdf(base::span<const uint8_t> input_buffer,
+                                size_t pages_per_sheet,
+                                size_t page_size_width,
+                                size_t page_size_height,
+                                void** dest_pdf_buffer,
+                                size_t* dest_pdf_buffer_size);
+
 }  // namespace chrome_pdf
 
 #endif  // PDF_PDF_H_
diff --git a/pdf/pdf_engine.h b/pdf/pdf_engine.h
index b8be454..1e4dc14 100644
--- a/pdf/pdf_engine.h
+++ b/pdf/pdf_engine.h
@@ -18,6 +18,7 @@
 #include <string>
 #include <vector>
 
+#include "base/containers/span.h"
 #include "base/optional.h"
 #include "base/strings/string16.h"
 #include "base/time/time.h"
@@ -464,6 +465,24 @@
                                      const RenderingSettings& settings,
                                      void* bitmap_buffer) = 0;
 
+  // See the definition of ConvertPdfPagesToNupPdf in pdf.cc for details.
+  virtual bool ConvertPdfPagesToNupPdf(
+      std::vector<base::span<const uint8_t>> input_buffers,
+      size_t pages_per_sheet,
+      size_t page_size_width,
+      size_t page_size_height,
+      void** dest_pdf_buffer,
+      size_t* dest_pdf_buffer_size) = 0;
+
+  // See the definition of ConvertPdfDocumentToNupPdf in pdf.cc for details.
+  virtual bool ConvertPdfDocumentToNupPdf(
+      base::span<const uint8_t> input_buffer,
+      size_t pages_per_sheet,
+      size_t page_size_width,
+      size_t page_size_height,
+      void** dest_pdf_buffer,
+      size_t* dest_pdf_buffer_size) = 0;
+
   virtual bool GetPDFDocInfo(const void* pdf_buffer,
                              int buffer_size,
                              int* page_count,
diff --git a/pdf/pdfium/pdfium_engine_exports.cc b/pdf/pdfium/pdfium_engine_exports.cc
index e6c94fb..2dcfc55 100644
--- a/pdf/pdfium/pdfium_engine_exports.cc
+++ b/pdf/pdfium/pdfium_engine_exports.cc
@@ -8,8 +8,13 @@
 #include <utility>
 
 #include "base/no_destructor.h"
+#include "base/numerics/safe_conversions.h"
+#include "pdf/pdfium/pdfium_mem_buffer_file_write.h"
+#include "pdf/pdfium/pdfium_print.h"
+#include "printing/nup_parameters.h"
 #include "printing/units.h"
 #include "third_party/pdfium/public/cpp/fpdf_scopers.h"
+#include "third_party/pdfium/public/fpdf_ppo.h"
 #include "third_party/pdfium/public/fpdfview.h"
 
 using printing::ConvertUnitDouble;
@@ -89,6 +94,66 @@
   return rotate;
 }
 
+ScopedFPDFDocument LoadPdfData(base::span<const uint8_t> pdf_buffer) {
+  ScopedFPDFDocument doc;
+  if (base::IsValueInRangeForNumericType<int>(pdf_buffer.size())) {
+    doc.reset(
+        FPDF_LoadMemDocument(pdf_buffer.data(), pdf_buffer.size(), nullptr));
+  }
+  return doc;
+}
+
+ScopedFPDFDocument CreatePdfDoc(
+    std::vector<base::span<const uint8_t>> input_buffers) {
+  ScopedFPDFDocument doc(FPDF_CreateNewDocument());
+
+  size_t index = 0;
+  for (auto input_buffer : input_buffers) {
+    ScopedFPDFDocument single_page_doc = LoadPdfData(input_buffer);
+    if (!FPDF_ImportPages(doc.get(), single_page_doc.get(), "1", index++)) {
+      return nullptr;
+    }
+  }
+
+  return doc;
+}
+
+bool CreateNupPdfDocument(FPDF_DOCUMENT doc,
+                          size_t pages_per_sheet,
+                          size_t page_size_width,
+                          size_t page_size_height,
+                          void** dest_pdf_buffer,
+                          size_t* dest_pdf_buffer_size) {
+  if (!dest_pdf_buffer || !dest_pdf_buffer_size)
+    return false;
+
+  printing::NupParameters nup_params;
+  bool is_landscape = PDFiumPrint::IsSourcePdfLandscape(doc);
+  nup_params.SetParameters(pages_per_sheet, is_landscape);
+  bool paper_is_landscape = page_size_width > page_size_height;
+  if (nup_params.landscape() != paper_is_landscape)
+    std::swap(page_size_width, page_size_height);
+
+  ScopedFPDFDocument output_doc_nup(FPDF_ImportNPagesToOne(
+      doc, page_size_width, page_size_height, nup_params.num_pages_on_x_axis(),
+      nup_params.num_pages_on_y_axis()));
+
+  if (!output_doc_nup)
+    return false;
+
+  // Copy data to the |dest_pdf_buffer| here.
+  // TODO(thestig): Avoid this copy.
+  PDFiumMemBufferFileWrite output_file_write;
+  if (!FPDF_SaveAsCopy(output_doc_nup.get(), &output_file_write, 0)) {
+    return false;
+  }
+  *dest_pdf_buffer = malloc(output_file_write.size());
+  memcpy(*dest_pdf_buffer, output_file_write.buffer().c_str(),
+         output_file_write.size());
+  *dest_pdf_buffer_size = output_file_write.size();
+  return true;
+}
+
 }  // namespace
 
 PDFEngineExports::RenderingSettings::RenderingSettings(int dpi_x,
@@ -245,6 +310,38 @@
   return true;
 }
 
+bool PDFiumEngineExports::ConvertPdfPagesToNupPdf(
+    std::vector<base::span<const uint8_t>> input_buffers,
+    size_t pages_per_sheet,
+    size_t page_size_width,
+    size_t page_size_height,
+    void** dest_pdf_buffer,
+    size_t* dest_pdf_buffer_size) {
+  ScopedFPDFDocument doc = CreatePdfDoc(std::move(input_buffers));
+  if (!doc)
+    return false;
+
+  return CreateNupPdfDocument(doc.get(), pages_per_sheet, page_size_width,
+                              page_size_height, dest_pdf_buffer,
+                              dest_pdf_buffer_size);
+}
+
+bool PDFiumEngineExports::ConvertPdfDocumentToNupPdf(
+    base::span<const uint8_t> input_buffer,
+    size_t pages_per_sheet,
+    size_t page_size_width,
+    size_t page_size_height,
+    void** dest_pdf_buffer,
+    size_t* dest_pdf_buffer_size) {
+  ScopedFPDFDocument doc = LoadPdfData(input_buffer);
+  if (!doc)
+    return false;
+
+  return CreateNupPdfDocument(doc.get(), pages_per_sheet, page_size_width,
+                              page_size_height, dest_pdf_buffer,
+                              dest_pdf_buffer_size);
+}
+
 bool PDFiumEngineExports::GetPDFDocInfo(const void* pdf_buffer,
                                         int buffer_size,
                                         int* page_count,
diff --git a/pdf/pdfium/pdfium_engine_exports.h b/pdf/pdfium/pdfium_engine_exports.h
index b37de82..3a23d85 100644
--- a/pdf/pdfium/pdfium_engine_exports.h
+++ b/pdf/pdfium/pdfium_engine_exports.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include "base/containers/span.h"
 #include "build/build_config.h"
 #include "pdf/pdf_engine.h"
 
@@ -36,6 +37,19 @@
                              int page_number,
                              const RenderingSettings& settings,
                              void* bitmap_buffer) override;
+  bool ConvertPdfPagesToNupPdf(
+      std::vector<base::span<const uint8_t>> input_buffers,
+      size_t pages_per_sheet,
+      size_t page_size_width,
+      size_t page_size_height,
+      void** dest_pdf_buffer,
+      size_t* dest_pdf_buffer_size) override;
+  bool ConvertPdfDocumentToNupPdf(base::span<const uint8_t> input_buffer,
+                                  size_t pages_per_sheet,
+                                  size_t page_size_width,
+                                  size_t page_size_height,
+                                  void** dest_pdf_buffer,
+                                  size_t* dest_pdf_buffer_size) override;
   bool GetPDFDocInfo(const void* pdf_buffer,
                      int buffer_size,
                      int* page_count,
diff --git a/pdf/pdfium/pdfium_engine_exports_unittest.cc b/pdf/pdfium/pdfium_engine_exports_unittest.cc
index fe83add7..818dfc6c 100644
--- a/pdf/pdfium/pdfium_engine_exports_unittest.cc
+++ b/pdf/pdfium/pdfium_engine_exports_unittest.cc
@@ -98,4 +98,74 @@
   }
 }
 
+TEST_F(PDFiumEngineExportsTest, ConvertPdfPagesToNupPdf) {
+  base::FilePath pdf_path =
+      pdf_data_dir().Append(FILE_PATH_LITERAL("rectangles.pdf"));
+  std::string pdf_data;
+  ASSERT_TRUE(base::ReadFileToString(pdf_path, &pdf_data));
+
+  std::vector<base::span<const uint8_t>> pdf_buffers;
+
+  EXPECT_FALSE(
+      ConvertPdfPagesToNupPdf(pdf_buffers, 1, 512, 792, nullptr, nullptr));
+
+  pdf_buffers.push_back(base::as_bytes(base::make_span(pdf_data)));
+  pdf_buffers.push_back(base::as_bytes(base::make_span(pdf_data)));
+
+  void* output_pdf_buffer;
+  size_t output_pdf_buffer_size;
+  ASSERT_TRUE(ConvertPdfPagesToNupPdf(
+      pdf_buffers, 2, 512, 792, &output_pdf_buffer, &output_pdf_buffer_size));
+  ASSERT_GT(output_pdf_buffer_size, 0U);
+  ASSERT_NE(output_pdf_buffer, nullptr);
+  int page_count;
+  ASSERT_TRUE(GetPDFDocInfo(output_pdf_buffer, output_pdf_buffer_size,
+                            &page_count, nullptr));
+  ASSERT_EQ(1, page_count);
+
+  double width;
+  double height;
+  ASSERT_TRUE(GetPDFPageSizeByIndex(output_pdf_buffer, output_pdf_buffer_size,
+                                    0, &width, &height));
+  EXPECT_DOUBLE_EQ(792.0, width);
+  EXPECT_DOUBLE_EQ(512.0, height);
+
+  free(output_pdf_buffer);
+}
+
+TEST_F(PDFiumEngineExportsTest, ConvertPdfDocumentToNupPdf) {
+  base::FilePath pdf_path =
+      pdf_data_dir().Append(FILE_PATH_LITERAL("rectangles_multi_pages.pdf"));
+  std::string pdf_data;
+  ASSERT_TRUE(base::ReadFileToString(pdf_path, &pdf_data));
+
+  base::span<const uint8_t> pdf_buffer;
+
+  EXPECT_FALSE(
+      ConvertPdfDocumentToNupPdf(pdf_buffer, 1, 512, 792, nullptr, nullptr));
+
+  pdf_buffer = base::as_bytes(base::make_span(pdf_data));
+
+  void* output_pdf_buffer;
+  size_t output_pdf_buffer_size;
+  ASSERT_TRUE(ConvertPdfDocumentToNupPdf(
+      pdf_buffer, 4, 512, 792, &output_pdf_buffer, &output_pdf_buffer_size));
+  ASSERT_GT(output_pdf_buffer_size, 0U);
+  ASSERT_NE(output_pdf_buffer, nullptr);
+  int page_count;
+  ASSERT_TRUE(GetPDFDocInfo(output_pdf_buffer, output_pdf_buffer_size,
+                            &page_count, nullptr));
+  ASSERT_EQ(2, page_count);
+  for (int page_number = 0; page_number < page_count; ++page_number) {
+    double width;
+    double height;
+    ASSERT_TRUE(GetPDFPageSizeByIndex(output_pdf_buffer, output_pdf_buffer_size,
+                                      page_number, &width, &height));
+    EXPECT_DOUBLE_EQ(512.0, width);
+    EXPECT_DOUBLE_EQ(792.0, height);
+  }
+
+  free(output_pdf_buffer);
+}
+
 }  // namespace chrome_pdf
diff --git a/pdf/pdfium/pdfium_print.cc b/pdf/pdfium/pdfium_print.cc
index ea3e2f37..9dc4709 100644
--- a/pdf/pdfium/pdfium_print.cc
+++ b/pdf/pdfium/pdfium_print.cc
@@ -37,24 +37,6 @@
   return pages_per_sheet > 1;
 }
 
-// Check the source doc orientation.  Returns true if the doc is landscape.
-// For now the orientation of the doc is determined by its first page's
-// orientation.  Improvement can be added in the future to better determine the
-// orientation of the source docs that have mixed orientation.
-// TODO(xlou): rotate pages if the source doc has mixed orientation.  So that
-// the orientation of all pages of the doc are uniform.  Pages of square size
-// will not be rotated.
-bool IsSourcePdfLandscape(FPDF_DOCUMENT doc) {
-  DCHECK(doc);
-
-  ScopedFPDFPage pdf_page(FPDF_LoadPage(doc, 0));
-  DCHECK(pdf_page);
-
-  bool is_source_landscape =
-      FPDF_GetPageWidth(pdf_page.get()) > FPDF_GetPageHeight(pdf_page.get());
-  return is_source_landscape;
-}
-
 // Set the destination page size and content area in points based on source
 // page rotation and orientation.
 //
@@ -235,6 +217,17 @@
   return page_numbers;
 }
 
+bool PDFiumPrint::IsSourcePdfLandscape(FPDF_DOCUMENT doc) {
+  DCHECK(doc);
+
+  ScopedFPDFPage pdf_page(FPDF_LoadPage(doc, 0));
+  DCHECK(pdf_page);
+
+  bool is_source_landscape =
+      FPDF_GetPageWidth(pdf_page.get()) > FPDF_GetPageHeight(pdf_page.get());
+  return is_source_landscape;
+}
+
 pp::Buffer_Dev PDFiumPrint::PrintPagesAsRasterPDF(
     const PP_PrintPageNumberRange_Dev* page_ranges,
     uint32_t page_range_count,
diff --git a/pdf/pdfium/pdfium_print.h b/pdf/pdfium/pdfium_print.h
index c0df7d9..5405a1f 100644
--- a/pdf/pdfium/pdfium_print.h
+++ b/pdf/pdfium/pdfium_print.h
@@ -40,6 +40,15 @@
       const PP_PrintSettings_Dev& print_settings,
       const PP_PdfPrintSettings_Dev& pdf_print_settings);
 
+  // Check the source doc orientation.  Returns true if the doc is landscape.
+  // For now the orientation of the doc is determined by its first page's
+  // orientation.  Improvement can be added in the future to better determine
+  // the orientation of the source docs that have mixed orientation.
+  // TODO(xlou): rotate pages if the source doc has mixed orientation.  So that
+  // the orientation of all pages of the doc are uniform.  Pages of square size
+  // will not be rotated.
+  static bool IsSourcePdfLandscape(FPDF_DOCUMENT doc);
+
  private:
   FPDF_DOCUMENT CreateSinglePageRasterPdf(
       double source_page_width,
diff --git a/pdf/test/data/rectangles.pdf b/pdf/test/data/rectangles.pdf
new file mode 100644
index 0000000..7bad251b
--- /dev/null
+++ b/pdf/test/data/rectangles.pdf
@@ -0,0 +1,50 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+endobj
+2 0 obj <<
+  /Type /Pages
+  /MediaBox [ 0 0 200 300 ]
+  /Count 1
+  /Kids [ 3 0 R ]
+>>
+endobj
+3 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /Contents 4 0 R
+>>
+endobj
+4 0 obj <<
+>>
+stream
+q
+0 0 0 rg
+0 290 10 10 re B*
+10 150 50 30 re B*
+0 0 1 rg
+190 290 10 10 re B*
+70 232 50 30 re B*
+0 1 0 rg
+190 0 10 10 re B*
+130 150 50 30 re B*
+1 0 0 rg
+0 0 10 10 re B*
+70 67 50 30 re B*
+Q
+endstream
+endobj
+xref
+0 5
+0000000000 65535 f 
+0000000015 00000 n 
+0000000068 00000 n 
+0000000161 00000 n 
+0000000230 00000 n 
+trailer<< /Root 1 0 R /Size 5 >>
+startxref
+456
+%%EOF
diff --git a/pdf/test/data/rectangles_multi_pages.pdf b/pdf/test/data/rectangles_multi_pages.pdf
new file mode 100644
index 0000000..22d44a4
--- /dev/null
+++ b/pdf/test/data/rectangles_multi_pages.pdf
@@ -0,0 +1,122 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+endobj
+2 0 obj <<
+  /Type /Pages
+  /MediaBox [ 0 0 200 250 ]
+  /Count 5
+  /Kids [ 3 0 R 5 0 R 7 0 R 9 0 R 11 0 R ]
+>>
+endobj
+3 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /Contents 4 0 R
+>>
+endobj
+4 0 obj <<
+  /Length 49
+>>
+stream
+q
+1 1 0 rg
+100 0 30 50 re B*
+70 67 50 30 re B*
+Q
+endstream
+endobj
+5 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /Rotate 90
+  /Contents 6 0 R
+>>
+endobj
+6 0 obj <<
+  /Length 49
+>>
+stream
+q
+0 1 1 rg
+100 0 30 50 re B*
+70 67 50 30 re B*
+Q
+endstream
+endobj
+7 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /Contents 8 0 R
+>>
+endobj
+8 0 obj <<
+  /Length 49
+>>
+stream
+q
+1 0 0 rg
+100 0 30 50 re B*
+70 67 50 30 re B*
+Q
+endstream
+endobj
+9 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /Contents 10 0 R
+>>
+endobj
+10 0 obj <<
+  /Length 51
+>>
+stream
+q
+0 1 0 rg
+100 0 30 50 re B*
+100 150 50 30 re B*
+Q
+endstream
+endobj
+11 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /Contents 12 0 R
+>>
+endobj
+12 0 obj <<
+  /Length 50
+>>
+stream
+q
+0 0 0 rg
+0 90 80 60 re B*
+100 150 50 30 re B*
+Q
+endstream
+endobj
+xref
+0 13
+0000000000 65535 f 
+0000000015 00000 n 
+0000000068 00000 n 
+0000000186 00000 n 
+0000000255 00000 n 
+0000000355 00000 n 
+0000000437 00000 n 
+0000000537 00000 n 
+0000000606 00000 n 
+0000000706 00000 n 
+0000000776 00000 n 
+0000000879 00000 n 
+0000000950 00000 n 
+trailer <<
+  /Root 1 0 R
+  /Size 13
+>>
+startxref
+1052
+%%EOF
diff --git a/services/network/cors/cors_url_loader.cc b/services/network/cors/cors_url_loader.cc
index 5a66d8c..d4afb95 100644
--- a/services/network/cors/cors_url_loader.cc
+++ b/services/network/cors/cors_url_loader.cc
@@ -125,10 +125,6 @@
     const base::Optional<std::vector<std::string>>&
         to_be_removed_request_headers,
     const base::Optional<net::HttpRequestHeaders>& modified_request_headers) {
-  DCHECK(!to_be_removed_request_headers.has_value());
-  DCHECK(!modified_request_headers.has_value()) << "Redirect with modified "
-                                                   "headers was not supported "
-                                                   "yet. crbug.com/845683";
   if (!network_loader_ || !is_waiting_follow_redirect_call_) {
     HandleComplete(URLLoaderCompletionStatus(net::ERR_FAILED));
     return;
@@ -142,6 +138,13 @@
     return;
   }
 
+  if (to_be_removed_request_headers) {
+    for (const auto& name : *to_be_removed_request_headers)
+      request_.headers.RemoveHeader(name);
+  }
+  if (modified_request_headers)
+    request_.headers.MergeFrom(*modified_request_headers);
+
   request_.url = redirect_info_.new_url;
   request_.method = redirect_info_.new_method;
   request_.referrer = GURL(redirect_info_.new_referrer);
@@ -161,7 +164,8 @@
   // in net/url_request/redirect_util.cc).
   if ((original_fetch_cors_flag && !NeedsPreflight(request_)) ||
       !fetch_cors_flag_) {
-    network_loader_->FollowRedirect(base::nullopt, base::nullopt);
+    network_loader_->FollowRedirect(to_be_removed_request_headers,
+                                    modified_request_headers);
     return;
   }
   DCHECK_NE(request_.fetch_request_mode, mojom::FetchRequestMode::kNoCORS);
@@ -348,6 +352,13 @@
 }
 
 void CORSURLLoader::StartRequest() {
+  if (fetch_cors_flag_ && !base::ContainsValue(url::GetCORSEnabledSchemes(),
+                                               request_.url.scheme())) {
+    HandleComplete(URLLoaderCompletionStatus(
+        CORSErrorStatus(mojom::CORSError::kCORSDisabledScheme)));
+    return;
+  }
+
   // If the CORS flag is set, |httpRequest|’s method is neither `GET` nor
   // `HEAD`, or |httpRequest|’s mode is "websocket", then append
   // `Origin`/the result of serializing a request origin with |httpRequest|, to
diff --git a/services/network/public/mojom/cors.mojom b/services/network/public/mojom/cors.mojom
index 9b8b0732..b0e7b16 100644
--- a/services/network/public/mojom/cors.mojom
+++ b/services/network/public/mojom/cors.mojom
@@ -37,6 +37,9 @@
   // header.
   kInvalidAllowCredentials,
 
+  // The scheme is not for CORS.
+  kCORSDisabledScheme,
+
   // Preflight:
   // Failed to check HTTP response ok status in a CORS-preflight response.
   kPreflightInvalidStatus,
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom
index 3091427..7a5ca878 100644
--- a/services/network/public/mojom/network_context.mojom
+++ b/services/network/public/mojom/network_context.mojom
@@ -353,6 +353,8 @@
   // Clears content from the HTTP cache. A specific range of time can be
   // specified with |start_time| and |end_time|. This supports unbounded deletes
   // in either direction by using null Time values for either argument.
+  // If a non-null |filter| is specified, will clear only entries matching the
+  // filter.
   ClearHttpCache(mojo_base.mojom.Time start_time,
                  mojo_base.mojom.Time end_time,
                  ClearDataFilter? filter) => ();
diff --git a/services/test/BUILD.gn b/services/test/BUILD.gn
index 4e31ddc..8ffc1dd 100644
--- a/services/test/BUILD.gn
+++ b/services/test/BUILD.gn
@@ -37,10 +37,6 @@
   if (is_android) {
     deps += [ "//mojo/public/java/system:native_support" ]
   }
-
-  if (use_ozone) {
-    deps += [ "//ui/ozone" ]
-  }
 }
 
 bundle_data("tests_bundle_data") {
diff --git a/services/test/run_all_service_tests.cc b/services/test/run_all_service_tests.cc
index 9ba9046..4276a1b 100644
--- a/services/test/run_all_service_tests.cc
+++ b/services/test/run_all_service_tests.cc
@@ -12,16 +12,12 @@
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/ui_base_paths.h"
 
-#if defined(USE_OZONE)
-#include "ui/ozone/public/ozone_platform.h"
-#endif
-
 namespace {
 
 class ServiceTestSuite : public base::TestSuite {
  public:
   ServiceTestSuite(int argc, char** argv) : base::TestSuite(argc, argv) {}
-  ~ServiceTestSuite() override {}
+  ~ServiceTestSuite() override = default;
 
  protected:
   void Initialize() override {
@@ -32,13 +28,6 @@
     ASSERT_TRUE(base::PathService::Get(ui::UI_TEST_PAK, &ui_test_pak_path));
     ui::ResourceBundle::InitSharedInstanceWithPakPath(ui_test_pak_path);
 
-#if defined(USE_OZONE)
-    ui::OzonePlatform::InitParams params;
-    params.single_process = true;
-    ui::OzonePlatform::InitializeForGPU(params);
-    ui::OzonePlatform::GetInstance()->AfterSandboxEntry();
-#endif
-
     // base::TestSuite and ViewsInit both try to load icu. That's ok for tests.
     base::i18n::AllowMultipleInitializeCallsForTesting();
   }
diff --git a/testing/libfuzzer/libprotobuf-mutator.md b/testing/libfuzzer/libprotobuf-mutator.md
index 3b96f30..34db388 100644
--- a/testing/libfuzzer/libprotobuf-mutator.md
+++ b/testing/libfuzzer/libprotobuf-mutator.md
@@ -95,28 +95,18 @@
 production contain this line: `option optimize_for = LITE_RUNTIME` But this
 line is incompatible with libprotobuf-mutator. Thus, we need to modify the
 `proto_library` build target so that builds when fuzzing are compatible with
-libprotobuf-mutator. We do this by using a protobuf compiler plugin,
-`override_lite_runtime_plugin`. Here's what a `proto_library` build target that
-is configured properly looks like:
+libprotobuf-mutator. To do this, change your `proto_library` to
+`fuzzable_proto_library` (don't worry, this works just like `proto_library` when
+`use_libfuzzer` is `false`) like so:
 
 ```python
-proto_library("my_proto") {
-  ... // These lines (probably) dont need to be changed.
+import("//third_party/libprotobuf-mutator/fuzzable_proto_library.gni")
 
-  if (use_libfuzzer && current_toolchain == host_toolchain) {
-    generator_plugin_label =
-      "//third_party/libprotobuf-mutator:override_lite_runtime_plugin"
-    generator_plugin_suffix = ".pb"
-    # The plugin will generate cc, so don't ask for it to be done by protoc.
-    generate_cc = false
-    // If deps is already defined, change "=" to "+=".
-    deps = ["//third_party/libprotobuf-mutator:override_lite_runtime_plugin"]
-  }
+fuzzable_proto_library("my_proto") {
+  ...
 }
 ```
 
-Note that this will not have any affects on the proto_library in production,
-since the plugin is only used when `use_libfuzzer == true`.
 And with that we have completed writing a libprotobuf-mutator fuzz target for
 Chromium code that accepts protobufs.
 
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 5b63006..1bb9a98 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -292,6 +292,7 @@
 crbug.com/591099 external/wpt/css/css-writing-modes/text-orientation-script-001j.html [ Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes/vertical-alignment-003.xht [ Pass ]
 crbug.com/591099 external/wpt/css/css-writing-modes/vertical-alignment-009.xht [ Pass ]
+crbug.com/591099 external/wpt/css/cssom/cssstyledeclaration-mutationrecord-001.html [ Pass ]
 crbug.com/591099 external/wpt/css/selectors/focus-visible-007.html [ Failure ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/descriptor-fallback.html [ Failure ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/descriptor-negative-invalid.html [ Failure ]
@@ -424,13 +425,8 @@
 crbug.com/591099 external/wpt/svg/painting/reftests/paint-context-001.svg [ Failure ]
 crbug.com/591099 external/wpt/svg/painting/reftests/paint-context-002.svg [ Failure ]
 crbug.com/591099 external/wpt/svg/path/bearing/zero.svg [ Failure ]
-crbug.com/591099 external/wpt/trusted-types/HTMLImageElement-src.tentative.html [ Failure Pass ]
-crbug.com/591099 external/wpt/trusted-types/HTMLMediaElement-src.tentative.html [ Failure Pass ]
-crbug.com/591099 external/wpt/trusted-types/HTMLSourceElement-src.tentative.html [ Failure Pass ]
-crbug.com/591099 external/wpt/trusted-types/block-string-assignment-to-HTMLImageElement-src.tentative.html [ Failure Pass ]
-crbug.com/591099 external/wpt/trusted-types/block-string-assignment-to-HTMLMediaElement-src.tentative.html [ Failure Pass ]
-crbug.com/591099 external/wpt/trusted-types/block-string-assignment-to-HTMLSourceElement-src.tentative.html [ Failure Pass ]
 crbug.com/591099 external/wpt/user-timing/invoke_with_timing_attributes.worker.html [ Failure ]
+crbug.com/591099 external/wpt/webrtc/RTCPeerConnection-setLocalDescription-answer.html [ Pass ]
 crbug.com/591099 external/wpt/webrtc/interfaces.html [ Pass Timeout ]
 crbug.com/591099 external/wpt/websockets/Create-Secure-extensions-empty.any.worker.html [ Timeout ]
 crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_down.html [ Failure ]
@@ -508,7 +504,7 @@
 crbug.com/591099 fast/box-shadow/box-shadow.html [ Failure ]
 crbug.com/591099 fast/box-shadow/inset-subpixel.html [ Failure ]
 crbug.com/591099 fast/box-shadow/inset.html [ Failure ]
-crbug.com/591099 fast/box-sizing/replaced.html [ Failure Pass ]
+crbug.com/591099 fast/box-sizing/replaced.html [ Failure ]
 crbug.com/591099 fast/css-generated-content/first-letter-next-sibling-crash.html [ Crash ]
 crbug.com/591099 fast/css-generated-content/float-first-letter-siblings-convert-to-inline.html [ Crash ]
 crbug.com/591099 fast/css-grid-layout/grid-align-baseline-vertical.html [ Failure ]
@@ -521,7 +517,7 @@
 crbug.com/591099 fast/css-grid-layout/grid-self-baseline-vertical-lr-04.html [ Failure ]
 crbug.com/591099 fast/css-grid-layout/grid-self-baseline-vertical-lr-05.html [ Failure ]
 crbug.com/591099 fast/css-grid-layout/maximize-tracks-definite-indefinite-width.html [ Failure ]
-crbug.com/591099 fast/css-grid-layout/mozilla/grid-repeat-auto-fill-fit-004.html [ Failure ]
+crbug.com/591099 fast/css-grid-layout/mozilla/grid-repeat-auto-fill-fit-004.html [ Failure Pass ]
 crbug.com/591099 fast/css-grid-layout/percent-padding-margin-resolution-grid-item.html [ Failure ]
 crbug.com/591099 fast/css-intrinsic-dimensions/fixed-height-stf-img-block-child-percent-height.html [ Failure ]
 crbug.com/591099 fast/css-intrinsic-dimensions/fixed-height-stf-img-inline-child-percent-height.html [ Failure ]
@@ -547,11 +543,11 @@
 crbug.com/591099 fast/dynamic/text-combine.html [ Failure ]
 crbug.com/591099 fast/encoding/utf-16-big-endian.html [ Failure ]
 crbug.com/591099 fast/encoding/utf-16-little-endian.html [ Failure ]
-crbug.com/591099 fast/events/background-tab-on-submit-ctrl-click.html [ Failure Timeout ]
+crbug.com/591099 fast/events/background-tab-on-submit-ctrl-click.html [ Failure ]
 crbug.com/591099 fast/events/background-tab-on-submit-synthesized-ctrl-click.html [ Failure ]
 crbug.com/591099 fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
 crbug.com/591099 fast/events/wheel/mainthread-touchpad-fling-latching.html [ Pass ]
-crbug.com/591099 fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Failure Pass ]
+crbug.com/591099 fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Pass ]
 crbug.com/591099 fast/forms/text-control-intrinsic-widths.html [ Timeout ]
 crbug.com/591099 fast/inline-block/vertical-align-top-and-bottom-2.html [ Failure ]
 crbug.com/591099 fast/inline/absolute-positioned-block-in-centred-block.html [ Failure ]
@@ -633,7 +629,7 @@
 crbug.com/591099 http/tests/csspaint/invalidation-border-image.html [ Timeout ]
 crbug.com/591099 http/tests/csspaint/invalidation-content-image.html [ Timeout ]
 crbug.com/591099 http/tests/devtools/console-resource-errors.js [ Failure Pass ]
-crbug.com/591099 http/tests/devtools/console/console-search.js [ Timeout ]
+crbug.com/591099 http/tests/devtools/console/console-search.js [ Pass Timeout ]
 crbug.com/591099 http/tests/devtools/persistence/persistence-merge-editor-tabs.js [ Failure ]
 crbug.com/591099 http/tests/devtools/tracing/timeline-misc/timeline-grouped-invalidations.js [ Failure ]
 crbug.com/591099 http/tests/devtools/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations.js [ Failure ]
@@ -656,12 +652,13 @@
 crbug.com/591099 http/tests/preload/dynamic_remove_preload_href.html [ Failure Pass ]
 crbug.com/591099 http/tests/security/cors-rfc1918/addressspace-document-appcache.https.html [ Crash Failure ]
 crbug.com/591099 http/tests/security/cors-rfc1918/addressspace-document-csp-appcache.https.html [ Crash Failure Pass ]
-crbug.com/591099 http/tests/security/setDomainRelaxationForbiddenForURLScheme.html [ Crash Pass ]
+crbug.com/591099 http/tests/security/setDomainRelaxationForbiddenForURLScheme.html [ Crash ]
 crbug.com/591099 http/tests/security/xssAuditor/block-does-not-leak-location.html [ Failure ]
 crbug.com/591099 http/tests/websocket/invalid-subprotocol-characters.html [ Pass Timeout ]
 crbug.com/591099 idle-callback/test-runner-run-idle-tasks.html [ Crash Pass Timeout ]
 crbug.com/714962 images/color-profile-background-clip-text.html [ Failure ]
 crbug.com/591099 images/color-profile-image-filter-all.html [ Failure ]
+crbug.com/591099 images/feature-policy-max-downscaling-image.html [ Failure ]
 crbug.com/714962 inspector-protocol/css/css-get-platform-fonts.js [ Failure ]
 crbug.com/714962 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot-viewport.js [ Failure ]
 crbug.com/591099 inspector-protocol/dom-snapshot/dom-snapshot-getSnapshot.js [ Failure ]
@@ -839,6 +836,7 @@
 crbug.com/591099 virtual/exotic-color-space/ [ Skip ]
 crbug.com/591099 virtual/feature-policy-vibrate/ [ Skip ]
 crbug.com/591099 virtual/gpu-rasterization/images/color-profile-image-filter-all.html [ Failure ]
+crbug.com/591099 virtual/gpu-rasterization/images/feature-policy-max-downscaling-image.html [ Failure ]
 crbug.com/591099 virtual/layout_ng/ [ Skip ]
 crbug.com/824918 virtual/layout_ng_experimental/ [ Skip ]
 crbug.com/591099 virtual/mojo-blob-urls/external/wpt/FileAPI/url/sandboxed-iframe.html [ Pass ]
@@ -846,9 +844,8 @@
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/background-tab-on-submit-synthesized-ctrl-click.html [ Failure ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/touch/compositor-touch-hit-rects.html [ Failure ]
 crbug.com/591099 virtual/mouseevent_fractional/fast/events/wheel/mainthread-touchpad-fling-latching.html [ Pass ]
-crbug.com/591099 virtual/mouseevent_fractional/fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Failure Pass ]
+crbug.com/591099 virtual/mouseevent_fractional/fast/events/wheel/wheel-scroll-latching-on-scrollbar.html [ Pass ]
 crbug.com/591099 virtual/new-remote-playback-pipeline/ [ Skip ]
-crbug.com/591099 virtual/off-main-thread-websocket/http/tests/websocket/invalid-subprotocol-characters.html [ Pass Timeout ]
 crbug.com/591099 virtual/outofblink-cors/ [ Skip ]
 crbug.com/591099 virtual/paint-timing/external/wpt/paint-timing/sibling-painting-first-image.html [ Failure ]
 crbug.com/591099 virtual/prefer_compositing_to_lcd_text/ [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees
index b92d190..b88ee95 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees
@@ -93,7 +93,6 @@
 Bug(none) virtual/mouseevent_fractional/ [ Skip ]
 Bug(none) virtual/mse-1mb-buffers/ [ Skip ]
 Bug(none) virtual/new-remote-playback-pipeline/ [ Skip ]
-Bug(none) virtual/off-main-thread-websocket/ [ Skip ]
 Bug(none) virtual/origin-trials-runtimeflags-disabled/ [ Skip ]
 Bug(none) virtual/outofblink-cors/ [ Skip ]
 Bug(none) virtual/paint-timing/ [ Skip ]
diff --git a/third_party/WebKit/LayoutTests/SlowTests b/third_party/WebKit/LayoutTests/SlowTests
index bb97bb8..23a53f79 100644
--- a/third_party/WebKit/LayoutTests/SlowTests
+++ b/third_party/WebKit/LayoutTests/SlowTests
@@ -148,7 +148,6 @@
 
 # This test takes 5+ seconds as intended because it tests connection throttling.
 crbug.com/459377 http/tests/websocket/multiple-connections-throttled.html [ Slow ]
-crbug.com/459377 virtual/off-main-thread-websocket/http/tests/websocket/multiple-connections-throttled.html [ Slow ]
 
 # These tests are slow to measure bounding box of every single Unicode character.
 crbug.com/492664 external/wpt/css/css-writing-modes/text-orientation-script-001a.html [ Slow ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 0bff5405..f55e4da 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1690,23 +1690,19 @@
 crbug.com/736308 virtual/outofblink-cors/external/wpt/service-workers/service-worker/navigation-timing.https.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors/http/tests/fetch/chromium/error-messages.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/cross-origin-no-credential-prompt.html [ Failure ]
-crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/cross-origin-unsupported-url.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/origin-whitelisting-all.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/origin-whitelisting-exact-match.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/origin-whitelisting-removal.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/origin-whitelisting-subdomains.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/origin-whitelisting-ip-addresses.html [ Failure ]
-crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors-ns/external/wpt/service-workers/service-worker/navigation-timing.https.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors-ns/http/tests/fetch/chromium/error-messages.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors-ns/http/tests/xmlhttprequest/cross-origin-no-credential-prompt.html [ Failure ]
-crbug.com/736308 virtual/outofblink-cors-ns/http/tests/xmlhttprequest/cross-origin-unsupported-url.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors-ns/http/tests/xmlhttprequest/origin-whitelisting-all.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors-ns/http/tests/xmlhttprequest/origin-whitelisting-exact-match.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors-ns/http/tests/xmlhttprequest/origin-whitelisting-removal.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors-ns/http/tests/xmlhttprequest/origin-whitelisting-subdomains.html [ Failure ]
 crbug.com/736308 virtual/outofblink-cors-ns/http/tests/xmlhttprequest/origin-whitelisting-ip-addresses.html [ Failure ]
-crbug.com/736308 virtual/outofblink-cors-ns/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url.html [ Failure ]
 
 # ====== Out of Blink CORS related tests END ======
 
@@ -1727,9 +1723,6 @@
 crbug.com/520736 [ Win7 ] virtual/video-surface-layer/media/W3C/video/networkState/networkState_during_progress.html [ Failure Pass ]
 
 crbug.com/865839 external/wpt/service-workers/service-worker/update-after-navigation-redirect.https.html [ Timeout ]
-crbug.com/865839 virtual/service-worker-servicification/external/wpt/service-workers/service-worker/update-after-navigation-redirect.https.html [ Timeout ]
-crbug.com/865839 virtual/outofblink-cors/external/wpt/service-workers/service-worker/update-after-navigation-redirect.https.html [ Timeout ]
-crbug.com/865839 virtual/outofblink-cors-ns/external/wpt/service-workers/service-worker/update-after-navigation-redirect.https.html [ Timeout ]
 
 crbug.com/841922 [ Linux Win Mac ] virtual/video-surface-layer/media/video-controls-focus-movement-on-hide.html [ Pass Failure ]
 
@@ -2628,12 +2621,9 @@
 crbug.com/849737 virtual/mojo-blob-urls/external/wpt/FileAPI/url/url-format.any.worker.html [ Pass Timeout ]
 
 # Websockets
-crbug.com/803358 virtual/off-main-thread-websocket/external/wpt/websockets/Create-Secure-extensions-empty.htm [ Timeout ]
 # Cannot be rebaselined because the output contains a timestamp and a random number.
 crbug.com/803200 external/wpt/websockets/cookies/006.html?wss [ Failure ]
 crbug.com/803200 external/wpt/websockets/opening-handshake/005.html?wss [ Pass Failure ]
-crbug.com/803200 virtual/off-main-thread-websocket/external/wpt/websockets/cookies/006.html?wss [ Failure ]
-crbug.com/803200 virtual/off-main-thread-websocket/external/wpt/websockets/opening-handshake/005.html?wss [ Pass Failure ]
 
 crbug.com/805463 external/wpt/acid/acid3/numbered-tests.html [ Skip ]
 
@@ -2872,9 +2862,7 @@
 crbug.com/626703 external/wpt/css/css-text/overflow-wrap/overflow-wrap-break-word-003.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/overflow-wrap/overflow-wrap-break-word-002.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-contain/counter-scoping-002.html [ Failure ]
-crbug.com/626703 virtual/off-main-thread-websocket/external/wpt/websockets/Create-Secure-extensions-empty.any.html [ Timeout ]
 crbug.com/626703 external/wpt/css/css-contain/contain-layout-breaks-002.html [ Failure ]
-crbug.com/626703 virtual/off-main-thread-websocket/external/wpt/websockets/Create-Secure-extensions-empty.any.worker.html [ Timeout ]
 crbug.com/626703 external/wpt/css/css-contain/quote-scoping-004.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-contain/quote-scoping-003.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-contain/contain-size-breaks-001.html [ Failure ]
@@ -4351,8 +4339,6 @@
 # Sheriff 2018-02-26
 crbug.com/816475 [ Win7 Linux ] external/wpt/webrtc/RTCDTMFSender-ontonechange.https.html [ Failure Pass ]
 crbug.com/816914 [ Mac ] fast/canvas/canvas-drawImage-live-video.html [ Failure Pass ]
-crbug.com/816766 [ Mac ] fast/dom/Window/window-focus-self.html [ Failure Pass ]
-crbug.com/816766 [ Mac ] virtual/user-activation-v2/fast/dom/Window/window-focus-self.html [ Failure Pass ]
 crbug.com/817167 http/tests/devtools/oopif/oopif-cookies-refresh.js [ Failure Timeout Pass ]
 
 # Sheriff 2018-03-02
@@ -4522,7 +4508,6 @@
 
 # Sheriff 2018-06-07
 crbug.com/850349 external/wpt/css/css-animations/CSSAnimation-getComputedTiming.tentative.html [ Pass Failure ]
-crbug.com/520739 virtual/off-main-thread-websocket/http/tests/websocket/close-code-and-reason.html [ Pass Failure ]
 crbug.com/850395 virtual/gpu/fast/canvas/canvas-filter-stroke-paint-pattern.html [ Pass Failure ]
 crbug.com/850358 http/tests/devtools/editor/text-editor-enter-behaviour.js [ Pass Failure ]
 crbug.com/849978 http/tests/devtools/elements/styles-4/stylesheet-source-url-comment.js [ Pass Failure ]
@@ -4634,9 +4619,6 @@
 # S13N Sheriff 2018-7-11
 crbug.com/862643 http/tests/serviceworker/navigation_preload/use-counter.html [ Failure Pass ]
 
-# Sheriff 2018-7-12
-crbug.com/863067 [ Win10 ] virtual/user-activation-v2/fast/dom/Window/window-focus-self.html [ Failure Pass ]
-
 # Sheriff 2018-7-13
 crbug.com/863599 [ Linux Debug ] external/wpt/requestidlecallback/callback-iframe.html [ Pass Timeout ]
 
@@ -4645,7 +4627,6 @@
 crbug.com/864891 [ Mac ] virtual/scroll_customization/fast/scroll-behavior/scroll-customization/scroll-customization-property.html [ Timeout Pass ]
 
 # Sheriff 2018-07-18
-crbug.com/863067 [ Win10 ] fast/dom/Window/window-focus-self.html [ Failure Pass ]
 crbug.com/864994 [ Mac ] external/wpt/encoding/legacy-mb-korean/euc-kr/euckr-decode-ksc_5601.html [ Timeout Failure Pass ]
 
 crbug.com/865432 [ Linux ] external/wpt/workers/modules/dedicated-worker-import-blob-url.any.worker.html [ Timeout Pass ]
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites
index b3a30f1..448c494 100644
--- a/third_party/WebKit/LayoutTests/VirtualTestSuites
+++ b/third_party/WebKit/LayoutTests/VirtualTestSuites
@@ -640,21 +640,6 @@
              "--disable-features=NetworkService"]
   },
   {
-    "prefix": "off-main-thread-websocket",
-    "base": "external/wpt/websockets",
-    "args": ["--disable-features=OffMainThreadWebSocket,NestedWorkers"]
-  },
-  {
-    "prefix": "off-main-thread-websocket",
-    "base": "http/tests/websocket",
-    "args": ["--disable-features=OffMainThreadWebSocket,NestedWorkers"]
-  },
-  {
-    "prefix": "off-main-thread-websocket",
-    "base": "http/tests/security/mixedContent/websocket",
-    "args": ["--disable-features=OffMainThreadWebSocket,NestedWorkers"]
-  },
-  {
     "prefix": "webrtc-wpt-unified-plan",
     "base": "external/wpt/webrtc",
     "args": ["--enable-blink-features=RTCUnifiedPlanByDefault"]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-break-word-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-break-word-004.html
deleted file mode 100644
index 560ef63..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-break-word-004.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Text Test: overflow-wrap: break-word</title>
-<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
-<link rel="help" href="https://drafts.csswg.org/css-text-3/#valdef-overflow-wrap-break-word">
-<meta name="flags" content="ahem">
-<link rel="match" href="reference/overflow-wrap-break-word-001-ref.html">
-<meta name="assert" content="A Single leading white-space constitutes a soft breaking opportunity, honoring the 'white-space: pre-wrap' property, that must prevent the word to be broken.">
-<style>
-div {
-   position: relative;
-   font-size: 20px;
-   font-family: Ahem;
-}
-.red {
-  position: absolute;
-  background: green;
-  color: red;
-  width: 100px;
-  height: 100px;
-  z-index: -1;
-}
-.test {
-  color: green;
-  line-height: 1em;
-  width: 5ch;
-
-  white-space: pre-wrap;
-  overflow-wrap: break-word;
-}
-</style>
-<body>
-  <p>Test passes if there is a <strong>filled green square</strong> and <strong>no red</strong>.</p>
-  <div class="red"><br>XXXXX</div>
-  <div class="test"> XXXXX </div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/word-break/reference/word-break-break-all-010-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/word-break/reference/word-break-break-all-010-ref.html
deleted file mode 100644
index 0e0300a..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/word-break/reference/word-break-break-all-010-ref.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Text Reference File</title>
-<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
-<style>
-div {
-  position: relative;
-  width: 100px;
-  height: 100px;
-  background: green;
-}
-</style>
-<body>
-  <p>Test passes if there is a <strong>filled green square</strong> and <strong>no red</strong>.</p>
-  <div></div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/word-break/word-break-break-all-010.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/word-break/word-break-break-all-010.html
deleted file mode 100644
index 1ab97fb1..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/word-break/word-break-break-all-010.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Text Test: overflow-wrap: break-word</title>
-<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
-<link rel="help" href="https://drafts.csswg.org/css-text-3/#valdef-word-break-break-all">
-<meta name="flags" content="ahem">
-<link rel="match" href="reference/word-break-break-all-010-ref.html">
-<meta name="assert" content="The word is broken even if pre-wrap provides a former breaking opportunity in leading white-space.">
-<style>
-div {
-   position: relative;
-   font-size: 20px;
-   font-family: Ahem;
-}
-.red {
-  position: absolute;
-  white-space: pre;
-  background: green;
-  color: red;
-  width: 100px;
-  height: 100px;
-  z-index: -1;
-}
-.test {
-  color: green;
-  line-height: 1em;
-  width: 5ch;
-
-  white-space: pre-wrap;
-  word-break: break-all;
-}
-</style>
-<body>
-  <p>Test passes if there is a <strong>filled green square</strong> and <strong>no red</strong>.</p>
-  <div class="red"> XXXX<br>X</div>
-  <div class="test"> XXXXX</div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/word-break/word-break-break-all-011.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/word-break/word-break-break-all-011.html
deleted file mode 100644
index ed07aeb7..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/word-break/word-break-break-all-011.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Text Test: overflow-wrap: break-word</title>
-<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
-<link rel="help" href="https://drafts.csswg.org/css-text-3/#valdef-word-break-break-all">
-<meta name="flags" content="ahem">
-<link rel="match" href="reference/word-break-break-all-010-ref.html">
-<meta name="assert" content="A single leading white-space should account as soft breaking opportunity, honoring the 'white-space: pre-wrap', on top to the ones provided by 'word-break: break-all'.">
-<style>
-div {
-   position: relative;
-   font-size: 20px;
-   font-family: Ahem;
-}
-.red {
-  position: absolute;
-  background: green;
-  color: red;
-  width: 100px;
-  height: 100px;
-  z-index: -1;
-}
-.test {
-  color: green;
-  background: green;
-  line-height: 1em;
-  width: 1ch;
-  white-space: pre-wrap;
-  word-break: break-all;
-}
-</style>
-<body>
-  <p>Test passes if there is a <strong>filled green square</strong> and <strong>no red</strong>.</p>
-  <div class="red">X<br>X<br>X</div>
-  <div class="test"> XX</div>
-</body>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/window-focus-self.html b/third_party/WebKit/LayoutTests/fast/dom/Window/window-focus-self.html
index e1fb6dbe..e758faaf 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/Window/window-focus-self.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/Window/window-focus-self.html
@@ -7,8 +7,6 @@
     window.onblur = windowBlurred;
 
     if (window.testRunner) {
-        testRunner.waitUntilDone();
-        testRunner.dumpAsText();
         testRunner.setWindowIsKey(false);
         window.open('javascript:window.focus()', '_self', '');
         setTimeout(function() { testRunner.notifyDone(); }, 0);
@@ -36,6 +34,16 @@
 <body>
     This tests that a window cannot focus itself by using javascript: urls.
     <ul id="console"></ul>
-    <script>runTest();</script>
+    <script>
+    if (window.testRunner) {
+        testRunner.waitUntilDone();
+        testRunner.dumpAsText();
+        // If this test is run on a fresh content shell, its initial focus
+        // may deliver a focus event which can race with runTest() above,
+        // and result in false failure.  Add some delay to avoid the initial
+        // focus event.  See crbug.com/863067 for more background.
+        setTimeout(runTest, 100);
+    }
+    </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/selection/selection-clear-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/selection/selection-clear-expected.txt
index 564c7f30..6bbe70d 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/selection/selection-clear-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-slimming-paint-v2/paint/invalidation/selection/selection-clear-expected.txt
@@ -57,14 +57,6 @@
     {
       "object": "RootInlineBox",
       "reason": "geometry"
-    },
-    {
-      "object": "LayoutBR BR",
-      "reason": "selection"
-    },
-    {
-      "object": "InlineTextBox '\n'",
-      "reason": "selection"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/http/tests/loading/sxg/sxg-location-fragment.html b/third_party/WebKit/LayoutTests/http/tests/loading/sxg/sxg-location-fragment.html
new file mode 100644
index 0000000..3502dd58
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/http/tests/loading/sxg/sxg-location-fragment.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Navigating to a Signed Exchange should preserve URL fragment</title>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="./resources/sxg-util.js"></script>
+<body>
+<script>
+promise_test(async (t) => {
+  await waitUntilDidFinishLoadForFrame;
+
+  // The timestamp of the test SXG file is "Apr 1 2018 00:00 UTC" and valid
+  // until "Apr 8 2018 00:00 UTC".
+  await setSignedExchangeVerificationTime(new Date("Apr 1 2018 00:01 UTC"));
+
+  const event = await new Promise(async (resolve, reject) => {
+    // We can't catch the network error on iframe. So we use the timer.
+    t.step_timeout(() => reject('timeout'), 1000);
+
+    const frame =
+        await withIframe('resources/sxg-location.sxg#fragment', 'sxg_iframe');
+    const channel = new MessageChannel();
+    channel.port1.onmessage = resolve;
+    frame.contentWindow.postMessage(
+        {port: channel.port2}, '*', [channel.port2]);
+  });
+  assert_equals(event.data.location, 'https://127.0.0.1:8443/test.html#fragment');
+}, 'Navigating to a Signed Exchange should preserve URL fragment');
+
+</script>
+</body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/cross-origin-unsupported-url-expected.txt b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/cross-origin-unsupported-url-expected.txt
index bf07bdf..991ed31 100644
--- a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/cross-origin-unsupported-url-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/cross-origin-unsupported-url-expected.txt
@@ -1,40 +1,28 @@
-CONSOLE WARNING: line 14: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
-CONSOLE ERROR: line 20: Failed to load ftp://127.0.0.1/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 1: Failed to load ftp://127.0.0.1/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 20: Failed to load ftp://127.0.0.1/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 1: Failed to load ftp://127.0.0.1/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 20: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 1: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 20: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 1: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 20: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 1: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 20: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 1: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-Test cross-origin XHRs to CORS-unsupported protocol schemes in the URL.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS errorEvent.name is "NetworkError"
-PASS errorEvent.type is "error"
-PASS xhr.send() did not throw exception.
-PASS errorEvent.name is "NetworkError"
-PASS errorEvent.type is "error"
-PASS xhr.send() did not throw exception.
-PASS errorEvent.name is "NetworkError"
-PASS errorEvent.type is "error"
-PASS xhr.send() did not throw exception.
-PASS errorEvent.name is "NetworkError"
-PASS errorEvent.type is "error"
-PASS xhr.send() did not throw exception.
-PASS errorEvent.name is "NetworkError"
-PASS errorEvent.type is "error"
-PASS xhr.send() did not throw exception.
-PASS errorEvent.name is "NetworkError"
-PASS errorEvent.type is "error"
-PASS xhr.send() did not throw exception.
-PASS successfullyParsed is true
-
-TEST COMPLETE
+CONSOLE WARNING: line 8: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
+CONSOLE ERROR: line 13: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 29: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 29: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 29: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 29: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 29: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 29: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+This is a testharness.js-based test.
+PASS sync test for url=mailto:foo@bar.com, contentType=undefined
+PASS sync test for url=mailto:foo@bar.com, contentType=application/json
+PASS async test for url=mailto:foo@bar.com, contentType=undefined
+PASS async test for url=mailto:foo@bar.com, contentType=application/json
+PASS sync test for url=localhost:8080/, contentType=undefined
+PASS sync test for url=localhost:8080/, contentType=application/json
+PASS async test for url=localhost:8080/, contentType=undefined
+PASS async test for url=localhost:8080/, contentType=application/json
+PASS sync test for url=tel:1234, contentType=undefined
+PASS sync test for url=tel:1234, contentType=application/json
+PASS async test for url=tel:1234, contentType=undefined
+PASS async test for url=tel:1234, contentType=application/json
+Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/cross-origin-unsupported-url.html b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/cross-origin-unsupported-url.html
index 7f908bc..40941d8a 100644
--- a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/cross-origin-unsupported-url.html
+++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/cross-origin-unsupported-url.html
@@ -1,3 +1,4 @@
 <!DOCTYPE HTML>
-<script src="/js-test-resources/js-test.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
 <script src="resources/cross-origin-unsupported-url.js"></script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/resources/cross-origin-unsupported-url.js b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/resources/cross-origin-unsupported-url.js
index f1e0fe4..9f3f4f8 100644
--- a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/resources/cross-origin-unsupported-url.js
+++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/resources/cross-origin-unsupported-url.js
@@ -1,58 +1,47 @@
-if (self.importScripts)
-    importScripts("/js-test-resources/js-test.js");
+if (self.importScripts) {
+    importScripts('/resources/testharness.js');
+}
 
-self.jsTestIsAsync = true;
-
-description("Test cross-origin XHRs to CORS-unsupported protocol schemes in the URL.");
-
-var xhr;
-var errorEvent;
-function issueRequest(url, contentType)
-{
-    xhr = new XMLHttpRequest();
-    // async = false
+function testSync(url, contentType) {
+  test((t) => {
+    const xhr = new XMLHttpRequest();
     xhr.open('POST', url, false);
-    xhr.onerror = () => testFailed("onerror callback should not be called.");
-    // Assumed a Content-Type that turns it into a non-simple CORS request.
-    if (contentType)
-        xhr.setRequestHeader('Content-Type', contentType);
-    try {
-        xhr.send();
-    } catch(e) {
-        errorEvent = e;
-        shouldBeEqualToString("errorEvent.name", "NetworkError");
+    xhr.onerror = t.unreached_func('onerror');
+    if (contentType) {
+      xhr.setRequestHeader('Content-Type', contentType);
     }
-
-    xhr = new XMLHttpRequest();
-    // async = true
-    xhr.open('POST', url, true);
-    xhr.onerror = function (a) {
-        errorEvent = a;
-        shouldBeEqualToString("errorEvent.type", "error");
-        setTimeout(runTest, 0);
-    };
-    // Assumed a Content-Type that turns it into a non-simple CORS request.
-    if (contentType)
-        xhr.setRequestHeader('Content-Type', contentType);
-
-    shouldNotThrow('xhr.send()');
+    assert_throws('NetworkError', () => xhr.send());
+  }, `sync test for url=${url}, contentType=${contentType}`);
 }
 
-var withContentType = true;
-var tests = [ 'ftp://127.0.0.1',
-              'localhost:8080/',
-              'tel:1234' ];
-
-function runTest()
-{
-    if (!tests.length && withContentType) {
-        finishJSTest();
-        return;
-    }
-    withContentType = !withContentType;
-    if (!withContentType)
-        issueRequest(tests[0]);
-    else
-        issueRequest(tests.shift(), 'application/json');
+function testAsync(url, contentType) {
+  promise_test((t) => {
+    return new Promise(resolve => {
+      const xhr = new XMLHttpRequest();
+      xhr.open('POST', url, true);
+      xhr.onerror = t.step_func((e) => {
+        assert_equals(e.type, 'error');
+        resolve();
+      });
+      if (contentType) {
+        xhr.setRequestHeader('Content-Type', contentType);
+      }
+      xhr.send();
+    });
+  }, `async test for url=${url}, contentType=${contentType}`);
 }
-runTest();
+
+const urls = [
+  'mailto:foo@bar.com',
+  'localhost:8080/',
+  'tel:1234',
+];
+
+for (const url of urls) {
+  testSync(url);
+  testSync(url, 'application/json');
+  testAsync(url);
+  testAsync(url, 'application/json');
+}
+
+done();
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url-expected.txt b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url-expected.txt
index 8bd184cc..4c171e65 100644
--- a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url-expected.txt
@@ -1,40 +1,27 @@
-CONSOLE ERROR: line 20: Failed to load ftp://127.0.0.1/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 1: Failed to load ftp://127.0.0.1/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 20: Failed to load ftp://127.0.0.1/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 1: Failed to load ftp://127.0.0.1/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 20: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 1: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 20: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 1: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 20: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 1: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 20: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-CONSOLE ERROR: line 1: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
-[Worker] Test cross-origin XHRs to CORS-unsupported protocol schemes in the URL.
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-Starting worker: ../resources/cross-origin-unsupported-url.js
-PASS [Worker] errorEvent.name is "NetworkError"
-PASS [Worker] errorEvent.type is "error"
-PASS [Worker] xhr.send() did not throw exception.
-PASS [Worker] errorEvent.name is "NetworkError"
-PASS [Worker] errorEvent.type is "error"
-PASS [Worker] xhr.send() did not throw exception.
-PASS [Worker] errorEvent.name is "NetworkError"
-PASS [Worker] errorEvent.type is "error"
-PASS [Worker] xhr.send() did not throw exception.
-PASS [Worker] errorEvent.name is "NetworkError"
-PASS [Worker] errorEvent.type is "error"
-PASS [Worker] xhr.send() did not throw exception.
-PASS [Worker] errorEvent.name is "NetworkError"
-PASS [Worker] errorEvent.type is "error"
-PASS [Worker] xhr.send() did not throw exception.
-PASS [Worker] errorEvent.name is "NetworkError"
-PASS [Worker] errorEvent.type is "error"
-PASS [Worker] xhr.send() did not throw exception.
-PASS successfullyParsed is true
-
-TEST COMPLETE
+CONSOLE ERROR: line 13: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 29: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 29: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 29: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 29: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 29: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 29: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+This is a testharness.js-based test.
+PASS sync test for url=mailto:foo@bar.com, contentType=undefined
+PASS sync test for url=mailto:foo@bar.com, contentType=application/json
+PASS async test for url=mailto:foo@bar.com, contentType=undefined
+PASS async test for url=mailto:foo@bar.com, contentType=application/json
+PASS sync test for url=localhost:8080/, contentType=undefined
+PASS sync test for url=localhost:8080/, contentType=application/json
+PASS async test for url=localhost:8080/, contentType=undefined
+PASS async test for url=localhost:8080/, contentType=application/json
+PASS sync test for url=tel:1234, contentType=undefined
+PASS sync test for url=tel:1234, contentType=application/json
+PASS async test for url=tel:1234, contentType=undefined
+PASS async test for url=tel:1234, contentType=application/json
+Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url.html b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url.html
index 5268d80..eab87fb 100644
--- a/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url.html
+++ b/third_party/WebKit/LayoutTests/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url.html
@@ -1,11 +1,13 @@
 <!DOCTYPE html>
 <html>
 <head>
-<script src="/js-test-resources/js-test.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
 </head>
 <body>
 <script>
-startWorker("../resources/cross-origin-unsupported-url.js");
+const worker = new Worker('../resources/cross-origin-unsupported-url.js');
+fetch_tests_from_worker(worker);
 </script>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-clear-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-clear-expected.txt
index 97f78022..841fbcff 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-clear-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/linux/paint/invalidation/selection/selection-clear-expected.txt
@@ -68,14 +68,6 @@
     {
       "object": "RootInlineBox",
       "reason": "geometry"
-    },
-    {
-      "object": "LayoutBR BR",
-      "reason": "selection"
-    },
-    {
-      "object": "InlineTextBox '\n'",
-      "reason": "selection"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-clear-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-clear-expected.txt
index dd2ce67..209104b 100644
--- a/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-clear-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/mac/paint/invalidation/selection/selection-clear-expected.txt
@@ -68,14 +68,6 @@
     {
       "object": "RootInlineBox",
       "reason": "geometry"
-    },
-    {
-      "object": "LayoutBR BR",
-      "reason": "selection"
-    },
-    {
-      "object": "InlineTextBox '\n'",
-      "reason": "selection"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-clear-expected.txt b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-clear-expected.txt
index 3c95b95..f712a6b 100644
--- a/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-clear-expected.txt
+++ b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-clear-expected.txt
@@ -68,14 +68,6 @@
     {
       "object": "RootInlineBox",
       "reason": "geometry"
-    },
-    {
-      "object": "LayoutBR BR",
-      "reason": "selection"
-    },
-    {
-      "object": "InlineTextBox '\n'",
-      "reason": "selection"
     }
   ]
 }
diff --git a/third_party/WebKit/LayoutTests/virtual/off-main-thread-websocket/external/wpt/websockets/Create-on-worker-shutdown.any-expected.txt b/third_party/WebKit/LayoutTests/virtual/off-main-thread-websocket/external/wpt/websockets/Create-on-worker-shutdown.any-expected.txt
deleted file mode 100644
index f754aec..0000000
--- a/third_party/WebKit/LayoutTests/virtual/off-main-thread-websocket/external/wpt/websockets/Create-on-worker-shutdown.any-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-PASS WebSocket created after a worker self.close()
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/virtual/off-main-thread-websocket/external/wpt/websockets/Create-on-worker-shutdown.any.worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/off-main-thread-websocket/external/wpt/websockets/Create-on-worker-shutdown.any.worker-expected.txt
deleted file mode 100644
index 4b86e76..0000000
--- a/third_party/WebKit/LayoutTests/virtual/off-main-thread-websocket/external/wpt/websockets/Create-on-worker-shutdown.any.worker-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL WebSocket created after a worker self.close() Worker is not defined
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/virtual/off-main-thread-websocket/external/wpt/websockets/README.txt b/third_party/WebKit/LayoutTests/virtual/off-main-thread-websocket/external/wpt/websockets/README.txt
deleted file mode 100644
index 56a6b31..0000000
--- a/third_party/WebKit/LayoutTests/virtual/off-main-thread-websocket/external/wpt/websockets/README.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-This directory is for testing off-main-thread WebSocket.
-Tracking bug: https://crbug.com/825740
diff --git a/third_party/WebKit/LayoutTests/virtual/off-main-thread-websocket/http/tests/security/mixedContent/websocket/README.txt b/third_party/WebKit/LayoutTests/virtual/off-main-thread-websocket/http/tests/security/mixedContent/websocket/README.txt
deleted file mode 100644
index 56a6b31..0000000
--- a/third_party/WebKit/LayoutTests/virtual/off-main-thread-websocket/http/tests/security/mixedContent/websocket/README.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-This directory is for testing off-main-thread WebSocket.
-Tracking bug: https://crbug.com/825740
diff --git a/third_party/WebKit/LayoutTests/virtual/off-main-thread-websocket/http/tests/websocket/README.txt b/third_party/WebKit/LayoutTests/virtual/off-main-thread-websocket/http/tests/websocket/README.txt
deleted file mode 100644
index 56a6b31..0000000
--- a/third_party/WebKit/LayoutTests/virtual/off-main-thread-websocket/http/tests/websocket/README.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-This directory is for testing off-main-thread WebSocket.
-Tracking bug: https://crbug.com/825740
diff --git a/third_party/WebKit/LayoutTests/virtual/outofblink-cors-ns/http/tests/xmlhttprequest/cross-origin-unsupported-url-expected.txt b/third_party/WebKit/LayoutTests/virtual/outofblink-cors-ns/http/tests/xmlhttprequest/cross-origin-unsupported-url-expected.txt
new file mode 100644
index 0000000..65df437
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/outofblink-cors-ns/http/tests/xmlhttprequest/cross-origin-unsupported-url-expected.txt
@@ -0,0 +1,28 @@
+CONSOLE WARNING: line 8: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
+CONSOLE ERROR: line 13: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+This is a testharness.js-based test.
+PASS sync test for url=mailto:foo@bar.com, contentType=undefined
+PASS sync test for url=mailto:foo@bar.com, contentType=application/json
+PASS async test for url=mailto:foo@bar.com, contentType=undefined
+PASS async test for url=mailto:foo@bar.com, contentType=application/json
+PASS sync test for url=localhost:8080/, contentType=undefined
+PASS sync test for url=localhost:8080/, contentType=application/json
+PASS async test for url=localhost:8080/, contentType=undefined
+PASS async test for url=localhost:8080/, contentType=application/json
+PASS sync test for url=tel:1234, contentType=undefined
+PASS sync test for url=tel:1234, contentType=application/json
+PASS async test for url=tel:1234, contentType=undefined
+PASS async test for url=tel:1234, contentType=application/json
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/virtual/outofblink-cors-ns/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url-expected.txt b/third_party/WebKit/LayoutTests/virtual/outofblink-cors-ns/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url-expected.txt
new file mode 100644
index 0000000..17984a9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/outofblink-cors-ns/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url-expected.txt
@@ -0,0 +1,27 @@
+CONSOLE ERROR: line 13: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+This is a testharness.js-based test.
+PASS sync test for url=mailto:foo@bar.com, contentType=undefined
+PASS sync test for url=mailto:foo@bar.com, contentType=application/json
+PASS async test for url=mailto:foo@bar.com, contentType=undefined
+PASS async test for url=mailto:foo@bar.com, contentType=application/json
+PASS sync test for url=localhost:8080/, contentType=undefined
+PASS sync test for url=localhost:8080/, contentType=application/json
+PASS async test for url=localhost:8080/, contentType=undefined
+PASS async test for url=localhost:8080/, contentType=application/json
+PASS sync test for url=tel:1234, contentType=undefined
+PASS sync test for url=tel:1234, contentType=application/json
+PASS async test for url=tel:1234, contentType=undefined
+PASS async test for url=tel:1234, contentType=application/json
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/virtual/outofblink-cors/http/tests/xmlhttprequest/cross-origin-unsupported-url-expected.txt b/third_party/WebKit/LayoutTests/virtual/outofblink-cors/http/tests/xmlhttprequest/cross-origin-unsupported-url-expected.txt
new file mode 100644
index 0000000..65df437
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/outofblink-cors/http/tests/xmlhttprequest/cross-origin-unsupported-url-expected.txt
@@ -0,0 +1,28 @@
+CONSOLE WARNING: line 8: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
+CONSOLE ERROR: line 13: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+This is a testharness.js-based test.
+PASS sync test for url=mailto:foo@bar.com, contentType=undefined
+PASS sync test for url=mailto:foo@bar.com, contentType=application/json
+PASS async test for url=mailto:foo@bar.com, contentType=undefined
+PASS async test for url=mailto:foo@bar.com, contentType=application/json
+PASS sync test for url=localhost:8080/, contentType=undefined
+PASS sync test for url=localhost:8080/, contentType=application/json
+PASS async test for url=localhost:8080/, contentType=undefined
+PASS async test for url=localhost:8080/, contentType=application/json
+PASS sync test for url=tel:1234, contentType=undefined
+PASS sync test for url=tel:1234, contentType=application/json
+PASS async test for url=tel:1234, contentType=undefined
+PASS async test for url=tel:1234, contentType=application/json
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/virtual/outofblink-cors/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url-expected.txt b/third_party/WebKit/LayoutTests/virtual/outofblink-cors/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url-expected.txt
new file mode 100644
index 0000000..17984a9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/outofblink-cors/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url-expected.txt
@@ -0,0 +1,27 @@
+CONSOLE ERROR: line 13: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: line 13: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load mailto:foo@bar.com: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load localhost:8080/: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+CONSOLE ERROR: Failed to load tel:1234: Cross origin requests are only supported for protocol schemes: http, data, chrome, https.
+This is a testharness.js-based test.
+PASS sync test for url=mailto:foo@bar.com, contentType=undefined
+PASS sync test for url=mailto:foo@bar.com, contentType=application/json
+PASS async test for url=mailto:foo@bar.com, contentType=undefined
+PASS async test for url=mailto:foo@bar.com, contentType=application/json
+PASS sync test for url=localhost:8080/, contentType=undefined
+PASS sync test for url=localhost:8080/, contentType=application/json
+PASS async test for url=localhost:8080/, contentType=undefined
+PASS async test for url=localhost:8080/, contentType=application/json
+PASS sync test for url=tel:1234, contentType=undefined
+PASS sync test for url=tel:1234, contentType=application/json
+PASS async test for url=tel:1234, contentType=undefined
+PASS async test for url=tel:1234, contentType=application/json
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/virtual/sxg-origin-trial/http/tests/loading/sxg/sxg-location-fragment-expected.txt b/third_party/WebKit/LayoutTests/virtual/sxg-origin-trial/http/tests/loading/sxg/sxg-location-fragment-expected.txt
new file mode 100644
index 0000000..10cbd1e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/sxg-origin-trial/http/tests/loading/sxg/sxg-location-fragment-expected.txt
@@ -0,0 +1,13 @@
+main frame - didStartProvisionalLoadForFrame
+main frame - didCommitLoadForFrame
+main frame - didReceiveTitle: Navigating to a Signed Exchange should preserve URL fragment
+main frame - didFinishDocumentLoadForFrame
+main frame - didHandleOnloadEventsForFrame
+main frame - didFinishLoadForFrame
+frame "sxg_iframe" - didReceiveTitle: 
+frame "sxg_iframe" - didStartProvisionalLoadForFrame
+frame "sxg_iframe" - didFailProvisionalLoadWithError
+This is a testharness.js-based test.
+FAIL Navigating to a Signed Exchange should preserve URL fragment promise_test: Unhandled rejection with value: "timeout"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn
index c0a915f..c6c030a0 100644
--- a/third_party/blink/public/BUILD.gn
+++ b/third_party/blink/public/BUILD.gn
@@ -893,6 +893,10 @@
     ":media_devices_mojo_bindings_blink__generator",
     ":mojo_bindings__generator",
     ":mojo_bindings_blink__generator",
+    "mojom:mojom_core__generator",
+    "mojom:mojom_core_blink__generator",
+    "mojom:mojom_platform__generator",
+    "mojom:mojom_platform_blink__generator",
   ]
 }
 
diff --git a/third_party/blink/public/mojom/frame/find_in_page.mojom b/third_party/blink/public/mojom/frame/find_in_page.mojom
index da7ca3e..691dc8a 100644
--- a/third_party/blink/public/mojom/frame/find_in_page.mojom
+++ b/third_party/blink/public/mojom/frame/find_in_page.mojom
@@ -24,26 +24,16 @@
   GetNearestFindResult(gfx.mojom.PointF point) => (float distance);
 
   // Activates a find result nearest to |point|, which is in fractions of the
-  // content document's width and height.
-  //
-  // Return values:
-  //
-  // |active_match_rect| will contain the bounding box of the activated
-  // find-in-page match marker. Might be an empty rect if there is none.
-  //
-  // |number_of_matches| is the current number of matches, or -1 if we
-  // shouldn't update number of matches.
-  //
-  // |active_match_ordinal| will contain the activated match's ordinal
-  // or -1 if  we shouldn't update the active match ordinal.
-  //
-  // |final_update| is true if it's the final find reply for the frame.
-  //
-  ActivateNearestFindResult(gfx.mojom.PointF point) =>
-                           (gfx.mojom.Rect active_match_rect,
-                           int32 number_of_matches,
-                           int32 active_match_ordinal,
-                           bool final_update);
+  // content document's width and height. This function will call either the
+  // SetActiveMatch or SetNumberOfMatches on the FindInPageClient for this
+  // FindInPage instance.
+  // TODO(rakina): Find a way to remove |request_id|
+  ActivateNearestFindResult(int32 request_id, gfx.mojom.PointF point);
+
+  // Sets the client for this FindInPage instance. Should be called before
+  // calling ActivateNearestFindResult.
+  // TODO(rakina): Remove the need for this?
+  SetClient(FindInPageClient client);
 
   // Returns the bounding boxes of the find-in-page match markers from the
   // frame. The bounding boxes are returned in find-in-page coordinates.
@@ -68,6 +58,21 @@
                 gfx.mojom.RectF active_match_rect);
 };
 
+// Per-frame client of FindInPage.
+interface FindInPageClient {
+  // Sets the number of matches of the frame to |number_of_matches|.
+  // If |final_update| is true, there will be no more update to the number of
+  // matches or active match for this frame.
+  SetNumberOfMatches(int32 request_id, uint32 number_of_matches,
+                     FindMatchUpdateType update_type);
+
+  // Sets the current active match rect and ordinal. This is the final
+  // find update for the frame, notifying the browser side that there will be
+  // no more update to number of matches or active match for this frame.
+  SetActiveMatch(int32 request_id, gfx.mojom.Rect active_match_rect,
+                 int32 active_match_ordinal);
+};
+
 // This enum defines what actions the renderer should take next when
 // the user has completed a find-in-page;
 enum StopFindAction {
@@ -78,3 +83,9 @@
   // The active match selection will be activated.
   kStopFindActionActivateSelection
 };
+
+// Type of updates for FindInPageClient::SetNumberOfMatches
+enum FindMatchUpdateType {
+  kFinalUpdate,
+  kMoreUpdatesComing
+};
diff --git a/third_party/blink/public/platform/mac/web_scrollbar_theme.h b/third_party/blink/public/platform/mac/web_scrollbar_theme.h
index efdfeab..f9e45ba49 100644
--- a/third_party/blink/public/platform/mac/web_scrollbar_theme.h
+++ b/third_party/blink/public/platform/mac/web_scrollbar_theme.h
@@ -36,6 +36,10 @@
 
 namespace blink {
 
+#if INSIDE_BLINK
+class WebScrollbarThemeClient;
+#endif
+
 // This enum must match NSScrollerStyle in the 10.7 SDK.
 enum ScrollerStyle { kScrollerStyleLegacy = 0, kScrollerStyleOverlay = 1 };
 
@@ -49,16 +53,25 @@
   // |preferredScrollerStyle| is the current value of +[NSScroller
   // preferredScrollerStyle].
   // |redraw| is true if the update requires a redraw to include the change.
-  // |WebScrollbarButtonsPlacement| is the current value of
-  // AppleScrollBarVariant. |jump_on_track_click| is the current value of
-  // AppleScrollerPagingBehavior.
+  // |jump_on_track_click| is the current value of AppleScrollerPagingBehavior.
   BLINK_EXPORT static void UpdateScrollbarsWithNSDefaults(
       float initial_button_delay,
       float autoscroll_button_delay,
       ScrollerStyle preferred_scroller_style,
       bool redraw,
-      WebScrollbarButtonsPlacement,
       bool jump_on_track_click);
+
+  static float InitialButtonDelay();
+  static float AutoscrollButtonDelay();
+  static ScrollerStyle PreferredScrollerStyle();
+  static bool JumpOnTrackClick();
+
+// Registered clients will receive a callback whenever
+// UpdateScrollbarsWithNSDefaults is called.
+#if INSIDE_BLINK
+  static void RegisterClient(WebScrollbarThemeClient& client);
+  static void UnregisterClient(WebScrollbarThemeClient& client);
+#endif
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/platform/platform.h b/third_party/blink/public/platform/platform.h
index f927253a..e406f9f 100644
--- a/third_party/blink/public/platform/platform.h
+++ b/third_party/blink/public/platform/platform.h
@@ -122,7 +122,6 @@
 class WebRTCPeerConnectionHandlerClient;
 class WebSandboxSupport;
 class WebSecurityOrigin;
-class WebSocketHandshakeThrottle;
 class WebSpeechSynthesizer;
 class WebSpeechSynthesizerClient;
 class WebStorageNamespace;
@@ -611,15 +610,6 @@
 
   virtual void UpdateWebRTCAPICount(WebRTCAPIName api_name) {}
 
-  // WebSocket ----------------------------------------------------------
-
-  // If this method returns non-null the returned object will be used to
-  // determine if/when a new WebSocket connection can be exposed to Javascript.
-  // TODO(nhiroki): Remove this once the off-main-thread WebSocket is enabled by
-  // default (https://crbug.com/825740).
-  virtual std::unique_ptr<WebSocketHandshakeThrottle>
-  CreateWebSocketHandshakeThrottle();
-
   // WebWorker ----------------------------------------------------------
 
   virtual void DidStartWorkerThread() {}
diff --git a/third_party/blink/public/web/web_context_menu_data.h b/third_party/blink/public/web/web_context_menu_data.h
index d5164b0..a297571 100644
--- a/third_party/blink/public/web/web_context_menu_data.h
+++ b/third_party/blink/public/web/web_context_menu_data.h
@@ -145,10 +145,14 @@
   enum InputFieldType {
     // Not an input field.
     kInputFieldTypeNone,
-    // type = text, tel, search, number, email, url
+    // type = text, search, email, url
     kInputFieldTypePlainText,
     // type = password
     kInputFieldTypePassword,
+    // type = number
+    kInputFieldTypeNumber,
+    // type = tel
+    kInputFieldTypeTelephone,
     // type = <etc.>
     kInputFieldTypeOther,
     kInputFieldTypeLast = kInputFieldTypeOther
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h
index 437e8b22..8bb6744 100644
--- a/third_party/blink/public/web/web_local_frame.h
+++ b/third_party/blink/public/web/web_local_frame.h
@@ -688,6 +688,26 @@
 
   virtual WebPlugin* GetWebPluginForFind() = 0;
 
+  // Notifies how many matches have been found in this frame so far, for a
+  // given identifier.  |final_update| specifies whether this is the last
+  // update for this frame.
+  virtual void ReportFindInPageMatchCount(int identifier,
+                                          int count,
+                                          bool final_update) = 0;
+
+  // Notifies what tick-mark rect is currently selected.   The given
+  // identifier lets the client know which request this message belongs
+  // to, so that it can choose to ignore the message if it has moved on
+  // to other things.  The selection rect is expected to have coordinates
+  // relative to the top left corner of the web page area and represent
+  // where on the screen the selection rect is currently located.
+  // |final_update| specifies whether this is the last update for this
+  // frame.
+  virtual void ReportFindInPageSelection(int identifier,
+                                         int active_match_ordinal,
+                                         const WebRect& selection,
+                                         bool final_update) = 0;
+
   // Context menu -----------------------------------------------------------
 
   // Returns the node that the context menu opened over.
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h
index cdb5e79..8b1b8f8e 100644
--- a/third_party/blink/public/web/web_local_frame_client.h
+++ b/third_party/blink/public/web/web_local_frame_client.h
@@ -701,22 +701,11 @@
 
   // Find-in-page notifications ------------------------------------------
 
-  // Notifies how many matches have been found in this frame so far, for a
-  // given identifier.  |finalUpdate| specifies whether this is the last
-  // update for this frame.
-  virtual void ReportFindInPageMatchCount(int identifier,
-                                          int count,
-                                          bool final_update) {}
-
-  // Notifies what tick-mark rect is currently selected.   The given
-  // identifier lets the client know which request this message belongs
-  // to, so that it can choose to ignore the message if it has moved on
-  // to other things.  The selection rect is expected to have coordinates
-  // relative to the top left corner of the web page area and represent
-  // where on the screen the selection rect is currently located.
-  virtual void ReportFindInPageSelection(int identifier,
-                                         int active_match_ordinal,
-                                         const WebRect& selection) {}
+  virtual void SendFindReply(int request_id,
+                             int match_count,
+                             int ordinal,
+                             const WebRect& selection_rect,
+                             bool final_status_update) {}
 
   // MediaStream -----------------------------------------------------
 
diff --git a/third_party/blink/renderer/bindings/core/v8/BUILD.gn b/third_party/blink/renderer/bindings/core/v8/BUILD.gn
index 8648fa71..521f6d6 100644
--- a/third_party/blink/renderer/bindings/core/v8/BUILD.gn
+++ b/third_party/blink/renderer/bindings/core/v8/BUILD.gn
@@ -257,8 +257,10 @@
              [ "//third_party/blink/renderer/core:config" ]
 
   deps = [
-    ":bindings_core_impl_generated",
+    ":bindings_core_v8_generated",
     "//skia",
+    "//third_party/blink/public:generate_mojo_bindings",
+    "//third_party/blink/renderer/core:all_generators",
     "//third_party/blink/renderer/platform",
     "//v8",
   ]
diff --git a/third_party/blink/renderer/core/dom/synchronous_mutation_notifier.cc b/third_party/blink/renderer/core/dom/synchronous_mutation_notifier.cc
index 53e1eb05..c2c71988 100644
--- a/third_party/blink/renderer/core/dom/synchronous_mutation_notifier.cc
+++ b/third_party/blink/renderer/core/dom/synchronous_mutation_notifier.cc
@@ -46,14 +46,7 @@
     unsigned offset,
     unsigned old_length,
     unsigned new_length) {
-  // Using ForEachObserverWithoutChecks() instead of ForEachObserver() is
-  // necessary because DocumentMarkerController::DidUpdateCharacterData ends up
-  // calling SynchronousMutationNotifier::RemoveObserver, which is unsafe and
-  // can result in memory corruption.
-  //
-  // TODO(crbug.com/862900): Fix DocumentMarkerController and switch to
-  //                         ForEachObsever() here.
-  ForEachObserverWithoutChecks([&](SynchronousMutationObserver* observer) {
+  ForEachObserver([&](SynchronousMutationObserver* observer) {
     observer->DidUpdateCharacterData(character_data, offset, old_length,
                                      new_length);
   });
diff --git a/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc b/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc
index 17f724a..147d873e 100644
--- a/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc
+++ b/third_party/blink/renderer/core/editing/commands/clipboard_commands.cc
@@ -34,6 +34,7 @@
 #include "third_party/blink/renderer/core/clipboard/data_transfer_access_policy.h"
 #include "third_party/blink/renderer/core/clipboard/system_clipboard.h"
 #include "third_party/blink/renderer/core/editing/commands/editing_commands_utilities.h"
+#include "third_party/blink/renderer/core/editing/editing_behavior.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
 #include "third_party/blink/renderer/core/editing/editor.h"
 #include "third_party/blink/renderer/core/editing/ephemeral_range.h"
diff --git a/third_party/blink/renderer/core/editing/commands/move_commands.cc b/third_party/blink/renderer/core/editing/commands/move_commands.cc
index 01dbd04..c9c11f8 100644
--- a/third_party/blink/renderer/core/editing/commands/move_commands.cc
+++ b/third_party/blink/renderer/core/editing/commands/move_commands.cc
@@ -31,6 +31,7 @@
 
 #include "third_party/blink/renderer/core/editing/commands/move_commands.h"
 
+#include "third_party/blink/renderer/core/editing/editing_behavior.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
 #include "third_party/blink/renderer/core/editing/editor.h"
 #include "third_party/blink/renderer/core/editing/frame_selection.h"
diff --git a/third_party/blink/renderer/core/editing/commands/style_commands.cc b/third_party/blink/renderer/core/editing/commands/style_commands.cc
index 54be08d2d..9063088 100644
--- a/third_party/blink/renderer/core/editing/commands/style_commands.cc
+++ b/third_party/blink/renderer/core/editing/commands/style_commands.cc
@@ -36,6 +36,7 @@
 #include "third_party/blink/renderer/core/css/css_property_value_set.h"
 #include "third_party/blink/renderer/core/css/css_value_list.h"
 #include "third_party/blink/renderer/core/editing/commands/apply_style_command.h"
+#include "third_party/blink/renderer/core/editing/editing_behavior.h"
 #include "third_party/blink/renderer/core/editing/editing_style_utilities.h"
 #include "third_party/blink/renderer/core/editing/editing_tri_state.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
diff --git a/third_party/blink/renderer/core/editing/commands/typing_command.cc b/third_party/blink/renderer/core/editing/commands/typing_command.cc
index 302caa96..327bb72 100644
--- a/third_party/blink/renderer/core/editing/commands/typing_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/typing_command.cc
@@ -37,6 +37,7 @@
 #include "third_party/blink/renderer/core/editing/commands/insert_line_break_command.h"
 #include "third_party/blink/renderer/core/editing/commands/insert_paragraph_separator_command.h"
 #include "third_party/blink/renderer/core/editing/commands/insert_text_command.h"
+#include "third_party/blink/renderer/core/editing/editing_behavior.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
 #include "third_party/blink/renderer/core/editing/editor.h"
 #include "third_party/blink/renderer/core/editing/ephemeral_range.h"
diff --git a/third_party/blink/renderer/core/editing/editor.cc b/third_party/blink/renderer/core/editing/editor.cc
index afc57ca..858da736 100644
--- a/third_party/blink/renderer/core/editing/editor.cc
+++ b/third_party/blink/renderer/core/editing/editor.cc
@@ -49,6 +49,7 @@
 #include "third_party/blink/renderer/core/editing/commands/simplify_markup_command.h"
 #include "third_party/blink/renderer/core/editing/commands/typing_command.h"
 #include "third_party/blink/renderer/core/editing/commands/undo_stack.h"
+#include "third_party/blink/renderer/core/editing/editing_behavior.h"
 #include "third_party/blink/renderer/core/editing/editing_style_utilities.h"
 #include "third_party/blink/renderer/core/editing/editing_tri_state.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
diff --git a/third_party/blink/renderer/core/editing/editor.h b/third_party/blink/renderer/core/editing/editor.h
index 7b44ff8..a92656b 100644
--- a/third_party/blink/renderer/core/editing/editor.h
+++ b/third_party/blink/renderer/core/editing/editor.h
@@ -30,7 +30,6 @@
 
 #include "base/macros.h"
 #include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/editing/editing_behavior.h"
 #include "third_party/blink/renderer/core/editing/editing_style.h"
 #include "third_party/blink/renderer/core/editing/finder/find_options.h"
 #include "third_party/blink/renderer/core/editing/forward.h"
@@ -43,6 +42,7 @@
 
 class CompositeEditCommand;
 class DragData;
+class EditingBehavior;
 class EditorCommand;
 class FrameSelection;
 class LocalFrame;
diff --git a/third_party/blink/renderer/core/editing/editor_key_bindings.cc b/third_party/blink/renderer/core/editing/editor_key_bindings.cc
index fc3b5e5..4e9cca8 100644
--- a/third_party/blink/renderer/core/editing/editor_key_bindings.cc
+++ b/third_party/blink/renderer/core/editing/editor_key_bindings.cc
@@ -28,6 +28,7 @@
 
 #include "third_party/blink/public/platform/web_input_event.h"
 #include "third_party/blink/renderer/core/editing/commands/editor_command.h"
+#include "third_party/blink/renderer/core/editing/editing_behavior.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
 #include "third_party/blink/renderer/core/editing/frame_selection.h"
 #include "third_party/blink/renderer/core/events/keyboard_event.h"
diff --git a/third_party/blink/renderer/core/editing/finder/text_finder.cc b/third_party/blink/renderer/core/editing/finder/text_finder.cc
index 152190f..3f01432 100644
--- a/third_party/blink/renderer/core/editing/finder/text_finder.cc
+++ b/third_party/blink/renderer/core/editing/finder/text_finder.cc
@@ -600,20 +600,17 @@
   total_match_count_ += count;
 
   // Update the UI with the latest findings.
-  if (OwnerFrame().Client()) {
-    OwnerFrame().Client()->ReportFindInPageMatchCount(
-        identifier, total_match_count_, !frame_scoping_ || !total_match_count_);
-  }
+  OwnerFrame().ReportFindInPageMatchCount(
+      identifier, total_match_count_, !frame_scoping_ || !total_match_count_);
 }
 
 void TextFinder::ReportFindInPageSelection(const WebRect& selection_rect,
                                            int active_match_ordinal,
                                            int identifier) {
   // Update the UI with the latest selection rect.
-  if (OwnerFrame().Client()) {
-    OwnerFrame().Client()->ReportFindInPageSelection(
-        identifier, active_match_ordinal, selection_rect);
-  }
+  OwnerFrame().ReportFindInPageSelection(identifier, active_match_ordinal,
+                                         selection_rect,
+                                         false /* final_update */);
   // Update accessibility too, so if the user commits to this query
   // we can move accessibility focus to this result.
   ReportFindInPageResultToAccessibility(identifier);
diff --git a/third_party/blink/renderer/core/editing/frame_selection.cc b/third_party/blink/renderer/core/editing/frame_selection.cc
index d88aac9c..c7b68dd 100644
--- a/third_party/blink/renderer/core/editing/frame_selection.cc
+++ b/third_party/blink/renderer/core/editing/frame_selection.cc
@@ -39,6 +39,7 @@
 #include "third_party/blink/renderer/core/dom/text.h"
 #include "third_party/blink/renderer/core/editing/caret_display_item_client.h"
 #include "third_party/blink/renderer/core/editing/commands/typing_command.h"
+#include "third_party/blink/renderer/core/editing/editing_behavior.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
 #include "third_party/blink/renderer/core/editing/editor.h"
 #include "third_party/blink/renderer/core/editing/ephemeral_range.h"
diff --git a/third_party/blink/renderer/core/editing/layout_selection.cc b/third_party/blink/renderer/core/editing/layout_selection.cc
index 2286b3e..ba5170d 100644
--- a/third_party/blink/renderer/core/editing/layout_selection.cc
+++ b/third_party/blink/renderer/core/editing/layout_selection.cc
@@ -40,70 +40,10 @@
 
 namespace blink {
 
-SelectionPaintRange::SelectionPaintRange(LayoutObject* start_layout_object,
-                                         base::Optional<unsigned> start_offset,
-                                         LayoutObject* end_layout_object,
-                                         base::Optional<unsigned> end_offset)
-    : start_layout_object_(start_layout_object),
-      start_offset_(start_offset),
-      end_layout_object_(end_layout_object),
-      end_offset_(end_offset) {}
-
-bool SelectionPaintRange::operator==(const SelectionPaintRange& other) const {
-  return start_layout_object_ == other.start_layout_object_ &&
-         start_offset_ == other.start_offset_ &&
-         end_layout_object_ == other.end_layout_object_ &&
-         end_offset_ == other.end_offset_;
-}
-
-LayoutObject* SelectionPaintRange::StartLayoutObject() const {
-  DCHECK(!IsNull());
-  return start_layout_object_;
-}
-
-base::Optional<unsigned> SelectionPaintRange::StartOffset() const {
-  DCHECK(!IsNull());
-  return start_offset_;
-}
-
-LayoutObject* SelectionPaintRange::EndLayoutObject() const {
-  DCHECK(!IsNull());
-  return end_layout_object_;
-}
-
-base::Optional<unsigned> SelectionPaintRange::EndOffset() const {
-  DCHECK(!IsNull());
-  return end_offset_;
-}
-
-SelectionPaintRange::Iterator::Iterator(const SelectionPaintRange* range) {
-  if (!range || range->IsNull()) {
-    current_ = nullptr;
-    return;
-  }
-  current_ = range->StartLayoutObject();
-  stop_ = range->EndLayoutObject()->NextInPreOrder();
-}
-
-LayoutObject* SelectionPaintRange::Iterator::operator*() const {
-  DCHECK(current_);
-  return current_;
-}
-
-SelectionPaintRange::Iterator& SelectionPaintRange::Iterator::operator++() {
-  DCHECK(current_);
-  current_ = current_->NextInPreOrder();
-  if (current_ && current_ != stop_)
-    return *this;
-
-  current_ = nullptr;
-  return *this;
-}
-
 LayoutSelection::LayoutSelection(FrameSelection& frame_selection)
     : frame_selection_(&frame_selection),
       has_pending_selection_(false),
-      paint_range_(SelectionPaintRange()) {}
+      has_selection_(false) {}
 
 enum class SelectionMode {
   kNone,
@@ -166,89 +106,64 @@
 // LayoutObjects each has SelectionState of kStart, kEnd, kStartAndEnd, or
 // kInside.
 using SelectedLayoutObjects = HashSet<LayoutObject*>;
+
+// The current selection to be painted is represented as 2 pairs of
+// (LayoutObject, offset).
+struct SelectionPaintRange {
+  STACK_ALLOCATED();
+  bool IsNull() const { return !start_layout_object; }
+  LayoutObject* start_layout_object = nullptr;
+  base::Optional<unsigned> start_offset = base::nullopt;
+  LayoutObject* end_layout_object = nullptr;
+  base::Optional<unsigned> end_offset = base::nullopt;
+};
+
 // OldSelectedLayoutObjects is current selected LayoutObjects with
 // current SelectionState which is kStart, kEnd, kStartAndEnd or kInside.
-using OldSelectedLayoutObjects = HashMap<LayoutObject*, SelectionState>;
-
-#ifndef NDEBUG
-void PrintSelectedLayoutObjects(
-    const SelectedLayoutObjects& new_selected_objects) {
-  std::stringstream stream;
-  stream << std::endl;
-  for (LayoutObject* layout_object : new_selected_objects) {
-    PrintLayoutObjectForSelection(stream, layout_object);
-    stream << std::endl;
-  }
-  LOG(INFO) << stream.str();
-}
-
-void PrintOldSelectedLayoutObjects(
-    const OldSelectedLayoutObjects& old_selected_objects) {
-  std::stringstream stream;
-  stream << std::endl;
-  for (const auto& key_pair : old_selected_objects) {
-    LayoutObject* layout_object = key_pair.key;
-    SelectionState old_state = key_pair.value;
-    PrintLayoutObjectForSelection(stream, layout_object);
-    stream << " old: " << old_state << std::endl;
-  }
-  LOG(INFO) << stream.str();
-}
-
-void PrintSelectionPaintRange(const SelectionPaintRange& paint_range) {
-  std::stringstream stream;
-  stream << std::endl << "layout_objects:" << std::endl;
-  for (LayoutObject* layout_object : paint_range) {
-    PrintLayoutObjectForSelection(stream, layout_object);
-    stream << std::endl;
-  }
-  LOG(INFO) << stream.str();
-}
-
-void PrintSelectionStateInLayoutView(const FrameSelection& selection) {
-  std::stringstream stream;
-  stream << std::endl << "layout_objects:" << std::endl;
-  LayoutView* layout_view = selection.GetDocument().GetLayoutView();
-  for (LayoutObject* layout_object = layout_view; layout_object;
-       layout_object = layout_object->NextInPreOrder()) {
-    PrintLayoutObjectForSelection(stream, layout_object);
-    stream << std::endl;
-  }
-  LOG(INFO) << stream.str();
-}
-#endif
-
-// This class represents a selection range in layout tree and each LayoutObject
-// is SelectionState-marked.
-class NewPaintRangeAndSelectedLayoutObjects {
+struct OldSelectedLayoutObjects {
   STACK_ALLOCATED();
-
- public:
-  NewPaintRangeAndSelectedLayoutObjects() = default;
-  NewPaintRangeAndSelectedLayoutObjects(SelectionPaintRange paint_range,
-                                        SelectedLayoutObjects selected_objects)
-      : paint_range_(paint_range),
-        selected_objects_(std::move(selected_objects)) {}
-  NewPaintRangeAndSelectedLayoutObjects(
-      NewPaintRangeAndSelectedLayoutObjects&& other) {
-    paint_range_ = other.paint_range_;
-    selected_objects_ = std::move(other.selected_objects_);
+  OldSelectedLayoutObjects() = default;
+  OldSelectedLayoutObjects(OldSelectedLayoutObjects&& other) {
+    paint_range = other.paint_range;
+    selected_map = std::move(other.selected_map);
   }
 
-  SelectionPaintRange PaintRange() const { return paint_range_; }
-
-  const SelectedLayoutObjects& LayoutObjects() const {
-    return selected_objects_;
-  }
+  SelectionPaintRange paint_range;
+  HashMap<LayoutObject*, SelectionState> selected_map;
 
  private:
-  SelectionPaintRange paint_range_;
-  SelectedLayoutObjects selected_objects_;
+  DISALLOW_COPY_AND_ASSIGN(OldSelectedLayoutObjects);
+};
+
+std::ostream& operator<<(std::ostream&, const OldSelectedLayoutObjects&);
+
+// This struct represents a selection range in layout tree and each
+// LayoutObject is SelectionState-marked.
+struct NewPaintRangeAndSelectedLayoutObjects {
+  STACK_ALLOCATED();
+
+  NewPaintRangeAndSelectedLayoutObjects() = default;
+  NewPaintRangeAndSelectedLayoutObjects(
+      SelectionPaintRange passed_paint_range,
+      SelectedLayoutObjects passed_selected_objects)
+      : paint_range(passed_paint_range),
+        selected_objects(std::move(passed_selected_objects)) {}
+  NewPaintRangeAndSelectedLayoutObjects(
+      NewPaintRangeAndSelectedLayoutObjects&& other) {
+    paint_range = other.paint_range;
+    selected_objects = std::move(other.selected_objects);
+  }
+
+  SelectionPaintRange paint_range;
+  SelectedLayoutObjects selected_objects;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(NewPaintRangeAndSelectedLayoutObjects);
 };
 
+std::ostream& operator<<(std::ostream&,
+                         const NewPaintRangeAndSelectedLayoutObjects&);
+
 static void SetShouldInvalidateIfNeeded(LayoutObject* layout_object) {
   if (layout_object->ShouldInvalidateSelection())
     return;
@@ -274,6 +189,14 @@
   }
 }
 
+static const Node* GetNodeOf(LayoutObject* layout_object) {
+  if (LayoutTextFragment* first_letter =
+          ToLayoutTextFragmentOrNull(layout_object)) {
+    return first_letter->AssociatedTextNode();
+  }
+  return layout_object->GetNode();
+}
+
 static void SetSelectionStateIfNeeded(LayoutObject* layout_object,
                                       SelectionState state) {
   DCHECK_NE(state, SelectionState::kContain) << layout_object;
@@ -282,14 +205,17 @@
     return;
   layout_object->SetSelectionState(state);
 
-  // Set containing block SelectionState kContain for CSS ::selection style.
-  // See LayoutObject::InvalidatePaintForSelection().
-  for (LayoutObject* containing_block = layout_object->ContainingBlock();
-       containing_block;
-       containing_block = containing_block->ContainingBlock()) {
-    if (containing_block->GetSelectionState() == SelectionState::kContain)
+  const Node* node = GetNodeOf(layout_object);
+  DCHECK(node);
+  // Set ancestors SelectionState kContain for CSS ::selection style.
+  // See LayoutObject::InvalidateSelectedChildrenOnStyleChange().
+  for (Node& ancestor : FlatTreeTraversal::AncestorsOf(*node)) {
+    LayoutObject* ancestor_layout = ancestor.GetLayoutObject();
+    if (!ancestor_layout)
+      continue;
+    if (ancestor_layout->GetSelectionState() == SelectionState::kContain)
       return;
-    containing_block->LayoutObject::SetSelectionState(SelectionState::kContain);
+    ancestor_layout->LayoutObject::SetSelectionState(SelectionState::kContain);
   }
 }
 
@@ -297,13 +223,12 @@
 // comparing them in |new_range| and |old_range|.
 static void SetShouldInvalidateSelection(
     const NewPaintRangeAndSelectedLayoutObjects& new_range,
-    const SelectionPaintRange& old_range,
     const OldSelectedLayoutObjects& old_selected_objects) {
   // We invalidate each LayoutObject in new SelectionPaintRange which
   // has SelectionState of kStart, kEnd, kStartAndEnd, or kInside
   // and is not in old SelectionPaintRange.
-  for (LayoutObject* layout_object : new_range.LayoutObjects()) {
-    if (old_selected_objects.Contains(layout_object))
+  for (LayoutObject* layout_object : new_range.selected_objects) {
+    if (old_selected_objects.selected_map.Contains(layout_object))
       continue;
     const SelectionState new_state = layout_object->GetSelectionState();
     DCHECK_NE(new_state, SelectionState::kContain) << layout_object;
@@ -314,7 +239,7 @@
   // each of:
   // 1. LayoutObject was painted and would not be painted.
   // 2. LayoutObject was not painted and would be painted.
-  for (const auto& key_value : old_selected_objects) {
+  for (const auto& key_value : old_selected_objects.selected_map) {
     LayoutObject* const layout_object = key_value.key;
     const SelectionState old_state = key_value.value;
     const SelectionState new_state = layout_object->GetSelectionState();
@@ -329,77 +254,129 @@
   }
 
   // Invalidate Selection start/end is moving on a same node.
-  const SelectionPaintRange& new_paint_range = new_range.PaintRange();
-  if (new_paint_range.IsNull() || old_range.IsNull())
+  const SelectionPaintRange& new_paint_range = new_range.paint_range;
+  const SelectionPaintRange& old_paint_range = old_selected_objects.paint_range;
+  if (new_paint_range.IsNull())
     return;
-  if (new_paint_range.StartLayoutObject()->IsText() &&
-      new_paint_range.StartLayoutObject() == old_range.StartLayoutObject() &&
-      new_paint_range.StartOffset() != old_range.StartOffset())
-    SetShouldInvalidateIfNeeded(new_paint_range.StartLayoutObject());
-  if (new_paint_range.EndLayoutObject()->IsText() &&
-      new_paint_range.EndLayoutObject() == old_range.EndLayoutObject() &&
-      new_paint_range.EndOffset() != old_range.EndOffset())
-    SetShouldInvalidateIfNeeded(new_paint_range.EndLayoutObject());
+  if (new_paint_range.start_layout_object->IsText() &&
+      new_paint_range.start_layout_object ==
+          old_paint_range.start_layout_object &&
+      new_paint_range.start_offset != old_paint_range.start_offset)
+    SetShouldInvalidateIfNeeded(new_paint_range.start_layout_object);
+  if (new_paint_range.end_layout_object->IsText() &&
+      new_paint_range.end_layout_object == old_paint_range.end_layout_object &&
+      new_paint_range.end_offset != old_paint_range.end_offset)
+    SetShouldInvalidateIfNeeded(new_paint_range.end_layout_object);
 }
 
 base::Optional<unsigned> LayoutSelection::SelectionStart() const {
   DCHECK(!HasPendingSelection());
-  if (paint_range_.IsNull())
-    return base::nullopt;
-  return paint_range_.StartOffset();
+  return start_offset_;
 }
 
 base::Optional<unsigned> LayoutSelection::SelectionEnd() const {
   DCHECK(!HasPendingSelection());
-  if (paint_range_.IsNull())
-    return base::nullopt;
-  return paint_range_.EndOffset();
+  return end_offset_;
+}
+
+static LayoutTextFragment* FirstLetterPartFor(
+    const LayoutObject* layout_object) {
+  if (!layout_object->IsText())
+    return nullptr;
+  if (const LayoutText* layout_text = ToLayoutTextOrNull(layout_object))
+    return ToLayoutTextFragmentOrNull(layout_text->GetFirstLetterPart());
+  return nullptr;
+}
+
+template <typename Visitor>
+static void VisitSelectedInclusiveDescendantsOfInternal(const Node& node,
+                                                        Visitor* visitor) {
+  LayoutObject* layout_object = node.GetLayoutObject();
+  if (!layout_object)
+    return;
+  if (LayoutTextFragment* first_letter = FirstLetterPartFor(layout_object)) {
+    if (first_letter->GetSelectionState() != SelectionState::kNone)
+      visitor->Visit(first_letter);
+  }
+  if (layout_object->GetSelectionState() == SelectionState::kNone)
+    return;
+  visitor->Visit(layout_object);
+
+  for (Node& child : FlatTreeTraversal::ChildrenOf(node))
+    VisitSelectedInclusiveDescendantsOfInternal(child, visitor);
+}
+
+static inline bool IsFlatTreeClean(const Node& node) {
+  return !node.GetDocument().IsSlotAssignmentOrLegacyDistributionDirty();
+}
+
+template <typename Visitor>
+static void VisitSelectedInclusiveDescendantsOf(const Node& node,
+                                                Visitor* visitor) {
+  DCHECK(IsFlatTreeClean(node));
+  return VisitSelectedInclusiveDescendantsOfInternal(node, visitor);
 }
 
 static OldSelectedLayoutObjects ResetOldSelectedLayoutObjects(
-    const SelectionPaintRange& old_range) {
-  OldSelectedLayoutObjects old_selected_objects;
-  HashSet<LayoutObject*> containing_block_set;
-  for (LayoutObject* layout_object : old_range) {
-    const SelectionState old_state = layout_object->GetSelectionState();
-    if (old_state == SelectionState::kNone)
-      continue;
-    if (old_state != SelectionState::kContain)
-      old_selected_objects.insert(layout_object, old_state);
-    layout_object->SetSelectionState(SelectionState::kNone);
+    const Node& root,
+    base::Optional<unsigned> old_start_offset,
+    base::Optional<unsigned> old_end_offset) {
+  class OldSelectedVisitor {
+    STACK_ALLOCATED();
 
-    // Reset containing block SelectionState for CSS ::selection style.
-    // See LayoutObject::InvalidatePaintForSelection().
-    for (LayoutObject* containing_block = layout_object->ContainingBlock();
-         containing_block;
-         containing_block = containing_block->ContainingBlock()) {
-      if (containing_block_set.Contains(containing_block))
-        break;
-      containing_block->SetSelectionState(SelectionState::kNone);
-      containing_block_set.insert(containing_block);
+   public:
+    OldSelectedVisitor(base::Optional<unsigned> passed_old_start_offset,
+                       base::Optional<unsigned> passed_old_end_offset)
+        : old_start_offset(passed_old_start_offset),
+          old_end_offset(passed_old_end_offset) {}
+
+    void Visit(LayoutObject* layout_object) {
+      const SelectionState old_state = layout_object->GetSelectionState();
+      DCHECK_NE(old_state, SelectionState::kNone) << layout_object;
+      layout_object->SetSelectionState(SelectionState::kNone);
+      if (old_state == SelectionState::kContain)
+        return;
+      old_selected_objects.selected_map.insert(layout_object, old_state);
+      if (old_state == SelectionState::kInside)
+        return;
+      switch (old_state) {
+        case SelectionState::kStart: {
+          DCHECK(!old_selected_objects.paint_range.start_layout_object);
+          old_selected_objects.paint_range.start_layout_object = layout_object;
+          old_selected_objects.paint_range.start_offset = old_start_offset;
+          break;
+        }
+        case SelectionState::kEnd: {
+          DCHECK(!old_selected_objects.paint_range.end_layout_object);
+          old_selected_objects.paint_range.end_layout_object = layout_object;
+          old_selected_objects.paint_range.end_offset = old_end_offset;
+          break;
+        }
+        case SelectionState::kStartAndEnd: {
+          DCHECK(!old_selected_objects.paint_range.start_layout_object);
+          DCHECK(!old_selected_objects.paint_range.end_layout_object);
+          old_selected_objects.paint_range.start_layout_object = layout_object;
+          old_selected_objects.paint_range.start_offset = old_start_offset;
+          old_selected_objects.paint_range.end_layout_object = layout_object;
+          old_selected_objects.paint_range.end_offset = old_end_offset;
+          break;
+        }
+        default: {
+          NOTREACHED();
+          break;
+        }
+      }
     }
-  }
-  return old_selected_objects;
+
+    OldSelectedLayoutObjects old_selected_objects;
+    const base::Optional<unsigned> old_start_offset;
+    const base::Optional<unsigned> old_end_offset;
+  } visitor(old_start_offset, old_end_offset);
+  VisitSelectedInclusiveDescendantsOf(root, &visitor);
+  return std::move(visitor.old_selected_objects);
 }
 
-void LayoutSelection::ClearSelection() {
-  // For querying Layer::compositingState()
-  // This is correct, since destroying layout objects needs to cause eager paint
-  // invalidations.
-  DisableCompositingQueryAsserts disabler;
-
-  // Just return if the selection is already empty.
-  if (paint_range_.IsNull())
-    return;
-
-  const OldSelectedLayoutObjects& old_selected_objects =
-      ResetOldSelectedLayoutObjects(paint_range_);
-  for (LayoutObject* const layout_object : old_selected_objects.Keys())
-    SetShouldInvalidateIfNeeded(layout_object);
-
-  // Reset selection.
-  paint_range_ = SelectionPaintRange();
-}
+void LayoutSelection::ClearSelection() {}
 
 static base::Optional<unsigned> ComputeStartOffset(
     const LayoutObject& layout_object,
@@ -425,15 +402,6 @@
   return ToText(layout_node)->length();
 }
 
-static LayoutTextFragment* FirstLetterPartFor(LayoutObject* layout_object) {
-  if (!layout_object->IsText())
-    return nullptr;
-  if (!ToLayoutText(layout_object)->IsTextFragment())
-    return nullptr;
-  return ToLayoutTextFragment(const_cast<LayoutObject*>(
-      AssociatedLayoutObjectOf(*layout_object->GetNode(), 0)));
-}
-
 static void MarkSelected(SelectedLayoutObjects* selected_objects,
                          LayoutObject* layout_object,
                          SelectionState state) {
@@ -676,23 +644,23 @@
     base::Optional<unsigned> start_node_offset,
     LayoutObject* end_layout_object,
     base::Optional<unsigned> end_node_offset) {
-  if (new_range.PaintRange().IsNull())
+  if (new_range.paint_range.IsNull())
     return {};
-  LayoutObject* const start = new_range.PaintRange().StartLayoutObject();
+  LayoutObject* const start = new_range.paint_range.start_layout_object;
   // If LayoutObject is not in NG, use legacy offset.
   const base::Optional<unsigned> start_offset =
       start->EnclosingNGBlockFlow()
           ? GetTextContentOffsetStart(start_layout_object, start_node_offset)
-          : new_range.PaintRange().StartOffset();
+          : new_range.paint_range.start_offset;
 
-  LayoutObject* const end = new_range.PaintRange().EndLayoutObject();
+  LayoutObject* const end = new_range.paint_range.end_layout_object;
   const base::Optional<unsigned> end_offset =
       end->EnclosingNGBlockFlow()
           ? GetTextContentOffsetEnd(end_layout_object, end_node_offset)
-          : new_range.PaintRange().EndOffset();
+          : new_range.paint_range.end_offset;
 
   return {{start, start_offset, end, end_offset},
-          std::move(new_range.LayoutObjects())};
+          std::move(new_range.selected_objects)};
 }
 
 // ClampOffset modifies |offset| fixed in a range of |text_fragment| start/end
@@ -868,6 +836,34 @@
   has_pending_selection_ = true;
 }
 
+void AssertNewRangeSanity(
+    const NewPaintRangeAndSelectedLayoutObjects& new_range) {
+#if DCHECK_IS_ON()
+  const SelectionPaintRange& paint_range = new_range.paint_range;
+  if (paint_range.start_layout_object) {
+    DCHECK(paint_range.end_layout_object) << new_range;
+    DCHECK(paint_range.start_layout_object->GetSelectionState() ==
+               SelectionState::kStart ||
+           paint_range.start_layout_object->GetSelectionState() ==
+               SelectionState::kStartAndEnd)
+        << new_range;
+    DCHECK(paint_range.end_layout_object->GetSelectionState() ==
+               SelectionState::kEnd ||
+           paint_range.end_layout_object->GetSelectionState() ==
+               SelectionState::kStartAndEnd);
+    DCHECK(new_range.selected_objects.Contains(paint_range.start_layout_object))
+        << new_range;
+    DCHECK(new_range.selected_objects.Contains(paint_range.end_layout_object))
+        << new_range;
+    return;
+  }
+  DCHECK(!paint_range.end_layout_object) << new_range;
+  DCHECK(!paint_range.start_offset.has_value()) << new_range;
+  DCHECK(!paint_range.end_offset.has_value()) << new_range;
+  DCHECK(new_range.selected_objects.IsEmpty()) << new_range;
+#endif
+}
+
 void LayoutSelection::Commit() {
   if (!HasPendingSelection())
     return;
@@ -880,56 +876,24 @@
       frame_selection_->GetDocument().Lifecycle());
 
   const OldSelectedLayoutObjects& old_selected_objects =
-      ResetOldSelectedLayoutObjects(paint_range_);
+      ResetOldSelectedLayoutObjects(frame_selection_->GetDocument(),
+                                    start_offset_, end_offset_);
   const NewPaintRangeAndSelectedLayoutObjects& new_range =
       CalcSelectionRangeAndSetSelectionState(*frame_selection_);
+  AssertNewRangeSanity(new_range);
   DCHECK(frame_selection_->GetDocument().GetLayoutView()->GetFrameView());
-  SetShouldInvalidateSelection(new_range, paint_range_, old_selected_objects);
+  SetShouldInvalidateSelection(new_range, old_selected_objects);
 
-  paint_range_ = new_range.PaintRange();
-  if (paint_range_.IsNull())
-    return;
-  // TODO(yoichio): Remove this if state.
-  // This SelectionState reassignment is ad-hoc patch for
-  // prohibiting use-after-free(crbug.com/752715).
-  // LayoutText::setSelectionState(state) propergates |state| to ancestor
-  // LayoutObjects, which can accidentally change start/end LayoutObject state
-  // then LayoutObject::IsSelectionBorder() returns false although we should
-  // clear selection at LayoutObject::WillBeRemoved().
-  // We should make LayoutObject::setSelectionState() trivial and remove
-  // such propagation or at least do it in LayoutSelection.
-  if ((paint_range_.StartLayoutObject()->GetSelectionState() !=
-           SelectionState::kStart &&
-       paint_range_.StartLayoutObject()->GetSelectionState() !=
-           SelectionState::kStartAndEnd) ||
-      (paint_range_.EndLayoutObject()->GetSelectionState() !=
-           SelectionState::kEnd &&
-       paint_range_.EndLayoutObject()->GetSelectionState() !=
-           SelectionState::kStartAndEnd)) {
-    if (paint_range_.StartLayoutObject() == paint_range_.EndLayoutObject()) {
-      paint_range_.StartLayoutObject()->SetSelectionState(
-          SelectionState::kStartAndEnd);
-    } else {
-      paint_range_.StartLayoutObject()->SetSelectionState(
-          SelectionState::kStart);
-      paint_range_.EndLayoutObject()->SetSelectionState(SelectionState::kEnd);
-    }
-  }
-  // TODO(yoichio): If start == end, they should be kStartAndEnd.
-  // If not, start.SelectionState == kStart and vice versa.
-  DCHECK(paint_range_.StartLayoutObject()->GetSelectionState() ==
-             SelectionState::kStart ||
-         paint_range_.StartLayoutObject()->GetSelectionState() ==
-             SelectionState::kStartAndEnd);
-  DCHECK(paint_range_.EndLayoutObject()->GetSelectionState() ==
-             SelectionState::kEnd ||
-         paint_range_.EndLayoutObject()->GetSelectionState() ==
-             SelectionState::kStartAndEnd);
+  start_offset_ = new_range.paint_range.start_offset;
+  end_offset_ = new_range.paint_range.end_offset;
+  has_selection_ = !new_range.paint_range.IsNull();
 }
 
 void LayoutSelection::OnDocumentShutdown() {
   has_pending_selection_ = false;
-  paint_range_ = SelectionPaintRange();
+  has_selection_ = false;
+  start_offset_ = base::nullopt;
+  end_offset_ = base::nullopt;
 }
 
 static LayoutRect SelectionRectForLayoutObject(const LayoutObject* object) {
@@ -944,31 +908,43 @@
 
 IntRect LayoutSelection::AbsoluteSelectionBounds() {
   Commit();
-  if (paint_range_.IsNull())
+  if (!has_selection_)
     return IntRect();
 
   // Create a single bounding box rect that encloses the whole selection.
-  LayoutRect selected_rect;
-  for (LayoutObject* layout_object : paint_range_) {
-    const SelectionState state = layout_object->GetSelectionState();
-    if (state == SelectionState::kContain || state == SelectionState::kNone)
-      continue;
-    selected_rect.Unite(SelectionRectForLayoutObject(layout_object));
-  }
+  class SelectionBoundsVisitor {
+    STACK_ALLOCATED();
 
-  return PixelSnappedIntRect(selected_rect);
+   public:
+    void Visit(LayoutObject* layout_object) {
+      if (layout_object->GetSelectionState() == SelectionState::kContain)
+        return;
+      selected_rect.Unite(SelectionRectForLayoutObject(layout_object));
+    }
+    LayoutRect selected_rect;
+  } visitor;
+  VisitSelectedInclusiveDescendantsOf(frame_selection_->GetDocument(),
+                                      &visitor);
+  return PixelSnappedIntRect(visitor.selected_rect);
 }
 
 void LayoutSelection::InvalidatePaintForSelection() {
-  if (paint_range_.IsNull())
+  if (!has_selection_)
     return;
 
-  for (LayoutObject* runner : paint_range_) {
-    if (runner->GetSelectionState() == SelectionState::kNone)
-      continue;
+  class InvalidatingVisitor {
+    STACK_ALLOCATED();
 
-    runner->SetShouldInvalidateSelection();
-  }
+   public:
+    void Visit(LayoutObject* layout_object) {
+      if (layout_object->GetSelectionState() == SelectionState::kContain)
+        return;
+      layout_object->SetShouldInvalidateSelection();
+    }
+    LayoutRect selected_rect;
+  } visitor;
+  VisitSelectedInclusiveDescendantsOf(frame_selection_->GetDocument(),
+                                      &visitor);
 }
 
 void LayoutSelection::Trace(blink::Visitor* visitor) {
@@ -997,12 +973,104 @@
           << (layout_object->ShouldInvalidateSelection() ? ", ShouldInvalidate"
                                                          : ", NotInvalidate");
 }
-#ifndef NDEBUG
+
+#if DCHECK_IS_ON()
 void ShowLayoutObjectForSelection(LayoutObject* layout_object) {
   std::stringstream stream;
   PrintLayoutObjectForSelection(stream, layout_object);
   LOG(INFO) << '\n' << stream.str();
 }
+
+std::ostream& operator<<(std::ostream& ostream,
+                         const base::Optional<unsigned>& offset) {
+  if (offset.has_value())
+    ostream << offset.value();
+  else
+    ostream << "<nullopt>";
+  return ostream;
+}
+
+std::ostream& operator<<(std::ostream& ostream,
+                         const SelectionPaintRange& range) {
+  ostream << range.start_layout_object << ": " << range.start_offset << ", "
+          << range.end_layout_object << ": " << range.end_offset;
+  return ostream;
+}
+
+std::ostream& operator<<(std::ostream& ostream,
+                         const HashMap<LayoutObject*, SelectionState>& map) {
+  ostream << "[";
+  const char* comma = "";
+  for (const auto& key_value : map) {
+    LayoutObject* const layout_object = key_value.key;
+    const SelectionState old_state = key_value.value;
+    ostream << comma << layout_object << "." << old_state;
+    comma = ", ";
+  }
+  ostream << "]";
+  return ostream;
+}
+
+std::ostream& operator<<(std::ostream& ostream,
+                         const OldSelectedLayoutObjects& objects) {
+  ostream << objects.paint_range << ". " << objects.selected_map;
+  return ostream;
+}
+
+std::ostream& operator<<(std::ostream& ostream,
+                         const SelectedLayoutObjects& selected_objects) {
+  ostream << "[";
+  const char* comma = "";
+  for (LayoutObject* layout_object : selected_objects) {
+    ostream << comma << layout_object;
+    comma = ", ";
+  }
+  ostream << "]";
+  return ostream;
+}
+
+std::ostream& operator<<(
+    std::ostream& ostream,
+    const NewPaintRangeAndSelectedLayoutObjects& new_range) {
+  ostream << new_range.paint_range << ". " << new_range.selected_objects;
+  return ostream;
+}
+
+void PrintSelectedLayoutObjects(
+    const SelectedLayoutObjects& new_selected_objects) {
+  std::stringstream stream;
+  stream << std::endl;
+  for (LayoutObject* layout_object : new_selected_objects) {
+    PrintLayoutObjectForSelection(stream, layout_object);
+    stream << std::endl;
+  }
+  LOG(INFO) << stream.str();
+}
+
+void PrintOldSelectedLayoutObjects(
+    const OldSelectedLayoutObjects& old_selected_objects) {
+  std::stringstream stream;
+  stream << std::endl;
+  for (const auto& key_pair : old_selected_objects.selected_map) {
+    LayoutObject* layout_object = key_pair.key;
+    SelectionState old_state = key_pair.value;
+    PrintLayoutObjectForSelection(stream, layout_object);
+    stream << " old: " << old_state << std::endl;
+  }
+  LOG(INFO) << stream.str();
+}
+
+void PrintSelectionStateInLayoutView(const FrameSelection& selection) {
+  std::stringstream stream;
+  stream << std::endl << "layout_objects:" << std::endl;
+  LayoutView* layout_view = selection.GetDocument().GetLayoutView();
+  for (LayoutObject* layout_object = layout_view; layout_object;
+       layout_object = layout_object->NextInPreOrder()) {
+    PrintLayoutObjectForSelection(stream, layout_object);
+    stream << std::endl;
+  }
+  LOG(INFO) << stream.str();
+}
 #endif
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/editing/layout_selection.h b/third_party/blink/renderer/core/editing/layout_selection.h
index 42daa45..7692fe1 100644
--- a/third_party/blink/renderer/core/editing/layout_selection.h
+++ b/third_party/blink/renderer/core/editing/layout_selection.h
@@ -34,60 +34,6 @@
 class NGPaintFragment;
 class FrameSelection;
 struct LayoutSelectionStatus;
-// This class represents a selection range in layout tree for painting and
-// paint invalidation.
-// The current selection to be painted is represented as 2 pairs of
-// (LayoutObject, offset).
-// 2 LayoutObjects are only valid for |Text| node without 'transform' or
-// 'first-letter'.
-// TODO(editing-dev): Clarify the meaning of "offset".
-// editing/ passes them as offsets in the DOM tree but layout uses them as
-// offset in the layout tree. This doesn't work in the cases of
-// CSS first-letter or character transform. See crbug.com/17528.
-class SelectionPaintRange {
-  DISALLOW_NEW();
-
- public:
-  class Iterator
-      : public std::iterator<std::input_iterator_tag, LayoutObject*> {
-   public:
-    explicit Iterator(const SelectionPaintRange*);
-    Iterator(const Iterator&) = default;
-    bool operator==(const Iterator& other) const {
-      return current_ == other.current_;
-    }
-    bool operator!=(const Iterator& other) const { return !operator==(other); }
-    Iterator& operator++();
-    LayoutObject* operator*() const;
-
-   private:
-    LayoutObject* current_;
-    const LayoutObject* stop_;
-  };
-  Iterator begin() const { return Iterator(this); };
-  Iterator end() const { return Iterator(nullptr); };
-
-  SelectionPaintRange() = default;
-  SelectionPaintRange(LayoutObject* start_layout_object,
-                      base::Optional<unsigned> start_offset,
-                      LayoutObject* end_layout_object,
-                      base::Optional<unsigned> end_offset);
-
-  bool operator==(const SelectionPaintRange& other) const;
-
-  LayoutObject* StartLayoutObject() const;
-  base::Optional<unsigned> StartOffset() const;
-  LayoutObject* EndLayoutObject() const;
-  base::Optional<unsigned> EndOffset() const;
-
-  bool IsNull() const { return !start_layout_object_; }
-
- private:
-  LayoutObject* start_layout_object_ = nullptr;
-  base::Optional<unsigned> start_offset_ = base::nullopt;
-  LayoutObject* end_layout_object_ = nullptr;
-  base::Optional<unsigned> end_offset_ = base::nullopt;
-};
 
 class LayoutSelection final : public GarbageCollected<LayoutSelection> {
  public:
@@ -102,6 +48,7 @@
   IntRect AbsoluteSelectionBounds();
   void InvalidatePaintForSelection();
 
+  // TODO(yoichio): Remove this function since this doesn't do anything.
   void ClearSelection();
   base::Optional<unsigned> SelectionStart() const;
   base::Optional<unsigned> SelectionEnd() const;
@@ -116,8 +63,19 @@
 
   Member<FrameSelection> frame_selection_;
   bool has_pending_selection_ : 1;
-
-  SelectionPaintRange paint_range_;
+  // Each offset represents text offsets on selection edge if it is text.
+  // For example, suppose we select "f^oo<br><img>|",
+  // |start_offset_| is 1 and |end_offset_| is nullopt.
+  // Each of them is only valid for a |Text| node without 'transform' or
+  // 'first-letter'.
+  // TODO(editing-dev): Clarify the meaning of "offset".
+  // editing/ passes them as offsets in the DOM tree but layout uses them as
+  // offset in the layout tree. This doesn't work in the cases of
+  // character transform. See crbug.com/17528.
+  base::Optional<unsigned> start_offset_;
+  base::Optional<unsigned> end_offset_;
+  // This is true if at least one LayoutObject has a valid SelectionState.
+  bool has_selection_;
 };
 
 void CORE_EXPORT PrintLayoutObjectForSelection(std::ostream&, LayoutObject*);
diff --git a/third_party/blink/renderer/core/editing/layout_selection_test.cc b/third_party/blink/renderer/core/editing/layout_selection_test.cc
index abb63da7..06bedcc 100644
--- a/third_party/blink/renderer/core/editing/layout_selection_test.cc
+++ b/third_party/blink/renderer/core/editing/layout_selection_test.cc
@@ -139,26 +139,19 @@
     ostream << "'" << text.data().Utf8().data() << "'";
   }
 
-  void PrintSelectionInfo(std::ostream& ostream, LayoutObject* layout_object) {
+  void PrintSelectionInfo(std::ostream& ostream, const Node& node) {
+    if (const Text* text = ToTextOrNull(node))
+      PrintText(ostream, *text);
+    else if (const Element* element = ToElementOrNull(node))
+      ostream << element->tagName().Utf8().data();
+    else
+      ostream << node;
+
+    LayoutObject* layout_object = node.GetLayoutObject();
     if (!layout_object) {
-      ostream << "<null>";
+      ostream << ", <null LayoutObject> ";
       return;
     }
-    if (const LayoutTextFragment* fragment =
-            ToLayoutTextFragmentOrNull(*layout_object)) {
-      // TODO(yoichio): Treat LayoutQuote which may generate LayoutTextFragment
-      // that's neither first-letter nor remaining text.
-      if (fragment->IsRemainingTextLayoutObject())
-        ostream << "remaining part of ";
-      else
-        ostream << "first-letter of ";
-      PrintText(ostream, *fragment->AssociatedTextNode());
-    } else {
-      if (Text* text = ToTextOrNull(layout_object->GetNode()))
-        PrintText(ostream, *text);
-      else
-        ostream << layout_object->GetNode();
-    }
     ostream << ", " << layout_object->GetSelectionState()
             << (layout_object->ShouldInvalidateSelection()
                     ? ", ShouldInvalidate "
@@ -169,7 +162,7 @@
                             const Node& node,
                             size_t depth) {
     ostream << RepeatString("  ", depth).Utf8().data();
-    PrintSelectionInfo(ostream, node.GetLayoutObject());
+    PrintSelectionInfo(ostream, node);
     if (ShadowRoot* shadow_root = node.GetShadowRoot()) {
       ostream << std::endl << RepeatString("  ", depth + 1).Utf8().data();
       ostream << "#shadow-root";
@@ -415,7 +408,7 @@
   TEST_NEXT("Foo", kInside, ShouldInvalidate);
   TEST_NEXT(IsLayoutOf("SPAN"), kNone, NotInvalidate);
   TEST_NEXT("bar1", kNone, NotInvalidate);
-  TEST_NEXT(IsLayoutOf("SPAN"), kNone, NotInvalidate);
+  TEST_NEXT(IsLayoutOf("SPAN"), kContain, NotInvalidate);
   TEST_NEXT("bar2", kEnd, ShouldInvalidate);
   TEST_CHECK();
 }
@@ -438,7 +431,7 @@
   TEST_NEXT("div1", kNone, NotInvalidate);
   TEST_NEXT(IsLayoutBlockFlow, kContain, NotInvalidate);
   TEST_NEXT("foo", kNone, NotInvalidate);
-  TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
+  TEST_NEXT(IsLayoutInline, kContain, NotInvalidate);
   TEST_NEXT("bar", kStartAndEnd, ShouldInvalidate);
   TEST_NEXT("baz", kNone, NotInvalidate);
   TEST_CHECK();
@@ -488,8 +481,8 @@
           .Build());
   Selection().CommitAppearanceIfNeeded();
   TEST_RESET();
-  TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
-  TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
+  TEST_NEXT(IsLayoutOf("BODY"), kContain, NotInvalidate);
+  TEST_NEXT(IsLayoutOf("SPAN"), kContain, NotInvalidate);
   TEST_NEXT(IsLayoutTextFragmentOf("f"), kStart, ShouldInvalidate);
   TEST_NEXT(IsLayoutTextFragmentOf("oo"), kEnd, ShouldInvalidate);
   TEST_CHECK();
@@ -509,7 +502,8 @@
   TEST_NEXT("baz", kEnd, ShouldInvalidate);
   TEST_CHECK();
 
-  Selection().ClearLayoutSelection();
+  Selection().Clear();
+  Selection().CommitAppearanceIfNeeded();
   TEST_RESET();
   TEST_NEXT(IsLayoutBlock, kNone, NotInvalidate);
   TEST_NEXT("foo", kNone, ShouldInvalidate);
@@ -594,7 +588,7 @@
   TEST_RESET();
   TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
   TEST_NEXT("foo", kStart, ShouldInvalidate);
-  TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
+  TEST_NEXT(IsLayoutInline, kContain, NotInvalidate);
   TEST_NEXT("bar", kEnd, ShouldInvalidate);
   TEST_CHECK();
   EXPECT_EQ(1u, Selection().LayoutSelectionStart());
@@ -605,7 +599,7 @@
   TEST_RESET();
   TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
   TEST_NEXT("foo", kStart, NotInvalidate);
-  TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
+  TEST_NEXT(IsLayoutInline, kContain, NotInvalidate);
   TEST_NEXT("bar", kEnd, NotInvalidate);
   TEST_CHECK();
 
@@ -620,7 +614,7 @@
   TEST_RESET();
   TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
   TEST_NEXT("foo", kStart, ShouldInvalidate);
-  TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
+  TEST_NEXT(IsLayoutInline, kContain, NotInvalidate);
   TEST_NEXT("bar", kEnd, NotInvalidate);
   TEST_CHECK();
   EXPECT_EQ(2u, Selection().LayoutSelectionStart());
@@ -635,7 +629,7 @@
   TEST_RESET();
   TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
   TEST_NEXT("foo", kStart, ShouldInvalidate);
-  TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
+  TEST_NEXT(IsLayoutInline, kContain, NotInvalidate);
   TEST_NEXT("bar", kEnd, ShouldInvalidate);
   TEST_CHECK();
   EXPECT_EQ(1u, Selection().LayoutSelectionStart());
@@ -646,7 +640,7 @@
   TEST_RESET();
   TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
   TEST_NEXT("foo", kStart, NotInvalidate);
-  TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
+  TEST_NEXT(IsLayoutInline, kContain, NotInvalidate);
   TEST_NEXT("bar", kEnd, NotInvalidate);
   TEST_CHECK();
 
@@ -661,7 +655,7 @@
   TEST_RESET();
   TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
   TEST_NEXT("foo", kStart, NotInvalidate);
-  TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
+  TEST_NEXT(IsLayoutInline, kContain, NotInvalidate);
   TEST_NEXT("bar", kEnd, ShouldInvalidate);
   TEST_CHECK();
   EXPECT_EQ(1u, Selection().LayoutSelectionStart());
@@ -768,7 +762,8 @@
   TEST_NEXT("foo", kStartAndEnd, NotInvalidate);
   TEST_CHECK();
 
-  Selection().ClearLayoutSelection();
+  Selection().Clear();
+  Selection().CommitAppearanceIfNeeded();
   TEST_RESET();
   TEST_NEXT(IsLayoutBlock, kNone, NotInvalidate);
   TEST_NEXT(IsLayoutBlock, kNone, NotInvalidate);
@@ -785,7 +780,7 @@
   Selection().CommitAppearanceIfNeeded();
   TEST_RESET();
   TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
-  TEST_NEXT(IsSVGRoot, kNone, NotInvalidate);
+  TEST_NEXT(IsSVGRoot, kContain, NotInvalidate);
   // LayoutSVGText should be invalidate though it is kContain.
   TEST_NEXT(IsSVGText, kContain, ShouldInvalidate);
   TEST_NEXT("foobar", kStartAndEnd, ShouldInvalidate);
@@ -796,7 +791,7 @@
   UpdateAllLifecyclePhases();
   TEST_RESET();
   TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
-  TEST_NEXT(IsSVGRoot, kNone, NotInvalidate);
+  TEST_NEXT(IsSVGRoot, kContain, NotInvalidate);
   TEST_NEXT(IsSVGText, kContain, NotInvalidate);
   TEST_NEXT("foobar", kStartAndEnd, NotInvalidate);
   TEST_CHECK();
@@ -809,7 +804,7 @@
   Selection().CommitAppearanceIfNeeded();
   TEST_RESET();
   TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
-  TEST_NEXT(IsSVGRoot, kNone, NotInvalidate);
+  TEST_NEXT(IsSVGRoot, kContain, NotInvalidate);
   TEST_NEXT(IsSVGText, kContain, ShouldInvalidate);
   TEST_NEXT("foobar", kStartAndEnd, ShouldInvalidate);
   TEST_CHECK();
@@ -825,10 +820,10 @@
   Selection().CommitAppearanceIfNeeded();
   TEST_RESET();
   TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
-  TEST_NEXT(IsSVGRoot, kNone, NotInvalidate);
+  TEST_NEXT(IsSVGRoot, kContain, NotInvalidate);
   // LayoutSVGText should be invalidated.
   TEST_NEXT(IsSVGText, kContain, ShouldInvalidate);
-  TEST_NEXT(IsSVGTSpan, kNone, NotInvalidate);
+  TEST_NEXT(IsSVGTSpan, kContain, NotInvalidate);
   TEST_NEXT("foobar", kStartAndEnd, ShouldInvalidate);
   TEST_CHECK();
   EXPECT_EQ(2u, Selection().LayoutSelectionStart());
@@ -837,9 +832,9 @@
   UpdateAllLifecyclePhases();
   TEST_RESET();
   TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
-  TEST_NEXT(IsSVGRoot, kNone, NotInvalidate);
+  TEST_NEXT(IsSVGRoot, kContain, NotInvalidate);
   TEST_NEXT(IsSVGText, kContain, NotInvalidate);
-  TEST_NEXT(IsSVGTSpan, kNone, NotInvalidate);
+  TEST_NEXT(IsSVGTSpan, kContain, NotInvalidate);
   TEST_NEXT("foobar", kStartAndEnd, NotInvalidate);
   TEST_CHECK();
 
@@ -851,9 +846,9 @@
   Selection().CommitAppearanceIfNeeded();
   TEST_RESET();
   TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
-  TEST_NEXT(IsSVGRoot, kNone, NotInvalidate);
+  TEST_NEXT(IsSVGRoot, kContain, NotInvalidate);
   TEST_NEXT(IsSVGText, kContain, ShouldInvalidate);
-  TEST_NEXT(IsSVGTSpan, kNone, NotInvalidate);
+  TEST_NEXT(IsSVGTSpan, kContain, NotInvalidate);
   TEST_NEXT("foobar", kStartAndEnd, ShouldInvalidate);
   TEST_CHECK();
   EXPECT_EQ(2u, Selection().LayoutSelectionStart());
@@ -877,7 +872,7 @@
   Selection().CommitAppearanceIfNeeded();
   TEST_RESET();
   TEST_NEXT(IsLayoutOf("BODY"), kContain, NotInvalidate);
-  TEST_NEXT(IsRuby, kNone, NotInvalidate);
+  TEST_NEXT(IsRuby, kContain, NotInvalidate);
   TEST_NEXT("foo", kStart, ShouldInvalidate);
   TEST_NEXT(IsRubyText, kContain, NotInvalidate);
   TEST_NEXT("bar", kEnd, ShouldInvalidate);
@@ -886,25 +881,156 @@
   UpdateAllLifecyclePhases();
   TEST_RESET();
   TEST_NEXT(IsLayoutOf("BODY"), kContain, NotInvalidate);
-  TEST_NEXT(IsRuby, kNone, NotInvalidate);
+  TEST_NEXT(IsRuby, kContain, NotInvalidate);
   TEST_NEXT("foo", kStart, NotInvalidate);
   TEST_NEXT(IsRubyText, kContain, NotInvalidate);
   TEST_NEXT("bar", kEnd, NotInvalidate);
   TEST_CHECK();
 
-  Selection().ClearLayoutSelection();
+  Selection().Clear();
+  Selection().CommitAppearanceIfNeeded();
   TEST_RESET();
   TEST_NEXT(IsLayoutOf("BODY"), kNone, NotInvalidate);
   TEST_NEXT(IsRuby, kNone, NotInvalidate);
   TEST_NEXT("foo", kNone, ShouldInvalidate);
-  // TODO(yoichio): These 2 should be kNone.
-  // TEST_NEXT(IsRubyText, kNone, NotInvalidate);
-  // TEST_NEXT("bar", kNone, ShouldInvalidate);
-  TEST_NEXT(IsRubyText, kContain, NotInvalidate);
+  TEST_NEXT(IsRubyText, kNone, NotInvalidate);
+  TEST_NEXT("bar", kNone, ShouldInvalidate);
+  TEST_CHECK();
+}
+
+TEST_F(LayoutSelectionTest, ClearByRemoveNode) {
+  Selection().SetSelectionAndEndTyping(
+      SetSelectionTextToBody("^foo<span>bar</span>baz|"));
+  Selection().CommitAppearanceIfNeeded();
+  TEST_RESET();
+  TEST_NEXT(IsLayoutOf("BODY"), kContain, NotInvalidate);
+  TEST_NEXT("foo", kStart, ShouldInvalidate);
+  TEST_NEXT(IsLayoutOf("SPAN"), kContain, NotInvalidate);
+  TEST_NEXT("bar", kInside, ShouldInvalidate);
+  TEST_NEXT("baz", kEnd, ShouldInvalidate);
+  TEST_CHECK();
+
+  Node* baz = GetDocument().body()->lastChild();
+  baz->remove();
+  TEST_RESET();
+  TEST_NEXT(IsLayoutOf("BODY"), kContain, NotInvalidate);
+  TEST_NEXT("foo", kStart, ShouldInvalidate);
+  TEST_NEXT(IsLayoutOf("SPAN"), kContain, NotInvalidate);
+  TEST_NEXT("bar", kInside, ShouldInvalidate);
+  TEST_CHECK();
+
+  UpdateAllLifecyclePhases();
+  TEST_RESET();
+  TEST_NEXT(IsLayoutOf("BODY"), kContain, NotInvalidate);
+  TEST_NEXT("foo", kStart, NotInvalidate);
+  TEST_NEXT(IsLayoutOf("SPAN"), kContain, NotInvalidate);
   TEST_NEXT("bar", kEnd, NotInvalidate);
   TEST_CHECK();
 }
 
+TEST_F(LayoutSelectionTest, ClearByRemoveLayoutObject) {
+  Selection().SetSelectionAndEndTyping(
+      SetSelectionTextToBody("^foo<span>bar</span><span>baz</span>|"));
+  Selection().CommitAppearanceIfNeeded();
+  TEST_RESET();
+  TEST_NEXT(IsLayoutOf("BODY"), kContain, NotInvalidate);
+  TEST_NEXT("foo", kStart, ShouldInvalidate);
+  TEST_NEXT(IsLayoutOf("SPAN"), kContain, NotInvalidate);
+  TEST_NEXT("bar", kInside, ShouldInvalidate);
+  TEST_NEXT(IsLayoutOf("SPAN"), kContain, NotInvalidate);
+  TEST_NEXT("baz", kEnd, ShouldInvalidate);
+  TEST_CHECK();
+
+  Element* span_baz = ToElement(GetDocument().body()->lastChild());
+  span_baz->SetInlineStyleProperty(CSSPropertyDisplay, CSSValueNone);
+  GetDocument().UpdateStyleAndLayoutTreeIgnorePendingStylesheets();
+  TEST_RESET();
+  TEST_NEXT(IsLayoutOf("BODY"), kContain, NotInvalidate);
+  TEST_NEXT("foo", kStart, ShouldInvalidate);
+  TEST_NEXT(IsLayoutOf("SPAN"), kContain, NotInvalidate);
+  TEST_NEXT("bar", kInside, ShouldInvalidate);
+  TEST_CHECK();
+
+  UpdateAllLifecyclePhases();
+  TEST_RESET();
+  TEST_NEXT(IsLayoutOf("BODY"), kContain, NotInvalidate);
+  TEST_NEXT("foo", kStart, NotInvalidate);
+  TEST_NEXT(IsLayoutOf("SPAN"), kContain, NotInvalidate);
+  TEST_NEXT("bar", kEnd, NotInvalidate);
+  TEST_CHECK();
+}
+
+TEST_F(LayoutSelectionTest, ClearBySlotChange) {
+  Selection().SetSelectionAndEndTyping(
+      SetSelectionTextToBody("<div>"
+                             "<template data-mode=open>"
+                             "^Foo<slot name=s1></slot>|"
+                             "</template>"
+                             "baz<span slot=s1>bar</span>"
+                             "</div>"));
+  Selection().CommitAppearanceIfNeeded();
+  TEST_RESET();
+  TEST_NEXT(IsLayoutOf("BODY"), kContain, NotInvalidate);
+  TEST_NEXT(IsLayoutOf("DIV"), kContain, NotInvalidate);
+  TEST_NEXT("Foo", kStart, ShouldInvalidate);
+  TEST_NEXT(IsLayoutOf("SPAN"), kContain, NotInvalidate);
+  TEST_NEXT("bar", kEnd, ShouldInvalidate);
+  TEST_CHECK();
+
+  Element* slot =
+      GetDocument().body()->firstChild()->GetShadowRoot()->QuerySelector(
+          "slot");
+  slot->setAttribute("name", "s2");
+  GetDocument().UpdateStyleAndLayoutTreeIgnorePendingStylesheets();
+  TEST_RESET();
+  TEST_NEXT(IsLayoutOf("BODY"), kContain, NotInvalidate);
+  TEST_NEXT(IsLayoutOf("DIV"), kContain, NotInvalidate);
+  TEST_NEXT("Foo", kStart, ShouldInvalidate);
+  TEST_CHECK();
+
+  UpdateAllLifecyclePhases();
+  TEST_RESET();
+  TEST_NEXT(IsLayoutOf("BODY"), kContain, NotInvalidate);
+  TEST_NEXT(IsLayoutOf("DIV"), kContain, NotInvalidate);
+  TEST_NEXT("Foo", kStartAndEnd, NotInvalidate);
+  TEST_CHECK();
+}
+
+TEST_F(LayoutSelectionTest, MoveNode) {
+  Selection().SetSelectionAndEndTyping(SetSelectionTextToBody(
+      "<div id='div1'></div><div id='div2'>^foo<b>ba|r</b></div>"));
+  Selection().CommitAppearanceIfNeeded();
+  EXPECT_EQ(
+      "BODY, Contain, NotInvalidate \n"
+      "  DIV, None, NotInvalidate \n"
+      "  DIV, Contain, NotInvalidate \n"
+      "    'foo', Start, ShouldInvalidate \n"
+      "    B, Contain, NotInvalidate \n"
+      "      'bar', End, ShouldInvalidate ",
+      DumpSelectionInfo());
+  Node* div1 = GetDocument().QuerySelector("#div1");
+  Node* div2 = GetDocument().QuerySelector("#div2");
+  div1->appendChild(div2);
+  EXPECT_EQ(
+      "BODY, Contain, NotInvalidate \n"
+      "  DIV, None, NotInvalidate \n"
+      "    DIV, <null LayoutObject> \n"
+      "      'foo', <null LayoutObject> \n"
+      "      B, <null LayoutObject> \n"
+      "        'bar', <null LayoutObject> ",
+      DumpSelectionInfo());
+
+  UpdateAllLifecyclePhases();
+  EXPECT_EQ(
+      "BODY, None, NotInvalidate \n"
+      "  DIV, None, NotInvalidate \n"
+      "    DIV, None, NotInvalidate \n"
+      "      'foo', None, NotInvalidate \n"
+      "      B, None, NotInvalidate \n"
+      "        'bar', None, NotInvalidate ",
+      DumpSelectionInfo());
+}
+
 static const NGPaintFragment* FindNGPaintFragmentInternal(
     const NGPaintFragment* paint,
     const LayoutObject* layout_object) {
@@ -986,7 +1112,7 @@
   TEST_RESET();
   TEST_NEXT(IsLayoutNGBlockFlow, kContain, NotInvalidate);
   TEST_NEXT("foo", kNone, NotInvalidate);
-  TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
+  TEST_NEXT(IsLayoutOf("SPAN"), kContain, NotInvalidate);
   TEST_NEXT("bar", kStartAndEnd, ShouldInvalidate);
   TEST_CHECK();
 
diff --git a/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc b/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc
index 2e0516ee..5b780a4a 100644
--- a/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc
+++ b/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc
@@ -129,27 +129,14 @@
 }
 
 bool DocumentMarkerController::PossiblyHasMarkers(
-    DocumentMarker::MarkerType type) {
+    DocumentMarker::MarkerType type) const {
   return PossiblyHasMarkers(DocumentMarker::MarkerTypes(type));
 }
 
 inline bool DocumentMarkerController::PossiblyHasMarkers(
-    DocumentMarker::MarkerTypes types) {
-  if (markers_.IsEmpty()) {
-    // It's possible for markers_ to become empty through garbage collection if
-    // all its Nodes are GC'ed since we only hold weak references, in which case
-    // possibly_existing_marker_types_ isn't reset to 0 as it is in the other
-    // codepaths that remove from markers_. Therefore, we check for this case
-    // here.
-
-    // Alternatively, we could handle this case at the time the Node is GC'ed,
-    // but that operation is more performance-sensitive than anywhere
-    // PossiblyHasMarkers() is used.
-    possibly_existing_marker_types_ = DocumentMarker::MarkerTypes();
-    SetContext(nullptr);
-    return false;
-  }
-
+    DocumentMarker::MarkerTypes types) const {
+  DCHECK(!markers_.IsEmpty() ||
+         possibly_existing_marker_types_ == DocumentMarker::MarkerTypes(0));
   return possibly_existing_marker_types_.Intersects(types);
 }
 
@@ -662,7 +649,17 @@
   }
 }
 
+void DocumentMarkerController::DidProcessMarkerMap(Visitor* visitor) {
+  if (markers_.IsEmpty())
+    Clear();
+}
+
 void DocumentMarkerController::Trace(blink::Visitor* visitor) {
+  // Note: To make |DidProcessMarkerMap()| called after weak members callback
+  // of |markers_|, we should register it before tracing |markers_|.
+  visitor->template RegisterWeakMembers<
+      DocumentMarkerController, &DocumentMarkerController::DidProcessMarkerMap>(
+      this);
   visitor->Trace(markers_);
   visitor->Trace(document_);
   SynchronousMutationObserver::Trace(visitor);
diff --git a/third_party/blink/renderer/core/editing/markers/document_marker_controller.h b/third_party/blink/renderer/core/editing/markers/document_marker_controller.h
index 3ce98e9..34036b30 100644
--- a/third_party/blink/renderer/core/editing/markers/document_marker_controller.h
+++ b/third_party/blink/renderer/core/editing/markers/document_marker_controller.h
@@ -152,8 +152,8 @@
   using MarkerMap = HeapHashMap<WeakMember<const Node>, Member<MarkerLists>>;
   static Member<DocumentMarkerList>& ListForType(MarkerLists*,
                                                  DocumentMarker::MarkerType);
-  bool PossiblyHasMarkers(DocumentMarker::MarkerTypes);
-  bool PossiblyHasMarkers(DocumentMarker::MarkerType);
+  bool PossiblyHasMarkers(DocumentMarker::MarkerTypes) const;
+  bool PossiblyHasMarkers(DocumentMarker::MarkerType) const;
   void RemoveMarkersFromList(MarkerMap::iterator, DocumentMarker::MarkerTypes);
   void RemoveMarkers(TextIterator&, DocumentMarker::MarkerTypes);
   void RemoveMarkersInternal(const Node&,
@@ -161,6 +161,9 @@
                              int length,
                              DocumentMarker::MarkerTypes);
 
+  // Called after weak processing of |markers_| is done.
+  void DidProcessMarkerMap(Visitor* visitor);
+
   MarkerMap markers_;
   // Provide a quick way to determine whether a particular marker type is absent
   // without going through the map.
diff --git a/third_party/blink/renderer/core/editing/markers/document_marker_controller_test.cc b/third_party/blink/renderer/core/editing/markers/document_marker_controller_test.cc
index a7e2c103..c17f3ed 100644
--- a/third_party/blink/renderer/core/editing/markers/document_marker_controller_test.cc
+++ b/third_party/blink/renderer/core/editing/markers/document_marker_controller_test.cc
@@ -189,10 +189,8 @@
   EXPECT_EQ(0u, MarkerController().Markers().size());
 }
 
-// TODO(crbug.com/862900): Fix DocumentMarkerController::DidUpdateCharacterData
-//                         and enable this test.
-TEST_F(DocumentMarkerControllerTest,
-       DISABLED_SynchronousMutationNotificationAfterGC) {
+// For http://crbug.com/862900
+TEST_F(DocumentMarkerControllerTest, SynchronousMutationNotificationAfterGC) {
   SetBodyContent("<b><i>foo</i></b>");
   Persistent<Text> sibling_text = CreateTextNode("bar");
   {
diff --git a/third_party/blink/renderer/core/editing/selection_controller.cc b/third_party/blink/renderer/core/editing/selection_controller.cc
index 0a2ec76..3afb8fa 100644
--- a/third_party/blink/renderer/core/editing/selection_controller.cc
+++ b/third_party/blink/renderer/core/editing/selection_controller.cc
@@ -33,6 +33,7 @@
 #include "third_party/blink/public/platform/web_menu_source_type.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/editing/editing_behavior.h"
 #include "third_party/blink/renderer/core/editing/editing_boundary.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
 #include "third_party/blink/renderer/core/editing/editor.h"
diff --git a/third_party/blink/renderer/core/editing/selection_editor.cc b/third_party/blink/renderer/core/editing/selection_editor.cc
index 4a8c93b..b440db6 100644
--- a/third_party/blink/renderer/core/editing/selection_editor.cc
+++ b/third_party/blink/renderer/core/editing/selection_editor.cc
@@ -27,6 +27,7 @@
 
 #include "third_party/blink/renderer/core/dom/node_with_index.h"
 #include "third_party/blink/renderer/core/dom/text.h"
+#include "third_party/blink/renderer/core/editing/editing_behavior.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
 #include "third_party/blink/renderer/core/editing/editor.h"
 #include "third_party/blink/renderer/core/editing/selection_adjuster.h"
diff --git a/third_party/blink/renderer/core/editing/selection_modifier.cc b/third_party/blink/renderer/core/editing/selection_modifier.cc
index b011187..cdd47a7b 100644
--- a/third_party/blink/renderer/core/editing/selection_modifier.cc
+++ b/third_party/blink/renderer/core/editing/selection_modifier.cc
@@ -26,6 +26,7 @@
 
 #include "third_party/blink/renderer/core/editing/selection_modifier.h"
 
+#include "third_party/blink/renderer/core/editing/editing_behavior.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
 #include "third_party/blink/renderer/core/editing/editor.h"
 #include "third_party/blink/renderer/core/editing/ephemeral_range.h"
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 e74dcd5..ca50a72 100644
--- a/third_party/blink/renderer/core/exported/web_frame_test.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -5089,18 +5089,19 @@
   ~FindUpdateWebFrameClient() override = default;
 
   // FrameTestHelpers::TestWebFrameClient:
-  void ReportFindInPageMatchCount(int, int count, bool final_update) override {
-    count_ = count;
-    if (final_update)
+  void SendFindReply(int request_id,
+                     int match_count,
+                     int ordinal,
+                     const WebRect& selection_rect,
+                     bool final_status_update) override {
+    if (match_count != -1)
+      count_ = match_count;
+    if (ordinal != -1)
+      active_index_ = ordinal;
+    if (final_status_update)
       find_results_are_ready_ = true;
   }
 
-  void ReportFindInPageSelection(int,
-                                 int active_match_ordinal,
-                                 const WebRect&) override {
-    active_index_ = active_match_ordinal;
-  }
-
   bool FindResultsAreReady() const { return find_results_are_ready_; }
   int Count() const { return count_; }
   int ActiveIndex() const { return active_index_; }
diff --git a/third_party/blink/renderer/core/exported/worker_shadow_page.cc b/third_party/blink/renderer/core/exported/worker_shadow_page.cc
index 9f424d9..56312ab 100644
--- a/third_party/blink/renderer/core/exported/worker_shadow_page.cc
+++ b/third_party/blink/renderer/core/exported/worker_shadow_page.cc
@@ -104,11 +104,6 @@
   return client_->GetDevToolsWorkerToken();
 }
 
-std::unique_ptr<WebSocketHandshakeThrottle>
-WorkerShadowPage::CreateWebSocketHandshakeThrottle() {
-  return Platform::Current()->CreateWebSocketHandshakeThrottle();
-}
-
 bool WorkerShadowPage::WasInitialized() const {
   return state_ == State::kInitialized;
 }
diff --git a/third_party/blink/renderer/core/exported/worker_shadow_page.h b/third_party/blink/renderer/core/exported/worker_shadow_page.h
index c5eddff6..bde2d73 100644
--- a/third_party/blink/renderer/core/exported/worker_shadow_page.h
+++ b/third_party/blink/renderer/core/exported/worker_shadow_page.h
@@ -79,11 +79,6 @@
   std::unique_ptr<blink::WebURLLoaderFactory> CreateURLLoaderFactory() override;
   base::UnguessableToken GetDevToolsFrameToken() override;
 
-  // TODO(nhiroki): Remove this once the off-main-thread WebSocket is enabled by
-  // default (https://crbug.com/825740).
-  std::unique_ptr<WebSocketHandshakeThrottle> CreateWebSocketHandshakeThrottle()
-      override;
-
   Document* GetDocument() { return main_frame_->GetFrame()->GetDocument(); }
   WebSettings* GetSettings() { return web_view_->GetSettings(); }
   WebDocumentLoader* DocumentLoader() {
diff --git a/third_party/blink/renderer/core/frame/find_in_page.cc b/third_party/blink/renderer/core/frame/find_in_page.cc
index c1a4a34c..1ddb382 100644
--- a/third_party/blink/renderer/core/frame/find_in_page.cc
+++ b/third_party/blink/renderer/core/frame/find_in_page.cc
@@ -35,6 +35,7 @@
 #include "third_party/blink/public/web/web_local_frame_client.h"
 #include "third_party/blink/public/web/web_plugin.h"
 #include "third_party/blink/public/web/web_plugin_document.h"
+#include "third_party/blink/public/web/web_widget_client.h"
 #include "third_party/blink/renderer/core/editing/finder/text_finder.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -68,8 +69,8 @@
                              const WebFindOptions& options) {
   // Send "no results" if this frame has no visible content.
   if (!frame_->HasVisibleContent() && !options.force) {
-    frame_->Client()->ReportFindInPageMatchCount(identifier, 0 /* count */,
-                                                 true /* finalUpdate */);
+    frame_->ReportFindInPageMatchCount(identifier, 0 /* count */,
+                                       true /* finalUpdate */);
     return;
   }
 
@@ -87,8 +88,8 @@
   if (result && !options.find_next) {
     // Indicate that at least one match has been found. 1 here means
     // possibly more matches could be coming.
-    frame_->Client()->ReportFindInPageMatchCount(identifier, 1 /* count */,
-                                                 false /* finalUpdate */);
+    frame_->ReportFindInPageMatchCount(identifier, 1 /* count */,
+                                       false /* final_update */);
   }
 
   // There are three cases in which scoping is needed:
@@ -197,9 +198,8 @@
   return WebFloatRect();
 }
 
-void FindInPage::ActivateNearestFindResult(
-    const WebFloatPoint& point,
-    ActivateNearestFindResultCallback callback) {
+void FindInPage::ActivateNearestFindResult(int request_id,
+                                           const WebFloatPoint& point) {
   WebRect active_match_rect;
   const int ordinal =
       EnsureTextFinder().SelectNearestFindMatch(point, &active_match_rect);
@@ -208,16 +208,18 @@
     // the current match count) in case the host is waiting for a response due
     // to rate-limiting.
     int number_of_matches = EnsureTextFinder().TotalMatchCount();
-    std::move(callback).Run(WebRect(), number_of_matches,
-                            -1 /* active_match_ordinal */,
-                            !EnsureTextFinder().FrameScoping() ||
-                                !number_of_matches /* final_reply */);
+    mojom::blink::FindMatchUpdateType update_type =
+        mojom::blink::FindMatchUpdateType::kMoreUpdatesComing;
+    if (!EnsureTextFinder().FrameScoping() || !number_of_matches)
+      update_type = mojom::blink::FindMatchUpdateType::kFinalUpdate;
+    client_->SetNumberOfMatches(request_id, number_of_matches, update_type);
     return;
   }
-  // Call callback with current active match's rect and its ordinal,
-  // and don't update total number of matches.
-  std::move(callback).Run(active_match_rect, -1 /* number_of_matches */,
-                          ordinal, true /* final_reply*/);
+  client_->SetActiveMatch(request_id, active_match_rect, ordinal);
+}
+
+void FindInPage::SetClient(mojom::blink::FindInPageClientPtr client) {
+  client_ = std::move(client);
 }
 
 void FindInPage::GetNearestFindResult(const WebFloatPoint& point,
@@ -307,4 +309,24 @@
   binding_.Close();
 }
 
+void WebLocalFrameImpl::ReportFindInPageMatchCount(int request_id,
+                                                   int count,
+                                                   bool final_update) {
+  if (!Client())
+    return;
+  Client()->SendFindReply(request_id, count, -1 /* active_match_ordinal */,
+                          WebRect(), final_update);
+}
+
+void WebLocalFrameImpl::ReportFindInPageSelection(
+    int request_id,
+    int active_match_ordinal,
+    const blink::WebRect& selection_rect,
+    bool final_update) {
+  if (!Client())
+    return;
+  Client()->SendFindReply(request_id, -1 /* match_count */,
+                          active_match_ordinal, selection_rect, final_update);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/find_in_page.h b/third_party/blink/renderer/core/frame/find_in_page.h
index cd5c66b..68ec387 100644
--- a/third_party/blink/renderer/core/frame/find_in_page.h
+++ b/third_party/blink/renderer/core/frame/find_in_page.h
@@ -56,8 +56,9 @@
 
   // mojom::blink::FindInPage overrides
 
-  void ActivateNearestFindResult(const WebFloatPoint&,
-                                 ActivateNearestFindResultCallback) final;
+  void SetClient(mojom::blink::FindInPageClientPtr) final;
+
+  void ActivateNearestFindResult(int request_id, const WebFloatPoint&) final;
 
   // Stops the current find-in-page, following the given |action|
   void StopFinding(mojom::StopFindAction action) final;
@@ -108,6 +109,8 @@
 
   const Member<WebLocalFrameImpl> frame_;
 
+  mojom::blink::FindInPageClientPtr client_;
+
   mojo::AssociatedBinding<mojom::blink::FindInPage> binding_;
 
   DISALLOW_COPY_AND_ASSIGN(FindInPage);
diff --git a/third_party/blink/renderer/core/frame/picture_in_picture_controller.h b/third_party/blink/renderer/core/frame/picture_in_picture_controller.h
index 92dfb88..4565488 100644
--- a/third_party/blink/renderer/core/frame/picture_in_picture_controller.h
+++ b/third_party/blink/renderer/core/frame/picture_in_picture_controller.h
@@ -41,6 +41,7 @@
     kDisabledBySystem,
     kDisabledByFeaturePolicy,
     kDisabledByAttribute,
+    kMediaStreamsNotSupportedYet,
   };
 
   // Enter Picture-in-Picture for a video element and resolve promise if any.
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
index feb4b14..4b736228 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -314,9 +314,15 @@
             bool wrap_within_frame,
             bool* active_now = nullptr) override;
   void StopFindingForTesting(mojom::StopFindAction) override;
-
   void SetTickmarks(const WebVector<WebRect>&) override;
   WebPlugin* GetWebPluginForFind() override;
+  void ReportFindInPageMatchCount(int identifier,
+                                  int count,
+                                  bool final_update) override;
+  void ReportFindInPageSelection(int identifier,
+                                 int active_match_ordinal,
+                                 const WebRect& selection,
+                                 bool final_update) override;
   WebNode ContextMenuNode() const override;
   WebFrameWidget* FrameWidget() const override;
   void CopyImageAt(const WebPoint&) override;
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
index 473c6a7..8596b77e5 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -415,13 +415,9 @@
 
     if (!LowLatencyEnabled())
       canvas2d_bridge_->FinalizeFrame();
-  }
 
-  if (LowLatencyEnabled() && !dirty_rect_.IsEmpty()) {
-    AccelerationHint hint =
-        Is2d() ? kPreferNoAcceleration : kPreferAcceleration;
-    if (GetOrCreateCanvasResourceProvider(hint)) {
-      ResourceProvider()->TryEnableSingleBuffering();
+    if (LowLatencyEnabled() && !dirty_rect_.IsEmpty() &&
+        GetOrCreateCanvasResourceProvider(kPreferAcceleration)) {
       // Push a frame
       base::TimeTicks start_time = WTF::CurrentTimeTicks();
       scoped_refptr<StaticBitmapImage> image =
@@ -1141,8 +1137,9 @@
 scoped_refptr<Image> HTMLCanvasElement::CopiedImage(
     SourceDrawingBuffer source_buffer,
     AccelerationHint hint) {
-  if (PlaceholderFrame())
+  if (SurfaceLayerBridge()) {
     return PlaceholderFrame()->Bitmap();
+  }
 
   if (!IsPaintable())
     return nullptr;
diff --git a/third_party/blink/renderer/core/html/forms/text_control_element.cc b/third_party/blink/renderer/core/html/forms/text_control_element.cc
index ac7f798..0d2474b 100644
--- a/third_party/blink/renderer/core/html/forms/text_control_element.cc
+++ b/third_party/blink/renderer/core/html/forms/text_control_element.cc
@@ -31,6 +31,7 @@
 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
 #include "third_party/blink/renderer/core/dom/shadow_root.h"
 #include "third_party/blink/renderer/core/dom/text.h"
+#include "third_party/blink/renderer/core/editing/editing_behavior.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
 #include "third_party/blink/renderer/core/editing/editor.h"
 #include "third_party/blink/renderer/core/editing/frame_selection.h"
diff --git a/third_party/blink/renderer/core/input/event_handler_test.cc b/third_party/blink/renderer/core/input/event_handler_test.cc
index 399af96..c8947ab 100644
--- a/third_party/blink/renderer/core/input/event_handler_test.cc
+++ b/third_party/blink/renderer/core/input/event_handler_test.cc
@@ -8,6 +8,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/range.h"
+#include "third_party/blink/renderer/core/editing/editing_behavior.h"
 #include "third_party/blink/renderer/core/editing/editor.h"
 #include "third_party/blink/renderer/core/editing/ephemeral_range.h"
 #include "third_party/blink/renderer/core/editing/frame_selection.h"
diff --git a/third_party/blink/renderer/core/layout/api/selection_state.h b/third_party/blink/renderer/core/layout/api/selection_state.h
index 922c514..fea6336 100644
--- a/third_party/blink/renderer/core/layout/api/selection_state.h
+++ b/third_party/blink/renderer/core/layout/api/selection_state.h
@@ -10,25 +10,32 @@
 
 namespace blink {
 
+// Each LayoutObject has a SelectionState and it represents how the
+// LayoutObject is selected. This enum is used to paint/invalidate selection
+// highlight for the LayoutObject.
 enum class SelectionState {
-  // LayoutObject is not selected.
+  // The LayoutObject is not selected.
   kNone,
-  // LayoutObject is the start of a selection run and doesn't have children.
+  // kStart, kInside, kEnd and kStartAndEnd represent the LayoutObject
+  // is somehow selected to paint and either LayoutText or LayoutReplaced.
+  // The start of a selection.
   kStart,
-  // LayoutObject is fully encompassed by a selection run and
-  // doesn't have children.
+  // Inside a selection.
   kInside,
-  // LayoutObject is the end of a selection run and doesn't have children.
+  // The end of a selection.
   kEnd,
-  // LayoutObject contains an entire selection run and doesn't have children.
+  // The LayoutObject contains an entire selection.
   kStartAndEnd,
-  // LayoutObject has at least one LayoutObject child which SelectionState is
-  // kStart, kInside, kEnd or kStartAndEnd.
-  // This property is used to invalidate LayoutObject for ::selection style
-  // change. See LayoutObject::InvalidatePaintForSelection().
+  // The LayoutObject has at least one LayoutObject child which SelectionState
+  // is not KNone.
+  // This property is used to invalidate LayoutObject.
   kContain
 };
 
+inline bool IsSelected(const SelectionState state) {
+  return state != SelectionState::kNone && state != SelectionState::kContain;
+}
+
 CORE_EXPORT std::ostream& operator<<(std::ostream&, const SelectionState);
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.cc b/third_party/blink/renderer/core/layout/layout_block_flow.cc
index 0fcd90c..b371979 100644
--- a/third_party/blink/renderer/core/layout/layout_block_flow.cc
+++ b/third_party/blink/renderer/core/layout/layout_block_flow.cc
@@ -34,6 +34,7 @@
 #include <memory>
 #include <utility>
 
+#include "third_party/blink/renderer/core/editing/editing_behavior.h"
 #include "third_party/blink/renderer/core/editing/editor.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
diff --git a/third_party/blink/renderer/core/layout/line/breaking_context_inline_headers.h b/third_party/blink/renderer/core/layout/line/breaking_context_inline_headers.h
index 75f77db..9a3994b 100644
--- a/third_party/blink/renderer/core/layout/line/breaking_context_inline_headers.h
+++ b/third_party/blink/renderer/core/layout/line/breaking_context_inline_headers.h
@@ -824,7 +824,7 @@
   int start = word_measurement.start_offset;
   int end = CanMidWordBreakBefore(text)
                 ? start
-                : break_iterator.NextBreakOpportunity(start);
+                : break_iterator.NextBreakOpportunity(start + 1);
   if (end >= word_measurement.end_offset)
     return false;
 
@@ -1063,13 +1063,11 @@
                              break_all, next_breakable_position_for_break_all);
     }
 
-    // Determine if we are in the whitespace between words or in a leading
-    // whitespace.
+    // Determine if we are in the whitespace between words.
     int next_breakable_position = current_.NextBreakablePosition();
     bool between_words =
         c == kNewlineCharacter ||
-        (curr_ws_ != EWhiteSpace::kPre &&
-         (!at_start_ || current_character_is_space_) &&
+        (curr_ws_ != EWhiteSpace::kPre && !at_start_ &&
          layout_text_info_.line_break_iterator_.IsBreakable(
              current_.Offset(), next_breakable_position, line_break_type) &&
          (!disable_soft_hyphen ||
@@ -1213,8 +1211,7 @@
     }
 
     // Auto-wrapping text should not wrap in the middle of a word once it has
-    // had an opportunity to break after a word or before, at a leading
-    // white-space.
+    // had an opportunity to break after a word.
     if (auto_wrap_ && between_words) {
       width_.Commit();
       width_from_last_breaking_opportunity = 0;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
index 09b24129..dc03fc2 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
@@ -805,14 +805,12 @@
 
     if (item.Type() == NGInlineItem::kFloating) {
       NGBlockNode node(ToLayoutBox(item.GetLayoutObject()));
-      NGBoxStrut margins =
-          ComputeMarginsForContainer(ConstraintSpace(), node.Style());
 
       scoped_refptr<NGUnpositionedFloat> unpositioned_float =
           NGUnpositionedFloat::Create(
               ConstraintSpace().AvailableSize(),
               ConstraintSpace().PercentageResolutionSize(), bfc_line_offset,
-              bfc_line_offset, margins, node, /* break_token */ nullptr);
+              bfc_line_offset, node, /* break_token */ nullptr);
       AddUnpositionedFloat(&unpositioned_floats_, &container_builder_,
                            std::move(unpositioned_float));
     }
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 0c2d05dd..62b2bc3 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
@@ -829,8 +829,6 @@
   NGBlockNode node(ToLayoutBox(item.GetLayoutObject()));
 
   const ComputedStyle& float_style = node.Style();
-  NGBoxStrut margins =
-      ComputeMarginsForContainer(constraint_space_, float_style);
 
   // TODO(ikilpatrick): Add support for float break tokens inside an inline
   // layout context.
@@ -839,8 +837,7 @@
                                   constraint_space_.PercentageResolutionSize(),
                                   constraint_space_.BfcOffset().line_offset,
                                   constraint_space_.BfcOffset().line_offset,
-                                  margins, node,
-                                  /* break_token */ nullptr);
+                                  node, /* break_token */ nullptr);
 
   // If we are currently computing our min/max-content size simply append
   // to the unpositioned floats list and abort.
@@ -851,10 +848,8 @@
   }
 
   LayoutUnit inline_margin_size =
-      (ComputeInlineSizeForUnpositionedFloat(constraint_space_,
-                                             unpositioned_float.get()) +
-       margins.InlineSum())
-          .ClampNegativeToZero();
+      ComputeMarginBoxInlineSizeForUnpositionedFloat(constraint_space_,
+                                                     unpositioned_float.get());
 
   LayoutUnit bfc_block_offset = line_opportunity_.bfc_block_offset;
 
@@ -893,9 +888,6 @@
         unpositioned_float.get(), constraint_space_, exclusion_space_);
     positioned_floats_->push_back(positioned_float);
 
-    DCHECK_EQ(positioned_float.bfc_offset.block_offset,
-              bfc_block_offset + margins.block_start);
-
     NGLayoutOpportunity opportunity = exclusion_space_->FindLayoutOpportunity(
         {constraint_space_.BfcOffset().line_offset, bfc_block_offset},
         constraint_space_.AvailableSize().inline_size, NGLogicalSize());
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
index bd3d4fc..bccd1197 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -704,18 +704,14 @@
     const NGPreviousInflowPosition& previous_inflow_position,
     NGBlockNode child,
     NGBlockBreakToken* child_break_token) {
-  // Calculate margins in the BFC's writing mode.
-  NGBoxStrut margins = CalculateMargins(child, child_break_token);
-
   LayoutUnit origin_inline_offset =
       ConstraintSpace().BfcOffset().line_offset +
       border_scrollbar_padding_.LineLeft(ConstraintSpace().Direction());
 
   scoped_refptr<NGUnpositionedFloat> unpositioned_float =
-      NGUnpositionedFloat::Create(child_available_size_, child_percentage_size_,
-                                  origin_inline_offset,
-                                  ConstraintSpace().BfcOffset().line_offset,
-                                  margins, child, child_break_token);
+      NGUnpositionedFloat::Create(
+          child_available_size_, child_percentage_size_, origin_inline_offset,
+          ConstraintSpace().BfcOffset().line_offset, child, child_break_token);
   AddUnpositionedFloat(&unpositioned_floats_, &container_builder_,
                        unpositioned_float);
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_floats_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_floats_utils.cc
index 58bc8c2..3611f43e 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_floats_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_floats_utils.cc
@@ -40,6 +40,7 @@
     const NGBfcOffset& origin_offset,
     const NGExclusionSpace& exclusion_space,
     const NGUnpositionedFloat& unpositioned_float,
+    const NGBoxStrut& fragment_margins,
     LayoutUnit inline_size) {
   NGBfcOffset adjusted_origin_point =
       AdjustToTopEdgeAlignmentRule(exclusion_space, origin_offset);
@@ -48,10 +49,8 @@
 
   AdjustToClearance(clearance_offset, &adjusted_origin_point);
 
-  NGLogicalSize float_size(inline_size + unpositioned_float.margins.InlineSum(),
+  NGLogicalSize float_size(inline_size + fragment_margins.InlineSum(),
                            LayoutUnit());
-  // TODO(ikilpatrick): Don't include the block-start margin of a float which
-  // has fragmented.
   return exclusion_space.FindLayoutOpportunity(
       adjusted_origin_point, unpositioned_float.available_size.inline_size,
       float_size);
@@ -147,14 +146,11 @@
     const NGConstraintSpace& parent_space,
     TextDirection direction,
     EFloat type) {
-  // TODO(ikilpatrick): Don't include the block-start margin of a float which
-  // has fragmented.
   NGBfcOffset start_offset = float_margin_bfc_offset;
-
   NGBfcOffset end_offset(
-      /* line_offset */ start_offset.line_offset +
+      start_offset.line_offset +
           (fragment.InlineSize() + margins.InlineSum()).ClampNegativeToZero(),
-      /* block_offset */ start_offset.block_offset +
+      start_offset.block_offset +
           (fragment.BlockSize() + margins.BlockSum()).ClampNegativeToZero());
 
   std::unique_ptr<NGExclusionShapeData> shape_data =
@@ -178,11 +174,13 @@
       CreateConstraintSpaceForFloat(*unpositioned_float, parent_space);
 
   unpositioned_float->layout_result = unpositioned_float->node.Layout(*space);
+  unpositioned_float->margins =
+      ComputeMarginsFor(*space, unpositioned_float->node.Style(), parent_space);
 }
 
 }  // namespace
 
-LayoutUnit ComputeInlineSizeForUnpositionedFloat(
+LayoutUnit ComputeMarginBoxInlineSizeForUnpositionedFloat(
     const NGConstraintSpace& parent_space,
     NGUnpositionedFloat* unpositioned_float) {
   DCHECK(unpositioned_float);
@@ -194,7 +192,9 @@
   DCHECK(fragment);
   DCHECK(fragment->BreakToken()->IsFinished());
 
-  return NGFragment(parent_space.GetWritingMode(), *fragment).InlineSize();
+  return (NGFragment(parent_space.GetWritingMode(), *fragment).InlineSize() +
+          unpositioned_float->margins.InlineSum())
+      .ClampNegativeToZero();
 }
 
 NGPositionedFloat PositionFloat(LayoutUnit origin_block_offset,
@@ -212,16 +212,27 @@
       is_same_writing_mode && parent_space.HasBlockFragmentation();
 
   scoped_refptr<NGLayoutResult> layout_result;
+  NGBoxStrut fragment_margins;
+
   // We may be able to re-use the fragment from when we calculated the
   // inline-size, if there is no block fragmentation.
   if (!is_fragmentable) {
     LayoutFloatWithoutFragmentation(parent_space, unpositioned_float);
     layout_result = unpositioned_float->layout_result;
+    fragment_margins = unpositioned_float->margins;
   } else {
     scoped_refptr<NGConstraintSpace> space = CreateConstraintSpaceForFloat(
         *unpositioned_float, parent_space, origin_block_offset);
     layout_result = unpositioned_float->node.Layout(
         *space, unpositioned_float->token.get());
+    fragment_margins = ComputeMarginsFor(
+        *space, unpositioned_float->node.Style(), parent_space);
+
+    // Make the margins fragmentation aware.
+    if (unpositioned_float->token)
+      fragment_margins.block_start = LayoutUnit();
+    if (!layout_result->PhysicalFragment()->BreakToken()->IsFinished())
+      fragment_margins.block_end = LayoutUnit();
   }
 
   DCHECK(layout_result->PhysicalFragment());
@@ -233,21 +244,21 @@
 
   // Find a layout opportunity that will fit our float.
   NGLayoutOpportunity opportunity = FindLayoutOpportunityForFloat(
-      origin_offset, *exclusion_space, *unpositioned_float,
+      origin_offset, *exclusion_space, *unpositioned_float, fragment_margins,
       float_fragment.InlineSize());
 
   // Calculate the float's margin box BFC offset.
   NGBfcOffset float_margin_bfc_offset = opportunity.rect.start_offset;
   if (unpositioned_float->IsRight()) {
     LayoutUnit float_margin_box_inline_size =
-        float_fragment.InlineSize() + unpositioned_float->margins.InlineSum();
+        float_fragment.InlineSize() + fragment_margins.InlineSum();
     float_margin_bfc_offset.line_offset +=
         (opportunity.rect.InlineSize() - float_margin_box_inline_size);
   }
 
   // Add the float as an exclusion.
   scoped_refptr<NGExclusion> exclusion = CreateExclusion(
-      float_fragment, float_margin_bfc_offset, unpositioned_float->margins,
+      float_fragment, float_margin_bfc_offset, fragment_margins,
       unpositioned_float->node.GetLayoutBox(), *unpositioned_float,
       parent_space, parent_space.Direction(),
       unpositioned_float->IsRight() ? EFloat::kRight : EFloat::kLeft);
@@ -256,9 +267,8 @@
   // Adjust the float's bfc_offset to its border-box (instead of margin-box).
   NGBfcOffset float_bfc_offset(
       float_margin_bfc_offset.line_offset +
-          unpositioned_float->margins.LineLeft(parent_space.Direction()),
-      float_margin_bfc_offset.block_offset +
-          unpositioned_float->margins.block_start);
+          fragment_margins.LineLeft(parent_space.Direction()),
+      float_margin_bfc_offset.block_offset + fragment_margins.block_start);
 
   return NGPositionedFloat(std::move(layout_result), float_bfc_offset);
 }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_floats_utils.h b/third_party/blink/renderer/core/layout/ng/ng_floats_utils.h
index ffd1b872..d5b5df53 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_floats_utils.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_floats_utils.h
@@ -29,11 +29,10 @@
 typedef int NGFloatTypes;
 
 // Returns the inline size (relative to {@code parent_space}) of the
-// unpositioned float. If the float is in a different writing mode, this will
-// perform a layout.
-CORE_EXPORT LayoutUnit
-ComputeInlineSizeForUnpositionedFloat(const NGConstraintSpace& parent_space,
-                                      NGUnpositionedFloat* unpositioned_float);
+// unpositioned float.
+CORE_EXPORT LayoutUnit ComputeMarginBoxInlineSizeForUnpositionedFloat(
+    const NGConstraintSpace& parent_space,
+    NGUnpositionedFloat* unpositioned_float);
 
 // Positions {@code unpositioned_float} into {@code new_parent_space}.
 // @returns A positioned float.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
index 9a32ed0..e78515c 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
@@ -624,13 +624,6 @@
       .ConvertToLogical(compute_for.GetWritingMode(), compute_for.Direction());
 }
 
-NGBoxStrut ComputeMarginsForContainer(const NGConstraintSpace& constraint_space,
-                                      const ComputedStyle& style) {
-  return ComputePhysicalMargins(constraint_space, style)
-      .ConvertToLogical(constraint_space.GetWritingMode(),
-                        constraint_space.Direction());
-}
-
 NGBoxStrut ComputeMarginsForVisualContainer(
     const NGConstraintSpace& constraint_space,
     const ComputedStyle& style) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_length_utils_test.cc b/third_party/blink/renderer/core/layout/ng/ng_length_utils_test.cc
index a6577d9..15ef5e5e 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_length_utils_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_length_utils_test.cc
@@ -391,12 +391,13 @@
   scoped_refptr<NGConstraintSpace> constraint_space(
       ConstructConstraintSpace(200, 300));
 
-  NGBoxStrut margins = ComputeMarginsForContainer(*constraint_space, *style_);
+  NGPhysicalBoxStrut margins =
+      ComputePhysicalMargins(*constraint_space, *style_);
 
-  EXPECT_EQ(LayoutUnit(20), margins.block_start);
-  EXPECT_EQ(LayoutUnit(52), margins.inline_end);
-  EXPECT_EQ(LayoutUnit(), margins.block_end);
-  EXPECT_EQ(LayoutUnit(22), margins.inline_start);
+  EXPECT_EQ(LayoutUnit(20), margins.top);
+  EXPECT_EQ(LayoutUnit(52), margins.right);
+  EXPECT_EQ(LayoutUnit(), margins.bottom);
+  EXPECT_EQ(LayoutUnit(22), margins.left);
 }
 
 TEST_F(NGLengthUtilsTest, testBorders) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.cc b/third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.cc
index 285bee17..3d6b553 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.cc
@@ -12,8 +12,7 @@
 
 // Define the constructor and destructor here, so that we can forward-declare
 // more in the header file.
-NGUnpositionedFloat::NGUnpositionedFloat(const NGBoxStrut& margins,
-                                         const NGLogicalSize& available_size,
+NGUnpositionedFloat::NGUnpositionedFloat(const NGLogicalSize& available_size,
                                          const NGLogicalSize& percentage_size,
                                          LayoutUnit origin_bfc_line_offset,
                                          LayoutUnit bfc_line_offset,
@@ -24,8 +23,7 @@
       available_size(available_size),
       percentage_size(percentage_size),
       origin_bfc_line_offset(origin_bfc_line_offset),
-      bfc_line_offset(bfc_line_offset),
-      margins(margins) {}
+      bfc_line_offset(bfc_line_offset) {}
 
 NGUnpositionedFloat::~NGUnpositionedFloat() = default;
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h b/third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h
index 761bcc6..b00aed4c 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h
@@ -26,11 +26,10 @@
       NGLogicalSize percentage_size,
       LayoutUnit origin_bfc_line_offset,
       LayoutUnit bfc_line_offset,
-      NGBoxStrut margins,
       NGBlockNode node,
       NGBlockBreakToken* token) {
     return base::AdoptRef(new NGUnpositionedFloat(
-        margins, available_size, percentage_size, origin_bfc_line_offset,
+        available_size, percentage_size, origin_bfc_line_offset,
         bfc_line_offset, node, token));
   }
 
@@ -66,8 +65,7 @@
   EClear ClearType() const;
 
  private:
-  NGUnpositionedFloat(const NGBoxStrut& margins,
-                      const NGLogicalSize& available_size,
+  NGUnpositionedFloat(const NGLogicalSize& available_size,
                       const NGLogicalSize& percentage_size,
                       LayoutUnit origin_bfc_line_offset,
                       LayoutUnit bfc_line_offset,
diff --git a/third_party/blink/renderer/core/loader/subresource_filter.cc b/third_party/blink/renderer/core/loader/subresource_filter.cc
index 5716c9a..93f68ea 100644
--- a/third_party/blink/renderer/core/loader/subresource_filter.cc
+++ b/third_party/blink/renderer/core/loader/subresource_filter.cc
@@ -13,8 +13,6 @@
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/core/loader/document_loader.h"
-#include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
 
@@ -69,12 +67,6 @@
 }
 
 bool SubresourceFilter::AllowWebSocketConnection(const KURL& url) {
-  // WebSocket is handled via document on the main thread unless the
-  // experimental off-main-thread WebSocket flag is enabled. See
-  // https://crbug.com/825740 for the details of the off-main-thread WebSocket.
-  DCHECK(execution_context_->IsDocument() ||
-         RuntimeEnabledFeatures::OffMainThreadWebSocketEnabled());
-
   WebDocumentSubresourceFilter::LoadPolicy load_policy =
       subresource_filter_->GetLoadPolicyForWebSocketConnect(url);
 
diff --git a/third_party/blink/renderer/core/page/context_menu_controller.cc b/third_party/blink/renderer/core/page/context_menu_controller.cc
index abfaa89d..5af515b 100644
--- a/third_party/blink/renderer/core/page/context_menu_controller.cc
+++ b/third_party/blink/renderer/core/page/context_menu_controller.cc
@@ -448,6 +448,10 @@
   if (auto* input = ToHTMLInputElementOrNull(result.InnerNode())) {
     if (input->type() == InputTypeNames::password)
       data.input_field_type = WebContextMenuData::kInputFieldTypePassword;
+    else if (input->type() == InputTypeNames::number)
+      data.input_field_type = WebContextMenuData::kInputFieldTypeNumber;
+    else if (input->type() == InputTypeNames::tel)
+      data.input_field_type = WebContextMenuData::kInputFieldTypeTelephone;
     else if (input->IsTextField())
       data.input_field_type = WebContextMenuData::kInputFieldTypePlainText;
     else
diff --git a/third_party/blink/renderer/core/page/touch_adjustment.cc b/third_party/blink/renderer/core/page/touch_adjustment.cc
index 83a8a7c3..ca57520 100644
--- a/third_party/blink/renderer/core/page/touch_adjustment.cc
+++ b/third_party/blink/renderer/core/page/touch_adjustment.cc
@@ -23,6 +23,7 @@
 #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_behavior.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
 #include "third_party/blink/renderer/core/editing/editor.h"
 #include "third_party/blink/renderer/core/editing/frame_selection.h"
diff --git a/third_party/blink/renderer/core/paint/replaced_painter.cc b/third_party/blink/renderer/core/paint/replaced_painter.cc
index b6219ca..af26f37 100644
--- a/third_party/blink/renderer/core/paint/replaced_painter.cc
+++ b/third_party/blink/renderer/core/paint/replaced_painter.cc
@@ -108,7 +108,7 @@
   // want it to run right up to the edges of surrounding content.
   bool draw_selection_tint =
       local_paint_info.phase == PaintPhase::kForeground &&
-      layout_replaced_.GetSelectionState() != SelectionState::kNone &&
+      IsSelected(layout_replaced_.GetSelectionState()) &&
       !local_paint_info.IsPrinting();
   if (draw_selection_tint && !DrawingRecorder::UseCachedDrawingIfPossible(
                                  local_paint_info.context, layout_replaced_,
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.cc b/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.cc
index 3c346b7..9e10d8a 100644
--- a/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.cc
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.cc
@@ -5,12 +5,14 @@
 #include "third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h"
 
 #include "skia/ext/image_operations.h"
+#include "third_party/blink/public/common/manifest/manifest_icon_selector.h"
 #include "third_party/blink/public/platform/web_size.h"
 #include "third_party/blink/public/platform/web_url_request.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/loader/threadable_loader.h"
 #include "third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h"
 #include "third_party/blink/renderer/modules/manifest/image_resource.h"
+#include "third_party/blink/renderer/modules/manifest/image_resource_type_converters.h"
 #include "third_party/blink/renderer/platform/graphics/color_behavior.h"
 #include "third_party/blink/renderer/platform/heap/heap_allocator.h"
 #include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
@@ -19,6 +21,7 @@
 #include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_impl.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #include "third_party/blink/renderer/platform/wtf/threading.h"
 
 namespace blink {
@@ -26,9 +29,7 @@
 namespace {
 
 const unsigned long kIconFetchTimeoutInMs = 30000;
-const int kMinimumIconSizeInPx = 16;
-const double kAnySizeScore = 0.8;
-const double kUnspecifiedSizeScore = 0.4;
+const int kMinimumIconSizeInPx = 0;
 
 }  // namespace
 
@@ -62,15 +63,14 @@
     return;
   }
 
-  int best_icon_index =
+  KURL best_icon_url =
       PickBestIconForDisplay(execution_context, icon_display_size_pixels);
-  if (best_icon_index < 0) {
+  if (best_icon_url.IsEmpty()) {
     // None of the icons provided was suitable.
     std::move(icon_callback).Run(SkBitmap());
     return;
   }
-  KURL best_icon_url =
-      execution_context->CompleteURL(icons_[best_icon_index].src());
+
   icon_callback_ = std::move(icon_callback);
 
   ThreadableLoaderOptions threadable_loader_options;
@@ -92,94 +92,16 @@
   threadable_loader_->Start(resource_request);
 }
 
-int BackgroundFetchIconLoader::PickBestIconForDisplay(
+KURL BackgroundFetchIconLoader::PickBestIconForDisplay(
     ExecutionContext* execution_context,
     const WebSize& icon_display_size_pixels) {
-  int best_index = -1;
-  double best_score = 0.0;
-  for (size_t i = 0; i < icons_.size(); ++i) {
-    // If the icon has no or invalid src, move on.
-    if (!icons_[i].hasSrc())
-      continue;
-    KURL icon_url = execution_context->CompleteURL(icons_[i].src());
-    if (!icon_url.IsValid() || icon_url.IsEmpty())
-      continue;
+  std::vector<Manifest::ImageResource> icons;
+  for (const auto& icon : icons_)
+    icons.emplace_back(blink::ConvertManifestImageResource(icon));
 
-    double score = GetIconScore(icons_[i], icon_display_size_pixels.width);
-    if (!score)
-      continue;
-    // According to the spec, if two icons get the same score, we must use the
-    // one that's declared last. (https://w3c.github.io/manifest/#icons-member).
-    if (score >= best_score) {
-      best_score = score;
-      best_index = i;
-    }
-  }
-  return best_index;
-}
-
-// The scoring works as follows:
-// When the size is "any", the icon size score is kAnySizeScore.
-// If unspecified, use the unspecified size score, kUnspecifiedSizeScore as
-// icon score.
-
-// For other sizes, the icon score lies in [0,1] and is computed by multiplying
-// the dominant size score and aspect ratio score.
-//
-// The dominant size score lies in [0, 1] and is computed using
-// dominant size and and |ideal_size|:
-//   - If dominant_size < kMinimumIconSizeInPx, the size score is 0.0.
-//   - For all other sizes, the score is calculated as
-//     1/(1 + abs(dominant_size-ideal_size))
-//   - If dominant_size < ideal_size, there is an upscaling penalty, which is
-//     dominant_size/ideal_size.
-//
-// The aspect ratio score lies in [0, 1] and is computed by dividing the short
-// edge length by the long edge. (Bias towards square icons assumed).
-//
-// Note: If this is an ico file containing multiple sizes, return the best
-// score.
-double BackgroundFetchIconLoader::GetIconScore(ManifestImageResource icon,
-                                               const int ideal_size) {
-  // Extract sizes from the icon definition, expressed as "<width>x<height>
-  // <width>x<height> ...."
-  if (!icon.hasSizes() || icon.sizes().IsEmpty())
-    return kUnspecifiedSizeScore;
-
-  String sizes = icon.sizes();
-  // if any size is set to "any" return kAnySizeScore;
-  if (sizes.LowerASCII() == "any")
-    return kAnySizeScore;
-
-  Vector<String> sizes_str;
-  sizes.Split(" ", false /* allow_empty_entries*/, sizes_str);
-
-  // Pick the first size.
-  // TODO(nator): Add support for multiple sizes (.ico files).
-  Vector<String> width_and_height_str;
-  sizes_str[0].Split("x", false /* allow_empty_entries */,
-                     width_and_height_str);
-  // If sizes isn't in this format, consider it as 'unspecified'.
-  if (width_and_height_str.size() != 2)
-    return kUnspecifiedSizeScore;
-  double width = width_and_height_str[0].ToDouble();
-  double height = width_and_height_str[1].ToDouble();
-
-  // Compute dominant size score
-  int dominant_size = std::max(width, height);
-  int short_size = std::min(width, height);
-  if (dominant_size < kMinimumIconSizeInPx)
-    return 0.0;
-
-  double dominant_size_score = 1.0 / (1.0 + abs(dominant_size - ideal_size));
-  if (dominant_size < ideal_size)
-    dominant_size_score = dominant_size_score * dominant_size / ideal_size;
-  // Compute aspect ratio score. If dominant_size is zero, we'd have returned
-  // by now.
-  double aspect_ratio_score = short_size / dominant_size;
-
-  // Compute icon score.
-  return aspect_ratio_score * dominant_size_score;
+  return KURL(ManifestIconSelector::FindBestMatchingIcon(
+      std::move(icons), icon_display_size_pixels.height, kMinimumIconSizeInPx,
+      Manifest::ImageResource::Purpose::ANY));
 }
 
 void BackgroundFetchIconLoader::Stop() {
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h b/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h
index 400dc73c..52c44fff 100644
--- a/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h
@@ -10,7 +10,6 @@
 #include "third_party/blink/renderer/core/loader/threadable_loader.h"
 #include "third_party/blink/renderer/core/loader/threadable_loader_client.h"
 #include "third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.h"
-#include "third_party/blink/renderer/modules/manifest/image_resource.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/shared_buffer.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -68,14 +67,10 @@
       const WebSize& icon_display_size_pixels);
 
   // Picks the best icon from the list of developer provided icons, for current
-  // display, given the ideal |icon_display_size_pixels|, and returns its index
-  // in the icons_ array.
-  int PickBestIconForDisplay(ExecutionContext* execution_context,
-                             const WebSize& icon_display_size_pixels);
-
-  // Get a score for the given icon, based on ideal_size. The icon with the
-  // highest score is chosen.
-  double GetIconScore(ManifestImageResource icon, const int ideal_size);
+  // display, given the ideal |icon_display_size_pixels|, and returns its KURL.
+  // If none of the icons is appropriate, this returns an empty URL.
+  KURL PickBestIconForDisplay(ExecutionContext* execution_context,
+                              const WebSize& icon_display_size_pixels);
 
   bool stopped_ = false;
   scoped_refptr<SharedBuffer> data_;
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader_test.cc b/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader_test.cc
index df73355f..bae2a95 100644
--- a/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader_test.cc
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader_test.cc
@@ -74,8 +74,8 @@
     return icon;
   }
 
-  int PickRightIcon(HeapVector<ManifestImageResource> icons,
-                    const WebSize& ideal_display_size) {
+  KURL PickRightIcon(HeapVector<ManifestImageResource> icons,
+                     const WebSize& ideal_display_size) {
     loader_->icons_ = std::move(icons);
     return loader_->PickBestIconForDisplay(GetContext(), ideal_display_size);
   }
@@ -85,6 +85,7 @@
     icon.setSrc(url.GetString());
     icon.setType("image/png");
     icon.setSizes("500x500");
+    icon.setPurpose("ANY");
     HeapVector<ManifestImageResource> icons(1, icon);
     loader_->icons_ = std::move(icons);
     loader_->DidGetIconDisplaySizeIfSoLoadIcon(
@@ -123,8 +124,8 @@
   icons.push_back(icon1);
   icons.push_back(icon2);
 
-  int index = PickRightIcon(std::move(icons), WebSize(50, 50));
-  EXPECT_EQ(index, 1);
+  KURL best_icon = PickRightIcon(std::move(icons), WebSize(50, 50));
+  EXPECT_EQ(best_icon, KURL(kBackgroundFetchImageLoaderIcon48x48));
 }
 
 TEST_F(BackgroundFetchIconLoaderTest, PickRightIconGivenAnyTest) {
@@ -140,8 +141,8 @@
   icons.push_back(icon1);
   icons.push_back(icon2);
 
-  int index = PickRightIcon(std::move(icons), WebSize(50, 50));
-  EXPECT_EQ(index, 2);
+  KURL best_icon = PickRightIcon(std::move(icons), WebSize(50, 50));
+  EXPECT_EQ(best_icon, KURL(kBackgroundFetchImageLoaderIcon));
 }
 
 TEST_F(BackgroundFetchIconLoaderTest, PickRightIconWithTieBreakTest) {
@@ -157,8 +158,8 @@
   icons.push_back(icon0);
   icons.push_back(icon1);
   icons.push_back(icon2);
-  int index = PickRightIcon(std::move(icons), WebSize(50, 50));
-  EXPECT_EQ(index, 2);
+  KURL best_icon = PickRightIcon(std::move(icons), WebSize(50, 50));
+  EXPECT_EQ(best_icon, KURL(kBackgroundFetchImageLoaderIcon3000x2000));
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
index 208ff8c..5c679f9 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
@@ -120,15 +120,16 @@
     return CanvasElement().GetGPUMemoryUsage();
   }
   void DrawSomething() {
-    CanvasElement().DidDraw();
-    CanvasElement().FinalizeFrame();
+    Canvas2DLayerBridge* bridge = CanvasElement().GetCanvas2DLayerBridge();
+    bridge->DidDraw(FloatRect(0, 0, 1, 1));
+    bridge->FinalizeFrame();
     // Grabbing an image forces a flush
-    CanvasElement().CopiedImage(kBackBuffer, kPreferAcceleration);
+    bridge->NewImageSnapshot(kPreferAcceleration);
   }
 
-  enum LatencyMode { kNormalLatency, kLowLatency };
-
-  void CreateContext(OpacityMode, LatencyMode = kNormalLatency);
+  void CreateContext(OpacityMode,
+                     String color_space = String(),
+                     LinearPixelMathState = kLinearPixelMathDisabled);
   ScriptState* GetScriptState() {
     return ToScriptStateForMainWorld(canvas_element_->GetFrame());
   }
@@ -184,12 +185,19 @@
       opaque_bitmap_(IntSize(10, 10), kOpaqueBitmap),
       alpha_bitmap_(IntSize(10, 10), kTransparentBitmap) {}
 
-void CanvasRenderingContext2DTest::CreateContext(OpacityMode opacity_mode,
-                                                 LatencyMode latency_mode) {
+void CanvasRenderingContext2DTest::CreateContext(
+    OpacityMode opacity_mode,
+    String color_space,
+    LinearPixelMathState LinearPixelMath_state) {
   String canvas_type("2d");
   CanvasContextCreationAttributesCore attributes;
   attributes.alpha = opacity_mode == kNonOpaque;
-  attributes.low_latency = latency_mode == kLowLatency;
+  if (!color_space.IsEmpty()) {
+    attributes.color_space = color_space;
+    if (LinearPixelMath_state == kLinearPixelMathEnabled) {
+      attributes.pixel_format = "float16";
+    }
+  }
   canvas_element_->GetCanvasRenderingContext(canvas_type, attributes);
 }
 
@@ -1201,22 +1209,4 @@
   EXPECT_FALSE(layer->NeedsCompositingInputsUpdate());
 }
 
-TEST_F(CanvasRenderingContext2DTest, LowLatencyIsSingleBuffered) {
-  CreateContext(kNonOpaque, kLowLatency);
-  // No need to set-up the layer bridge when testing low latency mode.
-  DrawSomething();
-  auto frame1_resource =
-      CanvasElement()
-          .GetOrCreateCanvasResourceProvider(kPreferNoAcceleration)
-          ->ProduceFrame();
-  EXPECT_TRUE(!!frame1_resource);
-  DrawSomething();
-  auto frame2_resource =
-      CanvasElement()
-          .GetOrCreateCanvasResourceProvider(kPreferNoAcceleration)
-          ->ProduceFrame();
-  EXPECT_TRUE(!!frame2_resource);
-  EXPECT_EQ(frame1_resource.get(), frame2_resource.get());
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/manifest/image_resource_type_converters.cc b/third_party/blink/renderer/modules/manifest/image_resource_type_converters.cc
index 6068f41..fa48425 100644
--- a/third_party/blink/renderer/modules/manifest/image_resource_type_converters.cc
+++ b/third_party/blink/renderer/modules/manifest/image_resource_type_converters.cc
@@ -9,6 +9,7 @@
 #include "third_party/blink/public/platform/web_size.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_vector.h"
+#include "third_party/blink/renderer/modules/manifest/image_resource.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 #include "third_party/blink/renderer/platform/wtf/hash_set.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -105,3 +106,31 @@
 }
 
 }  // namespace mojo
+
+namespace blink {
+
+Manifest::ImageResource ConvertManifestImageResource(
+    const ManifestImageResource& icon) {
+  Manifest::ImageResource manifest_icon;
+  manifest_icon.src = blink::KURL(icon.src());
+  manifest_icon.type = WebString(mojo::ParseType(icon.type())).Utf16();
+
+  // Parse 'purpose'
+  const auto purposes = mojo::ParsePurpose(icon.purpose());
+  // ParsePurpose() would've weeded out any purposes that're not ANY or BADGE.
+  for (auto purpose : purposes) {
+    manifest_icon.purpose.emplace_back(
+        purpose == mojo::Purpose::ANY
+            ? Manifest::ImageResource::Purpose::ANY
+            : Manifest::ImageResource::Purpose::BADGE);
+  }
+  // Parse 'sizes'.
+  WTF::Vector<WebSize> sizes = mojo::ParseSizes(icon.sizes());
+  for (const auto& size : sizes) {
+    manifest_icon.sizes.emplace_back(gfx::Size(size.height, size.width));
+  }
+
+  return manifest_icon;
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/manifest/image_resource_type_converters.h b/third_party/blink/renderer/modules/manifest/image_resource_type_converters.h
index 4f0f1a4..ad5589b 100644
--- a/third_party/blink/renderer/modules/manifest/image_resource_type_converters.h
+++ b/third_party/blink/renderer/modules/manifest/image_resource_type_converters.h
@@ -5,10 +5,18 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MANIFEST_IMAGE_RESOURCE_TYPE_CONVERTERS_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_MANIFEST_IMAGE_RESOURCE_TYPE_CONVERTERS_H_
 
+#include "third_party/blink/public/common/manifest/manifest.h"
 #include "third_party/blink/public/mojom/manifest/manifest.mojom-blink.h"
-#include "third_party/blink/renderer/modules/manifest/image_resource.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 
+namespace blink {
+
+class ManifestImageResource;
+MODULES_EXPORT Manifest::ImageResource ConvertManifestImageResource(
+    const ManifestImageResource& image_resource);
+
+}  // namespace blink
+
 namespace mojo {
 
 template <>
diff --git a/third_party/blink/renderer/modules/manifest/image_resource_type_converters_test.cc b/third_party/blink/renderer/modules/manifest/image_resource_type_converters_test.cc
index 4f86f8a..a1bf8f10 100644
--- a/third_party/blink/renderer/modules/manifest/image_resource_type_converters_test.cc
+++ b/third_party/blink/renderer/modules/manifest/image_resource_type_converters_test.cc
@@ -7,6 +7,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/mojom/manifest/manifest.mojom-blink.h"
 #include "third_party/blink/public/platform/web_size.h"
+#include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/renderer/modules/manifest/image_resource.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -184,6 +185,22 @@
   EXPECT_EQ(expected_resource, ManifestImageResource::From(resource));
 }
 
+TEST(ImageResourceConverter, BlinkToMojoTypeTest) {
+  blink::ManifestImageResource icon;
+  icon.setSrc("http://example.com/lolcat.jpg");
+  icon.setPurpose("BADGE");
+  icon.setSizes("32x32 64x64 128x128");
+  icon.setType("image/jpeg");
+
+  blink::Manifest::ImageResource mojo_icon =
+      blink::ConvertManifestImageResource(icon);
+  EXPECT_EQ(mojo_icon.src.spec(), "http://example.com/lolcat.jpg");
+  EXPECT_EQ(mojo_icon.type, blink::WebString("image/jpeg").Utf16());
+  EXPECT_EQ(mojo_icon.sizes[1], gfx::Size(64, 64));
+  EXPECT_EQ(mojo_icon.purpose[0],
+            blink::Manifest::ImageResource::Purpose::BADGE);
+}
+
 }  // namespace
 
 }  // namespace mojo
diff --git a/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.cc b/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.cc
index 02c3959..6a78896 100644
--- a/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.cc
+++ b/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.cc
@@ -4,7 +4,6 @@
 
 #include "third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.h"
 
-#include "third_party/blink/public/platform/web_media_player.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
@@ -26,6 +25,8 @@
     "Metadata for the video element are not loaded yet.";
 const char kVideoTrackNotAvailableError[] =
     "The video element has no video track.";
+const char kMediaStreamsNotSupportedYet[] =
+    "Media Streams are not supported yet.";
 const char kFeaturePolicyBlocked[] =
     "Access to the feature \"picture-in-picture\" is disallowed by feature "
     "policy.";
@@ -60,6 +61,11 @@
           script_state,
           DOMException::Create(DOMExceptionCode::kInvalidStateError,
                                kVideoTrackNotAvailableError));
+    case Status::kMediaStreamsNotSupportedYet:
+      return ScriptPromise::RejectWithDOMException(
+          script_state,
+          DOMException::Create(DOMExceptionCode::kNotSupportedError,
+                               kMediaStreamsNotSupportedYet));
     case Status::kDisabledByFeaturePolicy:
       return ScriptPromise::RejectWithDOMException(
           script_state, DOMException::Create(DOMExceptionCode::kSecurityError,
@@ -88,14 +94,6 @@
                                            kUserGestureRequired));
   }
 
-  // TODO(crbug.com/806249): Remove this when MediaStreams are supported.
-  if (element.GetLoadType() == WebMediaPlayer::kLoadTypeMediaStream) {
-    return ScriptPromise::RejectWithDOMException(
-        script_state,
-        DOMException::Create(DOMExceptionCode::kNotSupportedError,
-                             "MediaStreams are not supported yet."));
-  }
-
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
   ScriptPromise promise = resolver->Promise();
 
diff --git a/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc b/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc
index 75819a5..8a54faa 100644
--- a/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc
+++ b/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.h"
 
+#include "third_party/blink/public/platform/web_media_player.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
@@ -77,6 +78,10 @@
   if (element.FastHasAttribute(HTMLNames::disablepictureinpictureAttr))
     return Status::kDisabledByAttribute;
 
+  // TODO(crbug.com/806249): Remove this when MediaStreams are supported.
+  if (element.GetLoadType() == WebMediaPlayer::kLoadTypeMediaStream)
+    return Status::kMediaStreamsNotSupportedYet;
+
   return Status::kEnabled;
 }
 
diff --git a/third_party/blink/renderer/modules/websockets/BUILD.gn b/third_party/blink/renderer/modules/websockets/BUILD.gn
index 02643db..cc34a49d 100644
--- a/third_party/blink/renderer/modules/websockets/BUILD.gn
+++ b/third_party/blink/renderer/modules/websockets/BUILD.gn
@@ -24,7 +24,5 @@
     "websocket_handle_client.h",
     "websocket_handle_impl.cc",
     "websocket_handle_impl.h",
-    "worker_websocket_channel.cc",
-    "worker_websocket_channel.h",
   ]
 }
diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel.cc b/third_party/blink/renderer/modules/websockets/websocket_channel.cc
index c05a94c0..6dfdbb54b 100644
--- a/third_party/blink/renderer/modules/websockets/websocket_channel.cc
+++ b/third_party/blink/renderer/modules/websockets/websocket_channel.cc
@@ -32,14 +32,9 @@
 
 #include <memory>
 #include "third_party/blink/renderer/bindings/core/v8/source_location.h"
-#include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
-#include "third_party/blink/renderer/core/workers/worker_thread.h"
 #include "third_party/blink/renderer/modules/websockets/websocket_channel_client.h"
 #include "third_party/blink/renderer/modules/websockets/websocket_channel_impl.h"
-#include "third_party/blink/renderer/modules/websockets/worker_websocket_channel.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 
 namespace blink {
 
@@ -47,20 +42,8 @@
                                            WebSocketChannelClient* client) {
   DCHECK(context);
   DCHECK(client);
-
-  std::unique_ptr<SourceLocation> location = SourceLocation::Capture(context);
-
-  // When the off-main-thread WebSocket flag is enabled, web workers use
-  // WebSocketChannelImpl as opposed to WorkerWebSocketChannel. See
-  // https://crbug.com/825740
-  if (context->IsDocument() ||
-      RuntimeEnabledFeatures::OffMainThreadWebSocketEnabled()) {
-    return WebSocketChannelImpl::Create(context, client, std::move(location));
-  }
-
-  WorkerGlobalScope* worker_global_scope = ToWorkerGlobalScope(context);
-  return WorkerWebSocketChannel::Create(*worker_global_scope, client,
-                                        std::move(location));
+  return WebSocketChannelImpl::Create(context, client,
+                                      SourceLocation::Capture(context));
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h b/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h
index d7e4af0a..5d4767e 100644
--- a/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h
+++ b/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h
@@ -60,6 +60,7 @@
 // This is an implementation of WebSocketChannel. This is created on the main
 // thread for Document, or on the worker thread for WorkerGlobalScope. All
 // functions must be called on the execution context's thread.
+// TODO(nhiroki): Merge this class into WebSocketChannel.
 class MODULES_EXPORT WebSocketChannelImpl final
     : public WebSocketChannel,
       public WebSocketHandleClient,
diff --git a/third_party/blink/renderer/modules/websockets/worker_websocket_channel.cc b/third_party/blink/renderer/modules/websockets/worker_websocket_channel.cc
deleted file mode 100644
index c84700b..0000000
--- a/third_party/blink/renderer/modules/websockets/worker_websocket_channel.cc
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- * Copyright (C) 2011, 2012 Google Inc.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/modules/websockets/worker_websocket_channel.h"
-
-#include <memory>
-#include "services/service_manager/public/cpp/interface_provider.h"
-#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/fileapi/blob.h"
-#include "third_party/blink/renderer/core/loader/threadable_loading_context.h"
-#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
-#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
-#include "third_party/blink/renderer/core/workers/worker_thread.h"
-#include "third_party/blink/renderer/core/workers/worker_thread_lifecycle_context.h"
-#include "third_party/blink/renderer/platform/cross_thread_functional.h"
-#include "third_party/blink/renderer/platform/heap/safe_point.h"
-#include "third_party/blink/renderer/platform/waitable_event.h"
-#include "third_party/blink/renderer/platform/web_task_runner.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "third_party/blink/renderer/platform/wtf/functional.h"
-#include "third_party/blink/renderer/platform/wtf/text/cstring.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-typedef WorkerWebSocketChannel::Bridge Bridge;
-typedef WorkerWebSocketChannel::MainChannelClient MainChannelClient;
-
-// Created and destroyed on the worker thread. All setters of this class are
-// called on the main thread, while all getters are called on the worker
-// thread. signalWorkerThread() must be called before any getters are called.
-class WebSocketChannelSyncHelper {
- public:
-  WebSocketChannelSyncHelper() = default;
-  ~WebSocketChannelSyncHelper() = default;
-
-  // All setters are called on the main thread.
-  void SetConnectRequestResult(bool connect_request_result) {
-    DCHECK(IsMainThread());
-    connect_request_result_ = connect_request_result;
-  }
-
-  // All getters are called on the worker thread.
-  bool ConnectRequestResult() const {
-    DCHECK(!IsMainThread());
-    return connect_request_result_;
-  }
-
-  // This should be called after all setters are called and before any
-  // getters are called.
-  void SignalWorkerThread() {
-    DCHECK(IsMainThread());
-    event_.Signal();
-  }
-
-  void Wait() {
-    DCHECK(!IsMainThread());
-    event_.Wait();
-  }
-
- private:
-  WaitableEvent event_;
-  bool connect_request_result_ = false;
-};
-
-WorkerWebSocketChannel::WorkerWebSocketChannel(
-    WorkerGlobalScope& worker_global_scope,
-    WebSocketChannelClient* client,
-    std::unique_ptr<SourceLocation> location)
-    : bridge_(new Bridge(client, worker_global_scope)),
-      location_at_connection_(std::move(location)) {}
-
-WorkerWebSocketChannel::~WorkerWebSocketChannel() {
-  DCHECK(!bridge_);
-}
-
-bool WorkerWebSocketChannel::Connect(const KURL& url, const String& protocol) {
-  DCHECK(bridge_);
-  return bridge_->Connect(location_at_connection_->Clone(), url, protocol);
-}
-
-void WorkerWebSocketChannel::Send(const CString& message) {
-  DCHECK(bridge_);
-  bridge_->Send(message);
-}
-
-void WorkerWebSocketChannel::Send(const DOMArrayBuffer& binary_data,
-                                  unsigned byte_offset,
-                                  unsigned byte_length) {
-  DCHECK(bridge_);
-  bridge_->Send(binary_data, byte_offset, byte_length);
-}
-
-void WorkerWebSocketChannel::Send(scoped_refptr<BlobDataHandle> blob_data) {
-  DCHECK(bridge_);
-  bridge_->Send(std::move(blob_data));
-}
-
-void WorkerWebSocketChannel::Close(int code, const String& reason) {
-  DCHECK(bridge_);
-  bridge_->Close(code, reason);
-}
-
-void WorkerWebSocketChannel::Fail(const String& reason,
-                                  MessageLevel level,
-                                  std::unique_ptr<SourceLocation> location) {
-  DCHECK(bridge_);
-
-  std::unique_ptr<SourceLocation> captured_location = SourceLocation::Capture();
-  if (!captured_location->IsUnknown()) {
-    // If we are in JavaScript context, use the current location instead
-    // of passed one - it's more precise.
-    bridge_->Fail(reason, level, std::move(captured_location));
-  } else if (location->IsUnknown()) {
-    // No information is specified by the caller - use the url
-    // and the line number at the connection.
-    bridge_->Fail(reason, level, location_at_connection_->Clone());
-  } else {
-    // Use the specified information.
-    bridge_->Fail(reason, level, std::move(location));
-  }
-}
-
-void WorkerWebSocketChannel::Disconnect() {
-  bridge_->Disconnect();
-  bridge_.Clear();
-}
-
-void WorkerWebSocketChannel::Trace(blink::Visitor* visitor) {
-  visitor->Trace(bridge_);
-  WebSocketChannel::Trace(visitor);
-}
-
-MainChannelClient::MainChannelClient(
-    Bridge* bridge,
-    scoped_refptr<base::SingleThreadTaskRunner> worker_networking_task_runner,
-    WorkerThreadLifecycleContext* worker_thread_lifecycle_context)
-    : WorkerThreadLifecycleObserver(worker_thread_lifecycle_context),
-      bridge_(bridge),
-      worker_networking_task_runner_(std::move(worker_networking_task_runner)),
-      main_channel_(nullptr) {
-  DCHECK(IsMainThread());
-}
-
-MainChannelClient::~MainChannelClient() {
-  DCHECK(IsMainThread());
-}
-
-bool MainChannelClient::Initialize(std::unique_ptr<SourceLocation> location,
-                                   ThreadableLoadingContext* loading_context) {
-  DCHECK(IsMainThread());
-  if (WasContextDestroyedBeforeObserverCreation())
-    return false;
-  main_channel_ =
-      WebSocketChannelImpl::Create(loading_context, this, std::move(location));
-  return true;
-}
-
-bool MainChannelClient::Connect(
-    const KURL& url,
-    const String& protocol,
-    network::mojom::blink::WebSocketPtr socket_ptr) {
-  DCHECK(IsMainThread());
-  if (!main_channel_)
-    return false;
-  if (socket_ptr)
-    return main_channel_->Connect(url, protocol, std::move(socket_ptr));
-  // See Bridge::Connect for an explanation of the case where |socket_ptr| is
-  // null. In this case we allow |main_channel_| to connect the pipe for us.
-  return main_channel_->Connect(url, protocol);
-}
-
-void MainChannelClient::SendTextAsCharVector(
-    std::unique_ptr<Vector<char>> data) {
-  DCHECK(IsMainThread());
-  if (main_channel_)
-    main_channel_->SendTextAsCharVector(std::move(data));
-}
-
-void MainChannelClient::SendBinaryAsCharVector(
-    std::unique_ptr<Vector<char>> data) {
-  DCHECK(IsMainThread());
-  if (main_channel_)
-    main_channel_->SendBinaryAsCharVector(std::move(data));
-}
-
-void MainChannelClient::SendBlob(scoped_refptr<BlobDataHandle> blob_data) {
-  DCHECK(IsMainThread());
-  if (main_channel_)
-    main_channel_->Send(std::move(blob_data));
-}
-
-void MainChannelClient::Close(int code, const String& reason) {
-  DCHECK(IsMainThread());
-  if (main_channel_)
-    main_channel_->Close(code, reason);
-}
-
-void MainChannelClient::Fail(const String& reason,
-                             MessageLevel level,
-                             std::unique_ptr<SourceLocation> location) {
-  DCHECK(IsMainThread());
-  if (main_channel_)
-    main_channel_->Fail(reason, level, std::move(location));
-}
-
-void MainChannelClient::ReleaseMainChannel() {
-  if (!main_channel_)
-    return;
-
-  main_channel_->Disconnect();
-  main_channel_ = nullptr;
-}
-
-void MainChannelClient::Disconnect() {
-  DCHECK(IsMainThread());
-
-  ReleaseMainChannel();
-}
-
-static void WorkerGlobalScopeDidConnect(Bridge* bridge,
-                                        const String& subprotocol,
-                                        const String& extensions) {
-  if (bridge && bridge->Client())
-    bridge->Client()->DidConnect(subprotocol, extensions);
-}
-
-void MainChannelClient::DidConnect(const String& subprotocol,
-                                   const String& extensions) {
-  DCHECK(IsMainThread());
-  PostCrossThreadTask(*worker_networking_task_runner_, FROM_HERE,
-                      CrossThreadBind(&WorkerGlobalScopeDidConnect, bridge_,
-                                      subprotocol, extensions));
-}
-
-static void WorkerGlobalScopeDidReceiveTextMessage(Bridge* bridge,
-                                                   const String& payload) {
-  if (bridge && bridge->Client())
-    bridge->Client()->DidReceiveTextMessage(payload);
-}
-
-void MainChannelClient::DidReceiveTextMessage(const String& payload) {
-  DCHECK(IsMainThread());
-  PostCrossThreadTask(*worker_networking_task_runner_, FROM_HERE,
-                      CrossThreadBind(&WorkerGlobalScopeDidReceiveTextMessage,
-                                      bridge_, payload));
-}
-
-static void WorkerGlobalScopeDidReceiveBinaryMessage(
-    Bridge* bridge,
-    std::unique_ptr<Vector<char>> payload) {
-  if (bridge && bridge->Client())
-    bridge->Client()->DidReceiveBinaryMessage(std::move(payload));
-}
-
-void MainChannelClient::DidReceiveBinaryMessage(
-    std::unique_ptr<Vector<char>> payload) {
-  DCHECK(IsMainThread());
-  PostCrossThreadTask(
-      *worker_networking_task_runner_, FROM_HERE,
-      CrossThreadBind(&WorkerGlobalScopeDidReceiveBinaryMessage, bridge_,
-                      WTF::Passed(std::move(payload))));
-}
-
-static void WorkerGlobalScopeDidConsumeBufferedAmount(Bridge* bridge,
-                                                      uint64_t consumed) {
-  if (bridge && bridge->Client())
-    bridge->Client()->DidConsumeBufferedAmount(consumed);
-}
-
-void MainChannelClient::DidConsumeBufferedAmount(uint64_t consumed) {
-  DCHECK(IsMainThread());
-  PostCrossThreadTask(
-      *worker_networking_task_runner_, FROM_HERE,
-      CrossThreadBind(&WorkerGlobalScopeDidConsumeBufferedAmount, bridge_,
-                      consumed));
-}
-
-static void WorkerGlobalScopeDidStartClosingHandshake(Bridge* bridge) {
-  if (bridge && bridge->Client())
-    bridge->Client()->DidStartClosingHandshake();
-}
-
-void MainChannelClient::DidStartClosingHandshake() {
-  DCHECK(IsMainThread());
-  PostCrossThreadTask(
-      *worker_networking_task_runner_, FROM_HERE,
-      CrossThreadBind(&WorkerGlobalScopeDidStartClosingHandshake, bridge_));
-}
-
-static void WorkerGlobalScopeDidClose(
-    Bridge* bridge,
-    WebSocketChannelClient::ClosingHandshakeCompletionStatus
-        closing_handshake_completion,
-    unsigned short code,
-    const String& reason) {
-  if (bridge && bridge->Client())
-    bridge->Client()->DidClose(closing_handshake_completion, code, reason);
-}
-
-void MainChannelClient::DidClose(
-    ClosingHandshakeCompletionStatus closing_handshake_completion,
-    unsigned short code,
-    const String& reason) {
-  DCHECK(IsMainThread());
-
-  ReleaseMainChannel();
-
-  PostCrossThreadTask(
-      *worker_networking_task_runner_, FROM_HERE,
-      CrossThreadBind(&WorkerGlobalScopeDidClose, bridge_,
-                      closing_handshake_completion, code, reason));
-}
-
-static void WorkerGlobalScopeDidError(Bridge* bridge) {
-  if (bridge && bridge->Client())
-    bridge->Client()->DidError();
-}
-
-void MainChannelClient::DidError() {
-  DCHECK(IsMainThread());
-  PostCrossThreadTask(*worker_networking_task_runner_, FROM_HERE,
-                      CrossThreadBind(&WorkerGlobalScopeDidError, bridge_));
-}
-
-void MainChannelClient::ContextDestroyed(WorkerThreadLifecycleContext*) {
-  DCHECK(IsMainThread());
-
-  ReleaseMainChannel();
-
-  bridge_ = nullptr;
-}
-
-void MainChannelClient::Trace(blink::Visitor* visitor) {
-  visitor->Trace(main_channel_);
-  WebSocketChannelClient::Trace(visitor);
-  WorkerThreadLifecycleObserver::Trace(visitor);
-}
-
-Bridge::Bridge(WebSocketChannelClient* client,
-               WorkerGlobalScope& worker_global_scope)
-    : client_(client),
-      worker_global_scope_(worker_global_scope),
-      parent_execution_context_task_runners_(
-          worker_global_scope_->GetThread()
-              ->GetParentExecutionContextTaskRunners()) {}
-
-Bridge::~Bridge() {
-  DCHECK(!main_channel_client_);
-}
-
-void Bridge::ConnectOnMainThread(
-    std::unique_ptr<SourceLocation> location,
-    ThreadableLoadingContext* loading_context,
-    scoped_refptr<base::SingleThreadTaskRunner> worker_networking_task_runner,
-    WorkerThreadLifecycleContext* worker_thread_lifecycle_context,
-    const KURL& url,
-    const String& protocol,
-    network::mojom::blink::WebSocketPtrInfo socket_ptr_info,
-    WebSocketChannelSyncHelper* sync_helper) {
-  DCHECK(IsMainThread());
-  DCHECK(!main_channel_client_);
-  MainChannelClient* main_channel_client =
-      new MainChannelClient(this, std::move(worker_networking_task_runner),
-                            worker_thread_lifecycle_context);
-  if (main_channel_client->Initialize(std::move(location), loading_context)) {
-    main_channel_client_ = main_channel_client;
-    sync_helper->SetConnectRequestResult(main_channel_client_->Connect(
-        url, protocol, mojo::MakeProxy(std::move(socket_ptr_info))));
-  }
-  sync_helper->SignalWorkerThread();
-}
-
-bool Bridge::Connect(std::unique_ptr<SourceLocation> location,
-                     const KURL& url,
-                     const String& protocol) {
-  DCHECK(worker_global_scope_->IsContextThread());
-  // Wait for completion of the task on the main thread because the mixed
-  // content check must synchronously be conducted.
-  WebSocketChannelSyncHelper sync_helper;
-  scoped_refptr<base::SingleThreadTaskRunner> worker_networking_task_runner =
-      worker_global_scope_->GetTaskRunner(TaskType::kNetworking);
-  WorkerThread* worker_thread = worker_global_scope_->GetThread();
-
-  // Dedicated workers are a special case as they always have an associated
-  // document and so can make requests using that context. In the case of
-  // https://crbug.com/760708 for example this is necessary to apply the user's
-  // SSL interstitial decision to WebSocket connections from the worker.
-  network::mojom::blink::WebSocketPtrInfo socket_ptr_info;
-  if (!worker_global_scope_->IsDedicatedWorkerGlobalScope()) {
-    worker_global_scope_->GetInterfaceProvider()->GetInterface(
-        mojo::MakeRequest(&socket_ptr_info));
-  }
-
-  PostCrossThreadTask(
-      *parent_execution_context_task_runners_->Get(TaskType::kNetworking),
-      FROM_HERE,
-      CrossThreadBind(
-          &Bridge::ConnectOnMainThread, WrapCrossThreadPersistent(this),
-          WTF::Passed(location->Clone()),
-          WrapCrossThreadPersistent(worker_thread->GetLoadingContext()),
-          std::move(worker_networking_task_runner),
-          WrapCrossThreadPersistent(
-              worker_thread->GetWorkerThreadLifecycleContext()),
-          url, protocol, WTF::Passed(std::move(socket_ptr_info)),
-          CrossThreadUnretained(&sync_helper)));
-  sync_helper.Wait();
-  return sync_helper.ConnectRequestResult();
-}
-
-void Bridge::Send(const CString& message) {
-  DCHECK(main_channel_client_);
-  std::unique_ptr<Vector<char>> data =
-      std::make_unique<Vector<char>>(message.length());
-  if (message.length()) {
-    memcpy(data->data(), static_cast<const char*>(message.data()),
-           message.length());
-  }
-
-  PostCrossThreadTask(
-      *parent_execution_context_task_runners_->Get(TaskType::kNetworking),
-      FROM_HERE,
-      CrossThreadBind(&MainChannelClient::SendTextAsCharVector,
-                      main_channel_client_, WTF::Passed(std::move(data))));
-}
-
-void Bridge::Send(const DOMArrayBuffer& binary_data,
-                  unsigned byte_offset,
-                  unsigned byte_length) {
-  DCHECK(main_channel_client_);
-  // ArrayBuffer isn't thread-safe, hence the content of ArrayBuffer is copied
-  // into Vector<char>.
-  std::unique_ptr<Vector<char>> data =
-      std::make_unique<Vector<char>>(byte_length);
-  if (binary_data.ByteLength()) {
-    memcpy(data->data(),
-           static_cast<const char*>(binary_data.Data()) + byte_offset,
-           byte_length);
-  }
-
-  PostCrossThreadTask(
-      *parent_execution_context_task_runners_->Get(TaskType::kNetworking),
-      FROM_HERE,
-      CrossThreadBind(&MainChannelClient::SendBinaryAsCharVector,
-                      main_channel_client_, WTF::Passed(std::move(data))));
-}
-
-void Bridge::Send(scoped_refptr<BlobDataHandle> data) {
-  DCHECK(main_channel_client_);
-  PostCrossThreadTask(
-      *parent_execution_context_task_runners_->Get(TaskType::kNetworking),
-      FROM_HERE,
-      CrossThreadBind(&MainChannelClient::SendBlob, main_channel_client_,
-                      std::move(data)));
-}
-
-void Bridge::Close(int code, const String& reason) {
-  DCHECK(main_channel_client_);
-  PostCrossThreadTask(
-      *parent_execution_context_task_runners_->Get(TaskType::kNetworking),
-      FROM_HERE,
-      CrossThreadBind(&MainChannelClient::Close, main_channel_client_, code,
-                      reason));
-}
-
-void Bridge::Fail(const String& reason,
-                  MessageLevel level,
-                  std::unique_ptr<SourceLocation> location) {
-  DCHECK(main_channel_client_);
-  PostCrossThreadTask(
-      *parent_execution_context_task_runners_->Get(TaskType::kNetworking),
-      FROM_HERE,
-      CrossThreadBind(&MainChannelClient::Fail, main_channel_client_, reason,
-                      level, WTF::Passed(location->Clone())));
-}
-
-void Bridge::Disconnect() {
-  if (!main_channel_client_)
-    return;
-
-  PostCrossThreadTask(
-      *parent_execution_context_task_runners_->Get(TaskType::kNetworking),
-      FROM_HERE,
-      CrossThreadBind(&MainChannelClient::Disconnect, main_channel_client_));
-
-  client_ = nullptr;
-  main_channel_client_ = nullptr;
-  worker_global_scope_.Clear();
-}
-
-void Bridge::Trace(blink::Visitor* visitor) {
-  visitor->Trace(client_);
-  visitor->Trace(worker_global_scope_);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/modules/websockets/worker_websocket_channel.h b/third_party/blink/renderer/modules/websockets/worker_websocket_channel.h
deleted file mode 100644
index af46395..0000000
--- a/third_party/blink/renderer/modules/websockets/worker_websocket_channel.h
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (C) 2011 Google Inc.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBSOCKETS_WORKER_WEBSOCKET_CHANNEL_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBSOCKETS_WORKER_WEBSOCKET_CHANNEL_H_
-
-#include <stdint.h>
-#include <memory>
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/single_thread_task_runner.h"
-#include "services/network/public/mojom/websocket.mojom-blink.h"
-#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
-#include "third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h"
-#include "third_party/blink/renderer/core/workers/worker_thread_lifecycle_observer.h"
-#include "third_party/blink/renderer/modules/websockets/websocket_channel.h"
-#include "third_party/blink/renderer/modules/websockets/websocket_channel_client.h"
-#include "third_party/blink/renderer/modules/websockets/websocket_channel_impl.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-class BlobDataHandle;
-class KURL;
-class ThreadableLoadingContext;
-class WebSocketChannelSyncHelper;
-class WorkerGlobalScope;
-class WorkerThreadLifecycleContext;
-
-class WorkerWebSocketChannel final : public WebSocketChannel {
- public:
-  static WebSocketChannel* Create(WorkerGlobalScope& worker_global_scope,
-                                  WebSocketChannelClient* client,
-                                  std::unique_ptr<SourceLocation> location) {
-    return new WorkerWebSocketChannel(worker_global_scope, client,
-                                      std::move(location));
-  }
-  ~WorkerWebSocketChannel() override;
-
-  // WebSocketChannel functions.
-  bool Connect(const KURL&, const String& protocol) override;
-  void Send(const CString&) override;
-  void Send(const DOMArrayBuffer&,
-            unsigned byte_offset,
-            unsigned byte_length) override;
-  void Send(scoped_refptr<BlobDataHandle>) override;
-  void SendTextAsCharVector(std::unique_ptr<Vector<char>>) override {
-    NOTREACHED();
-  }
-  void SendBinaryAsCharVector(std::unique_ptr<Vector<char>>) override {
-    NOTREACHED();
-  }
-  void Close(int code, const String& reason) override;
-  void Fail(const String& reason,
-            MessageLevel,
-            std::unique_ptr<SourceLocation>) override;
-  void Disconnect() override;  // Will suppress didClose().
-
-  void Trace(blink::Visitor*) override;
-
-  class Bridge;
-
-  // A WebSocketChannelClient to pass to |main_channel_|. It forwards
-  // method incovactions to the worker thread, and re-invokes them on the
-  // WebSocketChannelClient given to the WorkerWebSocketChannel.
-  //
-  // Allocated and used in the main thread.
-  class MainChannelClient final
-      : public GarbageCollectedFinalized<MainChannelClient>,
-        public WebSocketChannelClient,
-        public WorkerThreadLifecycleObserver {
-    USING_GARBAGE_COLLECTED_MIXIN(MainChannelClient);
-
-   public:
-    MainChannelClient(Bridge*,
-                      scoped_refptr<base::SingleThreadTaskRunner>,
-                      WorkerThreadLifecycleContext*);
-    ~MainChannelClient() override;
-
-    // SourceLocation parameter may be shown when the connection fails.
-    bool Initialize(std::unique_ptr<SourceLocation>, ThreadableLoadingContext*);
-
-    bool Connect(const KURL&,
-                 const String& protocol,
-                 network::mojom::blink::WebSocketPtr);
-    void SendTextAsCharVector(std::unique_ptr<Vector<char>>);
-    void SendBinaryAsCharVector(std::unique_ptr<Vector<char>>);
-    void SendBlob(scoped_refptr<BlobDataHandle>);
-    void Close(int code, const String& reason);
-    void Fail(const String& reason,
-              MessageLevel,
-              std::unique_ptr<SourceLocation>);
-    void Disconnect();
-
-    void Trace(blink::Visitor*) override;
-    // Promptly clear connection to bridge + loader proxy.
-    EAGERLY_FINALIZE();
-
-    // WebSocketChannelClient functions.
-    void DidConnect(const String& subprotocol,
-                    const String& extensions) override;
-    void DidReceiveTextMessage(const String& payload) override;
-    void DidReceiveBinaryMessage(std::unique_ptr<Vector<char>>) override;
-    void DidConsumeBufferedAmount(uint64_t) override;
-    void DidStartClosingHandshake() override;
-    void DidClose(ClosingHandshakeCompletionStatus,
-                  unsigned short code,
-                  const String& reason) override;
-    void DidError() override;
-
-    // WorkerThreadLifecycleObserver function.
-    void ContextDestroyed(WorkerThreadLifecycleContext*) override;
-
-   private:
-    void ReleaseMainChannel();
-
-    CrossThreadWeakPersistent<Bridge> bridge_;
-    scoped_refptr<base::SingleThreadTaskRunner> worker_networking_task_runner_;
-    Member<WebSocketChannelImpl> main_channel_;
-
-    DISALLOW_COPY_AND_ASSIGN(MainChannelClient);
-  };
-
-  // Bridge for MainChannelClient. Running on the worker thread.
-  class Bridge final : public GarbageCollectedFinalized<Bridge> {
-   public:
-    Bridge(WebSocketChannelClient*, WorkerGlobalScope&);
-    ~Bridge();
-
-    // SourceLocation parameter may be shown when the connection fails.
-    bool Connect(std::unique_ptr<SourceLocation>,
-                 const KURL&,
-                 const String& protocol);
-
-    void Send(const CString& message);
-    void Send(const DOMArrayBuffer&,
-              unsigned byte_offset,
-              unsigned byte_length);
-    void Send(scoped_refptr<BlobDataHandle>);
-    void Close(int code, const String& reason);
-    void Fail(const String& reason,
-              MessageLevel,
-              std::unique_ptr<SourceLocation>);
-    void Disconnect();
-
-    void ConnectOnMainThread(std::unique_ptr<SourceLocation>,
-                             ThreadableLoadingContext*,
-                             scoped_refptr<base::SingleThreadTaskRunner>,
-                             WorkerThreadLifecycleContext*,
-                             const KURL&,
-                             const String& protocol,
-                             network::mojom::blink::WebSocketPtrInfo,
-                             WebSocketChannelSyncHelper*);
-
-    // Returns null when |disconnect| has already been called.
-    WebSocketChannelClient* Client() { return client_; }
-
-    void Trace(blink::Visitor*);
-    // Promptly clear connection to peer + loader proxy.
-    EAGERLY_FINALIZE();
-
-   private:
-    Member<WebSocketChannelClient> client_;
-    Member<WorkerGlobalScope> worker_global_scope_;
-    CrossThreadPersistent<ParentExecutionContextTaskRunners>
-        parent_execution_context_task_runners_;
-    CrossThreadPersistent<MainChannelClient> main_channel_client_;
-
-    DISALLOW_COPY_AND_ASSIGN(Bridge);
-  };
-
- private:
-  WorkerWebSocketChannel(WorkerGlobalScope&,
-                         WebSocketChannelClient*,
-                         std::unique_ptr<SourceLocation>);
-
-  Member<Bridge> bridge_;
-  std::unique_ptr<SourceLocation> location_at_connection_;
-
-  DISALLOW_COPY_AND_ASSIGN(WorkerWebSocketChannel);
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBSOCKETS_WORKER_WEBSOCKET_CHANNEL_H_
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index d5d8e483..83aa1ad 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1284,6 +1284,7 @@
     "scroll/smooth_scroll_sequencer.h",
     "scroll/web_scroll_into_view_params.cc",
     "scroll/web_scrollbar_theme.mm",
+    "scroll/web_scrollbar_theme_client.h",
     "serialized_resource.h",
     "shared_buffer.cc",
     "shared_buffer.h",
diff --git a/third_party/blink/renderer/platform/exported/platform.cc b/third_party/blink/renderer/platform/exported/platform.cc
index 848cda3..7d0838e 100644
--- a/third_party/blink/renderer/platform/exported/platform.cc
+++ b/third_party/blink/renderer/platform/exported/platform.cc
@@ -248,11 +248,6 @@
   return nullptr;
 }
 
-std::unique_ptr<WebSocketHandshakeThrottle>
-Platform::CreateWebSocketHandshakeThrottle() {
-  return nullptr;
-}
-
 std::unique_ptr<WebImageCaptureFrameGrabber>
 Platform::CreateImageCaptureFrameGrabber() {
   return nullptr;
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
index 8d951cd..4685fcd2 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
@@ -152,7 +152,6 @@
 
   ~CanvasResourceProviderTextureGpuMemoryBuffer() override = default;
   bool SupportsDirectCompositing() const override { return true; }
-  bool SupportsSingleBuffering() const override { return true; }
 
  private:
   scoped_refptr<CanvasResource> CreateResource() final {
@@ -264,7 +263,6 @@
 
   ~CanvasResourceProviderRamGpuMemoryBuffer() override = default;
   bool SupportsDirectCompositing() const override { return true; }
-  bool SupportsSingleBuffering() const override { return true; }
 
  private:
   scoped_refptr<CanvasResource> CreateResource() final {
@@ -320,7 +318,6 @@
   }
   ~CanvasResourceProviderSharedBitmap() override = default;
   bool SupportsDirectCompositing() const override { return true; }
-  bool SupportsSingleBuffering() const override { return true; }
 
  private:
   scoped_refptr<CanvasResource> CreateResource() final {
@@ -687,7 +684,6 @@
   canvas_image_provider_.reset();
   xform_canvas_ = nullptr;
   surface_ = nullptr;
-  single_buffer_ = nullptr;
 }
 
 uint32_t CanvasResourceProvider::ContentUniqueID() const {
@@ -725,11 +721,6 @@
 }
 
 scoped_refptr<CanvasResource> CanvasResourceProvider::NewOrRecycledResource() {
-  if (IsSingleBuffered()) {
-    if (!single_buffer_)
-      single_buffer_ = CreateResource();
-    return single_buffer_;
-  }
   if (recycled_resources_.size()) {
     scoped_refptr<CanvasResource> resource =
         std::move(recycled_resources_.back());
@@ -739,11 +730,4 @@
   return CreateResource();
 }
 
-void CanvasResourceProvider::TryEnableSingleBuffering() {
-  if (IsSingleBuffered() || !SupportsSingleBuffering())
-    return;
-  SetResourceRecyclingEnabled(false);
-  is_single_buffered_ = true;
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h
index cf0325b..cfa543e5 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h
@@ -100,26 +100,11 @@
   virtual bool IsValid() const = 0;
   virtual bool IsAccelerated() const = 0;
   virtual bool SupportsDirectCompositing() const = 0;
-  virtual bool SupportsSingleBuffering() const { return false; }
   uint32_t ContentUniqueID() const;
   CanvasResourceDispatcher* ResourceDispatcher() {
     return resource_dispatcher_.get();
   }
 
-  // Indicates that the compositing path is single buffered, meaning that
-  // ProduceFrame() return a reference to the same resource each time, which
-  // implies that Producing an animation frame may overwrite the resource used
-  // by the previous frame. This results in graphics updates skipping the
-  // queue, thus reducing latency, but with the possible side effects of
-  // tearring (in cases where the resource is scanned out directly) and
-  // irregular frame rate.
-  bool IsSingleBuffered() { return is_single_buffered_; }
-
-  // Attempt to enable single buffering mode on this resource provider.  May
-  // fail if the CanvasResourcePRovider subclass does not support this mode of
-  // operation.
-  void TryEnableSingleBuffering();
-
   void RecycleResource(scoped_refptr<CanvasResource>);
   void SetResourceRecyclingEnabled(bool);
   void ClearRecycledResources();
@@ -204,9 +189,6 @@
   WTF::Vector<scoped_refptr<CanvasResource>> recycled_resources_;
   bool resource_recycling_enabled_ = true;
 
-  bool is_single_buffered_ = false;
-  scoped_refptr<CanvasResource> single_buffer_;
-
   base::WeakPtrFactory<CanvasResourceProvider> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(CanvasResourceProvider);
diff --git a/third_party/blink/renderer/platform/lifecycle_notifier.h b/third_party/blink/renderer/platform/lifecycle_notifier.h
index 668002ef..47e9a283 100644
--- a/third_party/blink/renderer/platform/lifecycle_notifier.h
+++ b/third_party/blink/renderer/platform/lifecycle_notifier.h
@@ -81,20 +81,6 @@
     }
   }
 
-  // ForEachObserver() variant that does not protect against memory corruption.
-  //
-  // Only used by SynchronousMutationNotifier::NotifyUpdateCharacterData. See
-  // implementation comment for why it is necessary.
-  //
-  // TODO(crbug.com/862900): Fix SynchronousMutationNotifier and remove this.
-  template <typename ForEachCallable>
-  void ForEachObserverWithoutChecks(const ForEachCallable& callable) const {
-    for (LifecycleObserverBase* observer_base : observers_) {
-      Observer* observer = static_cast<Observer*>(observer_base);
-      callable(observer);
-    }
-  }
-
  private:
   using ObserverSet = HeapHashSet<WeakMember<LifecycleObserverBase>>;
 
diff --git a/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc b/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc
index 961b7677..e25acfc7 100644
--- a/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc
+++ b/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/platform/loader/cors/cors_error_string.h"
 
+#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
 #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 
@@ -82,6 +83,7 @@
     case network::mojom::CORSError::kInvalidAllowOriginValue:
     case network::mojom::CORSError::kAllowOriginMismatch:
     case network::mojom::CORSError::kInvalidAllowCredentials:
+    case network::mojom::CORSError::kCORSDisabledScheme:
     case network::mojom::CORSError::kPreflightWildcardOriginNotAllowed:
     case network::mojom::CORSError::kPreflightMissingAllowOriginHeader:
     case network::mojom::CORSError::kPreflightMultipleAllowOriginValues:
@@ -312,6 +314,10 @@
                  "XMLHttpRequest is controlled by the withCredentials "
                  "attribute."
                : ""));
+    case CORSError::kCORSDisabledScheme:
+      return String::Format(
+          "Cross origin requests are only supported for protocol schemes: %s.",
+          SchemeRegistry::ListOfCORSEnabledURLSchemes().Ascii().data());
     case CORSError::kPreflightInvalidStatus:
       return String("Response for preflight does not have HTTP ok status.");
     case CORSError::kPreflightDisallowedRedirect:
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_error.cc b/third_party/blink/renderer/platform/loader/fetch/resource_error.cc
index 788f95b..e0fbcb3 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_error.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_error.cc
@@ -92,6 +92,10 @@
   InitializeDescription();
 }
 
+ResourceError::ResourceError(const KURL& url,
+                             const network::CORSErrorStatus& cors_error_status)
+    : ResourceError(net::ERR_FAILED, url, cors_error_status) {}
+
 ResourceError::ResourceError(const WebURLError& error)
     : error_code_(error.reason()),
       extended_error_code_(error.extended_reason()),
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_error.h b/third_party/blink/renderer/platform/loader/fetch/resource_error.h
index 5aaaa0c..7ffdfea 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_error.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_error.h
@@ -64,6 +64,8 @@
   ResourceError(int error_code,
                 const KURL& failing_url,
                 base::Optional<network::CORSErrorStatus>);
+  ResourceError(const KURL& failing_url,
+                const network::CORSErrorStatus& status);
   ResourceError(const WebURLError&);
 
   // Makes a deep copy. Useful for when you need to use a ResourceError on
diff --git a/third_party/blink/renderer/platform/scheduler/child/features.h b/third_party/blink/renderer/platform/scheduler/child/features.h
index 796e257..b518589 100644
--- a/third_party/blink/renderer/platform/scheduler/child/features.h
+++ b/third_party/blink/renderer/platform/scheduler/child/features.h
@@ -11,7 +11,7 @@
 namespace scheduler {
 
 const base::Feature kHighPriorityInputOnMainThread{
-    "BlinkSchedulerHighPriorityInput", base::FEATURE_DISABLED_BY_DEFAULT};
+    "BlinkSchedulerHighPriorityInput", base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kHighPriorityInputOnCompositorThread{
     "BlinkSchedulerHighPriorityInputOnCompositorThread",
diff --git a/third_party/blink/renderer/platform/scroll/scrollbar_theme_mac.h b/third_party/blink/renderer/platform/scroll/scrollbar_theme_mac.h
index 4259a285..688a9ab 100644
--- a/third_party/blink/renderer/platform/scroll/scrollbar_theme_mac.h
+++ b/third_party/blink/renderer/platform/scroll/scrollbar_theme_mac.h
@@ -30,6 +30,7 @@
 
 #include "third_party/blink/renderer/platform/mac/ns_scroller_imp_details.h"
 #include "third_party/blink/renderer/platform/scroll/scrollbar_theme.h"
+#include "third_party/blink/renderer/platform/scroll/web_scrollbar_theme_client.h"
 
 typedef id ScrollbarPainter;
 
@@ -37,18 +38,14 @@
 
 class Pattern;
 
-class PLATFORM_EXPORT ScrollbarThemeMac : public ScrollbarTheme {
+class PLATFORM_EXPORT ScrollbarThemeMac : public ScrollbarTheme,
+                                          public WebScrollbarThemeClient {
  public:
+  ScrollbarThemeMac();
   ~ScrollbarThemeMac() override;
 
   void RegisterScrollbar(Scrollbar&) override;
   void UnregisterScrollbar(Scrollbar&) override;
-  void PreferencesChanged(float initial_button_delay,
-                          float autoscroll_button_delay,
-                          NSScrollerStyle preferred_scroller_style,
-                          bool redraw,
-                          WebScrollbarButtonsPlacement,
-                          bool jump_on_track_click);
 
   bool SupportsControlTints() const override { return true; }
 
@@ -97,6 +94,8 @@
 
   float ThumbOpacity(const Scrollbar&) const override;
 
+  void PreferencesChanged() override;
+
   static NSScrollerStyle RecommendedScrollerStyle();
   static void SetJumpOnTrackClick(bool);
 
diff --git a/third_party/blink/renderer/platform/scroll/scrollbar_theme_mac.mm b/third_party/blink/renderer/platform/scroll/scrollbar_theme_mac.mm
index d15d6f263..5a1f094 100644
--- a/third_party/blink/renderer/platform/scroll/scrollbar_theme_mac.mm
+++ b/third_party/blink/renderer/platform/scroll/scrollbar_theme_mac.mm
@@ -27,6 +27,7 @@
 
 #include <Carbon/Carbon.h>
 #include "skia/ext/skia_utils_mac.h"
+#include "third_party/blink/public/platform/mac/web_scrollbar_theme.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_mouse_event.h"
 #include "third_party/blink/public/platform/web_rect.h"
@@ -103,11 +104,6 @@
   return set;
 }
 
-static float g_initial_button_delay = 0.5f;
-static float g_autoscroll_button_delay = 0.05f;
-static NSScrollerStyle g_preferred_scroller_style = NSScrollerStyleLegacy;
-static bool g_jump_on_track_click = false;
-
 typedef PersistentHeapHashMap<WeakMember<Scrollbar>,
                               RetainPtr<BlinkScrollbarObserver>>
     ScrollbarPainterMap;
@@ -126,6 +122,10 @@
   return global_supports_expanded_scrollbars;
 }
 
+ScrollbarThemeMac::ScrollbarThemeMac() {
+  WebScrollbarTheme::RegisterClient(*this);
+}
+
 ScrollbarTheme& ScrollbarTheme::NativeTheme() {
   DEFINE_STATIC_LOCAL(ScrollbarThemeMac, overlay_theme, ());
   return overlay_theme;
@@ -144,37 +144,19 @@
                                             const WebMouseEvent& event) {
   bool alt_key_pressed = event.GetModifiers() & WebInputEvent::kAltKey;
   return (event.button == WebPointerProperties::Button::kLeft) &&
-         (g_jump_on_track_click != alt_key_pressed);
+         (WebScrollbarTheme::JumpOnTrackClick() != alt_key_pressed);
 }
 
-ScrollbarThemeMac::~ScrollbarThemeMac() {}
-
-void ScrollbarThemeMac::PreferencesChanged(
-    float initial_button_delay,
-    float autoscroll_button_delay,
-    NSScrollerStyle preferred_scroller_style,
-    bool redraw,
-    WebScrollbarButtonsPlacement button_placement,
-    bool jump_on_track_click) {
-  UpdateButtonPlacement(button_placement);
-  g_initial_button_delay = initial_button_delay;
-  g_autoscroll_button_delay = autoscroll_button_delay;
-  g_preferred_scroller_style = preferred_scroller_style;
-  g_jump_on_track_click = jump_on_track_click;
-  if (redraw && !GetScrollbarSet().IsEmpty()) {
-    for (const auto& scrollbar : GetScrollbarSet()) {
-      scrollbar->StyleChanged();
-      scrollbar->SetNeedsPaintInvalidation(kAllParts);
-    }
-  }
+ScrollbarThemeMac::~ScrollbarThemeMac() {
+  WebScrollbarTheme::UnregisterClient(*this);
 }
 
 TimeDelta ScrollbarThemeMac::InitialAutoscrollTimerDelay() {
-  return TimeDelta::FromSecondsD(g_initial_button_delay);
+  return TimeDelta::FromSecondsD(WebScrollbarTheme::InitialButtonDelay());
 }
 
 TimeDelta ScrollbarThemeMac::AutoscrollTimerDelay() {
-  return TimeDelta::FromSecondsD(g_autoscroll_button_delay);
+  return TimeDelta::FromSecondsD(WebScrollbarTheme::AutoscrollButtonDelay());
 }
 
 bool ScrollbarThemeMac::ShouldDragDocumentInsteadOfThumb(
@@ -419,11 +401,19 @@
   return [scrollbar_painter knobAlpha];
 }
 
+void ScrollbarThemeMac::PreferencesChanged() {
+  for (const auto& scrollbar : GetScrollbarSet()) {
+    scrollbar->StyleChanged();
+    scrollbar->SetNeedsPaintInvalidation(kAllParts);
+  }
+}
+
 // static
 NSScrollerStyle ScrollbarThemeMac::RecommendedScrollerStyle() {
   if (RuntimeEnabledFeatures::OverlayScrollbarsEnabled())
     return NSScrollerStyleOverlay;
-  return g_preferred_scroller_style;
+  return static_cast<NSScrollerStyle>(
+      WebScrollbarTheme::PreferredScrollerStyle());
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/scroll/web_scrollbar_theme.mm b/third_party/blink/renderer/platform/scroll/web_scrollbar_theme.mm
index d553932..19297c8 100644
--- a/third_party/blink/renderer/platform/scroll/web_scrollbar_theme.mm
+++ b/third_party/blink/renderer/platform/scroll/web_scrollbar_theme.mm
@@ -44,21 +44,58 @@
                   NSScrollerStyleOverlay,
               "ScrollerStyleOverlay must match NSScrollerStyleOverlay");
 
+typedef WTF::HashSet<WebScrollbarThemeClient*> ClientSet;
+
+static ClientSet& GetClientSet() {
+  DEFINE_STATIC_LOCAL(ClientSet, set, ());
+  return set;
+}
+
+static float s_initial_button_delay = 0.5f;
+static float s_autoscroll_button_delay = 0.05f;
+static ScrollerStyle s_preferred_scroller_style = kScrollerStyleLegacy;
+static bool s_jump_on_track_click = false;
+
 void WebScrollbarTheme::UpdateScrollbarsWithNSDefaults(
     float initial_button_delay,
     float autoscroll_button_delay,
     ScrollerStyle preferred_scroller_style,
     bool redraw,
-    WebScrollbarButtonsPlacement button_placement,
     bool jump_on_track_click) {
-  ScrollbarTheme& theme = ScrollbarTheme::DeprecatedStaticGetTheme();
-  if (theme.IsMockTheme())
-    return;
+  s_initial_button_delay = initial_button_delay;
+  s_autoscroll_button_delay = autoscroll_button_delay;
+  s_preferred_scroller_style = preferred_scroller_style;
+  s_jump_on_track_click = jump_on_track_click;
 
-  static_cast<ScrollbarThemeMac&>(theme).PreferencesChanged(
-      initial_button_delay, autoscroll_button_delay,
-      static_cast<NSScrollerStyle>(preferred_scroller_style), redraw,
-      button_placement, jump_on_track_click);
+  if (redraw && !GetClientSet().IsEmpty()) {
+    for (auto* client : GetClientSet()) {
+      client->PreferencesChanged();
+    }
+  }
+}
+
+float WebScrollbarTheme::InitialButtonDelay() {
+  return s_initial_button_delay;
+}
+
+float WebScrollbarTheme::AutoscrollButtonDelay() {
+  return s_autoscroll_button_delay;
+}
+
+ScrollerStyle WebScrollbarTheme::PreferredScrollerStyle() {
+  return s_preferred_scroller_style;
+}
+
+bool WebScrollbarTheme::JumpOnTrackClick() {
+  return s_jump_on_track_click;
+}
+
+void WebScrollbarTheme::RegisterClient(WebScrollbarThemeClient& client) {
+  GetClientSet().insert(&client);
+}
+
+void WebScrollbarTheme::UnregisterClient(WebScrollbarThemeClient& client) {
+  GetClientSet().erase(&client);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/scroll/web_scrollbar_theme_client.h b/third_party/blink/renderer/platform/scroll/web_scrollbar_theme_client.h
new file mode 100644
index 0000000..6a9952eac
--- /dev/null
+++ b/third_party/blink/renderer/platform/scroll/web_scrollbar_theme_client.h
@@ -0,0 +1,20 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCROLL_WEB_SCROLLBAR_THEME_CLIENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCROLL_WEB_SCROLLBAR_THEME_CLIENT_H_
+
+namespace blink {
+
+class WebScrollbarThemeClient {
+ protected:
+  WebScrollbarThemeClient() = default;
+
+ public:
+  virtual void PreferencesChanged() {}
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCROLL_WEB_SCROLLBAR_THEME_CLIENT_H_
diff --git a/third_party/closure_compiler/OWNERS b/third_party/closure_compiler/OWNERS
index 4f5335a..addd5dd 100644
--- a/third_party/closure_compiler/OWNERS
+++ b/third_party/closure_compiler/OWNERS
@@ -1,2 +1,3 @@
+calamity@chromium.org
 dpapad@chromium.org
 fukino@chromium.org
diff --git a/third_party/libprotobuf-mutator/BUILD.gn b/third_party/libprotobuf-mutator/BUILD.gn
index cea5363..3d81890 100644
--- a/third_party/libprotobuf-mutator/BUILD.gn
+++ b/third_party/libprotobuf-mutator/BUILD.gn
@@ -1,7 +1,7 @@
 # Copyright 2017 The Chromium Authors. All rights reserved.
 import("//build/config/sanitizers/sanitizers.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
-import("//third_party/protobuf/proto_library.gni")
+import("//third_party/libprotobuf-mutator/fuzzable_proto_library.gni")
 
 config("include_config") {
   include_dirs = [ "src/" ]
@@ -63,18 +63,9 @@
     ]
     public_configs = [ "//third_party/protobuf:protobuf_config" ]
   }
-  # To use the plugin in a proto_library you want to fuzz, add these lines to
-  # the proto_library definition (note the "=" in second to last line in the
-  # comment will need to be changed to "+=" if you have already defined
-  # deps):
-  # if (use_libfuzzer && current_toolchain == host_toolchain) {
-  #   generator_plugin_label =
-  #     "//third_party/libprotobuf-mutator:override_lite_runtime_plugin"
-  #   generator_plugin_suffix = ".pb"
-  #   # The plugin will generate cc, so don't ask for it to be done by protoc.
-  #   generate_cc = false
-  #   deps = ["//third_party/libprotobuf-mutator:override_lite_runtime_plugin"]
-  # }
+  # To use the plugin in a proto_library you want to fuzz, change the build
+  # target to fuzzable_proto_library (defined in
+  # //third_party/libprotobuf-mutator/fuzzable_proto_library.gni)
 }
 
 # The CQ will try building this target without "use_libfuzzer" if it is defined.
@@ -99,24 +90,21 @@
 }
 
 # Proto library for override_lite_runtime_plugin_test_fuzzer
-proto_library("override_lite_runtime_plugin_test_fuzzer_proto") {
+fuzzable_proto_library("override_lite_runtime_plugin_test_fuzzer_proto") {
   sources = [
     "protoc_plugin/imported.proto",
     "protoc_plugin/imported_publicly.proto",
     "protoc_plugin/test_fuzzer_input.proto",
   ]
+}
 
-  # TODO(metzman): Figure out how we can avoid using this toolchain check
-  # (maybe remove compilation from the plugin).
-  if (use_libfuzzer && current_toolchain == host_toolchain) {
-    generator_plugin_label =
-        "//third_party/libprotobuf-mutator:override_lite_runtime_plugin"
-    generator_plugin_suffix = ".pb"
-
-    # The plugin will generate cc, so don't ask for it to be done by protoc.
-    generate_cc = false
-    deps = [
-      "//third_party/libprotobuf-mutator:override_lite_runtime_plugin",
-    ]
+# Component that can provide protobuf_full to non-testonly targets
+component("protobuf_full") {
+  # Stop people from using me by accident.
+  if (!use_libfuzzer) {
+    testonly = true
   }
+  public_deps = [
+    "//third_party/protobuf:protobuf_full",
+  ]
 }
diff --git a/third_party/libprotobuf-mutator/fuzzable_proto_library.gni b/third_party/libprotobuf-mutator/fuzzable_proto_library.gni
new file mode 100644
index 0000000..4e70c62
--- /dev/null
+++ b/third_party/libprotobuf-mutator/fuzzable_proto_library.gni
@@ -0,0 +1,36 @@
+import("//third_party/protobuf/proto_library.gni")
+
+template("fuzzable_proto_library") {
+  forward_variables_from(invoker, "*")
+  if (use_libfuzzer) {
+    proto_library("proto_library_" + target_name) {
+      assert(current_toolchain == host_toolchain)
+      if (!defined(deps)) {
+        deps = []
+      }
+      deps +=
+          [ "//third_party/libprotobuf-mutator:override_lite_runtime_plugin" ]
+      generator_plugin_label =
+          "//third_party/libprotobuf-mutator:override_lite_runtime_plugin"
+      generator_plugin_suffix = ".pb"
+
+      # The plugin will generate cc, so don't ask for it to be done by protoc.
+      generate_cc = false
+      generate_python = false
+    }
+
+    # Use a component for the build target with target_name. That way we can
+    # also force dependencies to build using protobuf_full.
+    component(target_name) {
+      public_deps = [
+        ":proto_library_" + target_name,
+        "//third_party/libprotobuf-mutator:protobuf_full",
+      ]
+    }
+  } else {
+    # fuzzable_proto_library should behave like a proto_library when
+    # !use_libfuzzer.
+    proto_library(target_name) {
+    }
+  }
+}
diff --git a/third_party/node/OWNERS b/third_party/node/OWNERS
index 7dc2b53..718fadc3 100644
--- a/third_party/node/OWNERS
+++ b/third_party/node/OWNERS
@@ -1 +1,2 @@
 dpapad@chromium.org
+scottchen@chromium.org
diff --git a/third_party/polymer/OWNERS b/third_party/polymer/OWNERS
index 917b9f5..05d7008d 100644
--- a/third_party/polymer/OWNERS
+++ b/third_party/polymer/OWNERS
@@ -1,2 +1,3 @@
 dpapad@chromium.org
 michaelpg@chromium.org
+scottchen@chromium.org
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 8bcdc083..f473bd21 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -24463,6 +24463,7 @@
   <int value="81" label="PAGE_LOAD_CAPPING_INFOBAR_DELEGATE"/>
   <int value="83" label="AR_CORE_UPGRADE_ANDROID"/>
   <int value="84" label="BLOATED_RENDERER_INFOBAR_DELEGATE"/>
+  <int value="85" label="SUPERVISED_USERS_DEPRECATED_INFOBAR_DELEGATE"/>
 </enum>
 
 <enum name="InfoBarResponse">
@@ -43269,6 +43270,11 @@
   <int value="3" label="Request Failed"/>
 </enum>
 
+<enum name="SigninRequestHeaderOperation">
+  <int value="0" label="Header Added"/>
+  <int value="1" label="Header Removed"/>
+</enum>
+
 <enum name="SigninSignoutProfile">
   <int value="0" label="Preference changed">
     The preference or policy controlling if signin is valid has changed.
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 9c39efb7..2691519 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -45139,9 +45139,6 @@
 </histogram>
 
 <histogram name="MessageLoop.DelayedTaskQueue.PendingTasksCountOnIdle">
-  <obsolete>
-    Deprecated as of 07/2018.
-  </obsolete>
   <owner>gab@chromium.org</owner>
   <summary>
     The size of the delayed task queue when the loop becomes idle. Diagnosis
@@ -45150,9 +45147,6 @@
 </histogram>
 
 <histogram name="MessageLoop.DelayedTaskQueue.PostedDelay" units="ms">
-  <obsolete>
-    Deprecated as of 07/2018.
-  </obsolete>
   <owner>gab@chromium.org</owner>
   <summary>
     Reports the delay of a delayed task posted to a MessageLoop. Reported once
@@ -45160,20 +45154,7 @@
   </summary>
 </histogram>
 
-<histogram name="MessageLoop.DelayedTaskQueueForUI.PendingTasksCountOnIdle">
-  <owner>gab@chromium.org</owner>
-  <summary>
-    The size of the delayed task queue when the loop becomes idle on a UI
-    thread. Diagnosis metric for https://crbug.com/850450#c4. Note: this metric
-    is a bit broken on Mac OSX as CFRunLoop doesn't deterministically invoke
-    MessageLoop::DoIdleWork().
-  </summary>
-</histogram>
-
 <histogram name="MessageLoop.ScheduledSleep.Completed" units="ms">
-  <obsolete>
-    Deprecated as of 07/2018.
-  </obsolete>
   <owner>gab@chromium.org</owner>
   <summary>
     Reports the delay for which the MessageLoop successfully slept until an
@@ -45183,9 +45164,6 @@
 </histogram>
 
 <histogram name="MessageLoop.ScheduledSleep.Interrupted" units="ms">
-  <obsolete>
-    Deprecated as of 07/2018.
-  </obsolete>
   <owner>gab@chromium.org</owner>
   <summary>
     Reports the delay for which the MessageLoop had planned to sleep (next
@@ -93352,6 +93330,24 @@
   </summary>
 </histogram>
 
+<histogram name="Signin.RequestHeaderOperation.Dice"
+    enum="SigninRequestHeaderOperation">
+  <owner>msarda@chromium.org</owner>
+  <summary>
+    Tracks when Chrome adds or removes the Desktop Identity Consistency HTTP
+    header to Gaia.
+  </summary>
+</histogram>
+
+<histogram name="Signin.RequestHeaderOperation.Mirror"
+    enum="SigninRequestHeaderOperation">
+  <owner>msarda@chromium.org</owner>
+  <summary>
+    Tracks when Chrome adds or removes the the X-Chrome-Connected HTTP header to
+    Gaia.
+  </summary>
+</histogram>
+
 <histogram name="Signin.SignedInDurationBeforeSignout" units="minutes">
   <owner>mlerman@chromium.org</owner>
   <summary>
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn
index a19955e..5c86592 100644
--- a/ui/accessibility/BUILD.gn
+++ b/ui/accessibility/BUILD.gn
@@ -105,6 +105,7 @@
     "//base",
     "//base:i18n",
     "//ui/base",
+    "//ui/display",
     "//ui/gfx",
     "//ui/gfx/geometry",
     "//ui/strings",
diff --git a/ui/accessibility/DEPS b/ui/accessibility/DEPS
index 605f104..8a91ec8 100644
--- a/ui/accessibility/DEPS
+++ b/ui/accessibility/DEPS
@@ -7,6 +7,7 @@
   "+ui/base/l10n",
   "+ui/base/win",
   "+ui/gfx",
+  "+ui/display",
   "+ui/strings/grit/ui_strings.h",
 ]
 
diff --git a/ui/accessibility/platform/ax_platform_node_base.cc b/ui/accessibility/platform/ax_platform_node_base.cc
index 9c8fc68..895b32b0 100644
--- a/ui/accessibility/platform/ax_platform_node_base.cc
+++ b/ui/accessibility/platform/ax_platform_node_base.cc
@@ -519,6 +519,35 @@
   return false;
 }
 
+bool AXPlatformNodeBase::IsScrollable() const {
+  return (HasIntAttribute(ax::mojom::IntAttribute::kScrollXMin) &&
+          HasIntAttribute(ax::mojom::IntAttribute::kScrollXMax) &&
+          HasIntAttribute(ax::mojom::IntAttribute::kScrollX)) ||
+         (HasIntAttribute(ax::mojom::IntAttribute::kScrollYMin) &&
+          HasIntAttribute(ax::mojom::IntAttribute::kScrollYMax) &&
+          HasIntAttribute(ax::mojom::IntAttribute::kScrollY));
+}
+
+bool AXPlatformNodeBase::IsHorizontallyScrollable() const {
+  DCHECK_GE(GetIntAttribute(ax::mojom::IntAttribute::kScrollXMin), 0)
+      << "Pixel sizes should be non-negative.";
+  DCHECK_GE(GetIntAttribute(ax::mojom::IntAttribute::kScrollXMax), 0)
+      << "Pixel sizes should be non-negative.";
+  return IsScrollable() &&
+         GetIntAttribute(ax::mojom::IntAttribute::kScrollXMin) <
+             GetIntAttribute(ax::mojom::IntAttribute::kScrollXMax);
+}
+
+bool AXPlatformNodeBase::IsVerticallyScrollable() const {
+  DCHECK_GE(GetIntAttribute(ax::mojom::IntAttribute::kScrollYMin), 0)
+      << "Pixel sizes should be non-negative.";
+  DCHECK_GE(GetIntAttribute(ax::mojom::IntAttribute::kScrollYMax), 0)
+      << "Pixel sizes should be non-negative.";
+  return IsScrollable() &&
+         GetIntAttribute(ax::mojom::IntAttribute::kScrollYMin) <
+             GetIntAttribute(ax::mojom::IntAttribute::kScrollYMax);
+}
+
 base::string16 AXPlatformNodeBase::GetText() {
   return GetInnerText();
 }
diff --git a/ui/accessibility/platform/ax_platform_node_base.h b/ui/accessibility/platform/ax_platform_node_base.h
index 4c8e1331..efb4040 100644
--- a/ui/accessibility/platform/ax_platform_node_base.h
+++ b/ui/accessibility/platform/ax_platform_node_base.h
@@ -137,6 +137,16 @@
   // that might send notifications.
   bool IsLeaf();
 
+  // Returns true if this node can be scrolled either in the horizontal or the
+  // vertical direction.
+  bool IsScrollable() const;
+
+  // Returns true if this node can be scrolled in the horizontal direction.
+  bool IsHorizontallyScrollable() const;
+
+  // Returns true if this node can be scrolled in the vertical direction.
+  bool IsVerticallyScrollable() const;
+
   bool HasFocus();
 
   virtual base::string16 GetText();
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc
index 27d9167..38961732 100644
--- a/ui/accessibility/platform/ax_platform_node_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -27,7 +27,9 @@
 #include "ui/accessibility/platform/ax_platform_node_delegate.h"
 #include "ui/accessibility/platform/ax_platform_relation_win.h"
 #include "ui/base/win/atl_module.h"
+#include "ui/display/win/screen_win.h"
 #include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gfx/geometry/safe_integer_conversions.h"
 
 //
 // Macros to use at the top of any AXPlatformNodeWin function that implements
@@ -170,9 +172,14 @@
     g_iaccessible2_usage_observer_list = LAZY_INSTANCE_INITIALIZER;
 
 // Sets the multiplier by which large changes to a RangeValueProvider are
-// greater than small changes
+// greater than small changes.
 constexpr int kLargeChangeScaleFactor = 10;
 
+// The amount to scroll when UI Automation asks to scroll by a small increment.
+// Value is in device independent pixels and is the same used by Blink when
+// cursor keys are used to scroll a webpage.
+constexpr float kSmallScrollIncrement = 40.0f;
+
 }  // namespace
 
 // There is no easy way to decouple |kScreenReader| and |kHTML| accessibility
@@ -423,6 +430,72 @@
   return uia_array;
 }
 
+gfx::Vector2d AXPlatformNodeWin::CalculateUIAScrollPoint(
+    const ScrollAmount horizontal_amount,
+    const ScrollAmount vertical_amount) const {
+  if (!delegate_ || !IsScrollable())
+    return {};
+
+  const gfx::Rect bounds = delegate_->GetClippedScreenBoundsRect();
+  const int large_horizontal_change = bounds.width();
+  const int large_vertical_change = bounds.height();
+
+  const HWND hwnd = delegate_->GetTargetForNativeAccessibilityEvent();
+  DCHECK(hwnd);
+  const float scale_factor =
+      display::win::ScreenWin::GetScaleFactorForHWND(hwnd);
+  const int small_change =
+      gfx::ToRoundedInt(kSmallScrollIncrement * scale_factor);
+
+  const int x_min = GetIntAttribute(ax::mojom::IntAttribute::kScrollXMin);
+  const int x_max = GetIntAttribute(ax::mojom::IntAttribute::kScrollXMax);
+  const int y_min = GetIntAttribute(ax::mojom::IntAttribute::kScrollYMin);
+  const int y_max = GetIntAttribute(ax::mojom::IntAttribute::kScrollYMax);
+
+  int x = GetIntAttribute(ax::mojom::IntAttribute::kScrollX);
+  int y = GetIntAttribute(ax::mojom::IntAttribute::kScrollY);
+
+  switch (horizontal_amount) {
+    case ScrollAmount_LargeDecrement:
+      x -= large_horizontal_change;
+      break;
+    case ScrollAmount_LargeIncrement:
+      x += large_horizontal_change;
+      break;
+    case ScrollAmount_NoAmount:
+      break;
+    case ScrollAmount_SmallDecrement:
+      x -= small_change;
+      break;
+    case ScrollAmount_SmallIncrement:
+      x += small_change;
+      break;
+  }
+  x = std::min(x, x_max);
+  x = std::max(x, x_min);
+
+  switch (vertical_amount) {
+    case ScrollAmount_LargeDecrement:
+      y -= large_vertical_change;
+      break;
+    case ScrollAmount_LargeIncrement:
+      y += large_vertical_change;
+      break;
+    case ScrollAmount_NoAmount:
+      break;
+    case ScrollAmount_SmallDecrement:
+      y -= small_change;
+      break;
+    case ScrollAmount_SmallIncrement:
+      y += small_change;
+      break;
+  }
+  y = std::min(y, y_max);
+  y = std::max(y, y_min);
+
+  return {x, y};
+}
+
 //
 // AXPlatformNodeBase implementation.
 //
@@ -1292,7 +1365,7 @@
   // ax::mojom::Action::kScrollToMakeVisible wants a target rect in *local*
   // coords.
   gfx::Rect r = gfx::ToEnclosingRect(GetData().location);
-  r.Offset(-r.OffsetFromOrigin());
+  r -= r.OffsetFromOrigin();
   switch (scroll_type) {
     case IA2_SCROLL_TYPE_TOP_LEFT:
       r = gfx::Rect(r.x(), r.y(), 0, 0);
@@ -1313,7 +1386,6 @@
       r = gfx::Rect(r.right(), r.y(), 0, r.height());
       break;
     case IA2_SCROLL_TYPE_ANYWHERE:
-    default:
       break;
   }
 
@@ -1330,11 +1402,9 @@
     LONG x,
     LONG y) {
   COM_OBJECT_VALIDATE();
-
   WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SCROLL_TO_POINT);
 
   gfx::Point scroll_to(x, y);
-
   if (coordinate_type == IA2_COORDTYPE_SCREEN_RELATIVE) {
     scroll_to -= delegate_->GetUnclippedScreenBoundsRect().OffsetFromOrigin();
   } else if (coordinate_type == IA2_COORDTYPE_PARENT_RELATIVE) {
@@ -1525,7 +1595,6 @@
 
 STDMETHODIMP AXPlatformNodeWin::ScrollIntoView() {
   COM_OBJECT_VALIDATE();
-
   gfx::Rect r = gfx::ToEnclosingRect(GetData().location);
   r -= r.OffsetFromOrigin();
 
@@ -1533,13 +1602,131 @@
   action_data.target_node_id = GetData().id;
   action_data.target_rect = r;
   action_data.action = ax::mojom::Action::kScrollToMakeVisible;
-
   if (delegate_->AccessibilityPerformAction(action_data))
     return S_OK;
   return E_FAIL;
 }
 
 //
+// IScrollProvider implementation.
+//
+
+STDMETHODIMP AXPlatformNodeWin::Scroll(ScrollAmount horizontal_amount,
+                                       ScrollAmount vertical_amount) {
+  COM_OBJECT_VALIDATE();
+  if (!IsScrollable())
+    return E_FAIL;
+
+  AXActionData action_data;
+  action_data.target_node_id = GetData().id;
+  action_data.action = ax::mojom::Action::kSetScrollOffset;
+  action_data.target_point = gfx::PointAtOffsetFromOrigin(
+      CalculateUIAScrollPoint(horizontal_amount, vertical_amount));
+  if (delegate_->AccessibilityPerformAction(action_data))
+    return S_OK;
+  return E_FAIL;
+}
+
+STDMETHODIMP AXPlatformNodeWin::SetScrollPercent(double horizontal_percent,
+                                                 double vertical_percent) {
+  COM_OBJECT_VALIDATE();
+  if (!IsScrollable())
+    return E_FAIL;
+
+  const double x_min = GetIntAttribute(ax::mojom::IntAttribute::kScrollXMin);
+  const double x_max = GetIntAttribute(ax::mojom::IntAttribute::kScrollXMax);
+  const double y_min = GetIntAttribute(ax::mojom::IntAttribute::kScrollYMin);
+  const double y_max = GetIntAttribute(ax::mojom::IntAttribute::kScrollYMax);
+  const int x = gfx::ToRoundedInt(horizontal_percent * (x_max - x_min) + x_min);
+  const int y = gfx::ToRoundedInt(vertical_percent * (y_max - y_min) + y_min);
+  const gfx::Point scroll_to(x, y);
+
+  AXActionData action_data;
+  action_data.target_node_id = GetData().id;
+  action_data.action = ax::mojom::Action::kSetScrollOffset;
+  action_data.target_point = scroll_to;
+  if (delegate_->AccessibilityPerformAction(action_data))
+    return S_OK;
+  return E_FAIL;
+}
+
+STDMETHODIMP AXPlatformNodeWin::get_HorizontallyScrollable(BOOL* result) {
+  COM_OBJECT_VALIDATE_1_ARG(result);
+  *result = IsHorizontallyScrollable();
+  return S_OK;
+}
+
+STDMETHODIMP AXPlatformNodeWin::get_HorizontalScrollPercent(double* result) {
+  COM_OBJECT_VALIDATE_1_ARG(result);
+  if (!IsHorizontallyScrollable()) {
+    *result = UIA_ScrollPatternNoScroll;
+    return S_OK;
+  }
+
+  float x_min = GetIntAttribute(ax::mojom::IntAttribute::kScrollXMin);
+  float x_max = GetIntAttribute(ax::mojom::IntAttribute::kScrollXMax);
+  float x = GetIntAttribute(ax::mojom::IntAttribute::kScrollX);
+  *result = 100.0 * (x - x_min) / (x_max - x_min);
+  return S_OK;
+}
+
+// Horizontal size of the viewable region as a percentage of the total content
+// area.
+STDMETHODIMP AXPlatformNodeWin::get_HorizontalViewSize(double* result) {
+  COM_OBJECT_VALIDATE_1_ARG(result);
+  if (!IsHorizontallyScrollable()) {
+    *result = 100.;
+    return S_OK;
+  }
+
+  gfx::RectF clipped_bounds(delegate_->GetClippedScreenBoundsRect());
+  float x_min = GetIntAttribute(ax::mojom::IntAttribute::kScrollXMin);
+  float x_max = GetIntAttribute(ax::mojom::IntAttribute::kScrollXMax);
+  float total_width = clipped_bounds.width() + x_max - x_min;
+  DCHECK_LE(clipped_bounds.width(), total_width);
+  *result = 100.0 * clipped_bounds.width() / total_width;
+  return S_OK;
+}
+
+STDMETHODIMP AXPlatformNodeWin::get_VerticallyScrollable(BOOL* result) {
+  COM_OBJECT_VALIDATE_1_ARG(result);
+  *result = IsVerticallyScrollable();
+  return S_OK;
+}
+
+STDMETHODIMP AXPlatformNodeWin::get_VerticalScrollPercent(double* result) {
+  COM_OBJECT_VALIDATE_1_ARG(result);
+  if (!IsVerticallyScrollable()) {
+    *result = UIA_ScrollPatternNoScroll;
+    return S_OK;
+  }
+
+  float y_min = GetIntAttribute(ax::mojom::IntAttribute::kScrollYMin);
+  float y_max = GetIntAttribute(ax::mojom::IntAttribute::kScrollYMax);
+  float y = GetIntAttribute(ax::mojom::IntAttribute::kScrollY);
+  *result = 100.0 * (y - y_min) / (y_max - y_min);
+  return S_OK;
+}
+
+// Vertical size of the viewable region as a percentage of the total content
+// area.
+STDMETHODIMP AXPlatformNodeWin::get_VerticalViewSize(double* result) {
+  COM_OBJECT_VALIDATE_1_ARG(result);
+  if (!IsVerticallyScrollable()) {
+    *result = 100.0;
+    return S_OK;
+  }
+
+  gfx::RectF clipped_bounds(delegate_->GetClippedScreenBoundsRect());
+  float y_min = GetIntAttribute(ax::mojom::IntAttribute::kScrollYMin);
+  float y_max = GetIntAttribute(ax::mojom::IntAttribute::kScrollYMax);
+  float total_height = clipped_bounds.height() + y_max - y_min;
+  DCHECK_LE(clipped_bounds.height(), total_height);
+  *result = 100.0 * clipped_bounds.height() / total_height;
+  return S_OK;
+}
+
+//
 // ISelectionItemProvider implementation.
 //
 
diff --git a/ui/accessibility/platform/ax_platform_node_win.h b/ui/accessibility/platform/ax_platform_node_win.h
index 80069406..33356be 100644
--- a/ui/accessibility/platform/ax_platform_node_win.h
+++ b/ui/accessibility/platform/ax_platform_node_win.h
@@ -247,6 +247,7 @@
                         public IRangeValueProvider,
                         public IRawElementProviderSimple,
                         public IScrollItemProvider,
+                        public IScrollProvider,
                         public ISelectionItemProvider,
                         public ISelectionProvider,
                         public IServiceProvider,
@@ -273,6 +274,7 @@
     COM_INTERFACE_ENTRY(IRangeValueProvider)
     COM_INTERFACE_ENTRY(IRawElementProviderSimple)
     COM_INTERFACE_ENTRY(IScrollItemProvider)
+    COM_INTERFACE_ENTRY(IScrollProvider)
     COM_INTERFACE_ENTRY(ISelectionItemProvider)
     COM_INTERFACE_ENTRY(ISelectionProvider)
     COM_INTERFACE_ENTRY(ITableItemProvider)
@@ -483,6 +485,32 @@
   STDMETHODIMP ScrollIntoView() override;
 
   //
+  // IScrollProvider methods.
+  //
+
+  STDMETHODIMP Scroll(ScrollAmount horizontal_amount,
+                      ScrollAmount vertical_amount) override;
+
+  STDMETHODIMP SetScrollPercent(double horizontal_percent,
+                                double vertical_percent) override;
+
+  STDMETHODIMP get_HorizontallyScrollable(BOOL* result) override;
+
+  STDMETHODIMP get_HorizontalScrollPercent(double* result) override;
+
+  // Horizontal size of the viewable region as a percentage of the total content
+  // area.
+  STDMETHODIMP get_HorizontalViewSize(double* result) override;
+
+  STDMETHODIMP get_VerticallyScrollable(BOOL* result) override;
+
+  STDMETHODIMP get_VerticalScrollPercent(double* result) override;
+
+  // Vertical size of the viewable region as a percentage of the total content
+  // area.
+  STDMETHODIMP get_VerticalViewSize(double* result) override;
+
+  //
   // ISelectionItemProvider methods.
   //
 
@@ -985,6 +1013,12 @@
   // of |AXNode| ids.
   SAFEARRAY* CreateUIAElementsArrayFromIdVector(std::vector<int32_t>& ids);
 
+  // Returns the scroll offsets to which UI Automation should scroll an
+  // accessible object, given the horizontal and vertical scroll amounts.
+  gfx::Vector2d CalculateUIAScrollPoint(
+      const ScrollAmount horizontal_amount,
+      const ScrollAmount vertical_amount) const;
+
   void AddAlertTarget();
   void RemoveAlertTarget();
 
diff --git a/ui/aura/env.cc b/ui/aura/env.cc
index 376bb94..b8824e9 100644
--- a/ui/aura/env.cc
+++ b/ui/aura/env.cc
@@ -52,11 +52,6 @@
   for (EnvObserver& observer : observers_)
     observer.OnWillDestroyEnv();
 
-#if defined(USE_OZONE)
-  if (mode_ == Mode::LOCAL)
-    ui::OzonePlatform::Shutdown();
-#endif
-
   DCHECK_EQ(this, lazy_tls_ptr.Pointer()->Get());
   lazy_tls_ptr.Pointer()->Set(NULL);
 }
diff --git a/ui/aura/mus/window_tree_client_unittest.cc b/ui/aura/mus/window_tree_client_unittest.cc
index 131dfe1..010e8a5a 100644
--- a/ui/aura/mus/window_tree_client_unittest.cc
+++ b/ui/aura/mus/window_tree_client_unittest.cc
@@ -37,7 +37,6 @@
 #include "ui/aura/mus/window_tree_host_mus.h"
 #include "ui/aura/mus/window_tree_host_mus_init_params.h"
 #include "ui/aura/test/aura_mus_test_base.h"
-#include "ui/aura/test/aura_test_suite.h"
 #include "ui/aura/test/mus/test_window_tree.h"
 #include "ui/aura/test/mus/window_tree_client_private.h"
 #include "ui/aura/test/test_window_delegate.h"
@@ -55,8 +54,6 @@
 #include "ui/display/screen.h"
 #include "ui/events/event.h"
 #include "ui/events/event_utils.h"
-#include "ui/events/platform/platform_event_observer.h"
-#include "ui/events/platform/platform_event_source.h"
 #include "ui/events/test/test_event_handler.h"
 #include "ui/gfx/geometry/dip_util.h"
 #include "ui/gfx/geometry/rect.h"
@@ -2989,84 +2986,4 @@
   window_tree_client()->OnWindowFocused(server_id(embed_root->window()));
 }
 
-#if defined(USE_OZONE)
-
-class TestPlatformEventObserver : public ui::PlatformEventObserver {
- public:
-  TestPlatformEventObserver() = default;
-  ~TestPlatformEventObserver() override = default;
-
-  int will_process_count() const { return will_process_count_; }
-  int did_process_count() const { return did_process_count_; }
-  ui::EventType will_process_type() const { return will_process_type_; }
-  ui::EventType did_process_type() const { return did_process_type_; }
-
-  // PlatformEventObserver:
-  void WillProcessEvent(const ui::PlatformEvent& event) override {
-    will_process_count_++;
-    will_process_type_ = static_cast<const ui::Event*>(event)->type();
-  }
-  void DidProcessEvent(const ui::PlatformEvent& event) override {
-    did_process_count_++;
-    did_process_type_ = static_cast<const ui::Event*>(event)->type();
-  }
-
- private:
-  int will_process_count_ = 0;
-  int did_process_count_ = 0;
-  ui::EventType will_process_type_ = ui::ET_UNKNOWN;
-  ui::EventType did_process_type_ = ui::ET_UNKNOWN;
-
-  DISALLOW_COPY_AND_ASSIGN(TestPlatformEventObserver);
-};
-
-// Base class that installs a new version of Env configured for Mus in SetUp()
-// (and installs a new version of Env configured for Local during TearDown()).
-// This is necessary as when Env is created with a Model of Local it installs
-// a PlatformEventSource, not the one that WindowTreeClient installs.
-class WindowTreeClientWmOzoneTest : public test::AuraMusWmTestBase {
- public:
-  WindowTreeClientWmOzoneTest() = default;
-  ~WindowTreeClientWmOzoneTest() override = default;
-
-  // test::AuraMusWmTestBase:
-  void SetUp() override {
-    env_reinstaller_ = std::make_unique<test::EnvReinstaller>();
-    env_ = Env::CreateInstance(Env::Mode::MUS);
-    AuraMusWmTestBase::SetUp();
-  }
-
-  void TearDown() override {
-    AuraMusWmTestBase::TearDown();
-    env_.reset();
-    env_reinstaller_.reset();
-  }
-
- private:
-  std::unique_ptr<test::EnvReinstaller> env_reinstaller_;
-  std::unique_ptr<Env> env_;
-
-  DISALLOW_COPY_AND_ASSIGN(WindowTreeClientWmOzoneTest);
-};
-
-// Used to verify PlatformEventSource is correctly wired up in ozone.
-TEST_F(WindowTreeClientWmOzoneTest, PlatformEventSourceInstalled) {
-  ASSERT_TRUE(ui::PlatformEventSource::GetInstance());
-  TestPlatformEventObserver test_observer;
-  ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(
-      &test_observer);
-  ui::MouseEvent event(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(),
-                       ui::EventTimeForNow(), ui::EF_NONE, 0);
-  window_tree_client()->OnWindowInputEvent(1, server_id(root_window()), 0,
-                                           ui::Id(), gfx::PointF(),
-                                           ui::Event::Clone(event), 0);
-  ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(
-      &test_observer);
-  EXPECT_EQ(1, test_observer.will_process_count());
-  EXPECT_EQ(1, test_observer.did_process_count());
-  EXPECT_EQ(ui::ET_MOUSE_MOVED, test_observer.will_process_type());
-  EXPECT_EQ(ui::ET_MOUSE_MOVED, test_observer.did_process_type());
-}
-#endif
-
 }  // namespace aura
diff --git a/ui/compositor/recyclable_compositor_mac.cc b/ui/compositor/recyclable_compositor_mac.cc
index 187aebad..d0670c7 100644
--- a/ui/compositor/recyclable_compositor_mac.cc
+++ b/ui/compositor/recyclable_compositor_mac.cc
@@ -111,7 +111,11 @@
     std::unique_ptr<RecyclableCompositorMac> result;
     result = std::move(compositors_.back());
     compositors_.pop_back();
-    return result;
+    if (result->compositor()->context_factory() == context_factory &&
+        result->compositor()->context_factory_private() ==
+            context_factory_private) {
+      return result;
+    }
   }
   return std::make_unique<RecyclableCompositorMac>(context_factory,
                                                    context_factory_private);
@@ -119,6 +123,10 @@
 
 void RecyclableCompositorMacFactory::RecycleCompositor(
     std::unique_ptr<RecyclableCompositorMac> compositor) {
+  // Disable all recycling to see if it fixes https://crbug.com/863817
+  // TODO(ccameron): Remove this.
+  return;
+
   if (recycling_disabled_)
     return;
 
diff --git a/ui/display/manager/display_configurator.cc b/ui/display/manager/display_configurator.cc
index a780b56..6822b06 100644
--- a/ui/display/manager/display_configurator.cc
+++ b/ui/display/manager/display_configurator.cc
@@ -593,6 +593,10 @@
   UpdatePowerState(power_state);
 }
 
+void DisplayConfigurator::InitializeDisplayPowerState() {
+  SetInitialDisplayPower(chromeos::DISPLAY_POWER_ALL_ON);
+}
+
 void DisplayConfigurator::Init(
     std::unique_ptr<NativeDisplayDelegate> display_delegate,
     bool is_panel_fitting_enabled) {
diff --git a/ui/display/manager/display_configurator.h b/ui/display/manager/display_configurator.h
index e3cbbe0f..954b2fcc 100644
--- a/ui/display/manager/display_configurator.h
+++ b/ui/display/manager/display_configurator.h
@@ -216,6 +216,9 @@
   // e.g. via SetDisplayPower().
   void SetInitialDisplayPower(chromeos::DisplayPowerState power_state);
 
+  // Initialize the display power state to DISPLAY_POWER_ALL_ON
+  void InitializeDisplayPowerState();
+
   // Initialization, must be called right after constructor.
   // |is_panel_fitting_enabled| indicates hardware panel fitting support.
   void Init(std::unique_ptr<NativeDisplayDelegate> delegate,
@@ -307,6 +310,11 @@
     requested_power_state_ = base::nullopt;
   }
 
+  base::Optional<chromeos::DisplayPowerState>
+  GetRequestedPowerStateForTest() const {
+    return requested_power_state_;
+  }
+
  private:
   class DisplayLayoutManagerImpl;
 
diff --git a/ui/gl/init/create_gr_gl_interface.cc b/ui/gl/init/create_gr_gl_interface.cc
index 7bbf552..59f01ff 100644
--- a/ui/gl/init/create_gr_gl_interface.cc
+++ b/ui/gl/init/create_gr_gl_interface.cc
@@ -45,7 +45,7 @@
 
 }  // anonymous namespace
 
-sk_sp<GrGLInterface> CreateGrGLInterface(
+sk_sp<const GrGLInterface> CreateGrGLInterface(
     const gl::GLVersionInfo& version_info) {
   gl::ProcsGL* gl = &gl::g_current_gl_driver->fn;
   gl::GLApi* api = gl::g_current_gl_context;
@@ -488,7 +488,7 @@
 
   interface->fStandard = standard;
   interface->fExtensions.swap(&extensions);
-  sk_sp<GrGLInterface> returned(interface);
+  sk_sp<const GrGLInterface> returned(interface);
   return returned;
 }
 
diff --git a/ui/gl/init/create_gr_gl_interface.h b/ui/gl/init/create_gr_gl_interface.h
index 22cc5ac..c121262 100644
--- a/ui/gl/init/create_gr_gl_interface.h
+++ b/ui/gl/init/create_gr_gl_interface.h
@@ -18,7 +18,7 @@
 
 // Creates a GrGLInterface by taking function pointers from the current
 // GL bindings.
-GL_INIT_EXPORT sk_sp<GrGLInterface> CreateGrGLInterface(
+GL_INIT_EXPORT sk_sp<const GrGLInterface> CreateGrGLInterface(
     const gl::GLVersionInfo& version_info);
 
 }  // namespace init
diff --git a/ui/gl/init/gl_factory_ozone.cc b/ui/gl/init/gl_factory_ozone.cc
index 8b35da4..1dfbf40 100644
--- a/ui/gl/init/gl_factory_ozone.cc
+++ b/ui/gl/init/gl_factory_ozone.cc
@@ -50,7 +50,7 @@
       return stub_context;
     }
     default:
-      NOTREACHED();
+      NOTREACHED() << "Expected Mock or Stub, actual:" << GetGLImplementation();
   }
   return nullptr;
 }
@@ -66,7 +66,7 @@
     case kGLImplementationStubGL:
       return InitializeGLSurface(new GLSurfaceStub());
     default:
-      NOTREACHED();
+      NOTREACHED() << "Expected Mock or Stub, actual:" << GetGLImplementation();
   }
 
   return nullptr;
@@ -99,7 +99,7 @@
     case kGLImplementationStubGL:
       return InitializeGLSurface(new GLSurfaceStub);
     default:
-      NOTREACHED();
+      NOTREACHED() << "Expected Mock or Stub, actual:" << GetGLImplementation();
   }
 
   return nullptr;
@@ -116,7 +116,7 @@
     case kGLImplementationStubGL:
       break;
     default:
-      NOTREACHED();
+      NOTREACHED() << "Expected Mock or Stub, actual:" << GetGLImplementation();
   }
 }
 
@@ -129,7 +129,7 @@
     case kGLImplementationStubGL:
       return true;
     default:
-      NOTREACHED();
+      NOTREACHED() << "Expected Mock or Stub, actual:" << GetGLImplementation();
       return false;
   }
 }
diff --git a/ui/keyboard/keyboard_controller.cc b/ui/keyboard/keyboard_controller.cc
index 2213931..42b24e51 100644
--- a/ui/keyboard/keyboard_controller.cc
+++ b/ui/keyboard/keyboard_controller.cc
@@ -297,11 +297,6 @@
     animator->StopAnimating();
 
   GetKeyboardWindow()->SetBounds(new_bounds);
-
-  // We need to send out this notification only if keyboard is visible since
-  // the keyboard window is resized even if keyboard is hidden.
-  if (IsKeyboardVisible())
-    NotifyKeyboardBoundsChanging(new_bounds);
 }
 
 void KeyboardController::NotifyKeyboardWindowLoaded() {
@@ -519,10 +514,15 @@
     const gfx::Rect& old_bounds,
     const gfx::Rect& new_bounds,
     ui::PropertyChangeReason reason) {
-  if (!window->IsRootWindow() || !ui_->HasKeyboardWindow())
+  if (!GetKeyboardWindow())
     return;
 
-  container_behavior_->SetCanonicalBounds(GetKeyboardWindow(), new_bounds);
+  // |window| could be the root window (for detecting screen rotations) or the
+  // keyboard window (for detecting keyboard bounds changes).
+  if (window == GetRootWindow())
+    container_behavior_->SetCanonicalBounds(GetKeyboardWindow(), new_bounds);
+  else if (window == GetKeyboardWindow())
+    NotifyKeyboardBoundsChanging(new_bounds);
 }
 
 void KeyboardController::Reload() {
@@ -619,6 +619,7 @@
     DCHECK_EQ(state_, KeyboardControllerState::INITIAL);
     aura::Window* keyboard_window = ui_->GetKeyboardWindow();
     keyboard_window->AddPreTargetHandler(&event_filter_);
+    keyboard_window->AddObserver(this);
     parent_container_->AddChild(keyboard_window);
   }
 
diff --git a/ui/keyboard/keyboard_controller.h b/ui/keyboard/keyboard_controller.h
index 48dca73..275a3fae 100644
--- a/ui/keyboard/keyboard_controller.h
+++ b/ui/keyboard/keyboard_controller.h
@@ -235,9 +235,6 @@
   // For access to Observer methods for simulation.
   friend class KeyboardControllerTest;
 
-  // For access to SetContainerBounds.
-  friend class KeyboardLayoutManager;
-
   // For access to NotifyKeyboardConfigChanged
   friend bool keyboard::UpdateKeyboardConfig(
       const keyboard::KeyboardConfig& config);
diff --git a/ui/keyboard/keyboard_controller_unittest.cc b/ui/keyboard/keyboard_controller_unittest.cc
index d8c3eda..12854f0 100644
--- a/ui/keyboard/keyboard_controller_unittest.cc
+++ b/ui/keyboard/keyboard_controller_unittest.cc
@@ -720,11 +720,7 @@
   keyboard_window()->SetBounds(gfx::Rect());
 }
 
-// TODO(https://crbug.com/849995): This is testing KeyboardLayoutManager /
-// ContainerFullWidthBehavior. Put this test there.
 TEST_F(KeyboardControllerTest, DisplayChangeShouldNotifyBoundsChange) {
-  root_window()->SetLayoutManager(new KeyboardLayoutManager(&controller()));
-
   ui::DummyTextInputClient input_client(ui::TEXT_INPUT_TYPE_TEXT);
 
   SetFocus(&input_client);
diff --git a/ui/keyboard/keyboard_layout_manager.cc b/ui/keyboard/keyboard_layout_manager.cc
index f8a1b68..32d34a50 100644
--- a/ui/keyboard/keyboard_layout_manager.cc
+++ b/ui/keyboard/keyboard_layout_manager.cc
@@ -60,8 +60,6 @@
     return;
 
   SetChildBoundsDirect(contents_window, new_bounds);
-
-  controller_->SetKeyboardWindowBounds(new_bounds);
 }
 
 }  // namespace keyboard
diff --git a/ui/ozone/public/ozone_platform.cc b/ui/ozone/public/ozone_platform.cc
index 2d9d7f9..828076e 100644
--- a/ui/ozone/public/ozone_platform.cc
+++ b/ui/ozone/public/ozone_platform.cc
@@ -67,14 +67,6 @@
 }
 
 // static
-void OzonePlatform::Shutdown() {
-  base::AutoLock lock(GetOzoneInstanceLock());
-  auto* tmp = instance_;
-  instance_ = nullptr;
-  delete tmp;
-}
-
-// static
 OzonePlatform* OzonePlatform::GetInstance() {
   base::AutoLock lock(GetOzoneInstanceLock());
   DCHECK(instance_) << "OzonePlatform is not initialized";
diff --git a/ui/ozone/public/ozone_platform.h b/ui/ozone/public/ozone_platform.h
index b8d329f5..2189dc6 100644
--- a/ui/ozone/public/ozone_platform.h
+++ b/ui/ozone/public/ozone_platform.h
@@ -105,10 +105,6 @@
   // provided by |args| as with InitalizeForUI.
   static void InitializeForGPU(const InitParams& args);
 
-  // Deletes the instance. Does nothing if OzonePlatform has not yet been
-  // initialized.
-  static void Shutdown();
-
   static OzonePlatform* GetInstance();
 
   // Registers a callback to be run when the OzonePlatform is initialized. Note
diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h
index 6862cfb4..c92fd03 100644
--- a/ui/views/widget/widget.h
+++ b/ui/views/widget/widget.h
@@ -34,9 +34,6 @@
 #if defined(IsMinimized)
 #undef IsMinimized
 #endif
-#if defined(CreateWindow)
-#undef CreateWindow
-#endif
 #endif
 
 namespace base {