diff --git a/AUTHORS b/AUTHORS
index 134c126..f5e53ef4 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -704,6 +704,7 @@
 Radu Stavila <stavila@adobe.com>
 Radu Velea <radu.velea@intel.com>
 Rafael Antognolli <rafael.antognolli@intel.com>
+Rafael Cintron <rafael.cintron@microsoft.com>
 Raghavendra Ghatage <r.ghatage@samsung.com>
 Raghu Ram Nagaraj <r.nagaraj@samsung.com>
 Rahul Gupta <rahul.g@samsung.com>
@@ -983,7 +984,7 @@
 Rajesh Mahindra <rmahindra@uber.com>
 Yuan-Pin Yu <yjames@uber.com>
 Vinoth Chandar <vinoth@uber.com>
-Zheng Xu <zxu@kobo.com>

+Zheng Xu <zxu@kobo.com>
 
 ACCESS CO., LTD. <*@access-company.com>
 Akamai Inc. <*@akamai.com>
@@ -1031,4 +1032,4 @@
 Vewd Software AS <*@vewd.com>
 Vivaldi Technologies AS <*@vivaldi.com>
 Yandex LLC <*@yandex-team.ru>
-Make Positive Provar Limited <*@provartesting.com>

+Make Positive Provar Limited <*@provartesting.com>
diff --git a/BUILD.gn b/BUILD.gn
index 3bc64860..9343be9 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -143,8 +143,8 @@
       "//third_party/SPIRV-Tools/src:SPIRV-Tools",
       "//third_party/SPIRV-Tools/src/test/fuzzers",
       "//third_party/cacheinvalidation:cacheinvalidation_unittests",
-      "//third_party/dawn:dawn_end2end_tests",
-      "//third_party/dawn:dawn_unittests",
+      "//third_party/dawn:dawn_end2end_tests_temp_group",
+      "//third_party/dawn:dawn_unittests_temp_group",
       "//third_party/pdfium/samples:pdfium_test",
       "//third_party/webrtc/rtc_tools:frame_analyzer",
       "//tools/perf/clear_system_cache",
diff --git a/DEPS b/DEPS
index b02e1fdb..1f6fa64 100644
--- a/DEPS
+++ b/DEPS
@@ -115,7 +115,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '3bdc3f5f9c0bf62c1eb7932f67f9f4838782a36a',
+  'skia_revision': '5beabfe918625a5c5813b513178b11f36e99d9c4',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -127,7 +127,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'be607ad63609429030481a8653aafedfc512ce59',
+  'angle_revision': '611bbaabb28cf4231ad0a138cd7bc21fe559ea02',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -139,7 +139,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': 'f4f8cc56aacf075306bbb6ee0da845e4f3ae32e3',
+  'pdfium_revision': '05e255178ba218c9b435c0a494bc4cd092011079',
   # 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.
@@ -175,7 +175,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': '74c92bb2207675ea7702153dd1cf60fddefe8495',
+  'catapult_revision': '7814fa2650935d6ff95c1e16f71a493feaa6aa1f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -223,7 +223,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'spv_tools_revision': '248debf55ad6de4a80f6d4a128ef195b6ed05a30',
+  'spv_tools_revision': 'a719fc18a57d86b679004f86e79a3ae47954c4b1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -875,7 +875,7 @@
     Var('chromium_git') + '/external/libaddressinput.git' + '@' + 'd7ed8e2f3f35ce9a3aafdfdc48745ceab66e7229',
 
   'src/third_party/libaom/source/libaom':
-    Var('aomedia_git') + '/aom.git' + '@' +  '67223a304e098da309776bac253456f75f613fc2',
+    Var('aomedia_git') + '/aom.git' + '@' +  '98dae942edd3032c89b0e8bae9b4d50398931405',
 
   # Userspace interface to kernel DRM services.
   'src/third_party/libdrm/src': {
@@ -1019,7 +1019,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '1ec085624fc7fed26266b07466832a4127e0959b',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '4998533202d979b69cd8aaddbee2bc0b5e263e6e',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78',
@@ -1182,7 +1182,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '5b6cbd789b9b91b4e46dde883c9f2ecb31eddade',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '7025535b4bb45bac82e4ff6444571f1db83dc13d',
+    Var('webrtc_git') + '/src.git' + '@' + 'ad858d1231e7e8456bb99565c74c17137b7f1414',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1213,7 +1213,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@a030e16bdf09be455567136e66810da62340ed7f',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@a039a0255e189909821df4acc3c64ad1168b1f61',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnRendererUnresponsiveTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnRendererUnresponsiveTest.java
index 66f62a0c8..d8f482ac 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnRendererUnresponsiveTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientOnRendererUnresponsiveTest.java
@@ -1,4 +1,4 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// 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.
 
@@ -8,6 +8,7 @@
 
 import android.support.test.filters.LargeTest;
 import android.view.KeyEvent;
+import android.webkit.JavascriptInterface;
 
 import org.junit.Assert;
 import org.junit.Rule;
@@ -22,6 +23,7 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.content_public.common.ContentUrlConstants;
 
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -34,34 +36,47 @@
 
     private static final String TAG = "AwRendererUnresponsive";
 
+    private static class JSBlocker {
+        private CountDownLatch mLatch;
+        JSBlocker() {
+            mLatch = new CountDownLatch(1);
+        }
+
+        public void releaseBlock() {
+            mLatch.countDown();
+        }
+
+        @JavascriptInterface
+        public void block() throws Exception {
+            mLatch.await(AwActivityTestRule.WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+        }
+    }
+
     private static class RendererTransientlyUnresponsiveTestAwContentsClient
             extends TestAwContentsClient {
         private CallbackHelper mUnresponsiveCallbackHelper;
         private CallbackHelper mResponsiveCallbackHelper;
+        private JSBlocker mBlocker;
 
         public RendererTransientlyUnresponsiveTestAwContentsClient() {
             mUnresponsiveCallbackHelper = new CallbackHelper();
             mResponsiveCallbackHelper = new CallbackHelper();
+            mBlocker = new JSBlocker();
         }
 
         void transientlyBlockBlinkThread(final AwContents awContents) {
             ThreadUtils.runOnUiThread(() -> {
-                // clang-format off
-                awContents.evaluateJavaScript(
-                        "let t0 = performance.now();\n" +
-                        "while(performance.now() < t0 + 6000 /*ms*/) {}",
-                        null);
-                // clang-format on
+                awContents.addJavascriptInterface(mBlocker, "blocker");
+                awContents.evaluateJavaScript("blocker.block();", null);
             });
         }
 
         void awaitRecovery() throws Exception {
-            // unresponsive signal should occur after 5 seconds, so wait for 6.
-            mUnresponsiveCallbackHelper.waitForCallback(0, 1, 6, TimeUnit.SECONDS);
+            mUnresponsiveCallbackHelper.waitForCallback(
+                    0, 1, AwActivityTestRule.WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
             Assert.assertEquals(1, mUnresponsiveCallbackHelper.getCallCount());
-            // blink main thread is transiently blocked for 6 seconds; wait
-            // an additional 5 seconds.
-            mResponsiveCallbackHelper.waitForCallback(0, 1, 5, TimeUnit.SECONDS);
+            mResponsiveCallbackHelper.waitForCallback(
+                    0, 1, AwActivityTestRule.WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
             Assert.assertEquals(1, mResponsiveCallbackHelper.getCallCount());
         }
 
@@ -75,6 +90,7 @@
             // onRendererResponsive should not have been called yet.
             Assert.assertEquals(0, mResponsiveCallbackHelper.getCallCount());
             mUnresponsiveCallbackHelper.notifyCalled();
+            mBlocker.releaseBlock();
         }
     }
 
@@ -85,25 +101,29 @@
 
         private CallbackHelper mUnresponsiveCallbackHelper;
         private CallbackHelper mTerminatedCallbackHelper;
+        private JSBlocker mBlocker;
 
         public RendererUnresponsiveTestAwContentsClient() {
             mUnresponsiveCallbackHelper = new CallbackHelper();
             mTerminatedCallbackHelper = new CallbackHelper();
+            mBlocker = new JSBlocker();
         }
 
         void permanentlyBlockBlinkThread(final AwContents awContents) {
-            ThreadUtils.runOnUiThread(() -> { awContents.evaluateJavaScript("while(1);", null); });
+            ThreadUtils.runOnUiThread(() -> {
+                awContents.addJavascriptInterface(mBlocker, "blocker");
+                awContents.evaluateJavaScript("blocker.block();", null);
+            });
         }
 
         void awaitRendererTermination() throws Exception {
-            // The input ack timeout is 5 seconds, and the unresponsive callback should retrigger at
-            // that interval, so wait for the expected multiple of 5 seconds, plus one second
-            // leeway.
-            mUnresponsiveCallbackHelper.waitForCallback(
-                    0, 2, 5 * UNRESPONSIVE_CALLBACK_COUNT + 1, TimeUnit.SECONDS);
-            Assert.assertEquals(2, mUnresponsiveCallbackHelper.getCallCount());
+            mUnresponsiveCallbackHelper.waitForCallback(0, UNRESPONSIVE_CALLBACK_COUNT,
+                    AwActivityTestRule.WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+            Assert.assertEquals(
+                    UNRESPONSIVE_CALLBACK_COUNT, mUnresponsiveCallbackHelper.getCallCount());
 
-            mTerminatedCallbackHelper.waitForCallback(0, 1, 5, TimeUnit.SECONDS);
+            mTerminatedCallbackHelper.waitForCallback(
+                    0, 1, AwActivityTestRule.WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
             Assert.assertEquals(1, mTerminatedCallbackHelper.getCallCount());
         }
 
@@ -127,6 +147,9 @@
             awContents.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
         });
     }
+
+    // This test requires the ability to terminate the renderer in order to recover from a
+    // permanently stuck blink main thread, so it can only run in multiprocess.
     @Test
     @Feature({"AndroidWebView"})
     @LargeTest
diff --git a/ash/app_list/app_list_presenter_delegate_unittest.cc b/ash/app_list/app_list_presenter_delegate_unittest.cc
index 58b040b..47a7a4a9 100644
--- a/ash/app_list/app_list_presenter_delegate_unittest.cc
+++ b/ash/app_list/app_list_presenter_delegate_unittest.cc
@@ -1312,15 +1312,34 @@
 }
 
 // Tests that the mouse-scroll cannot dismiss the app list.
-TEST_F(AppListPresenterDelegateHomeLauncherTest, MouseScrollToDismiss) {
+TEST_F(AppListPresenterDelegateHomeLauncherTest,
+       MouseScrollDoesntDismissPeekingLauncher) {
   // Show app list in non-tablet mode. Mouse-scroll up.
   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
+  GetAppListTestHelper()->CheckState(app_list::AppListViewState::PEEKING);
   GetAppListTestHelper()->CheckVisibility(true);
   ui::test::EventGenerator* generator = GetEventGenerator();
   generator->MoveMouseTo(GetPointOutsideSearchbox());
+
+  // Scroll up to get fullscreen.
   generator->MoveMouseWheel(0, 1);
   GetAppListTestHelper()->WaitUntilIdle();
-  GetAppListTestHelper()->CheckVisibility(false);
+  GetAppListTestHelper()->CheckState(
+      app_list::AppListViewState::FULLSCREEN_ALL_APPS);
+  GetAppListTestHelper()->CheckVisibility(true);
+
+  // Reset and show app list in non-tablet mode. Mouse-scroll down.
+  GetAppListTestHelper()->DismissAndRunLoop();
+  GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
+  GetAppListTestHelper()->CheckState(app_list::AppListViewState::PEEKING);
+  GetAppListTestHelper()->CheckVisibility(true);
+
+  // Scroll down to get fullscreen.
+  generator->MoveMouseWheel(0, -1);
+  GetAppListTestHelper()->WaitUntilIdle();
+  GetAppListTestHelper()->CheckState(
+      app_list::AppListViewState::FULLSCREEN_ALL_APPS);
+  GetAppListTestHelper()->CheckVisibility(true);
 
   // Show app list in tablet mode. Mouse-scroll up.
   EnableTabletMode(true);
@@ -1331,6 +1350,30 @@
   GetAppListTestHelper()->CheckVisibility(true);
 }
 
+// Tests that mouse-scroll up at fullscreen will dismiss app list.
+TEST_F(AppListPresenterDelegateHomeLauncherTest,
+       MouseScrollToDismissFromFullscreen) {
+  // Show app list in non-tablet mode. Mouse-scroll down.
+  GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
+  GetAppListTestHelper()->CheckState(app_list::AppListViewState::PEEKING);
+  ui::test::EventGenerator* generator = GetEventGenerator();
+  generator->MoveMouseTo(GetPointOutsideSearchbox());
+
+  // Scroll up with mouse wheel to fullscreen.
+  generator->MoveMouseWheel(0, 1);
+  GetAppListTestHelper()->WaitUntilIdle();
+  GetAppListTestHelper()->CheckState(
+      app_list::AppListViewState::FULLSCREEN_ALL_APPS);
+  GetAppListTestHelper()->CheckVisibility(true);
+  generator->MoveMouseTo(GetPointOutsideSearchbox());
+
+  // Scroll up with mouse wheel to close app list.
+  generator->MoveMouseWheel(0, 1);
+  GetAppListTestHelper()->WaitUntilIdle();
+  GetAppListTestHelper()->CheckState(app_list::AppListViewState::CLOSED);
+  GetAppListTestHelper()->CheckVisibility(false);
+}
+
 // Tests the app list opacity in overview mode.
 TEST_F(AppListPresenterDelegateHomeLauncherTest, OpacityInOverviewMode) {
   // Show app list in tablet mode.
diff --git a/ash/app_list/views/app_list_view.cc b/ash/app_list/views/app_list_view.cc
index 6dd54391..ef3243b 100644
--- a/ash/app_list/views/app_list_view.cc
+++ b/ash/app_list/views/app_list_view.cc
@@ -1151,21 +1151,25 @@
       return true;
   }
 
+  // The AppList should not be dismissed with scroll in tablet mode.
+  if (is_tablet_mode())
+    return true;
+
   // If the event is a mousewheel event, the offset is always large enough,
   // otherwise the offset must be larger than the scroll threshold.
   if (type == ui::ET_MOUSEWHEEL ||
       abs(offset.y()) > kAppListMinScrollToSwitchStates) {
-    if (offset.y() > 0 && !is_tablet_mode()) {
-      Dismiss();
-    } else {
-      if (app_list_state_ == AppListViewState::FULLSCREEN_ALL_APPS)
-        return true;
-      SetState(AppListViewState::FULLSCREEN_ALL_APPS);
-      const AppListPeekingToFullscreenSource source =
-          type == ui::ET_MOUSEWHEEL ? kMousewheelScroll : kMousepadScroll;
-      UMA_HISTOGRAM_ENUMERATION(kAppListPeekingToFullscreenHistogram, source,
-                                kMaxPeekingToFullscreen);
+    if (app_list_state_ == AppListViewState::FULLSCREEN_ALL_APPS) {
+      if (offset.y() > 0)
+        Dismiss();
+      return true;
     }
+
+    SetState(AppListViewState::FULLSCREEN_ALL_APPS);
+    const AppListPeekingToFullscreenSource source =
+        type == ui::ET_MOUSEWHEEL ? kMousewheelScroll : kMousepadScroll;
+    UMA_HISTOGRAM_ENUMERATION(kAppListPeekingToFullscreenHistogram, source,
+                              kMaxPeekingToFullscreen);
   }
   return true;
 }
diff --git a/ash/app_list/views/app_list_view_unittest.cc b/ash/app_list/views/app_list_view_unittest.cc
index b914d294a..b7baf50 100644
--- a/ash/app_list/views/app_list_view_unittest.cc
+++ b/ash/app_list/views/app_list_view_unittest.cc
@@ -139,7 +139,14 @@
   // and returns false on failure.
   bool SetAppListState(ash::AppListState state) {
     ContentsView* contents_view = view_->app_list_main_view()->contents_view();
-    contents_view->SetActiveState(state);
+
+    // The default method of changing the state to |kStateSearchResults| is via
+    // |ShowSearchResults|
+    if (state == ash::AppListState::kStateSearchResults)
+      contents_view->ShowSearchResults(true);
+    else
+      contents_view->SetActiveState(state);
+
     contents_view->Layout();
     return IsStateShown(state);
   }
@@ -1700,7 +1707,7 @@
   IsStateShown(ash::AppListState::kStateStart);
 
   // Change pages. View should not have moved without Layout().
-  contents_view->SetActiveState(ash::AppListState::kStateSearchResults);
+  contents_view->ShowSearchResults(true);
   IsStateShown(ash::AppListState::kStateStart);
 
   // Change to a third page. This queues up the second animation behind the
diff --git a/ash/app_list/views/contents_view.cc b/ash/app_list/views/contents_view.cc
index e3e8dcd..a4f2f4c 100644
--- a/ash/app_list/views/contents_view.cc
+++ b/ash/app_list/views/contents_view.cc
@@ -143,6 +143,10 @@
   if (IsStateActive(state))
     return;
 
+  // The primary way to set the state to search results should be via
+  // |ShowSearchResults|
+  DCHECK(state != ash::AppListState::kStateSearchResults);
+
   SetActiveStateInternal(GetPageIndexForState(state), false, animate);
 }
 
@@ -227,12 +231,11 @@
       GetPageIndexForState(ash::AppListState::kStateSearchResults);
   DCHECK_GE(search_page, 0);
 
-  // Search results page is hidden when it is behind the search box, so reshow
-  // it here.
-  if (show)
-    GetPageView(search_page)->SetVisible(true);
+  // Hide or Show results
+  GetPageView(search_page)->SetVisible(show);
 
-  SetActiveStateInternal(show ? search_page : page_before_search_, show, true);
+  SetActiveStateInternal(show ? search_page : page_before_search_, show,
+                         !AppListView::ShortAnimationsForTesting());
 }
 
 bool ContentsView::IsShowingSearchResults() const {
diff --git a/ash/display/display_configuration_controller_unittest.cc b/ash/display/display_configuration_controller_unittest.cc
index 84751b6d..6735f9e 100644
--- a/ash/display/display_configuration_controller_unittest.cc
+++ b/ash/display/display_configuration_controller_unittest.cc
@@ -28,12 +28,6 @@
   DisplayConfigurationControllerSmoothRotationTest() = default;
   ~DisplayConfigurationControllerSmoothRotationTest() override = default;
 
-  void SetUp() override {
-    base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-        switches::kAshDisableSmoothScreenRotation, "false");
-    AshTestBase::SetUp();
-  }
-
  private:
   DISALLOW_COPY_AND_ASSIGN(DisplayConfigurationControllerSmoothRotationTest);
 };
@@ -68,12 +62,11 @@
   display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
   DisplayConfigurationController* controller =
       Shell::Get()->display_configuration_controller();
-  // AshTestHelper disables display animations; re-enable them.
   DisplayConfigurationControllerTestApi(controller).SetDisplayAnimator(true);
   controller->SetDisplayRotation(
       display.id(), display::Display::ROTATE_180,
       display::Display::RotationSource::USER,
-      DisplayConfigurationController::ANIMATION_ASYNC);
+      DisplayConfigurationController::ANIMATION_SYNC);
   EXPECT_EQ(display::Display::ROTATE_180,
             controller->GetTargetRotation(display.id()));
   EXPECT_EQ(display::Display::ROTATE_180, GetDisplayRotation(display.id()));
@@ -84,7 +77,6 @@
   display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
   DisplayConfigurationController* controller =
       Shell::Get()->display_configuration_controller();
-  // AshTestHelper disables display animations; re-enable them.
   DisplayConfigurationControllerTestApi(controller).SetDisplayAnimator(true);
   controller->SetDisplayRotation(
       display.id(), display::Display::ROTATE_180,
diff --git a/ash/host/ash_window_tree_host_platform.cc b/ash/host/ash_window_tree_host_platform.cc
index 903b733..d7a8a368 100644
--- a/ash/host/ash_window_tree_host_platform.cc
+++ b/ash/host/ash_window_tree_host_platform.cc
@@ -201,11 +201,12 @@
   SetSharedInputMethod(input_method_.get());
 }
 
-void AshWindowTreeHostPlatform::DispatchEventFromQueue(ui::Event* event) {
+ui::EventDispatchDetails AshWindowTreeHostPlatform::DispatchEventFromQueue(
+    ui::Event* event) {
   TRACE_EVENT0("input", "AshWindowTreeHostPlatform::DispatchEvent");
   if (event->IsLocatedEvent())
     TranslateLocatedEvent(static_cast<ui::LocatedEvent*>(event));
-  SendEventToSink(event);
+  return SendEventToSink(event);
 }
 
 void AshWindowTreeHostPlatform::SetTapToClickPaused(bool state) {
diff --git a/ash/host/ash_window_tree_host_platform.h b/ash/host/ash_window_tree_host_platform.h
index b65f23d6..32267ac1 100644
--- a/ash/host/ash_window_tree_host_platform.h
+++ b/ash/host/ash_window_tree_host_platform.h
@@ -82,7 +82,7 @@
                         ui::mojom::TextInputStatePtr state) override;
 
   // ws::HostEventDispatcher:
-  void DispatchEventFromQueue(ui::Event* event) override;
+  ui::EventDispatchDetails DispatchEventFromQueue(ui::Event* event) override;
 
  private:
   // All constructors call into this.
diff --git a/ash/public/cpp/ash_switches.cc b/ash/public/cpp/ash_switches.cc
index b83352173..ff6bf24d 100644
--- a/ash/public/cpp/ash_switches.cc
+++ b/ash/public/cpp/ash_switches.cc
@@ -21,10 +21,6 @@
 // Disables the dimming and blur of the wallpaper on login and lock screens.
 const char kAshDisableLoginDimAndBlur[] = "ash-disable-login-dim-and-blur";
 
-// Disables a smoother animation for screen rotation.
-const char kAshDisableSmoothScreenRotation[] =
-    "ash-disable-smooth-screen-rotation";
-
 // Disables the split view on tablet mode.
 const char kAshDisableTabletSplitView[] = "disable-tablet-splitview";
 
diff --git a/ash/public/cpp/ash_switches.h b/ash/public/cpp/ash_switches.h
index 6dbf942a..01e8cf6 100644
--- a/ash/public/cpp/ash_switches.h
+++ b/ash/public/cpp/ash_switches.h
@@ -20,7 +20,6 @@
 ASH_PUBLIC_EXPORT extern const char kAshDebugShortcuts[];
 ASH_PUBLIC_EXPORT extern const char kAshDeveloperShortcuts[];
 ASH_PUBLIC_EXPORT extern const char kAshDisableLoginDimAndBlur[];
-ASH_PUBLIC_EXPORT extern const char kAshDisableSmoothScreenRotation[];
 ASH_PUBLIC_EXPORT extern const char kAshDisableTabletSplitView[];
 ASH_PUBLIC_EXPORT extern const char kAshDisableTouchExplorationMode[];
 ASH_PUBLIC_EXPORT extern const char kAshEnableCursorMotionBlur[];
diff --git a/ash/rotator/screen_rotation_animator.cc b/ash/rotator/screen_rotation_animator.cc
index 89e93e8..6859a2d 100644
--- a/ash/rotator/screen_rotation_animator.cc
+++ b/ash/rotator/screen_rotation_animator.cc
@@ -166,12 +166,6 @@
       metrics_reporter_(
           std::make_unique<ScreenRotationAnimationMetricsReporter>()),
       disable_animation_timers_for_test_(false),
-      // TODO(wutao): remove the flag. http://crbug.com/707800.
-      has_switch_ash_disable_smooth_screen_rotation_(
-          base::CommandLine::ForCurrentProcess()->HasSwitch(
-              switches::kAshDisableSmoothScreenRotation) &&
-          base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-              switches::kAshDisableSmoothScreenRotation) != "false"),
       weak_factory_(this) {}
 
 ScreenRotationAnimator::~ScreenRotationAnimator() {
@@ -198,9 +192,8 @@
   }
 
   rotation_request->old_rotation = current_rotation;
-  if (has_switch_ash_disable_smooth_screen_rotation_ ||
-      DisplayConfigurationController::ANIMATION_SYNC ==
-          rotation_request->mode) {
+  if (DisplayConfigurationController::ANIMATION_SYNC ==
+      rotation_request->mode) {
     StartSlowAnimation(std::move(rotation_request));
   } else {
     current_async_rotation_request_ = ScreenRotationRequest(*rotation_request);
@@ -372,8 +365,7 @@
   ui::Layer* screen_rotation_container_layer =
       GetScreenRotationContainer(root_window_)->layer();
   ui::Layer* new_root_layer;
-  if (!new_layer_tree_owner_ ||
-      has_switch_ash_disable_smooth_screen_rotation_) {
+  if (!new_layer_tree_owner_) {
     new_root_layer = screen_rotation_container_layer;
   } else {
     new_root_layer = new_layer_tree_owner_->root();
diff --git a/ash/rotator/screen_rotation_animator.h b/ash/rotator/screen_rotation_animator.h
index 987f494..d17e454 100644
--- a/ash/rotator/screen_rotation_animator.h
+++ b/ash/rotator/screen_rotation_animator.h
@@ -188,7 +188,6 @@
   std::unique_ptr<ui::LayerTreeOwner> mask_layer_tree_owner_;
   std::unique_ptr<ScreenRotationRequest> last_pending_request_;
   base::Optional<ScreenRotationRequest> current_async_rotation_request_;
-  bool has_switch_ash_disable_smooth_screen_rotation_;
   display::Display::Rotation target_rotation_ = display::Display::ROTATE_0;
   base::WeakPtrFactory<ScreenRotationAnimator> weak_factory_;
 
diff --git a/ash/session/session_controller.cc b/ash/session/session_controller.cc
index d089dfb..e30b7b7 100644
--- a/ash/session/session_controller.cc
+++ b/ash/session/session_controller.cc
@@ -37,6 +37,8 @@
 #include "services/preferences/public/mojom/preferences.mojom.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "ui/message_center/message_center.h"
+#include "ui/wm/core/focus_controller.h"
+#include "ui/wm/core/focus_rules.h"
 
 using session_manager::SessionState;
 
@@ -524,6 +526,7 @@
   if (state_ == state)
     return;
 
+  const bool was_user_session_blocked = IsUserSessionBlocked();
   const bool was_locked = state_ == SessionState::LOCKED;
   state_ = state;
   for (auto& observer : observers_)
@@ -547,6 +550,9 @@
     ConnectToSigninScreenPrefService();
     signin_screen_prefs_requested_ = true;
   }
+
+  if (was_user_session_blocked && !IsUserSessionBlocked())
+    EnsureActiveWindowAfterUnblockingUserSession();
 }
 
 void SessionController::AddUserSession(mojom::UserSessionPtr user_session) {
@@ -730,4 +736,20 @@
     observer.OnActiveUserPrefServiceChanged(last_active_user_prefs_);
 }
 
+void SessionController::EnsureActiveWindowAfterUnblockingUserSession() {
+  if (!Shell::HasInstance())
+    return;
+
+  ::wm::FocusController* focus_controller = Shell::Get()->focus_controller();
+  if (focus_controller->GetActiveWindow() ||
+      !Shell::GetRootWindowForNewWindows()) {
+    return;
+  }
+  aura::Window* to_activate =
+      Shell::Get()->focus_rules()->GetNextActivatableWindow(
+          Shell::GetRootWindowForNewWindows());
+  if (to_activate)
+    focus_controller->ActivateWindow(to_activate);
+}
+
 }  // namespace ash
diff --git a/ash/session/session_controller.h b/ash/session/session_controller.h
index 9603e48..a71d9979 100644
--- a/ash/session/session_controller.h
+++ b/ash/session/session_controller.h
@@ -249,6 +249,10 @@
   // notification until that happens.
   void MaybeNotifyOnActiveUserPrefServiceChanged();
 
+  // Called when IsUserSessionBlocked() becomes true. If there isn't an active
+  // window, tries to activate one.
+  void EnsureActiveWindowAfterUnblockingUserSession();
+
   // Bindings for users of the mojom::SessionController interface.
   mojo::BindingSet<mojom::SessionController> bindings_;
 
diff --git a/ash/session/session_controller_unittest.cc b/ash/session/session_controller_unittest.cc
index 489632c..bfbd777 100644
--- a/ash/session/session_controller_unittest.cc
+++ b/ash/session/session_controller_unittest.cc
@@ -812,5 +812,20 @@
   EXPECT_EQ(1, switch_callback_hit_count());
 }
 
+using SessionControllerUnblockTest = NoSessionAshTestBase;
+
+TEST_F(SessionControllerUnblockTest, ActiveWindowAfterUnblocking) {
+  EXPECT_TRUE(Shell::Get()->session_controller()->IsUserSessionBlocked());
+  auto widget = CreateTestWidget();
+  // |widget| should not be active as it is blocked by SessionController.
+  EXPECT_FALSE(widget->IsActive());
+  SimulateUserLogin("user@test.com");
+  EXPECT_FALSE(Shell::Get()->session_controller()->IsUserSessionBlocked());
+
+  // |widget| should now be active as SessionController no longer is blocking
+  // windows from becoming active.
+  EXPECT_TRUE(widget->IsActive());
+}
+
 }  // namespace
 }  // namespace ash
diff --git a/ash/shell.cc b/ash/shell.cc
index 9c2a4e2..bb76409 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -905,6 +905,7 @@
 
   // Depends on |focus_controller_|, so must be destroyed before.
   window_tree_host_manager_.reset();
+  focus_rules_ = nullptr;
   focus_controller_.reset();
   screen_position_controller_.reset();
 
@@ -1063,8 +1064,8 @@
   AddPreTargetHandler(env_filter_.get());
 
   // FocusController takes ownership of AshFocusRules.
-  focus_controller_ =
-      std::make_unique<::wm::FocusController>(new wm::AshFocusRules());
+  focus_rules_ = new wm::AshFocusRules();
+  focus_controller_ = std::make_unique<::wm::FocusController>(focus_rules_);
   focus_controller_->AddObserver(this);
 
   window_selector_controller_ = std::make_unique<WindowSelectorController>();
diff --git a/ash/shell.h b/ash/shell.h
index 19221f0..3341f9cc 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -75,6 +75,7 @@
 class ActivationClient;
 class CompoundEventFilter;
 class FocusController;
+class FocusRules;
 class ShadowController;
 class VisibilityController;
 class WindowModalityController;
@@ -401,6 +402,7 @@
   }
   FirstRunHelper* first_run_helper() { return first_run_helper_.get(); }
   ::wm::FocusController* focus_controller() { return focus_controller_.get(); }
+  ::wm::FocusRules* focus_rules() { return focus_rules_; }
   FocusCycler* focus_cycler() { return focus_cycler_.get(); }
   HighlighterController* highlighter_controller() {
     return highlighter_controller_.get();
@@ -770,6 +772,8 @@
   std::unique_ptr<WallpaperController> wallpaper_controller_;
   std::unique_ptr<WindowCycleController> window_cycle_controller_;
   std::unique_ptr<WindowSelectorController> window_selector_controller_;
+  // Owned by |focus_controller_|.
+  ::wm::FocusRules* focus_rules_ = nullptr;
   std::unique_ptr<::wm::ShadowController> shadow_controller_;
   std::unique_ptr<::wm::VisibilityController> visibility_controller_;
   std::unique_ptr<::wm::WindowModalityController> window_modality_controller_;
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc
index 4570da4..213fc19 100644
--- a/ash/test/ash_test_helper.cc
+++ b/ash/test/ash_test_helper.cc
@@ -136,18 +136,6 @@
         ::switches::kHostWindowBounds, "1+1-800x600");
   }
 
-  // TODO(wutao): We enabled a smooth screen rotation animation, which is using
-  // an asynchronous method. However for some tests require to evaluate the
-  // screen rotation immediately after the operation of setting display
-  // rotation, we need to append a slow screen rotation animation flag to pass
-  // the tests. When we remove the flag "ash-disable-smooth-screen-rotation", we
-  // need to disable the screen rotation animation in the test.
-  if (!command_line_->GetProcessCommandLine()->HasSwitch(
-          switches::kAshDisableSmoothScreenRotation)) {
-    command_line_->GetProcessCommandLine()->AppendSwitch(
-        switches::kAshDisableSmoothScreenRotation);
-  }
-
   statistics_provider_ =
       std::make_unique<chromeos::system::ScopedFakeStatisticsProvider>();
 
diff --git a/base/android/java/src/org/chromium/base/task/AsyncTask.java b/base/android/java/src/org/chromium/base/task/AsyncTask.java
index 8bed613..4a5a6f2 100644
--- a/base/android/java/src/org/chromium/base/task/AsyncTask.java
+++ b/base/android/java/src/org/chromium/base/task/AsyncTask.java
@@ -279,6 +279,25 @@
         return r;
     }
 
+    @SuppressWarnings({"MissingCasesInEnumSwitch"})
+    private void executionPreamble() {
+        if (mStatus != Status.PENDING) {
+            switch (mStatus) {
+                case RUNNING:
+                    throw new IllegalStateException("Cannot execute task:"
+                            + " the task is already running.");
+                case FINISHED:
+                    throw new IllegalStateException("Cannot execute task:"
+                            + " the task has already been executed "
+                            + "(a task can be executed only once)");
+            }
+        }
+
+        mStatus = Status.RUNNING;
+
+        onPreExecute();
+    }
+
     /**
      * Executes the task with the specified parameters. The task returns
      * itself (this) so that the caller can keep a reference to it.
@@ -309,27 +328,23 @@
      * @throws IllegalStateException If {@link #getStatus()} returns either
      *         {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.
      */
-    @SuppressWarnings({"MissingCasesInEnumSwitch"})
     @MainThread
     public final AsyncTask<Result> executeOnExecutor(Executor exec) {
-        if (mStatus != Status.PENDING) {
-            switch (mStatus) {
-                case RUNNING:
-                    throw new IllegalStateException("Cannot execute task:"
-                            + " the task is already running.");
-                case FINISHED:
-                    throw new IllegalStateException("Cannot execute task:"
-                            + " the task has already been executed "
-                            + "(a task can be executed only once)");
-            }
-        }
-
-        mStatus = Status.RUNNING;
-
-        onPreExecute();
-
+        executionPreamble();
         exec.execute(mFuture);
+        return this;
+    }
 
+    /**
+     * Executes an AsyncTask on the given TaskRunner.
+     *
+     * @param taskRunner taskRunner to run this AsyncTask on.
+     * @return This instance of AsyncTask.
+     */
+    @MainThread
+    public final AsyncTask<Result> executeOnTaskRunner(TaskRunner taskRunner) {
+        executionPreamble();
+        taskRunner.postTask(mFuture);
         return this;
     }
 
diff --git a/base/fuchsia/test.fidl b/base/fuchsia/test.fidl
index b76b194..6e0f173 100644
--- a/base/fuchsia/test.fidl
+++ b/base/fuchsia/test.fidl
@@ -6,5 +6,5 @@
 
 [Discoverable]
 interface TestInterface {
-    1: Add(int32 a, int32 b) -> (int32 sum);
+  Add(int32 a, int32 b) -> (int32 sum);
 };
diff --git a/base/mac/mach_port_broker.mm b/base/mac/mach_port_broker.mm
index 21f5d18..2e0bcb7 100644
--- a/base/mac/mach_port_broker.mm
+++ b/base/mac/mach_port_broker.mm
@@ -39,14 +39,15 @@
 bool MachPortBroker::ChildSendTaskPortToParent(const std::string& name) {
   // Look up the named MachPortBroker port that's been registered with the
   // bootstrap server.
-  mach_port_t parent_port;
-  kern_return_t kr = bootstrap_look_up(bootstrap_port,
-      const_cast<char*>(GetMachPortName(name, true).c_str()), &parent_port);
+  mac::ScopedMachSendRight parent_port;
+  std::string bootstrap_name = GetMachPortName(name, true);
+  kern_return_t kr = bootstrap_look_up(
+      bootstrap_port, const_cast<char*>(bootstrap_name.c_str()),
+      mac::ScopedMachSendRight::Receiver(parent_port).get());
   if (kr != KERN_SUCCESS) {
-    BOOTSTRAP_LOG(ERROR, kr) << "bootstrap_look_up";
+    BOOTSTRAP_LOG(ERROR, kr) << "bootstrap_look_up " << bootstrap_name;
     return false;
   }
-  base::mac::ScopedMachSendRight scoped_right(parent_port);
 
   // Create the check in message. This will copy a send right on this process'
   // (the child's) task port and send it to the parent.
@@ -54,7 +55,7 @@
   msg.header.msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_COPY_SEND) |
                          MACH_MSGH_BITS_COMPLEX;
   msg.header.msgh_size = sizeof(msg);
-  msg.header.msgh_remote_port = parent_port;
+  msg.header.msgh_remote_port = parent_port.get();
   msg.header.msgh_id = kTaskPortMessageId;
   msg.body.msgh_descriptor_count = 1;
   msg.child_task_port.name = mach_task_self();
@@ -96,14 +97,14 @@
   DCHECK(server_port_.get() == MACH_PORT_NULL);
 
   // Check in with launchd and publish the service name.
-  mach_port_t port;
+  std::string bootstrap_name = GetMachPortName(name_, false);
   kern_return_t kr = bootstrap_check_in(
-      bootstrap_port, GetMachPortName(name_, false).c_str(), &port);
+      bootstrap_port, bootstrap_name.c_str(),
+      mac::ScopedMachReceiveRight::Receiver(server_port_).get());
   if (kr != KERN_SUCCESS) {
-    BOOTSTRAP_LOG(ERROR, kr) << "bootstrap_check_in";
+    BOOTSTRAP_LOG(ERROR, kr) << "bootstrap_check_in " << bootstrap_name;
     return false;
   }
-  server_port_.reset(port);
 
   // Start the dispatch source.
   std::string queue_name =
diff --git a/base/test/android/javatests/src/org/chromium/base/test/ScreenshotOnFailureStatement.java b/base/test/android/javatests/src/org/chromium/base/test/ScreenshotOnFailureStatement.java
index 397e8ab..f982e14 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/ScreenshotOnFailureStatement.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/ScreenshotOnFailureStatement.java
@@ -4,6 +4,10 @@
 
 package org.chromium.base.test;
 
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.Build;
+import android.os.SystemClock;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.uiautomator.UiDevice;
 
@@ -52,14 +56,6 @@
             return;
         }
 
-        UiDevice uiDevice = null;
-        try {
-            uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
-        } catch (RuntimeException ex) {
-            Log.d(TAG, "Failed to initialize UiDevice", ex);
-            return;
-        }
-
         File screenshotFile = new File(screenshotFilePath);
         File screenshotDir = screenshotFile.getParentFile();
         if (screenshotDir == null) {
@@ -77,7 +73,49 @@
                 return;
             }
         }
+
+        // The Vega standalone VR headset can't take screenshots normally (they just show a black
+        // screen with the VR overlay), so instead, use VrCore's RecorderService.
+        if (Build.DEVICE.equals("vega")) {
+            takeScreenshotVega(screenshotFile);
+            return;
+        }
+
+        UiDevice uiDevice = null;
+        try {
+            uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+        } catch (RuntimeException ex) {
+            Log.d(TAG, "Failed to initialize UiDevice", ex);
+            return;
+        }
+
         Log.d(TAG, String.format("Saving screenshot of test failure, %s", screenshotFile));
         uiDevice.takeScreenshot(screenshotFile);
     }
+
+    private void takeScreenshotVega(final File screenshotFile) {
+        Intent screenshotIntent = new Intent();
+        screenshotIntent.putExtra("command", "IMAGE");
+        screenshotIntent.putExtra("quality", 100);
+        screenshotIntent.putExtra("path", screenshotFile.toString());
+        screenshotIntent.setComponent(new ComponentName(
+                "com.google.vr.vrcore", "com.google.vr.vrcore.capture.record.RecorderService"));
+        Log.d(TAG, String.format("Saving VR screenshot of test failure, %s", screenshotFile));
+        InstrumentationRegistry.getContext().startService(screenshotIntent);
+        // The screenshot taking is asynchronous, so wait until it actually gets taken before
+        // returning, otherwise we can end up capturing the Daydream Home app instead of Chrome.
+        // We can't use CriteriaHelper for polling since this is in base, and CriteriaHelper isn't.
+        boolean screenshotSuccessful = false;
+        // Poll for a second max with 10 attempts.
+        for (int i = 0; i < 10; ++i) {
+            if (screenshotFile.exists()) {
+                screenshotSuccessful = true;
+                break;
+            }
+            SystemClock.sleep(100);
+        }
+        if (!screenshotSuccessful) {
+            Log.d(TAG, "Failed to save VR screenshot of test failure");
+        }
+    }
 }
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h
index 6a721057..d4f6c94 100644
--- a/base/threading/thread_restrictions.h
+++ b/base/threading/thread_restrictions.h
@@ -340,7 +340,6 @@
                            ScopedAllowBaseSyncPrimitivesWithBlockingDisallowed);
 
   // Allowed usage:
-  friend class ::BrowserProcessImpl;
   friend class SimpleThread;
   friend class android_webview::AwFormDatabaseService;
   friend class android_webview::CookieManager;
@@ -390,6 +389,7 @@
       ScopedAllowBaseSyncPrimitivesOutsideBlockingScopeResetsState);
 
   // Allowed usage:
+  friend class ::BrowserProcessImpl;  // http://crbug.com/125207
   friend class ::KeyStorageLinux;
   friend class Thread;
   friend class android::JavaHandlerThread;
diff --git a/build/android/pylib/constants/__init__.py b/build/android/pylib/constants/__init__.py
index cf6ca11..919f506 100644
--- a/build/android/pylib/constants/__init__.py
+++ b/build/android/pylib/constants/__init__.py
@@ -65,6 +65,11 @@
         'org.chromium.chromedriver_webview_shell.Main',
         None,
         None),
+    'android_webview_cts': chrome.PackageInfo(
+        'com.android.webview',
+        'com.android.cts.webkit.WebViewStartupCtsActivity',
+        'webview-command-line',
+        None),
 })
 
 
diff --git a/build/android/pylib/instrumentation/instrumentation_test_instance.py b/build/android/pylib/instrumentation/instrumentation_test_instance.py
index 315cfcb7..a9019707 100644
--- a/build/android/pylib/instrumentation/instrumentation_test_instance.py
+++ b/build/android/pylib/instrumentation/instrumentation_test_instance.py
@@ -485,6 +485,7 @@
     self._initializeTestFilterAttributes(args)
 
     self._flags = None
+    self._use_apk_under_test_flags_file = False
     self._initializeFlagAttributes(args)
 
     self._driver_apk = None
@@ -659,6 +660,7 @@
           if a not in requested_annotations)
 
   def _initializeFlagAttributes(self, args):
+    self._use_apk_under_test_flags_file = args.use_apk_under_test_flags_file
     self._flags = ['--enable-test-intents']
     if args.command_line_flags:
       self._flags.extend(args.command_line_flags)
@@ -814,6 +816,10 @@
     return self._total_external_shards
 
   @property
+  def use_apk_under_test_flags_file(self):
+    return self._use_apk_under_test_flags_file
+
+  @property
   def wait_for_java_debugger(self):
     return self._wait_for_java_debugger
 
diff --git a/build/android/pylib/instrumentation/instrumentation_test_instance_test.py b/build/android/pylib/instrumentation/instrumentation_test_instance_test.py
index 1d3b4d7..78446d1 100755
--- a/build/android/pylib/instrumentation/instrumentation_test_instance_test.py
+++ b/build/android/pylib/instrumentation/instrumentation_test_instance_test.py
@@ -46,13 +46,15 @@
         'command_line_flags',
         'device_flags_file',
         'strict_mode',
+        'use_apk_under_test_flags_file'
       ])
 
   def createFlagAttributesArgs(
       self, command_line_flags=None, device_flags_file=None,
-      strict_mode=None):
+      strict_mode=None, use_apk_under_test_flags_file=False):
     return self._FlagAttributesArgs(
-        command_line_flags, device_flags_file, strict_mode)
+        command_line_flags, device_flags_file, strict_mode,
+        use_apk_under_test_flags_file)
 
   def test_initializeFlagAttributes_commandLineFlags(self):
     o = self.createTestInstance()
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
index 8857b88a5..1d2efe95 100644
--- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py
+++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -235,6 +235,19 @@
           shared_preference_utils.ApplySharedPreferenceSetting(
               shared_pref, setting)
 
+      @trace_event.traced
+      def set_vega_permissions(dev):
+        # Normally, installation of VrCore automatically grants storage
+        # permissions. However, since VrCore is part of the system image on
+        # the Vega standalone headset, we don't install the APK as part of test
+        # setup. Instead, grant the permissions here so that it can take
+        # screenshots.
+        if dev.product_name == 'vega':
+          dev.GrantPermissions('com.google.vr.vrcore', [
+              'android.permission.WRITE_EXTERNAL_STORAGE',
+              'android.permission.READ_EXTERNAL_STORAGE'
+          ])
+
       @instrumentation_tracing.no_tracing
       def push_test_data(dev):
         device_root = posixpath.join(dev.GetExternalStoragePath(),
@@ -262,8 +275,10 @@
         valgrind_tools.SetChromeTimeoutScale(
             dev, self._test_instance.timeout_scale)
 
-      steps += [set_debug_app, edit_shared_prefs, push_test_data,
-                create_flag_changer]
+      steps += [
+          set_debug_app, edit_shared_prefs, push_test_data, create_flag_changer,
+          set_vega_permissions
+      ]
 
       def bind_crash_handler(step, dev):
         return lambda: crash_handler.RetryOnSystemCrash(step, dev)
@@ -343,8 +358,16 @@
 
   def _CreateFlagChangerIfNeeded(self, device):
     if str(device) not in self._flag_changers:
+      cmdline_file = 'test-cmdline-file'
+      if self._test_instance.use_apk_under_test_flags_file:
+        if self._test_instance.package_info:
+          cmdline_file = self._test_instance.package_info.cmdline_file
+        else:
+          logging.warning(
+              'No PackageInfo found, falling back to using flag file %s',
+              cmdline_file)
       self._flag_changers[str(device)] = flag_changer.FlagChanger(
-        device, "test-cmdline-file")
+          device, cmdline_file)
 
   #override
   def _CreateShards(self, tests):
@@ -708,7 +731,8 @@
             host_file = os.path.join(host_dir, 'list_tests.json')
             dev.PullFile(dev_test_list_json.name, host_file)
             with open(host_file, 'r') as host_file:
-                return json.load(host_file)
+              return json.load(host_file)
+
       return crash_handler.RetryOnSystemCrash(_run, d)
 
     raw_test_lists = self._env.parallel_devices.pMap(list_tests).pGet(None)
@@ -786,19 +810,19 @@
 
   def _SaveScreenshot(self, device, screenshot_device_file, test_name, results,
                       link_name):
-      screenshot_filename = '%s-%s.png' % (
-          test_name, time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime()))
-      if device.FileExists(screenshot_device_file.name):
-        with self._env.output_manager.ArchivedTempfile(
-            screenshot_filename, 'screenshot',
-            output_manager.Datatype.PNG) as screenshot_host_file:
-          try:
-            device.PullFile(screenshot_device_file.name,
-                            screenshot_host_file.name)
-          finally:
-            screenshot_device_file.close()
-        for result in results:
-          result.SetLink(link_name, screenshot_host_file.Link())
+    screenshot_filename = '%s-%s.png' % (
+        test_name, time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime()))
+    if device.FileExists(screenshot_device_file.name):
+      with self._env.output_manager.ArchivedTempfile(
+          screenshot_filename, 'screenshot',
+          output_manager.Datatype.PNG) as screenshot_host_file:
+        try:
+          device.PullFile(screenshot_device_file.name,
+                          screenshot_host_file.name)
+        finally:
+          screenshot_device_file.close()
+      for result in results:
+        result.SetLink(link_name, screenshot_host_file.Link())
 
   def _ProcessRenderTestResults(
       self, device, render_tests_device_output_dir, results):
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index 6b55115..f1a1046d8 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -106,6 +106,11 @@
       type=os.path.realpath,
       help='The relative filepath to a file containing '
            'command-line flags to set on the device')
+  parser.add_argument(
+      '--use-apk-under-test-flags-file',
+      action='store_true',
+      help='Wether to use the flags file for the apk under test. If set, '
+           "the filename will be looked up in the APK's PackageInfo.")
   parser.set_defaults(allow_unknown=True)
   parser.set_defaults(command_line_flags=None)
 
diff --git a/build/fuchsia/fidlgen_js/test/simple.fidl b/build/fuchsia/fidlgen_js/test/simple.fidl
index 376f03a..1d1c6be 100644
--- a/build/fuchsia/fidlgen_js/test/simple.fidl
+++ b/build/fuchsia/fidlgen_js/test/simple.fidl
@@ -101,42 +101,42 @@
 };
 
 interface AnotherInterface {
-  1: TimesTwo(int32 a) -> (int32 b);
+  TimesTwo(int32 a) -> (int32 b);
 };
 
 interface Testola {
-  1: DoSomething();
+  DoSomething();
 
-  2: PrintInt(int32 num);
+  PrintInt(int32 num);
 
-  3: PrintMsg(string msg);
+  PrintMsg(string msg);
 
-  4: VariousArgs(Blorp blorp, string:32 msg, vector<uint32> stuff);
+  VariousArgs(Blorp blorp, string:32 msg, vector<uint32> stuff);
 
-  5: WithResponse(int32 a, int32 b) -> (int32 sum);
+  WithResponse(int32 a, int32 b) -> (int32 sum);
 
-  6: SendAStruct(BasicStruct basic);
+  SendAStruct(BasicStruct basic);
 
-  7: NestedStructsWithResponse(BasicStruct basic) -> (StuffAndThings resp);
+  NestedStructsWithResponse(BasicStruct basic) -> (StuffAndThings resp);
 
-  8: PassHandles(handle<job> job) -> (handle<debuglog> debuglog);
+  PassHandles(handle<job> job) -> (handle<debuglog> debuglog);
 
-  9: ReceiveUnions(StructOfMultipleUnions somu);
+  ReceiveUnions(StructOfMultipleUnions somu);
 
-  10: SendUnions() -> (StructOfMultipleUnions somu);
+  SendUnions() -> (StructOfMultipleUnions somu);
 
-  11: SendVectorsOfString(vector<string> unsized,
-                          vector<string?> nullable,
-                          vector<string:10> max_strlen);
+  SendVectorsOfString(vector<string> unsized,
+                      vector<string?> nullable,
+                      vector<string:10> max_strlen);
 
-  12: VectorOfStruct(vector<StructWithUint> stuff)
-        -> (vector<StructWithUint> result);
+  VectorOfStruct(vector<StructWithUint> stuff)
+    -> (vector<StructWithUint> result);
 
-  13: PassVectorOfPrimitives(VectorsOfPrimitives input)
-        -> (VectorsOfPrimitives output);
+  PassVectorOfPrimitives(VectorsOfPrimitives input)
+    -> (VectorsOfPrimitives output);
 
-  14: PassVectorOfVMO(VectorOfHandleToVMO input)
-        -> (VectorOfHandleToVMO output);
+  PassVectorOfVMO(VectorOfHandleToVMO input)
+    -> (VectorOfHandleToVMO output);
 
-  15: GetAnother(request<AnotherInterface> another);
+  GetAnother(request<AnotherInterface> another);
 };
diff --git a/cc/test/stub_layer_tree_host_single_thread_client.h b/cc/test/stub_layer_tree_host_single_thread_client.h
index 762b6ce..365292f 100644
--- a/cc/test/stub_layer_tree_host_single_thread_client.h
+++ b/cc/test/stub_layer_tree_host_single_thread_client.h
@@ -16,7 +16,6 @@
 
   // LayerTreeHostSingleThreadClient implementation.
   void RequestScheduleComposite() override {}
-  void RequestScheduleAnimation() override {}
   void DidSubmitCompositorFrame() override {}
   void DidLoseLayerTreeFrameSink() override {}
 };
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 75bc620..accc22e 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -564,7 +564,7 @@
   swap_promise_manager_.NotifySwapPromiseMonitorsOfSetNeedsCommit();
 }
 
-bool LayerTreeHost::RequestedMainFramePending() {
+bool LayerTreeHost::RequestedMainFramePendingForTesting() {
   return proxy_->RequestedAnimatePending();
 }
 
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index eb2f07e5..97ab043 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -211,7 +211,7 @@
 
   // Returns true after SetNeedsAnimate(), SetNeedsUpdateLayers() or
   // SetNeedsCommit(), until it is satisfied.
-  bool RequestedMainFramePending();
+  bool RequestedMainFramePendingForTesting();
 
   // Requests that the next frame re-chooses crisp raster scales for all layers.
   void SetNeedsRecalculateRasterScales();
@@ -337,6 +337,7 @@
   // viewport layers.
   struct ViewportPropertyIds {
     int page_scale_transform = TransformTree::kInvalidNodeId;
+    int inner_scroll = ScrollTree::kInvalidNodeId;
     // TODO(crbug.com/909750): Switch other usages of viewport layers to
     // property ids for CompositeAfterPaint.
   };
diff --git a/cc/trees/layer_tree_host_single_thread_client.h b/cc/trees/layer_tree_host_single_thread_client.h
index a648ed5..f2ce8e1 100644
--- a/cc/trees/layer_tree_host_single_thread_client.h
+++ b/cc/trees/layer_tree_host_single_thread_client.h
@@ -11,11 +11,9 @@
 
 class LayerTreeHostSingleThreadClient {
  public:
-  // Request that the client schedule a composite.
+  // Request that the client schedule a composite. For tests using single thread
+  // without a scheduler.
   virtual void RequestScheduleComposite() {}
-  // Request that the client schedule a composite now, and calculate appropriate
-  // delay for potential future frame.
-  virtual void RequestScheduleAnimation() {}
 
   // Called whenever the begin frame interval changes. This interval can be used
   // for animations.
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index f23b40f..cf11b6b 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -230,7 +230,7 @@
 
   void NextStep() {
     // The MainFrame request is cleared once a MainFrame happens.
-    EXPECT_FALSE(layer_tree_host()->RequestedMainFramePending());
+    EXPECT_FALSE(layer_tree_host()->RequestedMainFramePendingForTesting());
     switch (layer_tree_host()->SourceFrameNumber()) {
       case 0:
         ADD_FAILURE()
@@ -250,7 +250,7 @@
         return;
     }
     // SetNeeds{Animate,UpdateLayers,Commit}() will mean a MainFrame is pending.
-    EXPECT_TRUE(layer_tree_host()->RequestedMainFramePending());
+    EXPECT_TRUE(layer_tree_host()->RequestedMainFramePendingForTesting());
   }
 
   void AfterTest() override {}
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index c6c6aa9..9a69462 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -472,6 +472,7 @@
   // The page scale factor update can affect scrolling which requires that
   // these ids are set, so this must be before PushPageScaleFactorAndLimits.
   target_tree->SetViewportLayersFromIds(viewport_layer_ids_);
+  target_tree->set_viewport_property_ids(viewport_property_ids_);
 
   // Active tree already shares the page_scale_factor object with pending
   // tree so only the limits need to be provided.
@@ -1181,9 +1182,13 @@
 
 const ScrollNode* LayerTreeImpl::InnerViewportScrollNode() const {
   auto* inner_scroll = InnerViewportScrollLayer();
-  if (!inner_scroll)
-    return nullptr;
-
+  if (!inner_scroll) {
+    // TODO(crbug.com/909750): Check all other callers of
+    // InnerViewportScrollLayer() and switch to
+    // viewport_property_ids_.inner_scroll if needed.
+    return property_trees()->scroll_tree.Node(
+        viewport_property_ids_.inner_scroll);
+  }
   return property_trees()->scroll_tree.Node(inner_scroll->scroll_tree_index());
 }
 
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index 2e3b7c61..d05cfb3 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -164,7 +164,6 @@
 void SingleThreadProxy::SetNeedsAnimate() {
   TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsAnimate");
   DCHECK(task_runner_provider_->IsMainThread());
-  single_thread_client_->RequestScheduleAnimation();
   if (animate_requested_)
     return;
   animate_requested_ = true;
diff --git a/chrome/android/java/res/layout-sw600dp/location_status.xml b/chrome/android/java/res/layout-sw600dp/location_status.xml
index 15079c3..d443fefd 100644
--- a/chrome/android/java/res/layout-sw600dp/location_status.xml
+++ b/chrome/android/java/res/layout-sw600dp/location_status.xml
@@ -8,10 +8,15 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto">
 
-    <FrameLayout android:id="@+id/location_bar_icon"
-        android:layout_width="@dimen/location_bar_icon_width"
-        android:layout_height="match_parent"
-        android:layout_gravity="start|center_vertical">
+    <org.chromium.chrome.browser.omnibox.status.StatusView
+        android:id="@+id/location_bar_status"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent">
+
+        <FrameLayout android:id="@+id/location_bar_icon"
+            android:layout_width="@dimen/location_bar_icon_width"
+            android:layout_height="match_parent"
+            android:layout_gravity="start|center_vertical">
 
         <ImageView android:id="@+id/navigation_button"
             style="@style/LocationBarButton"
@@ -33,7 +38,10 @@
             android:visibility="invisible"
             app:tint="@color/dark_mode_tint" />
 
-    </FrameLayout>
+        </FrameLayout>
 
-    <include layout="@layout/location_bar_status" />
+        <include layout="@layout/location_bar_status" />
+
+    </org.chromium.chrome.browser.omnibox.status.StatusView>
+
 </merge>
diff --git a/chrome/android/java/res/layout/location_status.xml b/chrome/android/java/res/layout/location_status.xml
index f0acfc2..417b9d2 100644
--- a/chrome/android/java/res/layout/location_status.xml
+++ b/chrome/android/java/res/layout/location_status.xml
@@ -8,11 +8,16 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto">
 
-    <FrameLayout android:id="@+id/location_bar_icon"
-        android:layout_width="@dimen/location_bar_start_icon_width"
-        android:layout_height="match_parent"
-        android:paddingEnd="4dp"
-        android:visibility="gone" >
+    <org.chromium.chrome.browser.omnibox.status.StatusView
+        android:id="@+id/location_bar_status"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent">
+
+        <FrameLayout android:id="@+id/location_bar_icon"
+            android:layout_width="@dimen/location_bar_start_icon_width"
+            android:layout_height="match_parent"
+            android:paddingEnd="4dp"
+            android:visibility="gone" >
 
         <ImageView android:id="@+id/navigation_button"
             style="@style/LocationBarButton"
@@ -33,7 +38,10 @@
             android:visibility="invisible"
             app:tint="@color/dark_mode_tint" />
 
-    </FrameLayout>
+        </FrameLayout>
 
-    <include layout="@layout/location_bar_status" />
+        <include layout="@layout/location_bar_status" />
+
+    </org.chromium.chrome.browser.omnibox.status.StatusView>
+
 </merge>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AbstractAutofillAssistantUiController.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AbstractAutofillAssistantUiController.java
new file mode 100644
index 0000000..93bc2f2
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AbstractAutofillAssistantUiController.java
@@ -0,0 +1,18 @@
+// 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.autofill_assistant;
+
+/**
+ * Abstract AutofillAssistantUiController, this is created for testing UI.
+ *
+ * TODO(crbug.com/806868): Refactor this class to AutofillAssistantUiController interface and the
+ * original AutofillAssistantUiController to AutofillAssistantUiControllerImpl after done necessary
+ * merges to M72.
+ */
+abstract class AbstractAutofillAssistantUiController
+        implements AutofillAssistantUiDelegate.Client, UiDelegateHolder.Listener {
+    /** Interface called to initiate controller. */
+    public void init(UiDelegateHolder delegateHolder, Details details) {}
+}
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java
index dd22aed..3bb32cb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java
@@ -6,6 +6,7 @@
 
 import android.os.Bundle;
 import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
 
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
@@ -36,18 +37,28 @@
 
     /** Starts Autofill Assistant on the given {@code activity}. */
     public static void start(ChromeActivity activity) {
+        startInternal(activity, /* controller= */ null);
+    }
+
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    static void startInternal(
+            ChromeActivity activity, @Nullable AbstractAutofillAssistantUiController controller) {
         Map<String, String> parameters = extractParameters(activity.getInitialIntent().getExtras());
         parameters.remove(PARAMETER_ENABLED);
+
+        final AbstractAutofillAssistantUiController targetController = controller == null
+                ? new AutofillAssistantUiController(activity, parameters)
+                : controller;
         if (!AutofillAssistantPreferencesUtil.getSkipInitScreenPreference()) {
             FirstRunScreen.show(activity, (result) -> {
-                if (result) initiateAutofillAssistant(activity, parameters);
+                if (result) initiateAutofillAssistant(activity, parameters, targetController);
             });
             return;
         }
 
         if (AutofillAssistantPreferencesUtil.isAutofillAssistantSwitchOn()
                 && AutofillAssistantPreferencesUtil.getSkipInitScreenPreference()) {
-            initiateAutofillAssistant(activity, parameters);
+            initiateAutofillAssistant(activity, parameters, targetController);
         }
         // We don't have consent to start Autofill Assistant and cannot show initial screen.
         // Do nothing.
@@ -56,12 +67,10 @@
     /**
      * Instantiates all essential Autofill Assistant components and starts it.
      */
-    private static void initiateAutofillAssistant(
-            ChromeActivity activity, Map<String, String> parameters) {
-        AutofillAssistantUiController controller =
-                new AutofillAssistantUiController(activity, parameters);
+    private static void initiateAutofillAssistant(ChromeActivity activity,
+            Map<String, String> parameters, AbstractAutofillAssistantUiController controller) {
         UiDelegateHolder delegateHolder = new UiDelegateHolder(
-                controller, new AutofillAssistantUiDelegate(activity, controller));
+                new AutofillAssistantUiDelegate(activity, controller), controller);
         initTabObservers(activity, delegateHolder);
 
         controller.init(delegateHolder, Details.makeFromParameters(parameters));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
index e27a489..1e9b555 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
@@ -34,7 +34,7 @@
  * Autofill Assistant related UIs and forward UI events to native side.
  */
 @JNINamespace("autofill_assistant")
-public class AutofillAssistantUiController implements AutofillAssistantUiDelegate.Client {
+public class AutofillAssistantUiController extends AbstractAutofillAssistantUiController {
     /** OAuth2 scope that RPCs require. */
     private static final String AUTH_TOKEN_TYPE =
             "oauth2:https://www.googleapis.com/auth/userinfo.profile";
@@ -94,6 +94,7 @@
         mUiControllerAndroid = 0;
     }
 
+    @Override
     public void init(UiDelegateHolder delegateHolder, Details details) {
         mUiDelegateHolder = delegateHolder;
         maybeUpdateDetails(details);
@@ -163,17 +164,8 @@
         return nativeOnRequestDebugContext(mUiControllerAndroid);
     }
 
-    /**
-     * Immediately and unconditionally destroys the UI Controller.
-     *
-     * <p>Call {@link UiDelegateHolder#shutdown} to shutdown Autofill Assistant properly and safely.
-     *
-     * <p>Destroy is different from shutdown in that {@code unsafeDestroy} just deletes the native
-     * controller and all the objects it owns, without changing the state of the UI. When that
-     * happens, everything stops irrevocably on the native side. Doing this at the wrong time will
-     * cause crashes.
-     */
-    void unsafeDestroy() {
+    @Override
+    public void onCompleteShutdown() {
         if (mUiControllerAndroid != 0) nativeDestroy(mUiControllerAndroid);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/UiDelegateHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/UiDelegateHolder.java
index 37bfea44..ae6a610 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/UiDelegateHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/UiDelegateHolder.java
@@ -19,8 +19,8 @@
     /** Display the final message for that long before shutting everything down. */
     private static final long GRACEFUL_SHUTDOWN_DELAY_MS = 5_000;
 
-    private final AutofillAssistantUiController mUiController;
     private final AutofillAssistantUiDelegate mUiDelegate;
+    private final Listener mListener;
 
     private boolean mPaused;
     private boolean mHasBeenShutdown;
@@ -29,10 +29,14 @@
     private final Queue<Callback<AutofillAssistantUiDelegate>> mPendingUiOperations =
             new ArrayDeque<>();
 
-    UiDelegateHolder(
-            AutofillAssistantUiController controller, AutofillAssistantUiDelegate uiDelegate) {
-        mUiController = controller;
+    public interface Listener {
+        /** Called when UI completes change for shutdown. */
+        public void onCompleteShutdown();
+    }
+
+    UiDelegateHolder(AutofillAssistantUiDelegate uiDelegate, Listener listener) {
         mUiDelegate = uiDelegate;
+        mListener = listener;
     }
 
     /**
@@ -126,7 +130,7 @@
             mUiDelegate.dismissSnackbar(mDismissSnackbar);
         }
         mUiDelegate.hide();
-        mUiController.unsafeDestroy();
+        mListener.onCompleteShutdown();
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
index a1577137..e6cdee0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -6,7 +6,6 @@
 
 import android.app.Activity;
 import android.app.PendingIntent;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
@@ -24,9 +23,7 @@
 import android.support.annotation.IntDef;
 import android.support.annotation.Nullable;
 import android.support.customtabs.CustomTabsIntent;
-import android.support.customtabs.CustomTabsService;
 import android.support.customtabs.CustomTabsSessionToken;
-import android.support.customtabs.PostMessageBackend;
 import android.support.v4.app.ActivityOptionsCompat;
 import android.text.TextUtils;
 import android.util.Pair;
@@ -40,7 +37,6 @@
 import android.widget.RemoteViews;
 
 import org.chromium.base.ApiCompatibilityUtils;
-import org.chromium.base.Callback;
 import org.chromium.base.CommandLine;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
@@ -60,28 +56,18 @@
 import org.chromium.chrome.browser.KeyboardShortcuts;
 import org.chromium.chrome.browser.LaunchIntentDispatcher;
 import org.chromium.chrome.browser.ServiceTabLauncher;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.WarmupManager;
 import org.chromium.chrome.browser.WebContentsFactory;
 import org.chromium.chrome.browser.appmenu.AppMenuPropertiesDelegate;
 import org.chromium.chrome.browser.autofill_assistant.AutofillAssistantFacade;
 import org.chromium.chrome.browser.browserservices.BrowserSessionContentHandler;
 import org.chromium.chrome.browser.browserservices.BrowserSessionContentUtils;
-import org.chromium.chrome.browser.browserservices.PostMessageHandler;
 import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
 import org.chromium.chrome.browser.contextual_suggestions.ContextualSuggestionsModule;
 import org.chromium.chrome.browser.customtabs.dependency_injection.CustomTabActivityComponent;
 import org.chromium.chrome.browser.customtabs.dependency_injection.CustomTabActivityModule;
-import org.chromium.chrome.browser.customtabs.dynamicmodule.ActivityDelegate;
-import org.chromium.chrome.browser.customtabs.dynamicmodule.ActivityHostImpl;
-import org.chromium.chrome.browser.customtabs.dynamicmodule.DynamicModuleConstants;
-import org.chromium.chrome.browser.customtabs.dynamicmodule.DynamicModuleNavigationEventObserver;
-import org.chromium.chrome.browser.customtabs.dynamicmodule.IActivityDelegate;
-import org.chromium.chrome.browser.customtabs.dynamicmodule.ModuleEntryPoint;
-import org.chromium.chrome.browser.customtabs.dynamicmodule.ModuleLoader;
-import org.chromium.chrome.browser.customtabs.dynamicmodule.ModuleMetrics;
+import org.chromium.chrome.browser.customtabs.dynamicmodule.DynamicModuleCoordinator;
 import org.chromium.chrome.browser.dependency_injection.ChromeActivityCommonsModule;
-import org.chromium.chrome.browser.externalauth.ExternalAuthUtils;
 import org.chromium.chrome.browser.externalnav.ExternalNavigationDelegateImpl;
 import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor;
 import org.chromium.chrome.browser.gsa.GSAState;
@@ -123,7 +109,6 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
-import java.util.regex.Pattern;
 
 /**
  * The activity for custom tabs. It will be launched on top of a client's task.
@@ -176,7 +161,6 @@
     private boolean mHasSpeculated;
     private CustomTabObserver mTabObserver;
     private CustomTabNavigationEventObserver mTabNavigationEventObserver;
-    private DynamicModuleNavigationEventObserver mModuleNavigationEventObserver;
     /** Adds and removes observers from tabs when needed. */
     private TabObserverRegistrar mTabObserverRegistrar;
 
@@ -196,31 +180,10 @@
     private WebappCustomTabTimeSpentLogger mWebappTimeSpentLogger;
 
     @Nullable
-    private ModuleEntryPoint mModuleEntryPoint;
-    @Nullable
-    private ActivityDelegate mModuleActivityDelegate;
-    @Nullable
-    private PostMessageHandler mDynamicModulePostMessageHandler;
-
-    private boolean mModuleOnStartPending;
-    private boolean mModuleOnResumePending;
-    private boolean mHasSetOverlayView;
-    @Nullable
-    private LoadModuleCallback mModuleCallback;
+    private DynamicModuleCoordinator mDynamicModuleCoordinator;
 
     private ActivityTabTaskDescriptionHelper mTaskDescriptionHelper;
 
-    // Default visibility of the Toolbar prior to any header customization.
-    // The value is either View.VISIBLE, View.INVISIBLE, or View.GONE.
-    private int mDefaultToolbarVisibility;
-    // Default visibility of the Toolbar shadow prior to any header customization.
-    // The value is either View.VISIBLE, View.INVISIBLE, or View.GONE.
-    private int mDefaultToolbarShadowVisibility;
-    // Whether the progress bar is enabled prior to any header customization.
-    private boolean mDefaultIsProgressBarEnabled;
-    // Default height of the top control container prior to any header customization.
-    private int mDefaultTopControlContainerHeight;
-
     /**
      * Return true when the activity has been launched in a separate task. The default behavior is
      * to reuse the same task and put the activity on top of the previous one (i.e hiding it). A
@@ -324,200 +287,17 @@
         }
     }
 
-    /**
-     * Dynamically loads a module using the component name specified in the intent if the feature is
-     * enabled, the package is Google-signed, and it is not loaded yet.
-     *
-     * @return whether or not module loading starts.
-     */
-    private boolean maybeLoadModule() {
-        ComponentName componentName = mIntentDataProvider.getModuleComponentName();
-        // Return early if no component name was provided. It's important to do this before checking
-        // the feature experiment group, to avoid entering users into the experiment that do not
-        // even receive the extras for using the feature.
-        if (componentName == null) return false;
-
-        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_MODULE)) {
-            Log.w(TAG, "The %s feature is disabled.", ChromeFeatureList.CCT_MODULE);
-            ModuleMetrics.recordLoadResult(ModuleMetrics.LoadResult.FEATURE_DISABLED);
-            return false;
-        }
-
-        ExternalAuthUtils authUtils = getComponent().getParent().resolveExternalAuthUtils();
-        if (!authUtils.isGoogleSigned(componentName.getPackageName())) {
-            Log.w(TAG, "The %s package is not Google-signed.", componentName.getPackageName());
-            ModuleMetrics.recordLoadResult(ModuleMetrics.LoadResult.NOT_GOOGLE_SIGNED);
-            return false;
-        }
-
-        ModuleLoader moduleLoader = mConnection.getModuleLoader(componentName);
-        moduleLoader.loadModule();
-        mModuleCallback = new LoadModuleCallback();
-        moduleLoader.addCallbackAndIncrementUseCount(mModuleCallback);
-
-        getComponent().resolveCloseButtonNavigator().setLandingPageCriteria(url ->
-                (isModuleLoading() || isModuleLoaded()) && isModuleManagedUrl(url));
-
-        return true;
-    }
-
-    private boolean isModuleLoaded() {
-        return mModuleActivityDelegate != null;
-    }
-
-    @VisibleForTesting
-    public boolean isModuleLoading() {
-        return mModuleCallback != null;
-    }
-
-    private void unregisterModuleNavigationEventObserver() {
-        getActivityTab().removeObserver(mModuleNavigationEventObserver);
-        mTabObserverRegistrar.unregisterTabObserver(mModuleNavigationEventObserver);
-        mModuleNavigationEventObserver = null;
-    }
-
-    /**
-     * Callback to receive the entry point if it was loaded successfully,
-     * or null if there was a problem. This is always called on the UI thread.
-     */
-    private class LoadModuleCallback implements Callback<ModuleEntryPoint> {
-        @Override
-        public void onResult(@Nullable ModuleEntryPoint entryPoint) {
-            mModuleCallback = null;
-
-            if (entryPoint == null) {
-                unregisterModuleNavigationEventObserver();
-            } else {
-                mModuleEntryPoint = entryPoint;
-
-                long createActivityDelegateStartTime = ModuleMetrics.now();
-                mModuleActivityDelegate = entryPoint.createActivityDelegate(
-                        new ActivityHostImpl(CustomTabActivity.this));
-                ModuleMetrics.recordCreateActivityDelegateTime(createActivityDelegateStartTime);
-                mModuleActivityDelegate.onCreate(getSavedInstanceState());
-
-                if (mModuleOnStartPending) startModule();
-                if (mModuleOnResumePending) resumeModule();
-
-                if (mModuleEntryPoint.getModuleVersion()
-                        >= DynamicModuleConstants.ON_NAVIGATION_EVENT_MODULE_API_VERSION) {
-                    mModuleNavigationEventObserver.setActivityDelegate(mModuleActivityDelegate);
-                } else {
-                    unregisterModuleNavigationEventObserver();
-                }
-
-                // Initialise the PostMessageHandler for the current web contents.
-                maybeInitialiseDynamicModulePostMessageHandler(
-                        new ActivityDelegatePostMessageBackend());
-            }
-            // Show CCT header (or top bar) if module fails (or succeeds) to load.
-            maybeCustomizeCctHeader(mIntentDataProvider.getUrlToLoad());
-        }
-    }
-
     @Nullable
     private NavigationController getNavigationController() {
         WebContents webContents = getActivityTab().getWebContents();
         return webContents == null ? null : webContents.getNavigationController();
     }
 
-    @VisibleForTesting
-    void maybeInitialiseDynamicModulePostMessageHandler(PostMessageBackend backend) {
-        // Only initialise the handler if the feature is enabled.
-        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_MODULE_POST_MESSAGE)) return;
-
-        mDynamicModulePostMessageHandler = new PostMessageHandler(backend);
-        mDynamicModulePostMessageHandler.reset(getCurrentWebContents());
-    }
-
-    private void startModule() {
-        assert mModuleActivityDelegate != null;
-
-        mModuleOnStartPending = false;
-        mModuleActivityDelegate.onStart();
-        mModuleActivityDelegate.onRestoreInstanceState(getSavedInstanceState());
-        mModuleActivityDelegate.onPostCreate(getSavedInstanceState());
-    }
-
-    private void resumeModule() {
-        assert mModuleActivityDelegate != null;
-
-        mModuleOnResumePending = false;
-        mModuleActivityDelegate.onResume();
-    }
-
-    public void setBottomBarContentView(View view) {
-        // This method is currently only used by dynamic modules, and all its known uses require
-        // the shadow to be hidden. If this requirement ever changes, we could introduce an explicit
-        // API for that.
-        mBottomBarDelegate.setShowShadow(false);
-        mBottomBarDelegate.setBottomBarContentView(view);
-        mBottomBarDelegate.showBottomBarIfNecessary();
-    }
-
-    public void setOverlayView(View view) {
-        assert !mHasSetOverlayView;
-        mHasSetOverlayView = true;
-        ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
-        addContentView(view, layoutParams);
-    }
-
-    public void setBottomBarHeight(int height) {
-        mBottomBarDelegate.setBottomBarHeight(height);
-    }
-
     public void loadUri(Uri uri) {
         assert mMainTab != null;
         loadUrlInTab(mMainTab, new LoadUrlParams(uri.toString()), SystemClock.elapsedRealtime());
     }
 
-    public void setTopBarContentView(View view) {
-        mTopBarDelegate.setTopBarContentView(view);
-        maybeCustomizeCctHeader(mIntentDataProvider.getUrlToLoad());
-    }
-
-    /**
-     * Requests a postMessage channel for a loaded dynamic module.
-     *
-     * <p>The initialisation work is posted to the UI thread because this method will be called by
-     * the dynamic module so we can't be sure of the thread it will be called on.
-     *
-     * @param postMessageOrigin The origin to use for messages posted to this channel.
-     * @return Whether it was possible to request a channel. Will return false if the dynamic module
-     *         has not been loaded.
-     */
-    public boolean requestPostMessageChannel(Uri postMessageOrigin) {
-        if (mDynamicModulePostMessageHandler == null) return false;
-
-        ThreadUtils.postOnUiThread(
-            () -> mDynamicModulePostMessageHandler.initializeWithPostMessageUri(postMessageOrigin));
-        return true;
-    }
-
-    /**
-     * Posts a message from a loaded dynamic module.
-     *
-     * @param message The message to post to the page. Nothing is assumed about the format of the
-     *                message; we just post it as-is.
-     * @return Whether it was possible to post the message. Will always return {@link
-     *         CustomTabsService#RESULT_FAILURE_DISALLOWED} if the dynamic module has not been
-     *         loaded.
-     */
-    public int postMessage(String message) {
-        // Use of the postMessage API is disallowed when the module has not been loaded.
-        if (mDynamicModulePostMessageHandler == null) {
-            return CustomTabsService.RESULT_FAILURE_DISALLOWED;
-        }
-
-        return mDynamicModulePostMessageHandler.postMessageFromClientApp(message);
-    }
-
-    public void setTopBarHeight(int height) {
-        mTopBarDelegate.setTopBarHeight(height);
-        maybeCustomizeCctHeader(mIntentDataProvider.getUrlToLoad());
-    }
-
     @Override
     public boolean shouldAllocateChildConnection() {
         return !mHasCreatedTabEarly && !mHasSpeculated
@@ -553,14 +333,9 @@
         // Setting task title and icon to be null will preserve the client app's title and icon.
         ApiCompatibilityUtils.setTaskDescription(this, null, null, toolbarColor);
         showCustomButtonsOnToolbar();
-        mBottomBarDelegate = new CustomTabBottomBarDelegate(this, mIntentDataProvider,
-                getFullscreenManager());
+        mBottomBarDelegate = getComponent().resolveBottomBarDelegate();
         mBottomBarDelegate.showBottomBarIfNecessary();
-        mTopBarDelegate = new CustomTabTopBarDelegate(this);
-        mDefaultToolbarVisibility = getToolbarManager().getToolbarVisibility();
-        mDefaultToolbarShadowVisibility = getToolbarManager().getToolbarShadowVisibility();
-        mDefaultIsProgressBarEnabled = getToolbarManager().isProgressBarEnabled();
-        mDefaultTopControlContainerHeight = getFullscreenManager().getTopControlsHeight();
+        mTopBarDelegate = getComponent().resolveTobBarDelegate();
     }
 
     @Override
@@ -604,6 +379,12 @@
         tabModel.addObserver(mTabObserverRegistrar);
         tabModel.addObserver(mCloseActivityWhenEmptyTabModelObserver);
 
+        // Try to initialize dynamic module early to enqueue navigation events
+        // @see DynamicModuleNavigationEventObserver
+        if (mIntentDataProvider.isDynamicModuleEnabled()) {
+            mDynamicModuleCoordinator = getComponent().resolveDynamicModuleCoordinator();
+        }
+
         boolean successfulStateRestore = false;
         // Attempt to restore the previous tab state if applicable.
         if (getSavedInstanceState() != null) {
@@ -737,10 +518,6 @@
             }
         };
 
-        if (!maybeLoadModule()) {
-            unregisterModuleNavigationEventObserver();
-        }
-
         recordClientPackageName();
         mConnection.showSignInToastIfNecessary(mSession, getIntent());
         String url = mIntentDataProvider.getUrlToLoad();
@@ -881,10 +658,11 @@
     }
 
     private void resetPostMessageHandlersForCurrentSession(WebContents newWebContents) {
-        mConnection.resetPostMessageHandlerForSession(mSession, newWebContents);
+        mConnection.resetPostMessageHandlerForSession(
+                mIntentDataProvider.getSession(), newWebContents);
 
-        if (mDynamicModulePostMessageHandler != null) {
-            mDynamicModulePostMessageHandler.reset(newWebContents);
+        if (mDynamicModuleCoordinator != null) {
+            mDynamicModuleCoordinator.resetPostMessageHandlersForCurrentSession(null);
         }
     }
 
@@ -901,11 +679,9 @@
         mTabObserver = new CustomTabObserver(
                 getApplication(), mSession, mIntentDataProvider.isOpenedByChrome());
         mTabNavigationEventObserver = new CustomTabNavigationEventObserver(mSession);
-        mModuleNavigationEventObserver = new DynamicModuleNavigationEventObserver();
 
         mTabObserverRegistrar.registerTabObserver(mTabObserver);
         mTabObserverRegistrar.registerTabObserver(mTabNavigationEventObserver);
-        mTabObserverRegistrar.registerTabObserver(mModuleNavigationEventObserver);
         mTabObserverRegistrar.registerPageLoadMetricsObserver(
                 new PageLoadMetricsObserver(mConnection, mSession, tab));
         mTabObserverRegistrar.registerPageLoadMetricsObserver(
@@ -945,15 +721,6 @@
                 updateColor(tab);
             }
 
-            @Override
-            public void onDidFinishNavigation(Tab tab, String url, boolean isInMainFrame,
-                    boolean isErrorPage, boolean hasCommitted, boolean isSameDocument,
-                    boolean isFragmentNavigation, @Nullable Integer pageTransition, int errorCode,
-                    int httpStatusCode) {
-                if (!isInMainFrame || !hasCommitted) return;
-                maybeCustomizeCctHeader(url);
-            }
-
             /**
              * Updates the color of the Activity's status bar and the CCT Toolbar. When a preview is
              * shown, it should be reset to the default color. If the user later navigates away from
@@ -1020,12 +787,6 @@
         super.onStartWithNative();
         BrowserSessionContentUtils.setActiveContentHandler(mBrowserSessionContentHandler);
         if (mHasCreatedTabEarly && !mMainTab.isLoading()) postDeferredStartupIfNeeded();
-
-        if (mModuleActivityDelegate != null) {
-            startModule();
-        } else if (isModuleLoading()) {
-            mModuleOnStartPending = true;
-        }
     }
 
     @Override
@@ -1063,12 +824,6 @@
         mWebappTimeSpentLogger = WebappCustomTabTimeSpentLogger.createInstanceAndStartTimer(
                 getIntent().getIntExtra(CustomTabIntentDataProvider.EXTRA_BROWSER_LAUNCH_SOURCE,
                         CustomTabIntentDataProvider.LaunchSourceType.OTHER));
-
-        if (mModuleActivityDelegate != null) {
-            resumeModule();
-        } else if (isModuleLoading()) {
-            mModuleOnResumePending = true;
-        }
     }
 
     @Override
@@ -1077,16 +832,12 @@
         if (mWebappTimeSpentLogger != null) {
             mWebappTimeSpentLogger.onPause();
         }
-        if (mModuleActivityDelegate != null) mModuleActivityDelegate.onPause();
-        mModuleOnResumePending = false;
     }
 
     @Override
     public void onStopWithNative() {
         super.onStopWithNative();
         BrowserSessionContentUtils.removeActiveContentHandler(mBrowserSessionContentHandler);
-        if (mModuleActivityDelegate != null) mModuleActivityDelegate.onStop();
-        mModuleOnStartPending = false;
         if (mIsClosing) {
             getTabModelSelector().closeAllTabs(true);
             mTabPersistencePolicy.deleteMetadataStateFileAsync();
@@ -1098,19 +849,7 @@
     @Override
     protected void onDestroyInternal() {
         super.onDestroyInternal();
-        if (mModuleActivityDelegate != null) {
-            mModuleActivityDelegate.onDestroy();
-            mModuleActivityDelegate = null;
-        }
-        mModuleEntryPoint = null;
-        ComponentName moduleComponentName = null;
-        if (mIntentDataProvider != null) {
-            moduleComponentName = mIntentDataProvider.getModuleComponentName();
-        }
-        if (moduleComponentName != null) {
-            mConnection.getModuleLoader(moduleComponentName)
-                    .removeCallbackAndDecrementUseCount(mModuleCallback);
-        }
+
         if (mIncognitoTabHost != null) {
             IncognitoTabHostRegistry.getInstance().unregister(mIncognitoTabHost);
         }
@@ -1118,18 +857,6 @@
         if (mTaskDescriptionHelper != null) mTaskDescriptionHelper.destroy();
     }
 
-    @Override
-    protected void onSaveInstanceState(Bundle outState) {
-        super.onSaveInstanceState(outState);
-        if (mModuleActivityDelegate != null) mModuleActivityDelegate.onSaveInstanceState(outState);
-    }
-
-    @Override
-    public void onWindowFocusChanged(boolean hasFocus) {
-        super.onWindowFocusChanged(hasFocus);
-        if (mModuleActivityDelegate != null) mModuleActivityDelegate.onWindowFocusChanged(hasFocus);
-    }
-
     /**
      * Loads the current tab with the given load params while taking client
      * referrer and extra headers into account.
@@ -1302,8 +1029,8 @@
 
         if (exitFullscreenIfShowing()) return true;
 
-        if (mModuleActivityDelegate != null && mModuleEntryPoint.getModuleVersion() >= 2) {
-            mModuleActivityDelegate.onBackPressedAsync(this::handleTabBackNavigation);
+        if (mDynamicModuleCoordinator != null &&
+                mDynamicModuleCoordinator.onBackPressedAsync(this::handleTabBackNavigation)) {
             return true;
         }
 
@@ -1660,38 +1387,6 @@
         }
     }
 
-    /**
-     * A {@link PostMessageBackend} which delegates incoming notifications to the {@link
-     * ActivityDelegate} from the dynamic module.
-     *
-     * <p>If the dynamic module is not loaded, we ignore incoming notifications and always return
-     * false.
-     */
-    private class ActivityDelegatePostMessageBackend implements PostMessageBackend {
-        @Override
-        public boolean onPostMessage(String message, Bundle extras) {
-            if (mModuleActivityDelegate != null) {
-                mModuleActivityDelegate.onPostMessage(message);
-                return true;
-            }
-            return false;
-        }
-
-        @Override
-        public boolean onNotifyMessageChannelReady(Bundle extras) {
-            if (mModuleActivityDelegate != null) {
-                mModuleActivityDelegate.onMessageChannelReady();
-                return true;
-            }
-            return false;
-        }
-
-        @Override
-        public void onDisconnectChannel(Context appContext) {
-            // Nothing to do.
-        }
-    }
-
     @Override
     protected CustomTabActivityComponent createComponent(ChromeActivityCommonsModule commonsModule,
             ContextualSuggestionsModule contextualSuggestionsModule) {
@@ -1700,69 +1395,4 @@
         return ChromeApplication.getComponent().createCustomTabActivityComponent(
                 commonsModule, contextualSuggestionsModule, customTabsModule);
     }
-
-    private boolean isModuleManagedUrl(String url) {
-        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_MODULE)) {
-            return false;
-        }
-        List<String> moduleManagedHosts = mIntentDataProvider.getExtraModuleManagedHosts();
-        Pattern urlsPattern = mIntentDataProvider.getExtraModuleManagedUrlsPattern();
-        if (TextUtils.isEmpty(url) || moduleManagedHosts == null || moduleManagedHosts.isEmpty()
-                || urlsPattern == null) {
-            return false;
-        }
-        Uri parsed = Uri.parse(url);
-        String scheme = parsed.getScheme();
-        if (!UrlConstants.HTTPS_SCHEME.equals(scheme)) {
-            return false;
-        }
-        String host = parsed.getHost();
-        if (host == null) {
-            return false;
-        }
-        String pathAndQuery = url.substring(UrlUtilities.stripPath(url).length());
-        for (String moduleManagedHost : moduleManagedHosts) {
-            if (host.equals(moduleManagedHost) && urlsPattern.matcher(pathAndQuery).matches()) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private int getTopBarHeight() {
-        Integer topBarHeight = mTopBarDelegate.getTopBarHeight();
-        // Custom top bar height must not be too small compared to the default top control container
-        // height, nor shall it be larger than the height of the web content.
-        if (topBarHeight != null && topBarHeight >= 0
-                && topBarHeight > mDefaultTopControlContainerHeight / 2 && getWindow() != null
-                && topBarHeight < getWindow().getDecorView().getHeight() / 2) {
-            return topBarHeight;
-        }
-        return mDefaultTopControlContainerHeight;
-    }
-
-    private void maybeCustomizeCctHeader(String url) {
-        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_MODULE)
-                || (!isModuleLoaded() && !isModuleLoading())) {
-            return;
-        }
-        boolean isModuleManagedUrl = isModuleManagedUrl(url);
-        mTopBarDelegate.showTopBarIfNecessary(isModuleManagedUrl);
-        if (ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_MODULE_CUSTOM_HEADER)
-                && mIntentDataProvider.shouldHideCctHeaderOnModuleManagedUrls()) {
-            getToolbarManager().setToolbarVisibility(
-                    isModuleManagedUrl ? View.GONE : mDefaultToolbarVisibility);
-            getToolbarManager().setToolbarShadowVisibility(
-                    isModuleManagedUrl ? View.GONE : mDefaultToolbarShadowVisibility);
-            getToolbarManager().setProgressBarEnabled(
-                    isModuleManagedUrl ? false : mDefaultIsProgressBarEnabled);
-            getFullscreenManager().setTopControlsHeight(
-                    isModuleManagedUrl ? getTopBarHeight() : mDefaultTopControlContainerHeight);
-        }
-    }
-
-    @VisibleForTesting
-    public IActivityDelegate getActivityDelegateForTesting() {
-        return mModuleActivityDelegate.getIActivityDelegateForTesting();
-    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java
index 1b000251..2328aa9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java
@@ -28,6 +28,7 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager.OverlayPanelManagerObserver;
+import org.chromium.chrome.browser.dependency_injection.ActivityScope;
 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager.FullscreenListener;
 import org.chromium.chrome.browser.tab.Tab;
@@ -35,10 +36,13 @@
 
 import java.util.List;
 
+import javax.inject.Inject;
+
 /**
  * Delegate that manages bottom bar area inside of {@link CustomTabActivity}.
  */
-class CustomTabBottomBarDelegate implements FullscreenListener {
+@ActivityScope
+public class CustomTabBottomBarDelegate implements FullscreenListener {
     private static final String TAG = "CustomTab";
     private static final CachedMetrics.ActionEvent REMOTE_VIEWS_SHOWN =
             new CachedMetrics.ActionEvent("CustomTabsRemoteViewsShown");
@@ -70,6 +74,7 @@
         }
     };
 
+    @Inject
     public CustomTabBottomBarDelegate(ChromeActivity activity,
             CustomTabIntentDataProvider dataProvider, ChromeFullscreenManager fullscreenManager) {
         mActivity = activity;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
index 07baebe8..f3f96502 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
@@ -31,12 +31,14 @@
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.ChromeApplication;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.ChromeVersionInfo;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.browserservices.BrowserSessionDataProvider;
+import org.chromium.chrome.browser.customtabs.dynamicmodule.ModuleMetrics;
 import org.chromium.chrome.browser.externalauth.ExternalAuthUtils;
 import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
 import org.chromium.chrome.browser.util.ColorUtils;
@@ -787,10 +789,41 @@
     }
 
     /**
+     * @return Whether the Custom Tab should attempt to load a dynamic module, i.e.
+     * if the feature is enabled, the package is provided and package is Google-signed.
+     *
+     * Will return false if native is not initialized.
+     */
+    public boolean isDynamicModuleEnabled() {
+        if (!ChromeFeatureList.isInitialized()) return false;
+
+        ComponentName componentName = getModuleComponentName();
+        // Return early if no component name was provided. It's important to do this before checking
+        // the feature experiment group, to avoid entering users into the experiment that do not
+        // even receive the extras for using the feature.
+        if (componentName == null) return false;
+
+        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_MODULE)) {
+            Log.w(TAG, "The %s feature is disabled.", ChromeFeatureList.CCT_MODULE);
+            ModuleMetrics.recordLoadResult(ModuleMetrics.LoadResult.FEATURE_DISABLED);
+            return false;
+        }
+
+        ExternalAuthUtils authUtils = ChromeApplication.getComponent().resolveExternalAuthUtils();
+        if (!authUtils.isGoogleSigned(componentName.getPackageName())) {
+            Log.w(TAG, "The %s package is not Google-signed.", componentName.getPackageName());
+            ModuleMetrics.recordLoadResult(ModuleMetrics.LoadResult.NOT_GOOGLE_SIGNED);
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
      * @return The component name of the module entry point, or null if not specified.
      */
     @Nullable
-    ComponentName getModuleComponentName() {
+    public ComponentName getModuleComponentName() {
         return mModuleComponentName;
     }
 
@@ -800,7 +833,7 @@
      * or null if not specified.
      */
     @Nullable
-    Pattern getExtraModuleManagedUrlsPattern() {
+    public Pattern getExtraModuleManagedUrlsPattern() {
         return mModuleManagedUrlsPattern;
     }
 
@@ -809,7 +842,7 @@
      * @return The list of module managed hosts, or null if not specified.
      */
     @Nullable
-    List<String> getExtraModuleManagedHosts() {
+    public List<String> getExtraModuleManagedHosts() {
         return mModuleManagedHosts;
     }
 
@@ -823,7 +856,7 @@
     /**
      * @return Whether to hide CCT header on module managed URLs.
      */
-    boolean shouldHideCctHeaderOnModuleManagedUrls() {
+    public boolean shouldHideCctHeaderOnModuleManagedUrls() {
         return mHideCctHeaderOnModuleManagedUrls;
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabTopBarDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabTopBarDelegate.java
index 2e8bdcac..5a760efd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabTopBarDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabTopBarDelegate.java
@@ -11,11 +11,15 @@
 
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.dependency_injection.ActivityScope;
+
+import javax.inject.Inject;
 
 /**
  * Delegate that manages top bar area inside of {@link CustomTabActivity}.
  */
-class CustomTabTopBarDelegate {
+@ActivityScope
+public class CustomTabTopBarDelegate {
     private final ChromeActivity mActivity;
     private ViewGroup mTopBarView;
     @Nullable
@@ -23,6 +27,7 @@
     @Nullable
     private Integer mTopBarHeight;
 
+    @Inject
     public CustomTabTopBarDelegate(ChromeActivity activity) {
         mActivity = activity;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityComponent.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityComponent.java
index 86c9882..b2f660f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityComponent.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityComponent.java
@@ -7,8 +7,11 @@
 import org.chromium.chrome.browser.browserservices.trustedwebactivityui.TrustedWebActivityCoordinator;
 import org.chromium.chrome.browser.contextual_suggestions.ContextualSuggestionsModule;
 import org.chromium.chrome.browser.customtabs.CloseButtonNavigator;
+import org.chromium.chrome.browser.customtabs.CustomTabBottomBarDelegate;
 import org.chromium.chrome.browser.customtabs.CustomTabDelegateFactory;
+import org.chromium.chrome.browser.customtabs.CustomTabTopBarDelegate;
 import org.chromium.chrome.browser.customtabs.TabObserverRegistrar;
+import org.chromium.chrome.browser.customtabs.dynamicmodule.DynamicModuleCoordinator;
 import org.chromium.chrome.browser.dependency_injection.ActivityScope;
 import org.chromium.chrome.browser.dependency_injection.ChromeActivityCommonsModule;
 import org.chromium.chrome.browser.dependency_injection.ChromeActivityComponent;
@@ -24,7 +27,11 @@
 @ActivityScope
 public interface CustomTabActivityComponent extends ChromeActivityComponent {
     TrustedWebActivityCoordinator resolveTrustedWebActivityCoordinator();
+    DynamicModuleCoordinator resolveDynamicModuleCoordinator();
+
     CloseButtonNavigator resolveCloseButtonNavigator();
     CustomTabDelegateFactory resolveTabDelegateFactory();
     TabObserverRegistrar resolveTabObserverRegistrar();
+    CustomTabTopBarDelegate resolveTobBarDelegate();
+    CustomTabBottomBarDelegate resolveBottomBarDelegate();
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityDelegate.java
index 13daf7f..dd2db69c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityDelegate.java
@@ -8,14 +8,138 @@
 import android.os.RemoteException;
 
 import org.chromium.base.VisibleForTesting;
+import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.init.ActivityLifecycleDispatcher;
+import org.chromium.chrome.browser.lifecycle.Destroyable;
+import org.chromium.chrome.browser.lifecycle.PauseResumeWithNativeObserver;
+import org.chromium.chrome.browser.lifecycle.SaveInstanceStateObserver;
+import org.chromium.chrome.browser.lifecycle.StartStopWithNativeObserver;
+import org.chromium.chrome.browser.lifecycle.WindowFocusChangedObserver;
+
+import javax.inject.Inject;
 
 /**
  * A wrapper around a {@link IActivityDelegate}.
  *
  * No {@link RemoteException} should ever be thrown as all of this code runs in the same process.
  */
-public class ActivityDelegate {
-    private final IActivityDelegate mActivityDelegate;
+public class ActivityDelegate implements StartStopWithNativeObserver,
+        PauseResumeWithNativeObserver, Destroyable,
+        SaveInstanceStateObserver, WindowFocusChangedObserver {
+    private IActivityDelegate mActivityDelegate;
+
+    private boolean mModuleOnStartPending;
+    private boolean mModuleOnResumePending;
+    private ChromeActivity mActivity;
+
+    private Bundle getSavedInstanceState() {
+        return mActivity.getSavedInstanceState();
+    }
+
+    @Inject
+    public ActivityDelegate(
+            ChromeActivity chromeActivity,
+            ActivityLifecycleDispatcher activityLifecycleDispatcher) {
+
+        mActivity = chromeActivity;
+        activityLifecycleDispatcher.register(this);
+    }
+
+    public void setActivityDelegate(IActivityDelegate activityDelegate) {
+        mActivityDelegate = activityDelegate;
+
+        safeRun(() -> mActivityDelegate.onCreate(getSavedInstanceState()));
+
+        if (mModuleOnStartPending) startModule();
+        if (mModuleOnResumePending) resumeModule();
+    }
+
+    private void startModule() {
+        assert mActivityDelegate != null;
+
+        mModuleOnStartPending = false;
+        safeRun(() -> {
+            mActivityDelegate.onStart();
+            mActivityDelegate.onRestoreInstanceState(getSavedInstanceState());
+            mActivityDelegate.onPostCreate(getSavedInstanceState());
+        });
+    }
+
+    private void resumeModule() {
+        assert mActivityDelegate != null;
+
+        mModuleOnResumePending = false;
+        safeRun(mActivityDelegate::onResume);
+    }
+
+    @Override
+    public void destroy() {
+        if (mActivityDelegate != null) {
+            safeRun(mActivityDelegate::onDestroy);
+            mActivityDelegate = null;
+        }
+    }
+
+    @Override
+    public void onStartWithNative() {
+        if (mActivityDelegate != null) {
+            startModule();
+        } else {
+            mModuleOnStartPending = true;
+        }
+    }
+
+    @Override
+    public void onStopWithNative() {
+        if (mActivityDelegate != null) {
+            safeRun(mActivityDelegate::onStop);
+        }
+        mModuleOnStartPending = false;
+    }
+
+    @Override
+    public void onResumeWithNative() {
+        if (mActivityDelegate != null) {
+            resumeModule();
+        } else {
+            mModuleOnResumePending = true;
+        }
+    }
+
+    @Override
+    public void onPauseWithNative() {
+        if (mActivityDelegate != null) {
+            safeRun(mActivityDelegate::onPause);
+        }
+        mModuleOnResumePending = false;
+    }
+
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        if (mActivityDelegate != null) {
+            safeRun(() -> mActivityDelegate.onSaveInstanceState(outState));
+        }
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasFocus) {
+        if (mActivityDelegate != null) {
+            safeRun(() -> mActivityDelegate.onWindowFocusChanged(hasFocus));
+        }
+    }
+
+    public void onBackPressedAsync(Runnable notHandledRunnable) {
+        if (mActivityDelegate != null) {
+            safeRun(() -> mActivityDelegate.onBackPressedAsync(
+                    ObjectWrapper.wrap(notHandledRunnable)));
+        }
+    }
+
+    @VisibleForTesting
+    public IActivityDelegate getActivityDelegateForTesting() {
+        return mActivityDelegate;
+    }
 
     private interface RemoteRunnable { void run() throws RemoteException; }
 
@@ -39,58 +163,10 @@
         return defaultReturn;
     }
 
-    public ActivityDelegate(IActivityDelegate activityDelegate) {
-        mActivityDelegate = activityDelegate;
-    }
-
-    public void onCreate(Bundle savedInstanceState) {
-        safeRun(() -> mActivityDelegate.onCreate(savedInstanceState));
-    }
-
-    public void onPostCreate(Bundle savedInstanceState) {
-        safeRun(() -> mActivityDelegate.onPostCreate(savedInstanceState));
-    }
-
-    public void onStart() {
-        safeRun(mActivityDelegate::onStart);
-    }
-
-    public void onStop() {
-        safeRun(mActivityDelegate::onStop);
-    }
-
-    public void onWindowFocusChanged(boolean hasFocus) {
-        safeRun(() -> mActivityDelegate.onWindowFocusChanged(hasFocus));
-    }
-
-    public void onSaveInstanceState(Bundle outState) {
-        safeRun(() -> mActivityDelegate.onSaveInstanceState(outState));
-    }
-
     public void onRestoreInstanceState(Bundle savedInstanceState) {
         safeRun(() -> mActivityDelegate.onRestoreInstanceState(savedInstanceState));
     }
 
-    public void onResume() {
-        safeRun(mActivityDelegate::onResume);
-    }
-
-    public void onPause() {
-        safeRun(mActivityDelegate::onPause);
-    }
-
-    public void onDestroy() {
-        safeRun(mActivityDelegate::onDestroy);
-    }
-
-    public boolean onBackPressed() {
-        return safeCall(mActivityDelegate::onBackPressed, false);
-    }
-
-    public void onBackPressedAsync(Runnable notHandledRunnable) {
-        safeRun(() -> mActivityDelegate.onBackPressedAsync(ObjectWrapper.wrap(notHandledRunnable)));
-    }
-
     public void onNavigationEvent(int navigationEvent, Bundle extras) {
         safeRun(() -> mActivityDelegate.onNavigationEvent(navigationEvent, extras));
     }
@@ -102,9 +178,4 @@
     public void onPostMessage(String message) {
         safeRun(() -> mActivityDelegate.onPostMessage(message));
     }
-
-    @VisibleForTesting
-    public IActivityDelegate getIActivityDelegateForTesting() {
-        return mActivityDelegate;
-    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityDelegatePostMessageBackend.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityDelegatePostMessageBackend.java
new file mode 100644
index 0000000..4a3be88
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityDelegatePostMessageBackend.java
@@ -0,0 +1,47 @@
+// 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.customtabs.dynamicmodule;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.customtabs.PostMessageBackend;
+
+/**
+ * A {@link PostMessageBackend} which delegates incoming notifications to the {@link
+ * ActivityDelegate} from the dynamic module.
+ *
+ * <p>If the dynamic module is not loaded, we ignore incoming notifications and always return
+ * false.
+ */
+public class ActivityDelegatePostMessageBackend implements PostMessageBackend {
+    private final ActivityDelegate mActivityDelegate;
+
+    ActivityDelegatePostMessageBackend(ActivityDelegate activityDelegate) {
+        mActivityDelegate = activityDelegate;
+    }
+
+    @Override
+    public boolean onPostMessage(String message, Bundle extras) {
+        if (mActivityDelegate != null) {
+            mActivityDelegate.onPostMessage(message);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean onNotifyMessageChannelReady(Bundle extras) {
+        if (mActivityDelegate != null) {
+            mActivityDelegate.onMessageChannelReady();
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void onDisconnectChannel(Context appContext) {
+        // Nothing to do.
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityHostImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityHostImpl.java
index 5f19c79a..e86f371 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityHostImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityHostImpl.java
@@ -7,60 +7,58 @@
 import android.net.Uri;
 import android.view.View;
 
-import org.chromium.chrome.browser.customtabs.CustomTabActivity;
-
 /**
  * The implementation of {@link IActivityHost}.
  */
 public class ActivityHostImpl extends BaseActivityHost {
-    private final CustomTabActivity mActivity;
+    private final DynamicModuleCoordinator mModuleCoordinator;
 
-    public ActivityHostImpl(CustomTabActivity activity) {
-        mActivity = activity;
+    public ActivityHostImpl(DynamicModuleCoordinator moduleCoordinator) {
+        mModuleCoordinator = moduleCoordinator;
     }
 
     @Override
     public IObjectWrapper getActivityContext() {
-        return ObjectWrapper.wrap(mActivity);
+        return ObjectWrapper.wrap(mModuleCoordinator.getActivityContext());
     }
 
     @Override
     public void setBottomBarView(IObjectWrapper bottomBarView) {
-        mActivity.setBottomBarContentView(ObjectWrapper.unwrap(bottomBarView, View.class));
+        mModuleCoordinator.setBottomBarContentView(ObjectWrapper.unwrap(bottomBarView, View.class));
     }
 
     @Override
     public void setOverlayView(IObjectWrapper overlayView) {
-        mActivity.setOverlayView(ObjectWrapper.unwrap(overlayView, View.class));
+        mModuleCoordinator.setOverlayView(ObjectWrapper.unwrap(overlayView, View.class));
     }
 
     @Override
     public void setBottomBarHeight(int height) {
-        mActivity.setBottomBarHeight(height);
+        mModuleCoordinator.setBottomBarHeight(height);
     }
 
     @Override
     public void loadUri(Uri uri) {
-        mActivity.loadUri(uri);
+        mModuleCoordinator.loadUri(uri);
     }
 
     @Override
     public void setTopBarView(IObjectWrapper topBarView) {
-        mActivity.setTopBarContentView(ObjectWrapper.unwrap(topBarView, View.class));
+        mModuleCoordinator.setTopBarContentView(ObjectWrapper.unwrap(topBarView, View.class));
     }
 
     @Override
     public boolean requestPostMessageChannel(Uri postMessageOrigin) {
-        return mActivity.requestPostMessageChannel(postMessageOrigin);
+        return mModuleCoordinator.requestPostMessageChannel(postMessageOrigin);
     }
 
     @Override
     public int postMessage(String message) {
-        return mActivity.postMessage(message);
+        return mModuleCoordinator.postMessage(message);
     }
 
     @Override
     public void setTopBarHeight(int heightInPx) {
-        mActivity.setTopBarHeight(heightInPx);
+        mModuleCoordinator.setTopBarHeight(heightInPx);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleConstants.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleConstants.java
index d657097..d2599f6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleConstants.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleConstants.java
@@ -12,4 +12,9 @@
      * The module version when {@link IActivityDelegate#onNavigationEvent} is introduced.
      */
     public static final int ON_NAVIGATION_EVENT_MODULE_API_VERSION = 4;
+
+    /**
+     * The module version when {@link IActivityDelegate#onBackPressedAsync} is introduced.
+     */
+    public static final int ON_BACK_PRESSED_ASYNC_API_VERSION = 2;
 }
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java
new file mode 100644
index 0000000..249e8bc
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java
@@ -0,0 +1,398 @@
+// 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.customtabs.dynamicmodule;
+
+import static org.chromium.chrome.browser.customtabs.dynamicmodule.DynamicModuleConstants.ON_BACK_PRESSED_ASYNC_API_VERSION;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.net.Uri;
+import android.support.annotation.IntDef;
+import android.support.annotation.Nullable;
+import android.support.customtabs.CustomTabsService;
+import android.support.customtabs.PostMessageBackend;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.ViewGroup;
+
+import org.chromium.base.Callback;
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.VisibleForTesting;
+import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.ChromeFeatureList;
+import org.chromium.chrome.browser.UrlConstants;
+import org.chromium.chrome.browser.browserservices.PostMessageHandler;
+import org.chromium.chrome.browser.customtabs.CloseButtonNavigator;
+import org.chromium.chrome.browser.customtabs.CustomTabActivity;
+import org.chromium.chrome.browser.customtabs.CustomTabBottomBarDelegate;
+import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
+import org.chromium.chrome.browser.customtabs.CustomTabTopBarDelegate;
+import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
+import org.chromium.chrome.browser.customtabs.TabObserverRegistrar;
+import org.chromium.chrome.browser.dependency_injection.ActivityScope;
+import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
+import org.chromium.chrome.browser.init.ActivityLifecycleDispatcher;
+import org.chromium.chrome.browser.lifecycle.Destroyable;
+import org.chromium.chrome.browser.lifecycle.NativeInitObserver;
+import org.chromium.chrome.browser.tab.EmptyTabObserver;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tab.TabObserver;
+import org.chromium.chrome.browser.util.UrlUtilities;
+import org.chromium.content_public.browser.WebContents;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import javax.inject.Inject;
+
+import dagger.Lazy;
+
+/**
+ * Class to control a CCT dynamic module.
+ */
+@ActivityScope
+public class DynamicModuleCoordinator implements NativeInitObserver, Destroyable {
+    private final CustomTabIntentDataProvider mIntentDataProvider;
+    private final TabObserverRegistrar mTabObserverRegistrar;
+    private final CustomTabsConnection mConnection;
+
+    // TODO(amalova): CustomTabActivity is only needed for loadUri(). Remove it once it is possible.
+    private final CustomTabActivity mActivity;
+
+    private final Lazy<CustomTabTopBarDelegate> mTopBarDelegate;
+    private final Lazy<CustomTabBottomBarDelegate> mBottomBarDelegate;
+    private final Lazy<ChromeFullscreenManager> mFullscreenManager;
+
+    @Nullable
+    private LoadModuleCallback mModuleCallback;
+    @Nullable
+    private ModuleEntryPoint mModuleEntryPoint;
+
+    private ActivityDelegate mActivityDelegate;
+
+    @Nullable
+    private PostMessageHandler mDynamicModulePostMessageHandler;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({View.VISIBLE, View.INVISIBLE, View.GONE})
+    private @interface ToolbarVisibility {}
+
+    // Default visibility of the Toolbar prior to any header customization.
+    @ToolbarVisibility
+    private int mDefaultToolbarVisibility;
+    // The value is either View.VISIBLE, View.INVISIBLE, or View.GONE.
+    @ToolbarVisibility
+    private int mDefaultToolbarShadowVisibility;
+
+    // Whether the progress bar is enabled prior to any header customization.
+    private boolean mDefaultIsProgressBarEnabled;
+    // Default height of the top control container prior to any header customization.
+    private int mDefaultTopControlContainerHeight;
+    private boolean mHasSetOverlayView;
+
+    private final EmptyTabObserver mHeaderVisibilityObserver = new EmptyTabObserver() {
+        @Override
+        public void onDidFinishNavigation(Tab tab, String url, boolean isInMainFrame,
+                                          boolean isErrorPage, boolean hasCommitted,
+                                          boolean isSameDocument, boolean isFragmentNavigation,
+                                          @Nullable Integer pageTransition, int errorCode,
+                                          int httpStatusCode) {
+            if (!isInMainFrame || !hasCommitted) return;
+            maybeCustomizeCctHeader(url);
+        }
+    };
+    private final DynamicModuleNavigationEventObserver mModuleNavigationEventObserver =
+            new DynamicModuleNavigationEventObserver();
+
+    @Inject
+    public DynamicModuleCoordinator(CustomTabIntentDataProvider intentDataProvider,
+                                    CloseButtonNavigator closeButtonNavigator,
+                                    TabObserverRegistrar tabObserverRegistrar,
+                                    ActivityLifecycleDispatcher activityLifecycleDispatcher,
+                                    ActivityDelegate activityDelegate,
+                                    Lazy<CustomTabTopBarDelegate> topBarDelegate,
+                                    Lazy<CustomTabBottomBarDelegate> bottomBarDelegate,
+                                    Lazy<ChromeFullscreenManager> fullscreenManager,
+                                    CustomTabsConnection connection, ChromeActivity activity) {
+        mIntentDataProvider = intentDataProvider;
+        mTabObserverRegistrar = tabObserverRegistrar;
+        mActivity = (CustomTabActivity) activity;
+        mConnection = connection;
+
+        mTabObserverRegistrar.registerTabObserver(mModuleNavigationEventObserver);
+        mTabObserverRegistrar.registerTabObserver(mHeaderVisibilityObserver);
+
+        mActivityDelegate = activityDelegate;
+        mTopBarDelegate = topBarDelegate;
+        mBottomBarDelegate = bottomBarDelegate;
+        mFullscreenManager = fullscreenManager;
+
+        closeButtonNavigator.setLandingPageCriteria(url ->
+                (isModuleLoading() || isModuleLoaded()) && isModuleManagedUrl(url));
+
+        activityLifecycleDispatcher.register(this);
+    }
+
+    @Override
+    public void onFinishNativeInitialization() {
+        loadModule();
+    }
+
+    /**
+     * Dynamically loads a module using the component name specified in the intent if the feature is
+     * enabled, the package is Google-signed, and it is not loaded yet.
+     *
+     * @return whether or not module loading starts.
+     */
+    private void loadModule() {
+        ComponentName componentName = mIntentDataProvider.getModuleComponentName();
+
+        ModuleLoader moduleLoader = mConnection.getModuleLoader(componentName);
+        moduleLoader.loadModule();
+        mModuleCallback = new LoadModuleCallback();
+        moduleLoader.addCallbackAndIncrementUseCount(mModuleCallback);
+    }
+
+    @Override
+    public void destroy() {
+        mModuleEntryPoint = null;
+
+        ComponentName moduleComponentName = mIntentDataProvider.getModuleComponentName();
+        mConnection.getModuleLoader(moduleComponentName)
+                    .removeCallbackAndDecrementUseCount(mModuleCallback);
+    }
+
+    /* package */ Context getActivityContext() {
+        return mActivity;
+    }
+
+    /* package */ void setBottomBarContentView(View view) {
+        // All known usages of this method require the shadow to be hidden.
+        // If this requirement ever changes, we could introduce an explicit API for that.
+        mBottomBarDelegate.get().setShowShadow(false);
+        mBottomBarDelegate.get().setBottomBarContentView(view);
+        mBottomBarDelegate.get().showBottomBarIfNecessary();
+    }
+
+    /* package */ void setOverlayView(View view) {
+        assert !mHasSetOverlayView;
+        mHasSetOverlayView = true;
+        ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+        mActivity.addContentView(view, layoutParams);
+    }
+
+    /* package */ void setBottomBarHeight(int height) {
+        mBottomBarDelegate.get().setBottomBarHeight(height);
+    }
+
+    /* package */ void loadUri(Uri uri) {
+        mActivity.loadUri(uri);
+    }
+
+    @VisibleForTesting
+    public IActivityDelegate getActivityDelegateForTesting() {
+        return mActivityDelegate.getActivityDelegateForTesting();
+    }
+
+    @VisibleForTesting
+    public void setTopBarContentView(View view) {
+        mTopBarDelegate.get().setTopBarContentView(view);
+        maybeCustomizeCctHeader(mIntentDataProvider.getUrlToLoad());
+    }
+
+    @VisibleForTesting
+    public void maybeInitialiseDynamicModulePostMessageHandler(PostMessageBackend backend) {
+        // Only initialise the handler if the feature is enabled.
+        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_MODULE_POST_MESSAGE)) return;
+
+        mDynamicModulePostMessageHandler = new PostMessageHandler(backend);
+        mDynamicModulePostMessageHandler.reset(mActivity.getCurrentWebContents());
+    }
+
+    public void resetPostMessageHandlersForCurrentSession(WebContents newWebContents) {
+        if (mDynamicModulePostMessageHandler != null) {
+            mDynamicModulePostMessageHandler.reset(newWebContents);
+        }
+    }
+
+    /**
+     * @see IActivityDelegate#onBackPressedAsync
+     */
+    public boolean onBackPressedAsync(Runnable notHandledRunnable) {
+        if (mModuleEntryPoint != null &&
+                mModuleEntryPoint.getModuleVersion() >= ON_BACK_PRESSED_ASYNC_API_VERSION) {
+            mActivityDelegate.onBackPressedAsync(notHandledRunnable);
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Requests a postMessage channel for a loaded dynamic module.
+     *
+     * <p>The initialisation work is posted to the UI thread because this method will be called by
+     * the dynamic module so we can't be sure of the thread it will be called on.
+     *
+     * @param postMessageOrigin The origin to use for messages posted to this channel.
+     * @return Whether it was possible to request a channel. Will return false if the dynamic module
+     *         has not been loaded.
+     */
+    public boolean requestPostMessageChannel(Uri postMessageOrigin) {
+        if (mDynamicModulePostMessageHandler == null) return false;
+
+        ThreadUtils.postOnUiThread(() ->
+                mDynamicModulePostMessageHandler.initializeWithPostMessageUri(postMessageOrigin));
+        return true;
+    }
+
+    /**
+     * Posts a message from a loaded dynamic module.
+     *
+     * @param message The message to post to the page. Nothing is assumed about the format of the
+     *                message; we just post it as-is.
+     * @return Whether it was possible to post the message. Will always return {@link
+     *         CustomTabsService#RESULT_FAILURE_DISALLOWED} if the dynamic module has not been
+     *         loaded.
+     */
+    public int postMessage(String message) {
+        // Use of the postMessage API is disallowed when the module has not been loaded.
+        if (mDynamicModulePostMessageHandler == null) {
+            return CustomTabsService.RESULT_FAILURE_DISALLOWED;
+        }
+
+        return mDynamicModulePostMessageHandler.postMessageFromClientApp(message);
+    }
+
+    /**
+     * Callback to receive the entry point if it was loaded successfully,
+     * or null if there was a problem. This is always called on the UI thread.
+     */
+    private class LoadModuleCallback implements Callback<ModuleEntryPoint> {
+        @Override
+        public void onResult(@Nullable ModuleEntryPoint entryPoint) {
+            mDefaultToolbarVisibility = mActivity.getToolbarManager().getToolbarVisibility();
+            mDefaultToolbarShadowVisibility =
+                    mActivity.getToolbarManager().getToolbarShadowVisibility();
+            mDefaultIsProgressBarEnabled = mActivity.getToolbarManager().isProgressBarEnabled();
+            mDefaultTopControlContainerHeight = mFullscreenManager.get().getTopControlsHeight();
+
+            mModuleCallback = null;
+
+            if (entryPoint == null) {
+                unregisterModuleObservers();
+                mActivityDelegate = null;
+            } else {
+                mModuleEntryPoint = entryPoint;
+                long createActivityDelegateStartTime = ModuleMetrics.now();
+                IActivityDelegate activityDelegate = entryPoint.createActivityDelegate(
+                        new ActivityHostImpl(DynamicModuleCoordinator.this));
+                ModuleMetrics.recordCreateActivityDelegateTime(createActivityDelegateStartTime);
+
+                mActivityDelegate.setActivityDelegate(activityDelegate);
+
+                if (mModuleEntryPoint.getModuleVersion()
+                        >= DynamicModuleConstants.ON_NAVIGATION_EVENT_MODULE_API_VERSION) {
+                    mModuleNavigationEventObserver.setActivityDelegate(mActivityDelegate);
+                } else {
+                    unregisterModuleObservers();
+                }
+
+                // Initialise the PostMessageHandler for the current web contents.
+
+                maybeInitialiseDynamicModulePostMessageHandler(
+                        new ActivityDelegatePostMessageBackend(mActivityDelegate));
+            }
+            // Show CCT header (or top bar) if module fails (or succeeds) to load.
+            maybeCustomizeCctHeader(mIntentDataProvider.getUrlToLoad());
+        }
+    }
+
+    private boolean isModuleLoaded() {
+        return mModuleEntryPoint != null;
+    }
+
+    @VisibleForTesting
+    public boolean isModuleLoading() {
+        return mModuleCallback != null;
+    }
+
+    private boolean isModuleManagedUrl(String url) {
+        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_MODULE)) {
+            return false;
+        }
+        List<String> moduleManagedHosts = mIntentDataProvider.getExtraModuleManagedHosts();
+        Pattern urlsPattern = mIntentDataProvider.getExtraModuleManagedUrlsPattern();
+        if (TextUtils.isEmpty(url) || moduleManagedHosts == null || moduleManagedHosts.isEmpty()
+                || urlsPattern == null) {
+            return false;
+        }
+        Uri parsed = Uri.parse(url);
+        String scheme = parsed.getScheme();
+        if (!UrlConstants.HTTPS_SCHEME.equals(scheme)) {
+            return false;
+        }
+        String host = parsed.getHost();
+        if (host == null) {
+            return false;
+        }
+        String pathAndQuery = url.substring(UrlUtilities.stripPath(url).length());
+        for (String moduleManagedHost : moduleManagedHosts) {
+            if (host.equals(moduleManagedHost) && urlsPattern.matcher(pathAndQuery).matches()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void setTopBarHeight(int height) {
+        mTopBarDelegate.get().setTopBarHeight(height);
+        maybeCustomizeCctHeader(mIntentDataProvider.getUrlToLoad());
+    }
+
+    private int getTopBarHeight() {
+        Integer topBarHeight = mTopBarDelegate.get().getTopBarHeight();
+        // Custom top bar height must not be too small compared to the default top control container
+        // height, nor shall it be larger than the height of the web content.
+        if (topBarHeight != null && topBarHeight >= 0
+                && topBarHeight > mDefaultTopControlContainerHeight / 2
+                && mActivity.getWindow() != null
+                && topBarHeight < mActivity.getWindow().getDecorView().getHeight() / 2) {
+            return topBarHeight;
+        }
+        return mDefaultTopControlContainerHeight;
+    }
+
+    private void maybeCustomizeCctHeader(String url) {
+        if (!isModuleLoaded() && !isModuleLoading()) return;
+
+        boolean isModuleManagedUrl = isModuleManagedUrl(url);
+        mTopBarDelegate.get().showTopBarIfNecessary(isModuleManagedUrl);
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_MODULE_CUSTOM_HEADER)
+                && mIntentDataProvider.shouldHideCctHeaderOnModuleManagedUrls()) {
+            mActivity.getToolbarManager().setToolbarVisibility(
+                    isModuleManagedUrl ? View.GONE : mDefaultToolbarVisibility);
+            mActivity.getToolbarManager().setToolbarShadowVisibility(
+                    isModuleManagedUrl ? View.GONE : mDefaultToolbarShadowVisibility);
+            mActivity.getToolbarManager().setProgressBarEnabled(
+                    isModuleManagedUrl ? false : mDefaultIsProgressBarEnabled);
+            mFullscreenManager.get().setTopControlsHeight(
+                    isModuleManagedUrl ? getTopBarHeight() : mDefaultTopControlContainerHeight);
+        }
+    }
+
+    private void unregisterModuleObservers() {
+        unregisterObserver(mModuleNavigationEventObserver);
+        unregisterObserver(mHeaderVisibilityObserver);
+    }
+
+    private void unregisterObserver(TabObserver observer) {
+        mActivity.getActivityTab().removeObserver(observer);
+        mTabObserverRegistrar.unregisterTabObserver(observer);
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleEntryPoint.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleEntryPoint.java
index 6caf0c9..4746e9026d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleEntryPoint.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleEntryPoint.java
@@ -45,9 +45,9 @@
         return -1;
     }
 
-    public ActivityDelegate createActivityDelegate(ActivityHostImpl activityHost) {
+    public IActivityDelegate createActivityDelegate(IActivityHost.Stub activityHost) {
         try {
-            return new ActivityDelegate(mEntryPoint.createActivityDelegate(activityHost));
+            return mEntryPoint.createActivityDelegate(activityHost);
         } catch (RemoteException e) {
             assert false;
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesBackgroundTask.java b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesBackgroundTask.java
index dd2e2183..3a46c57 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesBackgroundTask.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesBackgroundTask.java
@@ -9,6 +9,7 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.UsedByReflection;
 import org.chromium.chrome.browser.background_task_scheduler.NativeBackgroundTask;
 import org.chromium.chrome.browser.background_task_scheduler.NativeBackgroundTask.StartBeforeNativeResult;
 import org.chromium.chrome.browser.offlinepages.DeviceConditions;
@@ -29,6 +30,7 @@
  * approximately daily so that freshness is maintained.
  */
 @JNINamespace("explore_sites")
+@UsedByReflection("BackgroundTaskReflection.java")
 public class ExploreSitesBackgroundTask extends NativeBackgroundTask {
     private static final String TAG = "ESBackgroundTask";
     public static final int DEFAULT_DELAY_HOURS = 25;
@@ -93,8 +95,18 @@
                 ContextUtils.getApplicationContext(), TaskIds.EXPLORE_SITES_REFRESH_JOB_ID);
     }
 
+    /**
+     * Cancels an obsolete task ID that was saved in JobScheduler with the wrong background task
+     * class name.
+     */
+    public static void cancelObsoleteTaskId() {
+        BackgroundTaskSchedulerFactory.getScheduler().cancel(ContextUtils.getApplicationContext(),
+                TaskIds.DEPRECATED_EXPLORE_SITES_REFRESH_JOB_ID);
+    }
+
     // Begins the periodic update task.
     public static void schedule(boolean updateCurrent) {
+        cancelObsoleteTaskId();
         TaskInfo.Builder taskInfoBuilder =
                 TaskInfo.createPeriodicTask(TaskIds.EXPLORE_SITES_REFRESH_JOB_ID,
                                 ExploreSitesBackgroundTask.class,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ActivityLifecycleDispatcher.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ActivityLifecycleDispatcher.java
index 9e2a7e2..13743d4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/init/ActivityLifecycleDispatcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ActivityLifecycleDispatcher.java
@@ -4,13 +4,17 @@
 
 package org.chromium.chrome.browser.init;
 
+import android.os.Bundle;
+
 import org.chromium.base.ObserverList;
 import org.chromium.chrome.browser.lifecycle.Destroyable;
 import org.chromium.chrome.browser.lifecycle.InflationObserver;
 import org.chromium.chrome.browser.lifecycle.LifecycleObserver;
 import org.chromium.chrome.browser.lifecycle.NativeInitObserver;
 import org.chromium.chrome.browser.lifecycle.PauseResumeWithNativeObserver;
+import org.chromium.chrome.browser.lifecycle.SaveInstanceStateObserver;
 import org.chromium.chrome.browser.lifecycle.StartStopWithNativeObserver;
+import org.chromium.chrome.browser.lifecycle.WindowFocusChangedObserver;
 
 /**
  * Dispatches lifecycle events of activities extending {@link AsyncInitializationActivity} to
@@ -24,6 +28,10 @@
     private final ObserverList<StartStopWithNativeObserver> mStartStopObservers =
             new ObserverList<>();
     private final ObserverList<Destroyable> mDestroyables = new ObserverList<>();
+    private final ObserverList<SaveInstanceStateObserver> mSaveInstanceStateObservers =
+            new ObserverList<>();
+    private final ObserverList<WindowFocusChangedObserver> mWindowFocusChangesObservers =
+            new ObserverList<>();
 
     /**
      * Registers an observer.
@@ -46,6 +54,12 @@
         if (observer instanceof Destroyable) {
             mDestroyables.addObserver((Destroyable) observer);
         }
+        if (observer instanceof SaveInstanceStateObserver) {
+            mSaveInstanceStateObservers.addObserver((SaveInstanceStateObserver) observer);
+        }
+        if (observer instanceof WindowFocusChangedObserver) {
+            mWindowFocusChangesObservers.addObserver((WindowFocusChangedObserver) observer);
+        }
     }
 
     /**
@@ -67,6 +81,12 @@
         if (observer instanceof Destroyable) {
             mDestroyables.removeObserver((Destroyable) observer);
         }
+        if (observer instanceof SaveInstanceStateObserver) {
+            mSaveInstanceStateObservers.removeObserver((SaveInstanceStateObserver) observer);
+        }
+        if (observer instanceof WindowFocusChangedObserver) {
+            mWindowFocusChangesObservers.removeObserver((WindowFocusChangedObserver) observer);
+        }
     }
 
     void dispatchPreInflationStartup() {
@@ -116,4 +136,16 @@
             destroyable.destroy();
         }
     }
+
+    void dispatchOnSaveInstanceState(Bundle outBundle) {
+        for (SaveInstanceStateObserver observer: mSaveInstanceStateObservers) {
+            observer.onSaveInstanceState(outBundle);
+        }
+    }
+
+    void dispatchOnWindowFocusChanged(boolean hasFocus) {
+        for (WindowFocusChangedObserver observer: mWindowFocusChangesObservers) {
+            observer.onWindowFocusChanged(hasFocus);
+        }
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java
index d779b3a..0b6cf52 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java
@@ -440,7 +440,7 @@
     /**
      * @return The saved bundle for the last recorded state.
      */
-    protected Bundle getSavedInstanceState() {
+    public Bundle getSavedInstanceState() {
         return mSavedInstanceState;
     }
 
@@ -643,6 +643,16 @@
     protected void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
         if (mWindowAndroid != null) mWindowAndroid.saveInstanceState(outState);
+
+        mLifecycleDispatcher.dispatchOnSaveInstanceState(outState);
+    }
+
+    @CallSuper
+    @Override
+    public void onWindowFocusChanged(boolean hasFocus) {
+        super.onWindowFocusChanged(hasFocus);
+
+        mLifecycleDispatcher.dispatchOnWindowFocusChanged(hasFocus);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/lifecycle/SaveInstanceStateObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/lifecycle/SaveInstanceStateObserver.java
new file mode 100644
index 0000000..a3d1333
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/lifecycle/SaveInstanceStateObserver.java
@@ -0,0 +1,21 @@
+// 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.lifecycle;
+
+import android.os.Bundle;
+
+import org.chromium.chrome.browser.init.ActivityLifecycleDispatcher;
+
+/**
+ * Implement this interface and register in {@link ActivityLifecycleDispatcher} to receive
+ * onSaveInstanceState events.
+ */
+public interface SaveInstanceStateObserver extends LifecycleObserver {
+
+    /**
+     * Called before activity begins to stop.
+     */
+    void onSaveInstanceState(Bundle outState);
+}
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/lifecycle/WindowFocusChangedObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/lifecycle/WindowFocusChangedObserver.java
new file mode 100644
index 0000000..624d1093
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/lifecycle/WindowFocusChangedObserver.java
@@ -0,0 +1,19 @@
+// 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.lifecycle;
+
+import org.chromium.chrome.browser.init.ActivityLifecycleDispatcher;
+
+/**
+ * Implement this interface and register in {@link ActivityLifecycleDispatcher} to receive
+ * onWindowFocusChange events.
+ */
+public interface WindowFocusChangedObserver extends LifecycleObserver {
+
+    /**
+     * Called when the current Window of the activity gains or loses focus.
+     */
+    void onWindowFocusChanged(boolean hasFocus);
+}
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
index 615a44c..8562921 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -55,6 +55,7 @@
 import org.chromium.chrome.browser.toolbar.ToolbarDataProvider;
 import org.chromium.chrome.browser.toolbar.ToolbarManager;
 import org.chromium.chrome.browser.toolbar.top.ToolbarActionModeCallback;
+import org.chromium.chrome.browser.util.AccessibilityUtil;
 import org.chromium.chrome.browser.util.ColorUtils;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.ui.base.DeviceFormFactor;
@@ -156,6 +157,7 @@
         mDeleteButton = findViewById(R.id.delete_button);
 
         mUrlBar = findViewById(R.id.url_bar);
+
         mUrlCoordinator = new UrlBarCoordinator((UrlBar) mUrlBar);
         mUrlCoordinator.setDelegate(this);
 
@@ -199,7 +201,8 @@
 
         setLayoutTransition(null);
 
-        mStatusViewCoordinator = new StatusViewCoordinator(mIsTablet, this, this);
+        mStatusViewCoordinator =
+                new StatusViewCoordinator(mIsTablet, findViewById(R.id.location_bar_status), this);
 
         mUrlBar.setOnKeyListener(new UrlBarKeyListener());
 
@@ -381,6 +384,15 @@
         }
 
         if (!inProgress) {
+            // The accessibility bounding box is not properly updated when focusing the Omnibox
+            // from the NTP fakebox.  Clearing/re-requesting focus triggers the bounding box to
+            // be recalculated.
+            if (didFocusUrlFromFakebox() && !inProgress && mUrlHasFocus
+                    && AccessibilityUtil.isAccessibilityEnabled()) {
+                mUrlBar.clearFocus();
+                mUrlBar.requestFocus();
+            }
+
             for (UrlFocusChangeListener listener : mUrlFocusChangeListeners) {
                 listener.onUrlAnimationFinished(mUrlHasFocus);
             }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusView.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusView.java
new file mode 100644
index 0000000..edc96a52
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusView.java
@@ -0,0 +1,56 @@
+// 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.omnibox.status;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import org.chromium.chrome.R;
+
+/**
+ * StatusView is a location bar's view displaying status (icons and/or text).
+ */
+public class StatusView extends LinearLayout {
+    private ImageView mNavigationButton;
+    private ImageButton mSecurityButton;
+    private TextView mVerboseStatusTextView;
+
+    public StatusView(Context context) {
+        super(context);
+    }
+
+    public StatusView(Context context, AttributeSet attributes) {
+        super(context, attributes);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+
+        mNavigationButton = findViewById(R.id.navigation_button);
+        mSecurityButton = findViewById(R.id.security_button);
+        mVerboseStatusTextView = findViewById(R.id.location_bar_verbose_status);
+
+        assert mNavigationButton != null : "Missing navigation type view.";
+    }
+
+    // TODO(ender): replace these with methods manipulating views directly.
+    // Do not depend on these when creating new code!
+    public ImageView getNavigationButton() {
+        return mNavigationButton;
+    }
+
+    public ImageButton getSecurityButton() {
+        return mSecurityButton;
+    }
+
+    public TextView getVerboseStatusTextView() {
+        return mVerboseStatusTextView;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusViewCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusViewCoordinator.java
index 74fed78..21663ed 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusViewCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusViewCoordinator.java
@@ -18,7 +18,6 @@
 import android.view.View;
 import android.widget.ImageButton;
 import android.widget.ImageView;
-import android.widget.TextView;
 
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.VisibleForTesting;
@@ -72,10 +71,7 @@
 
     private final Delegate mDelegate;
     private final boolean mIsTablet;
-    private final View mParentView;
-    private final ImageView mNavigationButton;
-    private final ImageButton mSecurityButton;
-    private final TextView mVerboseStatusTextView;
+    private final StatusView mStatusView;
 
     private final float mUrlMinWidth;
     private final float mVerboseStatusMinWidth;
@@ -107,63 +103,58 @@
     /**
      * Creates a new StatusViewCoordinator.
      * @param isTablet Whether the UI is shown on a tablet.
-     * @param parentView The parent view that contains the status view, used to retrieve views.
+     * @param statusView The status view, used to supply and manipulate child views.
      * @param delegate The delegate that provides additional information needed to display this
      *                 view.
      */
-    public StatusViewCoordinator(boolean isTablet, View parentView, Delegate delegate) {
+    public StatusViewCoordinator(boolean isTablet, StatusView statusView, Delegate delegate) {
         mIsTablet = isTablet;
-        mParentView = parentView;
+        mStatusView = statusView;
         mDelegate = delegate;
 
-        mNavigationButton = mParentView.findViewById(R.id.navigation_button);
-        assert mNavigationButton != null : "Missing navigation type view.";
         mNavigationButtonType = mIsTablet ? NavigationButtonType.PAGE : NavigationButtonType.EMPTY;
 
-        mSecurityButton = mParentView.findViewById(R.id.security_button);
         mSecurityIconResource = 0;
 
-        mVerboseStatusTextView = mParentView.findViewById(R.id.location_bar_verbose_status);
-
         mLocationBarButtonType = LocationBarButtonType.NONE;
-        mNavigationButton.setVisibility(View.INVISIBLE);
-        mSecurityButton.setVisibility(View.INVISIBLE);
+        mStatusView.getNavigationButton().setVisibility(View.INVISIBLE);
+        mStatusView.getSecurityButton().setVisibility(View.INVISIBLE);
 
         AnimatorListenerAdapter iconChangeAnimatorListener = new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
                 if (animation == mSecurityButtonShowAnimator) {
-                    mNavigationButton.setVisibility(View.INVISIBLE);
+                    mStatusView.getNavigationButton().setVisibility(View.INVISIBLE);
                 } else if (animation == mNavigationIconShowAnimator) {
-                    mSecurityButton.setVisibility(View.INVISIBLE);
+                    mStatusView.getSecurityButton().setVisibility(View.INVISIBLE);
                 }
             }
 
             @Override
             public void onAnimationStart(Animator animation) {
                 if (animation == mSecurityButtonShowAnimator) {
-                    mSecurityButton.setVisibility(View.VISIBLE);
+                    mStatusView.getSecurityButton().setVisibility(View.VISIBLE);
                 } else if (animation == mNavigationIconShowAnimator) {
-                    mNavigationButton.setVisibility(View.VISIBLE);
+                    mStatusView.getNavigationButton().setVisibility(View.VISIBLE);
                 }
             }
         };
 
         mSecurityButtonShowAnimator = new AnimatorSet();
         mSecurityButtonShowAnimator.playTogether(
-                ObjectAnimator.ofFloat(mNavigationButton, View.ALPHA, 0),
-                ObjectAnimator.ofFloat(mSecurityButton, View.ALPHA, 1));
+                ObjectAnimator.ofFloat(mStatusView.getNavigationButton(), View.ALPHA, 0),
+                ObjectAnimator.ofFloat(mStatusView.getSecurityButton(), View.ALPHA, 1));
         mSecurityButtonShowAnimator.setDuration(URL_FOCUS_CHANGE_ANIMATION_DURATION_MS);
         mSecurityButtonShowAnimator.addListener(iconChangeAnimatorListener);
 
         mNavigationIconShowAnimator = new AnimatorSet();
         mNavigationIconShowAnimator.playTogether(
-                ObjectAnimator.ofFloat(mNavigationButton, View.ALPHA, 1),
-                ObjectAnimator.ofFloat(mSecurityButton, View.ALPHA, 0));
+                ObjectAnimator.ofFloat(mStatusView.getNavigationButton(), View.ALPHA, 1),
+                ObjectAnimator.ofFloat(mStatusView.getSecurityButton(), View.ALPHA, 0));
         mNavigationIconShowAnimator.setDuration(URL_FOCUS_CHANGE_ANIMATION_DURATION_MS);
         mNavigationIconShowAnimator.addListener(iconChangeAnimatorListener);
 
-        Resources res = mParentView.getResources();
+        Resources res = mStatusView.getResources();
         mUrlMinWidth = res.getDimensionPixelSize(R.dimen.location_bar_min_url_width)
                 + res.getDimensionPixelSize(R.dimen.location_bar_start_icon_width)
                 + (res.getDimensionPixelSize(R.dimen.location_bar_lateral_padding) * 2);
@@ -195,9 +186,9 @@
      * Signals that native initialization has completed.
      */
     public void onNativeInitialized() {
-        mSecurityButton.setOnClickListener(this);
-        mNavigationButton.setOnClickListener(this);
-        mVerboseStatusTextView.setOnClickListener(this);
+        mStatusView.getSecurityButton().setOnClickListener(this);
+        mStatusView.getNavigationButton().setOnClickListener(this);
+        mStatusView.getVerboseStatusTextView().setOnClickListener(this);
     }
 
     /**
@@ -242,11 +233,11 @@
         View viewToBeShown = null;
         switch (mLocationBarButtonType) {
             case LocationBarButtonType.SECURITY_ICON:
-                viewToBeShown = mSecurityButton;
+                viewToBeShown = mStatusView.getSecurityButton();
                 mLocationBarIconActiveAnimator = mSecurityButtonShowAnimator;
                 break;
             case LocationBarButtonType.NAVIGATION_ICON:
-                viewToBeShown = mNavigationButton;
+                viewToBeShown = mStatusView.getNavigationButton();
                 mLocationBarIconActiveAnimator = mNavigationIconShowAnimator;
                 break;
             case LocationBarButtonType.NONE:
@@ -273,17 +264,17 @@
         @DrawableRes
         int id = mToolbarDataProvider.getSecurityIconResource(mIsTablet);
         if (id == 0) {
-            mSecurityButton.setImageDrawable(null);
+            mStatusView.getSecurityButton().setImageDrawable(null);
         } else {
             // ImageView#setImageResource is no-op if given resource is the current one.
-            mSecurityButton.setImageResource(id);
-            ApiCompatibilityUtils.setImageTintList(
-                    mSecurityButton, mToolbarDataProvider.getSecurityIconColorStateList());
+            mStatusView.getSecurityButton().setImageResource(id);
+            ApiCompatibilityUtils.setImageTintList(mStatusView.getSecurityButton(),
+                    mToolbarDataProvider.getSecurityIconColorStateList());
         }
 
         int contentDescriptionId = mToolbarDataProvider.getSecurityIconContentDescription();
-        String contentDescription = mParentView.getContext().getString(contentDescriptionId);
-        mSecurityButton.setContentDescription(contentDescription);
+        String contentDescription = mStatusView.getContext().getString(contentDescriptionId);
+        mStatusView.getSecurityButton().setContentDescription(contentDescription);
 
         updateVerboseStatusVisibility();
 
@@ -300,7 +291,7 @@
      * @return The view displaying the security icon.
      */
     public View getSecurityIconView() {
-        return mSecurityButton;
+        return mStatusView.getSecurityButton();
     }
 
     /**
@@ -325,30 +316,31 @@
      * @param buttonType The type of navigation button to be shown.
      */
     public void setNavigationButtonType(@NavigationButtonType int buttonType) {
+        ImageView navigationButton = mStatusView.getNavigationButton();
         // TODO(twellington): Return early if the navigation button type and tint hasn't changed.
         if (!mIsTablet) return;
         switch (buttonType) {
             case NavigationButtonType.PAGE:
-                Drawable page = TintedDrawable.constructTintedDrawable(mParentView.getContext(),
+                Drawable page = TintedDrawable.constructTintedDrawable(mStatusView.getContext(),
                         R.drawable.ic_omnibox_page,
                         mUseDarkColors ? R.color.dark_mode_tint : R.color.light_mode_tint);
-                mNavigationButton.setImageDrawable(page);
+                navigationButton.setImageDrawable(page);
                 break;
             case NavigationButtonType.MAGNIFIER:
-                Drawable search = TintedDrawable.constructTintedDrawable(mParentView.getContext(),
+                Drawable search = TintedDrawable.constructTintedDrawable(mStatusView.getContext(),
                         R.drawable.omnibox_search,
                         mUseDarkColors ? R.color.dark_mode_tint : R.color.light_mode_tint);
-                mNavigationButton.setImageDrawable(search);
+                navigationButton.setImageDrawable(search);
                 break;
             case NavigationButtonType.EMPTY:
-                mNavigationButton.setImageDrawable(null);
+                navigationButton.setImageDrawable(null);
                 break;
             default:
                 assert false;
         }
 
-        if (mNavigationButton.getVisibility() != View.VISIBLE) {
-            mNavigationButton.setVisibility(View.VISIBLE);
+        if (navigationButton.getVisibility() != View.VISIBLE) {
+            navigationButton.setVisibility(View.VISIBLE);
         }
         mNavigationButtonType = buttonType;
 
@@ -359,13 +351,14 @@
      * @param visible Whether the navigation button should be visible.
      */
     public void setSecurityButtonVisibility(boolean visible) {
-        if (!visible && mSecurityButton.getVisibility() == View.VISIBLE) {
-            mSecurityButton.setVisibility(View.GONE);
-        } else if (visible && mSecurityButton.getVisibility() == View.GONE
-                && mSecurityButton.getDrawable() != null
-                && mSecurityButton.getDrawable().getIntrinsicWidth() > 0
-                && mSecurityButton.getDrawable().getIntrinsicHeight() > 0) {
-            mSecurityButton.setVisibility(View.VISIBLE);
+        ImageButton securityButton = mStatusView.getSecurityButton();
+        if (!visible && securityButton.getVisibility() == View.VISIBLE) {
+            securityButton.setVisibility(View.GONE);
+        } else if (visible && securityButton.getVisibility() == View.GONE
+                && securityButton.getDrawable() != null
+                && securityButton.getDrawable().getIntrinsicWidth() > 0
+                && securityButton.getDrawable().getIntrinsicHeight() > 0) {
+            securityButton.setVisibility(View.VISIBLE);
         }
     }
 
@@ -379,12 +372,12 @@
 
         int verboseStatusVisibility = verboseStatusVisible ? View.VISIBLE : View.GONE;
 
-        mVerboseStatusTextView.setVisibility(verboseStatusVisibility);
+        mStatusView.getVerboseStatusTextView().setVisibility(verboseStatusVisibility);
 
-        View separator = mParentView.findViewById(R.id.location_bar_verbose_status_separator);
+        View separator = mStatusView.findViewById(R.id.location_bar_verbose_status_separator);
         separator.setVisibility(verboseStatusVisibility);
 
-        mParentView.findViewById(R.id.location_bar_verbose_status_extra_space)
+        mStatusView.findViewById(R.id.location_bar_verbose_status_extra_space)
                 .setVisibility(verboseStatusVisibility);
 
         if (!verboseStatusVisible) {
@@ -393,12 +386,14 @@
             return;
         }
 
-        mVerboseStatusTextView.setText(mToolbarDataProvider.getVerboseStatusString());
-        mVerboseStatusTextView.setTextColor(mToolbarDataProvider.getVerboseStatusTextColor(
-                mParentView.getResources(), mUseDarkColors));
+        mStatusView.getVerboseStatusTextView().setText(
+                mToolbarDataProvider.getVerboseStatusString());
+        mStatusView.getVerboseStatusTextView().setTextColor(
+                mToolbarDataProvider.getVerboseStatusTextColor(
+                        mStatusView.getResources(), mUseDarkColors));
 
         separator.setBackgroundColor(mToolbarDataProvider.getVerboseStatusSeparatorColor(
-                mParentView.getResources(), mUseDarkColors));
+                mStatusView.getResources(), mUseDarkColors));
     }
 
     /**
@@ -408,7 +403,7 @@
     protected void updateLocationBarIconContainerVisibility() {
         @LocationBarButtonType
         int buttonToShow = getLocationBarButtonToShow();
-        mParentView.findViewById(R.id.location_bar_icon)
+        mStatusView.findViewById(R.id.location_bar_icon)
                 .setVisibility(
                         buttonToShow != LocationBarButtonType.NONE ? View.VISIBLE : View.GONE);
     }
@@ -418,7 +413,8 @@
      * show the Page Info popup.
      */
     public boolean shouldShowPageInfoForView(View v) {
-        return v == mSecurityButton || v == mNavigationButton || v == mVerboseStatusTextView;
+        return v == mStatusView.getSecurityButton() || v == mStatusView.getNavigationButton()
+                || v == mStatusView.getVerboseStatusTextView();
     }
 
     @Override
@@ -463,7 +459,7 @@
             // Skip setting the max width if it hasn't changed since TextView#setMaxWidth
             // invalidates the view and requests a layout.
             if (previousMaxWidth != mVerboseStatusTextMaxWidth) {
-                mVerboseStatusTextView.setMaxWidth(mVerboseStatusTextMaxWidth);
+                mStatusView.getVerboseStatusTextView().setMaxWidth(mVerboseStatusTextMaxWidth);
             }
         }
 
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index 54833fa..269201a 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -125,6 +125,7 @@
   "java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessorySheetCoordinator.java",
   "java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessorySheetMediator.java",
   "java/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessorySheetViewBinder.java",
+  "java/src/org/chromium/chrome/browser/autofill_assistant/AbstractAutofillAssistantUiController.java",
   "java/src/org/chromium/chrome/browser/autofill_assistant/AnimatedProgressBar.java",
   "java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantFacade.java",
   "java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPaymentRequest.java",
@@ -451,8 +452,10 @@
   "java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityComponent.java",
   "java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityModule.java",
   "java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityDelegate.java",
+  "java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityDelegatePostMessageBackend.java",
   "java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityHostImpl.java",
   "java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleConstants.java",
+  "java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java",
   "java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleNavigationEventObserver.java",
   "java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleEntryPoint.java",
   "java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleHostImpl.java",
@@ -833,7 +836,9 @@
   "java/src/org/chromium/chrome/browser/lifecycle/LifecycleObserver.java",
   "java/src/org/chromium/chrome/browser/lifecycle/NativeInitObserver.java",
   "java/src/org/chromium/chrome/browser/lifecycle/PauseResumeWithNativeObserver.java",
+  "java/src/org/chromium/chrome/browser/lifecycle/SaveInstanceStateObserver.java",
   "java/src/org/chromium/chrome/browser/lifecycle/StartStopWithNativeObserver.java",
+  "java/src/org/chromium/chrome/browser/lifecycle/WindowFocusChangedObserver.java",
   "java/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelper.java",
   "java/src/org/chromium/chrome/browser/locale/DefaultSearchEnginePromoDialog.java",
   "java/src/org/chromium/chrome/browser/locale/LocaleChangedBroadcastReceiver.java",
@@ -1133,6 +1138,7 @@
   "java/src/org/chromium/chrome/browser/omnibox/geo/PlatformNetworksManager.java",
   "java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworks.java",
   "java/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTracker.java",
+  "java/src/org/chromium/chrome/browser/omnibox/status/StatusView.java",
   "java/src/org/chromium/chrome/browser/omnibox/status/StatusViewCoordinator.java",
   "java/src/org/chromium/chrome/browser/omnibox/suggestions/AnswerTextBuilder.java",
   "java/src/org/chromium/chrome/browser/omnibox/suggestions/AnswersImageFetcher.java",
@@ -1880,6 +1886,7 @@
   "javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/ManualFillingTestHelper.java",
   "javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessoryIntegrationTest.java",
   "javatests/src/org/chromium/chrome/browser/autofill/keyboard_accessory/PasswordAccessorySheetViewTest.java",
+  "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java",
   "javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java",
   "javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java",
   "javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkModelTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ServicificationBackgroundService.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ServicificationBackgroundService.java
index 15a7eb3..3997bee8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ServicificationBackgroundService.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ServicificationBackgroundService.java
@@ -9,10 +9,12 @@
 import org.junit.Assert;
 
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.library_loader.LibraryProcessType;
 import org.chromium.base.library_loader.ProcessInitException;
 import org.chromium.chrome.browser.init.BrowserParts;
 import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
 import org.chromium.chrome.browser.init.EmptyBrowserParts;
+import org.chromium.content_public.browser.BrowserStartupController;
 import org.chromium.content_public.browser.test.util.Criteria;
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
 
@@ -65,4 +67,19 @@
                     }
                 });
     }
+
+    public void postTaskAndVerifyFullBrowserNotStarted() {
+        // This task will always be queued and executed after
+        // the BrowserStartupControllerImpl#browserStartupComplete() is called on the UI thread when
+        // the full browser starts. So we can use it to checks whether the
+        // {@link mFullBrowserStartupDone} has been set to true.
+        ThreadUtils.postOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                Assert.assertFalse("The full browser is started instead of ServiceManager only.",
+                        BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER)
+                                .isStartupSuccessfullyCompleted());
+            }
+        });
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ServicificationBackgroundServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ServicificationBackgroundServiceTest.java
index 187f22d..0d2b2cc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ServicificationBackgroundServiceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ServicificationBackgroundServiceTest.java
@@ -45,13 +45,13 @@
         mServicificationBackgroundService.onRunTask(new TaskParams(taskTag));
         mServicificationBackgroundService.checkExpectations(shouldStart);
         mServicificationBackgroundService.waitForServiceManagerStart();
+        mServicificationBackgroundService.postTaskAndVerifyFullBrowserNotStarted();
     }
 
     @Test
     @MediumTest
     @Feature({"ServicificationStartup"})
-    @CommandLineFlags.
-    Add({"enable-features=NetworkService,NetworkServiceInProcess,AllowStartingServiceManagerOnly"})
+    @CommandLineFlags.Add({"enable-features=NetworkService,AllowStartingServiceManagerOnly"})
     public void testSeriveManagerStarts() {
         startOnRunTaskAndVerify(ServiceManagerStartupUtils.TASK_TAG, true);
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java
new file mode 100644
index 0000000..b285629
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java
@@ -0,0 +1,195 @@
+// 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.autofill_assistant;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.Intent;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.mockito.stubbing.Answer;
+
+import org.chromium.base.PathUtils;
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.base.library_loader.LibraryProcessType;
+import org.chromium.base.test.util.UrlUtils;
+import org.chromium.chrome.autofill_assistant.R;
+import org.chromium.chrome.browser.customtabs.CustomTabActivity;
+import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
+import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils;
+import org.chromium.chrome.browser.firstrun.FirstRunStatus;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.net.test.EmbeddedTestServer;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Instrumentation tests for autofill assistant UI.
+ */
+@RunWith(ChromeJUnit4ClassRunner.class)
+public class AutofillAssistantUiTest {
+    private String mTestPage;
+    private EmbeddedTestServer mTestServer;
+
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Mock
+    private AbstractAutofillAssistantUiController mControllerMock;
+    @Captor
+    private ArgumentCaptor<UiDelegateHolder> mUiDelegateHolderCaptor;
+    @Captor
+    private ArgumentCaptor<String> mLastSelectedScriptPathCaptor;
+
+    @Rule
+    public CustomTabActivityTestRule mCustomTabActivityTestRule = new CustomTabActivityTestRule();
+
+    @Before
+    public void setUp() throws Exception {
+        ThreadUtils.runOnUiThreadBlocking(() -> FirstRunStatus.setFirstRunFlowComplete(true));
+
+        mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext());
+        mTestPage = mTestServer.getURL(UrlUtils.getIsolatedTestFilePath(
+                "components/test/data/autofill_assistant/autofill_assistant_target_website.html"));
+        PathUtils.setPrivateDataDirectorySuffix("chrome");
+        LibraryLoader.getInstance().ensureInitialized(LibraryProcessType.PROCESS_BROWSER);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        ThreadUtils.runOnUiThreadBlocking(() -> FirstRunStatus.setFirstRunFlowComplete(false));
+        mTestServer.stopAndDestroyServer();
+    }
+
+    /**
+     * @see CustomTabsTestUtils#createMinimalCustomTabIntent(Context, String).
+     */
+    private Intent createMinimalCustomTabIntent() {
+        return CustomTabsTestUtils.createMinimalCustomTabIntent(
+                InstrumentationRegistry.getTargetContext(), mTestPage);
+    }
+
+    private View findViewByIdInMainCoordinator(int id) {
+        return getActivity().findViewById(R.id.coordinator).findViewById(id);
+    }
+
+    private CustomTabActivity getActivity() {
+        return mCustomTabActivityTestRule.getActivity();
+    }
+
+    // TODO(crbug.com/806868): Add more UI details test and check, like payment request UI,
+    // highlight chips and so on.
+    @Test
+    @MediumTest
+    public void testStartAndDismiss() throws InterruptedException {
+        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(createMinimalCustomTabIntent());
+
+        // Start autofill assistant UI. The first run screen must be shown first since the
+        // preference hasn't been set.
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> AutofillAssistantFacade.startInternal(getActivity(), mControllerMock));
+        View firstRunScreen = findViewByIdInMainCoordinator(R.id.init_screen);
+        Assert.assertNotNull(firstRunScreen);
+        Assert.assertTrue(firstRunScreen.isShown());
+        verify(mControllerMock, never()).init(any(), any());
+
+        // Accept on the first run screen so as to continue.
+        View initOkButton = firstRunScreen.findViewById(R.id.button_init_ok);
+        ThreadUtils.runOnUiThreadBlocking(() -> { initOkButton.performClick(); });
+        verify(mControllerMock, times(1))
+                .init(mUiDelegateHolderCaptor.capture(), any(Details.class));
+        Assert.assertNotNull(mUiDelegateHolderCaptor.getValue());
+
+        // Show and check status message.
+        String testStatusMessage = "test message";
+        ThreadUtils.runOnUiThreadBlocking(
+                ()
+                        -> mUiDelegateHolderCaptor.getValue().performUiOperation(
+                                uiDelegate -> uiDelegate.showStatusMessage(testStatusMessage)));
+        View bottomSheet = findViewByIdInMainCoordinator(R.id.autofill_assistant);
+        Assert.assertTrue(bottomSheet.isShown());
+        TextView statusMessageView = (TextView) bottomSheet.findViewById(R.id.status_message);
+        Assert.assertEquals(statusMessageView.getText(), testStatusMessage);
+
+        // Show overlay.
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> mUiDelegateHolderCaptor.getValue().performUiOperation(uiDelegate -> {
+                    uiDelegate.showOverlay();
+                    uiDelegate.disableProgressBarPulsing();
+                }));
+        View overlay = bottomSheet.findViewById(R.id.touch_event_filter);
+        Assert.assertTrue(overlay.isShown());
+
+        // Show scripts.
+        List<AutofillAssistantUiDelegate.ScriptHandle> scriptHandles = new ArrayList<>();
+        scriptHandles.add(
+                new AutofillAssistantUiDelegate.ScriptHandle("testScript1", false, "path1"));
+        scriptHandles.add(
+                new AutofillAssistantUiDelegate.ScriptHandle("testScript2", false, "path2"));
+        ThreadUtils.runOnUiThreadBlocking(
+                ()
+                        -> mUiDelegateHolderCaptor.getValue().performUiOperation(
+                                uiDelegate -> uiDelegate.updateScripts(scriptHandles)));
+        ViewGroup chipsViewContainer = (ViewGroup) bottomSheet.findViewById(R.id.carousel);
+        Assert.assertEquals(2, chipsViewContainer.getChildCount());
+
+        //  choose the first script.
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> { chipsViewContainer.getChildAt(0).performClick(); });
+        verify(mControllerMock, times(1)).onScriptSelected(mLastSelectedScriptPathCaptor.capture());
+        Assert.assertEquals("path1", mLastSelectedScriptPathCaptor.getValue());
+
+        // Show movie details.
+        String movieTitle = "testTitle";
+        String movieDescription = "This is a fancy test movie";
+        ThreadUtils.runOnUiThreadBlocking(
+                ()
+                        -> mUiDelegateHolderCaptor.getValue().performUiOperation(uiDelegate
+                                -> uiDelegate.showDetails(new Details(movieTitle, /* url = */ "",
+                                        Calendar.getInstance().getTime(), movieDescription,
+                                        /* mId = */ "",
+                                        /* isFinal= */ true, Collections.emptySet()))));
+        TextView detailsTitle = (TextView) bottomSheet.findViewById(R.id.details_title);
+        TextView detailsText = (TextView) bottomSheet.findViewById(R.id.details_text);
+        Assert.assertEquals(detailsTitle.getText(), movieTitle);
+        Assert.assertTrue(detailsText.getText().toString().contains(movieDescription));
+
+        // Progress bar must be shown.
+        Assert.assertTrue(bottomSheet.findViewById(R.id.progress_bar).isShown());
+
+        // Click 'X' button to graceful shutdown.
+        doAnswer((Answer<Void>) invocation -> {
+            mUiDelegateHolderCaptor.getValue().dismiss(R.string.autofill_assistant_stopped);
+            return null;
+        })
+                .when(mControllerMock)
+                .onDismiss();
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> { bottomSheet.findViewById(R.id.close_button).performClick(); });
+        Assert.assertFalse(bottomSheet.isShown());
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/OWNERS
new file mode 100644
index 0000000..829eb83
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/OWNERS
@@ -0,0 +1 @@
+file://components/autofill_assistant/OWNERS
\ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
index e56ab98..320aadd 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -90,6 +90,7 @@
 import org.chromium.chrome.browser.browserservices.BrowserSessionContentUtils;
 import org.chromium.chrome.browser.browserservices.Origin;
 import org.chromium.chrome.browser.browserservices.OriginVerifier;
+import org.chromium.chrome.browser.customtabs.dynamicmodule.DynamicModuleCoordinator;
 import org.chromium.chrome.browser.dependency_injection.ModuleFactoryOverrides;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.firstrun.FirstRunStatus;
@@ -1271,7 +1272,8 @@
         CriteriaHelper.pollUiThread(new Criteria() {
             @Override
             public boolean isSatisfied() {
-                return !cctActivity.isModuleLoading();
+                return !cctActivity.getComponent()
+                        .resolveDynamicModuleCoordinator().isModuleLoading();
             }
         });
 
@@ -1299,7 +1301,8 @@
         ThreadUtils.runOnUiThread(() -> {
             CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
             View anyView = new View(cctActivity);
-            cctActivity.setTopBarContentView(anyView);
+            cctActivity.getComponent().resolveDynamicModuleCoordinator()
+                    .setTopBarContentView(anyView);
             ViewGroup topBar = cctActivity.findViewById(R.id.topbar);
             Assert.assertNotNull(topBar);
             Assert.assertThat(anyView.getParent(), equalTo(topBar));
@@ -1317,13 +1320,14 @@
                 CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(moduleManagedUrl, null);
         mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
         waitForModuleLoading();
-
+        DynamicModuleCoordinator coordinator =
+                getActivity().getComponent().resolveDynamicModuleCoordinator();
         ThreadUtils.runOnUiThread(() -> {
             CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
             View anyView = new View(cctActivity);
-            cctActivity.setTopBarContentView(anyView);
+            coordinator.setTopBarContentView(anyView);
             // Second call will not crash.
-            cctActivity.setTopBarContentView(anyView);
+            coordinator.setTopBarContentView(anyView);
         });
     }
 
@@ -1343,7 +1347,6 @@
         ThreadUtils.runOnUiThread(() -> {
             CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
             View anyView = new View(cctActivity);
-            cctActivity.setTopBarContentView(anyView);
             ViewGroup topBar = cctActivity.findViewById(R.id.topbar);
             Assert.assertNull(topBar);
         });
@@ -1364,7 +1367,6 @@
         ThreadUtils.runOnUiThread(() -> {
             CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
             View anyView = new View(cctActivity);
-            cctActivity.setTopBarContentView(anyView);
             ViewGroup topBar = cctActivity.findViewById(R.id.topbar);
             Assert.assertNull(topBar);
         });
@@ -1387,7 +1389,8 @@
         ThreadUtils.runOnUiThread(() -> {
             CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
             View anyView = new View(cctActivity);
-            cctActivity.setTopBarContentView(anyView);
+            cctActivity.getComponent().resolveDynamicModuleCoordinator()
+                    .setTopBarContentView(anyView);
             ViewGroup topBar = cctActivity.findViewById(R.id.topbar);
             Assert.assertNull(topBar);
         });
@@ -1408,7 +1411,8 @@
         ThreadUtils.runOnUiThread(() -> {
             CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
             View anyView = new View(cctActivity);
-            cctActivity.setTopBarContentView(anyView);
+            cctActivity.getComponent().resolveDynamicModuleCoordinator()
+                    .setTopBarContentView(anyView);
             ViewGroup topBar = cctActivity.findViewById(R.id.topbar);
             Assert.assertNotNull(topBar);
             Assert.assertThat(anyView.getParent(), equalTo(topBar));
@@ -1433,7 +1437,6 @@
 
         ThreadUtils.runOnUiThread(() -> {
             CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
-            cctActivity.setTopBarContentView(new View(cctActivity));
             View toolbarView = cctActivity.findViewById(R.id.toolbar);
             Assert.assertTrue(
                     "A custom tab toolbar is never shown", toolbarView instanceof CustomTabToolbar);
@@ -1458,7 +1461,8 @@
 
         ThreadUtils.runOnUiThread(() -> {
             CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
-            cctActivity.setTopBarContentView(new View(cctActivity));
+            cctActivity.getComponent().resolveDynamicModuleCoordinator()
+                    .setTopBarContentView(new View(cctActivity));
             View toolbarView = cctActivity.findViewById(R.id.toolbar);
             Assert.assertTrue(
                     "A custom tab toolbar is never shown", toolbarView instanceof CustomTabToolbar);
@@ -1482,10 +1486,10 @@
                 CustomTabIntentDataProvider.EXTRA_MODULE_MANAGED_HOST_LIST, "www.google.com");
         mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
         waitForModuleLoading();
-
         ThreadUtils.runOnUiThread(() -> {
             CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
-            cctActivity.setTopBarContentView(new View(cctActivity));
+            cctActivity.getComponent().resolveDynamicModuleCoordinator()
+                    .setTopBarContentView(new View(cctActivity));
             View toolbarView = cctActivity.findViewById(R.id.toolbar);
             Assert.assertTrue(
                     "A custom tab toolbar is never shown", toolbarView instanceof CustomTabToolbar);
@@ -1510,7 +1514,8 @@
 
         ThreadUtils.runOnUiThread(() -> {
             CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
-            cctActivity.setTopBarContentView(new View(cctActivity));
+            cctActivity.getComponent().resolveDynamicModuleCoordinator()
+                    .setTopBarContentView(new View(cctActivity));
             ViewGroup toolbarContainerView = cctActivity.findViewById(R.id.toolbar_container);
             for (int index = 0; index < toolbarContainerView.getChildCount(); index++) {
                 View childView = toolbarContainerView.getChildAt(index);
@@ -1537,8 +1542,6 @@
         ThreadUtils.runOnUiThread(() -> {
             CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
             int defaultHeight = cctActivity.getFullscreenManager().getTopControlsHeight();
-            int newHeight = defaultHeight + 10;
-            cctActivity.setTopBarHeight(newHeight);
             Assert.assertEquals(
                     defaultHeight, cctActivity.getFullscreenManager().getTopControlsHeight());
         });
@@ -1561,7 +1564,7 @@
             CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
             int defaultHeight = cctActivity.getFullscreenManager().getTopControlsHeight();
             int newHeight = defaultHeight + 10;
-            cctActivity.setTopBarHeight(newHeight);
+            cctActivity.getComponent().resolveDynamicModuleCoordinator().setTopBarHeight(newHeight);
             Assert.assertEquals(
                     defaultHeight, cctActivity.getFullscreenManager().getTopControlsHeight());
         });
@@ -1584,7 +1587,7 @@
             CustomTabActivity cctActivity = mCustomTabActivityTestRule.getActivity();
             int defaultHeight = cctActivity.getFullscreenManager().getTopControlsHeight();
             int newHeight = defaultHeight + 10;
-            cctActivity.setTopBarHeight(newHeight);
+            cctActivity.getComponent().resolveDynamicModuleCoordinator().setTopBarHeight(newHeight);
             Assert.assertEquals(
                     newHeight, cctActivity.getFullscreenManager().getTopControlsHeight());
         });
@@ -2279,13 +2282,13 @@
         final String url =
                 mWebServer.setResponse("/test.html", TITLE_FROM_POSTMESSAGE_TO_CHANNEL, null);
 
-        Context context = InstrumentationRegistry.getTargetContext();
-        Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, url);
+        Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(url, null);
         mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
 
         ChromeTabUtils.waitForTabPageLoaded(getActivity().getActivityTab(), url);
-
-        getActivity().maybeInitialiseDynamicModulePostMessageHandler(new PostMessageBackend() {
+        DynamicModuleCoordinator coordinator =
+                getActivity().getComponent().resolveDynamicModuleCoordinator();
+        coordinator.maybeInitialiseDynamicModulePostMessageHandler(new PostMessageBackend() {
             @Override
             public boolean onPostMessage(String message, Bundle extras) {
                 return true;
@@ -2294,8 +2297,8 @@
             @Override
             public boolean onNotifyMessageChannelReady(Bundle extras) {
                 // Now attempt to post a message.
-                Assert.assertTrue(
-                        getActivity().postMessage("New title") == CustomTabsService.RESULT_SUCCESS);
+                Assert.assertEquals(coordinator.postMessage("New title"),
+                        CustomTabsService.RESULT_SUCCESS);
                 return true;
             }
 
@@ -2303,9 +2306,8 @@
             public void onDisconnectChannel(Context appContext) {}
         });
 
-        Assert.assertTrue(getActivity().requestPostMessageChannel(FAKE_ORIGIN_URI));
+        Assert.assertTrue(coordinator.requestPostMessageChannel(FAKE_ORIGIN_URI));
         // The callback registered above will post a message once the requested channel is ready.
-
         waitForTitle("New title");
     }
 
@@ -2314,19 +2316,21 @@
      */
     @Test
     @SmallTest
-    @EnableFeatures(ChromeFeatureList.CCT_MODULE_POST_MESSAGE)
+    @EnableFeatures({ChromeFeatureList.CCT_MODULE, ChromeFeatureList.CCT_MODULE_POST_MESSAGE})
     public void testPostMessageReceivedFromPageByDynamicModule() throws Exception {
         final CallbackHelper messageChannelHelper = new CallbackHelper();
         final CallbackHelper onPostMessageHelper = new CallbackHelper();
         final String url = mWebServer.setResponse("/test.html", MESSAGE_FROM_PAGE_TO_CHANNEL, null);
 
-        Context context = InstrumentationRegistry.getTargetContext();
-        Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, url);
+        Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(url, null);
         mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
 
         ChromeTabUtils.waitForTabPageLoaded(getActivity().getActivityTab(), url);
 
-        getActivity().maybeInitialiseDynamicModulePostMessageHandler(new PostMessageBackend() {
+        DynamicModuleCoordinator coordinator =
+                getActivity().getComponent().resolveDynamicModuleCoordinator();
+
+        coordinator.maybeInitialiseDynamicModulePostMessageHandler(new PostMessageBackend() {
             @Override
             public boolean onPostMessage(String message, Bundle extras) {
                 onPostMessageHelper.notifyCalled();
@@ -2340,10 +2344,10 @@
             }
 
             @Override
-            public void onDisconnectChannel(Context appContext) {}
+                public void onDisconnectChannel(Context appContext) {}
         });
 
-        Assert.assertTrue(getActivity().requestPostMessageChannel(FAKE_ORIGIN_URI));
+        Assert.assertTrue(coordinator.requestPostMessageChannel(FAKE_ORIGIN_URI));
         messageChannelHelper.waitForCallback();
         onPostMessageHelper.waitForCallback();
     }
@@ -2365,49 +2369,57 @@
 
         ChromeTabUtils.waitForTabPageLoaded(getActivity().getActivityTab(), url);
 
+        // If feature disabled dynamic module is not instantiated
+        DynamicModuleCoordinator coordinator =
+                getActivity().getComponent().resolveDynamicModuleCoordinator();
+
         // We shouldn't be able to open a channel or post messages yet.
-        Assert.assertFalse(getActivity().requestPostMessageChannel(FAKE_ORIGIN_URI));
-        Assert.assertTrue(getActivity().postMessage("Message")
+        Assert.assertFalse(coordinator
+                .requestPostMessageChannel(FAKE_ORIGIN_URI));
+        Assert.assertTrue(coordinator.postMessage("Message")
                 == CustomTabsService.RESULT_FAILURE_DISALLOWED);
 
         // Now fake initialisation of the dynamic module.
-        getActivity().maybeInitialiseDynamicModulePostMessageHandler(new PostMessageBackend() {
-            @Override
-            public boolean onPostMessage(String message, Bundle extras) {
-                onPostMessageHelper.notifyCalled();
-                return true;
-            }
+        coordinator.maybeInitialiseDynamicModulePostMessageHandler(
+                new PostMessageBackend() {
+                    @Override
+                    public boolean onPostMessage(String message, Bundle extras) {
+                        onPostMessageHelper.notifyCalled();
+                        return true;
+                    }
 
-            @Override
-            public boolean onNotifyMessageChannelReady(Bundle extras) {
-                messageChannelHelper.notifyCalled();
-                return true;
-            }
+                    @Override
+                    public boolean onNotifyMessageChannelReady(Bundle extras) {
+                        messageChannelHelper.notifyCalled();
+                        return true;
+                    }
 
-            @Override
-            public void onDisconnectChannel(Context appContext) {}
-        });
+                    @Override
+                    public void onDisconnectChannel(Context appContext) {}
+                });
 
         // We can now request a postMessage channel.
-        Assert.assertTrue(getActivity().requestPostMessageChannel(FAKE_ORIGIN_URI));
+        Assert.assertTrue(coordinator
+                .requestPostMessageChannel(FAKE_ORIGIN_URI));
     }
 
     @Test
     @SmallTest
+    @EnableFeatures(ChromeFeatureList.CCT_MODULE)
     @DisableFeatures(ChromeFeatureList.CCT_MODULE_POST_MESSAGE)
     public void testPostMessageFromDynamicModuleDisallowedWhenFeatureDisabled() throws Exception {
         final String url = mWebServer.setResponse("/test.html", MESSAGE_FROM_PAGE_TO_CHANNEL, null);
 
-        Context context = InstrumentationRegistry.getTargetContext();
-        Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, url);
+        Intent intent = CustomTabsDynamicModuleTestUtils.makeDynamicModuleIntent(url, null);
         mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
 
         ChromeTabUtils.waitForTabPageLoaded(getActivity().getActivityTab(), url);
-
+        DynamicModuleCoordinator coordinator = getActivity().getComponent()
+                .resolveDynamicModuleCoordinator();
         // We shouldn't be able to open a channel or post messages yet.
-        Assert.assertFalse(getActivity().requestPostMessageChannel(FAKE_ORIGIN_URI));
-        Assert.assertTrue(getActivity().postMessage("Message")
-                == CustomTabsService.RESULT_FAILURE_DISALLOWED);
+        Assert.assertFalse(coordinator.requestPostMessageChannel(FAKE_ORIGIN_URI));
+        Assert.assertEquals(coordinator.postMessage("Message"),
+                CustomTabsService.RESULT_FAILURE_DISALLOWED);
     }
 
     /**
@@ -3384,7 +3396,12 @@
         CriteriaHelper.pollUiThread(new Criteria() {
             @Override
             public boolean isSatisfied() {
-                return !mCustomTabActivityTestRule.getActivity().isModuleLoading();
+                if (!getActivity().getIntentDataProvider().isDynamicModuleEnabled()) return true;
+
+                DynamicModuleCoordinator module =
+                        mCustomTabActivityTestRule.getActivity().getComponent()
+                                .resolveDynamicModuleCoordinator();
+                return module != null && !module.isModuleLoading();
             }
         });
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsDynamicModuleNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsDynamicModuleNavigationTest.java
index 38a501af..e63784ab 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsDynamicModuleNavigationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsDynamicModuleNavigationTest.java
@@ -99,7 +99,8 @@
 
         CustomTabsDynamicModuleTestUtils.FakeCCTActivityDelegate activityDelegate =
                 (CustomTabsDynamicModuleTestUtils.FakeCCTActivityDelegate)
-                        cctActivity.getActivityDelegateForTesting();
+                        cctActivity.getComponent()
+                                .resolveDynamicModuleCoordinator().getActivityDelegateForTesting();
 
         activityDelegate.waitForNavigationEvent(CustomTabsCallback.NAVIGATION_STARTED,
                 0, 3);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/ServicificationDownloadTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/ServicificationDownloadTest.java
index f096afe6c..82554c6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/ServicificationDownloadTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/ServicificationDownloadTest.java
@@ -83,12 +83,12 @@
     @Test
     @LargeTest
     @Feature({"Download"})
-    @CommandLineFlags.
-    Add({"enable-features=NetworkService,NetworkServiceInProcess,AllowStartingServiceManagerOnly"})
+    @CommandLineFlags.Add({"enable-features=NetworkService,AllowStartingServiceManagerOnly"})
     public void testResumeInterruptedDownload() {
         mServicificationBackgroundService.onRunTask(
                 new TaskParams(ServiceManagerStartupUtils.TASK_TAG));
         mServicificationBackgroundService.waitForServiceManagerStart();
+        mServicificationBackgroundService.postTaskAndVerifyFullBrowserNotStarted();
 
         String tempFile = InstrumentationRegistry.getInstrumentation()
                                   .getTargetContext()
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java
index a64f6cb..0c2a458 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java
@@ -34,6 +34,7 @@
 
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.UrlUtils;
 import org.chromium.chrome.R;
@@ -200,6 +201,7 @@
     @Test
     @MediumTest
     @Feature({"FeedNewTabPage"})
+    @DisabledTest(message = "https://crbug.com/914068")
     public void testArticleSectionHeader() throws Exception {
         final int expectedCountWhenCollapsed = 2;
         final int expectedCountWhenExpanded = 4; // 3 header views and the empty view.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedRefreshTaskTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedRefreshTaskTest.java
index ed49c39..8cb22ead 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedRefreshTaskTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedRefreshTaskTest.java
@@ -114,9 +114,10 @@
     @SmallTest
     public void testCancelWakeUp() {
         ThreadUtils.runOnUiThreadBlocking(() -> {
-            Assert.assertEquals(0, mTaskScheduler.getCanceledTaskIds().size());
+            int initialCanceledTasks = mTaskScheduler.getCanceledTaskIds().size();
             FeedRefreshTask.cancelWakeUp();
-            Assert.assertEquals(1, mTaskScheduler.getCanceledTaskIds().size());
+            Assert.assertEquals(
+                    initialCanceledTasks + 1, mTaskScheduler.getCanceledTaskIds().size());
         });
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java
index 092bd8a..143613a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrInputTest.java
@@ -116,6 +116,7 @@
      * Tests that screen touches are not registered when in an immersive session. Disabled on
      * standalones because they don't have touchscreens.
      */
+    @DisabledTest(message = "https://crbug.com/913161")
     @Test
     @MediumTest
     @DisableIf
@@ -295,6 +296,7 @@
     /**
      * Tests that screen touches are registered as XR input when the viewer is Cardboard.
      */
+    @DisabledTest(message = "https://crbug.com/913161")
     @Test
     @MediumTest
     @Restriction(RESTRICTION_TYPE_VIEWER_NON_DAYDREAM)
@@ -346,6 +348,7 @@
      * Tests that focus is locked to the device with an immersive session for the purposes of
      * VR input.
      */
+    @DisabledTest(message = "https://crbug.com/913161")
     @Test
     @MediumTest
     @CommandLineFlags
@@ -585,6 +588,7 @@
      * WebXRGamepadSupport is not explicitly enabled. Correctness testing for
      * https://crbug.com/830935.
      */
+    @DisabledTest(message = "https://crbug.com/913161")
     @Test
     @MediumTest
     @Restriction(RESTRICTION_TYPE_VIEWER_NON_DAYDREAM)
@@ -602,6 +606,7 @@
      * Verifies that a Gamepad API gamepad is returned when using WebXR  and Daydream View if
      * WebXRGamepadSupport is explicitly enabled. Correctness testing for https://crbug.com/830935.
      */
+    @DisabledTest(message = "https://crbug.com/913161")
     @Test
     @MediumTest
     @Restriction(RESTRICTION_TYPE_VIEWER_DAYDREAM_OR_STANDALONE)
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java
index 04c5c59..9a1d162a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java
@@ -37,6 +37,7 @@
 import org.chromium.base.test.params.ParameterSet;
 import org.chromium.base.test.params.ParameterizedRunner;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.ChromeActivity;
@@ -104,6 +105,7 @@
     /**
      * Tests that a successful request for an immersive session actually enters VR.
      */
+    @DisabledTest(message = "https://crbug.com/913161")
     @Test
     @MediumTest
     @CommandLineFlags
@@ -328,6 +330,7 @@
     /**
      * Tests that the omnibox reappears after exiting an immersive session.
      */
+    @DisabledTest(message = "https://crbug.com/913161")
     @Test
     @MediumTest
     @CommandLineFlags
@@ -378,6 +381,7 @@
      * Tests that window.requestAnimationFrame stops firing while in a WebXR immersive session, but
      * resumes afterwards.
      */
+    @DisabledTest(message = "https://crbug.com/913161")
     @Test
     @MediumTest
     @CommandLineFlags
@@ -468,6 +472,7 @@
      * Tests that non-immersive sessions stop receiving rAFs during an immersive session, but resume
      * once the immersive session ends.
      */
+    @DisabledTest(message = "https://crbug.com/913161")
     @Test
     @MediumTest
     @CommandLineFlags
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/explore_sites/ExploreSitesBackgroundTaskUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/explore_sites/ExploreSitesBackgroundTaskUnitTest.java
index a3b70ed..73437f2 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/explore_sites/ExploreSitesBackgroundTaskUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/explore_sites/ExploreSitesBackgroundTaskUnitTest.java
@@ -198,4 +198,29 @@
         assertEquals(1, taskFinishedList.size());
         assertEquals(false, taskFinishedList.get(0));
     }
+
+    @Test
+    public void testRemovesDeprecatedJobId() throws Exception {
+        TaskInfo.Builder deprecatedTaskInfoBuilder =
+                TaskInfo.createPeriodicTask(TaskIds.DEPRECATED_EXPLORE_SITES_REFRESH_JOB_ID,
+                                ExploreSitesBackgroundTask.class, TimeUnit.HOURS.toMillis(4),
+                                TimeUnit.HOURS.toMillis(1))
+                        .setRequiredNetworkType(TaskInfo.NETWORK_TYPE_ANY)
+                        .setIsPersisted(true)
+                        .setUpdateCurrent(false);
+        mFakeTaskScheduler.schedule(
+                RuntimeEnvironment.application, deprecatedTaskInfoBuilder.build());
+        TaskInfo deprecatedTask =
+                mFakeTaskScheduler.getTaskInfo(TaskIds.DEPRECATED_EXPLORE_SITES_REFRESH_JOB_ID);
+        assertNotNull(deprecatedTask);
+
+        ExploreSitesBackgroundTask.schedule(false /* updateCurrent */);
+        TaskInfo scheduledTask =
+                mFakeTaskScheduler.getTaskInfo(TaskIds.EXPLORE_SITES_REFRESH_JOB_ID);
+        assertNotNull(scheduledTask);
+
+        deprecatedTask =
+                mFakeTaskScheduler.getTaskInfo(TaskIds.DEPRECATED_EXPLORE_SITES_REFRESH_JOB_ID);
+        assertNull(deprecatedTask);
+    }
 }
diff --git a/chrome/android/shared_preference_files/test/vr_ddview_skipdon_setupcomplete.json b/chrome/android/shared_preference_files/test/vr_ddview_skipdon_setupcomplete.json
index a255598..062695e 100644
--- a/chrome/android/shared_preference_files/test/vr_ddview_skipdon_setupcomplete.json
+++ b/chrome/android/shared_preference_files/test/vr_ddview_skipdon_setupcomplete.json
@@ -12,7 +12,9 @@
       "PairedControllerAddress": "FOO",
       "GvrPlatformLibraryPref": false,
       "EnableVrCoreHeadTracking": false,
-      "EnableDeveloperService": false
+      "EnableDeveloperService": false,
+      "gConfigFlags:enable_screen_capture": true,
+      "EnableAdbRecording": true
     }
   }
 ]
diff --git a/chrome/app/chrome_crash_reporter_client.cc b/chrome/app/chrome_crash_reporter_client.cc
index 659b5659..b84fff9 100644
--- a/chrome/app/chrome_crash_reporter_client.cc
+++ b/chrome/app/chrome_crash_reporter_client.cc
@@ -41,6 +41,11 @@
 #include "components/version_info/version_info.h"
 #endif
 
+void ChromeCrashReporterClient::Create() {
+  static base::NoDestructor<ChromeCrashReporterClient> crash_client;
+  crash_reporter::SetCrashReporterClient(crash_client.get());
+}
+
 ChromeCrashReporterClient::ChromeCrashReporterClient() {}
 
 ChromeCrashReporterClient::~ChromeCrashReporterClient() {}
diff --git a/chrome/app/chrome_crash_reporter_client.h b/chrome/app/chrome_crash_reporter_client.h
index db37f06b..fa5f6d7 100644
--- a/chrome/app/chrome_crash_reporter_client.h
+++ b/chrome/app/chrome_crash_reporter_client.h
@@ -11,13 +11,13 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
+#include "base/no_destructor.h"
 #include "build/build_config.h"
 #include "components/crash/content/app/crash_reporter_client.h"
 
 class ChromeCrashReporterClient : public crash_reporter::CrashReporterClient {
  public:
-  ChromeCrashReporterClient();
-  ~ChromeCrashReporterClient() override;
+  static void Create();
 
   // crash_reporter::CrashReporterClient implementation.
 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
@@ -59,6 +59,11 @@
   bool EnableBreakpadForProcess(const std::string& process_type) override;
 
  private:
+  friend class base::NoDestructor<ChromeCrashReporterClient>;
+
+  ChromeCrashReporterClient();
+  ~ChromeCrashReporterClient() override;
+
   DISALLOW_COPY_AND_ASSIGN(ChromeCrashReporterClient);
 };
 
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc
index 6a160d6..59884dc0 100644
--- a/chrome/app/chrome_main_delegate.cc
+++ b/chrome/app/chrome_main_delegate.cc
@@ -169,11 +169,6 @@
     g_chrome_content_utility_client = LAZY_INSTANCE_INITIALIZER;
 #endif
 
-#if defined(OS_POSIX)
-base::LazyInstance<ChromeCrashReporterClient>::Leaky g_chrome_crash_client =
-    LAZY_INSTANCE_INITIALIZER;
-#endif
-
 extern int NaClMain(const content::MainFunctionParams&);
 
 #if !defined(OS_CHROMEOS)
@@ -790,7 +785,7 @@
   crash_reporter::InitializeCrashKeys();
 
 #if defined(OS_POSIX)
-  crash_reporter::SetCrashReporterClient(g_chrome_crash_client.Pointer());
+  ChromeCrashReporterClient::Create();
 #endif
 
 #if defined(OS_MACOSX)
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 0a2ab19..381a398 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -3302,6 +3302,26 @@
     Please wait...
   </message>
 
+  <!-- Supervision transition OOBE screen. -->
+  <message name="IDS_REMOVING_SUPERVISION_TITLE" desc="Title of the supervision transition OOBE screen when stopping supervision.">
+    Stopping supervision...
+  </message>
+  <message name="IDS_ADDING_SUPERVISION_TITLE" desc="Title of the supervision transition OOBE screen when adding supervision.">
+    Setting up supervision...
+  </message>
+  <message name="IDS_SUPERVISION_TRANSITION_MESSAGE" desc="Introduction message for the supervision transition OOBE screen.">
+    Keep device turned on
+  </message>
+  <message name="IDS_SUPERVISION_TRANSITION_ERROR_TITLE" desc="Title of the supervision transition OOBE error screen.">
+    Something went wrong
+  </message>
+  <message name="IDS_SUPERVISION_TRANSITION_ERROR_MESSAGE" desc="Introduction message for the supervision transition OOBE error screen.">
+    Data from some apps may be lost
+  </message>
+  <message name="IDS_SUPERVISION_TRANSITION_ERROR_BUTTON" desc="Button label for acknowledging that supervision transition failed.">
+    OK
+  </message>
+
   <!-- Print Job Notification -->
   <message name="IDS_PRINT_JOB_NOTIFICATION_DISPLAY_SOURCE" desc="The context title of printing notification.">
     Print
diff --git a/chrome/app/chromeos_strings_grdp/IDS_ADDING_SUPERVISION_TITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_ADDING_SUPERVISION_TITLE.png.sha1
new file mode 100644
index 0000000..10498e1
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_ADDING_SUPERVISION_TITLE.png.sha1
@@ -0,0 +1 @@
+87a3260f32d7afdb64aaee3a6a9cd4cf9b8a2703
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_REMOVING_SUPERVISION_TITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_REMOVING_SUPERVISION_TITLE.png.sha1
new file mode 100644
index 0000000..20c9bdca
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_REMOVING_SUPERVISION_TITLE.png.sha1
@@ -0,0 +1 @@
+945a9188f00715d169a8b5a0cc4edc9c680666e9
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_SUPERVISION_TRANSITION_ERROR_BUTTON.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_SUPERVISION_TRANSITION_ERROR_BUTTON.png.sha1
new file mode 100644
index 0000000..76b55e9
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_SUPERVISION_TRANSITION_ERROR_BUTTON.png.sha1
@@ -0,0 +1 @@
+90bdaa3753fc18488ca98cb40dbb706cfebdf522
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_SUPERVISION_TRANSITION_ERROR_MESSAGE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_SUPERVISION_TRANSITION_ERROR_MESSAGE.png.sha1
new file mode 100644
index 0000000..76b55e9
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_SUPERVISION_TRANSITION_ERROR_MESSAGE.png.sha1
@@ -0,0 +1 @@
+90bdaa3753fc18488ca98cb40dbb706cfebdf522
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_SUPERVISION_TRANSITION_ERROR_TITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_SUPERVISION_TRANSITION_ERROR_TITLE.png.sha1
new file mode 100644
index 0000000..76b55e9
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_SUPERVISION_TRANSITION_ERROR_TITLE.png.sha1
@@ -0,0 +1 @@
+90bdaa3753fc18488ca98cb40dbb706cfebdf522
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_SUPERVISION_TRANSITION_MESSAGE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_SUPERVISION_TRANSITION_MESSAGE.png.sha1
new file mode 100644
index 0000000..10498e1
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_SUPERVISION_TRANSITION_MESSAGE.png.sha1
@@ -0,0 +1 @@
+87a3260f32d7afdb64aaee3a6a9cd4cf9b8a2703
\ No newline at end of file
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 3d51027..cead8a9 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -4876,6 +4876,27 @@
       <message name="IDS_NTP_CUSTOM_BG_PHOTO_SELECTED" desc="Label to indicate that a photo has been selected. (On the New Tab Page)">
        selected
       </message>
+      <message name="IDS_NTP_DOODLE_SHARE_LABEL" desc="The text label for the share button of a static or animated doodle that opens a sharing dialog.">
+        Share Doodle
+      </message>
+      <message name="IDS_NTP_DOODLE_SHARE_DIALOG_CLOSE_LABEL" desc="The text label for the close button on the doodle sharing dialog.">
+        Close
+      </message>
+      <message name="IDS_NTP_DOODLE_SHARE_DIALOG_FACEBOOK_LABEL" desc="The text label for the Facebook button on the doodle sharing dialog.">
+        Facebook
+      </message>
+      <message name="IDS_NTP_DOODLE_SHARE_DIALOG_TWITTER_LABEL" desc="The text label for the Twitter button on the doodle sharing dialog.">
+        Twitter
+      </message>
+      <message name="IDS_NTP_DOODLE_SHARE_DIALOG_MAIL_LABEL" desc="The text label for the mail button on the doodle sharing dialog.">
+        E-mail
+      </message>
+      <message name="IDS_NTP_DOODLE_SHARE_DIALOG_COPY_LABEL" desc="The text label for the copy link button on the doodle sharing dialog.">
+        Copy Link
+      </message>
+      <message name="IDS_NTP_DOODLE_SHARE_DIALOG_LINK_LABEL" desc="The text label for the share link text area on the doodle sharing dialog.">
+        Doodle Link
+      </message>
 
       <!--Tooltip strings-->
       <message name="IDS_TOOLTIP_BACK" desc="The tooltip for back button">
diff --git a/chrome/app/generated_resources_grd/IDS_NTP_DOODLE_SHARE_DIALOG_CLOSE_LABEL.png.sha1 b/chrome/app/generated_resources_grd/IDS_NTP_DOODLE_SHARE_DIALOG_CLOSE_LABEL.png.sha1
new file mode 100644
index 0000000..7939b0f
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_NTP_DOODLE_SHARE_DIALOG_CLOSE_LABEL.png.sha1
@@ -0,0 +1 @@
+61c4c0e2959a4a6cbd3ec5a608e26f1f68f6b698
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_NTP_DOODLE_SHARE_DIALOG_COPY_LABEL.png.sha1 b/chrome/app/generated_resources_grd/IDS_NTP_DOODLE_SHARE_DIALOG_COPY_LABEL.png.sha1
new file mode 100644
index 0000000..c14f4de
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_NTP_DOODLE_SHARE_DIALOG_COPY_LABEL.png.sha1
@@ -0,0 +1 @@
+5b4f517cec8a787cd6c03fc6273136b34b633a83
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_NTP_DOODLE_SHARE_DIALOG_FACEBOOK_LABEL.png.sha1 b/chrome/app/generated_resources_grd/IDS_NTP_DOODLE_SHARE_DIALOG_FACEBOOK_LABEL.png.sha1
new file mode 100644
index 0000000..f334336a
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_NTP_DOODLE_SHARE_DIALOG_FACEBOOK_LABEL.png.sha1
@@ -0,0 +1 @@
+82c61aaef7f071bdfae7b323969cb7091efe315e
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_NTP_DOODLE_SHARE_DIALOG_LINK_LABEL.png.sha1 b/chrome/app/generated_resources_grd/IDS_NTP_DOODLE_SHARE_DIALOG_LINK_LABEL.png.sha1
new file mode 100644
index 0000000..c3f868c
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_NTP_DOODLE_SHARE_DIALOG_LINK_LABEL.png.sha1
@@ -0,0 +1 @@
+27864239f00c1cb14fd4ebbb6cf0518dcc0a29d4
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_NTP_DOODLE_SHARE_DIALOG_MAIL_LABEL.png.sha1 b/chrome/app/generated_resources_grd/IDS_NTP_DOODLE_SHARE_DIALOG_MAIL_LABEL.png.sha1
new file mode 100644
index 0000000..bf1ae135
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_NTP_DOODLE_SHARE_DIALOG_MAIL_LABEL.png.sha1
@@ -0,0 +1 @@
+26281d0757c053f42bc8a84b66e95f2decb8d61b
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_NTP_DOODLE_SHARE_DIALOG_TWITTER_LABEL.png.sha1 b/chrome/app/generated_resources_grd/IDS_NTP_DOODLE_SHARE_DIALOG_TWITTER_LABEL.png.sha1
new file mode 100644
index 0000000..6f8358f
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_NTP_DOODLE_SHARE_DIALOG_TWITTER_LABEL.png.sha1
@@ -0,0 +1 @@
+77752048259a2f02cd7662c68a37384194e70d02
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_NTP_DOODLE_SHARE_LABEL.png.sha1 b/chrome/app/generated_resources_grd/IDS_NTP_DOODLE_SHARE_LABEL.png.sha1
new file mode 100644
index 0000000..633f5c1
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_NTP_DOODLE_SHARE_LABEL.png.sha1
@@ -0,0 +1 @@
+3c10f6aa7059b30d1bdde80cf18b56dc49da6697
\ No newline at end of file
diff --git a/chrome/app_shim/BUILD.gn b/chrome/app_shim/BUILD.gn
index 754f97a..7551180 100644
--- a/chrome/app_shim/BUILD.gn
+++ b/chrome/app_shim/BUILD.gn
@@ -11,6 +11,7 @@
 # Framework bundle.
 source_set("app_shim") {
   sources = [
+    "../app/chrome_crash_reporter_client.h",
     "app_shim_controller.h",
     "app_shim_controller.mm",
     "app_shim_delegate.h",
@@ -23,6 +24,7 @@
     "//chrome/browser/ui:ui",
     "//chrome/common",
     "//chrome/common:mojo_bindings",
+    "//components/crash/content/app",
     "//content/public/browser",
     "//ipc",
     "//mojo/core/embedder",
diff --git a/chrome/app_shim/DEPS b/chrome/app_shim/DEPS
index e8cc0435..c4ebe7b0 100644
--- a/chrome/app_shim/DEPS
+++ b/chrome/app_shim/DEPS
@@ -1,6 +1,8 @@
 include_rules = [
+  "+chrome/app/chrome_crash_reporter_client.h",
   "+chrome/browser/ui/cocoa",
   "+chrome/installer/launcher_support",
+  "+components/crash/content/app",
   "+content/public/browser",
   "+mojo/core/embedder",
 ]
diff --git a/chrome/app_shim/chrome_main_app_mode_mac.mm b/chrome/app_shim/chrome_main_app_mode_mac.mm
index 894e8df..1dbba3b 100644
--- a/chrome/app_shim/chrome_main_app_mode_mac.mm
+++ b/chrome/app_shim/chrome_main_app_mode_mac.mm
@@ -27,10 +27,12 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/threading/thread.h"
+#include "chrome/app/chrome_crash_reporter_client.h"
 #include "chrome/app_shim/app_shim_controller.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
+#include "components/crash/content/app/crashpad.h"
 #include "mojo/core/embedder/embedder.h"
 #include "mojo/core/embedder/scoped_ipc_support.h"
 #include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
@@ -183,6 +185,9 @@
   base::mac::SetOverrideFrameworkBundlePath(
       info->chrome_versioned_path.Append(chrome::kFrameworkName));
 
+  ChromeCrashReporterClient::Create();
+  crash_reporter::InitializeCrashpad(true, "app_shim");
+
   // Calculate the preferred locale used by Chrome.
   // We can't use l10n_util::OverrideLocaleWithCocoaLocale() because it calls
   // [base::mac::OuterBundle() preferredLocalizations] which gets localizations
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 5f9b71e..a1dfd9e9 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -3162,6 +3162,8 @@
       "metrics/perf/metric_collector.h",
       "metrics/perf/perf_output.cc",
       "metrics/perf/perf_output.h",
+      "metrics/perf/profile_provider_chromeos.cc",
+      "metrics/perf/profile_provider_chromeos.h",
       "metrics/perf/random_selector.cc",
       "metrics/perf/random_selector.h",
       "metrics/perf/windowed_incognito_observer.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 6a48bfd..fb50000d 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -714,40 +714,6 @@
      switches::kDisableSiteIsolation, ""},
 };
 
-const FeatureEntry::Choice kTLS13VariantChoices[] = {
-    {flags_ui::kGenericExperimentChoiceDefault, "", ""},
-    {flag_descriptions::kTLS13VariantDisabled, switches::kTLS13Variant,
-     switches::kTLS13VariantDisabled},
-    // The Draft 18 variant was deprecated.
-    {flag_descriptions::kTLS13VariantDeprecated, switches::kTLS13Variant,
-     switches::kTLS13VariantDisabled},
-    // The Experiment variant was deprecated.
-    {flag_descriptions::kTLS13VariantDeprecated, switches::kTLS13Variant,
-     switches::kTLS13VariantDisabled},
-    // The RecordType variant was deprecated.
-    {flag_descriptions::kTLS13VariantDeprecated, switches::kTLS13Variant,
-     switches::kTLS13VariantDisabled},
-    // The NoSessionID variant was deprecated.
-    {flag_descriptions::kTLS13VariantDeprecated, switches::kTLS13Variant,
-     switches::kTLS13VariantDisabled},
-    // The Experiment2 variant was deprecated.
-    {flag_descriptions::kTLS13VariantDeprecated, switches::kTLS13Variant,
-     switches::kTLS13VariantDisabled},
-    // The Experiment3 variant was deprecated.
-    {flag_descriptions::kTLS13VariantDeprecated, switches::kTLS13Variant,
-     switches::kTLS13VariantDisabled},
-    // The Draft22 variant was deprecated.
-    {flag_descriptions::kTLS13VariantDeprecated, switches::kTLS13Variant,
-     switches::kTLS13VariantDisabled},
-    {flag_descriptions::kTLS13VariantDraft23, switches::kTLS13Variant,
-     switches::kTLS13VariantDraft23},
-    // The Draft28 variant was deprecated.
-    {flag_descriptions::kTLS13VariantDeprecated, switches::kTLS13Variant,
-     switches::kTLS13VariantDisabled},
-    {flag_descriptions::kTLS13VariantFinal, switches::kTLS13Variant,
-     switches::kTLS13VariantFinal},
-};
-
 const FeatureEntry::FeatureParam kEnforceTLS13DowngradeKnownOnly[] = {
     {"known_roots_only", "true"}};
 
@@ -2514,9 +2480,6 @@
      flag_descriptions::kAutomaticTabDiscardingDescription, kOsWin | kOsMac,
      FEATURE_VALUE_TYPE(features::kAutomaticTabDiscarding)},
 #endif  // OS_WIN || OS_MACOSX
-    {"tls13-variant", flag_descriptions::kTLS13VariantName,
-     flag_descriptions::kTLS13VariantDescription, kOsAll,
-     MULTI_VALUE_TYPE(kTLS13VariantChoices)},
     {"enforce-tls13-downgrade", flag_descriptions::kEnforceTLS13DowngradeName,
      flag_descriptions::kEnforceTLS13DowngradeDescription, kOsAll,
      FEATURE_WITH_PARAMS_VALUE_TYPE(net::features::kEnforceTLS13Downgrade,
@@ -3170,13 +3133,6 @@
      FEATURE_VALUE_TYPE(chrome::android::kCustomContextMenu)},
 #endif  // OS_ANDROID
 
-#if defined(OS_CHROMEOS)
-    {"ash-disable-smooth-screen-rotation",
-     flag_descriptions::kAshDisableSmoothScreenRotationName,
-     flag_descriptions::kAshDisableSmoothScreenRotationDescription, kOsCrOS,
-     SINGLE_DISABLE_VALUE_TYPE(ash::switches::kAshDisableSmoothScreenRotation)},
-#endif  // OS_CHROMEOS
-
     {"omnibox-display-title-for-current-url",
      flag_descriptions::kOmniboxDisplayTitleForCurrentUrlName,
      flag_descriptions::kOmniboxDisplayTitleForCurrentUrlDescription, kOsAll,
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index 8de9f9c..9733b70c 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -599,8 +599,10 @@
 #endif
   }
 
+  // This wait is legitimate and necessary on Windows, since the process will
+  // be terminated soon.
   // http://crbug.com/125207
-  base::ThreadRestrictions::ScopedAllowWait allow_wait;
+  base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait;
 
   // We must write that the profile and metrics service shutdown cleanly,
   // otherwise on startup we'll think we crashed. So we block until done and
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 5c9e355..9fa7370 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -670,6 +670,7 @@
       </if>
       <if expr="chromeos">
         <include name="IDR_ASSISTANT_LOGO_PNG" file="resources\chromeos\assistant_optin\assistant_logo.png" type="BINDATA" />
+        <include name="IDR_SUPERVISION_ICON_PNG" file="resources\chromeos\supervision\supervision_icon.png" type="BINDATA" />
       </if>
       <if expr="safe_browsing_mode == 1">
         <include name="IDR_RESET_PASSWORD_HTML" file="resources\reset_password\reset_password.html" type="BINDATA" compress="gzip" />
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index fed90925..594393a 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -1230,6 +1230,9 @@
     "login/screens/reset_view.h",
     "login/screens/screen_exit_code.cc",
     "login/screens/screen_exit_code.h",
+    "login/screens/supervision_transition_screen.cc",
+    "login/screens/supervision_transition_screen.h",
+    "login/screens/supervision_transition_screen_view.h",
     "login/screens/sync_consent_screen.cc",
     "login/screens/sync_consent_screen.h",
     "login/screens/sync_consent_screen_view.h",
@@ -2039,6 +2042,8 @@
     "login/screens/mock_model_view_channel.h",
     "login/screens/mock_network_screen.cc",
     "login/screens/mock_network_screen.h",
+    "login/screens/mock_supervision_transition_screen.cc",
+    "login/screens/mock_supervision_transition_screen.h",
     "login/screens/mock_update_screen.cc",
     "login/screens/mock_update_screen.h",
     "login/screens/mock_welcome_screen.cc",
diff --git a/chrome/browser/chromeos/accessibility/ax_host_service.cc b/chrome/browser/chromeos/accessibility/ax_host_service.cc
index 49eee3b..ac9ebcb 100644
--- a/chrome/browser/chromeos/accessibility/ax_host_service.cc
+++ b/chrome/browser/chromeos/accessibility/ax_host_service.cc
@@ -48,7 +48,7 @@
   // Create the AXRemoteHostDelegate first so a tree ID will be assigned.
   auto remote_host_delegate =
       std::make_unique<AXRemoteHostDelegate>(this, std::move(remote_host_ptr));
-  ui::AXTreeID tree_id = remote_host_delegate->tree_id();
+  ui::AXTreeID tree_id = remote_host_delegate->ax_tree_id();
   DCHECK_NE(ui::AXTreeIDUnknown(), tree_id);
   DCHECK(!base::ContainsKey(remote_host_delegate_map_, tree_id));
   remote_host_delegate_map_[tree_id] = std::move(remote_host_delegate);
diff --git a/chrome/browser/chromeos/accessibility/ax_remote_host_delegate.cc b/chrome/browser/chromeos/accessibility/ax_remote_host_delegate.cc
index c41e543..d905cbb 100644
--- a/chrome/browser/chromeos/accessibility/ax_remote_host_delegate.cc
+++ b/chrome/browser/chromeos/accessibility/ax_remote_host_delegate.cc
@@ -19,7 +19,7 @@
   DCHECK(remote_host_ptr_);
 
   // AX tree ID is automatically assigned.
-  DCHECK_NE(tree_id(), ui::AXTreeIDUnknown());
+  DCHECK_NE(ax_tree_id(), ui::AXTreeIDUnknown());
 
   // Handle both clean and unclean shutdown of the remote app.
   remote_host_ptr_.set_connection_error_handler(base::BindOnce(
@@ -36,7 +36,7 @@
     const ui::AXTreeID& tree_id,
     const std::vector<ui::AXTreeUpdate>& updates,
     const ui::AXEvent& event) {
-  CHECK_EQ(tree_id, this->tree_id());
+  CHECK_EQ(tree_id, ax_tree_id());
   ExtensionMsg_AccessibilityEventBundleParams event_bundle;
   event_bundle.tree_id = tree_id;
   for (const ui::AXTreeUpdate& update : updates)
@@ -60,7 +60,7 @@
 
 void AXRemoteHostDelegate::OnRemoteHostDisconnected() {
   extensions::AutomationEventRouter::GetInstance()->DispatchTreeDestroyedEvent(
-      tree_id(), nullptr /* browser_context */);
-  host_service_->OnRemoteHostDisconnected(tree_id());
+      ax_tree_id(), nullptr /* browser_context */);
+  host_service_->OnRemoteHostDisconnected(ax_tree_id());
   // This object is now deleted.
 }
diff --git a/chrome/browser/chromeos/accessibility/speech_monitor.cc b/chrome/browser/chromeos/accessibility/speech_monitor.cc
index ef30b306..e041022 100644
--- a/chrome/browser/chromeos/accessibility/speech_monitor.cc
+++ b/chrome/browser/chromeos/accessibility/speech_monitor.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/chromeos/accessibility/speech_monitor.h"
 
-#include "chrome/browser/speech/tts_controller_delegate_impl.h"
+#include "content/public/browser/tts_controller.h"
 
 namespace chromeos {
 
@@ -16,11 +16,11 @@
 }  // namespace
 
 SpeechMonitor::SpeechMonitor() {
-  TtsControllerDelegateImpl::GetInstance()->SetTtsPlatform(this);
+  content::TtsController::GetInstance()->SetTtsPlatform(this);
 }
 
 SpeechMonitor::~SpeechMonitor() {
-  TtsControllerDelegateImpl::GetInstance()->SetTtsPlatform(
+  content::TtsController::GetInstance()->SetTtsPlatform(
       content::TtsPlatform::GetInstance());
 }
 
@@ -76,7 +76,7 @@
     const std::string& lang,
     const content::VoiceData& voice,
     const content::UtteranceContinuousParameters& params) {
-  TtsControllerDelegateImpl::GetInstance()->OnTtsEvent(
+  content::TtsController::GetInstance()->OnTtsEvent(
       utterance_id, content::TTS_EVENT_END, static_cast<int>(utterance.size()),
       std::string());
   return true;
@@ -116,7 +116,7 @@
     loop_runner_->Quit();
 }
 
-bool SpeechMonitor::LoadBuiltInTtsExtension(
+bool SpeechMonitor::LoadBuiltInTtsEngine(
     content::BrowserContext* browser_context) {
   return false;
 }
diff --git a/chrome/browser/chromeos/accessibility/speech_monitor.h b/chrome/browser/chromeos/accessibility/speech_monitor.h
index b194621..6812bae 100644
--- a/chrome/browser/chromeos/accessibility/speech_monitor.h
+++ b/chrome/browser/chromeos/accessibility/speech_monitor.h
@@ -53,8 +53,7 @@
   void WillSpeakUtteranceWithVoice(
       const content::Utterance* utterance,
       const content::VoiceData& voice_data) override;
-  bool LoadBuiltInTtsExtension(
-      content::BrowserContext* browser_context) override;
+  bool LoadBuiltInTtsEngine(content::BrowserContext* browser_context) override;
   std::string GetError() override;
   void ClearError() override;
   void SetError(const std::string& error) override;
diff --git a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
index 6e16da0..51ade2d9 100644
--- a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
+++ b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
@@ -276,7 +276,8 @@
   // Verify an AX tree was destroyed. It's awkward to get the remote app's
   // actual tree ID, so just ensure it's a valid ID and not the desktop.
   EXPECT_NE(ui::AXTreeIDUnknown(), destroyed_tree_id);
-  EXPECT_NE(ui::DesktopAXTreeID(), destroyed_tree_id);
+  EXPECT_NE(AutomationManagerAura::GetInstance()->ax_tree_id(),
+            destroyed_tree_id);
 
   extensions::AutomationEventRouter::GetInstance()
       ->SetTreeDestroyedCallbackForTest(base::DoNothing());
diff --git a/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.cc b/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.cc
index c33210fa..0281c4fa 100644
--- a/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.cc
+++ b/chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.cc
@@ -324,7 +324,7 @@
     if (GetProperty(AXStringProperty::PACKAGE_NAME, &package_name)) {
       const std::string& url =
           base::StringPrintf("%s/%s", package_name.c_str(),
-                             tree_source_->tree_id().ToString().c_str());
+                             tree_source_->ax_tree_id().ToString().c_str());
       out_data->AddStringAttribute(ax::mojom::StringAttribute::kUrl, url);
     }
   }
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
index d479682..48aff3c 100644
--- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
+++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
@@ -159,7 +159,7 @@
   }
 
   ExtensionMsg_AccessibilityEventBundleParams event_bundle;
-  event_bundle.tree_id = tree_id();
+  event_bundle.tree_id = ax_tree_id();
 
   event_bundle.events.emplace_back();
   ui::AXEvent& event = event_bundle.events.back();
@@ -193,7 +193,7 @@
 }
 
 bool AXTreeSourceArc::GetTreeData(ui::AXTreeData* data) const {
-  data->tree_id = tree_id();
+  data->tree_id = ax_tree_id();
   if (focused_id_ >= 0) {
     data->focus_id = focused_id_;
   } else if (root_id_ >= 0) {
@@ -431,7 +431,7 @@
   if (!router)
     return;
 
-  router->DispatchTreeDestroyedEvent(tree_id(), nullptr);
+  router->DispatchTreeDestroyedEvent(ax_tree_id(), nullptr);
 }
 
 }  // namespace arc
diff --git a/chrome/browser/chromeos/arc/tts/arc_tts_service.cc b/chrome/browser/chromeos/arc/tts/arc_tts_service.cc
index e9e25fe3..444bef5 100644
--- a/chrome/browser/chromeos/arc/tts/arc_tts_service.cc
+++ b/chrome/browser/chromeos/arc/tts/arc_tts_service.cc
@@ -8,7 +8,6 @@
 
 #include "base/logging.h"
 #include "base/memory/singleton.h"
-#include "chrome/browser/speech/tts_controller_delegate_impl.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "content/public/browser/tts_controller.h"
@@ -51,7 +50,7 @@
 
 ArcTtsService::ArcTtsService(content::BrowserContext* context,
                              ArcBridgeService* bridge_service)
-    : arc_bridge_service_(bridge_service), tts_controller_delegate_(nullptr) {
+    : arc_bridge_service_(bridge_service), tts_controller_(nullptr) {
   arc_bridge_service_->tts()->SetHost(this);
 }
 
@@ -63,12 +62,12 @@
                                mojom::TtsEventType event_type,
                                uint32_t char_index,
                                const std::string& error_msg) {
-  if (!tts_controller_delegate_) {
+  if (!tts_controller_) {
     // GetInstance() returns a base::Singleton<> object which always outlives
     // |this| object.
-    tts_controller_delegate_ = TtsControllerDelegateImpl::GetInstance();
-    if (!tts_controller_delegate_) {
-      LOG(WARNING) << "TtsControllerDelegateImpl is not available.";
+    tts_controller_ = content::TtsController::GetInstance();
+    if (!tts_controller_) {
+      LOG(WARNING) << "TtsController is not available.";
       return;
     }
   }
@@ -88,8 +87,7 @@
       chrome_event_type = content::TTS_EVENT_ERROR;
       break;
   }
-  tts_controller_delegate_->OnTtsEvent(id, chrome_event_type, char_index,
-                                       error_msg);
+  tts_controller_->OnTtsEvent(id, chrome_event_type, char_index, error_msg);
 }
 
 }  // namespace arc
diff --git a/chrome/browser/chromeos/arc/tts/arc_tts_service.h b/chrome/browser/chromeos/arc/tts/arc_tts_service.h
index 0dd49bf..c25efff 100644
--- a/chrome/browser/chromeos/arc/tts/arc_tts_service.h
+++ b/chrome/browser/chromeos/arc/tts/arc_tts_service.h
@@ -13,7 +13,7 @@
 
 namespace content {
 class BrowserContext;
-class TtsControllerDelegate;
+class TtsController;
 }  // namespace content
 
 namespace arc {
@@ -41,15 +41,14 @@
                   uint32_t char_index,
                   const std::string& error_msg) override;
 
-  void set_tts_controller_delegate_for_testing(
-      content::TtsControllerDelegate* tts_controller_delegate) {
-    tts_controller_delegate_ = tts_controller_delegate;
+  void set_tts_controller_for_testing(content::TtsController* tts_controller) {
+    tts_controller_ = tts_controller;
   }
 
  private:
   ArcBridgeService* const arc_bridge_service_;  // Owned by ArcServiceManager.
 
-  content::TtsControllerDelegate* tts_controller_delegate_;
+  content::TtsController* tts_controller_;
 
   DISALLOW_COPY_AND_ASSIGN(ArcTtsService);
 };
diff --git a/chrome/browser/chromeos/arc/tts/arc_tts_service_unittest.cc b/chrome/browser/chromeos/arc/tts/arc_tts_service_unittest.cc
index 88ad682..a9310b12 100644
--- a/chrome/browser/chromeos/arc/tts/arc_tts_service_unittest.cc
+++ b/chrome/browser/chromeos/arc/tts/arc_tts_service_unittest.cc
@@ -7,7 +7,6 @@
 #include <memory>
 
 #include "base/threading/platform_thread.h"
-#include "chrome/browser/speech/tts_controller_delegate_impl.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service_manager.h"
@@ -21,7 +20,7 @@
 
 namespace {
 
-class TestableTtsController : public TtsControllerDelegateImpl {
+class TestableTtsController : public content::TtsController {
  public:
   TestableTtsController() = default;
   ~TestableTtsController() override = default;
@@ -36,6 +35,28 @@
     last_error_message_ = error_message;
   }
 
+  // Unimplemented.
+  bool IsSpeaking() override { return false; }
+  void SpeakOrEnqueue(content::Utterance* utterance) override {}
+  void Stop() override {}
+  void Pause() override {}
+  void Resume() override {}
+  void GetVoices(content::BrowserContext* browser_context,
+                 std::vector<content::VoiceData>* out_voices) override {}
+  void VoicesChanged() override {}
+  void AddVoicesChangedDelegate(
+      content::VoicesChangedDelegate* delegate) override {}
+  void RemoveVoicesChangedDelegate(
+      content::VoicesChangedDelegate* delegate) override {}
+  void RemoveUtteranceEventDelegate(
+      content::UtteranceEventDelegate* delegate) override {}
+  void SetTtsEngineDelegate(content::TtsEngineDelegate* delegate) override {}
+  content::TtsEngineDelegate* GetTtsEngineDelegate() override {
+    return nullptr;
+  }
+  void SetTtsPlatform(content::TtsPlatform* tts_platform) override {}
+  int QueueSize() override { return 0; }
+
   int last_utterance_id_;
   content::TtsEventType last_event_type_;
   int last_char_index_;
@@ -53,8 +74,7 @@
         tts_controller_(std::make_unique<TestableTtsController>()),
         tts_service_(ArcTtsService::GetForBrowserContextForTesting(
             testing_profile_.get())) {
-    tts_service_->set_tts_controller_delegate_for_testing(
-        tts_controller_.get());
+    tts_service_->set_tts_controller_for_testing(tts_controller_.get());
   }
 
   ~ArcTtsServiceTest() override { tts_service_->Shutdown(); }
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc
index 93827a8..92963ec 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -750,6 +750,7 @@
 
 void ExistingUserController::OnEnrollmentOwnershipCheckCompleted(
     DeviceSettingsService::OwnershipStatus status) {
+  VLOG(1) << "OnEnrollmentOwnershipCheckCompleted status=" << status;
   if (status == DeviceSettingsService::OWNERSHIP_NONE) {
     ShowEnrollmentScreen();
   } else if (status == DeviceSettingsService::OWNERSHIP_TAKEN) {
@@ -760,6 +761,7 @@
             &ExistingUserController::OnEnrollmentOwnershipCheckCompleted,
             weak_factory_.GetWeakPtr(), status));
     if (trusted_status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
+      VLOG(1) << "Showing enrollment because device is PERMANENTLY_UNTRUSTED";
       ShowEnrollmentScreen();
     }
   } else {
diff --git a/chrome/browser/chromeos/login/oobe_screen.cc b/chrome/browser/chromeos/login/oobe_screen.cc
index 62c6d46d..14c2af9 100644
--- a/chrome/browser/chromeos/login/oobe_screen.cc
+++ b/chrome/browser/chromeos/login/oobe_screen.cc
@@ -51,6 +51,7 @@
     "encryption-migration",          // SCREEN_ENCRYPTION_MIGRATION
     "voice-interaction-value-prop",  // SCREEN_VOICE_INTERACTION_VALUE_PROP
     "wait-for-container-ready",      // SCREEN_WAIT_FOR_CONTAINTER_READY
+    "supervision-transition",        // SCREEN_SUPERVISION_TRANSITION
     "update-required",               // SCREEN_UPDATE_REQUIRED
     "assistant-optin-flow",          // SCREEN_ASSISTANT_OPTIN_FLOW
     "login",                         // SCREEN_SPECIAL_LOGIN
diff --git a/chrome/browser/chromeos/login/oobe_screen.h b/chrome/browser/chromeos/login/oobe_screen.h
index b6d263d..4dfcd12c 100644
--- a/chrome/browser/chromeos/login/oobe_screen.h
+++ b/chrome/browser/chromeos/login/oobe_screen.h
@@ -49,6 +49,7 @@
   SCREEN_ENCRYPTION_MIGRATION,
   SCREEN_VOICE_INTERACTION_VALUE_PROP,
   SCREEN_WAIT_FOR_CONTAINER_READY,
+  SCREEN_SUPERVISION_TRANSITION,
   SCREEN_UPDATE_REQUIRED,
   SCREEN_ASSISTANT_OPTIN_FLOW,
 
diff --git a/chrome/browser/chromeos/login/screen_manager.h b/chrome/browser/chromeos/login/screen_manager.h
index eb902c1..8221e0a 100644
--- a/chrome/browser/chromeos/login/screen_manager.h
+++ b/chrome/browser/chromeos/login/screen_manager.h
@@ -33,6 +33,7 @@
   friend class WizardControllerOobeResumeTest;
   friend class WizardControllerBrokenLocalStateTest;
   friend class WizardControllerOobeConfigurationTest;
+  friend class WizardControllerSupervisionTransitionOobeTest;
 
   // Created screens.
   std::map<OobeScreen, std::unique_ptr<BaseScreen>> screens_;
diff --git a/chrome/browser/chromeos/login/screens/mock_supervision_transition_screen.cc b/chrome/browser/chromeos/login/screens/mock_supervision_transition_screen.cc
new file mode 100644
index 0000000..1d9e7459
--- /dev/null
+++ b/chrome/browser/chromeos/login/screens/mock_supervision_transition_screen.cc
@@ -0,0 +1,39 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/screens/mock_supervision_transition_screen.h"
+
+using ::testing::_;
+using ::testing::AtLeast;
+
+namespace chromeos {
+
+MockSupervisionTransitionScreen::MockSupervisionTransitionScreen(
+    BaseScreenDelegate* base_screen_delegate,
+    SupervisionTransitionScreenView* view)
+    : SupervisionTransitionScreen(base_screen_delegate, view) {}
+
+MockSupervisionTransitionScreen::~MockSupervisionTransitionScreen() = default;
+
+MockSupervisionTransitionScreenView::MockSupervisionTransitionScreenView() {
+  EXPECT_CALL(*this, MockBind(_)).Times(AtLeast(1));
+}
+
+MockSupervisionTransitionScreenView::~MockSupervisionTransitionScreenView() {
+  if (screen_)
+    screen_->OnViewDestroyed(this);
+}
+
+void MockSupervisionTransitionScreenView::Bind(
+    SupervisionTransitionScreen* screen) {
+  screen_ = screen;
+  MockBind(screen);
+}
+
+void MockSupervisionTransitionScreenView::Unbind() {
+  screen_ = nullptr;
+  MockUnbind();
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screens/mock_supervision_transition_screen.h b/chrome/browser/chromeos/login/screens/mock_supervision_transition_screen.h
new file mode 100644
index 0000000..dba5b009
--- /dev/null
+++ b/chrome/browser/chromeos/login/screens/mock_supervision_transition_screen.h
@@ -0,0 +1,49 @@
+// Copyright (c) 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_CHROMEOS_LOGIN_SCREENS_MOCK_SUPERVISION_TRANSITION_SCREEN_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_MOCK_SUPERVISION_TRANSITION_SCREEN_H_
+
+#include "chrome/browser/chromeos/login/screens/base_screen_delegate.h"
+#include "chrome/browser/chromeos/login/screens/supervision_transition_screen.h"
+#include "chrome/browser/chromeos/login/screens/supervision_transition_screen_view.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace chromeos {
+
+class MockSupervisionTransitionScreen : public SupervisionTransitionScreen {
+ public:
+  MockSupervisionTransitionScreen(BaseScreenDelegate* base_screen_delegate,
+                                  SupervisionTransitionScreenView* view);
+  virtual ~MockSupervisionTransitionScreen();
+
+  MOCK_METHOD0(Show, void());
+  MOCK_METHOD0(Hide, void());
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockSupervisionTransitionScreen);
+};
+
+class MockSupervisionTransitionScreenView
+    : public SupervisionTransitionScreenView {
+ public:
+  MockSupervisionTransitionScreenView();
+  virtual ~MockSupervisionTransitionScreenView();
+
+  void Bind(SupervisionTransitionScreen* screen) override;
+  void Unbind() override;
+
+  MOCK_METHOD0(Show, void());
+  MOCK_METHOD0(Hide, void());
+  MOCK_METHOD1(MockBind, void(SupervisionTransitionScreen* screen));
+  MOCK_METHOD0(MockUnbind, void());
+
+ private:
+  SupervisionTransitionScreen* screen_ = nullptr;
+  DISALLOW_COPY_AND_ASSIGN(MockSupervisionTransitionScreenView);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_MOCK_SUPERVISION_TRANSITION_SCREEN_H_
diff --git a/chrome/browser/chromeos/login/screens/screen_exit_code.cc b/chrome/browser/chromeos/login/screens/screen_exit_code.cc
index e4207ce..f4b1351 100644
--- a/chrome/browser/chromeos/login/screens/screen_exit_code.cc
+++ b/chrome/browser/chromeos/login/screens/screen_exit_code.cc
@@ -104,6 +104,8 @@
       return "ASSISTANT_OPTIN_FLOW_FINISHED";
     case ScreenExitCode::MULTIDEVICE_SETUP_FINISHED:
       return "MULTIDEVICE_SETUP_FINISHED";
+    case ScreenExitCode::SUPERVISION_TRANSITION_FINISHED:
+      return "SUPERVISION_TRANSITION_FINISHED";
     case ScreenExitCode::EXIT_CODES_COUNT:
     default:
       NOTREACHED();
diff --git a/chrome/browser/chromeos/login/screens/screen_exit_code.h b/chrome/browser/chromeos/login/screens/screen_exit_code.h
index b509354b..d81a28c 100644
--- a/chrome/browser/chromeos/login/screens/screen_exit_code.h
+++ b/chrome/browser/chromeos/login/screens/screen_exit_code.h
@@ -74,6 +74,7 @@
   ASSISTANT_OPTIN_FLOW_FINISHED = 47,
   MULTIDEVICE_SETUP_FINISHED = 48,
   UPDATE_REJECT_OVER_CELLULAR = 49,
+  SUPERVISION_TRANSITION_FINISHED = 50,
   EXIT_CODES_COUNT  // not a real code, must be the last
 };
 
diff --git a/chrome/browser/chromeos/login/screens/supervision_transition_screen.cc b/chrome/browser/chromeos/login/screens/supervision_transition_screen.cc
new file mode 100644
index 0000000..9c4525e
--- /dev/null
+++ b/chrome/browser/chromeos/login/screens/supervision_transition_screen.cc
@@ -0,0 +1,47 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/screens/supervision_transition_screen.h"
+
+#include "chrome/browser/chromeos/login/screens/base_screen_delegate.h"
+#include "chrome/browser/chromeos/login/screens/supervision_transition_screen_view.h"
+
+namespace chromeos {
+
+SupervisionTransitionScreen::SupervisionTransitionScreen(
+    BaseScreenDelegate* base_screen_delegate,
+    SupervisionTransitionScreenView* view)
+    : BaseScreen(base_screen_delegate,
+                 OobeScreen::SCREEN_SUPERVISION_TRANSITION),
+      view_(view) {
+  if (view_)
+    view_->Bind(this);
+}
+
+SupervisionTransitionScreen::~SupervisionTransitionScreen() {
+  if (view_)
+    view_->Unbind();
+}
+
+void SupervisionTransitionScreen::Show() {
+  if (view_)
+    view_->Show();
+}
+
+void SupervisionTransitionScreen::Hide() {
+  if (view_)
+    view_->Hide();
+}
+
+void SupervisionTransitionScreen::OnViewDestroyed(
+    SupervisionTransitionScreenView* view) {
+  if (view_ == view)
+    view_ = nullptr;
+}
+
+void SupervisionTransitionScreen::OnSupervisionTransitionFinished() {
+  Finish(ScreenExitCode::SUPERVISION_TRANSITION_FINISHED);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screens/supervision_transition_screen.h b/chrome/browser/chromeos/login/screens/supervision_transition_screen.h
new file mode 100644
index 0000000..44ccb624
--- /dev/null
+++ b/chrome/browser/chromeos/login/screens/supervision_transition_screen.h
@@ -0,0 +1,42 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_SUPERVISION_TRANSITION_SCREEN_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_SUPERVISION_TRANSITION_SCREEN_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "chrome/browser/chromeos/login/screens/base_screen.h"
+
+namespace chromeos {
+
+class SupervisionTransitionScreenView;
+class BaseScreenDelegate;
+
+class SupervisionTransitionScreen : public BaseScreen {
+ public:
+  SupervisionTransitionScreen(BaseScreenDelegate* base_screen_delegate,
+                              SupervisionTransitionScreenView* view);
+  ~SupervisionTransitionScreen() override;
+
+  // BaseScreen:
+  void Show() override;
+  void Hide() override;
+
+  // Called when view is destroyed so there's no dead reference to it.
+  void OnViewDestroyed(SupervisionTransitionScreenView* view_);
+
+  // Called when transition has finished, exits the screen.
+  void OnSupervisionTransitionFinished();
+
+ private:
+  SupervisionTransitionScreenView* view_;
+
+  DISALLOW_COPY_AND_ASSIGN(SupervisionTransitionScreen);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_SUPERVISION_TRANSITION_SCREEN_H_
diff --git a/chrome/browser/chromeos/login/screens/supervision_transition_screen_view.h b/chrome/browser/chromeos/login/screens/supervision_transition_screen_view.h
new file mode 100644
index 0000000..6b6fadd
--- /dev/null
+++ b/chrome/browser/chromeos/login/screens/supervision_transition_screen_view.h
@@ -0,0 +1,37 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_SUPERVISION_TRANSITION_SCREEN_VIEW_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_SUPERVISION_TRANSITION_SCREEN_VIEW_H_
+
+#include "chrome/browser/chromeos/login/oobe_screen.h"
+
+namespace chromeos {
+
+class SupervisionTransitionScreen;
+
+// Interface for dependency injection between SupervisionTransitionScreen
+// and its WebUI representation.
+class SupervisionTransitionScreenView {
+ public:
+  constexpr static OobeScreen kScreenId =
+      OobeScreen::SCREEN_SUPERVISION_TRANSITION;
+
+  virtual ~SupervisionTransitionScreenView() {}
+
+  virtual void Bind(SupervisionTransitionScreen* screen) = 0;
+  virtual void Unbind() = 0;
+  virtual void Show() = 0;
+  virtual void Hide() = 0;
+
+ protected:
+  SupervisionTransitionScreenView() = default;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(SupervisionTransitionScreenView);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_SUPERVISION_TRANSITION_SCREEN_VIEW_H_
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc
index 5877027..8adabc9c 100644
--- a/chrome/browser/chromeos/login/session/user_session_manager.cc
+++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -1674,6 +1674,11 @@
 
       ActivateWizard(OobeScreen::SCREEN_TERMS_OF_SERVICE);
       return false;
+    } else if (!user_manager->IsCurrentUserNew() &&
+               arc::GetSupervisionTransition(profile) !=
+                   arc::ArcSupervisionTransition::NO_TRANSITION) {
+      ActivateWizard(OobeScreen::SCREEN_SUPERVISION_TRANSITION);
+      return false;
     }
   }
 
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc
index 7158f93..ab531289 100644
--- a/chrome/browser/chromeos/login/wizard_controller.cc
+++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -64,6 +64,7 @@
 #include "chrome/browser/chromeos/login/screens/network_screen.h"
 #include "chrome/browser/chromeos/login/screens/recommend_apps_screen.h"
 #include "chrome/browser/chromeos/login/screens/reset_screen.h"
+#include "chrome/browser/chromeos/login/screens/supervision_transition_screen.h"
 #include "chrome/browser/chromeos/login/screens/sync_consent_screen.h"
 #include "chrome/browser/chromeos/login/screens/terms_of_service_screen.h"
 #include "chrome/browser/chromeos/login/screens/update_required_screen.h"
@@ -521,6 +522,9 @@
   } else if (screen == OobeScreen::SCREEN_WAIT_FOR_CONTAINER_READY) {
     return std::make_unique<WaitForContainerReadyScreen>(
         this, oobe_ui->GetWaitForContainerReadyScreenView());
+  } else if (screen == OobeScreen::SCREEN_SUPERVISION_TRANSITION) {
+    return std::make_unique<SupervisionTransitionScreen>(
+        this, oobe_ui->GetSupervisionTransitionScreenView());
   } else if (screen == OobeScreen::SCREEN_UPDATE_REQUIRED) {
     return std::make_unique<UpdateRequiredScreen>(
         this, oobe_ui->GetUpdateRequiredScreenView());
@@ -810,6 +814,13 @@
   SetCurrentScreen(GetScreen(OobeScreen::SCREEN_WAIT_FOR_CONTAINER_READY));
 }
 
+void WizardController::ShowSupervisionTransitionScreen() {
+  VLOG(1) << "Showing supervision transition screen.";
+  UpdateStatusAreaVisibilityForScreen(
+      OobeScreen::SCREEN_SUPERVISION_TRANSITION);
+  SetCurrentScreen(GetScreen(OobeScreen::SCREEN_SUPERVISION_TRANSITION));
+}
+
 void WizardController::ShowUpdateRequiredScreen() {
   SetCurrentScreen(GetScreen(OobeScreen::SCREEN_UPDATE_REQUIRED));
 }
@@ -1151,6 +1162,10 @@
   StartVoiceInteractionSetupWizard();
 }
 
+void WizardController::OnSupervisionTransitionFinished() {
+  OnOobeFlowFinished();
+}
+
 void WizardController::OnAssistantOptInFlowFinished() {
   ShowMultiDeviceSetupScreen();
 }
@@ -1199,7 +1214,8 @@
 }
 
 void WizardController::OnOobeFlowFinished() {
-  if (is_in_session_oobe_) {
+  if (is_in_session_oobe_ && current_screen_->screen_id() !=
+                                 OobeScreen::SCREEN_SUPERVISION_TRANSITION) {
     GetLoginDisplayHost()->SetStatusAreaVisible(true);
     GetLoginDisplayHost()->Finalize(base::OnceClosure());
     return;
@@ -1241,6 +1257,14 @@
   } else if (skip_update_enroll_after_eula_ ||
              prescribed_enrollment_config_.should_enroll() ||
              configuration_forced_enrollment) {
+    VLOG(1) << "StartEnrollment from OnDeviceDisabledChecked(device_disabled="
+            << device_disabled << ") "
+            << "skip_update_enroll_after_eula_="
+            << skip_update_enroll_after_eula_
+            << ", prescribed_enrollment_config_.should_enroll()="
+            << prescribed_enrollment_config_.should_enroll()
+            << ", configuration_forced_enrollment="
+            << configuration_forced_enrollment;
     StartEnrollmentScreen(skip_update_enroll_after_eula_);
   } else {
     PerformOOBECompletedActions();
@@ -1398,6 +1422,7 @@
              screen == OobeScreen::SCREEN_KIOSK_AUTOLAUNCH ||
              screen == OobeScreen::SCREEN_OOBE_ENABLE_DEBUGGING ||
              screen == OobeScreen::SCREEN_WRONG_HWID ||
+             screen == OobeScreen::SCREEN_SUPERVISION_TRANSITION ||
              screen == OobeScreen::SCREEN_ARC_KIOSK_SPLASH ||
              screen == OobeScreen::SCREEN_OOBE_CONTROLLER_PAIRING ||
              screen == OobeScreen::SCREEN_OOBE_HOST_PAIRING) {
@@ -1509,6 +1534,8 @@
     ShowFingerprintSetupScreen();
   } else if (screen == OobeScreen::SCREEN_MARKETING_OPT_IN) {
     ShowMarketingOptInScreen();
+  } else if (screen == OobeScreen::SCREEN_SUPERVISION_TRANSITION) {
+    ShowSupervisionTransitionScreen();
   } else if (screen != OobeScreen::SCREEN_TEST_NO_WINDOW) {
     if (is_out_of_box_) {
       time_oobe_started_ = base::Time::Now();
@@ -1697,6 +1724,9 @@
     case ScreenExitCode::MULTIDEVICE_SETUP_FINISHED:
       OnMultiDeviceSetupFinished();
       break;
+    case ScreenExitCode::SUPERVISION_TRANSITION_FINISHED:
+      OnSupervisionTransitionFinished();
+      break;
     default:
       NOTREACHED();
   }
diff --git a/chrome/browser/chromeos/login/wizard_controller.h b/chrome/browser/chromeos/login/wizard_controller.h
index 589e922..601fba2 100644
--- a/chrome/browser/chromeos/login/wizard_controller.h
+++ b/chrome/browser/chromeos/login/wizard_controller.h
@@ -195,6 +195,7 @@
   void ShowEncryptionMigrationScreen();
   void ShowVoiceInteractionValuePropScreen();
   void ShowWaitForContainerReadyScreen();
+  void ShowSupervisionTransitionScreen();
   void ShowUpdateRequiredScreen();
   void ShowAssistantOptInFlowScreen();
   void ShowMultiDeviceSetupScreen();
@@ -247,6 +248,7 @@
   void OnDemoPreferencesContinued();
   void OnDemoPreferencesCanceled();
   void OnWaitForContainerReadyFinished();
+  void OnSupervisionTransitionFinished();
   void OnAssistantOptInFlowFinished();
   void OnMultiDeviceSetupFinished();
   void OnOobeFlowFinished();
@@ -469,6 +471,7 @@
   friend class WizardControllerFlowTest;
   friend class WizardControllerOobeConfigurationTest;
   friend class WizardControllerOobeResumeTest;
+  friend class WizardControllerSupervisionTransitionOobeTest;
 
   std::unique_ptr<AccessibilityStatusSubscription> accessibility_subscription_;
 
diff --git a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
index 13a3c9f..c9d9fcd 100644
--- a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
+++ b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
@@ -38,6 +38,7 @@
 #include "chrome/browser/chromeos/login/screens/mock_enable_debugging_screen.h"
 #include "chrome/browser/chromeos/login/screens/mock_eula_screen.h"
 #include "chrome/browser/chromeos/login/screens/mock_network_screen.h"
+#include "chrome/browser/chromeos/login/screens/mock_supervision_transition_screen.h"
 #include "chrome/browser/chromeos/login/screens/mock_update_screen.h"
 #include "chrome/browser/chromeos/login/screens/mock_welcome_screen.h"
 #include "chrome/browser/chromeos/login/screens/mock_wrong_hwid_screen.h"
@@ -64,6 +65,7 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/testing_profile.h"
 #include "chromeos/audio/cras_audio_handler.h"
 #include "chromeos/chromeos_switches.h"
 #include "chromeos/chromeos_test_utils.h"
@@ -84,6 +86,8 @@
 #include "components/prefs/pref_service.h"
 #include "components/prefs/pref_service_factory.h"
 #include "components/prefs/testing_pref_store.h"
+#include "components/session_manager/core/session_manager.h"
+#include "components/session_manager/session_manager_types.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
@@ -481,6 +485,68 @@
             cras->GetOutputVolumePercent());
 }
 
+class WizardControllerSupervisionTransitionOobeTest
+    : public WizardControllerTest {
+ protected:
+  WizardControllerSupervisionTransitionOobeTest() = default;
+
+  void SetUpOnMainThread() override {
+    WizardControllerTest::SetUpOnMainThread();
+    // Setup existing user session and profile.
+    const AccountId test_account_id_ =
+        AccountId::FromUserEmailGaiaId("test@gmail.com", "123456");
+    session_manager::SessionManager::Get()->CreateSession(
+        test_account_id_, test_account_id_.GetUserEmail(),
+        /* is_child= */ false);
+    ProfileHelper::Get()->GetProfileByUserIdHashForTest(
+        test_account_id_.GetUserEmail());
+    // Pretend OOBE was complete.
+    StartupUtils::MarkOobeCompleted();
+
+    WizardController::default_controller()->is_official_build_ = true;
+    MOCK(mock_supervision_transition_screen_,
+         OobeScreen::SCREEN_SUPERVISION_TRANSITION,
+         MockSupervisionTransitionScreen, MockSupervisionTransitionScreenView);
+  }
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    command_line->AppendSwitch(switches::kLoginManager);
+    command_line->AppendSwitchASCII(switches::kLoginProfile,
+                                    TestingProfile::kTestUserProfileDir);
+  }
+
+  void OnSupervisionTransitionFinished() {
+    WizardController::default_controller()->OnExit(
+        ScreenExitCode::SUPERVISION_TRANSITION_FINISHED);
+  }
+
+  MockOutShowHide<MockSupervisionTransitionScreen,
+                  MockSupervisionTransitionScreenView>*
+      mock_supervision_transition_screen_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WizardControllerSupervisionTransitionOobeTest);
+};
+
+// Tests that when supervision transition screen finishes, session
+// proceeds to ACTIVE state.
+IN_PROC_BROWSER_TEST_F(WizardControllerSupervisionTransitionOobeTest,
+                       SupervisionTransitionScreenFinished) {
+  EXPECT_CALL(*mock_supervision_transition_screen_, Show()).Times(1);
+  ASSERT_NE(session_manager::SessionManager::Get()->session_state(),
+            session_manager::SessionState::ACTIVE);
+  // Start from login screen.
+  LoginDisplayHost::default_host()->StartSignInScreen(LoginScreenContext());
+  // Advance to supervision transition screen.
+  WizardController::default_controller()->AdvanceToScreen(
+      OobeScreen::SCREEN_SUPERVISION_TRANSITION);
+  CheckCurrentScreen(OobeScreen::SCREEN_SUPERVISION_TRANSITION);
+  OnSupervisionTransitionFinished();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(session_manager::SessionManager::Get()->session_state(),
+            session_manager::SessionState::ACTIVE);
+}
+
 class TimeZoneTestRunner {
  public:
   void OnResolved() { loop_.Quit(); }
@@ -2697,7 +2763,7 @@
 
 // TODO(khorimoto): Add tests for MultiDevice Setup UI.
 
-static_assert(static_cast<int>(ScreenExitCode::EXIT_CODES_COUNT) == 50,
+static_assert(static_cast<int>(ScreenExitCode::EXIT_CODES_COUNT) == 51,
               "tests for new control flow are missing");
 
 }  // namespace chromeos
diff --git a/chrome/browser/extensions/api/automation_internal/automation_event_router.cc b/chrome/browser/extensions/api/automation_internal/automation_event_router.cc
index c6687f1..892cd3c 100644
--- a/chrome/browser/extensions/api/automation_internal/automation_event_router.cc
+++ b/chrome/browser/extensions/api/automation_internal/automation_event_router.cc
@@ -67,7 +67,7 @@
 void AutomationEventRouter::RegisterListenerWithDesktopPermission(
     const ExtensionId& extension_id,
     int listener_process_id) {
-  Register(extension_id, listener_process_id, ui::DesktopAXTreeID(), true);
+  Register(extension_id, listener_process_id, ui::AXTreeIDUnknown(), true);
 }
 
 void AutomationEventRouter::DispatchAccessibilityEvents(
@@ -192,6 +192,7 @@
                                      int listener_process_id,
                                      ui::AXTreeID ax_tree_id,
                                      bool desktop) {
+  DCHECK(desktop || ax_tree_id != ui::AXTreeIDUnknown());
   auto iter =
       std::find_if(listeners_.begin(), listeners_.end(),
                    [listener_process_id](const AutomationListener& item) {
@@ -204,7 +205,8 @@
     listener.extension_id = extension_id;
     listener.process_id = listener_process_id;
     listener.desktop = desktop;
-    listener.tree_ids.insert(ax_tree_id);
+    if (!desktop)
+      listener.tree_ids.insert(ax_tree_id);
     listeners_.push_back(listener);
     UpdateActiveProfile();
     return;
@@ -212,9 +214,10 @@
 
   // We have an entry with that process so update the set of tree ids it wants
   // to listen to, and update its desktop permission.
-  iter->tree_ids.insert(ax_tree_id);
   if (desktop)
     iter->desktop = true;
+  else
+    iter->tree_ids.insert(ax_tree_id);
 }
 
 void AutomationEventRouter::DispatchAccessibilityEvents(
diff --git a/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc b/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
index 8d9fec92..0c3f7e8e 100644
--- a/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
+++ b/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
@@ -29,6 +29,7 @@
 #include "content/public/browser/browser_plugin_guest_manager.h"
 #include "content/public/browser/media_session.h"
 #include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
@@ -497,6 +498,43 @@
       registry->GetHostDelegate(ui::AXTreeID::FromString(params->args.tree_id));
   if (delegate) {
 #if defined(USE_AURA)
+    // Handle an AXHostDelegate with a rfh first. Some actions require a rfh ->
+    // web contents and this api requires web contents to perform a permissions
+    // check.
+    content::RenderFrameHost* rfh = content::RenderFrameHost::FromAXTreeID(
+        ui::AXTreeID::FromString(params->args.tree_id));
+    if (rfh) {
+      content::WebContents* contents =
+          content::WebContents::FromRenderFrameHost(rfh);
+      if (!CanRequestAutomation(extension(), automation_info, contents)) {
+        return RespondNow(
+            Error(kCannotRequestAutomationOnPage, contents->GetURL().spec()));
+      }
+
+      // Handle internal actions.
+      api::automation_internal::ActionTypePrivate internal_action_type =
+          api::automation_internal::ParseActionTypePrivate(
+              params->args.action_type);
+      content::MediaSession* session = content::MediaSession::Get(contents);
+      switch (internal_action_type) {
+        case api::automation_internal::ACTION_TYPE_PRIVATE_STARTDUCKINGMEDIA:
+          session->StartDucking();
+          return RespondNow(NoArguments());
+        case api::automation_internal::ACTION_TYPE_PRIVATE_STOPDUCKINGMEDIA:
+          session->StopDucking();
+          return RespondNow(NoArguments());
+        case api::automation_internal::ACTION_TYPE_PRIVATE_RESUMEMEDIA:
+          session->Resume(content::MediaSession::SuspendType::kSystem);
+          return RespondNow(NoArguments());
+        case api::automation_internal::ACTION_TYPE_PRIVATE_SUSPENDMEDIA:
+          session->Suspend(content::MediaSession::SuspendType::kSystem);
+          return RespondNow(NoArguments());
+        case api::automation_internal::ACTION_TYPE_PRIVATE_NONE:
+          // Not a private action.
+          break;
+      }
+    }
+
     ui::AXActionData data;
     ExtensionFunction::ResponseAction result =
         ConvertToAXActionData(params.get(), &data);
@@ -504,50 +542,12 @@
     return result;
 #else
     NOTREACHED();
-    return RespondNow(Error("Unexpected action on desktop automation tree;"
-                            " platform does not support desktop automation"));
+    return RespondNow(
+        Error("Unexpected action on desktop automation tree;"
+              " platform does not support desktop automation"));
 #endif  // defined(USE_AURA)
   }
-  content::RenderFrameHost* rfh = content::RenderFrameHost::FromAXTreeID(
-      ui::AXTreeID::FromString(params->args.tree_id));
-  if (!rfh)
-    return RespondNow(Error("Ignoring action on destroyed node"));
-
-  content::WebContents* contents =
-      content::WebContents::FromRenderFrameHost(rfh);
-  if (!CanRequestAutomation(extension(), automation_info, contents)) {
-    return RespondNow(
-        Error(kCannotRequestAutomationOnPage, contents->GetURL().spec()));
-  }
-
-  // Handle internal actions.
-  api::automation_internal::ActionTypePrivate internal_action_type =
-      api::automation_internal::ParseActionTypePrivate(
-          params->args.action_type);
-  content::MediaSession* session = content::MediaSession::Get(contents);
-  switch (internal_action_type) {
-    case api::automation_internal::ACTION_TYPE_PRIVATE_STARTDUCKINGMEDIA:
-      session->StartDucking();
-      return RespondNow(NoArguments());
-    case api::automation_internal::ACTION_TYPE_PRIVATE_STOPDUCKINGMEDIA:
-      session->StopDucking();
-      return RespondNow(NoArguments());
-    case api::automation_internal::ACTION_TYPE_PRIVATE_RESUMEMEDIA:
-      session->Resume(content::MediaSession::SuspendType::kSystem);
-      return RespondNow(NoArguments());
-    case api::automation_internal::ACTION_TYPE_PRIVATE_SUSPENDMEDIA:
-      session->Suspend(content::MediaSession::SuspendType::kSystem);
-      return RespondNow(NoArguments());
-    case api::automation_internal::ACTION_TYPE_PRIVATE_NONE:
-      // Not a private action.
-      break;
-  }
-
-  ui::AXActionData data;
-  ExtensionFunction::ResponseAction result =
-      ConvertToAXActionData(params.get(), &data);
-  rfh->AccessibilityPerformAction(data);
-  return result;
+  return RespondNow(Error("Unable to perform action on unknown tree."));
 }
 
 ExtensionFunction::ResponseAction
@@ -562,7 +562,10 @@
       extension_id(), source_process_id());
 
   AutomationManagerAura::GetInstance()->Enable();
-  return RespondNow(NoArguments());
+  ui::AXTreeID ax_tree_id = AutomationManagerAura::GetInstance()->ax_tree_id();
+  return RespondNow(
+      ArgumentList(api::automation_internal::EnableDesktop::Results::Create(
+          ax_tree_id.ToString())));
 #else
   return RespondNow(Error("getDesktop is unsupported by this platform"));
 #endif  // defined(USE_AURA)
diff --git a/chrome/browser/extensions/api/declarative/declarative_apitest.cc b/chrome/browser/extensions/api/declarative/declarative_apitest.cc
index fc9b8b1..e4fb1181 100644
--- a/chrome/browser/extensions/api/declarative/declarative_apitest.cc
+++ b/chrome/browser/extensions/api/declarative/declarative_apitest.cc
@@ -119,7 +119,7 @@
             RulesRegistryService::kDefaultRulesRegistryID,
             extensions::declarative_webrequest_constants::kOnRequest);
 
-    std::vector<linked_ptr<api::events::Rule>> rules;
+    std::vector<const api::events::Rule*> rules;
     base::PostTaskWithTraits(
         FROM_HERE, {BrowserThread::IO},
         base::BindOnce(&RulesRegistry::GetAllRules, rules_registry,
diff --git a/chrome/browser/extensions/api/declarative/rules_registry_service_unittest.cc b/chrome/browser/extensions/api/declarative/rules_registry_service_unittest.cc
index 1788f82..ec327a4 100644
--- a/chrome/browser/extensions/api/declarative/rules_registry_service_unittest.cc
+++ b/chrome/browser/extensions/api/declarative/rules_registry_service_unittest.cc
@@ -32,16 +32,16 @@
 
 void InsertRule(scoped_refptr<extensions::RulesRegistry> registry,
                 const std::string& id) {
-  std::vector<linked_ptr<extensions::api::events::Rule>> add_rules;
-  add_rules.push_back(make_linked_ptr(new extensions::api::events::Rule));
-  add_rules[0]->id.reset(new std::string(id));
-  std::string error = registry->AddRules(kExtensionId, add_rules);
+  std::vector<extensions::api::events::Rule> add_rules;
+  add_rules.emplace_back();
+  add_rules[0].id.reset(new std::string(id));
+  std::string error = registry->AddRules(kExtensionId, std::move(add_rules));
   EXPECT_TRUE(error.empty());
 }
 
 void VerifyNumberOfRules(scoped_refptr<extensions::RulesRegistry> registry,
                          size_t expected_number_of_rules) {
-  std::vector<linked_ptr<extensions::api::events::Rule>> get_rules;
+  std::vector<const extensions::api::events::Rule*> get_rules;
   registry->GetAllRules(kExtensionId, &get_rules);
   EXPECT_EQ(expected_number_of_rules, get_rules.size());
 }
diff --git a/chrome/browser/extensions/api/declarative/rules_registry_with_cache_unittest.cc b/chrome/browser/extensions/api/declarative/rules_registry_with_cache_unittest.cc
index 1b63dc1a..fd55b3d 100644
--- a/chrome/browser/extensions/api/declarative/rules_registry_with_cache_unittest.cc
+++ b/chrome/browser/extensions/api/declarative/rules_registry_with_cache_unittest.cc
@@ -75,10 +75,10 @@
   std::string AddRule(const std::string& extension_id,
                       const std::string& rule_id,
                       TestRulesRegistry* registry) {
-    std::vector<linked_ptr<api::events::Rule>> add_rules;
-    add_rules.push_back(make_linked_ptr(new api::events::Rule));
-    add_rules[0]->id.reset(new std::string(rule_id));
-    return registry->AddRules(extension_id, add_rules);
+    std::vector<api::events::Rule> add_rules;
+    add_rules.emplace_back();
+    add_rules[0].id.reset(new std::string(rule_id));
+    return registry->AddRules(extension_id, std::move(add_rules));
   }
 
   std::string AddRule(const std::string& extension_id,
@@ -95,7 +95,7 @@
 
   int GetNumberOfRules(const std::string& extension_id,
                        TestRulesRegistry* registry) {
-    std::vector<linked_ptr<api::events::Rule>> get_rules;
+    std::vector<const api::events::Rule*> get_rules;
     registry->GetAllRules(extension_id, &get_rules);
     return get_rules.size();
   }
@@ -191,7 +191,7 @@
   std::vector<std::string> rules_to_get;
   rules_to_get.push_back(kRuleId);
   rules_to_get.push_back("unknown_rule");
-  std::vector<linked_ptr<api::events::Rule>> gotten_rules;
+  std::vector<const api::events::Rule*> gotten_rules;
   registry_->GetRules(extension1_->id(), rules_to_get, &gotten_rules);
   ASSERT_EQ(1u, gotten_rules.size());
   ASSERT_TRUE(gotten_rules[0]->id.get());
@@ -205,7 +205,7 @@
   EXPECT_EQ("", AddRule(extension2_->id(), kRuleId));
 
   // Check that we get the correct rules.
-  std::vector<linked_ptr<api::events::Rule>> gotten_rules;
+  std::vector<const api::events::Rule*> gotten_rules;
   registry_->GetAllRules(extension1_->id(), &gotten_rules);
   EXPECT_EQ(2u, gotten_rules.size());
   ASSERT_TRUE(gotten_rules[0]->id.get());
diff --git a/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc b/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc
index f4a4ea8..0d28bb3 100644
--- a/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc
+++ b/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.cc
@@ -227,7 +227,7 @@
 
 std::string ChromeContentRulesRegistry::AddRulesImpl(
     const std::string& extension_id,
-    const std::vector<linked_ptr<api::events::Rule>>& api_rules) {
+    const std::vector<const api::events::Rule*>& api_rules) {
   EvaluationScope evaluation_scope(this);
   const Extension* extension = ExtensionRegistry::Get(browser_context())
       ->GetInstalledExtension(extension_id);
@@ -246,7 +246,7 @@
         evaluator.get();
   }
 
-  for (const linked_ptr<api::events::Rule>& api_rule : api_rules) {
+  for (auto* api_rule : api_rules) {
     ExtensionIdRuleIdPair rule_id(extension_id, *api_rule->id);
     DCHECK(content_rules_.find(rule_id) == content_rules_.end());
 
diff --git a/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.h b/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.h
index 80ee629..192c228ec 100644
--- a/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.h
+++ b/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry.h
@@ -74,7 +74,7 @@
   // RulesRegistry:
   std::string AddRulesImpl(
       const std::string& extension_id,
-      const std::vector<linked_ptr<api::events::Rule>>& rules) override;
+      const std::vector<const api::events::Rule*>& rules) override;
   std::string RemoveRulesImpl(
       const std::string& extension_id,
       const std::vector<std::string>& rule_identifiers) override;
diff --git a/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc b/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc
index 8d398b1..2f3ccaa 100644
--- a/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc
@@ -161,7 +161,7 @@
   EXPECT_EQ(0u, registry->GetActiveRulesCountForTesting());
 
   // Add a rule.
-  linked_ptr<api::events::Rule> rule(new api::events::Rule);
+  api::events::Rule rule;
   api::events::Rule::Populate(
       *base::test::ParseJson(
           "{\n"
@@ -176,9 +176,8 @@
           "    { \"instanceType\": \"declarativeContent.ShowAction\" }\n"
           "  ]\n"
           "}"),
-      rule.get());
-  std::vector<linked_ptr<api::events::Rule>> rules;
-  rules.push_back(rule);
+      &rule);
+  std::vector<const api::events::Rule*> rules({&rule});
 
   const Extension* extension = env()->MakeExtension(*base::test::ParseJson(
       "{\"page_action\": {}}"));
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
index 4ce1f72f..d0a6ccb 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
@@ -13,7 +13,6 @@
 
 #include "base/json/json_reader.h"
 #include "base/macros.h"
-#include "base/memory/linked_ptr.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "base/test/values_test_util.h"
@@ -108,7 +107,7 @@
 
   // Returns a rule that roughly matches http://*.example.com and
   // https://www.example.com and cancels it
-  linked_ptr<api::events::Rule> CreateRule1() {
+  api::events::Rule CreateRule1() {
     auto scheme_http = std::make_unique<base::ListValue>();
     scheme_http->AppendString("http");
     auto http_condition_dict = std::make_unique<base::DictionaryValue>();
@@ -132,36 +131,35 @@
     base::DictionaryValue action_dict;
     action_dict.SetString(keys::kInstanceTypeKey, keys::kCancelRequestType);
 
-    linked_ptr<api::events::Rule> rule(new api::events::Rule);
-    rule->id.reset(new std::string(kRuleId1));
-    rule->priority.reset(new int(100));
-    rule->actions.push_back(action_dict.CreateDeepCopy());
+    api::events::Rule rule;
+    rule.id.reset(new std::string(kRuleId1));
+    rule.priority.reset(new int(100));
+    rule.actions.push_back(action_dict.CreateDeepCopy());
     http_condition_dict->Set(keys2::kSchemesKey, std::move(scheme_http));
     http_condition_url_filter.Set(keys::kUrlKey,
                                   std::move(http_condition_dict));
-    rule->conditions.push_back(http_condition_url_filter.CreateDeepCopy());
-    rule->conditions.push_back(https_condition_url_filter.CreateDeepCopy());
+    rule.conditions.push_back(http_condition_url_filter.CreateDeepCopy());
+    rule.conditions.push_back(https_condition_url_filter.CreateDeepCopy());
     return rule;
   }
 
   // Returns a rule that matches anything and cancels it.
-  linked_ptr<api::events::Rule> CreateRule2() {
+  api::events::Rule CreateRule2() {
     base::DictionaryValue condition_dict;
     condition_dict.SetString(keys::kInstanceTypeKey, keys::kRequestMatcherType);
 
     base::DictionaryValue action_dict;
     action_dict.SetString(keys::kInstanceTypeKey, keys::kCancelRequestType);
 
-    linked_ptr<api::events::Rule> rule(new api::events::Rule);
-    rule->id.reset(new std::string(kRuleId2));
-    rule->priority.reset(new int(100));
-    rule->actions.push_back(action_dict.CreateDeepCopy());
-    rule->conditions.push_back(condition_dict.CreateDeepCopy());
+    api::events::Rule rule;
+    rule.id.reset(new std::string(kRuleId2));
+    rule.priority.reset(new int(100));
+    rule.actions.push_back(action_dict.CreateDeepCopy());
+    rule.conditions.push_back(condition_dict.CreateDeepCopy());
     return rule;
   }
 
-  linked_ptr<api::events::Rule> CreateRedirectRule(
-      const std::string& destination) {
+  api::events::Rule CreateRedirectRule(const std::string& destination) {
     base::DictionaryValue condition_dict;
     condition_dict.SetString(keys::kInstanceTypeKey, keys::kRequestMatcherType);
 
@@ -169,17 +167,17 @@
     action_dict.SetString(keys::kInstanceTypeKey, keys::kRedirectRequestType);
     action_dict.SetString(keys::kRedirectUrlKey, destination);
 
-    linked_ptr<api::events::Rule> rule(new api::events::Rule);
-    rule->id.reset(new std::string(kRuleId3));
-    rule->priority.reset(new int(100));
-    rule->actions.push_back(action_dict.CreateDeepCopy());
-    rule->conditions.push_back(condition_dict.CreateDeepCopy());
+    api::events::Rule rule;
+    rule.id.reset(new std::string(kRuleId3));
+    rule.priority.reset(new int(100));
+    rule.actions.push_back(action_dict.CreateDeepCopy());
+    rule.conditions.push_back(condition_dict.CreateDeepCopy());
     return rule;
   }
 
   // Create a rule to ignore all other rules for a destination that
   // contains index.html.
-  linked_ptr<api::events::Rule> CreateIgnoreRule() {
+  api::events::Rule CreateIgnoreRule() {
     base::DictionaryValue condition_dict;
     auto http_condition_dict = std::make_unique<base::DictionaryValue>();
     http_condition_dict->SetString(keys2::kPathContainsKey, "index.html");
@@ -190,11 +188,11 @@
     action_dict.SetString(keys::kInstanceTypeKey, keys::kIgnoreRulesType);
     action_dict.SetInteger(keys::kLowerPriorityThanKey, 150);
 
-    linked_ptr<api::events::Rule> rule(new api::events::Rule);
-    rule->id.reset(new std::string(kRuleId4));
-    rule->priority.reset(new int(200));
-    rule->actions.push_back(action_dict.CreateDeepCopy());
-    rule->conditions.push_back(condition_dict.CreateDeepCopy());
+    api::events::Rule rule;
+    rule.id.reset(new std::string(kRuleId4));
+    rule.priority.reset(new int(200));
+    rule.actions.push_back(action_dict.CreateDeepCopy());
+    rule.conditions.push_back(condition_dict.CreateDeepCopy());
     return rule;
   }
 
@@ -213,18 +211,18 @@
   // Create a rule with the ID |rule_id| and with conditions created from the
   // |attributes| specified (one entry one condition). An example value of a
   // string from |attributes| is: "\"resourceType\": [\"stylesheet\"], \n".
-  linked_ptr<api::events::Rule> CreateCancellingRule(
+  api::events::Rule CreateCancellingRule(
       const char* rule_id,
       const std::vector<const std::string*>& attributes) {
     base::DictionaryValue action_dict;
     action_dict.SetString(keys::kInstanceTypeKey, keys::kCancelRequestType);
 
-    linked_ptr<api::events::Rule> rule(new api::events::Rule);
-    rule->id.reset(new std::string(rule_id));
-    rule->priority.reset(new int(1));
-    rule->actions.push_back(action_dict.CreateDeepCopy());
+    api::events::Rule rule;
+    rule.id.reset(new std::string(rule_id));
+    rule.priority.reset(new int(1));
+    rule.actions.push_back(action_dict.CreateDeepCopy());
     for (auto it = attributes.cbegin(); it != attributes.cend(); ++it)
-      rule->conditions.push_back(CreateCondition(**it));
+      rule.conditions.push_back(CreateCondition(**it));
     return rule;
   }
 
@@ -274,13 +272,15 @@
       new TestWebRequestRulesRegistry(extension_info_map_));
   std::string error;
 
-  std::vector<linked_ptr<api::events::Rule>> rules;
-  rules.push_back(CreateRule1());
-  rules.push_back(CreateRule2());
+  {
+    std::vector<api::events::Rule> rules;
+    rules.push_back(CreateRule1());
+    rules.push_back(CreateRule2());
 
-  error = registry->AddRules(kExtensionId, rules);
-  EXPECT_EQ("", error);
-  EXPECT_EQ(1, registry->num_clear_cache_calls());
+    error = registry->AddRules(kExtensionId, std::move(rules));
+    EXPECT_EQ("", error);
+    EXPECT_EQ(1, registry->num_clear_cache_calls());
+  }
 
   std::set<const WebRequestRule*> matches;
 
@@ -314,15 +314,17 @@
   std::string error;
 
   // Setup RulesRegistry to contain two rules.
-  std::vector<linked_ptr<api::events::Rule>> rules_to_add;
-  rules_to_add.push_back(CreateRule1());
-  rules_to_add.push_back(CreateRule2());
-  error = registry->AddRules(kExtensionId, rules_to_add);
-  EXPECT_EQ("", error);
-  EXPECT_EQ(1, registry->num_clear_cache_calls());
+  {
+    std::vector<api::events::Rule> rules_to_add;
+    rules_to_add.push_back(CreateRule1());
+    rules_to_add.push_back(CreateRule2());
+    error = registry->AddRules(kExtensionId, std::move(rules_to_add));
+    EXPECT_EQ("", error);
+    EXPECT_EQ(1, registry->num_clear_cache_calls());
+  }
 
   // Verify initial state.
-  std::vector<linked_ptr<api::events::Rule>> registered_rules;
+  std::vector<const api::events::Rule*> registered_rules;
   registry->GetAllRules(kExtensionId, &registered_rules);
   EXPECT_EQ(2u, registered_rules.size());
   EXPECT_EQ(1u, registry->RulesWithoutTriggers());
@@ -361,20 +363,25 @@
       new TestWebRequestRulesRegistry(extension_info_map_));
   std::string error;
 
-  // Setup RulesRegistry to contain two rules, one for each extension.
-  std::vector<linked_ptr<api::events::Rule>> rules_to_add(1);
-  rules_to_add[0] = CreateRule1();
-  error = registry->AddRules(kExtensionId, rules_to_add);
-  EXPECT_EQ("", error);
-  EXPECT_EQ(1, registry->num_clear_cache_calls());
+  {
+    // Setup RulesRegistry to contain two rules, one for each extension.
+    std::vector<api::events::Rule> rules_to_add;
+    rules_to_add.push_back(CreateRule1());
+    error = registry->AddRules(kExtensionId, std::move(rules_to_add));
+    EXPECT_EQ("", error);
+    EXPECT_EQ(1, registry->num_clear_cache_calls());
+  }
 
-  rules_to_add[0] = CreateRule2();
-  error = registry->AddRules(kExtensionId2, rules_to_add);
-  EXPECT_EQ("", error);
-  EXPECT_EQ(2, registry->num_clear_cache_calls());
+  {
+    std::vector<api::events::Rule> rules_to_add;
+    rules_to_add.push_back(CreateRule2());
+    error = registry->AddRules(kExtensionId2, std::move(rules_to_add));
+    EXPECT_EQ("", error);
+    EXPECT_EQ(2, registry->num_clear_cache_calls());
+  }
 
   // Verify initial state.
-  std::vector<linked_ptr<api::events::Rule>> registered_rules;
+  std::vector<const api::events::Rule*> registered_rules;
   registry->GetAllRules(kExtensionId, &registered_rules);
   EXPECT_EQ(1u, registered_rules.size());
   registered_rules.clear();
@@ -413,15 +420,19 @@
       new TestWebRequestRulesRegistry(extension_info_map_));
   std::string error;
 
-  std::vector<linked_ptr<api::events::Rule>> rules_to_add_1(1);
-  rules_to_add_1[0] = CreateRedirectRule("http://www.foo.com");
-  error = registry->AddRules(kExtensionId, rules_to_add_1);
-  EXPECT_EQ("", error);
+  {
+    std::vector<api::events::Rule> rules_to_add_1(1);
+    rules_to_add_1[0] = CreateRedirectRule("http://www.foo.com");
+    error = registry->AddRules(kExtensionId, std::move(rules_to_add_1));
+    EXPECT_EQ("", error);
+  }
 
-  std::vector<linked_ptr<api::events::Rule>> rules_to_add_2(1);
-  rules_to_add_2[0] = CreateRedirectRule("http://www.bar.com");
-  error = registry->AddRules(kExtensionId2, rules_to_add_2);
-  EXPECT_EQ("", error);
+  {
+    std::vector<api::events::Rule> rules_to_add_2(1);
+    rules_to_add_2[0] = CreateRedirectRule("http://www.bar.com");
+    error = registry->AddRules(kExtensionId2, std::move(rules_to_add_2));
+    EXPECT_EQ("", error);
+  }
 
   GURL url("http://www.google.com");
   WebRequestInfo request_info = CreateRequest(url);
@@ -455,20 +466,26 @@
       new TestWebRequestRulesRegistry(extension_info_map_));
   std::string error;
 
-  std::vector<linked_ptr<api::events::Rule>> rules_to_add_1(1);
-  rules_to_add_1[0] = CreateRedirectRule("http://www.foo.com");
-  error = registry->AddRules(kExtensionId, rules_to_add_1);
-  EXPECT_EQ("", error);
+  {
+    std::vector<api::events::Rule> rules_to_add_1(1);
+    rules_to_add_1[0] = CreateRedirectRule("http://www.foo.com");
+    error = registry->AddRules(kExtensionId, std::move(rules_to_add_1));
+    EXPECT_EQ("", error);
+  }
 
-  std::vector<linked_ptr<api::events::Rule>> rules_to_add_2(1);
-  rules_to_add_2[0] = CreateRedirectRule("http://www.bar.com");
-  error = registry->AddRules(kExtensionId2, rules_to_add_2);
-  EXPECT_EQ("", error);
+  {
+    std::vector<api::events::Rule> rules_to_add_2(1);
+    rules_to_add_2[0] = CreateRedirectRule("http://www.bar.com");
+    error = registry->AddRules(kExtensionId2, std::move(rules_to_add_2));
+    EXPECT_EQ("", error);
+  }
 
-  std::vector<linked_ptr<api::events::Rule>> rules_to_add_3(1);
-  rules_to_add_3[0] = CreateIgnoreRule();
-  error = registry->AddRules(kExtensionId, rules_to_add_3);
-  EXPECT_EQ("", error);
+  {
+    std::vector<api::events::Rule> rules_to_add_3(1);
+    rules_to_add_3[0] = CreateIgnoreRule();
+    error = registry->AddRules(kExtensionId, std::move(rules_to_add_3));
+    EXPECT_EQ("", error);
+  }
 
   GURL url("http://www.google.com/index.html");
   WebRequestInfo request_info = CreateRequest(url);
@@ -530,11 +547,13 @@
   std::unique_ptr<base::Value> value2 = base::JSONReader::Read(kRule2);
   ASSERT_TRUE(value2.get());
 
-  std::vector<linked_ptr<api::events::Rule>> rules;
-  rules.push_back(make_linked_ptr(new api::events::Rule));
-  rules.push_back(make_linked_ptr(new api::events::Rule));
-  ASSERT_TRUE(api::events::Rule::Populate(*value1, rules[0].get()));
-  ASSERT_TRUE(api::events::Rule::Populate(*value2, rules[1].get()));
+  std::vector<const api::events::Rule*> rules;
+  api::events::Rule rule1;
+  api::events::Rule rule2;
+  rules.push_back(&rule1);
+  rules.push_back(&rule2);
+  ASSERT_TRUE(api::events::Rule::Populate(*value1, &rule1));
+  ASSERT_TRUE(api::events::Rule::Populate(*value2, &rule2));
 
   scoped_refptr<WebRequestRulesRegistry> registry(
       new TestWebRequestRulesRegistry(extension_info_map_));
@@ -565,28 +584,30 @@
       "\"resourceType\": [\"stylesheet\"], \n");
   const std::string kBothAttributes(kMatchingUrlAttribute +
                                     kNonMatchingNonUrlAttribute);
-  std::string error;
-  std::vector<const std::string*> attributes;
-  std::vector<linked_ptr<api::events::Rule>> rules;
+  {
+    std::string error;
+    std::vector<const std::string*> attributes;
+    std::vector<api::events::Rule> rules;
 
-  // Rules 1 and 2 have one condition, neither of them should fire.
-  attributes.push_back(&kNonMatchingNonUrlAttribute);
-  rules.push_back(CreateCancellingRule(kRuleId1, attributes));
+    // Rules 1 and 2 have one condition, neither of them should fire.
+    attributes.push_back(&kNonMatchingNonUrlAttribute);
+    rules.push_back(CreateCancellingRule(kRuleId1, attributes));
 
-  attributes.clear();
-  attributes.push_back(&kBothAttributes);
-  rules.push_back(CreateCancellingRule(kRuleId2, attributes));
+    attributes.clear();
+    attributes.push_back(&kBothAttributes);
+    rules.push_back(CreateCancellingRule(kRuleId2, attributes));
 
-  // Rule 3 has two conditions, one with a matching URL attribute, and one
-  // with a non-matching non-URL attribute.
-  attributes.clear();
-  attributes.push_back(&kMatchingUrlAttribute);
-  attributes.push_back(&kNonMatchingNonUrlAttribute);
-  rules.push_back(CreateCancellingRule(kRuleId3, attributes));
+    // Rule 3 has two conditions, one with a matching URL attribute, and one
+    // with a non-matching non-URL attribute.
+    attributes.clear();
+    attributes.push_back(&kMatchingUrlAttribute);
+    attributes.push_back(&kNonMatchingNonUrlAttribute);
+    rules.push_back(CreateCancellingRule(kRuleId3, attributes));
 
-  error = registry->AddRules(kExtensionId, rules);
-  EXPECT_EQ("", error);
-  EXPECT_EQ(1, registry->num_clear_cache_calls());
+    error = registry->AddRules(kExtensionId, std::move(rules));
+    EXPECT_EQ("", error);
+    EXPECT_EQ(1, registry->num_clear_cache_calls());
+  }
 
   std::set<const WebRequestRule*> matches;
 
@@ -610,22 +631,25 @@
       "\"url\": { \"hostContains\": \"url\" }, \n");
   const std::string kFirstPartyUrlAttribute(
       "\"firstPartyForCookiesUrl\": { \"hostContains\": \"fpfc\" }, \n");
-  std::string error;
-  std::vector<const std::string*> attributes;
-  std::vector<linked_ptr<api::events::Rule>> rules;
 
-  // Rule 1 has one condition, with a url attribute
-  attributes.push_back(&kUrlAttribute);
-  rules.push_back(CreateCancellingRule(kRuleId1, attributes));
+  {
+    std::string error;
+    std::vector<const std::string*> attributes;
+    std::vector<api::events::Rule> rules;
 
-  // Rule 2 has one condition, with a firstPartyForCookiesUrl attribute
-  attributes.clear();
-  attributes.push_back(&kFirstPartyUrlAttribute);
-  rules.push_back(CreateCancellingRule(kRuleId2, attributes));
+    // Rule 1 has one condition, with a url attribute
+    attributes.push_back(&kUrlAttribute);
+    rules.push_back(CreateCancellingRule(kRuleId1, attributes));
 
-  error = registry->AddRules(kExtensionId, rules);
-  EXPECT_EQ("", error);
-  EXPECT_EQ(1, registry->num_clear_cache_calls());
+    // Rule 2 has one condition, with a firstPartyForCookiesUrl attribute
+    attributes.clear();
+    attributes.push_back(&kFirstPartyUrlAttribute);
+    rules.push_back(CreateCancellingRule(kRuleId2, attributes));
+
+    error = registry->AddRules(kExtensionId, std::move(rules));
+    EXPECT_EQ("", error);
+    EXPECT_EQ(1, registry->num_clear_cache_calls());
+  }
 
   std::set<const WebRequestRule*> matches;
 
@@ -780,9 +804,10 @@
   std::unique_ptr<base::Value> value = base::JSONReader::Read(kRule);
   ASSERT_TRUE(value.get());
 
-  std::vector<linked_ptr<api::events::Rule>> rules;
-  rules.push_back(make_linked_ptr(new api::events::Rule));
-  ASSERT_TRUE(api::events::Rule::Populate(*value, rules.back().get()));
+  std::vector<const api::events::Rule*> rules;
+  api::events::Rule rule;
+  rules.push_back(&rule);
+  ASSERT_TRUE(api::events::Rule::Populate(*value, &rule));
 
   scoped_refptr<WebRequestRulesRegistry> registry(
       new TestWebRequestRulesRegistry(extension_info_map_));
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc
index dbeda831..9b5626bf 100644
--- a/chrome/browser/extensions/crx_installer.cc
+++ b/chrome/browser/extensions/crx_installer.cc
@@ -934,7 +934,7 @@
   if (!update_from_settings_page_) {
     // If there is a client, tell the client about installation.
     if (client_)
-      client_->OnInstallSuccess(extension(), install_icon_.get());
+      client_->OnInstallSuccess(extension_, install_icon_.get());
 
     // We update the extension's granted permissions if the user already
     // approved the install (client_ is non NULL), or we are allowed to install
diff --git a/chrome/browser/extensions/crx_installer_browsertest.cc b/chrome/browser/extensions/crx_installer_browsertest.cc
index 37a3427..113ab8b 100644
--- a/chrome/browser/extensions/crx_installer_browsertest.cc
+++ b/chrome/browser/extensions/crx_installer_browsertest.cc
@@ -160,7 +160,8 @@
       proxy_(proxy) {}
 
   // Overriding some of the ExtensionInstallUI API.
-  void OnInstallSuccess(const Extension* extension, SkBitmap* icon) override {
+  void OnInstallSuccess(scoped_refptr<const Extension> extension,
+                        SkBitmap* icon) override {
     proxy_->set_extension_id(extension->id());
     proxy_->set_confirmation_requested(did_call_show_dialog());
   }
diff --git a/chrome/browser/extensions/extension_install_prompt.cc b/chrome/browser/extensions/extension_install_prompt.cc
index 4ac6bdc..94fc4d3 100644
--- a/chrome/browser/extensions/extension_install_prompt.cc
+++ b/chrome/browser/extensions/extension_install_prompt.cc
@@ -580,8 +580,9 @@
   LoadImageIfNeeded();
 }
 
-void ExtensionInstallPrompt::OnInstallSuccess(const Extension* extension,
-                                              SkBitmap* icon) {
+void ExtensionInstallPrompt::OnInstallSuccess(
+    scoped_refptr<const Extension> extension,
+    SkBitmap* icon) {
   extension_ = extension;
   SetIcon(icon);
 
@@ -621,8 +622,7 @@
   }
 
   extensions::ExtensionResource image = extensions::IconsInfo::GetIconResource(
-      extension_,
-      extension_misc::EXTENSION_ICON_LARGE,
+      extension_.get(), extension_misc::EXTENSION_ICON_LARGE,
       ExtensionIconSet::MATCH_BIGGER);
 
   // Load the image asynchronously. The response will be sent to OnImageLoaded.
@@ -634,7 +634,7 @@
       extensions::ImageLoader::ImageRepresentation::NEVER_RESIZE,
       gfx::Size(),
       ui::SCALE_FACTOR_100P));
-  loader->LoadImagesAsync(extension_, images_list,
+  loader->LoadImagesAsync(extension_.get(), images_list,
                           base::BindOnce(&ExtensionInstallPrompt::OnImageLoaded,
                                          weak_factory_.GetWeakPtr()));
 }
@@ -649,14 +649,15 @@
     // any transformations are correctly reflected in the install prompt.
     extensions::PermissionsUpdater(
         profile_, extensions::PermissionsUpdater::INIT_FLAG_TRANSIENT)
-        .InitializePermissions(extension_);
+        .InitializePermissions(extension_.get());
     permissions_to_display =
         &extension_->permissions_data()->active_permissions();
     // For delegated installs, all optional permissions are pre-approved by the
     // person who triggers the install, so add them to the list.
     if (prompt_->type() == DELEGATED_PERMISSIONS_PROMPT) {
       const PermissionSet& optional_permissions =
-          extensions::PermissionsParser::GetOptionalPermissions(extension_);
+          extensions::PermissionsParser::GetOptionalPermissions(
+              extension_.get());
       permissions_wrapper = PermissionSet::CreateUnion(*permissions_to_display,
                                                        optional_permissions);
       permissions_to_display = permissions_wrapper.get();
@@ -673,7 +674,7 @@
         message_provider->GetAllPermissionIDs(*permissions_to_display, type)));
   }
 
-  prompt_->set_extension(extension_);
+  prompt_->set_extension(extension_.get());
   prompt_->set_icon(gfx::Image::CreateFrom1xBitmap(icon_));
 
   if (show_params_->WasParentDestroyed()) {
diff --git a/chrome/browser/extensions/extension_install_prompt.h b/chrome/browser/extensions/extension_install_prompt.h
index ec13a56b..c10dc09 100644
--- a/chrome/browser/extensions/extension_install_prompt.h
+++ b/chrome/browser/extensions/extension_install_prompt.h
@@ -301,8 +301,9 @@
       const ShowDialogCallback& show_dialog_callback);
 
   // Installation was successful. This is declared virtual for testing.
-  virtual void OnInstallSuccess(const extensions::Extension* extension,
-                                SkBitmap* icon);
+  virtual void OnInstallSuccess(
+      scoped_refptr<const extensions::Extension> extension,
+      SkBitmap* icon);
 
   // Installation failed. This is declared virtual for testing.
   virtual void OnInstallFailure(const extensions::CrxInstallError& error);
@@ -333,7 +334,7 @@
   SkBitmap icon_;
 
   // The extension we are showing the UI for.
-  const extensions::Extension* extension_;
+  scoped_refptr<const extensions::Extension> extension_;
 
   // A custom set of permissions to show in the install prompt instead of the
   // extension's active permissions.
diff --git a/chrome/browser/feature_engagement/incognito_window/incognito_window_tracker.cc b/chrome/browser/feature_engagement/incognito_window/incognito_window_tracker.cc
index c40a590..5d07a43 100644
--- a/chrome/browser/feature_engagement/incognito_window/incognito_window_tracker.cc
+++ b/chrome/browser/feature_engagement/incognito_window/incognito_window_tracker.cc
@@ -100,7 +100,7 @@
       FeaturePromoBubbleView::ActivationAction::ACTIVATE);
   views::Widget* widget = incognito_promo_->GetWidget();
   incognito_promo_observer_.Add(widget);
-  app_menu_button->SetIsProminent(true);
+  app_menu_button->SetPromoIsShowing(true);
 }
 
 void IncognitoWindowTracker::OnWidgetDestroying(views::Widget* widget) {
@@ -110,7 +110,7 @@
     incognito_promo_observer_.Remove(widget);
     BrowserAppMenuButton* app_menu_button = GetAppMenuButton();
     if (app_menu_button)
-      app_menu_button->SetIsProminent(false);
+      app_menu_button->SetPromoIsShowing(false);
   }
 }
 
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 59cac9af..f287466 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -3113,11 +3113,6 @@
     "expiry_milestone": 76
   },
   {
-    "name": "tls13-variant",
-    "owners": [ "davidben", "svaldez" ],
-    "expiry_milestone": 76
-  },
-  {
     "name": "top-chrome-touch-ui",
     // "owners": [ "your-team" ],
     "expiry_milestone": 76
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 3096cb6..52f4735c 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1892,13 +1892,6 @@
     "this can dramatically hurt scrolling performance of most websites and is "
     "intended for testing purposes only.";
 
-const char kTLS13VariantName[] = "TLS 1.3";
-const char kTLS13VariantDescription[] = "Sets the TLS 1.3 variant used.";
-const char kTLS13VariantDisabled[] = "Disabled";
-const char kTLS13VariantDeprecated[] = "Disabled (Deprecated Setting)";
-const char kTLS13VariantDraft23[] = "Enabled (Draft 23)";
-const char kTLS13VariantFinal[] = "Enabled (Final)";
-
 const char kTopSitesFromSiteEngagementName[] = "Top Sites from Site Engagement";
 const char kTopSitesFromSiteEngagementDescription[] =
     "Enable Top Sites on the New Tab Page to be sourced and sorted using site "
@@ -3109,11 +3102,6 @@
 const char kAshDisableLoginDimAndBlurDescription[] =
     "Disable dimming and blur on login screen.";
 
-const char kAshDisableSmoothScreenRotationName[] =
-    "Disable smooth rotation animations.";
-const char kAshDisableSmoothScreenRotationDescription[] =
-    "Disable smooth rotation animations.";
-
 const char kAshEnableDisplayMoveWindowAccelsName[] =
     "Enable shortcuts for moving window between displays.";
 const char kAshEnableDisplayMoveWindowAccelsDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index ce0d22fe1..d886427 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1091,13 +1091,6 @@
 extern const char kSystemKeyboardLockName[];
 extern const char kSystemKeyboardLockDescription[];
 
-extern const char kTLS13VariantName[];
-extern const char kTLS13VariantDescription[];
-extern const char kTLS13VariantDisabled[];
-extern const char kTLS13VariantDeprecated[];
-extern const char kTLS13VariantDraft23[];
-extern const char kTLS13VariantFinal[];
-
 extern const char kSuggestionsWithSubStringMatchName[];
 extern const char kSuggestionsWithSubStringMatchDescription[];
 
@@ -1865,9 +1858,6 @@
 extern const char kAshDisableLoginDimAndBlurName[];
 extern const char kAshDisableLoginDimAndBlurDescription[];
 
-extern const char kAshDisableSmoothScreenRotationName[];
-extern const char kAshDisableSmoothScreenRotationDescription[];
-
 extern const char kAshEnableDisplayMoveWindowAccelsName[];
 extern const char kAshEnableDisplayMoveWindowAccelsDescription[];
 
diff --git a/chrome/browser/metrics/perf/profile_provider_chromeos.cc b/chrome/browser/metrics/perf/profile_provider_chromeos.cc
new file mode 100644
index 0000000..005661c
--- /dev/null
+++ b/chrome/browser/metrics/perf/profile_provider_chromeos.cc
@@ -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.
+
+#include "chrome/browser/metrics/perf/profile_provider_chromeos.h"
+
+#include "chromeos/dbus/dbus_thread_manager.h"
+
+namespace metrics {
+
+namespace {
+
+// Returns true if a normal user is logged in. Returns false otherwise (e.g. if
+// logged in as a guest or as a kiosk app).
+bool IsNormalUserLoggedIn() {
+  return chromeos::LoginState::Get()->IsUserAuthenticated();
+}
+
+}  // namespace
+
+ProfileProvider::ProfileProvider() : weak_factory_(this) {}
+
+ProfileProvider::~ProfileProvider() {
+  chromeos::LoginState::Get()->RemoveObserver(this);
+  chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(
+      this);
+}
+
+void ProfileProvider::Init() {
+  for (auto& collector : collectors_) {
+    collector->Init();
+  }
+
+  // Register as an observer of login state changes.
+  chromeos::LoginState::Get()->AddObserver(this);
+
+  // Register as an observer of power manager events.
+  chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(
+      this);
+
+  // Register as an observer of session restore.
+  on_session_restored_callback_subscription_ =
+      SessionRestore::RegisterOnSessionRestoredCallback(base::BindRepeating(
+          &ProfileProvider::OnSessionRestoreDone, weak_factory_.GetWeakPtr()));
+
+  // Check the login state. At the time of writing, this class is instantiated
+  // before login. A subsequent login would activate the profiling. However,
+  // that behavior may change in the future so that the user is already logged
+  // when this class is instantiated. By calling LoggedInStateChanged() here,
+  // ProfileProvider will recognize that the system is already logged in.
+  LoggedInStateChanged();
+}
+
+bool ProfileProvider::GetSampledProfiles(
+    std::vector<SampledProfile>* sampled_profiles) {
+  bool result = false;
+  for (auto& collector : collectors_) {
+    bool written = collector->GetSampledProfiles(sampled_profiles);
+    result = result || written;
+  }
+  return result;
+}
+
+void ProfileProvider::LoggedInStateChanged() {
+  if (IsNormalUserLoggedIn()) {
+    for (auto& collector : collectors_) {
+      collector->OnUserLoggedIn();
+    }
+  } else {
+    for (auto& collector : collectors_) {
+      collector->Deactivate();
+    }
+  }
+}
+
+void ProfileProvider::SuspendDone(const base::TimeDelta& sleep_duration) {
+  // A zero value for the suspend duration indicates that the suspend was
+  // canceled. Do not collect anything if that's the case.
+  if (sleep_duration.is_zero())
+    return;
+
+  // Do not collect a profile unless logged in. The system behavior when closing
+  // the lid or idling when not logged in is currently to shut down instead of
+  // suspending. But it's good to enforce the rule here in case that changes.
+  if (!IsNormalUserLoggedIn())
+    return;
+
+  // Inform each collector that a successful suspend has completed.
+  for (auto& collector : collectors_) {
+    collector->SuspendDone(sleep_duration);
+  }
+}
+
+void ProfileProvider::OnSessionRestoreDone(int num_tabs_restored) {
+  // Do not collect a profile unless logged in as a normal user.
+  if (!IsNormalUserLoggedIn())
+    return;
+
+  // Inform each collector of a session restore event.
+  for (auto& collector : collectors_) {
+    collector->OnSessionRestoreDone(num_tabs_restored);
+  }
+}
+
+}  // namespace metrics
diff --git a/chrome/browser/metrics/perf/profile_provider_chromeos.h b/chrome/browser/metrics/perf/profile_provider_chromeos.h
new file mode 100644
index 0000000..c1585e9
--- /dev/null
+++ b/chrome/browser/metrics/perf/profile_provider_chromeos.h
@@ -0,0 +1,66 @@
+// 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_METRICS_PERF_PROFILE_PROVIDER_CHROMEOS_H_
+#define CHROME_BROWSER_METRICS_PERF_PROFILE_PROVIDER_CHROMEOS_H_
+
+#include <vector>
+
+#include "base/time/time.h"
+#include "chrome/browser/metrics/perf/metric_collector.h"
+#include "chromeos/dbus/power_manager_client.h"
+#include "chromeos/login/login_state.h"
+
+namespace metrics {
+
+// Provides access to ChromeOS profile data using different metric collectors.
+// It detects certain system triggers, such as device resuming from suspend
+// mode, or user logging in, which it forwards to the registered collectors.
+class ProfileProvider : public chromeos::PowerManagerClient::Observer,
+                        public chromeos::LoginState::Observer {
+ public:
+  ProfileProvider();
+  ~ProfileProvider() override;
+
+  void Init();
+
+  // Stores collected perf data protobufs in |sampled_profiles|. Clears all the
+  // stored profile data. Returns true if it wrote to |sampled_profiles|.
+  bool GetSampledProfiles(std::vector<SampledProfile>* sampled_profiles);
+
+ protected:
+  // Called when either the login state or the logged in user type changes.
+  // Activates the registered collectors to start collecting. Inherited from
+  // LoginState::Observer.
+  void LoggedInStateChanged() override;
+
+  // Called when a suspend finishes. This is either a successful suspend
+  // followed by a resume, or a suspend that was canceled. Inherited from
+  // PowerManagerClient::Observer.
+  void SuspendDone(const base::TimeDelta& sleep_duration) override;
+
+  // Called when a session restore has finished.
+  void OnSessionRestoreDone(int num_tabs_restored);
+
+  // Vector of registered metric collectors.
+  std::vector<std::unique_ptr<MetricCollector>> collectors_;
+
+ private:
+  // Points to the on-session-restored callback that was registered with
+  // SessionRestore's callback list. When objects of this class are destroyed,
+  // the subscription object's destructor will automatically unregister the
+  // callback in SessionRestore, so that the callback list does not contain any
+  // obsolete callbacks.
+  SessionRestore::CallbackSubscription
+      on_session_restored_callback_subscription_;
+
+  // To pass around the "this" pointer across threads safely.
+  base::WeakPtrFactory<ProfileProvider> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProfileProvider);
+};
+
+}  // namespace metrics
+
+#endif  // CHROME_BROWSER_METRICS_PERF_PROFILE_PROVIDER_CHROMEOS_H_
diff --git a/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc b/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc
new file mode 100644
index 0000000..7554934
--- /dev/null
+++ b/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc
@@ -0,0 +1,285 @@
+// 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/metrics/perf/profile_provider_chromeos.h"
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/login/login_state.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/metrics_proto/sampled_profile.pb.h"
+
+namespace metrics {
+
+namespace {
+
+const long kMsAfterBoot = 10000;
+const long kMsAfterLogin = 2000;
+
+// Returns sample PerfDataProtos with custom timestamps. The contents don't have
+// to make sense. They just need to constitute a semantically valid protobuf.
+// |proto| is an output parameter that will contain the created protobuf.
+PerfDataProto GetExamplePerfDataProto(int tstamp_sec) {
+  PerfDataProto proto;
+  proto.set_timestamp_sec(tstamp_sec);  // Time since epoch in seconds.
+
+  PerfDataProto_PerfFileAttr* file_attr = proto.add_file_attrs();
+  file_attr->add_ids(61);
+  file_attr->add_ids(62);
+  file_attr->add_ids(63);
+
+  PerfDataProto_PerfEventAttr* attr = file_attr->mutable_attr();
+  attr->set_type(1);
+  attr->set_size(2);
+  attr->set_config(3);
+  attr->set_sample_period(4);
+  attr->set_sample_freq(5);
+
+  PerfDataProto_PerfEventStats* stats = proto.mutable_stats();
+  stats->set_num_events_read(100);
+  stats->set_num_sample_events(200);
+  stats->set_num_mmap_events(300);
+  stats->set_num_fork_events(400);
+  stats->set_num_exit_events(500);
+
+  return proto;
+}
+
+// Custome metric collectors to register with the profile provider for testing.
+template <int TSTAMP>
+class TestMetricCollector : public MetricCollector {
+ public:
+  TestMetricCollector() {}
+  explicit TestMetricCollector(const CollectionParams& collection_params)
+      : MetricCollector(collection_params) {}
+
+  void CollectProfile(
+      std::unique_ptr<SampledProfile> sampled_profile) override {
+    PerfDataProto perf_data_proto = GetExamplePerfDataProto(TSTAMP);
+    sampled_profile->set_ms_after_boot(kMsAfterBoot);
+    sampled_profile->set_ms_after_login(kMsAfterLogin);
+    sampled_profile->mutable_perf_data()->Swap(&perf_data_proto);
+
+    // Add the collected data to the container of collected SampledProfiles.
+    cached_profile_data_.resize(cached_profile_data_.size() + 1);
+    cached_profile_data_.back().Swap(sampled_profile.get());
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestMetricCollector);
+};
+
+// Allows access to some private methods for testing.
+class TestProfileProvider : public ProfileProvider {
+ public:
+  TestProfileProvider() {
+    // Add a couple of metric collectors. We differentiate between them using
+    // different time stamps for profiles. Set sampling factors for triggers
+    // to 1, so we always trigger collection.
+    CollectionParams test_params;
+    test_params.resume_from_suspend.sampling_factor = 1;
+    test_params.restore_session.sampling_factor = 1;
+
+    collectors_.push_back(
+        std::make_unique<TestMetricCollector<100>>(test_params));
+    collectors_.push_back(
+        std::make_unique<TestMetricCollector<200>>(test_params));
+  }
+
+  using ProfileProvider::collectors_;
+  using ProfileProvider::LoggedInStateChanged;
+  using ProfileProvider::OnSessionRestoreDone;
+  using ProfileProvider::SuspendDone;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestProfileProvider);
+};
+
+template <SampledProfile_TriggerEvent TRIGGER_TYPE>
+void ExpectTwoStoredPerfProfiles(
+    const std::vector<SampledProfile>& stored_profiles) {
+  ASSERT_EQ(2U, stored_profiles.size());
+  // Both profiles must be of the given type and include perf data.
+  const SampledProfile& profile1 = stored_profiles[0];
+  const SampledProfile& profile2 = stored_profiles[1];
+  EXPECT_EQ(TRIGGER_TYPE, profile1.trigger_event());
+  ASSERT_TRUE(profile1.has_perf_data());
+  EXPECT_EQ(TRIGGER_TYPE, profile2.trigger_event());
+  ASSERT_TRUE(profile2.has_perf_data());
+
+  // We must have received a profile from each of the collectors.
+  EXPECT_EQ(100u, profile1.perf_data().timestamp_sec());
+  EXPECT_EQ(200u, profile2.perf_data().timestamp_sec());
+}
+
+}  // namespace
+
+class ProfileProviderTest : public testing::Test {
+ public:
+  ProfileProviderTest()
+      : task_runner_(base::MakeRefCounted<base::TestSimpleTaskRunner>()),
+        task_runner_handle_(task_runner_) {}
+
+  void SetUp() override {
+    // ProfileProvider requires chromeos::LoginState and
+    // chromeos::DBusThreadManager to be initialized.
+    chromeos::LoginState::Initialize();
+    chromeos::DBusThreadManager::Initialize();
+
+    profile_provider_ = std::make_unique<TestProfileProvider>();
+    profile_provider_->Init();
+  }
+
+  void TearDown() override {
+    profile_provider_.reset();
+    chromeos::DBusThreadManager::Shutdown();
+    chromeos::LoginState::Shutdown();
+  }
+
+ protected:
+  std::unique_ptr<TestProfileProvider> profile_provider_;
+
+  scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
+  base::ThreadTaskRunnerHandle task_runner_handle_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProfileProviderTest);
+};
+
+TEST_F(ProfileProviderTest, CheckSetup) {
+  EXPECT_EQ(2U, profile_provider_->collectors_.size());
+
+  // No profiles should be collected on start.
+  std::vector<SampledProfile> stored_profiles;
+  EXPECT_FALSE(profile_provider_->GetSampledProfiles(&stored_profiles));
+  EXPECT_TRUE(stored_profiles.empty());
+}
+
+TEST_F(ProfileProviderTest, UserLoginLogout) {
+  // No user is logged in, so no collection is scheduled to run.
+  task_runner_->RunPendingTasks();
+
+  std::vector<SampledProfile> stored_profiles;
+  EXPECT_FALSE(profile_provider_->GetSampledProfiles(&stored_profiles));
+  EXPECT_TRUE(stored_profiles.empty());
+
+  // Simulate a user log in, which should activate periodic collection for all
+  // collectors.
+  chromeos::LoginState::Get()->SetLoggedInState(
+      chromeos::LoginState::LOGGED_IN_ACTIVE,
+      chromeos::LoginState::LOGGED_IN_USER_REGULAR);
+
+  // Run all pending tasks. SetLoggedInState has activated timers for periodic
+  // collection causing timer based pending tasks.
+  task_runner_->RunPendingTasks();
+  // We should find two profiles, one for each collector.
+  EXPECT_TRUE(profile_provider_->GetSampledProfiles(&stored_profiles));
+  ExpectTwoStoredPerfProfiles<SampledProfile::PERIODIC_COLLECTION>(
+      stored_profiles);
+
+  // Periodic collection is deactivated when user logs out. Simulate a user
+  // logout event.
+  chromeos::LoginState::Get()->SetLoggedInState(
+      chromeos::LoginState::LOGGED_IN_NONE,
+      chromeos::LoginState::LOGGED_IN_USER_NONE);
+  // Run all pending tasks.
+  task_runner_->RunPendingTasks();
+  // We should find no new profiles.
+  stored_profiles.clear();
+  EXPECT_FALSE(profile_provider_->GetSampledProfiles(&stored_profiles));
+  ASSERT_TRUE(stored_profiles.empty());
+}
+
+TEST_F(ProfileProviderTest, SuspendDone_NoUserLoggedIn_NoCollection) {
+  // No user is logged in, so no collection is done on resume from suspend.
+  profile_provider_->SuspendDone(base::TimeDelta::FromMinutes(10));
+  // Run all pending tasks.
+  task_runner_->RunPendingTasks();
+
+  std::vector<SampledProfile> stored_profiles;
+  EXPECT_FALSE(profile_provider_->GetSampledProfiles(&stored_profiles));
+  EXPECT_TRUE(stored_profiles.empty());
+}
+
+TEST_F(ProfileProviderTest, CanceledSuspend_NoCollection) {
+  // Set user state as logged in. This activates periodic collection, but we can
+  // deactivate it for each collector.
+  chromeos::LoginState::Get()->SetLoggedInState(
+      chromeos::LoginState::LOGGED_IN_ACTIVE,
+      chromeos::LoginState::LOGGED_IN_USER_REGULAR);
+  for (auto& collector : profile_provider_->collectors_) {
+    collector->Deactivate();
+  }
+
+  // Trigger a canceled suspend (zero sleep duration).
+  profile_provider_->SuspendDone(base::TimeDelta::FromSeconds(0));
+  // Run all pending tasks.
+  task_runner_->RunPendingTasks();
+
+  // We should find no profiles.
+  std::vector<SampledProfile> stored_profiles;
+  EXPECT_FALSE(profile_provider_->GetSampledProfiles(&stored_profiles));
+  ASSERT_TRUE(stored_profiles.empty());
+}
+
+TEST_F(ProfileProviderTest, SuspendDone) {
+  // Set user state as logged in. This activates periodic collection, but we can
+  // deactivate it for each collector.
+  chromeos::LoginState::Get()->SetLoggedInState(
+      chromeos::LoginState::LOGGED_IN_ACTIVE,
+      chromeos::LoginState::LOGGED_IN_USER_REGULAR);
+
+  // Trigger a resume from suspend.
+  profile_provider_->SuspendDone(base::TimeDelta::FromMinutes(10));
+  // Run all pending tasks.
+  task_runner_->RunPendingTasks();
+
+  // We should find two profiles, one for each collector.
+  std::vector<SampledProfile> stored_profiles;
+  EXPECT_TRUE(profile_provider_->GetSampledProfiles(&stored_profiles));
+  ExpectTwoStoredPerfProfiles<SampledProfile::RESUME_FROM_SUSPEND>(
+      stored_profiles);
+}
+
+TEST_F(ProfileProviderTest, OnSessionRestoreDone_NoUserLoggedIn_NoCollection) {
+  // No user is logged in, so no collection is done on session restore.
+  profile_provider_->OnSessionRestoreDone(10);
+  // Run all pending tasks.
+  task_runner_->RunPendingTasks();
+
+  std::vector<SampledProfile> stored_profiles;
+  EXPECT_FALSE(profile_provider_->GetSampledProfiles(&stored_profiles));
+  EXPECT_TRUE(stored_profiles.empty());
+}
+
+TEST_F(ProfileProviderTest, OnSessionRestoreDone) {
+  // Set user state as logged in. This activates periodic collection, but we can
+  // deactivate it for each collector.
+  chromeos::LoginState::Get()->SetLoggedInState(
+      chromeos::LoginState::LOGGED_IN_ACTIVE,
+      chromeos::LoginState::LOGGED_IN_USER_REGULAR);
+  for (auto& collector : profile_provider_->collectors_) {
+    collector->Deactivate();
+  }
+
+  // Trigger a session restore.
+  profile_provider_->OnSessionRestoreDone(10);
+  // Run all pending tasks.
+  task_runner_->RunPendingTasks();
+
+  // We should find two profiles, one for each collector.
+  std::vector<SampledProfile> stored_profiles;
+  EXPECT_TRUE(profile_provider_->GetSampledProfiles(&stored_profiles));
+  ExpectTwoStoredPerfProfiles<SampledProfile::RESTORE_SESSION>(stored_profiles);
+}
+
+}  // namespace metrics
diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc
index 06667d4..7f6dbdb 100644
--- a/chrome/browser/net/chrome_network_delegate.cc
+++ b/chrome/browser/net/chrome_network_delegate.cc
@@ -106,6 +106,7 @@
   // directories below.
   static const base::FilePath::CharType* const kLocalAccessWhiteList[] = {
       "/home/chronos/user/Downloads",
+      "/home/chronos/user/MyFiles",
       "/home/chronos/user/log",
       "/home/chronos/user/WebRTC Logs",
       "/media",
@@ -127,6 +128,7 @@
   if (!profile_path.empty()) {
     const base::FilePath downloads = profile_path.AppendASCII("Downloads");
     whitelist.push_back(downloads);
+    whitelist.push_back(profile_path.AppendASCII("MyFiles"));
     const base::FilePath webrtc_logs = profile_path.AppendASCII("WebRTC Logs");
     whitelist.push_back(webrtc_logs);
   }
diff --git a/chrome/browser/net/chrome_network_delegate_unittest.cc b/chrome/browser/net/chrome_network_delegate_unittest.cc
index bc61cd1..cb7ef5e 100644
--- a/chrome/browser/net/chrome_network_delegate_unittest.cc
+++ b/chrome/browser/net/chrome_network_delegate_unittest.cc
@@ -207,6 +207,8 @@
   ASSERT_TRUE(base::PathService::Get(base::DIR_TEMP, &temp_dir));
   // Chrome OS allows the following directories.
   EXPECT_TRUE(IsAccessAllowed("/home/chronos/user/Downloads", ""));
+  EXPECT_TRUE(IsAccessAllowed("/home/chronos/user/MyFiles", ""));
+  EXPECT_TRUE(IsAccessAllowed("/home/chronos/user/MyFiles/file.pdf", ""));
   EXPECT_TRUE(IsAccessAllowed("/home/chronos/user/log", ""));
   EXPECT_TRUE(IsAccessAllowed("/home/chronos/user/WebRTC Logs", ""));
   EXPECT_TRUE(IsAccessAllowed("/media", ""));
@@ -223,6 +225,8 @@
 
   // If profile path is given, the following additional paths are allowed.
   EXPECT_TRUE(IsAccessAllowed("/profile/Downloads", "/profile"));
+  EXPECT_TRUE(IsAccessAllowed("/profile/MyFiles", "/profile"));
+  EXPECT_TRUE(IsAccessAllowed("/profile/MyFiles/file.pdf", "/profile"));
   EXPECT_TRUE(IsAccessAllowed("/profile/WebRTC Logs", "/profile"));
 
   // GCache/v2/<opaque ID>/Logs is allowed.
diff --git a/chrome/browser/offline_pages/offline_page_request_handler.cc b/chrome/browser/offline_pages/offline_page_request_handler.cc
index da7bc69..68de3a2 100644
--- a/chrome/browser/offline_pages/offline_page_request_handler.cc
+++ b/chrome/browser/offline_pages/offline_page_request_handler.cc
@@ -797,7 +797,8 @@
 
 void OfflinePageRequestHandler::FinalizeDigestOnBackground(
     base::OnceCallback<void(const std::string&)> digest_finalized_callback) {
-  DCHECK(archive_validator_.get());
+  if (!archive_validator_)
+    archive_validator_ = new ThreadSafeArchiveValidator();
 
   // Delegate to background task runner to finalize the hash to get the digest
   // since it is time consuming. Once it is done, |digest_finalized_callback|
diff --git a/chrome/browser/offline_pages/offline_page_request_handler_unittest.cc b/chrome/browser/offline_pages/offline_page_request_handler_unittest.cc
index 5a558305ef..c34349ac 100644
--- a/chrome/browser/offline_pages/offline_page_request_handler_unittest.cc
+++ b/chrome/browser/offline_pages/offline_page_request_handler_unittest.cc
@@ -2077,6 +2077,26 @@
   this->ExpectOfflinePageAccessCount(offline_id2, 0);
 }
 
+TYPED_TEST(OfflinePageRequestHandlerTest, EmptyFile) {
+  this->SimulateHasNetworkConnectivity(false);
+
+  const std::string expected_data("");
+  base::FilePath temp_file_path = this->CreateFileWithContent(expected_data);
+  ArchiveValidator archive_validator;
+  const std::string expected_digest = archive_validator.Finish();
+
+  int64_t offline_id =
+      this->SavePublicPage(kUrl, GURL(), temp_file_path, 0, expected_digest);
+
+  this->LoadPage(kUrl);
+
+  this->ExpectOfflinePageServed(
+      offline_id, 0,
+      OfflinePageRequestHandler::AggregatedRequestResult::
+          SHOW_OFFLINE_ON_DISCONNECTED_NETWORK);
+  EXPECT_EQ(expected_data, this->data_received());
+}
+
 TYPED_TEST(OfflinePageRequestHandlerTest, TinyFile) {
   this->SimulateHasNetworkConnectivity(false);
 
diff --git a/chrome/browser/prefs/chrome_command_line_pref_store.cc b/chrome/browser/prefs/chrome_command_line_pref_store.cc
index f345ab7b..e3e8ce7 100644
--- a/chrome/browser/prefs/chrome_command_line_pref_store.cc
+++ b/chrome/browser/prefs/chrome_command_line_pref_store.cc
@@ -42,7 +42,7 @@
          data_reduction_proxy::prefs::kDataReductionProxy},
         {switches::kAuthServerWhitelist, prefs::kAuthServerWhitelist},
         {switches::kSSLVersionMin, prefs::kSSLVersionMin},
-        {switches::kTLS13Variant, prefs::kTLS13Variant},
+        {switches::kSSLVersionMax, prefs::kSSLVersionMax},
 #if defined(OS_ANDROID)
         {switches::kAuthAndroidNegotiateAccountType,
          prefs::kAuthAndroidNegotiateAccountType},
@@ -171,16 +171,6 @@
     SetValue(prefs::kCipherSuiteBlacklist, std::move(list_value),
              WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
   }
-
-  // If a non-disabled TLS 1.3 variant flag is set, enable TLS 1.3 in
-  // SSLVersionMax.
-  if (command_line()->HasSwitch(switches::kTLS13Variant) &&
-      command_line()->GetSwitchValueASCII(switches::kTLS13Variant) !=
-          switches::kTLS13VariantDisabled) {
-    SetValue(prefs::kSSLVersionMax,
-             std::make_unique<base::Value>(switches::kSSLVersionTLSv13),
-             WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
-  }
 }
 
 void ChromeCommandLinePrefStore::ApplyBackgroundModeSwitches() {
diff --git a/chrome/browser/prefs/chrome_command_line_pref_store_ssl_manager_unittest.cc b/chrome/browser/prefs/chrome_command_line_pref_store_ssl_manager_unittest.cc
index 2fd0950..c2b3be2e 100644
--- a/chrome/browser/prefs/chrome_command_line_pref_store_ssl_manager_unittest.cc
+++ b/chrome/browser/prefs/chrome_command_line_pref_store_ssl_manager_unittest.cc
@@ -25,15 +25,14 @@
   base::MessageLoop message_loop_;
 };
 
-// Test that command-line settings for SSL versions and TLS 1.3 variants
-// are respected and that they do not persist to the preferences files.
+// Test that command-line settings for SSL versions are respected and that they
+// do not persist to the preferences files.
 TEST_F(CommandLinePrefStoreSSLManagerTest, CommandLinePrefs) {
   scoped_refptr<TestingPrefStore> local_state_store(new TestingPrefStore());
 
   base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
   command_line.AppendSwitchASCII(switches::kSSLVersionMin, "tls1.1");
   command_line.AppendSwitchASCII(switches::kSSLVersionMax, "tls1.2");
-  command_line.AppendSwitchASCII(switches::kTLS13Variant, "final");
 
   sync_preferences::PrefServiceMockFactory factory;
   factory.set_user_prefs(local_state_store);
@@ -51,10 +50,8 @@
   // Command-line flags should be respected.
   EXPECT_EQ(network::mojom::SSLVersion::kTLS11,
             context_params->initial_ssl_config->version_min);
-  EXPECT_EQ(network::mojom::SSLVersion::kTLS13,
+  EXPECT_EQ(network::mojom::SSLVersion::kTLS12,
             context_params->initial_ssl_config->version_max);
-  EXPECT_EQ(network::mojom::TLS13Variant::kFinal,
-            context_params->initial_ssl_config->tls13_variant);
 
   // Explicitly double-check the settings are not in the preference store.
   const PrefService::Preference* version_min_pref =
@@ -65,74 +62,10 @@
       local_state->FindPreference(prefs::kSSLVersionMax);
   EXPECT_FALSE(version_max_pref->IsUserModifiable());
 
-  const PrefService::Preference* tls13_variant_pref =
-      local_state->FindPreference(prefs::kTLS13Variant);
-  EXPECT_FALSE(tls13_variant_pref->IsUserModifiable());
-
   std::string version_min_str;
   std::string version_max_str;
-  std::string tls13_variant_str;
   EXPECT_FALSE(
       local_state_store->GetString(prefs::kSSLVersionMin, &version_min_str));
   EXPECT_FALSE(
       local_state_store->GetString(prefs::kSSLVersionMax, &version_max_str));
-  EXPECT_FALSE(
-      local_state_store->GetString(prefs::kTLS13Variant, &tls13_variant_str));
-}
-
-// Test that setting an enabled TLS 1.3 variant correctly sets SSLVersionMax.
-TEST_F(CommandLinePrefStoreSSLManagerTest, TLS13VariantEnabled) {
-  scoped_refptr<TestingPrefStore> local_state_store =
-      base::MakeRefCounted<TestingPrefStore>();
-
-  base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
-  command_line.AppendSwitchASCII(switches::kTLS13Variant, "final");
-
-  sync_preferences::PrefServiceMockFactory factory;
-  factory.set_user_prefs(local_state_store);
-  factory.set_command_line_prefs(new ChromeCommandLinePrefStore(&command_line));
-  scoped_refptr<PrefRegistrySimple> registry = new PrefRegistrySimple;
-  std::unique_ptr<PrefService> local_state(factory.Create(registry.get()));
-
-  SSLConfigServiceManager::RegisterPrefs(registry.get());
-
-  network::mojom::NetworkContextParamsPtr context_params =
-      network::mojom::NetworkContextParams::New();
-  std::unique_ptr<SSLConfigServiceManager> config_manager(
-      SSLConfigServiceManager::CreateDefaultManager(local_state.get()));
-  config_manager->AddToNetworkContextParams(context_params.get());
-
-  // Command-line flags should be respected.
-  EXPECT_EQ(network::mojom::SSLVersion::kTLS13,
-            context_params->initial_ssl_config->version_max);
-  EXPECT_EQ(network::mojom::TLS13Variant::kFinal,
-            context_params->initial_ssl_config->tls13_variant);
-}
-
-// Test that setting a disabled TLS 1.3 variant correctly sets SSLVersionMax.
-TEST_F(CommandLinePrefStoreSSLManagerTest, TLS13VariantDisabled) {
-  scoped_refptr<TestingPrefStore> local_state_store =
-      base::MakeRefCounted<TestingPrefStore>();
-
-  base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
-  command_line.AppendSwitchASCII(switches::kSSLVersionMax, "tls1.3");
-  command_line.AppendSwitchASCII(switches::kTLS13Variant, "disabled");
-
-  sync_preferences::PrefServiceMockFactory factory;
-  factory.set_user_prefs(local_state_store);
-  factory.set_command_line_prefs(new ChromeCommandLinePrefStore(&command_line));
-  scoped_refptr<PrefRegistrySimple> registry = new PrefRegistrySimple;
-  std::unique_ptr<PrefService> local_state(factory.Create(registry.get()));
-
-  SSLConfigServiceManager::RegisterPrefs(registry.get());
-
-  network::mojom::NetworkContextParamsPtr context_params =
-      network::mojom::NetworkContextParams::New();
-  std::unique_ptr<SSLConfigServiceManager> config_manager(
-      SSLConfigServiceManager::CreateDefaultManager(local_state.get()));
-  config_manager->AddToNetworkContextParams(context_params.get());
-
-  // Command-line flags should be respected.
-  EXPECT_EQ(network::mojom::SSLVersion::kTLS12,
-            context_params->initial_ssl_config->version_max);
 }
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc
index 2792982f..92f842b 100644
--- a/chrome/browser/prerender/prerender_browsertest.cc
+++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -57,7 +57,6 @@
 #include "chrome/browser/prerender/prerender_test_utils.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_io_data.h"
-#include "chrome/browser/speech/tts_controller_delegate_impl.h"
 #include "chrome/browser/task_manager/mock_web_contents_task_manager.h"
 #include "chrome/browser/task_manager/providers/web_contents/web_contents_tags_manager.h"
 #include "chrome/browser/task_manager/task_manager_browsertest_util.h"
@@ -3462,11 +3461,11 @@
 class TtsPlatformMock : public content::TtsPlatform {
  public:
   TtsPlatformMock() : speaking_requested_(false) {
-    TtsControllerDelegateImpl::GetInstance()->SetTtsPlatform(this);
+    content::TtsController::GetInstance()->SetTtsPlatform(this);
   }
 
   virtual ~TtsPlatformMock() {
-    TtsControllerDelegateImpl::GetInstance()->SetTtsPlatform(
+    content::TtsController::GetInstance()->SetTtsPlatform(
         TtsPlatform::GetInstance());
   }
 
@@ -3505,8 +3504,7 @@
 
   void Resume() override {}
 
-  bool LoadBuiltInTtsExtension(
-      content::BrowserContext* browser_context) override {
+  bool LoadBuiltInTtsEngine(content::BrowserContext* browser_context) override {
     return false;
   }
 
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_login.html b/chrome/browser/resources/chromeos/login/custom_elements_login.html
index 36d289b..058144b 100644
--- a/chrome/browser/resources/chromeos/login/custom_elements_login.html
+++ b/chrome/browser/resources/chromeos/login/custom_elements_login.html
@@ -26,6 +26,7 @@
 <include src="oobe_reset_confirmation_overlay.html">
 <include src="oobe_voice_interaction_value_prop.html">
 <include src="oobe_wait_for_container_ready.html">
+<include src="oobe_supervision_transition.html">
 <include src="encryption_migration.html">
 <include src="enrollment_license_card.html">
 <include src="sync_consent.html">
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_login.js b/chrome/browser/resources/chromeos/login/custom_elements_login.js
index b008807..ca82561 100644
--- a/chrome/browser/resources/chromeos/login/custom_elements_login.js
+++ b/chrome/browser/resources/chromeos/login/custom_elements_login.js
@@ -32,6 +32,7 @@
 // <include src="encryption_migration.js">
 // <include src="oobe_voice_interaction_value_prop.js">
 // <include src="oobe_wait_for_container_ready.js">
+// <include src="oobe_supervision_transition.js">
 // <include src="enrollment_license_card.js">
 // <include src="sync_consent.js">
 // <include src="fingerprint_setup.js">
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_oobe.html b/chrome/browser/resources/chromeos/login/custom_elements_oobe.html
index b58dcf2d..ccf1175 100644
--- a/chrome/browser/resources/chromeos/login/custom_elements_oobe.html
+++ b/chrome/browser/resources/chromeos/login/custom_elements_oobe.html
@@ -33,6 +33,7 @@
 <include src="oobe_welcome.html">
 <include src="oobe_voice_interaction_value_prop.html">
 <include src="oobe_wait_for_container_ready.html">
+<include src="oobe_supervision_transition.html">
 <include src="offline_ad_login.html">
 <include src="active_directory_password_change.html">
 <include src="arc_terms_of_service.html">
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_oobe.js b/chrome/browser/resources/chromeos/login/custom_elements_oobe.js
index bf47099e..b75bf6b9 100644
--- a/chrome/browser/resources/chromeos/login/custom_elements_oobe.js
+++ b/chrome/browser/resources/chromeos/login/custom_elements_oobe.js
@@ -46,6 +46,7 @@
 // <include src="arc_terms_of_service.js">
 // <include src="oobe_voice_interaction_value_prop.js">
 // <include src="oobe_wait_for_container_ready.js">
+// <include src="oobe_supervision_transition.js">
 // <include src="enrollment_license_card.js">
 // <include src="sync_consent.js">
 // <include src="fingerprint_setup.js">
diff --git a/chrome/browser/resources/chromeos/login/login.js b/chrome/browser/resources/chromeos/login/login.js
index 8fddfea..34408f3 100644
--- a/chrome/browser/resources/chromeos/login/login.js
+++ b/chrome/browser/resources/chromeos/login/login.js
@@ -57,6 +57,7 @@
       login.EncryptionMigrationScreen.register();
       login.VoiceInteractionValuePropScreen.register();
       login.WaitForContainerReadyScreen.register();
+      login.SupervisionTransitionScreen.register();
       login.UpdateRequiredScreen.register();
       login.DemoSetupScreen.register();
       login.DiscoverScreen.register();
diff --git a/chrome/browser/resources/chromeos/login/login_non_lock_shared.html b/chrome/browser/resources/chromeos/login/login_non_lock_shared.html
index a31aae07..763d0a9 100644
--- a/chrome/browser/resources/chromeos/login/login_non_lock_shared.html
+++ b/chrome/browser/resources/chromeos/login/login_non_lock_shared.html
@@ -16,6 +16,7 @@
 <link rel="stylesheet" href="oobe_screen_user_image.css">
 <link rel="stylesheet" href="oobe_screen_voice_interaction_value_prop.css">
 <link rel="stylesheet" href="oobe_screen_wait_for_container_ready.css">
+<link rel="stylesheet" href="oobe_screen_supervision_transition.css">
 
 <link rel="stylesheet" href="screen_app_launch_splash.css">
 <link rel="stylesheet" href="screen_arc_kiosk_splash.css">
diff --git a/chrome/browser/resources/chromeos/login/login_non_lock_shared.js b/chrome/browser/resources/chromeos/login/login_non_lock_shared.js
index 5d7e8d7..67c9428 100644
--- a/chrome/browser/resources/chromeos/login/login_non_lock_shared.js
+++ b/chrome/browser/resources/chromeos/login/login_non_lock_shared.js
@@ -15,6 +15,7 @@
 // <include src="oobe_screen_user_image.js">
 // <include src="oobe_screen_voice_interaction_value_prop.js">
 // <include src="oobe_screen_wait_for_container_ready.js">
+// <include src="oobe_screen_supervision_transition.js">
 // <include src="oobe_screen_assistant_optin_flow.js">
 // <include src="oobe_select.js">
 
diff --git a/chrome/browser/resources/chromeos/login/login_screens.html b/chrome/browser/resources/chromeos/login/login_screens.html
index ca1ca5cb..753d4302a 100644
--- a/chrome/browser/resources/chromeos/login/login_screens.html
+++ b/chrome/browser/resources/chromeos/login/login_screens.html
@@ -5,6 +5,7 @@
 <include src="oobe_screen_user_image.html">
 <include src="oobe_screen_voice_interaction_value_prop.html">
 <include src="oobe_screen_wait_for_container_ready.html">
+<include src="oobe_screen_supervision_transition.html">
 <include src="oobe_screen_assistant_optin_flow.html">
 <include src="../../../../../ui/login/account_picker/screen_account_picker.html">
 <include src="screen_arc_terms_of_service.html">
diff --git a/chrome/browser/resources/chromeos/login/md_login.js b/chrome/browser/resources/chromeos/login/md_login.js
index e5afcaa..7be4f3c 100644
--- a/chrome/browser/resources/chromeos/login/md_login.js
+++ b/chrome/browser/resources/chromeos/login/md_login.js
@@ -57,6 +57,7 @@
       login.EncryptionMigrationScreen.register();
       login.VoiceInteractionValuePropScreen.register();
       login.WaitForContainerReadyScreen.register();
+      login.SupervisionTransitionScreen.register();
       login.UpdateRequiredScreen.register();
       login.DiscoverScreen.register();
       login.MarketingOptInScreen.register();
diff --git a/chrome/browser/resources/chromeos/login/md_login_screens.html b/chrome/browser/resources/chromeos/login/md_login_screens.html
index 8239a4cb..a21a6eb 100644
--- a/chrome/browser/resources/chromeos/login/md_login_screens.html
+++ b/chrome/browser/resources/chromeos/login/md_login_screens.html
@@ -5,6 +5,7 @@
 <include src="oobe_screen_user_image.html">
 <include src="oobe_screen_voice_interaction_value_prop.html">
 <include src="oobe_screen_wait_for_container_ready.html">
+<include src="oobe_screen_supervision_transition.html">
 <include src="oobe_screen_assistant_optin_flow.html">
 <include src="../../../../../ui/login/account_picker/md_screen_account_picker.html">
 <include src="screen_arc_terms_of_service.html">
diff --git a/chrome/browser/resources/chromeos/login/oobe.js b/chrome/browser/resources/chromeos/login/oobe.js
index 78de013..65296c9 100644
--- a/chrome/browser/resources/chromeos/login/oobe.js
+++ b/chrome/browser/resources/chromeos/login/oobe.js
@@ -66,6 +66,7 @@
       login.ActiveDirectoryPasswordChangeScreen.register(/* lazyInit= */ true);
       login.VoiceInteractionValuePropScreen.register();
       login.WaitForContainerReadyScreen.register();
+      login.SupervisionTransitionScreen.register();
       login.DemoSetupScreen.register();
       login.DemoPreferencesScreen.register();
       login.DiscoverScreen.register();
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_supervision_transition.css b/chrome/browser/resources/chromeos/login/oobe_screen_supervision_transition.css
new file mode 100644
index 0000000..1d39d3b6
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_supervision_transition.css
@@ -0,0 +1,10 @@
+/* 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. */
+
+#supervision-transition {
+  display: flex;
+  flex-flow: column;
+  font-size: 16px;
+  min-height: 0;
+}
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_supervision_transition.html b/chrome/browser/resources/chromeos/login/oobe_screen_supervision_transition.html
new file mode 100644
index 0000000..f2a5e26c
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_supervision_transition.html
@@ -0,0 +1,9 @@
+<!-- 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. -->
+
+<div class="step faded hidden no-logo" id="supervision-transition"
+    role="group" hidden>
+  <supervision-transition-md id="supervision-transition-md">
+  </supervision-transition-md>
+</div>
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_supervision_transition.js b/chrome/browser/resources/chromeos/login/oobe_screen_supervision_transition.js
new file mode 100644
index 0000000..6ed2a1a
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_supervision_transition.js
@@ -0,0 +1,25 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Oobe Supervision Transition screen implementation.
+ */
+
+login.createScreen(
+    'SupervisionTransitionScreen', 'supervision-transition', function() {
+      return {
+        /** @override */
+        get defaultControl() {
+          return $('supervision-transition-md');
+        },
+
+        /** @override */
+        onBeforeShow: function(data) {
+          Oobe.getInstance().headerHidden = true;
+          $('supervision-transition-md')
+              .setIsRemovingSupervision(
+                  data['isRemovingSupervision'] ? true : false);
+        },
+      };
+    });
diff --git a/chrome/browser/resources/chromeos/login/oobe_screens.html b/chrome/browser/resources/chromeos/login/oobe_screens.html
index 153304f..0a22569 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screens.html
+++ b/chrome/browser/resources/chromeos/login/oobe_screens.html
@@ -14,6 +14,7 @@
 <include src="oobe_screen_hid_detection.html">
 <include src="oobe_screen_voice_interaction_value_prop.html">
 <include src="oobe_screen_wait_for_container_ready.html">
+<include src="oobe_screen_supervision_transition.html">
 <include src="oobe_screen_demo_setup.html">
 <include src="oobe_screen_demo_preferences.html">
 <include src="oobe_screen_assistant_optin_flow.html">
diff --git a/chrome/browser/resources/chromeos/login/oobe_supervision_transition.css b/chrome/browser/resources/chromeos/login/oobe_supervision_transition.css
new file mode 100644
index 0000000..2e4abdf
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/oobe_supervision_transition.css
@@ -0,0 +1,13 @@
+/* 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. */
+
+paper-progress {
+  --paper-progress-active-color: rgb(66, 133, 244);
+  --paper-progress-container-color: rgb(206, 224, 252);
+  --paper-progress-secondary-color: rgb(66, 133, 244);
+  display: block;
+  height: 3px;
+  padding: 40px 0 0 0;
+  width: 100%;
+}
diff --git a/chrome/browser/resources/chromeos/login/oobe_supervision_transition.html b/chrome/browser/resources/chromeos/login/oobe_supervision_transition.html
new file mode 100644
index 0000000..b21e969
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/oobe_supervision_transition.html
@@ -0,0 +1,38 @@
+<!-- Copyright 2018 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+
+<dom-module id="supervision-transition-md">
+  <template>
+    <link rel="stylesheet" href="oobe_flex_layout.css">
+    <link rel="stylesheet" href="oobe_supervision_transition.css">
+    <oobe-dialog id="supervisionTransitionDialog">
+      <iron-icon src="chrome://oobe/supervision_icon.png" slot="oobe-icon">
+      </iron-icon>
+      <h1 slot="title" id="supervisionTitle">
+        <div hidden="[[isRemovingSupervision_]]">
+          $i18n{addingSupervisionTitle}
+        </div>
+        <div hidden="[[!isRemovingSupervision_]]">
+          $i18n{removingSupervisionTitle}
+        </div>
+      </h1>
+      <div slot="subtitle">$i18n{supervisionTransitionIntroMessage}</div>
+      <div slot="footer">
+        <paper-progress class="slow" indeterminate>
+        </paper-progress>
+      </div>
+    </oobe-dialog>
+    <oobe-dialog id="supervisionTransitionErrorDialog" has-buttons hidden>
+      <iron-icon src="chrome://oobe/supervision_icon.png" slot="oobe-icon">
+      </iron-icon>
+      <h1 slot="title">$i18n{supervisionTransitionErrorTitle}</h1>
+      <div slot="subtitle">$i18n{supervisionTransitionErrorMessage}</div>
+      <div slot="bottom-buttons" class="layout horizontal end-justified">
+        <oobe-text-button on-tap="onAcceptAndContinue_" inverse>
+          <div>$i18n{supervisionTransitionButton}</div>
+        </oobe-text-button>
+      </div>
+    </oobe-dialog>
+  </template>
+</dom-module>
diff --git a/chrome/browser/resources/chromeos/login/oobe_supervision_transition.js b/chrome/browser/resources/chromeos/login/oobe_supervision_transition.js
new file mode 100644
index 0000000..548e2d2
--- /dev/null
+++ b/chrome/browser/resources/chromeos/login/oobe_supervision_transition.js
@@ -0,0 +1,49 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Polymer element for displaying material design supervision
+ * transition screen.
+ */
+
+Polymer({
+  is: 'supervision-transition-md',
+
+  behaviors: [OobeDialogHostBehavior],
+
+  properties: {
+    /**
+     * Flag that determines whether supervision is being removed or added.
+     */
+    isRemovingSupervision_: Boolean,
+  },
+
+  setIsRemovingSupervision: function(is_removing_supervision) {
+    this.isRemovingSupervision_ = is_removing_supervision;
+  },
+
+  /** @override */
+  attached: function() {
+    cr.addWebUIListener(
+        'supervision-transition-failed',
+        this.showSupervisionTransitionFailedScreen_.bind(this));
+  },
+
+  /** @private */
+  showSupervisionTransitionFailedScreen_: function() {
+    this.$.supervisionTransitionDialog.hidden = true;
+    this.$.supervisionTransitionErrorDialog.hidden = false;
+    this.$.supervisionTransitionErrorDialog.show();
+    this.$.supervisionTransitionErrorDialog.focus();
+  },
+
+  /**
+   * On-tap event handler for OK button.
+   *
+   * @private
+   */
+  onAcceptAndContinue_: function() {
+    chrome.send('finishSupervisionTransition');
+  },
+});
diff --git a/chrome/browser/resources/chromeos/supervision/supervision_icon.png b/chrome/browser/resources/chromeos/supervision/supervision_icon.png
new file mode 100644
index 0000000..6c8d786
--- /dev/null
+++ b/chrome/browser/resources/chromeos/supervision/supervision_icon.png
Binary files differ
diff --git a/chrome/browser/resources/local_ntp/local_ntp.html b/chrome/browser/resources/local_ntp/local_ntp.html
index edaf4df..b1bfba6 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.html
+++ b/chrome/browser/resources/local_ntp/local_ntp.html
@@ -124,19 +124,18 @@
     </div>
   </dialog>
 
-  <!-- TODO(crbug.com/896461): Add a11y to doodle sharing. -->
   <dialog id="ddlsd">
     <div id="ddlsd-title"></div>
-    <button id="ddlsd-close" title="Close"></button>
+    <button id="ddlsd-close"></button>
     <div id="ddlsd-content">
-      <button id="ddlsd-fbb" class="ddlsd-sbtn" title="Facebook"></button>
-      <button id="ddlsd-twb" class="ddlsd-sbtn" title="Twitter"></button>
-      <button id="ddlsd-emb" class="ddlsd-sbtn" title="Email"></button>
+      <button id="ddlsd-fbb" class="ddlsd-sbtn"></button>
+      <button id="ddlsd-twb" class="ddlsd-sbtn"></button>
+      <button id="ddlsd-emb" class="ddlsd-sbtn"></button>
       <hr id="ddlsd-hr">
       <div id="ddlsd-link">
-        <button id="ddlsd-copy" title="Copy"></button>
+        <button id="ddlsd-copy"></button>
         <span id="ddlsd-text-ctr">
-          <input type="text" id="ddlsd-text" dir="ltr" title="Share Link">
+          <input type="text" id="ddlsd-text" dir="ltr">
         </span>
       </div>
     </div>
diff --git a/chrome/browser/resources/local_ntp/local_ntp.js b/chrome/browser/resources/local_ntp/local_ntp.js
index a448042..51c891b 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.js
+++ b/chrome/browser/resources/local_ntp/local_ntp.js
@@ -1657,6 +1657,7 @@
   var shareButtonImg = document.createElement('img');
   shareButtonImg.id = IDS.DOODLE_SHARE_BUTTON_IMG;
   shareButtonWrapper.appendChild(shareButtonImg);
+  shareButtonWrapper.title = configData.translatedStrings.shareDoodle;
 
   shareButtonWrapper.style.left = targetDoodle.metadata.shareButtonX + 'px';
   shareButtonWrapper.style.top = targetDoodle.metadata.shareButtonY + 'px';
@@ -1716,6 +1717,7 @@
   };
 
   closeButton.onclick = closeDialog;
+  closeButton.title = configData.translatedStrings.shareClose;
   shareDialog.onclick = function(e) {
     if (e.target == shareDialog) {
       closeDialog();
@@ -1734,28 +1736,33 @@
         '&hashtag=' + encodeURIComponent('#GoogleDoodle');
     window.open(url);
   };
+  facebookButton.title = configData.translatedStrings.shareFacebook;
 
   twitterButton.onclick = function() {
     var url = 'https://twitter.com/intent/tweet' +
         '?text=' + encodeURIComponent(title + '\n' + shortLink);
     window.open(url);
   };
+  twitterButton.title = configData.translatedStrings.shareTwitter;
 
   mailButton.onclick = function() {
     var url = 'mailto:?subject=' + encodeURIComponent(title) +
         '&body=' + encodeURIComponent(shortLink);
     document.location.href = url;
   };
+  mailButton.title = configData.translatedStrings.shareMail;
 
   linkText.value = shortLink;
   linkText.onclick = function() {
     linkText.select();
   };
   linkText.setAttribute('readonly', true);
+  linkText.title = configData.translatedStrings.shareLink;
   copyButton.onclick = function() {
     linkText.select();
     document.execCommand('copy');
   };
+  copyButton.title = configData.translatedStrings.copyLink;
 };
 
 
diff --git a/chrome/browser/resources/omnibox/omnibox.css b/chrome/browser/resources/omnibox/omnibox.css
index d0336d7b..40e175bb 100644
--- a/chrome/browser/resources/omnibox/omnibox.css
+++ b/chrome/browser/resources/omnibox/omnibox.css
@@ -183,3 +183,22 @@
 .cell-contents-and-description .pair-item:first-child {
   color: blue;
 }
+
+.cell-fill-and-inline .pair-item {
+  display: inline-block;
+  vertical-align: middle;
+  word-break: break-all;
+}
+
+.cell-fill-and-inline .pair-item:first-child {
+  border: 1px solid white;
+}
+
+.cell-fill-and-inline .pair-item:nth-child(2):not(:empty) {
+  border: 1px solid;
+  font-weight: bold;
+}
+
+.cell-fill-and-inline .overlap-warning {
+  color: red;
+}
diff --git a/chrome/browser/resources/omnibox/omnibox_column_widths.css b/chrome/browser/resources/omnibox/omnibox_column_widths.css
index e7c50f87..0b9ae40 100644
--- a/chrome/browser/resources/omnibox/omnibox_column_widths.css
+++ b/chrome/browser/resources/omnibox/omnibox_column_widths.css
@@ -18,11 +18,7 @@
   width: 220%;
 }
 
-.header-fill-into-edit {
-  width: 180%;
-}
-
-.header-inline-autocompletion {
+.header-fill-and-inline {
   width: 180%;
 }
 
diff --git a/chrome/browser/resources/omnibox/omnibox_output.js b/chrome/browser/resources/omnibox/omnibox_output.js
index 78c33d82..77f1247b 100644
--- a/chrome/browser/resources/omnibox/omnibox_output.js
+++ b/chrome/browser/resources/omnibox/omnibox_output.js
@@ -487,19 +487,19 @@
     constructor() {
       super();
 
-      const container = document.createElement('span');
-      container.classList.add('pair-container');
-      this.appendChild(container);
+      this.container_ = document.createElement('div');
+      this.container_.classList.add('pair-container');
+      this.appendChild(this.container_);
 
       /** @type {!Element} */
       this.first_ = document.createElement('div');
       this.first_.classList.add('pair-item');
-      container.appendChild(this.first_);
+      this.container_.appendChild(this.first_);
 
       /** @type {!Element} */
       this.second_ = document.createElement('div');
       this.second_.classList.add('pair-item');
-      container.appendChild(this.second_);
+      this.container_.appendChild(this.second_);
     }
 
     /** @private @override */
@@ -514,6 +514,32 @@
     }
   }
 
+  class OutputOverlappingPairProperty extends OutputPairProperty {
+    constructor() {
+      super();
+
+      this.notOverlapWarning_ = document.createElement('div');
+      this.notOverlapWarning_.classList.add('overlap-warning');
+      this.container_.appendChild(this.notOverlapWarning_);
+    }
+
+    /** @private @override */
+    render_() {
+      const overlap = this.values_[0].endsWith(this.values_[1]);
+      const firstText = this.values_[1] && overlap ?
+          this.values_[0].slice(0, -this.values_[1].length) :
+          this.values_[0];
+
+      this.first_.textContent = firstText;
+      this.second_.textContent = this.values_[1];
+      this.notOverlapWarning_.textContent = overlap ?
+          '' :
+          `btw, these texts do not overlap; '${
+              this.values_[1]}' was expected to be a suffix of '${
+              this.values_[0]}'`;
+    }
+  }
+
   class OutputBooleanProperty extends OutputProperty {
     constructor() {
       super();
@@ -698,6 +724,12 @@
      * @return {!Array<string>}
      */
     static textToWords_(text) {
+      const MAX_TEXT_LENGTH = 200;
+      if (text.length > MAX_TEXT_LENGTH) {
+        text = text.slice(0, MAX_TEXT_LENGTH);
+        console.warn(`text to be filtered too long, truncatd; max length: ${
+            MAX_TEXT_LENGTH}, truncated text: ${text}`);
+      }
       return text.match(/[a-z]+|[A-Z][a-z]*|\d+|./g) || [];
     }
   }
@@ -777,14 +809,12 @@
         'URL', '', 'destinationUrl', true, 'The URL for the result.',
         ['destinationUrl'], OutputLinkProperty),
     new Column(
-        'Fill Into Edit', '', 'fillIntoEdit', false,
-        'The text shown in the omnibox when the result is selected.',
-        ['fillIntoEdit'], OutputTextProperty),
-    new Column(
-        'Inline Autocompletion', '', 'inlineAutocompletion', false,
-        'The text shown in the omnibox as a blue highlight selection ' +
+        'Fill & Inline', '', 'fillAndInline', false,
+        'The text shown in the omnibox when the result is selected. / The ' +
+            'text shown in the omnibox as a blue highlight selection ' +
             'following the cursor, if this match is shown inline.',
-        ['inlineAutocompletion'], OutputTextProperty),
+        ['fillIntoEdit', 'inlineAutocompletion'],
+        OutputOverlappingPairProperty),
     new Column(
         'Del', '', 'deletable', false,
         'A green checkmark indicates that the result can be deleted from the ' +
@@ -841,6 +871,9 @@
   customElements.define(
       'output-pair-property', OutputPairProperty, {extends: 'td'});
   customElements.define(
+      'output-overlapping-pair-property', OutputOverlappingPairProperty,
+      {extends: 'td'});
+  customElements.define(
       'output-boolean-property', OutputBooleanProperty, {extends: 'td'});
   customElements.define(
       'output-json-property', OutputJsonProperty, {extends: 'td'});
diff --git a/chrome/browser/resources/print_preview/new/destination_settings.html b/chrome/browser/resources/print_preview/new/destination_settings.html
index f26075f9..f23b7bb 100644
--- a/chrome/browser/resources/print_preview/new/destination_settings.html
+++ b/chrome/browser/resources/print_preview/new/destination_settings.html
@@ -24,10 +24,14 @@
 <dom-module id="print-preview-destination-settings">
   <template>
     <style include="print-preview-shared paper-button-style throbber cr-hidden-style">
+      div.button-wrapper {
+        display: inline-block;
+      }
+
       paper-button {
         margin: 2px;
         margin-top: 8px;
-        width: 89px;
+        min-width: 89px;
       }
 
       .throbber {
@@ -109,7 +113,7 @@
     </print-preview-settings-section>
     <print-preview-settings-section>
       <div slot="title"></div>
-      <div slot="controls">
+      <div slot="controls" class="button-wrapper">
         <paper-button
           disabled$="[[shouldDisableButton_(destinationStore, disabled,
                                             state, noDestinationsFound)]]"
diff --git a/chrome/browser/resources/print_preview/new/settings_section.html b/chrome/browser/resources/print_preview/new/settings_section.html
index a01102f..10dec7d 100644
--- a/chrome/browser/resources/print_preview/new/settings_section.html
+++ b/chrome/browser/resources/print_preview/new/settings_section.html
@@ -23,6 +23,7 @@
         flex-direction: column;
         justify-content: center;
         min-height: 38px;
+        word-break: break-word;
       }
 
       ::slotted([slot=controls]) {
@@ -37,7 +38,6 @@
         line-height: calc(20/13 * 1em);
         padding-inline-end: var(--policy-icon-padding);
         width: calc(75px - var(--policy-icon-padding));
-        word-break: break-word;
       }
 
       :host([managed]:not([show-policy-on-end])) ::slotted([slot=title]) {
diff --git a/chrome/browser/resources/settings/a11y_page/a11y_page.html b/chrome/browser/resources/settings/a11y_page/a11y_page.html
index aa40bde8..6a399f4 100644
--- a/chrome/browser/resources/settings/a11y_page/a11y_page.html
+++ b/chrome/browser/resources/settings/a11y_page/a11y_page.html
@@ -5,7 +5,6 @@
 <link rel="import" href="../settings_shared_css.html">
 
 <if expr="chromeos">
-<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
 <link rel="import" href="manage_a11y_page.html">
 <link rel="import" href="../controls/settings_toggle_button.html">
 <link rel="import" href="../settings_page/settings_animated_pages.html">
@@ -19,7 +18,7 @@
 <if expr="chromeos">
     <settings-animated-pages id="pages" current-route="{{currentRoute}}"
         section="a11y" focus-config="[[focusConfig_]]">
-      <neon-animatable route-path="default">
+      <div route-path="default">
         <settings-toggle-button id="optionsInMenuToggle"
             label="$i18n{optionsInMenuLabel}"
             pref="{{prefs.settings.a11y.enable_menu}}">
@@ -37,7 +36,7 @@
                 aria-describedby="themesSecondary"></button>
           </paper-icon-button-light>
         </div>
-      </neon-animatable>
+      </div>
 
       <template is="dom-if" route-path="/manageAccessibility">
         <settings-subpage
diff --git a/chrome/browser/resources/settings/about_page/about_page.html b/chrome/browser/resources/settings/about_page/about_page.html
index 207d4920..72c5f7e 100644
--- a/chrome/browser/resources/settings/about_page/about_page.html
+++ b/chrome/browser/resources/settings/about_page/about_page.html
@@ -19,7 +19,6 @@
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 
 <if expr="chromeos">
@@ -114,7 +113,7 @@
       <settings-section page-title="$i18n{aboutPageTitle}" section="about">
         <settings-animated-pages id="pages" section="about"
             focus-config="[[focusConfig_]]">
-          <neon-animatable route-path="default">
+          <div route-path="default">
             <div class="settings-box two-line">
               <img id="product-logo" on-click="onProductLogoTap_"
                   srcset="chrome://theme/current-channel-logo@1x 1x,
@@ -254,7 +253,7 @@
                 on-click="onDetailedBuildInfoTap_"
                 label="$i18n{aboutDetailedBuildInfo}"></cr-link-row>
 </if>
-          </neon-animatable>
+          </div>
 <if expr="chromeos">
           <template is="dom-if" route-path="/help/details">
             <settings-subpage page-title="$i18n{aboutDetailedBuildInfo}">
diff --git a/chrome/browser/resources/settings/android_apps_page/android_apps_page.html b/chrome/browser/resources/settings/android_apps_page/android_apps_page.html
index 7bfe7a2b7..a4d27d0 100644
--- a/chrome/browser/resources/settings/android_apps_page/android_apps_page.html
+++ b/chrome/browser/resources/settings/android_apps_page/android_apps_page.html
@@ -2,7 +2,6 @@
 
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="../i18n_setup.html">
@@ -19,7 +18,7 @@
 
     <settings-animated-pages id="pages" section="androidApps"
         focus-config="[[focusConfig_]]">
-      <neon-animatable route-path="default">
+      <div route-path="default">
         <template is="dom-if" if="[[havePlayStoreApp]]" restamp>
           <div id="android-apps" class="settings-box two-line first"
               actionable$="[[androidAppsInfo.playStoreEnabled]]"
@@ -56,7 +55,7 @@
           <settings-android-settings-element>
           </settings-android-settings-element>
         </template>
-      </neon-animatable>
+      </div>
 
       <template is="dom-if" route-path="/androidApps/details">
         <settings-subpage
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.html b/chrome/browser/resources/settings/appearance_page/appearance_page.html
index 23c0b7d..ca2ba675 100644
--- a/chrome/browser/resources/settings/appearance_page/appearance_page.html
+++ b/chrome/browser/resources/settings/appearance_page/appearance_page.html
@@ -3,7 +3,6 @@
 <link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/md_select_css.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="appearance_browser_proxy.html">
 <link rel="import" href="../controls/controlled_radio_button.html">
@@ -45,7 +44,7 @@
     </style>
     <settings-animated-pages id="pages" section="appearance"
         focus-config="[[focusConfig_]]">
-      <neon-animatable route-path="default">
+      <div route-path="default">
 <if expr="chromeos">
         <cr-link-row icon-class="icon-external" id="wallpaperButton"
             hidden="[[!pageVisibility.setWallpaper]]"
@@ -179,7 +178,7 @@
             label="$i18n{warnBeforeQuitting}">
         </settings-toggle-button>
 </if>
-      </neon-animatable>
+      </div>
       <template is="dom-if" route-path="/fonts">
         <settings-subpage
             associated-control="[[$$('#customize-fonts-subpage-trigger')]]"
diff --git a/chrome/browser/resources/settings/autofill_page/autofill_page.html b/chrome/browser/resources/settings/autofill_page/autofill_page.html
index 773bf44..350d7a0f 100644
--- a/chrome/browser/resources/settings/autofill_page/autofill_page.html
+++ b/chrome/browser/resources/settings/autofill_page/autofill_page.html
@@ -2,7 +2,6 @@
 
 <link rel="import" href="chrome://resources/cr_elements/cr_link_row/cr_link_row.html">
 <link rel="import" href="chrome://resources/html/cr.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
 <link rel="import" href="autofill_section.html">
 <link rel="import" href="passwords_section.html">
 <link rel="import" href="payments_section.html">
@@ -24,7 +23,7 @@
     </style>
     <settings-animated-pages id="pages" section="autofill"
         focus-config="[[focusConfig_]]">
-      <neon-animatable route-path="default">
+      <div route-path="default">
         <cr-link-row id="passwordManagerButton" start-icon="settings20:vpn-key"
             label="$i18n{passwords}" icon-class="subpage-arrow"
             on-click="onPasswordsClick_"></cr-link-row>
@@ -36,7 +35,7 @@
             start-icon="settings20:location-on" label="$i18n{addressesTitle}"
             icon-class="subpage-arrow" on-click="onAddressesClick_">
         </cr-link-row>
-      </neon-animatable>
+      </div>
       <template is="dom-if" route-path="/passwords">
         <settings-subpage
             associated-control="[[$$('#passwordManagerButton')]]"
diff --git a/chrome/browser/resources/settings/bluetooth_page/BUILD.gn b/chrome/browser/resources/settings/bluetooth_page/BUILD.gn
index 4f962207..3113995 100644
--- a/chrome/browser/resources/settings/bluetooth_page/BUILD.gn
+++ b/chrome/browser/resources/settings/bluetooth_page/BUILD.gn
@@ -14,6 +14,7 @@
 
 js_library("bluetooth_page") {
   deps = [
+    ":bluetooth_system_on_extensions",
     "..:route",
     "../prefs:prefs_behavior",
     "../settings_page:settings_animated_pages",
@@ -32,6 +33,7 @@
 
 js_library("bluetooth_subpage") {
   deps = [
+    ":bluetooth_system_on_extensions",
     "..:route",
     "//ui/webui/resources/cr_elements:cr_scrollable_behavior",
     "//ui/webui/resources/js:assert",
@@ -49,8 +51,16 @@
 
 js_library("bluetooth_device_list_item") {
   deps = [
+    ":bluetooth_system_on_extensions",
     "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
     "//ui/webui/resources/js:i18n_behavior",
   ]
   externs_list = [ "$externs_path/bluetooth.js" ]
 }
+
+js_library("bluetooth_system_on_extensions") {
+  sources = []
+  deps = [
+    "//services/device/public/mojom:mojom_js_externs",
+  ]
+}
diff --git a/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html b/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html
index cb249be..3defed79 100644
--- a/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html
+++ b/chrome/browser/resources/settings/bluetooth_page/bluetooth_page.html
@@ -4,7 +4,6 @@
 <link rel="import" href="chrome://resources/cr_elements/icons.html">
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../icons.html">
@@ -21,7 +20,7 @@
     </style>
     <settings-animated-pages id="pages" section="bluetooth"
         focus-config="[[focusConfig_]]">
-      <neon-animatable route-path="default">
+      <div route-path="default">
         <template is="dom-if" if="[[!isSecondaryUser_]]">
           <div id="bluetoothDevices"
               class="settings-box two-line" actionable on-click="onTap_">
@@ -63,7 +62,7 @@
             </div>
           </div>
         </template>
-      </neon-animatable>
+      </div>
 
       <template is="dom-if" route-path="/bluetoothDevices">
         <settings-subpage associated-control="[[$$('#bluetoothDevices')]]"
diff --git a/chrome/browser/resources/settings/crostini_page/crostini_page.html b/chrome/browser/resources/settings/crostini_page/crostini_page.html
index 32c230c5..5ba740a8 100644
--- a/chrome/browser/resources/settings/crostini_page/crostini_page.html
+++ b/chrome/browser/resources/settings/crostini_page/crostini_page.html
@@ -2,7 +2,6 @@
 
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_indicator.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../prefs/prefs_behavior.html">
@@ -20,7 +19,7 @@
 
     <settings-animated-pages id="pages" section="crostini"
         focus-config="[[focusConfig_]]">
-      <neon-animatable route-path="default">
+      <div route-path="default">
         <div id="crostini" class="settings-box two-line first"
             actionable$="[[prefs.crostini.enabled.value]]"
             on-click="onSubpageTap_">
@@ -52,7 +51,7 @@
             </paper-button>
           </template>
         </div>
-      </neon-animatable>
+      </div>
 
       <template is="dom-if" route-path="/crostini/details">
         <settings-subpage
diff --git a/chrome/browser/resources/settings/date_time_page/date_time_page.html b/chrome/browser/resources/settings/date_time_page/date_time_page.html
index ab71d7b0a..c98fd163 100644
--- a/chrome/browser/resources/settings/date_time_page/date_time_page.html
+++ b/chrome/browser/resources/settings/date_time_page/date_time_page.html
@@ -30,7 +30,7 @@
     </style>
     <settings-animated-pages id="pages" section="dateTime"
         focus-config="[[focusConfig_]]">
-      <neon-animatable id="main" route-path="default">
+      <div id="main" route-path="default">
         <template is="dom-if"
             if="[[!prefs.cros.flags.fine_grained_time_zone_detection_enabled.value]]"
             restamp>
@@ -84,7 +84,7 @@
             <button aria-label="$i18n{setDateTime}"></button>
           </paper-icon-button-light>
         </div>
-      </neon-animatable>
+      </div>
       <template is="dom-if" route-path="/dateTime/timeZone">
         <settings-subpage data-route="DATETIME_TIMEZONE_SUBPAGE"
             associated-control="[[$$('#timeZoneSettingsTrigger')]]"
diff --git a/chrome/browser/resources/settings/device_page/device_page.html b/chrome/browser/resources/settings/device_page/device_page.html
index d9a55adb..1785424 100644
--- a/chrome/browser/resources/settings/device_page/device_page.html
+++ b/chrome/browser/resources/settings/device_page/device_page.html
@@ -2,7 +2,6 @@
 
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="device_page_browser_proxy.html">
 <link rel="import" href="display.html">
@@ -22,7 +21,7 @@
     <style include="settings-shared"></style>
     <settings-animated-pages id="pages" section="device"
         focus-config="[[focusConfig_]]">
-      <neon-animatable id="main" route-path="default">
+      <div id="main" route-path="default">
         <div id="pointersRow" class="settings-box first"
             on-click="onPointersTap_" actionable>
           <div class="start">
@@ -73,7 +72,7 @@
             </paper-icon-button-light>
           </div>
         </template>
-      </neon-animatable>
+      </div>
       <template is="dom-if" route-path="/pointer-overlay">
         <settings-subpage
             associated-control="[[$$('#pointersRow')]]"
diff --git a/chrome/browser/resources/settings/downloads_page/downloads_page.html b/chrome/browser/resources/settings/downloads_page/downloads_page.html
index 3557cf1..36266078 100644
--- a/chrome/browser/resources/settings/downloads_page/downloads_page.html
+++ b/chrome/browser/resources/settings/downloads_page/downloads_page.html
@@ -21,7 +21,7 @@
     </style>
   <settings-animated-pages id="pages" section="downloads"
       focus-config="[[focusConfig_]]">
-    <neon-animatable route-path="default">
+    <div route-path="default">
       <div class="settings-box first two-line">
         <div class="start">
           <div>$i18n{downloadLocation}</div>
@@ -72,7 +72,7 @@
           </paper-button>
         </div>
       </template>
-    </neon-animatable>
+    </div>
 
 <if expr="chromeos">
     <template is="dom-if" route-path="/smbShares">
diff --git a/chrome/browser/resources/settings/internet_page/internet_page.html b/chrome/browser/resources/settings/internet_page/internet_page.html
index 5544462..69ef3e6 100644
--- a/chrome/browser/resources/settings/internet_page/internet_page.html
+++ b/chrome/browser/resources/settings/internet_page/internet_page.html
@@ -7,7 +7,6 @@
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="../prefs/prefs.html">
 <link rel="import" href="../route.html">
@@ -32,7 +31,7 @@
     </style>
     <settings-animated-pages id="pages" section="internet"
         focus-config="[[focusConfig_]]">
-      <neon-animatable route-path="default">
+      <div route-path="default">
         <network-summary default-network="{{defaultNetwork}}"
             device-states="{{deviceStates}}"
             networking-private="[[networkingPrivate]]">
@@ -96,7 +95,7 @@
             <div>$i18n{internetAddConnectionNotAllowed}</div>
           </div>
         </template>
-      </neon-animatable>
+      </div>
 
       <template is="dom-if" route-path="/networkDetail" no-search restamp>
         <settings-subpage page-title="$i18n{internetDetailPageTitle}">
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.html b/chrome/browser/resources/settings/languages_page/languages_page.html
index bada775..a572a31 100644
--- a/chrome/browser/resources/settings/languages_page/languages_page.html
+++ b/chrome/browser/resources/settings/languages_page/languages_page.html
@@ -9,7 +9,6 @@
 <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
@@ -118,7 +117,7 @@
     </settings-languages>
     <settings-animated-pages id="pages" section="languages"
         focus-config="[[focusConfig_]]">
-      <neon-animatable route-path="default">
+      <div route-path="default">
         <div class$="settings-box first [[getLanguageListTwoLine_()]]"
             actionable on-click="toggleExpandButton_">
           <div class="start">
@@ -374,7 +373,7 @@
             </cr-action-menu>
           </template>
         </cr-lazy-render>
-      </neon-animatable>
+      </div>
 <if expr="chromeos">
       <template is="dom-if" route-path="/inputMethods">
         <settings-subpage
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_page.html b/chrome/browser/resources/settings/multidevice_page/multidevice_page.html
index 78aba32..07759bb8 100644
--- a/chrome/browser/resources/settings/multidevice_page/multidevice_page.html
+++ b/chrome/browser/resources/settings/multidevice_page/multidevice_page.html
@@ -5,7 +5,6 @@
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="../i18n_setup.html">
@@ -31,7 +30,7 @@
     </style>
     <settings-animated-pages id="pages" section="multidevice"
         focus-config="[[focusConfig_]]">
-      <neon-animatable route-path="default">
+      <div route-path="default">
         <div id="multidevice-item"
             class="settings-box two-line"
             on-click="handleItemClick_"
@@ -88,7 +87,7 @@
             </settings-multidevice-feature-toggle>
           </template>
         </div>
-      </neon-animatable>
+      </div>
       <template is="dom-if" route-path="/multidevice/features" restamp>
         <settings-subpage associated-control="[[$$('#multidevice-item')]]"
             page-title="[[getLabelText_(pageContentData)]]">
diff --git a/chrome/browser/resources/settings/people_page/people_page.html b/chrome/browser/resources/settings/people_page/people_page.html
index dfd7b8a..bcd7a77 100644
--- a/chrome/browser/resources/settings/people_page/people_page.html
+++ b/chrome/browser/resources/settings/people_page/people_page.html
@@ -8,7 +8,6 @@
 <link rel="import" href="chrome://resources/html/util.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="../controls/settings_toggle_button.html">
@@ -128,7 +127,7 @@
     </style>
     <settings-animated-pages id="pages" section="people"
         focus-config="[[focusConfig_]]">
-      <neon-animatable route-path="default">
+      <div route-path="default">
 <if expr="not chromeos">
         <template is="dom-if" if="[[shouldShowSyncAccountControl_(diceEnabled_,
             syncStatus.syncSystemEnabled, syncStatus.signinAllowed)]]">
@@ -317,7 +316,7 @@
         </div>
 </if>
 
-      </neon-animatable>
+      </div>
       <template is="dom-if" route-path="/syncSetup"
           no-search="[[!isAdvancedSyncSettingsSearchable_(
               syncStatus, unifiedConsentEnabled_)]]">
diff --git a/chrome/browser/resources/settings/printing_page/printing_page.html b/chrome/browser/resources/settings/printing_page/printing_page.html
index 59372e8..10e4104d 100644
--- a/chrome/browser/resources/settings/printing_page/printing_page.html
+++ b/chrome/browser/resources/settings/printing_page/printing_page.html
@@ -1,6 +1,5 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
-<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="cloud_printers.html">
 <link rel="import" href="../route.html">
@@ -19,7 +18,7 @@
     <style include="settings-shared"></style>
     <settings-animated-pages id="pages" section="printing"
         focus-config="[[focusConfig_]]">
-      <neon-animatable route-path="default">
+      <div route-path="default">
 <if expr="chromeos">
         <div id="cupsPrinters" class="settings-box first"
             on-click="onTapCupsPrinters_" actionable>
@@ -45,7 +44,7 @@
             <button aria-label="$i18n{cloudPrintersTitle}"></button>
           </paper-icon-button-light>
         </div>
-      </neon-animatable>
+      </div>
 <if expr="chromeos">
       <template is="dom-if" route-path="/cupsPrinters">
         <settings-subpage
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html
index fda182d..1977e118 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_page.html
+++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -5,7 +5,6 @@
 <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="../clear_browsing_data_dialog/clear_browsing_data_dialog.html">
@@ -83,7 +82,7 @@
     </template>
     <settings-animated-pages id="pages" section="privacy"
         focus-config="[[focusConfig_]]">
-      <neon-animatable route-path="default">
+      <div route-path="default">
         <template is="dom-if" if="[[!unifiedConsentEnabled_]]">
           <div class="settings-box first">
             <p class="privacy-explanation">
@@ -181,7 +180,7 @@
             hidden="[[!unifiedConsentEnabled_]]">
           <div class="start">$i18nRaw{syncAndPersonalizationLink}</div>
         </div>
-      </neon-animatable>
+      </div>
 <if expr="use_nss_certs">
       <template is="dom-if" route-path="/certificates">
         <settings-subpage
diff --git a/chrome/browser/resources/settings/reset_page/reset_page.html b/chrome/browser/resources/settings/reset_page/reset_page.html
index 0727c4b..a70c57aa 100644
--- a/chrome/browser/resources/settings/reset_page/reset_page.html
+++ b/chrome/browser/resources/settings/reset_page/reset_page.html
@@ -3,7 +3,6 @@
 <link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html">
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="reset_profile_dialog.html">
@@ -24,7 +23,7 @@
   <template>
     <style include="settings-shared"></style>
     <settings-animated-pages id="reset-pages" section="reset">
-      <neon-animatable route-path="default">
+      <div route-path="default">
         <div class="settings-box first" id="resetProfile"
             on-click="onShowResetProfileDialog_" actionable>
           <div id="resetProfileTrigger" class="start">$i18n{resetTrigger}</div>
@@ -85,7 +84,7 @@
           </div>
         </template>
 </if>
-      </neon-animatable>
+      </div>
 <if expr="_google_chrome and is_win">
       <template is="dom-if" route-path="/cleanup">
         <settings-subpage id="chromeCleanupSubpage"
diff --git a/chrome/browser/resources/settings/search_page/search_page.html b/chrome/browser/resources/settings/search_page/search_page.html
index 0fa27b3..d3fa90a 100644
--- a/chrome/browser/resources/settings/search_page/search_page.html
+++ b/chrome/browser/resources/settings/search_page/search_page.html
@@ -4,7 +4,6 @@
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/md_select_css.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/neon-animatable.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
 <link rel="import" href="../controls/extension_controlled_indicator.html">
@@ -43,7 +42,7 @@
     </style>
     <settings-animated-pages id="pages" section="search"
         focus-config="[[focusConfig_]]">
-      <neon-animatable route-path="default">
+      <div route-path="default">
         <!-- Omnibox search engine -->
         <div class="settings-box first block">
           <div id="search-wrapper">
@@ -119,7 +118,7 @@
           </div>
         </template>
 </if>
-      </neon-animatable>
+      </div>
       <template is="dom-if" route-path="/searchEngines">
         <settings-subpage
             associated-control="[[$$('#engines-subpage-trigger')]]"
diff --git a/chrome/browser/resources/settings/settings_page/settings_animated_pages.js b/chrome/browser/resources/settings/settings_page/settings_animated_pages.js
index 5f0612e..0d79416 100644
--- a/chrome/browser/resources/settings/settings_page/settings_animated_pages.js
+++ b/chrome/browser/resources/settings/settings_page/settings_animated_pages.js
@@ -94,10 +94,9 @@
       subpagePaths.push(settings.routes.INTERNET_NETWORKS.path);
     // </if>
 
-    // Only handle iron-select events from neon-animatable elements and the
+    // Only handle iron-select events from div elements and the
     // given whitelist of settings-subpage instances.
-    // TODO(dpapad): Remove neon-animatable here.
-    const whitelist = ['settings-subpage#site-settings', 'neon-animatable'];
+    const whitelist = ['settings-subpage#site-settings', 'div[route-path]'];
     whitelist.push.apply(
         whitelist,
         subpagePaths.map(path => `settings-subpage[route-path="${path}"]`));
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc
index fcd6211..f8409cc 100644
--- a/chrome/browser/search/local_ntp_source.cc
+++ b/chrome/browser/search/local_ntp_source.cc
@@ -238,6 +238,22 @@
     AddString(translated_strings.get(), "linkCantRemove",
               IDS_NTP_CUSTOM_LINKS_CANT_REMOVE);
 
+    // Doodle Sharing
+    AddString(translated_strings.get(), "shareDoodle",
+              IDS_NTP_DOODLE_SHARE_LABEL);
+    AddString(translated_strings.get(), "shareClose",
+              IDS_NTP_DOODLE_SHARE_DIALOG_CLOSE_LABEL);
+    AddString(translated_strings.get(), "shareFacebook",
+              IDS_NTP_DOODLE_SHARE_DIALOG_FACEBOOK_LABEL);
+    AddString(translated_strings.get(), "shareTwitter",
+              IDS_NTP_DOODLE_SHARE_DIALOG_TWITTER_LABEL);
+    AddString(translated_strings.get(), "shareMail",
+              IDS_NTP_DOODLE_SHARE_DIALOG_MAIL_LABEL);
+    AddString(translated_strings.get(), "copyLink",
+              IDS_NTP_DOODLE_SHARE_DIALOG_COPY_LABEL);
+    AddString(translated_strings.get(), "shareLink",
+              IDS_NTP_DOODLE_SHARE_DIALOG_LINK_LABEL);
+
     // Voice Search
     AddString(translated_strings.get(), "audioError",
               IDS_NEW_TAB_VOICE_AUDIO_ERROR);
diff --git a/chrome/browser/speech/extension_api/tts_engine_extension_api.cc b/chrome/browser/speech/extension_api/tts_engine_extension_api.cc
index 572ea06..18907e4 100644
--- a/chrome/browser/speech/extension_api/tts_engine_extension_api.cc
+++ b/chrome/browser/speech/extension_api/tts_engine_extension_api.cc
@@ -205,7 +205,7 @@
       result_voice.name = voice.voice_name;
       result_voice.lang = voice.lang;
       result_voice.remote = voice.remote;
-      result_voice.extension_id = extension->id();
+      result_voice.engine_id = extension->id();
 
       for (auto iter = voice.event_types.begin();
            iter != voice.event_types.end(); ++iter) {
@@ -285,7 +285,7 @@
   auto event = std::make_unique<extensions::Event>(
       extensions::events::TTS_ENGINE_ON_SPEAK, tts_engine_events::kOnSpeak,
       std::move(args), profile);
-  EventRouter::Get(profile)->DispatchEventToExtension(utterance->extension_id(),
+  EventRouter::Get(profile)->DispatchEventToExtension(utterance->engine_id(),
                                                       std::move(event));
 }
 
@@ -295,7 +295,7 @@
   auto event = std::make_unique<extensions::Event>(
       extensions::events::TTS_ENGINE_ON_STOP, tts_engine_events::kOnStop,
       std::move(args), profile);
-  EventRouter::Get(profile)->DispatchEventToExtension(utterance->extension_id(),
+  EventRouter::Get(profile)->DispatchEventToExtension(utterance->engine_id(),
                                                       std::move(event));
 }
 
@@ -306,7 +306,7 @@
       extensions::events::TTS_ENGINE_ON_PAUSE, tts_engine_events::kOnPause,
       std::move(args), profile);
   EventRouter* event_router = EventRouter::Get(profile);
-  std::string id = utterance->extension_id();
+  std::string id = utterance->engine_id();
   event_router->DispatchEventToExtension(id, std::move(event));
   WarnIfMissingPauseOrResumeListener(profile, event_router, id);
 }
@@ -318,12 +318,12 @@
       extensions::events::TTS_ENGINE_ON_RESUME, tts_engine_events::kOnResume,
       std::move(args), profile);
   EventRouter* event_router = EventRouter::Get(profile);
-  std::string id = utterance->extension_id();
+  std::string id = utterance->engine_id();
   event_router->DispatchEventToExtension(id, std::move(event));
   WarnIfMissingPauseOrResumeListener(profile, event_router, id);
 }
 
-bool TtsExtensionEngine::LoadBuiltInTtsExtension(
+bool TtsExtensionEngine::LoadBuiltInTtsEngine(
     content::BrowserContext* browser_context) {
 #if defined(OS_CHROMEOS)
   Profile* profile = Profile::FromBrowserContext(browser_context);
diff --git a/chrome/browser/speech/extension_api/tts_engine_extension_api.h b/chrome/browser/speech/extension_api/tts_engine_extension_api.h
index 854419a..6cbedb48 100644
--- a/chrome/browser/speech/extension_api/tts_engine_extension_api.h
+++ b/chrome/browser/speech/extension_api/tts_engine_extension_api.h
@@ -37,8 +37,7 @@
   void Stop(content::Utterance* utterance) override;
   void Pause(content::Utterance* utterance) override;
   void Resume(content::Utterance* utterance) override;
-  bool LoadBuiltInTtsExtension(
-      content::BrowserContext* browser_context) override;
+  bool LoadBuiltInTtsEngine(content::BrowserContext* browser_context) override;
 };
 
 // Function that allows tts engines to update its list of supported voices at
diff --git a/chrome/browser/speech/extension_api/tts_extension_api.cc b/chrome/browser/speech/extension_api/tts_extension_api.cc
index 4c05604..e0979752 100644
--- a/chrome/browser/speech/extension_api/tts_extension_api.cc
+++ b/chrome/browser/speech/extension_api/tts_extension_api.cc
@@ -278,7 +278,7 @@
   utterance->set_can_enqueue(can_enqueue);
   utterance->set_required_event_types(required_event_types);
   utterance->set_desired_event_types(desired_event_types);
-  utterance->set_extension_id(voice_extension_id);
+  utterance->set_engine_id(voice_extension_id);
   utterance->set_options(options.get());
   utterance->set_event_delegate(new TtsExtensionEventHandler(extension_id()));
 
@@ -320,8 +320,8 @@
     result_voice->SetBoolean(constants::kRemoteKey, voice.remote);
     if (!voice.lang.empty())
       result_voice->SetString(constants::kLangKey, voice.lang);
-    if (!voice.extension_id.empty())
-      result_voice->SetString(constants::kExtensionIdKey, voice.extension_id);
+    if (!voice.engine_id.empty())
+      result_voice->SetString(constants::kExtensionIdKey, voice.engine_id);
 
     auto event_types = std::make_unique<base::ListValue>();
     for (auto iter = voice.events.begin(); iter != voice.events.end(); ++iter) {
diff --git a/chrome/browser/speech/extension_api/tts_extension_apitest.cc b/chrome/browser/speech/extension_api/tts_extension_apitest.cc
index c67e171..aa29bf420 100644
--- a/chrome/browser/speech/extension_api/tts_extension_apitest.cc
+++ b/chrome/browser/speech/extension_api/tts_extension_apitest.cc
@@ -60,8 +60,7 @@
       const content::Utterance* utterance,
       const content::VoiceData& voice_data) override {}
 
-  bool LoadBuiltInTtsExtension(
-      content::BrowserContext* browser_context) override {
+  bool LoadBuiltInTtsEngine(content::BrowserContext* browser_context) override {
     return false;
   }
 
@@ -162,9 +161,9 @@
                  content::TtsEventType event_type,
                  int char_index,
                  const std::string& message) {
-    TtsControllerDelegateImpl* tts_controller_delegate =
-        TtsControllerDelegateImpl::GetInstance();
-    if (wait_for_non_empty_queue && tts_controller_delegate->QueueSize() == 0) {
+    content::TtsController* tts_controller =
+        content::TtsController::GetInstance();
+    if (wait_for_non_empty_queue && tts_controller->QueueSize() == 0) {
       base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
           FROM_HERE,
           base::Bind(&MockTtsPlatformImpl::SendEvent, ptr_factory_.GetWeakPtr(),
@@ -173,8 +172,7 @@
       return;
     }
 
-    content::TtsController::GetInstance()->OnTtsEvent(utterance_id, event_type,
-                                                      char_index, message);
+    tts_controller->OnTtsEvent(utterance_id, event_type, char_index, message);
   }
 
  private:
@@ -229,8 +227,10 @@
  public:
   void SetUpInProcessBrowserTestFixture() override {
     ExtensionApiTest::SetUpInProcessBrowserTestFixture();
-    TtsControllerDelegateImpl::GetInstance()->SetTtsPlatform(
-        &mock_platform_impl_);
+    content::TtsController* tts_controller =
+        content::TtsController::GetInstance();
+    tts_controller->SetTtsPlatform(&mock_platform_impl_);
+    tts_controller->SetTtsEngineDelegate(TtsExtensionEngine::GetInstance());
   }
 
   void AddNetworkSpeechSynthesisExtension() {
diff --git a/chrome/browser/speech/tts_chromeos.cc b/chrome/browser/speech/tts_chromeos.cc
index 42ec4ba..33d4074 100644
--- a/chrome/browser/speech/tts_chromeos.cc
+++ b/chrome/browser/speech/tts_chromeos.cc
@@ -18,12 +18,12 @@
                                               ->IsConnected();
 }
 
-bool TtsPlatformImplChromeOs::LoadBuiltInTtsExtension(
+bool TtsPlatformImplChromeOs::LoadBuiltInTtsEngine(
     content::BrowserContext* browser_context) {
   content::TtsEngineDelegate* tts_engine_delegate =
       content::TtsController::GetInstance()->GetTtsEngineDelegate();
   if (tts_engine_delegate)
-    return tts_engine_delegate->LoadBuiltInTtsExtension(browser_context);
+    return tts_engine_delegate->LoadBuiltInTtsEngine(browser_context);
   return false;
 }
 
diff --git a/chrome/browser/speech/tts_chromeos.h b/chrome/browser/speech/tts_chromeos.h
index 5891488..cbd7b234 100644
--- a/chrome/browser/speech/tts_chromeos.h
+++ b/chrome/browser/speech/tts_chromeos.h
@@ -14,8 +14,7 @@
  public:
   // TtsPlatform overrides:
   bool PlatformImplAvailable() override;
-  bool LoadBuiltInTtsExtension(
-      content::BrowserContext* browser_context) override;
+  bool LoadBuiltInTtsEngine(content::BrowserContext* browser_context) override;
   bool Speak(int utterance_id,
              const std::string& utterance,
              const std::string& lang,
diff --git a/chrome/browser/speech/tts_controller_delegate_impl.cc b/chrome/browser/speech/tts_controller_delegate_impl.cc
index 5fa6a5b..b33861e 100644
--- a/chrome/browser/speech/tts_controller_delegate_impl.cc
+++ b/chrome/browser/speech/tts_controller_delegate_impl.cc
@@ -24,14 +24,12 @@
 #include "ui/base/l10n/l10n_util.h"
 
 namespace {
-// A value to be used to indicate that there is no char index available.
-const int kInvalidCharIndex = -1;
 
 #if defined(OS_CHROMEOS)
 bool VoiceIdMatches(const std::string& voice_id,
                     const content::VoiceData& voice) {
   if (voice_id.empty() || voice.name.empty() ||
-      (voice.extension_id.empty() && !voice.native))
+      (voice.engine_id.empty() && !voice.native))
     return false;
   std::unique_ptr<base::DictionaryValue> json =
       base::DictionaryValue::From(base::JSONReader::Read(voice_id));
@@ -41,31 +39,10 @@
   json->GetString("extension", &default_extension_id);
   if (voice.native)
     return default_name == voice.name && default_extension_id.empty();
-  return default_name == voice.name &&
-         default_extension_id == voice.extension_id;
+  return default_name == voice.name && default_extension_id == voice.engine_id;
 }
 #endif  // defined(OS_CHROMEOS)
 
-// IMPORTANT!
-// These values are written to logs.  Do not renumber or delete
-// existing items; add new entries to the end of the list.
-enum class UMATextToSpeechEvent {
-  START = 0,
-  END = 1,
-  WORD = 2,
-  SENTENCE = 3,
-  MARKER = 4,
-  INTERRUPTED = 5,
-  CANCELLED = 6,
-  SPEECH_ERROR = 7,
-  PAUSE = 8,
-  RESUME = 9,
-
-  // This must always be the last enum. It's okay for its value to
-  // increase, but none of the other enum values may change.
-  COUNT
-};
-
 }  // namespace
 
 //
@@ -78,296 +55,9 @@
 }
 
 TtsControllerDelegateImpl::TtsControllerDelegateImpl()
-    : current_utterance_(nullptr),
-      paused_(false),
-      tts_platform_(nullptr),
-      tts_engine_delegate_(nullptr) {}
+    : tts_engine_delegate_(nullptr) {}
 
 TtsControllerDelegateImpl::~TtsControllerDelegateImpl() {
-  if (current_utterance_) {
-    current_utterance_->Finish();
-    delete current_utterance_;
-  }
-
-  // Clear any queued utterances too.
-  ClearUtteranceQueue(false);  // Don't sent events.
-}
-
-void TtsControllerDelegateImpl::SpeakOrEnqueue(content::Utterance* utterance) {
-  // If we're paused and we get an utterance that can't be queued,
-  // flush the queue but stay in the paused state.
-  if (paused_ && !utterance->can_enqueue()) {
-    utterance_queue_.push(utterance);
-    Stop();
-    paused_ = true;
-    return;
-  }
-
-  if (paused_ || (IsSpeaking() && utterance->can_enqueue())) {
-    utterance_queue_.push(utterance);
-  } else {
-    Stop();
-    SpeakNow(utterance);
-  }
-}
-
-void TtsControllerDelegateImpl::SpeakNow(content::Utterance* utterance) {
-  // Ensure we have all built-in voices loaded. This is a no-op if already
-  // loaded.
-  bool loaded_built_in =
-      GetTtsPlatform()->LoadBuiltInTtsExtension(utterance->browser_context());
-
-  // Get all available voices and try to find a matching voice.
-  std::vector<content::VoiceData> voices;
-  GetVoices(utterance->browser_context(), &voices);
-
-  // Get the best matching voice. If nothing matches, just set "native"
-  // to true because that might trigger deferred loading of native voices.
-  int index = GetMatchingVoice(utterance, voices);
-  content::VoiceData voice;
-  if (index >= 0)
-    voice = voices[index];
-  else
-    voice.native = true;
-
-  UpdateUtteranceDefaults(utterance);
-
-  GetTtsPlatform()->WillSpeakUtteranceWithVoice(utterance, voice);
-
-  base::RecordAction(base::UserMetricsAction("TextToSpeech.Speak"));
-  UMA_HISTOGRAM_COUNTS_100000("TextToSpeech.Utterance.TextLength",
-                              utterance->text().size());
-  UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.FromExtensionAPI",
-                        !utterance->src_url().is_empty());
-  UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.HasVoiceName",
-                        !utterance->voice_name().empty());
-  UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.HasLang",
-                        !utterance->lang().empty());
-  UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.HasRate",
-                        utterance->continuous_parameters().rate != 1.0);
-  UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.HasPitch",
-                        utterance->continuous_parameters().pitch != 1.0);
-  UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.HasVolume",
-                        utterance->continuous_parameters().volume != 1.0);
-  UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.Native", voice.native);
-
-  if (!voice.native) {
-#if !defined(OS_ANDROID)
-    DCHECK(!voice.extension_id.empty());
-    current_utterance_ = utterance;
-    utterance->set_extension_id(voice.extension_id);
-    if (tts_engine_delegate_)
-      tts_engine_delegate_->Speak(utterance, voice);
-    bool sends_end_event =
-        voice.events.find(content::TTS_EVENT_END) != voice.events.end();
-    if (!sends_end_event) {
-      utterance->Finish();
-      delete utterance;
-      current_utterance_ = nullptr;
-      SpeakNextUtterance();
-    }
-#endif
-  } else {
-    // It's possible for certain platforms to send start events immediately
-    // during |speak|.
-    current_utterance_ = utterance;
-    GetTtsPlatform()->ClearError();
-    bool success = GetTtsPlatform()->Speak(utterance->id(), utterance->text(),
-                                           utterance->lang(), voice,
-                                           utterance->continuous_parameters());
-    if (!success)
-      current_utterance_ = nullptr;
-
-    // If the native voice wasn't able to process this speech, see if
-    // the browser has built-in TTS that isn't loaded yet.
-    if (!success && loaded_built_in) {
-      utterance_queue_.push(utterance);
-      return;
-    }
-
-    if (!success) {
-      utterance->OnTtsEvent(content::TTS_EVENT_ERROR, kInvalidCharIndex,
-                            GetTtsPlatform()->GetError());
-      delete utterance;
-      return;
-    }
-  }
-}
-
-void TtsControllerDelegateImpl::Stop() {
-  base::RecordAction(base::UserMetricsAction("TextToSpeech.Stop"));
-
-  paused_ = false;
-  if (current_utterance_ && !current_utterance_->extension_id().empty()) {
-    if (tts_engine_delegate_)
-      tts_engine_delegate_->Stop(current_utterance_);
-  } else {
-    GetTtsPlatform()->ClearError();
-    GetTtsPlatform()->StopSpeaking();
-  }
-
-  if (current_utterance_)
-    current_utterance_->OnTtsEvent(content::TTS_EVENT_INTERRUPTED,
-                                   kInvalidCharIndex, std::string());
-  FinishCurrentUtterance();
-  ClearUtteranceQueue(true);  // Send events.
-}
-
-void TtsControllerDelegateImpl::Pause() {
-  base::RecordAction(base::UserMetricsAction("TextToSpeech.Pause"));
-
-  paused_ = true;
-  if (current_utterance_ && !current_utterance_->extension_id().empty()) {
-    if (tts_engine_delegate_)
-      tts_engine_delegate_->Pause(current_utterance_);
-  } else if (current_utterance_) {
-    GetTtsPlatform()->ClearError();
-    GetTtsPlatform()->Pause();
-  }
-}
-
-void TtsControllerDelegateImpl::Resume() {
-  base::RecordAction(base::UserMetricsAction("TextToSpeech.Resume"));
-
-  paused_ = false;
-  if (current_utterance_ && !current_utterance_->extension_id().empty()) {
-    if (tts_engine_delegate_)
-      tts_engine_delegate_->Resume(current_utterance_);
-  } else if (current_utterance_) {
-    GetTtsPlatform()->ClearError();
-    GetTtsPlatform()->Resume();
-  } else {
-    SpeakNextUtterance();
-  }
-}
-
-void TtsControllerDelegateImpl::OnTtsEvent(int utterance_id,
-                                           content::TtsEventType event_type,
-                                           int char_index,
-                                           const std::string& error_message) {
-  // We may sometimes receive completion callbacks "late", after we've
-  // already finished the utterance (for example because another utterance
-  // interrupted or we got a call to Stop). This is normal and we can
-  // safely just ignore these events.
-  if (!current_utterance_ || utterance_id != current_utterance_->id()) {
-    return;
-  }
-
-  UMATextToSpeechEvent metric;
-  switch (event_type) {
-    case content::TTS_EVENT_START:
-      metric = UMATextToSpeechEvent::START;
-      break;
-    case content::TTS_EVENT_END:
-      metric = UMATextToSpeechEvent::END;
-      break;
-    case content::TTS_EVENT_WORD:
-      metric = UMATextToSpeechEvent::WORD;
-      break;
-    case content::TTS_EVENT_SENTENCE:
-      metric = UMATextToSpeechEvent::SENTENCE;
-      break;
-    case content::TTS_EVENT_MARKER:
-      metric = UMATextToSpeechEvent::MARKER;
-      break;
-    case content::TTS_EVENT_INTERRUPTED:
-      metric = UMATextToSpeechEvent::INTERRUPTED;
-      break;
-    case content::TTS_EVENT_CANCELLED:
-      metric = UMATextToSpeechEvent::CANCELLED;
-      break;
-    case content::TTS_EVENT_ERROR:
-      metric = UMATextToSpeechEvent::SPEECH_ERROR;
-      break;
-    case content::TTS_EVENT_PAUSE:
-      metric = UMATextToSpeechEvent::PAUSE;
-      break;
-    case content::TTS_EVENT_RESUME:
-      metric = UMATextToSpeechEvent::RESUME;
-      break;
-    default:
-      NOTREACHED();
-      return;
-  }
-  UMA_HISTOGRAM_ENUMERATION("TextToSpeech.Event", metric,
-                            UMATextToSpeechEvent::COUNT);
-
-  current_utterance_->OnTtsEvent(event_type, char_index, error_message);
-  if (current_utterance_->finished()) {
-    FinishCurrentUtterance();
-    SpeakNextUtterance();
-  }
-}
-
-void TtsControllerDelegateImpl::GetVoices(
-    content::BrowserContext* browser_context,
-    std::vector<content::VoiceData>* out_voices) {
-  content::TtsPlatform* tts_platform = GetTtsPlatform();
-  if (tts_platform) {
-    // Ensure we have all built-in voices loaded. This is a no-op if already
-    // loaded.
-    tts_platform->LoadBuiltInTtsExtension(browser_context);
-    if (tts_platform->PlatformImplAvailable())
-      tts_platform->GetVoices(out_voices);
-  }
-
-  if (browser_context && tts_engine_delegate_)
-    tts_engine_delegate_->GetVoices(browser_context, out_voices);
-}
-
-bool TtsControllerDelegateImpl::IsSpeaking() {
-  return current_utterance_ != nullptr || GetTtsPlatform()->IsSpeaking();
-}
-
-void TtsControllerDelegateImpl::FinishCurrentUtterance() {
-  if (current_utterance_) {
-    if (!current_utterance_->finished())
-      current_utterance_->OnTtsEvent(content::TTS_EVENT_INTERRUPTED,
-                                     kInvalidCharIndex, std::string());
-    delete current_utterance_;
-    current_utterance_ = nullptr;
-  }
-}
-
-void TtsControllerDelegateImpl::SpeakNextUtterance() {
-  if (paused_)
-    return;
-
-  // Start speaking the next utterance in the queue.  Keep trying in case
-  // one fails but there are still more in the queue to try.
-  while (!utterance_queue_.empty() && !current_utterance_) {
-    content::Utterance* utterance = utterance_queue_.front();
-    utterance_queue_.pop();
-    SpeakNow(utterance);
-  }
-}
-
-void TtsControllerDelegateImpl::ClearUtteranceQueue(bool send_events) {
-  while (!utterance_queue_.empty()) {
-    content::Utterance* utterance = utterance_queue_.front();
-    utterance_queue_.pop();
-    if (send_events)
-      utterance->OnTtsEvent(content::TTS_EVENT_CANCELLED, kInvalidCharIndex,
-                            std::string());
-    else
-      utterance->Finish();
-    delete utterance;
-  }
-}
-
-void TtsControllerDelegateImpl::SetTtsPlatform(
-    content::TtsPlatform* tts_platform) {
-  tts_platform_ = tts_platform;
-}
-
-int TtsControllerDelegateImpl::QueueSize() {
-  return static_cast<int>(utterance_queue_.size());
-}
-
-content::TtsPlatform* TtsControllerDelegateImpl::GetTtsPlatform() {
-  if (!tts_platform_)
-    tts_platform_ = content::TtsPlatform::GetInstance();
-  return tts_platform_;
 }
 
 int TtsControllerDelegateImpl::GetMatchingVoice(
@@ -412,8 +102,8 @@
     int score = 0;
 
     // If the extension ID is specified, check for an exact match.
-    if (!utterance->extension_id().empty() &&
-        utterance->extension_id() != voice.extension_id)
+    if (!utterance->engine_id().empty() &&
+        utterance->engine_id() != voice.engine_id)
       continue;
 
     // If the voice name is specified, check for an exact match.
@@ -496,38 +186,28 @@
   return best_score_index;
 }
 
-void TtsControllerDelegateImpl::UpdateUtteranceDefaults(
-    content::Utterance* utterance) {
-  double rate = utterance->continuous_parameters().rate;
-  double pitch = utterance->continuous_parameters().pitch;
-  double volume = utterance->continuous_parameters().volume;
+void TtsControllerDelegateImpl::UpdateUtteranceDefaultsFromPrefs(
+    content::Utterance* utterance,
+    double* rate,
+    double* pitch,
+    double* volume) {
 #if defined(OS_CHROMEOS)
   // Update pitch, rate and volume from user prefs if not set explicitly
   // on this utterance.
   const PrefService* prefs = GetPrefService(utterance);
-  if (rate == blink::kWebSpeechSynthesisDoublePrefNotSet) {
-    rate = prefs ? prefs->GetDouble(prefs::kTextToSpeechRate)
-                 : blink::kWebSpeechSynthesisDefaultTextToSpeechRate;
+  if (*rate == blink::kWebSpeechSynthesisDoublePrefNotSet) {
+    *rate = prefs ? prefs->GetDouble(prefs::kTextToSpeechRate)
+                  : blink::kWebSpeechSynthesisDefaultTextToSpeechRate;
   }
-  if (pitch == blink::kWebSpeechSynthesisDoublePrefNotSet) {
-    pitch = prefs ? prefs->GetDouble(prefs::kTextToSpeechPitch)
-                  : blink::kWebSpeechSynthesisDefaultTextToSpeechPitch;
+  if (*pitch == blink::kWebSpeechSynthesisDoublePrefNotSet) {
+    *pitch = prefs ? prefs->GetDouble(prefs::kTextToSpeechPitch)
+                   : blink::kWebSpeechSynthesisDefaultTextToSpeechPitch;
   }
-  if (volume == blink::kWebSpeechSynthesisDoublePrefNotSet) {
-    volume = prefs ? prefs->GetDouble(prefs::kTextToSpeechVolume)
-                   : blink::kWebSpeechSynthesisDefaultTextToSpeechVolume;
+  if (*volume == blink::kWebSpeechSynthesisDoublePrefNotSet) {
+    *volume = prefs ? prefs->GetDouble(prefs::kTextToSpeechVolume)
+                    : blink::kWebSpeechSynthesisDefaultTextToSpeechVolume;
   }
-#else
-  // Update pitch, rate and volume to defaults if not explicity set on
-  // this utterance.
-  if (rate == blink::kWebSpeechSynthesisDoublePrefNotSet)
-    rate = blink::kWebSpeechSynthesisDefaultTextToSpeechRate;
-  if (pitch == blink::kWebSpeechSynthesisDoublePrefNotSet)
-    pitch = blink::kWebSpeechSynthesisDefaultTextToSpeechPitch;
-  if (volume == blink::kWebSpeechSynthesisDoublePrefNotSet)
-    volume = blink::kWebSpeechSynthesisDefaultTextToSpeechVolume;
 #endif  // defined(OS_CHROMEOS)
-  utterance->set_continuous_parameters(rate, pitch, volume);
 }
 
 const PrefService* TtsControllerDelegateImpl::GetPrefService(
@@ -543,56 +223,6 @@
   return prefs;
 }
 
-void TtsControllerDelegateImpl::VoicesChanged() {
-  // Existence of platform tts indicates explicit requests to tts. Since
-  // |VoicesChanged| can occur implicitly, only send if needed.
-  if (!tts_platform_)
-    return;
-
-  for (auto& delegate : voices_changed_delegates_)
-    delegate.OnVoicesChanged();
-}
-
-void TtsControllerDelegateImpl::AddVoicesChangedDelegate(
-    content::VoicesChangedDelegate* delegate) {
-  voices_changed_delegates_.AddObserver(delegate);
-}
-
-void TtsControllerDelegateImpl::RemoveVoicesChangedDelegate(
-    content::VoicesChangedDelegate* delegate) {
-  voices_changed_delegates_.RemoveObserver(delegate);
-}
-
-void TtsControllerDelegateImpl::RemoveUtteranceEventDelegate(
-    content::UtteranceEventDelegate* delegate) {
-  // First clear any pending utterances with this delegate.
-  base::queue<content::Utterance*> old_queue = utterance_queue_;
-  utterance_queue_ = base::queue<content::Utterance*>();
-  while (!old_queue.empty()) {
-    content::Utterance* utterance = old_queue.front();
-    old_queue.pop();
-    if (utterance->event_delegate() != delegate)
-      utterance_queue_.push(utterance);
-    else
-      delete utterance;
-  }
-
-  if (current_utterance_ && current_utterance_->event_delegate() == delegate) {
-    current_utterance_->set_event_delegate(nullptr);
-    if (!current_utterance_->extension_id().empty()) {
-      if (tts_engine_delegate_)
-        tts_engine_delegate_->Stop(current_utterance_);
-    } else {
-      GetTtsPlatform()->ClearError();
-      GetTtsPlatform()->StopSpeaking();
-    }
-
-    FinishCurrentUtterance();
-    if (!paused_)
-      SpeakNextUtterance();
-  }
-}
-
 void TtsControllerDelegateImpl::SetTtsEngineDelegate(
     content::TtsEngineDelegate* delegate) {
   tts_engine_delegate_ = delegate;
diff --git a/chrome/browser/speech/tts_controller_delegate_impl.h b/chrome/browser/speech/tts_controller_delegate_impl.h
index d20be017..e1c47eb 100644
--- a/chrome/browser/speech/tts_controller_delegate_impl.h
+++ b/chrome/browser/speech/tts_controller_delegate_impl.h
@@ -19,39 +19,23 @@
 #include "content/public/browser/tts_platform.h"
 #include "url/gurl.h"
 
-// Singleton class that manages text-to-speech for the TTS and TTS engine
-// extension APIs, maintaining a queue of pending utterances and keeping
-// track of all state.
+// Singleton class that manages Chrome side logic for TTS and TTS engine
+// extension APIs.
 class TtsControllerDelegateImpl : public content::TtsControllerDelegate {
  public:
   // Get the single instance of this class.
   static TtsControllerDelegateImpl* GetInstance();
 
-  // TtsController methods
-  bool IsSpeaking() override;
-  void SpeakOrEnqueue(content::Utterance* utterance) override;
-  void Stop() override;
-  void Pause() override;
-  void Resume() override;
-  void OnTtsEvent(int utterance_id,
-                  content::TtsEventType event_type,
-                  int char_index,
-                  const std::string& error_message) override;
-  void GetVoices(content::BrowserContext* browser_context,
-                 std::vector<content::VoiceData>* out_voices) override;
-  void VoicesChanged() override;
-  void AddVoicesChangedDelegate(
-      content::VoicesChangedDelegate* delegate) override;
-  void RemoveVoicesChangedDelegate(
-      content::VoicesChangedDelegate* delegate) override;
-  void RemoveUtteranceEventDelegate(
-      content::UtteranceEventDelegate* delegate) override;
+  // TtsControllerDelegate overrides.
+  int GetMatchingVoice(const content::Utterance* utterance,
+                       std::vector<content::VoiceData>& voices) override;
+  void UpdateUtteranceDefaultsFromPrefs(content::Utterance* utterance,
+                                        double* rate,
+                                        double* pitch,
+                                        double* volume) override;
   void SetTtsEngineDelegate(content::TtsEngineDelegate* delegate) override;
   content::TtsEngineDelegate* GetTtsEngineDelegate() override;
 
-  void SetTtsPlatform(content::TtsPlatform* tts_platform);
-  int QueueSize();
-
  protected:
   TtsControllerDelegateImpl();
   ~TtsControllerDelegateImpl() override;
@@ -62,54 +46,11 @@
   FRIEND_TEST_ALL_PREFIXES(TtsControllerTest,
                            TestTtsControllerUtteranceDefaults);
 
-  // Get the platform TTS implementation (or injected mock).
-  content::TtsPlatform* GetTtsPlatform();
-
-  // Start speaking the given utterance. Will either take ownership of
-  // |utterance| or delete it if there's an error. Returns true on success.
-  void SpeakNow(content::Utterance* utterance);
-
-  // Clear the utterance queue. If send_events is true, will send
-  // TTS_EVENT_CANCELLED events on each one.
-  void ClearUtteranceQueue(bool send_events);
-
-  // Finalize and delete the current utterance.
-  void FinishCurrentUtterance();
-
-  // Start speaking the next utterance in the queue.
-  void SpeakNextUtterance();
-
-  // Given an utterance and a vector of voices, return the
-  // index of the voice that best matches the utterance.
-  int GetMatchingVoice(const content::Utterance* utterance,
-                       std::vector<content::VoiceData>& voices);
-
-  // Updates the utterance to have default values for rate, pitch, and
-  // volume if they have not yet been set. On Chrome OS, defaults are
-  // pulled from user prefs, and may not be the same as other platforms.
-  void UpdateUtteranceDefaults(content::Utterance* utterance);
-
   virtual const PrefService* GetPrefService(
       const content::Utterance* utterance);
 
   friend struct base::DefaultSingletonTraits<TtsControllerDelegateImpl>;
 
-  // The current utterance being spoken.
-  content::Utterance* current_utterance_;
-
-  // Whether the queue is paused or not.
-  bool paused_;
-
-  // A queue of utterances to speak after the current one finishes.
-  base::queue<content::Utterance*> utterance_queue_;
-
-  // A set of delegates that want to be notified when the voices change.
-  base::ObserverList<content::VoicesChangedDelegate> voices_changed_delegates_;
-
-  // A pointer to the platform implementation of text-to-speech, for
-  // dependency injection.
-  content::TtsPlatform* tts_platform_;
-
   // The delegate that processes TTS requests with user-installed extensions.
   content::TtsEngineDelegate* tts_engine_delegate_;
 
diff --git a/chrome/browser/speech/tts_controller_delegate_impl_unittest.cc b/chrome/browser/speech/tts_controller_delegate_impl_unittest.cc
new file mode 100644
index 0000000..4be2c7e
--- /dev/null
+++ b/chrome/browser/speech/tts_controller_delegate_impl_unittest.cc
@@ -0,0 +1,259 @@
+// Copyright (c) 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.
+
+// Unit tests for the TTS Controller.
+
+#include "chrome/browser/speech/tts_controller_delegate_impl.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/common/pref_names.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/testing_pref_service.h"
+#include "content/public/browser/tts_controller.h"
+#include "content/public/browser/tts_platform.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/web_speech_synthesis_constants.h"
+
+class TtsControllerTest : public testing::Test {};
+
+// Subclass of TtsController with a public ctor and dtor.
+class MockTtsControllerDelegate : public TtsControllerDelegateImpl {
+ public:
+  MockTtsControllerDelegate() {}
+  ~MockTtsControllerDelegate() override {}
+
+  PrefService* pref_service_ = nullptr;
+
+ private:
+  const PrefService* GetPrefService(
+      const content::Utterance* utterance) override {
+    return pref_service_;
+  }
+};
+
+TEST_F(TtsControllerTest, TestGetMatchingVoice) {
+  std::unique_ptr<MockTtsControllerDelegate> tts_controller_delegate =
+      std::make_unique<MockTtsControllerDelegate>();
+#if defined(OS_CHROMEOS)
+  TestingPrefServiceSimple pref_service_;
+  // Uses default pref voices.
+  std::unique_ptr<base::DictionaryValue> lang_to_voices =
+      std::make_unique<base::DictionaryValue>();
+  lang_to_voices->SetKey(
+      "es", base::Value("{\"name\":\"Voice7\",\"extension\":\"id7\"}"));
+  lang_to_voices->SetKey(
+      "noLanguage", base::Value("{\"name\":\"Android\",\"extension\":\"\"}"));
+  pref_service_.registry()->RegisterDictionaryPref(
+      prefs::kTextToSpeechLangToVoiceName, std::move(lang_to_voices));
+  tts_controller_delegate->pref_service_ = &pref_service_;
+#endif  // defined(OS_CHROMEOS)
+
+  {
+    // Calling GetMatchingVoice with no voices returns -1.
+    content::Utterance utterance(nullptr);
+    std::vector<content::VoiceData> voices;
+    EXPECT_EQ(-1,
+              tts_controller_delegate->GetMatchingVoice(&utterance, voices));
+  }
+
+  {
+    // Calling GetMatchingVoice with any voices returns the first one
+    // even if there are no criteria that match.
+    content::Utterance utterance(nullptr);
+    std::vector<content::VoiceData> voices;
+    voices.push_back(content::VoiceData());
+    voices.push_back(content::VoiceData());
+    EXPECT_EQ(0, tts_controller_delegate->GetMatchingVoice(&utterance, voices));
+  }
+
+  {
+    // If nothing else matches, the English voice is returned.
+    // (In tests the language will always be English.)
+    content::Utterance utterance(nullptr);
+    std::vector<content::VoiceData> voices;
+    content::VoiceData fr_voice;
+    fr_voice.lang = "fr";
+    voices.push_back(fr_voice);
+    content::VoiceData en_voice;
+    en_voice.lang = "en";
+    voices.push_back(en_voice);
+    content::VoiceData de_voice;
+    de_voice.lang = "de";
+    voices.push_back(de_voice);
+    EXPECT_EQ(1, tts_controller_delegate->GetMatchingVoice(&utterance, voices));
+  }
+
+  {
+    // Check precedence of various matching criteria.
+    std::vector<content::VoiceData> voices;
+    content::VoiceData voice0;
+    voices.push_back(voice0);
+    content::VoiceData voice1;
+    voice1.events.insert(content::TTS_EVENT_WORD);
+    voices.push_back(voice1);
+    content::VoiceData voice2;
+    voice2.lang = "de-DE";
+    voices.push_back(voice2);
+    content::VoiceData voice3;
+    voice3.lang = "fr-CA";
+    voices.push_back(voice3);
+    content::VoiceData voice4;
+    voice4.name = "Voice4";
+    voices.push_back(voice4);
+    content::VoiceData voice5;
+    voice5.engine_id = "id5";
+    voices.push_back(voice5);
+    content::VoiceData voice6;
+    voice6.engine_id = "id7";
+    voice6.name = "Voice6";
+    voice6.lang = "es-es";
+    voices.push_back(voice6);
+    content::VoiceData voice7;
+    voice7.engine_id = "id7";
+    voice7.name = "Voice7";
+    voice7.lang = "es-mx";
+    voices.push_back(voice7);
+    content::VoiceData voice8;
+    voice8.engine_id = "";
+    voice8.name = "Android";
+    voice8.lang = "";
+    voice8.native = true;
+    voices.push_back(voice8);
+
+    content::Utterance utterance(nullptr);
+    EXPECT_EQ(0, tts_controller_delegate->GetMatchingVoice(&utterance, voices));
+
+    std::set<content::TtsEventType> types;
+    types.insert(content::TTS_EVENT_WORD);
+    utterance.set_required_event_types(types);
+    EXPECT_EQ(1, tts_controller_delegate->GetMatchingVoice(&utterance, voices));
+
+    utterance.set_lang("de-DE");
+    EXPECT_EQ(2, tts_controller_delegate->GetMatchingVoice(&utterance, voices));
+
+    utterance.set_lang("fr-FR");
+    EXPECT_EQ(3, tts_controller_delegate->GetMatchingVoice(&utterance, voices));
+
+    utterance.set_voice_name("Voice4");
+    EXPECT_EQ(4, tts_controller_delegate->GetMatchingVoice(&utterance, voices));
+
+    utterance.set_voice_name("");
+    utterance.set_engine_id("id5");
+    EXPECT_EQ(5, tts_controller_delegate->GetMatchingVoice(&utterance, voices));
+
+#if defined(OS_CHROMEOS)
+    // Voice6 is matched when the utterance locale exactly matches its locale.
+    utterance.set_engine_id("");
+    utterance.set_lang("es-es");
+    EXPECT_EQ(6, tts_controller_delegate->GetMatchingVoice(&utterance, voices));
+
+    // The 7th voice is the default for "es", even though the utterance is
+    // "es-ar". |voice6| is not matched because it is not the default.
+    utterance.set_engine_id("");
+    utterance.set_lang("es-ar");
+    EXPECT_EQ(7, tts_controller_delegate->GetMatchingVoice(&utterance, voices));
+
+    // The 8th voice is like the built-in "Android" voice, it has no lang
+    // and no extension ID. Make sure it can still be matched.
+    utterance.set_voice_name("Android");
+    utterance.set_engine_id("");
+    utterance.set_lang("");
+    EXPECT_EQ(8, tts_controller_delegate->GetMatchingVoice(&utterance, voices));
+#endif  // defined(OS_CHROMEOS)
+  }
+
+  {
+    // Check voices against system language.
+    std::vector<content::VoiceData> voices;
+    content::VoiceData voice0;
+    voice0.engine_id = "id0";
+    voice0.name = "voice0";
+    voice0.lang = "en-GB";
+    voices.push_back(voice0);
+    content::VoiceData voice1;
+    voice1.engine_id = "id1";
+    voice1.name = "voice1";
+    voice1.lang = "en-US";
+    voices.push_back(voice1);
+    content::Utterance utterance(nullptr);
+
+    // voice1 is matched against the exact default system language.
+    g_browser_process->SetApplicationLocale("en-US");
+    utterance.set_lang("");
+    EXPECT_EQ(1, tts_controller_delegate->GetMatchingVoice(&utterance, voices));
+
+    // voice0 is matched against the system language which has no region piece.
+    g_browser_process->SetApplicationLocale("en");
+    utterance.set_lang("");
+    EXPECT_EQ(0, tts_controller_delegate->GetMatchingVoice(&utterance, voices));
+
+#if defined(OS_CHROMEOS)
+    // Add another preference.
+    std::unique_ptr<base::DictionaryValue> lang_to_voices =
+        std::make_unique<base::DictionaryValue>();
+    lang_to_voices->SetKey(
+        "en", base::Value("{\"name\":\"voice0\",\"extension\":\"id0\"}"));
+
+    pref_service_.SetUserPref(prefs::kTextToSpeechLangToVoiceName,
+                              std::move(lang_to_voices));
+
+    // voice0 is matched against the pref over the system language.
+    g_browser_process->SetApplicationLocale("en-US");
+    EXPECT_EQ(0, tts_controller_delegate->GetMatchingVoice(&utterance, voices));
+#endif  // defined(OS_CHROMEOS)
+  }
+}
+
+#if defined(OS_CHROMEOS)
+TEST_F(TtsControllerTest, TestTtsControllerUtteranceDefaults) {
+  std::unique_ptr<MockTtsControllerDelegate> tts_controller_delegate =
+      std::make_unique<MockTtsControllerDelegate>();
+
+  double rate = blink::kWebSpeechSynthesisDoublePrefNotSet;
+  double pitch = blink::kWebSpeechSynthesisDoublePrefNotSet;
+  double volume = blink::kWebSpeechSynthesisDoublePrefNotSet;
+
+  std::unique_ptr<content::Utterance> utterance1 =
+      std::make_unique<content::Utterance>(nullptr);
+  tts_controller_delegate->UpdateUtteranceDefaultsFromPrefs(
+      utterance1.get(), &rate, &pitch, &volume);
+  // Updated to global defaults.
+  EXPECT_EQ(blink::kWebSpeechSynthesisDefaultTextToSpeechRate, rate);
+  EXPECT_EQ(blink::kWebSpeechSynthesisDefaultTextToSpeechPitch, pitch);
+  EXPECT_EQ(blink::kWebSpeechSynthesisDefaultTextToSpeechVolume, volume);
+
+  // Now we will set prefs and expect those to be used as defaults.
+  rate = blink::kWebSpeechSynthesisDoublePrefNotSet;
+  pitch = blink::kWebSpeechSynthesisDoublePrefNotSet;
+  volume = blink::kWebSpeechSynthesisDoublePrefNotSet;
+  TestingPrefServiceSimple pref_service_;
+  pref_service_.registry()->RegisterDoublePref(prefs::kTextToSpeechRate, 1.5);
+  pref_service_.registry()->RegisterDoublePref(prefs::kTextToSpeechPitch, 2.0);
+  pref_service_.registry()->RegisterDoublePref(prefs::kTextToSpeechVolume, 0.5);
+  tts_controller_delegate->pref_service_ = &pref_service_;
+
+  std::unique_ptr<content::Utterance> utterance2 =
+      std::make_unique<content::Utterance>(nullptr);
+  tts_controller_delegate->UpdateUtteranceDefaultsFromPrefs(
+      utterance2.get(), &rate, &pitch, &volume);
+  // Updated to pref values.
+  EXPECT_EQ(1.5f, rate);
+  EXPECT_EQ(2.0f, pitch);
+  EXPECT_EQ(0.5f, volume);
+
+  // If we explicitly set rate, pitch and volume, they should not be changed.
+  rate = 1.1f;
+  pitch = 1.2f;
+  volume = 1.3f;
+
+  std::unique_ptr<content::Utterance> utterance3 =
+      std::make_unique<content::Utterance>(nullptr);
+  tts_controller_delegate->UpdateUtteranceDefaultsFromPrefs(
+      utterance3.get(), &rate, &pitch, &volume);
+  // Updated to pref values.
+  EXPECT_EQ(1.1f, rate);
+  EXPECT_EQ(1.2f, pitch);
+  EXPECT_EQ(1.3f, volume);
+}
+#endif  // defined(OS_CHROMEOS)
diff --git a/chrome/browser/speech/tts_controller_unittest.cc b/chrome/browser/speech/tts_controller_unittest.cc
deleted file mode 100644
index df8628b..0000000
--- a/chrome/browser/speech/tts_controller_unittest.cc
+++ /dev/null
@@ -1,299 +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.
-
-// Unit tests for the TTS Controller.
-
-#include "content/public/browser/tts_controller.h"
-#include "base/values.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/speech/tts_controller_delegate_impl.h"
-#include "chrome/common/pref_names.h"
-#include "components/prefs/pref_registry_simple.h"
-#include "components/prefs/testing_pref_service.h"
-#include "content/public/browser/tts_platform.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/web_speech_synthesis_constants.h"
-
-class TtsControllerTest : public testing::Test {
-};
-
-// Platform Tts implementation that does nothing.
-class DummyTtsPlatformImpl : public content::TtsPlatform {
- public:
-  DummyTtsPlatformImpl() {}
-  virtual ~DummyTtsPlatformImpl() {}
-  bool PlatformImplAvailable() override { return true; }
-  bool Speak(int utterance_id,
-             const std::string& utterance,
-             const std::string& lang,
-             const content::VoiceData& voice,
-             const content::UtteranceContinuousParameters& params) override {
-    return true;
-  }
-  bool IsSpeaking() override { return false; }
-  bool StopSpeaking() override { return true; }
-  void Pause() override {}
-  void Resume() override {}
-  void GetVoices(std::vector<content::VoiceData>* out_voices) override {}
-  bool LoadBuiltInTtsExtension(
-      content::BrowserContext* browser_context) override {
-    return false;
-  }
-  void WillSpeakUtteranceWithVoice(
-      const content::Utterance* utterance,
-      const content::VoiceData& voice_data) override {}
-  void SetError(const std::string& error) override {}
-  std::string GetError() override { return std::string(); }
-  void ClearError() override {}
-};
-
-// Subclass of TtsController with a public ctor and dtor.
-class TestableTtsController : public TtsControllerDelegateImpl {
- public:
-  TestableTtsController() {}
-  ~TestableTtsController() override {}
-
-  PrefService* pref_service_ = nullptr;
-
- private:
-  const PrefService* GetPrefService(
-      const content::Utterance* utterance) override {
-    return pref_service_;
-  }
-};
-
-TEST_F(TtsControllerTest, TestTtsControllerShutdown) {
-  DummyTtsPlatformImpl platform_impl;
-  TestableTtsController* controller =
-      new TestableTtsController();
-
-  controller->SetTtsPlatform(&platform_impl);
-
-  content::Utterance* utterance1 = new content::Utterance(nullptr);
-  utterance1->set_can_enqueue(true);
-  utterance1->set_src_id(1);
-  controller->SpeakOrEnqueue(utterance1);
-
-  content::Utterance* utterance2 = new content::Utterance(nullptr);
-  utterance2->set_can_enqueue(true);
-  utterance2->set_src_id(2);
-  controller->SpeakOrEnqueue(utterance2);
-
-  // Make sure that deleting the controller when there are pending
-  // utterances doesn't cause a crash.
-  delete controller;
-}
-
-TEST_F(TtsControllerTest, TestGetMatchingVoice) {
-  std::unique_ptr<TestableTtsController> tts_controller =
-      std::make_unique<TestableTtsController>();
-#if defined(OS_CHROMEOS)
-  TestingPrefServiceSimple pref_service_;
-  // Uses default pref voices.
-  std::unique_ptr<base::DictionaryValue> lang_to_voices =
-      std::make_unique<base::DictionaryValue>();
-  lang_to_voices->SetKey(
-      "es", base::Value("{\"name\":\"Voice7\",\"extension\":\"id7\"}"));
-  lang_to_voices->SetKey(
-      "noLanguage", base::Value("{\"name\":\"Android\",\"extension\":\"\"}"));
-  pref_service_.registry()->RegisterDictionaryPref(
-      prefs::kTextToSpeechLangToVoiceName, std::move(lang_to_voices));
-  tts_controller->pref_service_ = &pref_service_;
-#endif  // defined(OS_CHROMEOS)
-
-  {
-    // Calling GetMatchingVoice with no voices returns -1.
-    content::Utterance utterance(nullptr);
-    std::vector<content::VoiceData> voices;
-    EXPECT_EQ(-1, tts_controller->GetMatchingVoice(&utterance, voices));
-  }
-
-  {
-    // Calling GetMatchingVoice with any voices returns the first one
-    // even if there are no criteria that match.
-    content::Utterance utterance(nullptr);
-    std::vector<content::VoiceData> voices;
-    voices.push_back(content::VoiceData());
-    voices.push_back(content::VoiceData());
-    EXPECT_EQ(0, tts_controller->GetMatchingVoice(&utterance, voices));
-  }
-
-  {
-    // If nothing else matches, the English voice is returned.
-    // (In tests the language will always be English.)
-    content::Utterance utterance(nullptr);
-    std::vector<content::VoiceData> voices;
-    content::VoiceData fr_voice;
-    fr_voice.lang = "fr";
-    voices.push_back(fr_voice);
-    content::VoiceData en_voice;
-    en_voice.lang = "en";
-    voices.push_back(en_voice);
-    content::VoiceData de_voice;
-    de_voice.lang = "de";
-    voices.push_back(de_voice);
-    EXPECT_EQ(1, tts_controller->GetMatchingVoice(&utterance, voices));
-  }
-
-  {
-    // Check precedence of various matching criteria.
-    std::vector<content::VoiceData> voices;
-    content::VoiceData voice0;
-    voices.push_back(voice0);
-    content::VoiceData voice1;
-    voice1.events.insert(content::TTS_EVENT_WORD);
-    voices.push_back(voice1);
-    content::VoiceData voice2;
-    voice2.lang = "de-DE";
-    voices.push_back(voice2);
-    content::VoiceData voice3;
-    voice3.lang = "fr-CA";
-    voices.push_back(voice3);
-    content::VoiceData voice4;
-    voice4.name = "Voice4";
-    voices.push_back(voice4);
-    content::VoiceData voice5;
-    voice5.extension_id = "id5";
-    voices.push_back(voice5);
-    content::VoiceData voice6;
-    voice6.extension_id = "id7";
-    voice6.name = "Voice6";
-    voice6.lang = "es-es";
-    voices.push_back(voice6);
-    content::VoiceData voice7;
-    voice7.extension_id = "id7";
-    voice7.name = "Voice7";
-    voice7.lang = "es-mx";
-    voices.push_back(voice7);
-    content::VoiceData voice8;
-    voice8.extension_id = "";
-    voice8.name = "Android";
-    voice8.lang = "";
-    voice8.native = true;
-    voices.push_back(voice8);
-
-    content::Utterance utterance(nullptr);
-    EXPECT_EQ(0, tts_controller->GetMatchingVoice(&utterance, voices));
-
-    std::set<content::TtsEventType> types;
-    types.insert(content::TTS_EVENT_WORD);
-    utterance.set_required_event_types(types);
-    EXPECT_EQ(1, tts_controller->GetMatchingVoice(&utterance, voices));
-
-    utterance.set_lang("de-DE");
-    EXPECT_EQ(2, tts_controller->GetMatchingVoice(&utterance, voices));
-
-    utterance.set_lang("fr-FR");
-    EXPECT_EQ(3, tts_controller->GetMatchingVoice(&utterance, voices));
-
-    utterance.set_voice_name("Voice4");
-    EXPECT_EQ(4, tts_controller->GetMatchingVoice(&utterance, voices));
-
-    utterance.set_voice_name("");
-    utterance.set_extension_id("id5");
-    EXPECT_EQ(5, tts_controller->GetMatchingVoice(&utterance, voices));
-
-#if defined(OS_CHROMEOS)
-    // Voice6 is matched when the utterance locale exactly matches its locale.
-    utterance.set_extension_id("");
-    utterance.set_lang("es-es");
-    EXPECT_EQ(6, tts_controller->GetMatchingVoice(&utterance, voices));
-
-    // The 7th voice is the default for "es", even though the utterance is
-    // "es-ar". |voice6| is not matched because it is not the default.
-    utterance.set_extension_id("");
-    utterance.set_lang("es-ar");
-    EXPECT_EQ(7, tts_controller->GetMatchingVoice(&utterance, voices));
-
-    // The 8th voice is like the built-in "Android" voice, it has no lang
-    // and no extension ID. Make sure it can still be matched.
-    utterance.set_voice_name("Android");
-    utterance.set_extension_id("");
-    utterance.set_lang("");
-    EXPECT_EQ(8, tts_controller->GetMatchingVoice(&utterance, voices));
-#endif  // defined(OS_CHROMEOS)
-  }
-
-  {
-    // Check voices against system language.
-    std::vector<content::VoiceData> voices;
-    content::VoiceData voice0;
-    voice0.extension_id = "id0";
-    voice0.name = "voice0";
-    voice0.lang = "en-GB";
-    voices.push_back(voice0);
-    content::VoiceData voice1;
-    voice1.extension_id = "id1";
-    voice1.name = "voice1";
-    voice1.lang = "en-US";
-    voices.push_back(voice1);
-    content::Utterance utterance(nullptr);
-
-    // voice1 is matched against the exact default system language.
-    g_browser_process->SetApplicationLocale("en-US");
-    utterance.set_lang("");
-    EXPECT_EQ(1, tts_controller->GetMatchingVoice(&utterance, voices));
-
-    // voice0 is matched against the system language which has no region piece.
-    g_browser_process->SetApplicationLocale("en");
-    utterance.set_lang("");
-    EXPECT_EQ(0, tts_controller->GetMatchingVoice(&utterance, voices));
-
-#if defined(OS_CHROMEOS)
-    // Add another preference.
-    std::unique_ptr<base::DictionaryValue> lang_to_voices =
-        std::make_unique<base::DictionaryValue>();
-    lang_to_voices->SetKey(
-        "en", base::Value("{\"name\":\"voice0\",\"extension\":\"id0\"}"));
-
-    pref_service_.SetUserPref(prefs::kTextToSpeechLangToVoiceName,
-                              std::move(lang_to_voices));
-
-    // voice0 is matched against the pref over the system language.
-    g_browser_process->SetApplicationLocale("en-US");
-    EXPECT_EQ(0, tts_controller->GetMatchingVoice(&utterance, voices));
-#endif  // defined(OS_CHROMEOS)
-  }
-}
-
-#if defined(OS_CHROMEOS)
-TEST_F(TtsControllerTest, TestTtsControllerUtteranceDefaults) {
-  std::unique_ptr<TestableTtsController> controller =
-      std::make_unique<TestableTtsController>();
-
-  std::unique_ptr<content::Utterance> utterance1 =
-      std::make_unique<content::Utterance>(nullptr);
-  // Initialized to default (unset constant) values.
-  EXPECT_EQ(blink::kWebSpeechSynthesisDoublePrefNotSet,
-            utterance1->continuous_parameters().rate);
-  EXPECT_EQ(blink::kWebSpeechSynthesisDoublePrefNotSet,
-            utterance1->continuous_parameters().pitch);
-  EXPECT_EQ(blink::kWebSpeechSynthesisDoublePrefNotSet,
-            utterance1->continuous_parameters().volume);
-
-  controller->UpdateUtteranceDefaults(utterance1.get());
-  // Updated to global defaults.
-  EXPECT_EQ(blink::kWebSpeechSynthesisDefaultTextToSpeechRate,
-            utterance1->continuous_parameters().rate);
-  EXPECT_EQ(blink::kWebSpeechSynthesisDefaultTextToSpeechPitch,
-            utterance1->continuous_parameters().pitch);
-  EXPECT_EQ(blink::kWebSpeechSynthesisDefaultTextToSpeechVolume,
-            utterance1->continuous_parameters().volume);
-
-  // Now we will set prefs and expect those to be used as defaults.
-  TestingPrefServiceSimple pref_service_;
-  pref_service_.registry()->RegisterDoublePref(prefs::kTextToSpeechRate, 1.5);
-  pref_service_.registry()->RegisterDoublePref(prefs::kTextToSpeechPitch, 2.0);
-  pref_service_.registry()->RegisterDoublePref(prefs::kTextToSpeechVolume, 0.5);
-  controller->pref_service_ = &pref_service_;
-
-  std::unique_ptr<content::Utterance> utterance2 =
-      std::make_unique<content::Utterance>(nullptr);
-  controller->UpdateUtteranceDefaults(utterance2.get());
-  // Updated to pref values.
-  EXPECT_EQ(1.5f, utterance2->continuous_parameters().rate);
-  EXPECT_EQ(2.0f, utterance2->continuous_parameters().pitch);
-  EXPECT_EQ(0.5f, utterance2->continuous_parameters().volume);
-}
-#endif  // defined(OS_CHROMEOS)
diff --git a/chrome/browser/ssl/ssl_config_service_manager_pref.cc b/chrome/browser/ssl/ssl_config_service_manager_pref.cc
index 01b1167..48ab2c0 100644
--- a/chrome/browser/ssl/ssl_config_service_manager_pref.cc
+++ b/chrome/browser/ssl/ssl_config_service_manager_pref.cc
@@ -113,8 +113,6 @@
   return out;
 }
 
-const char kTLS13VariantExperimentName[] = "TLS13Variant";
-
 ////////////////////////////////////////////////////////////////////////////////
 //  SSLConfigServiceManagerPref
 
@@ -155,7 +153,6 @@
   BooleanPrefMember symantec_legacy_infrastructure_enabled_;
   StringPrefMember ssl_version_min_;
   StringPrefMember ssl_version_max_;
-  StringPrefMember tls13_variant_;
   StringListPrefMember h2_client_cert_coalescing_host_patterns_;
 
   // The cached list of disabled SSL cipher suites.
@@ -170,29 +167,6 @@
     PrefService* local_state) {
   DCHECK(local_state);
 
-  const std::string tls13_variant =
-      base::GetFieldTrialParamValue(kTLS13VariantExperimentName, "variant");
-  const char* tls13_value = nullptr;
-  const char* version_value = nullptr;
-  if (tls13_variant == "disabled") {
-    tls13_value = switches::kTLS13VariantDisabled;
-  } else if (tls13_variant == "draft23") {
-    tls13_value = switches::kTLS13VariantDraft23;
-    version_value = switches::kSSLVersionTLSv13;
-  } else if (tls13_variant == "final") {
-    tls13_value = switches::kTLS13VariantFinal;
-    version_value = switches::kSSLVersionTLSv13;
-  }
-
-  if (tls13_value) {
-    local_state->SetDefaultPrefValue(prefs::kTLS13Variant,
-                                     base::Value(tls13_value));
-  }
-  if (version_value) {
-    local_state->SetDefaultPrefValue(prefs::kSSLVersionMax,
-                                     base::Value(version_value));
-  }
-
   PrefChangeRegistrar::NamedChangeCallback local_state_callback =
       base::BindRepeating(&SSLConfigServiceManagerPref::OnPreferenceChanged,
                           base::Unretained(this), local_state);
@@ -209,7 +183,6 @@
                         local_state_callback);
   ssl_version_max_.Init(prefs::kSSLVersionMax, local_state,
                         local_state_callback);
-  tls13_variant_.Init(prefs::kTLS13Variant, local_state, local_state_callback);
   h2_client_cert_coalescing_host_patterns_.Init(
       prefs::kH2ClientCertCoalescingHosts, local_state, local_state_callback);
 
@@ -235,7 +208,6 @@
       default_verifier_config.disable_symantec_enforcement);
   registry->RegisterStringPref(prefs::kSSLVersionMin, std::string());
   registry->RegisterStringPref(prefs::kSSLVersionMax, std::string());
-  registry->RegisterStringPref(prefs::kTLS13Variant, std::string());
   registry->RegisterListPref(prefs::kCipherSuiteBlacklist);
   registry->RegisterListPref(prefs::kH2ClientCertCoalescingHosts);
 }
@@ -287,7 +259,6 @@
       symantec_legacy_infrastructure_enabled_.GetValue();
   std::string version_min_str = ssl_version_min_.GetValue();
   std::string version_max_str = ssl_version_max_.GetValue();
-  std::string tls13_variant_str = tls13_variant_.GetValue();
 
   network::mojom::SSLVersion version_min;
   if (SSLProtocolVersionFromString(version_min_str, &version_min))
@@ -299,15 +270,6 @@
     config->version_max = version_max;
   }
 
-  if (tls13_variant_str == switches::kTLS13VariantDisabled) {
-    if (config->version_max > network::mojom::SSLVersion::kTLS12)
-      config->version_max = network::mojom::SSLVersion::kTLS12;
-  } else if (tls13_variant_str == switches::kTLS13VariantDraft23) {
-    config->tls13_variant = network::mojom::TLS13Variant::kDraft23;
-  } else if (tls13_variant_str == switches::kTLS13VariantFinal) {
-    config->tls13_variant = network::mojom::TLS13Variant::kFinal;
-  }
-
   config->disabled_cipher_suites = disabled_cipher_suites_;
   config->client_cert_pooling_policy = CanonicalizeHostnamePatterns(
       h2_client_cert_coalescing_host_patterns_.GetValue());
diff --git a/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc b/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc
index 9716359..3aca951 100644
--- a/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc
+++ b/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc
@@ -163,18 +163,14 @@
   // The settings should not be added to the local_state.
   EXPECT_FALSE(local_state.HasPrefPath(prefs::kSSLVersionMin));
   EXPECT_FALSE(local_state.HasPrefPath(prefs::kSSLVersionMax));
-  EXPECT_FALSE(local_state.HasPrefPath(prefs::kTLS13Variant));
 
   // Explicitly double-check the settings are not in the preference store.
   std::string version_min_str;
   std::string version_max_str;
-  std::string tls13_variant_str;
   EXPECT_FALSE(
       local_state_store->GetString(prefs::kSSLVersionMin, &version_min_str));
   EXPECT_FALSE(
       local_state_store->GetString(prefs::kSSLVersionMax, &version_max_str));
-  EXPECT_FALSE(
-      local_state_store->GetString(prefs::kTLS13Variant, &tls13_variant_str));
 }
 
 // Tests that "ssl3" is not treated as a valid minimum version.
@@ -241,118 +237,6 @@
   EXPECT_LE(network::mojom::SSLVersion::kTLS12, initial_config_->version_max);
 }
 
-// Tests that TLS 1.3 can be disabled via field trials.
-TEST_F(SSLConfigServiceManagerPrefTest, TLS13VariantFeatureDisabled) {
-  // Toggle the field trial.
-  variations::testing::VariationParamsManager variation_params(
-      "TLS13Variant", {{"variant", "disabled"}});
-
-  TestingPrefServiceSimple local_state;
-  SSLConfigServiceManager::RegisterPrefs(local_state.registry());
-
-  std::unique_ptr<SSLConfigServiceManager> config_manager =
-      SetUpConfigServiceManager(&local_state);
-
-  EXPECT_EQ(network::mojom::SSLVersion::kTLS12, initial_config_->version_max);
-}
-
-// Tests that Draft23 TLS 1.3 can be enabled via field trials.
-TEST_F(SSLConfigServiceManagerPrefTest, TLS13VariantFeatureDraft23) {
-  // Toggle the field trial.
-  variations::testing::VariationParamsManager variation_params(
-      "TLS13Variant", {{"variant", "draft23"}});
-
-  TestingPrefServiceSimple local_state;
-  SSLConfigServiceManager::RegisterPrefs(local_state.registry());
-
-  std::unique_ptr<SSLConfigServiceManager> config_manager =
-      SetUpConfigServiceManager(&local_state);
-
-  EXPECT_EQ(network::mojom::SSLVersion::kTLS13, initial_config_->version_max);
-  EXPECT_EQ(network::mojom::TLS13Variant::kDraft23,
-            initial_config_->tls13_variant);
-}
-
-// Tests that Final TLS 1.3 can be enabled via field trials.
-TEST_F(SSLConfigServiceManagerPrefTest, TLS13VariantFeatureFinal) {
-  // Toggle the field trial.
-  variations::testing::VariationParamsManager variation_params(
-      "TLS13Variant", {{"variant", "final"}});
-
-  TestingPrefServiceSimple local_state;
-  SSLConfigServiceManager::RegisterPrefs(local_state.registry());
-
-  std::unique_ptr<SSLConfigServiceManager> config_manager =
-      SetUpConfigServiceManager(&local_state);
-
-  EXPECT_EQ(network::mojom::SSLVersion::kTLS13, initial_config_->version_max);
-  EXPECT_EQ(network::mojom::TLS13Variant::kFinal,
-            initial_config_->tls13_variant);
-}
-
-// Tests that the SSLVersionMax preference overwites the TLS 1.3 variant
-// field trial.
-TEST_F(SSLConfigServiceManagerPrefTest, TLS13SSLVersionMax) {
-  scoped_refptr<TestingPrefStore> local_state_store(new TestingPrefStore());
-
-  // Toggle the field trial.
-  variations::testing::VariationParamsManager variation_params(
-      "TLS13Variant", {{"variant", "draft23"}});
-
-  TestingPrefServiceSimple local_state;
-  local_state.SetUserPref(prefs::kSSLVersionMax,
-                          std::make_unique<base::Value>("tls1.2"));
-  SSLConfigServiceManager::RegisterPrefs(local_state.registry());
-
-  std::unique_ptr<SSLConfigServiceManager> config_manager =
-      SetUpConfigServiceManager(&local_state);
-
-  EXPECT_EQ(network::mojom::SSLVersion::kTLS12, initial_config_->version_max);
-}
-
-// Tests that disabling TLS 1.3 by preference overwrites the TLS 1.3 field
-// trial.
-TEST_F(SSLConfigServiceManagerPrefTest, TLS13VariantOverrideDisable) {
-  scoped_refptr<TestingPrefStore> local_state_store(new TestingPrefStore());
-
-  // Toggle the field trial.
-  variations::testing::VariationParamsManager variation_params(
-      "TLS13Variant", {{"variant", "draft23"}});
-
-  TestingPrefServiceSimple local_state;
-  local_state.SetUserPref(prefs::kTLS13Variant,
-                          std::make_unique<base::Value>("disabled"));
-  SSLConfigServiceManager::RegisterPrefs(local_state.registry());
-
-  std::unique_ptr<SSLConfigServiceManager> config_manager =
-      SetUpConfigServiceManager(&local_state);
-
-  EXPECT_EQ(network::mojom::SSLVersion::kTLS12, initial_config_->version_max);
-}
-
-// Tests that enabling TLS 1.3 by preference overwrites the TLS 1.3 field trial.
-TEST_F(SSLConfigServiceManagerPrefTest, TLS13VariantOverrideEnable) {
-  scoped_refptr<TestingPrefStore> local_state_store(new TestingPrefStore());
-
-  // Toggle the field trial.
-  variations::testing::VariationParamsManager variation_params(
-      "TLS13Variant", {{"variant", "disabled"}});
-
-  TestingPrefServiceSimple local_state;
-  local_state.SetUserPref(prefs::kSSLVersionMax,
-                          std::make_unique<base::Value>("tls1.3"));
-  local_state.SetUserPref(prefs::kTLS13Variant,
-                          std::make_unique<base::Value>("draft23"));
-  SSLConfigServiceManager::RegisterPrefs(local_state.registry());
-
-  std::unique_ptr<SSLConfigServiceManager> config_manager =
-      SetUpConfigServiceManager(&local_state);
-
-  EXPECT_EQ(network::mojom::SSLVersion::kTLS13, initial_config_->version_max);
-  EXPECT_EQ(network::mojom::TLS13Variant::kDraft23,
-            initial_config_->tls13_variant);
-}
-
 // Tests that Symantec's legacy infrastructure can be enabled.
 TEST_F(SSLConfigServiceManagerPrefTest, SymantecLegacyInfrastructure) {
   scoped_refptr<TestingPrefStore> local_state_store(new TestingPrefStore());
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 05aaa167..d0e9ac80 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1608,6 +1608,8 @@
       "webui/chromeos/login/screenlock_icon_source.h",
       "webui/chromeos/login/signin_screen_handler.cc",
       "webui/chromeos/login/signin_screen_handler.h",
+      "webui/chromeos/login/supervision_transition_screen_handler.cc",
+      "webui/chromeos/login/supervision_transition_screen_handler.h",
       "webui/chromeos/login/sync_consent_screen_handler.cc",
       "webui/chromeos/login/sync_consent_screen_handler.h",
       "webui/chromeos/login/terms_of_service_screen_handler.cc",
diff --git a/chrome/browser/ui/ash/accessibility/ax_tree_source_aura_unittest.cc b/chrome/browser/ui/ash/accessibility/ax_tree_source_aura_unittest.cc
index 2153cb5..abd1fbda 100644
--- a/chrome/browser/ui/ash/accessibility/ax_tree_source_aura_unittest.cc
+++ b/chrome/browser/ui/ash/accessibility/ax_tree_source_aura_unittest.cc
@@ -94,7 +94,7 @@
   // Focus the textfield so the cursor does not disappear.
   textfield_->RequestFocus();
 
-  AXTreeSourceViews ax_tree(&root_wrapper_, ui::DesktopAXTreeID());
+  AXTreeSourceViews ax_tree(&root_wrapper_, ui::AXTreeID::CreateNewAXTreeID());
   ASSERT_TRUE(ax_tree.GetRoot());
 
   // ID's should be > 0.
@@ -131,7 +131,7 @@
 }
 
 TEST_F(AXTreeSourceAuraTest, DoDefault) {
-  AXTreeSourceViews ax_tree(&root_wrapper_, ui::DesktopAXTreeID());
+  AXTreeSourceViews ax_tree(&root_wrapper_, ui::AXTreeID::CreateNewAXTreeID());
 
   // Grab a wrapper to |DoDefault| (click).
   AXAuraObjWrapper* textfield_wrapper =
@@ -147,7 +147,7 @@
 }
 
 TEST_F(AXTreeSourceAuraTest, Focus) {
-  AXTreeSourceViews ax_tree(&root_wrapper_, ui::DesktopAXTreeID());
+  AXTreeSourceViews ax_tree(&root_wrapper_, ui::AXTreeID::CreateNewAXTreeID());
 
   // Grab a wrapper to focus.
   AXAuraObjWrapper* textfield_wrapper =
@@ -163,7 +163,7 @@
 }
 
 TEST_F(AXTreeSourceAuraTest, Serialize) {
-  AXTreeSourceViews ax_tree(&root_wrapper_, ui::DesktopAXTreeID());
+  AXTreeSourceViews ax_tree(&root_wrapper_, ui::AXTreeID::CreateNewAXTreeID());
   AuraAXTreeSerializer ax_serializer(&ax_tree);
   ui::AXTreeUpdate out_update;
 
@@ -204,7 +204,7 @@
 }
 
 TEST_F(AXTreeSourceAuraTest, SerializeWindowSetsClipsChildren) {
-  AXTreeSourceViews ax_tree(&root_wrapper_, ui::DesktopAXTreeID());
+  AXTreeSourceViews ax_tree(&root_wrapper_, ui::AXTreeID::CreateNewAXTreeID());
   AuraAXTreeSerializer ax_serializer(&ax_tree);
   AXAuraObjWrapper* widget_wrapper =
       AXAuraObjCache::GetInstance()->GetOrCreate(widget_);
diff --git a/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc b/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc
index 2f1483ca..c6d2623e 100644
--- a/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc
+++ b/chrome/browser/ui/aura/accessibility/automation_manager_aura.cc
@@ -8,7 +8,6 @@
 
 #include "base/memory/singleton.h"
 #include "build/build_config.h"
-#include "content/public/browser/render_frame_host.h"
 #include "ui/accessibility/ax_action_data.h"
 #include "ui/accessibility/ax_enum_util.h"
 #include "ui/accessibility/ax_enums.mojom.h"
@@ -159,10 +158,7 @@
 }
 
 AutomationManagerAura::AutomationManagerAura()
-    : AXHostDelegate(ui::DesktopAXTreeID()),
-      enabled_(false),
-      processing_events_(false),
-      weak_ptr_factory_(this) {
+    : enabled_(false), processing_events_(false), weak_ptr_factory_(this) {
   views::AXEventManager::Get()->AddObserver(this);
 }
 
@@ -174,7 +170,7 @@
   if (!current_tree_) {
     desktop_root_ = std::make_unique<AXRootObjWrapper>(this);
     current_tree_ = std::make_unique<views::AXTreeSourceViews>(
-        desktop_root_.get(), ui::DesktopAXTreeID());
+        desktop_root_.get(), ax_tree_id());
   }
   reset_serializer ? current_tree_serializer_.reset()
                    : current_tree_serializer_.reset(
@@ -227,7 +223,7 @@
 
   if (event_bundle_sink_) {
     event_bundle_sink_->DispatchAccessibilityEvents(
-        ui::DesktopAXTreeID(), std::move(tree_updates),
+        ax_tree_id(), std::move(tree_updates),
         aura::Env::GetInstance()->last_mouse_location(), std::move(events));
   }
 
@@ -263,22 +259,18 @@
     child_ax_tree_id = ui::AXTreeID::FromString(*child_ax_tree_id_ptr);
 
   // If the window has a child AX tree ID, forward the action to the
-  // associated AXHostDelegate or RenderFrameHost.
+  // associated AXHostDelegate.
   if (child_ax_tree_id != ui::AXTreeIDUnknown()) {
     ui::AXTreeIDRegistry* registry = ui::AXTreeIDRegistry::GetInstance();
     ui::AXHostDelegate* delegate = registry->GetHostDelegate(child_ax_tree_id);
-    if (delegate) {
-      delegate->PerformAction(action);
-      return;
-    }
 
-    content::RenderFrameHost* rfh =
-        content::RenderFrameHost::FromAXTreeID(child_ax_tree_id);
-    if (rfh) {
-      // Convert to pixels for the RenderFrameHost HitTest.
+    CHECK(delegate);
+
+    // Convert to pixels for the RenderFrameHost HitTest, if required.
+    if (delegate->RequiresPerformActionPointInPixels())
       window->GetHost()->ConvertDIPToPixels(&action.target_point);
-      rfh->AccessibilityPerformAction(action);
-    }
+
+    delegate->PerformAction(action);
     return;
   }
 
diff --git a/chrome/browser/ui/aura/accessibility/automation_manager_aura_browsertest.cc b/chrome/browser/ui/aura/accessibility/automation_manager_aura_browsertest.cc
index 9839301..ed9e29e63 100644
--- a/chrome/browser/ui/aura/accessibility/automation_manager_aura_browsertest.cc
+++ b/chrome/browser/ui/aura/accessibility/automation_manager_aura_browsertest.cc
@@ -11,6 +11,7 @@
 #include "chrome/test/views/accessibility_checker.h"
 #include "content/public/browser/browser_accessibility_state.h"
 #include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
 #include "extensions/common/extension_messages.h"
@@ -47,6 +48,13 @@
   }
 }
 
+// A helper to retrieve an ax tree id given a RenderFrameHost.
+ui::AXTreeID GetAXTreeIDFromRenderFrameHost(content::RenderFrameHost* rfh) {
+  auto* registry = ui::AXTreeIDRegistry::GetInstance();
+  return registry->GetAXTreeID(ui::AXTreeIDRegistry::FrameID(
+      rfh->GetProcess()->GetID(), rfh->GetRoutingID()));
+}
+
 // A class that installs itself as the sink to handle automation event bundles
 // from AutomationManagerAura, then waits until an automation event indicates
 // that a given node ID is focused.
@@ -126,7 +134,7 @@
   WaitForAccessibilityTreeToContainNodeWithName(web_contents, "Click me");
 
   auto* frame_host = web_contents->GetMainFrame();
-  ui::AXTreeID ax_tree_id = frame_host->GetAXTreeID();
+  ui::AXTreeID ax_tree_id = GetAXTreeIDFromRenderFrameHost(frame_host);
   ASSERT_NE(ax_tree_id, ui::AXTreeIDUnknown());
 
   std::vector<views::AXAuraObjWrapper*> web_hosts;
diff --git a/chrome/browser/ui/cocoa/main_menu_builder.mm b/chrome/browser/ui/cocoa/main_menu_builder.mm
index 6d296c3..552d6a5 100644
--- a/chrome/browser/ui/cocoa/main_menu_builder.mm
+++ b/chrome/browser/ui/cocoa/main_menu_builder.mm
@@ -118,7 +118,7 @@
                     .remove_if(is_pwa),
                 Item().is_separator().remove_if(is_pwa),
                 Item(IDS_SHARE_MAC).remove_if(is_pwa), Item().is_separator(),
-                Item(IDS_PRINT).command_id(IDC_PRINT).remove_if(is_pwa),
+                Item(IDS_PRINT).command_id(IDC_PRINT),
                 Item(IDS_PRINT_USING_SYSTEM_DIALOG_MAC)
                     .command_id(IDC_BASIC_PRINT)
                     .is_alternate()
diff --git a/chrome/browser/ui/extensions/extension_install_ui_default.cc b/chrome/browser/ui/extensions/extension_install_ui_default.cc
index 2307b0c..ba7dfe11 100644
--- a/chrome/browser/ui/extensions/extension_install_ui_default.cc
+++ b/chrome/browser/ui/extensions/extension_install_ui_default.cc
@@ -56,9 +56,10 @@
   return browser;
 }
 
-void ShowExtensionInstalledBubble(const extensions::Extension* extension,
-                                  Profile* profile,
-                                  const SkBitmap& icon) {
+void ShowExtensionInstalledBubble(
+    scoped_refptr<const extensions::Extension> extension,
+    Profile* profile,
+    const SkBitmap& icon) {
   Browser* browser = FindOrCreateVisibleBrowser(profile);
   if (browser)
     ExtensionInstalledBubble::ShowBubble(extension, browser, icon);
@@ -74,8 +75,9 @@
 
 ExtensionInstallUIDefault::~ExtensionInstallUIDefault() {}
 
-void ExtensionInstallUIDefault::OnInstallSuccess(const Extension* extension,
-                                                 const SkBitmap* icon) {
+void ExtensionInstallUIDefault::OnInstallSuccess(
+    scoped_refptr<const extensions::Extension> extension,
+    const SkBitmap* icon) {
   if (disable_ui_for_tests() || skip_post_install_ui_ || extension->is_theme())
     return;
 
@@ -102,7 +104,7 @@
     }
 
 #if defined(OS_CHROMEOS)
-    ExtensionInstalledNotification::Show(extension, current_profile);
+    ExtensionInstalledNotification::Show(extension.get(), current_profile);
 #else  // defined(OS_CHROMEOS)
     OpenAppInstalledUI(extension->id());
 #endif  // defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/extensions/extension_install_ui_default.h b/chrome/browser/ui/extensions/extension_install_ui_default.h
index 2586f2e..4d2f97a 100644
--- a/chrome/browser/ui/extensions/extension_install_ui_default.h
+++ b/chrome/browser/ui/extensions/extension_install_ui_default.h
@@ -21,7 +21,7 @@
   ~ExtensionInstallUIDefault() override;
 
   // ExtensionInstallUI:
-  void OnInstallSuccess(const extensions::Extension* extension,
+  void OnInstallSuccess(scoped_refptr<const extensions::Extension> extension,
                         const SkBitmap* icon) override;
   void OnInstallFailure(const extensions::CrxInstallError& error) override;
   void SetUseAppInstalledBubble(bool use_bubble) override;
diff --git a/chrome/browser/ui/extensions/extension_installed_bubble.cc b/chrome/browser/ui/extensions/extension_installed_bubble.cc
index f3e1162..a7cf6af 100644
--- a/chrome/browser/ui/extensions/extension_installed_bubble.cc
+++ b/chrome/browser/ui/extensions/extension_installed_bubble.cc
@@ -173,7 +173,7 @@
 
 // static
 void ExtensionInstalledBubble::ShowBubble(
-    const extensions::Extension* extension,
+    scoped_refptr<const extensions::Extension> extension,
     Browser* browser,
     const SkBitmap& icon) {
   // The ExtensionInstalledBubbleObserver will delete itself when the
@@ -187,16 +187,16 @@
   }
 }
 
-ExtensionInstalledBubble::ExtensionInstalledBubble(const Extension* extension,
-                                                   Browser* browser,
-                                                   const SkBitmap& icon)
+ExtensionInstalledBubble::ExtensionInstalledBubble(
+    scoped_refptr<const Extension> extension,
+    Browser* browser,
+    const SkBitmap& icon)
     : extension_(extension),
       browser_(browser),
       icon_(icon),
       type_(GENERIC),
       options_(NONE),
-      anchor_position_(ANCHOR_APP_MENU) {
-}
+      anchor_position_(ANCHOR_APP_MENU) {}
 
 ExtensionInstalledBubble::~ExtensionInstalledBubble() {}
 
@@ -230,7 +230,7 @@
       break;
     case OMNIBOX_KEYWORD:
       extra =
-          base::UTF8ToUTF16(extensions::OmniboxInfo::GetKeyword(extension_));
+          base::UTF8ToUTF16(extensions::OmniboxInfo::GetKeyword(extension()));
       message_id = IDS_EXTENSION_INSTALLED_OMNIBOX_KEYWORD_INFO;
       break;
     case GENERIC:
@@ -246,19 +246,19 @@
 void ExtensionInstalledBubble::Initialize() {
   const extensions::ActionInfo* action_info = nullptr;
   if ((action_info = extensions::ActionInfo::GetBrowserActionInfo(
-           extension_)) != nullptr) {
+           extension())) != nullptr) {
     type_ = BROWSER_ACTION;
   } else if ((action_info = extensions::ActionInfo::GetPageActionInfo(
-                  extension_)) != nullptr) {
+                  extension())) != nullptr) {
     type_ = PAGE_ACTION;
-  } else if (!extensions::OmniboxInfo::GetKeyword(extension_).empty()) {
+  } else if (!extensions::OmniboxInfo::GetKeyword(extension()).empty()) {
     type_ = OMNIBOX_KEYWORD;
   } else {
     type_ = GENERIC;
   }
 
   action_command_ = GetCommand(extension_->id(), browser_->profile(), type_);
-  if (extensions::sync_helper::IsSyncable(extension_) &&
+  if (extensions::sync_helper::IsSyncable(extension()) &&
       SyncPromoUI::ShouldShowSyncPromo(browser_->profile()))
     options_ |= SIGN_IN_PROMO;
 
diff --git a/chrome/browser/ui/extensions/extension_installed_bubble.h b/chrome/browser/ui/extensions/extension_installed_bubble.h
index e7347ac..f85935764 100644
--- a/chrome/browser/ui/extensions/extension_installed_bubble.h
+++ b/chrome/browser/ui/extensions/extension_installed_bubble.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/strings/string16.h"
 #include "components/bubble/bubble_delegate.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -65,17 +66,17 @@
   // the extension has loaded. |extension| is the installed extension. |browser|
   // is the browser window which will host the bubble. |icon| is the install
   // icon of the extension.
-  static void ShowBubble(const extensions::Extension* extension,
+  static void ShowBubble(scoped_refptr<const extensions::Extension> extension,
                          Browser* browser,
                          const SkBitmap& icon);
 
-  ExtensionInstalledBubble(const extensions::Extension* extension,
+  ExtensionInstalledBubble(scoped_refptr<const extensions::Extension> extension,
                            Browser* browser,
                            const SkBitmap& icon);
 
   ~ExtensionInstalledBubble() override;
 
-  const extensions::Extension* extension() const { return extension_; }
+  const extensions::Extension* extension() const { return extension_.get(); }
   Browser* browser() { return browser_; }
   const Browser* browser() const { return browser_; }
   const SkBitmap& icon() const { return icon_; }
@@ -106,8 +107,10 @@
   void Initialize();
 
  private:
-  // |extension_| is NULL when we are deleted.
-  const extensions::Extension* extension_;
+  // It's possible for an extension to be programmatically uninstalled
+  // underneath us, so don't let the extension object go away until the bubble
+  // is hidden.
+  scoped_refptr<const extensions::Extension> extension_;
   Browser* const browser_;
   const SkBitmap icon_;
   BubbleType type_;
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
index ba806f0..22ceadb 100644
--- a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
+++ b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
@@ -4,7 +4,9 @@
 
 #include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
 
+#include <algorithm>
 #include <set>
+#include <string>
 #include <utility>
 
 #include "base/auto_reset.h"
@@ -649,9 +651,12 @@
   std::unique_ptr<ToolbarActionViewController> removed_action =
       std::move(*iter);
   toolbar_actions_.erase(iter);
-  delegate_->RemoveViewForAction(removed_action.get());
+
+  // If we kill the view before we undo the popout, highlights and pop-ups can
+  // get left in weird states, so undo the popout first.
   if (popped_out_action_ == removed_action.get())
     UndoPopOut();
+  delegate_->RemoveViewForAction(removed_action.get());
   removed_action.reset();
 
   // If the extension is being upgraded we don't want the bar to shrink
diff --git a/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.cc b/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.cc
index 296d495c..9d4bc99 100644
--- a/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.cc
+++ b/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.cc
@@ -33,7 +33,7 @@
   BrowserAppMenuButton* app_menu_button =
       browser_view_->toolbar()->app_menu_button();
   app_menu_button->AddMenuListener(this);
-  app_menu_button->SetHighlighted(true);
+  app_menu_button->SetPromoIsShowing(true);
 
   promo_bubble_ = FeaturePromoBubbleView::CreateOwned(
       app_menu_button, views::BubbleBorder::Arrow::TOP_RIGHT,
@@ -66,8 +66,7 @@
     BrowserAppMenuButton* app_menu_button =
         browser_view_->toolbar()->app_menu_button();
     app_menu_button->RemoveMenuListener(this);
-    app_menu_button->SetHighlighted(false);
-
+    app_menu_button->SetPromoIsShowing(false);
     iph_service_->HelpDismissed();
   }
 }
@@ -78,6 +77,8 @@
   // Success is determined by whether the reopen tab event was sent.
   iph_service_->HelpDismissed();
 
+  browser_view_->toolbar()->app_menu_button()->SetPromoIsShowing(false);
+
   AppMenu* app_menu = browser_view_->toolbar()->app_menu_button()->app_menu();
   app_menu->RemoveObserver(this);
 }
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
index 10742cd..a93a05f6 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -736,9 +736,16 @@
 
   // Drag to target_tab_strip. This should stop the nested loop from dragging
   // the window.
-  gfx::Point target_point(target_tab_strip->width() / 2,
-                          target_tab_strip->height() / 2);
-  views::View::ConvertPointToScreen(target_tab_strip, &target_point);
+  //
+  // Note: It's possible on small screens for the windows to overlap, so we want
+  // to pick a point squarely within the second tab strip and not in the
+  // starting window.
+  const gfx::Rect old_window_bounds =
+      not_attached_tab_strip->GetWidget()->GetWindowBoundsInScreen();
+  const gfx::Rect target_bounds = target_tab_strip->GetBoundsInScreen();
+  gfx::Point target_point = target_bounds.CenterPoint();
+  target_point.set_x(std::max(target_point.x(), old_window_bounds.right() + 1));
+  ASSERT_TRUE(target_bounds.Contains(target_point));
   ASSERT_TRUE(test->DragInputToAsync(target_point));
 }
 
diff --git a/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc b/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc
index 9e40391..bad3d71 100644
--- a/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc
+++ b/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc
@@ -34,13 +34,25 @@
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/animation/ink_drop.h"
 #include "ui/views/animation/ink_drop_highlight.h"
+#include "ui/views/animation/ink_drop_state.h"
 #include "ui/views/controls/button/label_button_border.h"
 #include "ui/views/metrics.h"
+#include "ui/views/view.h"
+#include "ui/views/view_properties.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h"
 #endif  // defined(OS_CHROMEOS)
 
+namespace {
+
+// Button background and icon color for in-product help promos.
+// TODO(collinbaker): https://crbug.com/909747 handle themed toolbar colors, and
+// maybe move this into theme system.
+constexpr SkColor kFeaturePromoHighlightColor = gfx::kGoogleBlue600;
+
+}  // namespace
+
 // static
 bool BrowserAppMenuButton::g_open_app_immediately_for_testing = false;
 
@@ -69,13 +81,19 @@
   UpdateIcon();
 }
 
-void BrowserAppMenuButton::SetIsProminent(bool is_prominent) {
-  if (is_prominent) {
-    SetBackground(views::CreateSolidBackground(GetNativeTheme()->GetSystemColor(
-        ui::NativeTheme::kColorId_ProminentButtonColor)));
-  } else {
-    SetBackground(nullptr);
-  }
+void BrowserAppMenuButton::SetPromoIsShowing(bool promo_is_showing) {
+  if (promo_is_showing_ == promo_is_showing)
+    return;
+
+  promo_is_showing_ = promo_is_showing;
+  // We override GetInkDropBaseColor below in the |promo_is_showing_| case. This
+  // sets the ink drop into the activated state, which will highlight it in the
+  // desired color.
+  GetInkDrop()->AnimateToState(promo_is_showing_
+                                   ? views::InkDropState::ACTIVATED
+                                   : views::InkDropState::HIDDEN);
+
+  UpdateIcon();
   SchedulePaint();
 }
 
@@ -118,8 +136,10 @@
   const ui::NativeTheme* native_theme = GetNativeTheme();
   switch (type_and_severity_.severity) {
     case AppMenuIconController::Severity::NONE:
-      severity_color = GetThemeProvider()->GetColor(
-          ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON);
+      severity_color = promo_is_showing_
+                           ? kFeaturePromoHighlightColor
+                           : GetThemeProvider()->GetColor(
+                                 ThemeProperties::COLOR_TOOLBAR_BUTTON_ICON);
       break;
     case AppMenuIconController::Severity::LOW:
       severity_color = native_theme->GetSystemColor(
@@ -251,3 +271,8 @@
 BrowserAppMenuButton::CreateInkDropHighlight() const {
   return CreateToolbarInkDropHighlight(this);
 }
+
+SkColor BrowserAppMenuButton::GetInkDropBaseColor() const {
+  return promo_is_showing_ ? kFeaturePromoHighlightColor
+                           : AppMenuButton::GetInkDropBaseColor();
+}
diff --git a/chrome/browser/ui/views/toolbar/browser_app_menu_button.h b/chrome/browser/ui/views/toolbar/browser_app_menu_button.h
index 01e70f6..d6bf5fb 100644
--- a/chrome/browser/ui/views/toolbar/browser_app_menu_button.h
+++ b/chrome/browser/ui/views/toolbar/browser_app_menu_button.h
@@ -36,9 +36,9 @@
   // drag-and-drop operation.
   void ShowMenu(bool for_drop);
 
-  // Sets the background to a prominent color if |is_prominent| is true. This is
-  // used for an experimental UI for In-Product Help.
-  void SetIsProminent(bool is_prominent);
+  // Sets whether an in-product help feature promo is showing for the app menu.
+  // When true, the button is highlighted in a noticeable color.
+  void SetPromoIsShowing(bool promo_is_showing);
 
   // views::MenuButton:
   void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
@@ -63,7 +63,7 @@
  private:
   void UpdateBorder();
 
-  // views::MenuButton:
+  // AppMenuButton:
   const char* GetClassName() const override;
   bool GetDropFormats(
       int* formats,
@@ -77,6 +77,7 @@
   std::unique_ptr<views::InkDrop> CreateInkDrop() override;
   std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
       const override;
+  SkColor GetInkDropBaseColor() const override;
 
   AppMenuIconController::TypeAndSeverity type_and_severity_{
       AppMenuIconController::IconType::NONE,
@@ -89,6 +90,9 @@
   // a maximized state to extend to the full window width.
   int margin_trailing_ = 0;
 
+  // Whether an in-product help promo is currently showing for the app menu.
+  bool promo_is_showing_ = false;
+
   ScopedObserver<ui::MaterialDesignController,
                  ui::MaterialDesignControllerObserver>
       md_observer_{this};
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
index e485a43a..37dafd4 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -70,6 +70,7 @@
 #include "chrome/browser/ui/webui/chromeos/login/recommend_apps_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
+#include "chrome/browser/ui/webui/chromeos/login/supervision_transition_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.h"
@@ -127,6 +128,7 @@
 constexpr char kArcPlaystoreCSSPath[] = "playstore.css";
 constexpr char kArcPlaystoreJSPath[] = "playstore.js";
 constexpr char kArcPlaystoreLogoPath[] = "playstore.svg";
+constexpr char kArcSupervisionIconPath[] = "supervision_icon.png";
 constexpr char kCustomElementsHTMLPath[] = "custom_elements.html";
 constexpr char kCustomElementsJSPath[] = "custom_elements.js";
 constexpr char kCustomElementsUserPodHTMLPath[] =
@@ -156,6 +158,7 @@
 void AddProductLogoResources(content::WebUIDataSource* source) {
   // Required for Assistant OOBE.
   source->AddResourcePath(kArcAssistantLogoPath, IDR_ASSISTANT_LOGO_PNG);
+  source->AddResourcePath(kArcSupervisionIconPath, IDR_SUPERVISION_ICON_PNG);
 
 #if defined(GOOGLE_CHROME_BUILD)
   source->AddResourcePath(kLogo24PX1XSvgPath, IDR_PRODUCT_LOGO_24PX_1X);
@@ -425,6 +428,8 @@
 
   AddScreenHandler(std::make_unique<WaitForContainerReadyScreenHandler>());
 
+  AddScreenHandler(std::make_unique<SupervisionTransitionScreenHandler>());
+
   AddScreenHandler(std::make_unique<UpdateRequiredScreenHandler>());
 
   AddScreenHandler(std::make_unique<AssistantOptInFlowScreenHandler>());
@@ -626,6 +631,10 @@
   return GetView<WaitForContainerReadyScreenHandler>();
 }
 
+SupervisionTransitionScreenView* OobeUI::GetSupervisionTransitionScreenView() {
+  return GetView<SupervisionTransitionScreenHandler>();
+}
+
 UpdateRequiredView* OobeUI::GetUpdateRequiredScreenView() {
   return GetView<UpdateRequiredScreenHandler>();
 }
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
index 6ae64ea..75f91a5 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
@@ -74,6 +74,7 @@
 class UpdateRequiredView;
 class VoiceInteractionValuePropScreenView;
 class WaitForContainerReadyScreenView;
+class SupervisionTransitionScreenView;
 class WelcomeView;
 class WrongHWIDScreenView;
 
@@ -141,6 +142,7 @@
   EncryptionMigrationScreenView* GetEncryptionMigrationScreenView();
   VoiceInteractionValuePropScreenView* GetVoiceInteractionValuePropScreenView();
   WaitForContainerReadyScreenView* GetWaitForContainerReadyScreenView();
+  SupervisionTransitionScreenView* GetSupervisionTransitionScreenView();
   UpdateRequiredView* GetUpdateRequiredScreenView();
   AssistantOptInFlowScreenView* GetAssistantOptInFlowScreenView();
   MultiDeviceSetupScreenView* GetMultiDeviceSetupScreenView();
diff --git a/chrome/browser/ui/webui/chromeos/login/supervision_transition_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/supervision_transition_screen_handler.cc
new file mode 100644
index 0000000..02abaa6
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/login/supervision_transition_screen_handler.cc
@@ -0,0 +1,130 @@
+// 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/webui/chromeos/login/supervision_transition_screen_handler.h"
+
+#include "base/logging.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/arc/arc_session_manager.h"
+#include "chrome/browser/chromeos/arc/arc_util.h"
+#include "chrome/browser/chromeos/login/oobe_screen.h"
+#include "chrome/browser/chromeos/login/screens/supervision_transition_screen.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/ui/ash/login_screen_client.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/arc/arc_prefs.h"
+#include "components/login/localized_values_builder.h"
+
+namespace {
+
+constexpr char kJsScreenPath[] = "login.SupervisionTransitionScreen";
+constexpr base::TimeDelta kWaitingTimeout = base::TimeDelta::FromMinutes(2);
+
+}  // namespace
+
+namespace chromeos {
+
+SupervisionTransitionScreenHandler::SupervisionTransitionScreenHandler()
+    : BaseScreenHandler(kScreenId) {
+  set_call_js_prefix(kJsScreenPath);
+}
+
+SupervisionTransitionScreenHandler::~SupervisionTransitionScreenHandler() {
+  if (screen_)
+    screen_->OnViewDestroyed(this);
+  timer_.Stop();
+}
+
+void SupervisionTransitionScreenHandler::DeclareLocalizedValues(
+    ::login::LocalizedValuesBuilder* builder) {
+  builder->Add("removingSupervisionTitle", IDS_REMOVING_SUPERVISION_TITLE);
+  builder->Add("addingSupervisionTitle", IDS_ADDING_SUPERVISION_TITLE);
+  builder->Add("supervisionTransitionIntroMessage",
+               IDS_SUPERVISION_TRANSITION_MESSAGE);
+  builder->Add("supervisionTransitionErrorTitle",
+               IDS_SUPERVISION_TRANSITION_ERROR_TITLE);
+  builder->Add("supervisionTransitionErrorMessage",
+               IDS_SUPERVISION_TRANSITION_ERROR_MESSAGE);
+  builder->Add("supervisionTransitionButton",
+               IDS_SUPERVISION_TRANSITION_ERROR_BUTTON);
+}
+
+void SupervisionTransitionScreenHandler::RegisterMessages() {
+  AddCallback(
+      "finishSupervisionTransition",
+      &SupervisionTransitionScreenHandler::OnSupervisionTransitionFinished);
+  BaseScreenHandler::RegisterMessages();
+}
+
+void SupervisionTransitionScreenHandler::Bind(
+    SupervisionTransitionScreen* screen) {
+  BaseScreenHandler::SetBaseScreen(screen);
+  screen_ = screen;
+  if (page_is_ready())
+    Initialize();
+}
+
+void SupervisionTransitionScreenHandler::Unbind() {
+  screen_ = nullptr;
+  BaseScreenHandler::SetBaseScreen(nullptr);
+  timer_.Stop();
+}
+
+void SupervisionTransitionScreenHandler::Show() {
+  if (!page_is_ready() || !screen_) {
+    show_on_init_ = true;
+    return;
+  }
+
+  timer_.Start(
+      FROM_HERE, kWaitingTimeout,
+      base::BindOnce(
+          &SupervisionTransitionScreenHandler::OnSupervisionTransitionFailed,
+          weak_factory_.GetWeakPtr()));
+
+  registrar_.Init(profile_->GetPrefs());
+  registrar_.Add(
+      arc::prefs::kArcSupervisionTransition,
+      base::BindRepeating(
+          &SupervisionTransitionScreenHandler::OnSupervisionTransitionFinished,
+          weak_factory_.GetWeakPtr()));
+
+  LoginScreenClient::Get()->login_screen()->SetAllowLoginAsGuest(false);
+  LoginScreenClient::Get()->login_screen()->SetShowGuestButtonInOobe(false);
+
+  base::DictionaryValue data;
+  data.SetBoolean("isRemovingSupervision",
+                  arc::GetSupervisionTransition(profile_) ==
+                      arc::ArcSupervisionTransition::CHILD_TO_REGULAR);
+  ShowScreenWithData(kScreenId, &data);
+}
+
+void SupervisionTransitionScreenHandler::Hide() {}
+
+void SupervisionTransitionScreenHandler::Initialize() {
+  profile_ = ProfileManager::GetPrimaryUserProfile();
+
+  if (!screen_ || !show_on_init_)
+    return;
+
+  Show();
+  show_on_init_ = false;
+}
+
+void SupervisionTransitionScreenHandler::OnSupervisionTransitionFailed() {
+  LOG(ERROR) << "Supervision transition failed; resetting ARC++ data.";
+  arc::ArcSessionManager::Get()->RequestArcDataRemoval();
+  arc::ArcSessionManager::Get()->StopAndEnableArc();
+  if (screen_) {
+    AllowJavascript();
+    FireWebUIListener("supervision-transition-failed");
+  }
+}
+
+void SupervisionTransitionScreenHandler::OnSupervisionTransitionFinished() {
+  if (screen_)
+    screen_->OnSupervisionTransitionFinished();
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/login/supervision_transition_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/supervision_transition_screen_handler.h
new file mode 100644
index 0000000..ee4cd04a
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/login/supervision_transition_screen_handler.h
@@ -0,0 +1,68 @@
+// 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_WEBUI_CHROMEOS_LOGIN_SUPERVISION_TRANSITION_SCREEN_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_SUPERVISION_TRANSITION_SCREEN_HANDLER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "base/timer/timer.h"
+#include "chrome/browser/chromeos/login/screens/supervision_transition_screen_view.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
+#include "components/prefs/pref_change_registrar.h"
+
+namespace chromeos {
+
+class SupervisionTransitionScreenHandler
+    : public BaseScreenHandler,
+      public SupervisionTransitionScreenView {
+ public:
+  SupervisionTransitionScreenHandler();
+  ~SupervisionTransitionScreenHandler() override;
+
+  // BaseScreenHandler:
+  void DeclareLocalizedValues(
+      ::login::LocalizedValuesBuilder* builder) override;
+  void RegisterMessages() override;
+
+  // SupervisionTransitionScreenView:
+  void Bind(SupervisionTransitionScreen* screen) override;
+  void Unbind() override;
+  void Show() override;
+  void Hide() override;
+
+ private:
+  // BaseScreenHandler:
+  void Initialize() override;
+
+  // Called when the max wait timeout is reached.
+  void OnSupervisionTransitionFailed();
+
+  void OnSupervisionTransitionFinished();
+
+  SupervisionTransitionScreen* screen_ = nullptr;
+
+  // Whether the screen should be shown right after initialization.
+  bool show_on_init_ = false;
+
+  // The primary user profile.
+  Profile* profile_ = nullptr;
+
+  // Timer used to exit the page when timeout reaches.
+  base::OneShotTimer timer_;
+
+  // Listens to pref changes.
+  PrefChangeRegistrar registrar_;
+
+  base::WeakPtrFactory<SupervisionTransitionScreenHandler> weak_factory_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(SupervisionTransitionScreenHandler);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_SUPERVISION_TRANSITION_SCREEN_HANDLER_H_
diff --git a/chrome/browser/ui/webui/settings/tts_handler.cc b/chrome/browser/ui/webui/settings/tts_handler.cc
index 84a6e408..243713f1 100644
--- a/chrome/browser/ui/webui/settings/tts_handler.cc
+++ b/chrome/browser/ui/webui/settings/tts_handler.cc
@@ -98,7 +98,7 @@
     response.SetString("languageCode", language_code);
     response.SetString("fullLanguageCode", voice.lang);
     response.SetInteger("languageScore", language_score);
-    response.SetString("extensionId", voice.extension_id);
+    response.SetString("extensionId", voice.engine_id);
     responses.GetList().push_back(std::move(response));
   }
   AllowJavascript();
@@ -141,7 +141,7 @@
       new content::Utterance(Profile::FromWebUI(web_ui()));
   utterance->set_text(text);
   utterance->set_voice_name(name);
-  utterance->set_extension_id(extension_id);
+  utterance->set_engine_id(extension_id);
   utterance->set_src_url(GURL("chrome://settings/manageAccessibility/tts"));
   utterance->set_event_delegate(this);
   content::TtsController::GetInstance()->Stop();
@@ -191,7 +191,7 @@
 
 void TtsHandler::WakeTtsEngine(const base::ListValue* args) {
   Profile* profile = Profile::FromWebUI(web_ui());
-  TtsExtensionEngine::GetInstance()->LoadBuiltInTtsExtension(profile);
+  TtsExtensionEngine::GetInstance()->LoadBuiltInTtsEngine(profile);
   extensions::ProcessManager::Get(profile)->WakeEventPage(
       extension_misc::kGoogleSpeechSynthesisExtensionId,
       base::BindOnce(&TtsHandler::OnTtsEngineAwake,
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_installation_task.cc b/chrome/browser/web_applications/extensions/bookmark_app_installation_task.cc
index d52b70c..c3f9e0f6 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_installation_task.cc
+++ b/chrome/browser/web_applications/extensions/bookmark_app_installation_task.cc
@@ -16,7 +16,6 @@
 #include "chrome/browser/web_applications/components/web_app_constants.h"
 #include "chrome/browser/web_applications/components/web_app_data_retriever.h"
 #include "chrome/browser/web_applications/extensions/bookmark_app_installer.h"
-#include "chrome/browser/web_applications/extensions/bookmark_app_tab_helper.h"
 #include "chrome/common/web_application_info.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/common/constants.h"
diff --git a/chrome/browser/web_applications/web_app_provider.cc b/chrome/browser/web_applications/web_app_provider.cc
index 5223c36..c3b583a 100644
--- a/chrome/browser/web_applications/web_app_provider.cc
+++ b/chrome/browser/web_applications/web_app_provider.cc
@@ -55,6 +55,9 @@
     CreateWebAppsSubsystems(profile);
   else
     CreateBookmarkAppsSubsystems(profile);
+
+  notification_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
+                              content::Source<Profile>(profile));
 }
 
 WebAppProvider::~WebAppProvider() = default;
@@ -91,9 +94,6 @@
   system_web_app_manager_ = std::make_unique<SystemWebAppManager>(
       profile, pending_app_manager_.get());
 
-  notification_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
-                              content::Source<Profile>(profile));
-
   web_app::ScanForExternalWebApps(
       profile, base::BindOnce(&WebAppProvider::OnScanForExternalWebApps,
                               weak_ptr_factory_.GetWeakPtr()));
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index ba84703..c536e30 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -636,18 +636,6 @@
 // Passes the name of the current running automated test to Chrome.
 const char kTestName[]                      = "test-name";
 
-// Specifies the enabled TLS 1.3 variant ("disabled", "draft23", "final").
-const char kTLS13Variant[] = "tls13-variant";
-
-// This mode disables the TLS 1.3 for the |kTLS13Variant| switch.
-const char kTLS13VariantDisabled[] = "disabled";
-
-// This mode enables TLS 1.3 draft-23 for the |kTLS13Variant| switch.
-const char kTLS13VariantDraft23[] = "draft23";
-
-// This mode enables TLS 1.3 final for the |kTLS13Variant| switch.
-const char kTLS13VariantFinal[] = "final";
-
 // Identifies a list of download sources as trusted, but only if proper group
 // policy is set.
 const char kTrustedDownloadSources[] = "trusted-download-sources";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 560c525..e0b8c0a 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -188,10 +188,6 @@
 extern const char kSystemLogUploadFrequency[];
 extern const char kTaskManagerShowExtraRenderers[];
 extern const char kTestName[];
-extern const char kTLS13Variant[];
-extern const char kTLS13VariantDisabled[];
-extern const char kTLS13VariantDraft23[];
-extern const char kTLS13VariantFinal[];
 extern const char kTrustedDownloadSources[];
 extern const char kTryChromeAgain[];
 extern const char kUnlimitedStorage[];
diff --git a/chrome/common/extensions/api/automation_internal.idl b/chrome/common/extensions/api/automation_internal.idl
index ce1eb38..084f0576 100644
--- a/chrome/common/extensions/api/automation_internal.idl
+++ b/chrome/common/extensions/api/automation_internal.idl
@@ -122,8 +122,9 @@
   // was enabled using enableTab().
   callback EnableTabCallback = void(DOMString tree_id);
 
-  // Callback called when enableDesktop() returns.
-  callback EnableDesktopCallback = void();
+  // Callback called when enableDesktop() returns. Returns the accessibility
+  // tree id of the desktop tree.
+  callback EnableDesktopCallback = void(DOMString tree_id);
 
   // Callback called when querySelector() returns.
   callback QuerySelectorCallback = void(long resultAutomationNodeID);
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index d4665f30..98a43ed7 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1697,11 +1697,6 @@
 // are "tls1.2", "tls1.3"
 const char kSSLVersionMax[] = "ssl.version_max";
 
-// String specifying the TLS 1.3 variant to negotiate when negotiating TLS 1.3.
-// Supported values are "disabled", which disables TLS 1.3, "draft23", and
-// "final".
-const char kTLS13Variant[] = "ssl.tls13_variant";
-
 // String specifying the TLS ciphersuites to disable. Ciphersuites are
 // specified as a comma-separated list of 16-bit hexadecimal values, with
 // the values being the ciphersuites assigned by the IANA registry (e.g.
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index ed33ad7..cfaf5c5 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -687,7 +687,6 @@
 extern const char kCertEnableSymantecLegacyInfrastructure[];
 extern const char kSSLVersionMin[];
 extern const char kSSLVersionMax[];
-extern const char kTLS13Variant[];
 extern const char kCipherSuiteBlacklist[];
 extern const char kH2ClientCertCoalescingHosts[];
 
diff --git a/chrome/renderer/extensions/automation_ax_tree_wrapper.cc b/chrome/renderer/extensions/automation_ax_tree_wrapper.cc
index e376a18..51d2245 100644
--- a/chrome/renderer/extensions/automation_ax_tree_wrapper.cc
+++ b/chrome/renderer/extensions/automation_ax_tree_wrapper.cc
@@ -202,16 +202,14 @@
 AutomationAXTreeWrapper::AutomationAXTreeWrapper(
     ui::AXTreeID tree_id,
     AutomationInternalCustomBindings* owner)
-    : tree_id_(tree_id), owner_(owner) {
-  // We have to initialize AXEventGenerator here - we can't do it in the
-  // initializer list because AXTree hasn't been initialized yet at that point.
-  SetTree(&tree_);
+    : tree_id_(tree_id), owner_(owner), event_generator_(&tree_) {
+  tree_.AddObserver(this);
 }
 
 AutomationAXTreeWrapper::~AutomationAXTreeWrapper() {
-  // Clearing the delegate so we don't get a callback for every node
-  // being deleted.
-  tree_.SetDelegate(nullptr);
+  // Stop observing so we don't get a callback for every node being deleted.
+  event_generator_.SetTree(nullptr);
+  tree_.RemoveObserver(this);
 }
 
 // static
@@ -237,7 +235,7 @@
   }
 
   for (const auto& update : event_bundle.updates) {
-    set_event_from(update.event_from);
+    event_generator_.set_event_from(update.event_from);
     deleted_node_ids_.clear();
     did_send_tree_change_during_unserialization_ = false;
 
@@ -283,7 +281,7 @@
   }
 
   // Send auto-generated AXEventGenerator events.
-  for (const auto& targeted_event : *this) {
+  for (const auto& targeted_event : event_generator_) {
     api::automation::EventType event_type =
         ToAutomationEvent(targeted_event.event_params.event);
     if (IsEventTypeHandledByAXEventGenerator(event_type)) {
@@ -295,7 +293,7 @@
                                   event_type);
     }
   }
-  ClearEvents();
+  event_generator_.ClearEvents();
 
   for (const auto& event : event_bundle.events) {
     if (event.event_type == ax::mojom::Event::kFocus ||
@@ -317,11 +315,14 @@
   return true;
 }
 
+bool AutomationAXTreeWrapper::IsDesktopTree() const {
+  return tree_.root()->data().role == ax::mojom::Role::kDesktop;
+}
+
 void AutomationAXTreeWrapper::OnNodeDataWillChange(
     ui::AXTree* tree,
     const ui::AXNodeData& old_node_data,
     const ui::AXNodeData& new_node_data) {
-  AXEventGenerator::OnNodeDataWillChange(tree, old_node_data, new_node_data);
   if (old_node_data.GetStringAttribute(ax::mojom::StringAttribute::kName) !=
       new_node_data.GetStringAttribute(ax::mojom::StringAttribute::kName))
     text_changed_node_ids_.push_back(new_node_data.id);
@@ -329,7 +330,6 @@
 
 void AutomationAXTreeWrapper::OnNodeWillBeDeleted(ui::AXTree* tree,
                                                   ui::AXNode* node) {
-  AXEventGenerator::OnNodeWillBeDeleted(tree, node);
   did_send_tree_change_during_unserialization_ |= owner_->SendTreeChangeEvent(
       api::automation::TREE_CHANGE_TYPE_NODEREMOVED, tree, node);
   deleted_node_ids_.push_back(node->id());
@@ -338,8 +338,7 @@
 void AutomationAXTreeWrapper::OnAtomicUpdateFinished(
     ui::AXTree* tree,
     bool root_changed,
-    const std::vector<ui::AXTreeDelegate::Change>& changes) {
-  AXEventGenerator::OnAtomicUpdateFinished(tree, root_changed, changes);
+    const std::vector<ui::AXTreeObserver::Change>& changes) {
   DCHECK_EQ(&tree_, tree);
   for (const auto change : changes) {
     ui::AXNode* node = change.node;
diff --git a/chrome/renderer/extensions/automation_ax_tree_wrapper.h b/chrome/renderer/extensions/automation_ax_tree_wrapper.h
index 1de9ed5..cffe2a4 100644
--- a/chrome/renderer/extensions/automation_ax_tree_wrapper.h
+++ b/chrome/renderer/extensions/automation_ax_tree_wrapper.h
@@ -16,7 +16,7 @@
 
 // A class that wraps one AXTree and all of the additional state
 // and helper methods needed to use it for the automation API.
-class AutomationAXTreeWrapper : public ui::AXEventGenerator {
+class AutomationAXTreeWrapper : public ui::AXTreeObserver {
  public:
   AutomationAXTreeWrapper(ui::AXTreeID tree_id,
                           AutomationInternalCustomBindings* owner);
@@ -38,8 +38,11 @@
       const ExtensionMsg_AccessibilityEventBundleParams& events,
       bool is_active_profile);
 
+  // Returns true if this is the desktop tree.
+  bool IsDesktopTree() const;
+
  private:
-  // AXEventGenerator overrides.
+  // AXTreeObserver overrides.
   void OnNodeDataWillChange(ui::AXTree* tree,
                             const ui::AXNodeData& old_node_data,
                             const ui::AXNodeData& new_node_data) override;
@@ -58,6 +61,7 @@
   AutomationInternalCustomBindings* owner_;
   std::vector<int> deleted_node_ids_;
   std::vector<int> text_changed_node_ids_;
+  ui::AXEventGenerator event_generator_;
 
   // Tracks whether a tree change event was sent during unserialization. Tree
   // changes outside of unserialization do not get reflected here. The value is
diff --git a/chrome/renderer/extensions/automation_internal_custom_bindings.cc b/chrome/renderer/extensions/automation_internal_custom_bindings.cc
index f2a90aa..c4a3f3f 100644
--- a/chrome/renderer/extensions/automation_internal_custom_bindings.cc
+++ b/chrome/renderer/extensions/automation_internal_custom_bindings.cc
@@ -95,8 +95,8 @@
     // All trees other than the desktop tree are scaled by the device
     // scale factor. When crossing out of another tree into the desktop
     // tree, unscale the bounds by the device scale factor.
-    if (previous_tree_wrapper->tree_id() != ui::DesktopAXTreeID() &&
-        tree_wrapper->tree_id() == ui::DesktopAXTreeID()) {
+    if (!previous_tree_wrapper->IsDesktopTree() &&
+        tree_wrapper->IsDesktopTree()) {
       float scale_factor = tree_wrapper->owner()->GetDeviceScaleFactor();
       if (scale_factor > 0)
         bounds.Scale(1.0 / scale_factor);
@@ -1081,7 +1081,7 @@
           node = next(node, target_tree_wrapper);
 
           // We explicitly disallow searches in the desktop tree.
-          if ((*target_tree_wrapper)->tree_id() == ui::DesktopAXTreeID())
+          if ((*target_tree_wrapper)->IsDesktopTree())
             return;
 
           if (!node)
@@ -1301,7 +1301,7 @@
     ui::AXTreeID focused_tree_id =
         child_tree_wrapper->tree()->data().focused_tree_id;
     if (focused_tree_id != ui::AXTreeIDUnknown() &&
-        focused_tree_id != ui::DesktopAXTreeID()) {
+        !child_tree_wrapper->IsDesktopTree()) {
       AutomationAXTreeWrapper* focused_tree_wrapper =
           GetAutomationAXTreeWrapperFromTreeID(
               child_tree_wrapper->tree()->data().focused_tree_id);
@@ -1402,11 +1402,12 @@
     state_shifter = state_shifter >> 1;
     state_pos++;
   }
-
-  AutomationAXTreeWrapper* top_tree_wrapper =
-      GetAutomationAXTreeWrapperFromTreeID(ui::DesktopAXTreeID());
-  if (!top_tree_wrapper)
-    top_tree_wrapper = tree_wrapper;
+  AutomationAXTreeWrapper* top_tree_wrapper = nullptr;
+  AutomationAXTreeWrapper* walker = tree_wrapper;
+  while (walker && walker != top_tree_wrapper) {
+    top_tree_wrapper = walker;
+    GetParent(walker->tree()->root(), &walker);
+  }
   AutomationAXTreeWrapper* focused_tree_wrapper = nullptr;
   ui::AXNode* focused_node = nullptr;
   const bool focused =
diff --git a/chrome/renderer/resources/extensions/automation_custom_bindings.js b/chrome/renderer/resources/extensions/automation_custom_bindings.js
index df16509..1569aa11 100644
--- a/chrome/renderer/resources/extensions/automation_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/automation_custom_bindings.js
@@ -37,7 +37,7 @@
 // TODO(aboxhall): Look into using WeakMap
 var idToCallback = {};
 
-var DESKTOP_TREE_ID = "0";
+var desktopId = undefined;
 
 automationUtil.storeTreeCallback = function(id, callback) {
   if (!callback)
@@ -79,7 +79,10 @@
  * @return {AutomationNode}
  */
 automationUtil.getFocus = function() {
-  var focusedNodeInfo = GetFocusNative(DESKTOP_TREE_ID);
+  if (desktopId === undefined)
+    return;
+
+  var focusedNodeInfo = GetFocusNative(desktopId);
   if (!focusedNodeInfo)
     return null;
   var tree = AutomationRootNode.getOrCreate(focusedNodeInfo.treeId);
@@ -130,21 +133,22 @@
   var desktopTree = null;
   apiFunctions.setHandleRequest('getDesktop', function(callback) {
     StartCachingAccessibilityTrees();
-    desktopTree = AutomationRootNode.get(DESKTOP_TREE_ID);
+    if (desktopId !== undefined)
+      desktopTree = AutomationRootNode.get(desktopId);
     if (!desktopTree) {
-      if (DESKTOP_TREE_ID in idToCallback)
-        idToCallback[DESKTOP_TREE_ID].push(callback);
-      else
-        idToCallback[DESKTOP_TREE_ID] = [callback];
-
-      // TODO(dtseng): Disable desktop tree once desktop object goes out of
-      // scope.
-      automationInternal.enableDesktop(function() {
+      automationInternal.enableDesktop(function(treeId) {
         if (hasLastError()) {
-          AutomationRootNode.destroy(DESKTOP_TREE_ID);
+          AutomationRootNode.destroy(treeId);
+          desktopId = undefined;
           callback();
           return;
         }
+        desktopId = treeId;
+        desktopTree = AutomationRootNode.getOrCreate(desktopId);
+        callback(desktopTree);
+
+        // TODO(dtseng): Disable desktop tree once desktop object goes out of
+        // scope.
       });
     } else {
       callback(desktopTree);
@@ -184,7 +188,7 @@
     var focusNodeImpl = privates(params.focusObject).impl;
     if (anchorNodeImpl.treeID !== focusNodeImpl.treeID)
       throw new Error('Selection anchor and focus must be in the same tree.');
-    if (anchorNodeImpl.treeID === DESKTOP_TREE_ID) {
+    if (anchorNodeImpl.treeID === desktopId) {
       throw new Error('Use AutomationNode.setSelection to set the selection ' +
           'in the desktop tree.');
     }
@@ -309,8 +313,7 @@
   // attribute or child nodes. If we've got that, wait for the full tree before
   // calling the callback.
   // TODO(dmazzoni): Don't send down placeholder (crbug.com/397553)
-  if (id != DESKTOP_TREE_ID && !targetTree.url &&
-      targetTree.children.length == 0)
+  if (id != desktopId && !targetTree.url && targetTree.children.length == 0)
     return;
 
   // If the tree wasn't available when getTree() was called, the callback will
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index a4fe88e6..45dc4f7 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -3181,7 +3181,7 @@
       "../browser/sessions/persistent_tab_restore_service_unittest.cc",
       "../browser/signin/signin_promo_unittest.cc",
       "../browser/speech/extension_api/extension_manifests_tts_unittest.cc",
-      "../browser/speech/tts_controller_unittest.cc",
+      "../browser/speech/tts_controller_delegate_impl_unittest.cc",
       "../browser/sync/sessions/browser_list_router_helper_unittest.cc",
       "../browser/sync/sessions/sync_sessions_router_tab_helper_unittest.cc",
       "../browser/sync/sync_ui_util_unittest.cc",  # Sync setup uses native ui.
@@ -3477,6 +3477,7 @@
       "../browser/google/google_brand_code_map_chromeos_unittest.cc",
       "../browser/media/webrtc/desktop_media_list_ash_unittest.cc",
       "../browser/metrics/perf/metric_collector_unittest.cc",
+      "../browser/metrics/perf/profile_provider_chromeos_unittest.cc",
       "../browser/notifications/chrome_ash_message_center_client_unittest.cc",
       "../browser/renderer_context_menu/mock_render_view_context_menu.cc",
       "../browser/renderer_context_menu/mock_render_view_context_menu.h",
@@ -4850,6 +4851,7 @@
       "//third_party/icu",
       "//third_party/libpng",
       "//third_party/zlib",
+      "//ui/base:base_interactive_ui_tests",
       "//ui/base:test_support",
       "//ui/events:events_interactive_ui_tests",
       "//ui/resources:ui_test_pak",
diff --git a/chrome/test/base/chrome_test_launcher.cc b/chrome/test/base/chrome_test_launcher.cc
index 52e0526..0fc7f41 100644
--- a/chrome/test/base/chrome_test_launcher.cc
+++ b/chrome/test/base/chrome_test_launcher.cc
@@ -147,7 +147,9 @@
   install_static::ScopedInstallDetails install_details;
 #endif
 
-#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_WIN)
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+  ChromeCrashReporterClient::Create();
+#elif defined(OS_WIN)
   // We leak this pointer intentionally. The crash client needs to outlive
   // all other code.
   ChromeCrashReporterClient* crash_client = new ChromeCrashReporterClient();
diff --git a/chrome/test/data/extensions/api_test/declarative/api/background.js b/chrome/test/data/extensions/api_test/declarative/api/background.js
index 8715be2..0e75553 100644
--- a/chrome/test/data/extensions/api_test/declarative/api/background.js
+++ b/chrome/test/data/extensions/api_test/declarative/api/background.js
@@ -111,7 +111,8 @@
   function testGetRules() {
     var callback = function(rules) {
       chrome.test.assertNoLastError();
-      // We are not given any gurantee on the order in which rules are returned.
+      // We are not given any guarantee on the order in which rules are
+      // returned.
       chrome.test.assertTrue(
           chrome.test.checkDeepEq([outputRule0, outputRule1], rules) ||
           chrome.test.checkDeepEq([outputRule1, outputRule0], rules));
@@ -123,7 +124,8 @@
   function testGetRules2() {
     var callback = function(rules) {
       chrome.test.assertNoLastError();
-      // We are not given any gurantee on the order in which rules are returned.
+      // We are not given any guarantee on the order in which rules are
+      // returned.
       chrome.test.assertTrue(
           chrome.test.checkDeepEq([outputRule0, outputRule1], rules) ||
           chrome.test.checkDeepEq([outputRule1, outputRule0], rules));
@@ -147,7 +149,7 @@
   // function testGetRules4() {
   //   var callback = function(rules) {
   //     chrome.test.assertNoLastError();
-  //     // We are not given any gurantee on the order in which rules are
+  //     // We are not given any guarantee on the order in which rules are
   //     // returned.
   //     chrome.test.assertTrue(
   //         chrome.test.checkDeepEq([outputRule0, outputRule1], rules) ||
diff --git a/chrome/test/data/local_ntp/local_ntp_browsertest.html b/chrome/test/data/local_ntp/local_ntp_browsertest.html
index ab0ad6a8a..7054d26 100644
--- a/chrome/test/data/local_ntp/local_ntp_browsertest.html
+++ b/chrome/test/data/local_ntp/local_ntp_browsertest.html
@@ -31,9 +31,11 @@
         <div id="logo-non-white" title="Google"></div>
         <!-- A doodle, if any: its link and image. -->
         <div id="logo-doodle">
-          <button id="logo-doodle-button">
-            <img id="logo-doodle-image" tabindex="-1"></img>
-          </button>
+          <div id="logo-doodle-container">
+            <button id="logo-doodle-button">
+              <img id="logo-doodle-image" tabindex="-1"></img>
+            </button>
+          </div>
           <iframe id="logo-doodle-iframe" scrolling="no"></iframe>
           <!-- A spinner, visible on dark-themed NTPs, prompting the doodle -->
           <button id="logo-doodle-notifier">
@@ -113,6 +115,23 @@
       </div>
     </dialog>
 
+    <dialog id="ddlsd">
+      <div id="ddlsd-title"></div>
+      <button id="ddlsd-close"></button>
+      <div id="ddlsd-content">
+        <button id="ddlsd-fbb" class="ddlsd-sbtn"></button>
+        <button id="ddlsd-twb" class="ddlsd-sbtn"></button>
+        <button id="ddlsd-emb" class="ddlsd-sbtn"></button>
+        <hr id="ddlsd-hr">
+        <div id="ddlsd-link">
+          <button id="ddlsd-copy"></button>
+          <span id="ddlsd-text-ctr">
+            <input type="text" id="ddlsd-text" dir="ltr">
+          </span>
+        </div>
+      </div>
+    </dialog>
+
     <dialog id="bg-sel-menu">
       <div id="bg-sel-title-bar">
       <div id="bg-sel-back-circle" tabindex="0" role="button">
diff --git a/chrome/test/data/webui/cr_elements/cr_slider_test.js b/chrome/test/data/webui/cr_elements/cr_slider_test.js
index fb32fcb..726bc26 100644
--- a/chrome/test/data/webui/cr_elements/cr_slider_test.js
+++ b/chrome/test/data/webui/cr_elements/cr_slider_test.js
@@ -17,6 +17,9 @@
     assertEquals(
         expected,
         window.getComputedStyle(crSlider)['pointer-events'] == 'none');
+    const expectedTabindex = expected ? '-1' : '0';
+    assertEquals(expectedTabindex, crSlider.getAttribute('tabindex'));
+    assertEquals(expectedTabindex, crSlider.$.knob.getAttribute('tabindex'));
   }
 
   function pressArrowRight() {
diff --git a/chrome/test/data/webui/settings/settings_animated_pages_test.js b/chrome/test/data/webui/settings/settings_animated_pages_test.js
index a46cd8a..6848dcc 100644
--- a/chrome/test/data/webui/settings/settings_animated_pages_test.js
+++ b/chrome/test/data/webui/settings/settings_animated_pages_test.js
@@ -7,12 +7,12 @@
     document.body.innerHTML = `
       <settings-animated-pages
           section="${settings.routes.SEARCH_ENGINES.section}">
-        <neon-animatable route-path="default">
+        <div route-path="default">
           <button id="subpage-trigger"></button>
-        </neon-animatable>
-        <neon-animatable route-path="${settings.routes.SEARCH_ENGINES.path}">
+        </div>
+        <div route-path="${settings.routes.SEARCH_ENGINES.path}">
           <button id="subpage-trigger"></button>
-        </neon-animatable>
+        </div>
       </settings-animated-pages>`;
 
     const animatedPages =
diff --git a/chromecast/browser/extensions/api/automation_internal/automation_event_router.cc b/chromecast/browser/extensions/api/automation_internal/automation_event_router.cc
index d81ba15..09dceebf 100644
--- a/chromecast/browser/extensions/api/automation_internal/automation_event_router.cc
+++ b/chromecast/browser/extensions/api/automation_internal/automation_event_router.cc
@@ -53,7 +53,7 @@
 void AutomationEventRouter::RegisterListenerWithDesktopPermission(
     const ExtensionId& extension_id,
     int listener_process_id) {
-  Register(extension_id, listener_process_id, ui::DesktopAXTreeID(), true);
+  Register(extension_id, listener_process_id, ui::AXTreeIDUnknown(), true);
 }
 
 void AutomationEventRouter::DispatchAccessibilityEvents(
@@ -125,16 +125,18 @@
     listener.extension_id = extension_id;
     listener.process_id = listener_process_id;
     listener.desktop = desktop;
-    listener.tree_ids.insert(ax_tree_id);
+    if (!desktop)
+      listener.tree_ids.insert(ax_tree_id);
     listeners_.push_back(listener);
     return;
   }
 
   // We have an entry with that process so update the set of tree ids it wants
   // to listen to, and update its desktop permission.
-  iter->tree_ids.insert(ax_tree_id);
   if (desktop)
     iter->desktop = true;
+  else
+    iter->tree_ids.insert(ax_tree_id);
 }
 
 void AutomationEventRouter::Observe(
diff --git a/chromecast/browser/extensions/api/automation_internal/automation_internal_api.cc b/chromecast/browser/extensions/api/automation_internal/automation_internal_api.cc
index 0bf5d2d..8bd2ce51 100644
--- a/chromecast/browser/extensions/api/automation_internal/automation_internal_api.cc
+++ b/chromecast/browser/extensions/api/automation_internal/automation_internal_api.cc
@@ -26,6 +26,7 @@
 #include "content/public/browser/browser_plugin_guest_manager.h"
 #include "content/public/browser/media_session.h"
 #include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
@@ -148,6 +149,12 @@
   return false;
 }
 
+ui::AXTreeID GetAXTreeIDFromRenderFrameHost(content::RenderFrameHost* rfh) {
+  auto* registry = ui::AXTreeIDRegistry::GetInstance();
+  return registry->GetAXTreeID(ui::AXTreeIDRegistry::FrameID(
+      rfh->GetProcess()->GetID(), rfh->GetRoutingID()));
+}
+
 }  // namespace
 
 // Helper class that receives accessibility data from |WebContents|.
@@ -187,7 +194,7 @@
 
   void RenderFrameDeleted(
       content::RenderFrameHost* render_frame_host) override {
-    ui::AXTreeID tree_id = render_frame_host->GetAXTreeID();
+    ui::AXTreeID tree_id = GetAXTreeIDFromRenderFrameHost(render_frame_host);
     AutomationEventRouter::GetInstance()->DispatchTreeDestroyedEvent(
         tree_id, browser_context_);
   }
@@ -195,7 +202,8 @@
   void MediaStartedPlaying(const MediaPlayerInfo& video_type,
                            const MediaPlayerId& id) override {
     content::AXEventNotificationDetails content_event_bundle;
-    content_event_bundle.ax_tree_id = id.render_frame_host->GetAXTreeID();
+    content_event_bundle.ax_tree_id =
+        GetAXTreeIDFromRenderFrameHost(id.render_frame_host);
     content_event_bundle.events.resize(1);
     content_event_bundle.events[0].event_type =
         ax::mojom::Event::kMediaStartedPlaying;
@@ -207,7 +215,8 @@
       const MediaPlayerId& id,
       WebContentsObserver::MediaStoppedReason reason) override {
     content::AXEventNotificationDetails content_event_bundle;
-    content_event_bundle.ax_tree_id = id.render_frame_host->GetAXTreeID();
+    content_event_bundle.ax_tree_id =
+        GetAXTreeIDFromRenderFrameHost(id.render_frame_host);
     content_event_bundle.events.resize(1);
     content_event_bundle.events[0].event_type =
         ax::mojom::Event::kMediaStoppedPlaying;
@@ -226,7 +235,7 @@
         return;
 
       content::AXEventNotificationDetails content_event_bundle;
-      content_event_bundle.ax_tree_id = rfh->GetAXTreeID();
+      content_event_bundle.ax_tree_id = GetAXTreeIDFromRenderFrameHost(rfh);
       content_event_bundle.events.resize(1);
       content_event_bundle.events[0].event_type =
           ax::mojom::Event::kMediaStartedPlaying;
diff --git a/chromecast/browser/ui/aura/accessibility/automation_manager_aura.cc b/chromecast/browser/ui/aura/accessibility/automation_manager_aura.cc
index 5709b283..1f14d74 100644
--- a/chromecast/browser/ui/aura/accessibility/automation_manager_aura.cc
+++ b/chromecast/browser/ui/aura/accessibility/automation_manager_aura.cc
@@ -117,17 +117,15 @@
 }
 
 AutomationManagerAura::AutomationManagerAura()
-    : AXHostDelegate(ui::DesktopAXTreeID()),
-      enabled_(false),
-      processing_events_(false) {}
+    : enabled_(false), processing_events_(false) {}
 
 AutomationManagerAura::~AutomationManagerAura() {}
 
 void AutomationManagerAura::Reset(bool reset_serializer) {
   if (!current_tree_) {
     desktop_root_ = std::make_unique<AXRootObjWrapper>(this);
-    current_tree_ = std::make_unique<AXTreeSourceAura>(desktop_root_.get(),
-                                                       ui::DesktopAXTreeID());
+    current_tree_ =
+        std::make_unique<AXTreeSourceAura>(desktop_root_.get(), ax_tree_id());
   }
   reset_serializer ? current_tree_serializer_.reset()
                    : current_tree_serializer_.reset(
@@ -150,7 +148,7 @@
   processing_events_ = true;
 
   ExtensionMsg_AccessibilityEventBundleParams event_bundle;
-  event_bundle.tree_id = ui::DesktopAXTreeID();
+  event_bundle.tree_id = ax_tree_id();
   event_bundle.mouse_location = aura::Env::GetInstance()->last_mouse_location();
 
   ui::AXTreeUpdate update;
diff --git a/chromecast/renderer/extensions/automation_ax_tree_wrapper.cc b/chromecast/renderer/extensions/automation_ax_tree_wrapper.cc
index 854e891..99735251 100644
--- a/chromecast/renderer/extensions/automation_ax_tree_wrapper.cc
+++ b/chromecast/renderer/extensions/automation_ax_tree_wrapper.cc
@@ -203,16 +203,14 @@
 AutomationAXTreeWrapper::AutomationAXTreeWrapper(
     ui::AXTreeID tree_id,
     AutomationInternalCustomBindings* owner)
-    : tree_id_(tree_id), owner_(owner) {
-  // We have to initialize AXEventGenerator here - we can't do it in the
-  // initializer list because AXTree hasn't been initialized yet at that point.
-  SetTree(&tree_);
+    : tree_id_(tree_id), owner_(owner), event_generator_(&tree_) {
+  tree_.AddObserver(this);
 }
 
 AutomationAXTreeWrapper::~AutomationAXTreeWrapper() {
-  // Clearing the delegate so we don't get a callback for every node
-  // being deleted.
-  tree_.SetDelegate(nullptr);
+  // Stop observing so we don't get a callback for every node being deleted.
+  event_generator_.SetTree(nullptr);
+  tree_.RemoveObserver(this);
 }
 
 // static
@@ -238,7 +236,7 @@
   }
 
   for (const auto& update : event_bundle.updates) {
-    set_event_from(update.event_from);
+    event_generator_.set_event_from(update.event_from);
     deleted_node_ids_.clear();
     did_send_tree_change_during_unserialization_ = false;
 
@@ -284,7 +282,7 @@
   }
 
   // Send auto-generated AXEventGenerator events.
-  for (const auto& targeted_event : *this) {
+  for (const auto& targeted_event : event_generator_) {
     api::automation::EventType event_type =
         ToAutomationEvent(targeted_event.event_params.event);
     if (IsEventTypeHandledByAXEventGenerator(event_type)) {
@@ -296,7 +294,7 @@
                                   event_type);
     }
   }
-  ClearEvents();
+  event_generator_.ClearEvents();
 
   for (const auto& event : event_bundle.events) {
     if (event.event_type == ax::mojom::Event::kFocus ||
@@ -318,11 +316,14 @@
   return true;
 }
 
+bool AutomationAXTreeWrapper::IsDesktopTree() const {
+  return tree_.root()->data().role == ax::mojom::Role::kDesktop;
+}
+
 void AutomationAXTreeWrapper::OnNodeDataWillChange(
     ui::AXTree* tree,
     const ui::AXNodeData& old_node_data,
     const ui::AXNodeData& new_node_data) {
-  AXEventGenerator::OnNodeDataWillChange(tree, old_node_data, new_node_data);
   if (old_node_data.GetStringAttribute(ax::mojom::StringAttribute::kName) !=
       new_node_data.GetStringAttribute(ax::mojom::StringAttribute::kName))
     text_changed_node_ids_.push_back(new_node_data.id);
@@ -330,7 +331,6 @@
 
 void AutomationAXTreeWrapper::OnNodeWillBeDeleted(ui::AXTree* tree,
                                                   ui::AXNode* node) {
-  AXEventGenerator::OnNodeWillBeDeleted(tree, node);
   did_send_tree_change_during_unserialization_ |= owner_->SendTreeChangeEvent(
       api::automation::TREE_CHANGE_TYPE_NODEREMOVED, tree, node);
   deleted_node_ids_.push_back(node->id());
@@ -339,8 +339,7 @@
 void AutomationAXTreeWrapper::OnAtomicUpdateFinished(
     ui::AXTree* tree,
     bool root_changed,
-    const std::vector<ui::AXTreeDelegate::Change>& changes) {
-  AXEventGenerator::OnAtomicUpdateFinished(tree, root_changed, changes);
+    const std::vector<ui::AXTreeObserver::Change>& changes) {
   DCHECK_EQ(&tree_, tree);
   for (const auto change : changes) {
     ui::AXNode* node = change.node;
diff --git a/chromecast/renderer/extensions/automation_ax_tree_wrapper.h b/chromecast/renderer/extensions/automation_ax_tree_wrapper.h
index e5fd3b9f..f84a2fe 100644
--- a/chromecast/renderer/extensions/automation_ax_tree_wrapper.h
+++ b/chromecast/renderer/extensions/automation_ax_tree_wrapper.h
@@ -17,7 +17,7 @@
 
 // A class that wraps one AXTree and all of the additional state
 // and helper methods needed to use it for the automation API.
-class AutomationAXTreeWrapper : public ui::AXEventGenerator {
+class AutomationAXTreeWrapper : public ui::AXTreeObserver {
  public:
   AutomationAXTreeWrapper(ui::AXTreeID tree_id,
                           AutomationInternalCustomBindings* owner);
@@ -39,8 +39,11 @@
       const ExtensionMsg_AccessibilityEventBundleParams& events,
       bool is_active_profile);
 
+  // Returns true if this is the desktop tree.
+  bool IsDesktopTree() const;
+
  private:
-  // AXEventGenerator overrides.
+  // AXTreeObserver overrides.
   void OnNodeDataWillChange(ui::AXTree* tree,
                             const ui::AXNodeData& old_node_data,
                             const ui::AXNodeData& new_node_data) override;
@@ -59,6 +62,7 @@
   AutomationInternalCustomBindings* owner_;
   std::vector<int> deleted_node_ids_;
   std::vector<int> text_changed_node_ids_;
+  ui::AXEventGenerator event_generator_;
 
   // Tracks whether a tree change event was sent during unserialization. Tree
   // changes outside of unserialization do not get reflected here. The value is
diff --git a/chromecast/renderer/extensions/automation_internal_custom_bindings.cc b/chromecast/renderer/extensions/automation_internal_custom_bindings.cc
index 9fe8091..5c590686 100644
--- a/chromecast/renderer/extensions/automation_internal_custom_bindings.cc
+++ b/chromecast/renderer/extensions/automation_internal_custom_bindings.cc
@@ -96,8 +96,8 @@
     // All trees other than the desktop tree are scaled by the device
     // scale factor. When crossing out of another tree into the desktop
     // tree, unscale the bounds by the device scale factor.
-    if (previous_tree_wrapper->tree_id() != ui::DesktopAXTreeID() &&
-        tree_wrapper->tree_id() == ui::DesktopAXTreeID()) {
+    if (!previous_tree_wrapper->IsDesktopTree() &&
+        tree_wrapper->IsDesktopTree()) {
       float scale_factor = tree_wrapper->owner()->GetDeviceScaleFactor();
       if (scale_factor > 0)
         bounds.Scale(1.0 / scale_factor);
@@ -371,6 +371,61 @@
   NodeIDPlusStringBoolFunction function_;
 };
 
+using NodeIDPlusDimensionsFunction =
+    void (*)(v8::Isolate* isolate,
+             v8::ReturnValue<v8::Value> result,
+             AutomationAXTreeWrapper* tree_wrapper,
+             ui::AXNode* node,
+             int x,
+             int y,
+             int width,
+             int height);
+
+class NodeIDPlusDimensionsWrapper
+    : public base::RefCountedThreadSafe<NodeIDPlusDimensionsWrapper> {
+ public:
+  NodeIDPlusDimensionsWrapper(
+      AutomationInternalCustomBindings* automation_bindings,
+      NodeIDPlusDimensionsFunction function)
+      : automation_bindings_(automation_bindings), function_(function) {}
+
+  void Run(const v8::FunctionCallbackInfo<v8::Value>& args) {
+    v8::Isolate* isolate = automation_bindings_->GetIsolate();
+    if (args.Length() < 6 || !args[0]->IsString() || !args[1]->IsInt32() ||
+        !args[2]->IsInt32() || !args[3]->IsInt32() || !args[4]->IsInt32() ||
+        !args[5]->IsInt32()) {
+      ThrowInvalidArgumentsException(automation_bindings_);
+    }
+
+    ui::AXTreeID tree_id =
+        ui::AXTreeID::FromString(*v8::String::Utf8Value(isolate, args[0]));
+    int node_id = args[1].As<v8::Int32>()->Value();
+    int x = args[2].As<v8::Int32>()->Value();
+    int y = args[3].As<v8::Int32>()->Value();
+    int width = args[4].As<v8::Int32>()->Value();
+    int height = args[5].As<v8::Int32>()->Value();
+
+    AutomationAXTreeWrapper* tree_wrapper =
+        automation_bindings_->GetAutomationAXTreeWrapperFromTreeID(tree_id);
+    if (!tree_wrapper)
+      return;
+
+    ui::AXNode* node = tree_wrapper->tree()->GetFromId(node_id);
+    if (!node)
+      return;
+
+    function_(isolate, args.GetReturnValue(), tree_wrapper, node, x, y, width,
+              height);
+  }
+
+ private:
+  virtual ~NodeIDPlusDimensionsWrapper() {}
+
+  friend class base::RefCountedThreadSafe<NodeIDPlusDimensionsWrapper>;
+
+  AutomationInternalCustomBindings* automation_bindings_;
+  NodeIDPlusDimensionsFunction function_;
+};
 }  // namespace
 
 class AutomationMessageFilter : public IPC::MessageFilter {
@@ -695,6 +750,20 @@
         result.Set(RectToV8Object(isolate, global_bounds));
       });
 
+  RouteNodeIDPlusDimensionsFunction(
+      "ComputeGlobalBounds",
+      [](v8::Isolate* isolate, v8::ReturnValue<v8::Value> result,
+         AutomationAXTreeWrapper* tree_wrapper, ui::AXNode* node, int x, int y,
+         int width, int height) {
+        gfx::RectF local_bounds(x, y, width, height);
+
+        // Convert from local coordinates in Android window, to global
+        // coordinates spanning entire screen.
+        gfx::Rect global_bounds = ComputeGlobalNodeBounds(
+            tree_wrapper, node, local_bounds, nullptr, false /* clip_bounds */);
+        result.Set(RectToV8Object(isolate, global_bounds));
+      });
+
   // Bindings that take a Tree ID and Node ID and string attribute name
   // and return a property of the node.
 
@@ -1013,7 +1082,7 @@
           node = next(node, target_tree_wrapper);
 
           // We explicitly disallow searches in the desktop tree.
-          if ((*target_tree_wrapper)->tree_id() == ui::DesktopAXTreeID())
+          if ((*target_tree_wrapper)->IsDesktopTree())
             return;
 
           if (!node)
@@ -1233,7 +1302,7 @@
     ui::AXTreeID focused_tree_id =
         child_tree_wrapper->tree()->data().focused_tree_id;
     if (focused_tree_id != ui::AXTreeIDUnknown() &&
-        focused_tree_id != ui::DesktopAXTreeID()) {
+        !child_tree_wrapper->IsDesktopTree()) {
       AutomationAXTreeWrapper* focused_tree_wrapper =
           GetAutomationAXTreeWrapperFromTreeID(
               child_tree_wrapper->tree()->data().focused_tree_id);
@@ -1334,11 +1403,12 @@
     state_shifter = state_shifter >> 1;
     state_pos++;
   }
-
-  AutomationAXTreeWrapper* top_tree_wrapper =
-      GetAutomationAXTreeWrapperFromTreeID(ui::DesktopAXTreeID());
-  if (!top_tree_wrapper)
-    top_tree_wrapper = tree_wrapper;
+  AutomationAXTreeWrapper* top_tree_wrapper = nullptr;
+  AutomationAXTreeWrapper* walker = tree_wrapper;
+  while (walker && walker != top_tree_wrapper) {
+    top_tree_wrapper = walker;
+    GetParent(walker->tree()->root(), &walker);
+  }
   AutomationAXTreeWrapper* focused_tree_wrapper = nullptr;
   ui::AXNode* focused_node = nullptr;
   const bool focused =
@@ -1529,6 +1599,15 @@
       name, base::BindRepeating(&NodeIDPlusStringBoolWrapper::Run, wrapper));
 }
 
+void AutomationInternalCustomBindings::RouteNodeIDPlusDimensionsFunction(
+    const std::string& name,
+    NodeIDPlusDimensionsFunction callback) {
+  scoped_refptr<NodeIDPlusDimensionsWrapper> wrapper =
+      new NodeIDPlusDimensionsWrapper(this, callback);
+  RouteHandlerFunction(
+      name, base::BindRepeating(&NodeIDPlusDimensionsWrapper::Run, wrapper));
+}
+
 void AutomationInternalCustomBindings::GetChildIDAtIndex(
     const v8::FunctionCallbackInfo<v8::Value>& args) {
   if (args.Length() < 3 || !args[2]->IsNumber()) {
diff --git a/chromecast/renderer/extensions/automation_internal_custom_bindings.h b/chromecast/renderer/extensions/automation_internal_custom_bindings.h
index 9426b12..7cc26226 100644
--- a/chromecast/renderer/extensions/automation_internal_custom_bindings.h
+++ b/chromecast/renderer/extensions/automation_internal_custom_bindings.h
@@ -163,6 +163,16 @@
                          ui::AXNode* node,
                          const std::string& strVal,
                          bool boolVal)> callback);
+  void RouteNodeIDPlusDimensionsFunction(
+      const std::string& name,
+      void (*callback)(v8::Isolate* isolate,
+                       v8::ReturnValue<v8::Value> result,
+                       AutomationAXTreeWrapper* tree_wrapper,
+                       ui::AXNode* node,
+                       int start,
+                       int end,
+                       int width,
+                       int height));
 
   //
   // Access the cached accessibility trees and properties of their nodes.
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc
index e58659a..2a1be532f 100644
--- a/chromeos/chromeos_switches.cc
+++ b/chromeos/chromeos_switches.cc
@@ -681,7 +681,6 @@
 }
 
 bool IsAssistantEnabled() {
-  // TODO(xiaohuic): We will add locale restrictions later.
   return IsAssistantFlagsEnabled();
 }
 
diff --git a/chromeos/hugepage_text/OWNERS b/chromeos/hugepage_text/OWNERS
index 7e39036..670bf340 100644
--- a/chromeos/hugepage_text/OWNERS
+++ b/chromeos/hugepage_text/OWNERS
@@ -1,4 +1,4 @@
-yunlian@chromium.org
 llozano@chromium.org
-shenhan@chromium.org
 cmtice@chromium.org
+gbiv@chromium.org
+manojgupta@chromium.org
diff --git a/chromeos/hugepage_text/hugepage_text.cc b/chromeos/hugepage_text/hugepage_text.cc
index eb9f862..157a70e 100644
--- a/chromeos/hugepage_text/hugepage_text.cc
+++ b/chromeos/hugepage_text/hugepage_text.cc
@@ -9,6 +9,8 @@
 
 #include <link.h>
 #include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/time.h>
 
 #include "base/bit_cast.h"
 #include "base/logging.h"
@@ -61,6 +63,10 @@
     munmap(haddr, hsize);
     return NULL;
   }
+
+  if (mlock(haddr, hsize)) {
+    PLOG(INFO) << "Mlocking text pages failed";
+  }
   return haddr;
 }
 
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.cc b/chromeos/services/assistant/assistant_manager_service_impl.cc
index aefaf0b..b6d0d6d 100644
--- a/chromeos/services/assistant/assistant_manager_service_impl.cc
+++ b/chromeos/services/assistant/assistant_manager_service_impl.cc
@@ -750,7 +750,7 @@
 void AssistantManagerServiceImpl::PostInitAssistant(
     base::OnceClosure post_init_callback,
     std::unique_ptr<assistant_client::AssistantManager>* assistant_manager) {
-  DCHECK(service_->main_task_runner()->BelongsToCurrentThread());
+  DCHECK(service_->main_task_runner()->RunsTasksInCurrentSequence());
 
   assistant_manager_ = std::move(*assistant_manager);
   assistant_manager_internal_ =
diff --git a/chromeos/services/assistant/assistant_settings_manager_impl.cc b/chromeos/services/assistant/assistant_settings_manager_impl.cc
index a96b47c..636ee36 100644
--- a/chromeos/services/assistant/assistant_settings_manager_impl.cc
+++ b/chromeos/services/assistant/assistant_settings_manager_impl.cc
@@ -38,7 +38,7 @@
                                                GetSettingsCallback callback) {
   DCHECK(assistant_manager_service_->GetState() ==
          AssistantManagerService::State::RUNNING);
-  DCHECK(service_->main_task_runner()->BelongsToCurrentThread());
+  DCHECK(service_->main_task_runner()->RunsTasksInCurrentSequence());
 
   // Wraps the callback into a repeating callback since the server side
   // interface requires the callback to be copyable.
@@ -70,7 +70,7 @@
     GetSettingsCallback callback) {
   DCHECK(assistant_manager_service_->GetState() ==
          AssistantManagerService::State::RUNNING);
-  DCHECK(service_->main_task_runner()->BelongsToCurrentThread());
+  DCHECK(service_->main_task_runner()->RunsTasksInCurrentSequence());
   // Wraps the callback into a repeating callback since the server side
   // interface requires the callback to be copyable.
   std::string serialized_proto = SerializeUpdateSettingsUiRequest(update);
@@ -101,7 +101,7 @@
     mojom::SpeakerIdEnrollmentClientPtr client) {
   DCHECK(assistant_manager_service_->GetState() ==
          AssistantManagerService::State::RUNNING);
-  DCHECK(service_->main_task_runner()->BelongsToCurrentThread());
+  DCHECK(service_->main_task_runner()->RunsTasksInCurrentSequence());
 
   speaker_id_enrollment_client_ = std::move(client);
 
@@ -126,6 +126,7 @@
     StopSpeakerIdEnrollmentCallback callback) {
   DCHECK(assistant_manager_service_->GetState() ==
          AssistantManagerService::State::RUNNING);
+  DCHECK(service_->main_task_runner()->RunsTasksInCurrentSequence());
   assistant_manager_service_->assistant_manager_internal()
       ->StopSpeakerIdEnrollment([repeating_callback =
                                      base::AdaptCallbackForRepeating(
@@ -142,6 +143,7 @@
 
 void AssistantSettingsManagerImpl::HandleSpeakerIdEnrollmentUpdate(
     const assistant_client::SpeakerIdEnrollmentUpdate& update) {
+  DCHECK(service_->main_task_runner()->RunsTasksInCurrentSequence());
   switch (update.state) {
     case SpeakerIdEnrollmentState::LISTEN:
       speaker_id_enrollment_client_->OnListeningHotword();
@@ -170,6 +172,7 @@
 
 void AssistantSettingsManagerImpl::HandleSpeakerIdEnrollmentStatusSync(
     const assistant_client::SpeakerIdEnrollmentUpdate& update) {
+  DCHECK(service_->main_task_runner()->RunsTasksInCurrentSequence());
   switch (update.state) {
     case SpeakerIdEnrollmentState::LISTEN:
       speaker_id_enrollment_done_ = false;
@@ -194,12 +197,13 @@
 
 void AssistantSettingsManagerImpl::HandleStopSpeakerIdEnrollment(
     base::RepeatingCallback<void()> callback) {
+  DCHECK(service_->main_task_runner()->RunsTasksInCurrentSequence());
   speaker_id_enrollment_client_.reset();
   callback.Run();
 }
 
 void AssistantSettingsManagerImpl::SyncSpeakerIdEnrollmentStatus() {
-  DCHECK(service_->main_task_runner()->BelongsToCurrentThread());
+  DCHECK(service_->main_task_runner()->RunsTasksInCurrentSequence());
   if (speaker_id_enrollment_client_) {
     // Speaker id enrollment is in progress.
     return;
@@ -225,7 +229,7 @@
 }
 
 void AssistantSettingsManagerImpl::UpdateServerDeviceSettings() {
-  DCHECK(service_->main_task_runner()->BelongsToCurrentThread());
+  DCHECK(service_->main_task_runner()->RunsTasksInCurrentSequence());
 
   const std::string device_id =
       assistant_manager_service_->assistant_manager()->GetDeviceId();
diff --git a/chromeos/services/assistant/audio_decoder/assistant_audio_decoder.cc b/chromeos/services/assistant/audio_decoder/assistant_audio_decoder.cc
index 4dc4ae3..e44cf0e 100644
--- a/chromeos/services/assistant/audio_decoder/assistant_audio_decoder.cc
+++ b/chromeos/services/assistant/audio_decoder/assistant_audio_decoder.cc
@@ -4,6 +4,9 @@
 
 #include "chromeos/services/assistant/audio_decoder/assistant_audio_decoder.h"
 
+#include <utility>
+#include <vector>
+
 #include "base/threading/thread.h"
 #include "chromeos/services/assistant/audio_decoder/ipc_data_source.h"
 #include "media/base/audio_bus.h"
@@ -32,7 +35,7 @@
     mojom::AssistantMediaDataSourcePtr data_source)
     : service_ref_(std::move(service_ref)),
       client_(std::move(client)),
-      task_runner_(base::ThreadTaskRunnerHandle::Get()),
+      task_runner_(base::SequencedTaskRunnerHandle::Get()),
       data_source_(std::make_unique<IPCDataSource>(std::move(data_source))),
       media_thread_(std::make_unique<base::Thread>("media_thread")),
       weak_factory_(this) {
diff --git a/chromeos/services/assistant/audio_decoder/ipc_data_source.cc b/chromeos/services/assistant/audio_decoder/ipc_data_source.cc
index 0e4d322..96db366a 100644
--- a/chromeos/services/assistant/audio_decoder/ipc_data_source.cc
+++ b/chromeos/services/assistant/audio_decoder/ipc_data_source.cc
@@ -4,7 +4,11 @@
 
 #include "chromeos/services/assistant/audio_decoder/ipc_data_source.h"
 
-#include "base/threading/thread_task_runner_handle.h"
+#include <algorithm>
+#include <utility>
+#include <vector>
+
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "mojo/public/cpp/bindings/message.h"
 
 namespace chromeos {
@@ -13,7 +17,7 @@
 IPCDataSource::IPCDataSource(
     mojom::AssistantMediaDataSourcePtr media_data_source)
     : media_data_source_(std::move(media_data_source)),
-      utility_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
+      utility_task_runner_(base::SequencedTaskRunnerHandle::Get()) {
   DETACH_FROM_THREAD(data_source_thread_checker_);
 }
 
diff --git a/chromeos/services/assistant/platform/audio_input_impl.cc b/chromeos/services/assistant/platform/audio_input_impl.cc
index 0065814..303ed8d 100644
--- a/chromeos/services/assistant/platform/audio_input_impl.cc
+++ b/chromeos/services/assistant/platform/audio_input_impl.cc
@@ -139,7 +139,7 @@
 
 AudioInputImpl::AudioInputImpl(service_manager::Connector* connector)
     : connector_(connector),
-      task_runner_(base::ThreadTaskRunnerHandle::Get()),
+      task_runner_(base::SequencedTaskRunnerHandle::Get()),
       weak_factory_(this) {
   DETACH_FROM_SEQUENCE(observer_sequence_checker_);
 
diff --git a/chromeos/services/assistant/platform/audio_output_provider_impl.cc b/chromeos/services/assistant/platform/audio_output_provider_impl.cc
index 227d8dde..065f8d14 100644
--- a/chromeos/services/assistant/platform/audio_output_provider_impl.cc
+++ b/chromeos/services/assistant/platform/audio_output_provider_impl.cc
@@ -88,7 +88,7 @@
       assistant_client::OutputStreamType type,
       assistant_client::OutputStreamFormat format)
       : connector_(connector),
-        main_thread_task_runner_(task_runner),
+        main_task_runner_(task_runner),
         background_thread_task_runner_(background_task_runner),
         audio_decoder_factory_(audio_decoder_factory),
         stream_type_(type),
@@ -101,7 +101,7 @@
 
   ~AudioOutputImpl() override {
     // This ensures that it will be executed after StartOnMainThread.
-    main_thread_task_runner_->PostTask(
+    main_task_runner_->PostTask(
         FROM_HERE,
         base::BindOnce(
             [](std::unique_ptr<AudioDeviceOwner> device_owner,
@@ -110,8 +110,7 @@
               background_runner->DeleteSoon(FROM_HERE, device_owner.release());
             },
             std::move(device_owner_), background_thread_task_runner_));
-    main_thread_task_runner_->DeleteSoon(FROM_HERE,
-                                         audio_stream_handler_.release());
+    main_task_runner_->DeleteSoon(FROM_HERE, audio_stream_handler_.release());
   }
 
   // assistant_client::AudioOutput overrides:
@@ -119,7 +118,7 @@
 
   void Start(assistant_client::AudioOutput::Delegate* delegate) override {
     if (IsEncodedFormat(format_)) {
-      main_thread_task_runner_->PostTask(
+      main_task_runner_->PostTask(
           FROM_HERE,
           base::BindOnce(
               &AudioStreamHandler::StartAudioDecoder,
@@ -129,7 +128,7 @@
                              base::Unretained(device_owner_.get()),
                              audio_stream_handler_.get(), connector_)));
     } else {
-      main_thread_task_runner_->PostTask(
+      main_task_runner_->PostTask(
           FROM_HERE, base::BindOnce(&AudioDeviceOwner::StartOnMainThread,
                                     base::Unretained(device_owner_.get()),
                                     delegate, connector_, format_));
@@ -139,7 +138,7 @@
   void Stop() override {
     if (IsEncodedFormat(format_)) {
       device_owner_->SetDelegate(nullptr);
-      main_thread_task_runner_->PostTask(
+      main_task_runner_->PostTask(
           FROM_HERE,
           base::BindOnce(&AudioStreamHandler::OnStopped,
                          base::Unretained(audio_stream_handler_.get())));
@@ -152,7 +151,7 @@
 
  private:
   service_manager::Connector* connector_;
-  scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner_;
+  scoped_refptr<base::SequencedTaskRunner> main_task_runner_;
   scoped_refptr<base::SequencedTaskRunner> background_thread_task_runner_;
   mojom::AssistantAudioDecoderFactory* audio_decoder_factory_;
 
@@ -170,7 +169,7 @@
 
 VolumeControlImpl::VolumeControlImpl(service_manager::Connector* connector)
     : binding_(this),
-      main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+      main_task_runner_(base::SequencedTaskRunnerHandle::Get()),
       weak_factory_(this) {
   connector->BindInterface(ash::mojom::kServiceName, &volume_control_ptr_);
   ash::mojom::VolumeObserverPtr observer;
@@ -188,7 +187,7 @@
 }
 
 void VolumeControlImpl::SetSystemVolume(float new_volume, bool user_initiated) {
-  main_thread_task_runner_->PostTask(
+  main_task_runner_->PostTask(
       FROM_HERE,
       base::BindOnce(&VolumeControlImpl::SetSystemVolumeOnMainThread,
                      weak_factory_.GetWeakPtr(), new_volume, user_initiated));
@@ -208,7 +207,7 @@
 }
 
 void VolumeControlImpl::SetSystemMuted(bool muted) {
-  main_thread_task_runner_->PostTask(
+  main_task_runner_->PostTask(
       FROM_HERE, base::BindOnce(&VolumeControlImpl::SetSystemMutedOnMainThread,
                                 weak_factory_.GetWeakPtr(), muted));
 }
@@ -223,12 +222,12 @@
 
 void VolumeControlImpl::SetSystemVolumeOnMainThread(float new_volume,
                                                     bool user_initiated) {
-  DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
   volume_control_ptr_->SetVolume(new_volume * 100.0, user_initiated);
 }
 
 void VolumeControlImpl::SetSystemMutedOnMainThread(bool muted) {
-  DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
   volume_control_ptr_->SetMuted(muted);
 }
 
@@ -237,7 +236,7 @@
     scoped_refptr<base::SequencedTaskRunner> background_task_runner)
     : volume_control_impl_(connector),
       connector_(connector),
-      main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+      main_task_runner_(base::SequencedTaskRunnerHandle::Get()),
       background_task_runner_(background_task_runner) {
   connector_->BindInterface(mojom::kAudioDecoderServiceName,
                             mojo::MakeRequest(&audio_decoder_factory_ptr_));
@@ -251,7 +250,7 @@
     const assistant_client::OutputStreamFormat& stream_format) {
   // Owned by one arbitrary thread inside libassistant. It will be destroyed
   // once assistant_client::AudioOutput::Delegate::OnStopped() is called.
-  return new AudioOutputImpl(connector_, main_thread_task_runner_,
+  return new AudioOutputImpl(connector_, main_task_runner_,
                              background_task_runner_, audio_decoder_factory_,
                              type, stream_format);
 }
@@ -289,7 +288,7 @@
 AudioDeviceOwner::AudioDeviceOwner(
     scoped_refptr<base::SequencedTaskRunner> task_runner,
     scoped_refptr<base::SequencedTaskRunner> background_task_runner)
-    : main_thread_task_runner_(task_runner),
+    : main_task_runner_(task_runner),
       background_task_runner_(background_task_runner) {}
 
 AudioDeviceOwner::~AudioDeviceOwner() {
@@ -301,7 +300,7 @@
     service_manager::Connector* connector,
     const assistant_client::OutputStreamFormat& format) {
   DCHECK(!output_device_);
-  DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
 
   delegate_ = delegate;
   format_ = format;
diff --git a/chromeos/services/assistant/platform/audio_output_provider_impl.h b/chromeos/services/assistant/platform/audio_output_provider_impl.h
index 8c891968..b47af248 100644
--- a/chromeos/services/assistant/platform/audio_output_provider_impl.h
+++ b/chromeos/services/assistant/platform/audio_output_provider_impl.h
@@ -52,7 +52,7 @@
 
   ash::mojom::AssistantVolumeControlPtr volume_control_ptr_;
   mojo::Binding<ash::mojom::VolumeObserver> binding_;
-  scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner_;
+  scoped_refptr<base::SequencedTaskRunner> main_task_runner_;
 
   int volume_ = 100;
   bool mute_ = false;
@@ -89,7 +89,7 @@
  private:
   VolumeControlImpl volume_control_impl_;
   service_manager::Connector* connector_;
-  scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner_;
+  scoped_refptr<base::SequencedTaskRunner> main_task_runner_;
   scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
   mojom::AssistantAudioDecoderFactoryPtr audio_decoder_factory_ptr_;
   mojom::AssistantAudioDecoderFactory* audio_decoder_factory_;
@@ -130,7 +130,7 @@
   // Callback for assistant to notify that it completes the filling.
   void BufferFillDone(int num_bytes);
 
-  scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner_;
+  scoped_refptr<base::SequencedTaskRunner> main_task_runner_;
   scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
 
   base::Lock lock_;
diff --git a/chromeos/services/assistant/platform/audio_output_provider_impl_unittest.cc b/chromeos/services/assistant/platform/audio_output_provider_impl_unittest.cc
index e8893ed2..7647c4e 100644
--- a/chromeos/services/assistant/platform/audio_output_provider_impl_unittest.cc
+++ b/chromeos/services/assistant/platform/audio_output_provider_impl_unittest.cc
@@ -102,7 +102,8 @@
   delegate.set_num_of_bytes_to_fill(200);
   delegate.Reset();
   auto owner = std::make_unique<AudioDeviceOwner>(
-      base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get());
+      base::SequencedTaskRunnerHandle::Get(),
+      base::SequencedTaskRunnerHandle::Get());
   // Upon start, it will start to fill the buffer.
   owner->StartOnMainThread(&delegate, nullptr, format);
   delegate.Wait();
diff --git a/chromeos/services/assistant/service.cc b/chromeos/services/assistant/service.cc
index 3d1240c..332d860 100644
--- a/chromeos/services/assistant/service.cc
+++ b/chromeos/services/assistant/service.cc
@@ -59,7 +59,7 @@
       platform_binding_(this),
       session_observer_binding_(this),
       token_refresh_timer_(std::make_unique<base::OneShotTimer>()),
-      main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+      main_task_runner_(base::SequencedTaskRunnerHandle::Get()),
       power_manager_observer_(this),
       network_connection_tracker_(network_connection_tracker),
       io_task_runner_(std::move(io_task_runner)),
@@ -184,11 +184,11 @@
         assistant_manager_service_->Start(
             access_token_.value(), assistant_state_.hotword_enabled().value(),
             base::BindOnce(
-                [](scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+                [](scoped_refptr<base::SequencedTaskRunner> task_runner,
                    base::OnceCallback<void()> callback) {
                   task_runner->PostTask(FROM_HERE, std::move(callback));
                 },
-                main_thread_task_runner_,
+                main_task_runner_,
                 base::BindOnce(&Service::FinalizeAssistantManagerService,
                                weak_ptr_factory_.GetWeakPtr())));
         DVLOG(1) << "Request Assistant start";
diff --git a/chromeos/services/assistant/service.h b/chromeos/services/assistant/service.h
index 302040e..0e59b1d 100644
--- a/chromeos/services/assistant/service.h
+++ b/chromeos/services/assistant/service.h
@@ -77,12 +77,13 @@
   }
 
   ash::AssistantStateBase* assistant_state() { return &assistant_state_; }
+  // net::URLRequestContextGetter requires a base::SingleThreadTaskRunner.
   scoped_refptr<base::SingleThreadTaskRunner> io_task_runner() {
     return io_task_runner_;
   }
 
-  scoped_refptr<base::SingleThreadTaskRunner> main_task_runner() {
-    return main_thread_task_runner_;
+  scoped_refptr<base::SequencedTaskRunner> main_task_runner() {
+    return main_task_runner_;
   }
 
   void RequestAccessToken();
@@ -162,7 +163,7 @@
   std::unique_ptr<AssistantManagerService> assistant_manager_service_;
   std::unique_ptr<base::OneShotTimer> token_refresh_timer_;
   int token_refresh_error_backoff_factor = 1;
-  scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
+  scoped_refptr<base::SequencedTaskRunner> main_task_runner_;
   ScopedObserver<chromeos::PowerManagerClient,
                  chromeos::PowerManagerClient::Observer>
       power_manager_observer_;
diff --git a/components/autofill/core/browser/autofill_external_delegate.cc b/components/autofill/core/browser/autofill_external_delegate.cc
index 11e75b03..becd578 100644
--- a/components/autofill/core/browser/autofill_external_delegate.cc
+++ b/components/autofill/core/browser/autofill_external_delegate.cc
@@ -248,7 +248,7 @@
   } else if (identifier == POPUP_ITEM_ID_CREDIT_CARD_SIGNIN_PROMO) {
     manager_->client()->ExecuteCommand(identifier);
   } else if (identifier == POPUP_ITEM_ID_SHOW_ACCOUNT_CARDS) {
-    // TODO(crbug.com/905052): Handle this event.
+    manager_->OnUserAcceptedCardsFromAccountOption();
   } else {
     if (identifier > 0)  // Denotes an Autofill suggestion.
       AutofillMetrics::LogAutofillSuggestionAcceptedIndex(position);
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index 296d7ef2..e270c64 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -315,6 +315,10 @@
   return personal_data_->ShouldShowCardsFromAccountOption();
 }
 
+void AutofillManager::OnUserAcceptedCardsFromAccountOption() {
+  personal_data_->OnUserAcceptedCardsFromAccountOption();
+}
+
 bool AutofillManager::ShouldParseForms(const std::vector<FormData>& forms,
                                        const base::TimeTicks timestamp) {
   bool enabled = IsAutofillEnabled();
diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h
index 763975c..28ffb3e4 100644
--- a/components/autofill/core/browser/autofill_manager.h
+++ b/components/autofill/core/browser/autofill_manager.h
@@ -94,8 +94,13 @@
   virtual bool ShouldShowCreditCardSigninPromo(const FormData& form,
                                                const FormFieldData& field);
 
+  // Handlers for the "Set Cards From Account" row. This row should be shown to
+  // users who have cards in their account and can use Sync Transport. Clicking
+  // the row records the user's consent to see these cards on this device, and
+  // refreshes the popup.
   virtual bool ShouldShowCardsFromAccountOption(const FormData& form,
                                                 const FormFieldData& field);
+  virtual void OnUserAcceptedCardsFromAccountOption();
 
   // Called from our external delegate so they cannot be private.
   virtual void FillOrPreviewForm(AutofillDriver::RendererFormDataAction action,
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc
index 003a02c2..d4140c5c 100644
--- a/components/autofill/core/browser/personal_data_manager.cc
+++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -2103,6 +2103,14 @@
       pref_service_, sync_service_->GetAuthenticatedAccountInfo().account_id);
 }
 
+void PersonalDataManager::OnUserAcceptedCardsFromAccountOption() {
+  DCHECK_EQ(AutofillSyncSigninState::kSignedInAndWalletSyncTransportEnabled,
+            GetSyncSigninState());
+  prefs::SetUserOptedInWalletSyncTransport(
+      pref_service_, sync_service_->GetAuthenticatedAccountInfo().account_id,
+      /*opted_in=*/true);
+}
+
 void PersonalDataManager::LogServerCardLinkClicked() const {
   AutofillMetrics::LogServerCardLinkClicked(GetSyncSigninState());
 }
diff --git a/components/autofill/core/browser/personal_data_manager.h b/components/autofill/core/browser/personal_data_manager.h
index 4feb3f8..ffbd7b28 100644
--- a/components/autofill/core/browser/personal_data_manager.h
+++ b/components/autofill/core/browser/personal_data_manager.h
@@ -383,6 +383,10 @@
   // account should be shown in the dropdown.
   bool ShouldShowCardsFromAccountOption() const;
 
+  // Triggered when a user selects the option to see cards from their account.
+  // Records the sync transport consent.
+  void OnUserAcceptedCardsFromAccountOption();
+
   // Logs the fact that the server card link was clicked including information
   // about the current sync state.
   void LogServerCardLinkClicked() const;
diff --git a/components/autofill/core/browser/ui/card_name_fix_flow_view_delegate_mobile.cc b/components/autofill/core/browser/ui/card_name_fix_flow_view_delegate_mobile.cc
index 286c7e7..61ef373 100644
--- a/components/autofill/core/browser/ui/card_name_fix_flow_view_delegate_mobile.cc
+++ b/components/autofill/core/browser/ui/card_name_fix_flow_view_delegate_mobile.cc
@@ -19,15 +19,17 @@
     const base::string16& inferred_cardholder_name,
     base::OnceCallback<void(const base::string16&)> upload_save_card_callback)
     : inferred_cardholder_name_(inferred_cardholder_name),
-      upload_save_card_callback_(std::move(upload_save_card_callback)) {
+      upload_save_card_callback_(std::move(upload_save_card_callback)),
+      shown_(false),
+      had_user_interaction_(false) {
   DCHECK(!upload_save_card_callback_.is_null());
   AutofillMetrics::LogSaveCardCardholderNamePrefilled(
       !inferred_cardholder_name_.empty());
 }
 
 CardNameFixFlowViewDelegateMobile::~CardNameFixFlowViewDelegateMobile() {
-  if (!had_user_interaction_)
-    LogUserAction(
+  if (shown_ && !had_user_interaction_)
+    AutofillMetrics::LogCardholderNameFixFlowPromptEvent(
         AutofillMetrics::
             CARDHOLDER_NAME_FIX_FLOW_PROMPT_CLOSED_WITHOUT_INTERACTION);
 }
@@ -52,24 +54,23 @@
 
 void CardNameFixFlowViewDelegateMobile::Accept(const base::string16& name) {
   std::move(upload_save_card_callback_).Run(name);
-  LogUserAction(AutofillMetrics::CARDHOLDER_NAME_FIX_FLOW_PROMPT_ACCEPTED);
+  AutofillMetrics::LogCardholderNameFixFlowPromptEvent(
+      AutofillMetrics::CARDHOLDER_NAME_FIX_FLOW_PROMPT_ACCEPTED);
+  had_user_interaction_ = true;
   AutofillMetrics::LogSaveCardCardholderNameWasEdited(
       inferred_cardholder_name_ != name);
 }
 
 void CardNameFixFlowViewDelegateMobile::Dismissed() {
-  LogUserAction(AutofillMetrics::CARDHOLDER_NAME_FIX_FLOW_PROMPT_DISMISSED);
+  AutofillMetrics::LogCardholderNameFixFlowPromptEvent(
+      AutofillMetrics::CARDHOLDER_NAME_FIX_FLOW_PROMPT_DISMISSED);
+  had_user_interaction_ = true;
 }
 
 void CardNameFixFlowViewDelegateMobile::Shown() {
-  LogUserAction(AutofillMetrics::CARDHOLDER_NAME_FIX_FLOW_PROMPT_SHOWN);
-}
-
-void CardNameFixFlowViewDelegateMobile::LogUserAction(
-    AutofillMetrics::CardholderNameFixFlowPromptEvent user_action) {
-  DCHECK(!had_user_interaction_);
-  AutofillMetrics::LogCardholderNameFixFlowPromptEvent(user_action);
-  had_user_interaction_ = true;
+  AutofillMetrics::LogCardholderNameFixFlowPromptEvent(
+      AutofillMetrics::CARDHOLDER_NAME_FIX_FLOW_PROMPT_SHOWN);
+  shown_ = true;
 }
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/ui/card_name_fix_flow_view_delegate_mobile.h b/components/autofill/core/browser/ui/card_name_fix_flow_view_delegate_mobile.h
index e769fda..dcad3d0 100644
--- a/components/autofill/core/browser/ui/card_name_fix_flow_view_delegate_mobile.h
+++ b/components/autofill/core/browser/ui/card_name_fix_flow_view_delegate_mobile.h
@@ -34,8 +34,6 @@
   void Shown();
 
  private:
-  void LogUserAction(
-      AutofillMetrics::CardholderNameFixFlowPromptEvent user_action);
 
   // Inferred cardholder name from Gaia account.
   base::string16 inferred_cardholder_name_;
@@ -44,6 +42,9 @@
   // fix flow.
   base::OnceCallback<void(const base::string16&)> upload_save_card_callback_;
 
+  // Whether the prompt was shown to the user.
+  bool shown_;
+
   // Did the user ever explicitly accept or dismiss this prompt?
   bool had_user_interaction_;
 
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java
index aefcaae0..95b34c0 100644
--- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java
+++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java
@@ -33,9 +33,10 @@
     static final int BACKGROUND_TASK_DOWNLOAD_RESUMPTION = 13;
     static final int BACKGROUND_TASK_FEED_REFRESH = 14;
     static final int BACKGROUND_TASK_COMPONENT_UPDATE = 15;
-    static final int BACKGROUND_TASK_EXPLORE_SITES_REFRESH = 16;
+    static final int BACKGROUND_TASK_DEPRECATED_EXPLORE_SITES_REFRESH = 16;
+    static final int BACKGROUND_TASK_EXPLORE_SITES_REFRESH = 17;
     // Keep this one at the end and increment appropriately when adding new tasks.
-    static final int BACKGROUND_TASK_COUNT = 17;
+    static final int BACKGROUND_TASK_COUNT = 18;
 
     static final String KEY_CACHED_UMA = "bts_cached_uma";
 
@@ -254,6 +255,8 @@
                 return BACKGROUND_TASK_FEED_REFRESH;
             case TaskIds.COMPONENT_UPDATE_JOB_ID:
                 return BACKGROUND_TASK_COMPONENT_UPDATE;
+            case TaskIds.DEPRECATED_EXPLORE_SITES_REFRESH_JOB_ID:
+                return BACKGROUND_TASK_DEPRECATED_EXPLORE_SITES_REFRESH;
             case TaskIds.EXPLORE_SITES_REFRESH_JOB_ID:
                 return BACKGROUND_TASK_EXPLORE_SITES_REFRESH;
             default:
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java
index 2c545ac..a885f1c 100644
--- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java
+++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/TaskIds.java
@@ -28,7 +28,8 @@
     public static final int DOWNLOAD_RESUMPTION_JOB_ID = 55;
     public static final int FEED_REFRESH_JOB_ID = 22;
     public static final int COMPONENT_UPDATE_JOB_ID = 2;
-    public static final int EXPLORE_SITES_REFRESH_JOB_ID = 100;
+    public static final int DEPRECATED_EXPLORE_SITES_REFRESH_JOB_ID = 100;
+    public static final int EXPLORE_SITES_REFRESH_JOB_ID = 101;
 
     private TaskIds() {}
 }
diff --git a/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java b/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java
index 515cec37..8a9dc167 100644
--- a/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java
+++ b/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java
@@ -90,7 +90,10 @@
         assertEquals(BackgroundTaskSchedulerUma.BACKGROUND_TASK_EXPLORE_SITES_REFRESH,
                 BackgroundTaskSchedulerUma.toUmaEnumValueFromTaskId(
                         TaskIds.EXPLORE_SITES_REFRESH_JOB_ID));
-        assertEquals(BackgroundTaskSchedulerUma.BACKGROUND_TASK_COUNT, 17);
+        assertEquals(BackgroundTaskSchedulerUma.BACKGROUND_TASK_DEPRECATED_EXPLORE_SITES_REFRESH,
+                BackgroundTaskSchedulerUma.toUmaEnumValueFromTaskId(
+                        TaskIds.DEPRECATED_EXPLORE_SITES_REFRESH_JOB_ID));
+        assertEquals(BackgroundTaskSchedulerUma.BACKGROUND_TASK_COUNT, 18);
     }
 
     @Test
diff --git a/components/crash/content/app/crashpad.cc b/components/crash/content/app/crashpad.cc
index a84dbb8..a04a4d84 100644
--- a/components/crash/content/app/crashpad.cc
+++ b/components/crash/content/app/crashpad.cc
@@ -114,7 +114,8 @@
     // "relauncher" is hard-coded because it's a Chrome --type, but this
     // component can't see Chrome's switches. This is only used for argument
     // sanitization.
-    DCHECK(browser_process || process_type == "relauncher");
+    DCHECK(browser_process || process_type == "relauncher" ||
+           process_type == "app_shim");
 #elif defined(OS_WIN)
     // "Chrome Installer" is the name historically used for installer binaries
     // as processed by the backend.
diff --git a/components/omnibox/browser/autocomplete_match.h b/components/omnibox/browser/autocomplete_match.h
index d82d2584..4d443e5 100644
--- a/components/omnibox/browser/autocomplete_match.h
+++ b/components/omnibox/browser/autocomplete_match.h
@@ -41,6 +41,9 @@
 const char kACMatchPropertySuggestionText[] = "match suggestion text";
 const char kACMatchPropertyContentsPrefix[] = "match contents prefix";
 const char kACMatchPropertyContentsStartIndex[] = "match contents start index";
+// A match attribute when a default match's score has been boosted with a higher
+// scoring non-default match.
+const char kACMatchPropertyScoreBoostedFrom[] = "score_boosted_from";
 
 // AutocompleteMatch ----------------------------------------------------------
 
diff --git a/components/omnibox/browser/autocomplete_result.cc b/components/omnibox/browser/autocomplete_result.cc
index ecc5e1e..1eb96847 100644
--- a/components/omnibox/browser/autocomplete_result.cc
+++ b/components/omnibox/browser/autocomplete_result.cc
@@ -41,10 +41,6 @@
   }
 };
 
-// A match attribute when a default match's score has been boosted
-// with a higher scoring non-default match.
-static const char kScoreBoostedFrom[] = "score_boosted_from";
-
 // static
 size_t AutocompleteResult::GetMaxMatches() {
   constexpr size_t kDefaultMaxAutocompleteMatches = 6;
@@ -417,42 +413,6 @@
              : GURL();
 }
 
-// static
-bool AutocompleteResult::IsBetterMatch(
-    AutocompleteMatch& first,
-    AutocompleteMatch& second,
-    metrics::OmniboxEventProto::PageClassification page_classification) {
-  // This object implements greater than.
-  CompareWithDemoteByType<AutocompleteMatch> compare_demote_by_type(
-      page_classification);
-
-  if (first.type == ACMatchType::SEARCH_SUGGEST_ENTITY &&
-      second.type != ACMatchType::SEARCH_SUGGEST_ENTITY) {
-    // If |first| is an entity suggestion and |second| isn't, |first| is
-    // considered better. If its type-adjusted relevance is lower, boost it to
-    // the value of |second|.
-    if (compare_demote_by_type(second, first)) {
-      first.RecordAdditionalInfo(kScoreBoostedFrom, second.relevance);
-      first.relevance = second.relevance;
-    }
-    return true;
-  } else if (first.type != ACMatchType::SEARCH_SUGGEST_ENTITY &&
-             second.type == ACMatchType::SEARCH_SUGGEST_ENTITY) {
-    // Likewise, if |second| is an entity suggestion and |first| isn't, first
-    // is not considered better, even if it has a higher type-adjusted
-    // relevance. If it does have a higher relevance, boost |second|.
-    if (compare_demote_by_type(first, second)) {
-      second.RecordAdditionalInfo(kScoreBoostedFrom, first.relevance);
-      second.relevance = first.relevance;
-    }
-    return false;
-  }
-
-  // In the case that both values are entity suggestions or both aren't, |first|
-  // is simply considered better if it's type-adjusted relevance is higher.
-  return compare_demote_by_type(first, second);
-}
-
 void AutocompleteResult::SortAndDedupMatches(
     metrics::OmniboxEventProto::PageClassification page_classification,
     ACMatches* matches) {
@@ -490,7 +450,8 @@
     }
     if (best_match != best_default && best_default != duplicate_matches.end()) {
       (*best_default)
-          ->RecordAdditionalInfo(kScoreBoostedFrom, (*best_default)->relevance);
+          ->RecordAdditionalInfo(kACMatchPropertyScoreBoostedFrom,
+                                 (*best_default)->relevance);
       (*best_default)->relevance = (*best_match)->relevance;
       best_match = best_default;
     }
@@ -552,6 +513,44 @@
 }
 
 // static
+bool AutocompleteResult::IsBetterMatch(
+    AutocompleteMatch& first,
+    AutocompleteMatch& second,
+    metrics::OmniboxEventProto::PageClassification page_classification) {
+  // This object implements greater than.
+  CompareWithDemoteByType<AutocompleteMatch> compare_demote_by_type(
+      page_classification);
+
+  if (first.type == ACMatchType::SEARCH_SUGGEST_ENTITY &&
+      second.type != ACMatchType::SEARCH_SUGGEST_ENTITY) {
+    // If |first| is an entity suggestion and |second| isn't, |first| is
+    // considered better. If its type-adjusted relevance is lower, boost it to
+    // the value of |second|.
+    if (compare_demote_by_type(second, first)) {
+      first.RecordAdditionalInfo(kACMatchPropertyScoreBoostedFrom,
+                                 first.relevance);
+      first.relevance = second.relevance;
+    }
+    return true;
+  } else if (first.type != ACMatchType::SEARCH_SUGGEST_ENTITY &&
+             second.type == ACMatchType::SEARCH_SUGGEST_ENTITY) {
+    // Likewise, if |second| is an entity suggestion and |first| isn't, first
+    // is not considered better, even if it has a higher type-adjusted
+    // relevance. If it does have a higher relevance, boost |second|.
+    if (compare_demote_by_type(first, second)) {
+      second.RecordAdditionalInfo(kACMatchPropertyScoreBoostedFrom,
+                                  second.relevance);
+      second.relevance = first.relevance;
+    }
+    return false;
+  }
+
+  // In the case that both values are entity suggestions or both aren't, |first|
+  // is simply considered better if it's type-adjusted relevance is higher.
+  return compare_demote_by_type(first, second);
+}
+
+// static
 bool AutocompleteResult::HasMatchByDestination(const AutocompleteMatch& match,
                                                const ACMatches& matches) {
   for (auto i(matches.begin()); i != matches.end(); ++i) {
diff --git a/components/omnibox/browser/autocomplete_result.h b/components/omnibox/browser/autocomplete_result.h
index 2fc0109..746cbee7 100644
--- a/components/omnibox/browser/autocomplete_result.h
+++ b/components/omnibox/browser/autocomplete_result.h
@@ -135,8 +135,22 @@
   size_t EstimateMemoryUsage() const;
 
  private:
-  friend class AutocompleteProviderTest;
   FRIEND_TEST_ALL_PREFIXES(AutocompleteResultTest, ConvertsOpenTabsCorrectly);
+  FRIEND_TEST_ALL_PREFIXES(AutocompleteResultTest,
+                           IsBetterMatchEntityWithHigherRelevance);
+  FRIEND_TEST_ALL_PREFIXES(AutocompleteResultTest,
+                           IsBetterMatchEntityWithLowerRelevance);
+  FRIEND_TEST_ALL_PREFIXES(AutocompleteResultTest,
+                           IsBetterMatchEntityWithEqualRelevance);
+  FRIEND_TEST_ALL_PREFIXES(AutocompleteResultTest,
+                           IsBetterMatchNonEntityWithHigherRelevance);
+  FRIEND_TEST_ALL_PREFIXES(AutocompleteResultTest,
+                           IsBetterMatchNonEntityWithLowerRelevance);
+  FRIEND_TEST_ALL_PREFIXES(AutocompleteResultTest,
+                           IsBetterMatchNonEntityWithEqualRelevance);
+  FRIEND_TEST_ALL_PREFIXES(AutocompleteResultTest, IsBetterMatchBothEntities);
+  FRIEND_TEST_ALL_PREFIXES(AutocompleteResultTest,
+                           IsBetterMatchBothNonEntities);
 
   typedef std::map<AutocompleteProvider*, ACMatches> ProviderToMatches;
 
diff --git a/components/omnibox/browser/autocomplete_result_unittest.cc b/components/omnibox/browser/autocomplete_result_unittest.cc
index 434d186..f3e0377b 100644
--- a/components/omnibox/browser/autocomplete_result_unittest.cc
+++ b/components/omnibox/browser/autocomplete_result_unittest.cc
@@ -1002,3 +1002,163 @@
   EXPECT_TRUE(result.match_at(1)->has_tab_match);
   EXPECT_FALSE(result.match_at(2)->has_tab_match);
 }
+
+namespace {
+
+void CheckRelevanceExpectations(const AutocompleteMatch& first,
+                                const AutocompleteMatch& second,
+                                int first_expected_relevance,
+                                int second_expected_relevance,
+                                const char* first_expected_boosted_from,
+                                const char* second_expected_boosted_from) {
+  EXPECT_EQ(first_expected_relevance, first.relevance);
+  EXPECT_EQ(second_expected_relevance, second.relevance);
+  EXPECT_EQ(std::string(first_expected_boosted_from),
+            first.GetAdditionalInfo(kACMatchPropertyScoreBoostedFrom));
+  EXPECT_EQ(std::string(second_expected_boosted_from),
+            second.GetAdditionalInfo(kACMatchPropertyScoreBoostedFrom));
+}
+
+}  // namespace
+
+TEST_F(AutocompleteResultTest, IsBetterMatchEntityWithHigherRelevance) {
+  AutocompleteMatch first;
+  first.type = AutocompleteMatchType::SEARCH_SUGGEST_ENTITY;
+  first.relevance = 1000;
+
+  AutocompleteMatch second;
+  second.type = AutocompleteMatchType::SEARCH_SUGGEST;
+  second.relevance = 600;
+
+  // Expect the entity suggestion to be better and its relevance unchanged.
+  // HOME_PAGE is used here because it doesn't trigger the special logic in
+  // OmniboxFieldTrial::GetDemotionsByType. There should otherwise be no
+  // demotions since the field trial params are cleared in the test setup.
+  EXPECT_TRUE(AutocompleteResult::IsBetterMatch(first, second,
+                                                OmniboxEventProto::HOME_PAGE));
+  CheckRelevanceExpectations(first, second, 1000, 600, "", "");
+}
+
+TEST_F(AutocompleteResultTest, IsBetterMatchEntityWithLowerRelevance) {
+  AutocompleteMatch first;
+  first.type = AutocompleteMatchType::SEARCH_SUGGEST_ENTITY;
+  first.relevance = 600;
+
+  AutocompleteMatch second;
+  second.type = AutocompleteMatchType::SEARCH_SUGGEST;
+  second.relevance = 1000;
+
+  // Expect the entity suggestion to be better and its relevance to have been
+  // boosted to that of the non-entity suggestion.
+  EXPECT_TRUE(AutocompleteResult::IsBetterMatch(first, second,
+                                                OmniboxEventProto::HOME_PAGE));
+  CheckRelevanceExpectations(first, second, 1000, 1000, "600", "");
+}
+
+TEST_F(AutocompleteResultTest, IsBetterMatchEntityWithEqualRelevance) {
+  AutocompleteMatch first;
+  first.type = AutocompleteMatchType::SEARCH_SUGGEST_ENTITY;
+  first.relevance = 1000;
+
+  AutocompleteMatch second;
+  second.type = AutocompleteMatchType::SEARCH_SUGGEST;
+  second.relevance = 1000;
+
+  // Expect the entity suggestion to be better and the relevance scores
+  // unchanged.
+  EXPECT_TRUE(AutocompleteResult::IsBetterMatch(first, second,
+                                                OmniboxEventProto::HOME_PAGE));
+  CheckRelevanceExpectations(first, second, 1000, 1000, "", "");
+}
+
+TEST_F(AutocompleteResultTest, IsBetterMatchNonEntityWithHigherRelevance) {
+  AutocompleteMatch first;
+  first.type = AutocompleteMatchType::SEARCH_SUGGEST;
+  first.relevance = 1000;
+
+  AutocompleteMatch second;
+  second.type = AutocompleteMatchType::SEARCH_SUGGEST_ENTITY;
+  second.relevance = 600;
+
+  // Expect the non-entity suggestion to *not* be better and the relevance of
+  // the entity suggestion to have been boosted.
+  EXPECT_FALSE(AutocompleteResult::IsBetterMatch(first, second,
+                                                 OmniboxEventProto::HOME_PAGE));
+  CheckRelevanceExpectations(first, second, 1000, 1000, "", "600");
+}
+
+TEST_F(AutocompleteResultTest, IsBetterMatchNonEntityWithLowerRelevance) {
+  AutocompleteMatch first;
+  first.type = AutocompleteMatchType::SEARCH_SUGGEST;
+  first.relevance = 600;
+
+  AutocompleteMatch second;
+  second.type = AutocompleteMatchType::SEARCH_SUGGEST_ENTITY;
+  second.relevance = 1000;
+
+  // Expect the non-entity suggestion to *not* be better and the relevance
+  // scores unchanged.
+  EXPECT_FALSE(AutocompleteResult::IsBetterMatch(first, second,
+                                                 OmniboxEventProto::HOME_PAGE));
+  CheckRelevanceExpectations(first, second, 600, 1000, "", "");
+}
+
+TEST_F(AutocompleteResultTest, IsBetterMatchNonEntityWithEqualRelevance) {
+  AutocompleteMatch first;
+  first.type = AutocompleteMatchType::SEARCH_SUGGEST;
+  first.relevance = 1000;
+
+  AutocompleteMatch second;
+  second.type = AutocompleteMatchType::SEARCH_SUGGEST_ENTITY;
+  second.relevance = 1000;
+
+  // Expect the non-entity suggestion to *not* be better and the relevance
+  // scores unchanged.
+  EXPECT_FALSE(AutocompleteResult::IsBetterMatch(first, second,
+                                                 OmniboxEventProto::HOME_PAGE));
+  CheckRelevanceExpectations(first, second, 1000, 1000, "", "");
+}
+
+TEST_F(AutocompleteResultTest, IsBetterMatchBothEntities) {
+  AutocompleteMatch first;
+  first.type = AutocompleteMatchType::SEARCH_SUGGEST_ENTITY;
+  first.relevance = 1000;
+
+  AutocompleteMatch second;
+  second.type = AutocompleteMatchType::SEARCH_SUGGEST_ENTITY;
+  second.relevance = 600;
+
+  // Expect the first suggestion to be better since its relevance is higher and
+  // the relevance scores unchanged.
+  EXPECT_TRUE(AutocompleteResult::IsBetterMatch(first, second,
+                                                OmniboxEventProto::HOME_PAGE));
+  CheckRelevanceExpectations(first, second, 1000, 600, "", "");
+
+  // Expect the reversed condition to be false and the relevance scores
+  // unchanged.
+  EXPECT_FALSE(AutocompleteResult::IsBetterMatch(second, first,
+                                                 OmniboxEventProto::HOME_PAGE));
+  CheckRelevanceExpectations(first, second, 1000, 600, "", "");
+}
+
+TEST_F(AutocompleteResultTest, IsBetterMatchBothNonEntities) {
+  AutocompleteMatch first;
+  first.type = AutocompleteMatchType::SEARCH_SUGGEST;
+  first.relevance = 1000;
+
+  AutocompleteMatch second;
+  second.type = AutocompleteMatchType::SEARCH_SUGGEST;
+  second.relevance = 600;
+
+  // Expect the first suggestion to be better since its relevance is higher and
+  // the relevance scores unchanged.
+  EXPECT_TRUE(AutocompleteResult::IsBetterMatch(first, second,
+                                                OmniboxEventProto::HOME_PAGE));
+  CheckRelevanceExpectations(first, second, 1000, 600, "", "");
+
+  // Expect the reversed condition to be false and the relevance scores
+  // unchanged.
+  EXPECT_FALSE(AutocompleteResult::IsBetterMatch(second, first,
+                                                 OmniboxEventProto::HOME_PAGE));
+  CheckRelevanceExpectations(first, second, 1000, 600, "", "");
+}
diff --git a/components/plugins/renderer/webview_plugin.cc b/components/plugins/renderer/webview_plugin.cc
index dbb8eec..62cd569 100644
--- a/components/plugins/renderer/webview_plugin.cc
+++ b/components/plugins/renderer/webview_plugin.cc
@@ -322,7 +322,7 @@
   // Resizes must be self-contained: any lifecycle updating must
   // be triggerd from within the WebView or this WebViewPlugin.
   // This is because this WebViewPlugin is contained in another
-  // Web View which may be in the middle of updating its lifecycle,
+  // WebView which may be in the middle of updating its lifecycle,
   // but after layout is done, and it is illegal to dirty earlier
   // lifecycle stages during later ones.
   if (plugin_->is_resizing_)
@@ -330,6 +330,7 @@
   if (plugin_->container_) {
     // This should never happen; see also crbug.com/545039 for context.
     DCHECK(!plugin_->is_painting_);
+    // This goes to compositor of the containing frame.
     plugin_->container_->ScheduleAnimation();
   }
 }
diff --git a/components/printing/test/print_render_frame_helper_browsertest.cc b/components/printing/test/print_render_frame_helper_browsertest.cc
index f2b88d1b..8a7de67 100644
--- a/components/printing/test/print_render_frame_helper_browsertest.cc
+++ b/components/printing/test/print_render_frame_helper_browsertest.cc
@@ -51,6 +51,18 @@
 // A simple web page.
 const char kHelloWorldHTML[] = "<body><p>Hello World!</p></body>";
 
+// Web page used for testing onbeforeprint/onafterprint.
+const char kBeforeAfterPrintHtml[] =
+    "<body>"
+    "<script>"
+    "var beforePrintCount = 0;"
+    "var afterPrintCount = 0;"
+    "window.onbeforeprint = () => { ++beforePrintCount; };"
+    "window.onafterprint = () => { ++afterPrintCount; };"
+    "</script>"
+    "<button id=\"print\" onclick=\"window.print();\">Hello World!</button>"
+    "</body>";
+
 #if !defined(OS_CHROMEOS)
 // A simple webpage with a button to print itself with.
 const char kPrintOnUserAction[] =
@@ -147,8 +159,8 @@
 
 class PrintRenderFrameHelperTestBase : public content::RenderViewTest {
  public:
-  PrintRenderFrameHelperTestBase() : print_render_thread_(nullptr) {}
-  ~PrintRenderFrameHelperTestBase() override {}
+  PrintRenderFrameHelperTestBase() = default;
+  ~PrintRenderFrameHelperTestBase() override = default;
 
  protected:
   // content::RenderViewTest:
@@ -157,8 +169,9 @@
   }
 
   void SetUp() override {
-    print_render_thread_ = new PrintMockRenderThread();
-    render_thread_.reset(print_render_thread_);
+    render_thread_ = std::make_unique<PrintMockRenderThread>();
+    print_render_thread_ =
+        static_cast<PrintMockRenderThread*>(render_thread_.get());
 
     content::RenderViewTest::SetUp();
   }
@@ -255,6 +268,10 @@
     run_loop.Run();
     render_thread_->sink().RemoveFilter(&filter);
   }
+
+  void OnClosePrintPreviewDialog() {
+    GetPrintRenderFrameHelper()->OnClosePrintPreviewDialog();
+  }
 #endif  // BUILDFLAG(ENABLE_PRINT_PREVIEW)
 
   PrintRenderFrameHelper* GetPrintRenderFrameHelper() {
@@ -272,10 +289,58 @@
         content::RenderFrame::FromWebFrame(frame->ToWebLocalFrame()));
   }
 
-  // Naked pointer as ownership is with content::RenderViewTest::render_thread_.
-  PrintMockRenderThread* print_render_thread_;
+  void ClickMouseButton(const gfx::Rect& bounds) {
+    EXPECT_FALSE(bounds.IsEmpty());
+
+    blink::WebMouseEvent mouse_event(
+        blink::WebInputEvent::kMouseDown, blink::WebInputEvent::kNoModifiers,
+        blink::WebInputEvent::GetStaticTimeStampForTests());
+    mouse_event.button = blink::WebMouseEvent::Button::kLeft;
+    mouse_event.SetPositionInWidget(bounds.CenterPoint().x(),
+                                    bounds.CenterPoint().y());
+    mouse_event.click_count = 1;
+    SendWebMouseEvent(mouse_event);
+    mouse_event.SetType(blink::WebInputEvent::kMouseUp);
+    SendWebMouseEvent(mouse_event);
+  }
+
+  void ExpectNoBeforeNoAfterPrintEvent() {
+    int result;
+    ASSERT_TRUE(ExecuteJavaScriptAndReturnIntValue(
+        base::ASCIIToUTF16("beforePrintCount"), &result));
+    EXPECT_EQ(0, result) << "beforeprint event should not be dispatched.";
+    ASSERT_TRUE(ExecuteJavaScriptAndReturnIntValue(
+        base::ASCIIToUTF16("afterPrintCount"), &result));
+    EXPECT_EQ(0, result) << "afterprint event should not be dispatched.";
+  }
+
+  void ExpectOneBeforeNoAfterPrintEvent() {
+    int result;
+    ASSERT_TRUE(ExecuteJavaScriptAndReturnIntValue(
+        base::ASCIIToUTF16("beforePrintCount"), &result));
+    EXPECT_EQ(1, result) << "beforeprint event should be dispatched once.";
+    ASSERT_TRUE(ExecuteJavaScriptAndReturnIntValue(
+        base::ASCIIToUTF16("afterPrintCount"), &result));
+    EXPECT_EQ(0, result) << "afterprint event should not be dispatched.";
+  }
+
+  void ExpectOneBeforeOneAfterPrintEvent() {
+    int result;
+    ASSERT_TRUE(ExecuteJavaScriptAndReturnIntValue(
+        base::ASCIIToUTF16("beforePrintCount"), &result));
+    EXPECT_EQ(1, result) << "beforeprint event should be dispatched once.";
+    ASSERT_TRUE(ExecuteJavaScriptAndReturnIntValue(
+        base::ASCIIToUTF16("afterPrintCount"), &result));
+    EXPECT_EQ(1, result) << "afterprint event should be dispatched once.";
+  }
+
+  PrintMockRenderThread* print_render_thread() { return print_render_thread_; }
 
  private:
+  // Naked pointer as ownership is with
+  // |content::RenderViewTest::render_thread_|.
+  PrintMockRenderThread* print_render_thread_ = nullptr;
+
   DISALLOW_COPY_AND_ASSIGN(PrintRenderFrameHelperTestBase);
 };
 
@@ -289,8 +354,8 @@
 
 class MAYBE_PrintRenderFrameHelperTest : public PrintRenderFrameHelperTestBase {
  public:
-  MAYBE_PrintRenderFrameHelperTest() {}
-  ~MAYBE_PrintRenderFrameHelperTest() override {}
+  MAYBE_PrintRenderFrameHelperTest() = default;
+  ~MAYBE_PrintRenderFrameHelperTest() override = default;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MAYBE_PrintRenderFrameHelperTest);
@@ -302,7 +367,7 @@
 // frequently.
 TEST_F(MAYBE_PrintRenderFrameHelperTest, BlockScriptInitiatedPrinting) {
   // Pretend user will cancel printing.
-  print_render_thread_->set_print_dialog_user_response(false);
+  print_render_thread()->set_print_dialog_user_response(false);
   // Try to print with window.print() a few times.
   PrintWithJavaScript();
   PrintWithJavaScript();
@@ -310,13 +375,13 @@
   VerifyPagesPrinted(false);
 
   // Pretend user will print. (but printing is blocked.)
-  print_render_thread_->set_print_dialog_user_response(true);
+  print_render_thread()->set_print_dialog_user_response(true);
   PrintWithJavaScript();
   VerifyPagesPrinted(false);
 
   // Unblock script initiated printing and verify printing works.
   GetPrintRenderFrameHelper()->scripting_throttler_.Reset();
-  print_render_thread_->printer()->ResetPrinter();
+  print_render_thread()->printer()->ResetPrinter();
   PrintWithJavaScript();
   VerifyPageCount(1);
   VerifyPagesPrinted(true);
@@ -326,7 +391,7 @@
 // initiated.
 TEST_F(MAYBE_PrintRenderFrameHelperTest, AllowUserOriginatedPrinting) {
   // Pretend user will cancel printing.
-  print_render_thread_->set_print_dialog_user_response(false);
+  print_render_thread()->set_print_dialog_user_response(false);
   // Try to print with window.print() a few times.
   PrintWithJavaScript();
   PrintWithJavaScript();
@@ -334,28 +399,18 @@
   VerifyPagesPrinted(false);
 
   // Pretend user will print. (but printing is blocked.)
-  print_render_thread_->set_print_dialog_user_response(true);
+  print_render_thread()->set_print_dialog_user_response(true);
   PrintWithJavaScript();
   VerifyPagesPrinted(false);
 
   // Try again as if user initiated, without resetting the print count.
-  print_render_thread_->printer()->ResetPrinter();
+  print_render_thread()->printer()->ResetPrinter();
   LoadHTML(kPrintOnUserAction);
   gfx::Size new_size(200, 100);
   Resize(new_size, false);
 
   gfx::Rect bounds = GetElementBounds("print");
-  EXPECT_FALSE(bounds.IsEmpty());
-  blink::WebMouseEvent mouse_event(
-      blink::WebInputEvent::kMouseDown, blink::WebInputEvent::kNoModifiers,
-      blink::WebInputEvent::GetStaticTimeStampForTests());
-  mouse_event.button = blink::WebMouseEvent::Button::kLeft;
-  mouse_event.SetPositionInWidget(bounds.CenterPoint().x(),
-                                  bounds.CenterPoint().y());
-  mouse_event.click_count = 1;
-  SendWebMouseEvent(mouse_event);
-  mouse_event.SetType(blink::WebInputEvent::kMouseUp);
-  SendWebMouseEvent(mouse_event);
+  ClickMouseButton(bounds);
   base::RunLoop().RunUntilIdle();
 
   VerifyPageCount(1);
@@ -369,6 +424,18 @@
   VerifyPageCount(1);
   VerifyPagesPrinted(true);
 }
+
+// Regression test for https://crbug.com/912966
+TEST_F(MAYBE_PrintRenderFrameHelperTest, WindowPrintBeforePrintAfterPrint) {
+  LoadHTML(kBeforeAfterPrintHtml);
+  ExpectNoBeforeNoAfterPrintEvent();
+
+  PrintWithJavaScript();
+
+  VerifyPageCount(1);
+  VerifyPagesPrinted(true);
+  ExpectOneBeforeOneAfterPrintEvent();
+}
 #endif  // !BUILDFLAG(ENABLE_PRINT_PREVIEW)
 
 // Tests that printing pages work and sending and receiving messages through
@@ -382,31 +449,18 @@
 }
 
 TEST_F(MAYBE_PrintRenderFrameHelperTest, BasicBeforePrintAfterPrint) {
-  const char kHtml[] =
-      "<body>Hello"
-      "<script>"
-      "var beforePrintCount = 0;"
-      "var afterPrintCount = 0;"
-      "window.onbeforeprint = () => { ++beforePrintCount; };"
-      "window.onafterprint = () => { ++afterPrintCount; };"
-      "</script>"
-      "</body>";
+  LoadHTML(kBeforeAfterPrintHtml);
+  ExpectNoBeforeNoAfterPrintEvent();
 
-  LoadHTML(kHtml);
   OnPrintPages();
 
+  VerifyPageCount(1);
   VerifyPagesPrinted(true);
-  int result;
-  ASSERT_TRUE(ExecuteJavaScriptAndReturnIntValue(
-      base::ASCIIToUTF16("beforePrintCount"), &result));
-  EXPECT_EQ(1, result) << "beforeprint event should be dispatched once.";
-  ASSERT_TRUE(ExecuteJavaScriptAndReturnIntValue(
-      base::ASCIIToUTF16("afterPrintCount"), &result));
-  EXPECT_EQ(1, result) << "afterprint event should be dispatched once.";
+  ExpectOneBeforeOneAfterPrintEvent();
 }
 
 TEST_F(MAYBE_PrintRenderFrameHelperTest, BasicBeforePrintAfterPrintSubFrame) {
-  const char kCloseOnBeforeHtml[] =
+  static const char kCloseOnBeforeHtml[] =
       "<body>Hello"
       "<iframe name=sub srcdoc='<script>"
       "window.onbeforeprint = () => { window.frameElement.remove(); };"
@@ -418,7 +472,7 @@
   EXPECT_EQ(nullptr, GetMainFrame()->FindFrameByName("sub"));
   VerifyPagesPrinted(false);
 
-  const char kCloseOnAfterHtml[] =
+  static const char kCloseOnAfterHtml[] =
       "<body>Hello"
       "<iframe name=sub srcdoc='<script>"
       "window.onafterprint = () => { window.frameElement.remove(); };"
@@ -438,7 +492,7 @@
 // for us anyway.
 TEST_F(MAYBE_PrintRenderFrameHelperTest, PrintWithIframe) {
   // Document that populates an iframe.
-  const char html[] =
+  static const char html[] =
       "<html><body>Lorem Ipsum:"
       "<iframe name=\"sub1\" id=\"sub1\"></iframe><script>"
       "  document.write(frames['sub1'].name);"
@@ -464,7 +518,7 @@
   VerifyPagesPrinted(true);
 
   // Verify output through MockPrinter.
-  const MockPrinter* printer(print_render_thread_->printer());
+  const MockPrinter* printer(print_render_thread()->printer());
   ASSERT_EQ(1, printer->GetPrintedPages());
   const Image& image1(printer->GetPrintedPage(0)->image());
 
@@ -521,7 +575,7 @@
 TEST_F(MAYBE_PrintRenderFrameHelperTest, PrintLayoutTest) {
   bool baseline = false;
 
-  EXPECT_TRUE(print_render_thread_->printer());
+  EXPECT_TRUE(print_render_thread()->printer());
   for (size_t i = 0; i < base::size(kTestPages); ++i) {
     // Load an HTML page and print it.
     LoadHTML(kTestPages[i].page);
@@ -534,12 +588,12 @@
     // has been already finished.
     // So, we can start checking the output pages of this printing job.
     // Retrieve the number of pages actually printed.
-    size_t pages = print_render_thread_->printer()->GetPrintedPages();
+    size_t pages = print_render_thread()->printer()->GetPrintedPages();
     EXPECT_EQ(kTestPages[i].printed_pages, pages);
 
     // Retrieve the width and height of the output page.
-    int width = print_render_thread_->printer()->GetWidth(0);
-    int height = print_render_thread_->printer()->GetHeight(0);
+    int width = print_render_thread()->printer()->GetWidth(0);
+    int height = print_render_thread()->printer()->GetHeight(0);
 
     // Check with margin for error.  This has been failing with a one pixel
     // offset on our buildbot.
@@ -553,7 +607,7 @@
     // compare it with the expected result.
     std::string bitmap_actual;
     EXPECT_TRUE(
-        print_render_thread_->printer()->GetBitmapChecksum(0, &bitmap_actual));
+        print_render_thread()->printer()->GetBitmapChecksum(0, &bitmap_actual));
     if (kTestPages[i].checksum)
       EXPECT_EQ(kTestPages[i].checksum, bitmap_actual);
 
@@ -562,11 +616,11 @@
       // create base-line results.
       base::FilePath source_path;
       base::CreateTemporaryFile(&source_path);
-      print_render_thread_->printer()->SaveSource(0, source_path);
+      print_render_thread()->printer()->SaveSource(0, source_path);
 
       base::FilePath bitmap_path;
       base::CreateTemporaryFile(&bitmap_path);
-      print_render_thread_->printer()->SaveBitmap(0, bitmap_path);
+      print_render_thread()->printer()->SaveBitmap(0, bitmap_path);
     }
   }
 }
@@ -589,8 +643,8 @@
 class MAYBE_PrintRenderFrameHelperPreviewTest
     : public PrintRenderFrameHelperTestBase {
  public:
-  MAYBE_PrintRenderFrameHelperPreviewTest() {}
-  ~MAYBE_PrintRenderFrameHelperPreviewTest() override {}
+  MAYBE_PrintRenderFrameHelperPreviewTest() = default;
+  ~MAYBE_PrintRenderFrameHelperPreviewTest() override = default;
 
  protected:
   void VerifyPrintPreviewCancelled(bool expect_cancel) {
@@ -640,7 +694,7 @@
   void VerifyDidPreviewPage(bool expect_generated, int page_number) {
     bool msg_found = false;
     uint32_t data_size = 0;
-    for (const auto& preview : print_render_thread_->print_preview_pages()) {
+    for (const auto& preview : print_render_thread()->print_preview_pages()) {
       if (preview.first == page_number) {
         msg_found = true;
         data_size = preview.second;
@@ -701,17 +755,7 @@
   Resize(new_size, false);
 
   gfx::Rect bounds = GetElementBounds("print");
-  EXPECT_FALSE(bounds.IsEmpty());
-  blink::WebMouseEvent mouse_event(
-      blink::WebInputEvent::kMouseDown, blink::WebInputEvent::kNoModifiers,
-      blink::WebInputEvent::GetStaticTimeStampForTests());
-  mouse_event.button = blink::WebMouseEvent::Button::kLeft;
-  mouse_event.SetPositionInWidget(bounds.CenterPoint().x(),
-                                  bounds.CenterPoint().y());
-  mouse_event.click_count = 1;
-  SendWebMouseEvent(mouse_event);
-  mouse_event.SetType(blink::WebInputEvent::kMouseUp);
-  SendWebMouseEvent(mouse_event);
+  ClickMouseButton(bounds);
 
   VerifyPreviewRequest(true);
 }
@@ -726,7 +770,7 @@
   CreatePrintSettingsDictionary(&dict);
   OnPrintPreview(dict);
 
-  EXPECT_EQ(0, print_render_thread_->print_preview_pages_remaining());
+  EXPECT_EQ(0, print_render_thread()->print_preview_pages_remaining());
   VerifyDidPreviewPage(true, 0);
   VerifyPreviewPageCount(1);
   VerifyDefaultPageLayout(540, 720, 36, 36, 36, 36, false);
@@ -739,7 +783,7 @@
 TEST_F(MAYBE_PrintRenderFrameHelperPreviewTest,
        PrintPreviewHTMLWithPageMarginsCss) {
   // A simple web page with print margins css.
-  const char kHTMLWithPageMarginsCss[] =
+  static const char kHTMLWithPageMarginsCss[] =
       "<html><head><style>"
       "@media print {"
       "  @page {"
@@ -758,7 +802,7 @@
   dict.SetInteger(kSettingMarginsType, DEFAULT_MARGINS);
   OnPrintPreview(dict);
 
-  EXPECT_EQ(0, print_render_thread_->print_preview_pages_remaining());
+  EXPECT_EQ(0, print_render_thread()->print_preview_pages_remaining());
   VerifyDefaultPageLayout(519, 432, 216, 144, 21, 72, false);
   VerifyDidPreviewPage(true, 0);
   VerifyPreviewPageCount(1);
@@ -781,7 +825,7 @@
   dict.SetInteger(kSettingMarginsType, NO_MARGINS);
   OnPrintPreview(dict);
 
-  EXPECT_EQ(0, print_render_thread_->print_preview_pages_remaining());
+  EXPECT_EQ(0, print_render_thread()->print_preview_pages_remaining());
   VerifyDefaultPageLayout(612, 792, 0, 0, 0, 0, true);
   VerifyDidPreviewPage(true, 0);
   VerifyPreviewPageCount(1);
@@ -804,7 +848,7 @@
   dict.SetInteger(kSettingMarginsType, PRINTABLE_AREA_MARGINS);
   OnPrintPreview(dict);
 
-  EXPECT_EQ(0, print_render_thread_->print_preview_pages_remaining());
+  EXPECT_EQ(0, print_render_thread()->print_preview_pages_remaining());
   // Since PRINT_TO_PDF is selected, pdf page size is equal to print media page
   // size.
   VerifyDefaultPageLayout(252, 252, 18, 18, 18, 18, true);
@@ -819,7 +863,7 @@
 TEST_F(MAYBE_PrintRenderFrameHelperPreviewTest,
        PreviewLayoutTriggeredByResize) {
   // A simple web page with print margins css.
-  const char kHTMLWithPageCss[] =
+  static const char kHTMLWithPageCss[] =
       "<!DOCTYPE html>"
       "<style>"
       "@media (min-width: 540px) {"
@@ -929,7 +973,7 @@
   dict.SetInteger(kSettingMarginsType, DEFAULT_MARGINS);
   OnPrintPreview(dict);
 
-  EXPECT_EQ(0, print_render_thread_->print_preview_pages_remaining());
+  EXPECT_EQ(0, print_render_thread()->print_preview_pages_remaining());
   VerifyDidPreviewPage(true, 0);
   VerifyDidPreviewPage(true, 1);
   VerifyPreviewPageCount(2);
@@ -944,7 +988,7 @@
 TEST_F(MAYBE_PrintRenderFrameHelperPreviewTest,
        PrintToPDFSelectedHonorPageMarginsCss) {
   // A simple web page with print margins css.
-  const char kHTMLWithPageCss[] =
+  static const char kHTMLWithPageCss[] =
       "<html><head><style>"
       "@media print {"
       "  @page {"
@@ -964,7 +1008,7 @@
   dict.SetInteger(kSettingMarginsType, DEFAULT_MARGINS);
   OnPrintPreview(dict);
 
-  EXPECT_EQ(0, print_render_thread_->print_preview_pages_remaining());
+  EXPECT_EQ(0, print_render_thread()->print_preview_pages_remaining());
   // Since PRINT_TO_PDF is selected, pdf page size is equal to print media page
   // size.
   VerifyDefaultPageLayout(915, 648, 216, 144, 21, 72, true);
@@ -988,7 +1032,7 @@
   dict.SetInteger(kSettingMarginsType, DEFAULT_MARGINS);
   OnPrintPreview(dict);
 
-  EXPECT_EQ(0, print_render_thread_->print_preview_pages_remaining());
+  EXPECT_EQ(0, print_render_thread()->print_preview_pages_remaining());
   VerifyDefaultPageLayout(216, 216, 288, 288, 198, 198, true);
   VerifyDidPreviewPage(true, 0);
   VerifyPreviewPageCount(1);
@@ -1002,7 +1046,7 @@
 // fit the page size.
 TEST_F(MAYBE_PrintRenderFrameHelperPreviewTest, PrintPreviewShrinkToFitPage) {
   // A simple web page with print margins css.
-  const char kHTMLWithPageCss[] =
+  static const char kHTMLWithPageCss[] =
       "<html><head><style>"
       "@media print {"
       "  @page {"
@@ -1021,7 +1065,7 @@
   dict.SetInteger(kSettingMarginsType, DEFAULT_MARGINS);
   OnPrintPreview(dict);
 
-  EXPECT_EQ(0, print_render_thread_->print_preview_pages_remaining());
+  EXPECT_EQ(0, print_render_thread()->print_preview_pages_remaining());
   VerifyDefaultPageLayout(571, 652, 69, 71, 20, 21, true);
   VerifyDidPreviewPage(true, 0);
   VerifyPreviewPageCount(1);
@@ -1044,7 +1088,7 @@
   dict.SetInteger(kSettingMarginsType, NO_MARGINS);
   OnPrintPreview(dict);
 
-  EXPECT_EQ(0, print_render_thread_->print_preview_pages_remaining());
+  EXPECT_EQ(0, print_render_thread()->print_preview_pages_remaining());
   VerifyDefaultPageLayout(792, 612, 0, 0, 0, 0, true);
   VerifyDidPreviewPage(true, 0);
   VerifyPreviewPageCount(1);
@@ -1067,7 +1111,7 @@
   dict.SetInteger(kSettingMarginsType, CUSTOM_MARGINS);
   OnPrintPreview(dict);
 
-  EXPECT_EQ(0, print_render_thread_->print_preview_pages_remaining());
+  EXPECT_EQ(0, print_render_thread()->print_preview_pages_remaining());
   VerifyDefaultPageLayout(748, 568, 21, 23, 21, 23, true);
   VerifyDidPreviewPage(true, 0);
   VerifyPreviewPageCount(1);
@@ -1086,7 +1130,7 @@
 
   OnPrintPreview(dict);
 
-  EXPECT_EQ(0, print_render_thread_->print_preview_pages_remaining());
+  EXPECT_EQ(0, print_render_thread()->print_preview_pages_remaining());
   VerifyDidPreviewPage(true, 0);
   VerifyDidPreviewPage(true, 1);
   VerifyDidPreviewPage(true, 2);
@@ -1121,7 +1165,7 @@
   // generated, the print_preview_pages_remaining() result is 1.
   // TODO(thestig): Fix this on the browser side to accept the number of actual
   // pages generated instead, or to take both page counts.
-  EXPECT_EQ(1, print_render_thread_->print_preview_pages_remaining());
+  EXPECT_EQ(1, print_render_thread()->print_preview_pages_remaining());
   VerifyDidPreviewPage(false, 0);
   VerifyDidPreviewPage(true, 1);
   VerifyDidPreviewPage(true, 2);
@@ -1146,7 +1190,7 @@
 
   OnPrintPreview(dict);
 
-  EXPECT_EQ(0, print_render_thread_->print_preview_pages_remaining());
+  EXPECT_EQ(0, print_render_thread()->print_preview_pages_remaining());
   VerifyDidPreviewPage(true, 0);
   VerifyPreviewPageCount(1);
   VerifyPrintPreviewCancelled(false);
@@ -1169,7 +1213,7 @@
 
   OnPrintPreview(dict);
 
-  EXPECT_EQ(0, print_render_thread_->print_preview_pages_remaining());
+  EXPECT_EQ(0, print_render_thread()->print_preview_pages_remaining());
   VerifyDidPreviewPage(true, 0);
   VerifyPreviewPageCount(2);
   VerifyPrintPreviewCancelled(false);
@@ -1187,7 +1231,7 @@
   base::DictionaryValue empty_dict;
   OnPrintPreview(empty_dict);
 
-  EXPECT_EQ(0, print_render_thread_->print_preview_pages_remaining());
+  EXPECT_EQ(0, print_render_thread()->print_preview_pages_remaining());
   VerifyPrintPreviewCancelled(false);
   VerifyPrintPreviewFailed(true);
   VerifyPrintPreviewGenerated(false);
@@ -1199,13 +1243,14 @@
   LoadHTML(kLongPageHTML);
 
   const int kCancelPage = 3;
-  print_render_thread_->set_print_preview_cancel_page_number(kCancelPage);
+  print_render_thread()->set_print_preview_cancel_page_number(kCancelPage);
   // Fill in some dummy values.
   base::DictionaryValue dict;
   CreatePrintSettingsDictionary(&dict);
   OnPrintPreview(dict);
 
-  EXPECT_EQ(kCancelPage, print_render_thread_->print_preview_pages_remaining());
+  EXPECT_EQ(kCancelPage,
+            print_render_thread()->print_preview_pages_remaining());
   VerifyPrintPreviewCancelled(true);
   VerifyPrintPreviewFailed(false);
   VerifyPrintPreviewGenerated(false);
@@ -1219,7 +1264,7 @@
   LoadHTML(kPrintPreviewHTML);
 
   // Set mock printer to provide invalid settings.
-  print_render_thread_->printer()->UseInvalidSettings();
+  print_render_thread()->printer()->UseInvalidSettings();
 
   // Fill in some dummy values.
   base::DictionaryValue dict;
@@ -1228,7 +1273,7 @@
 
   // We should have received invalid printer settings from |printer_|.
   VerifyPrintPreviewInvalidPrinterSettings(true);
-  EXPECT_EQ(0, print_render_thread_->print_preview_pages_remaining());
+  EXPECT_EQ(0, print_render_thread()->print_preview_pages_remaining());
 
   // It should receive the invalid printer settings message only.
   VerifyPrintPreviewFailed(false);
@@ -1241,14 +1286,14 @@
        OnPrintPreviewUsingInvalidPageSize) {
   LoadHTML(kPrintPreviewHTML);
 
-  print_render_thread_->printer()->UseInvalidPageSize();
+  print_render_thread()->printer()->UseInvalidPageSize();
 
   base::DictionaryValue dict;
   CreatePrintSettingsDictionary(&dict);
   OnPrintPreview(dict);
 
   VerifyPrintPreviewInvalidPrinterSettings(true);
-  EXPECT_EQ(0, print_render_thread_->print_preview_pages_remaining());
+  EXPECT_EQ(0, print_render_thread()->print_preview_pages_remaining());
 
   // It should receive the invalid printer settings message only.
   VerifyPrintPreviewFailed(false);
@@ -1261,20 +1306,60 @@
        OnPrintPreviewUsingInvalidContentSize) {
   LoadHTML(kPrintPreviewHTML);
 
-  print_render_thread_->printer()->UseInvalidContentSize();
+  print_render_thread()->printer()->UseInvalidContentSize();
 
   base::DictionaryValue dict;
   CreatePrintSettingsDictionary(&dict);
   OnPrintPreview(dict);
 
   VerifyPrintPreviewInvalidPrinterSettings(true);
-  EXPECT_EQ(0, print_render_thread_->print_preview_pages_remaining());
+  EXPECT_EQ(0, print_render_thread()->print_preview_pages_remaining());
 
   // It should receive the invalid printer settings message only.
   VerifyPrintPreviewFailed(false);
   VerifyPrintPreviewGenerated(false);
 }
 
+TEST_F(MAYBE_PrintRenderFrameHelperPreviewTest, BasicBeforePrintAfterPrint) {
+  LoadHTML(kBeforeAfterPrintHtml);
+  ExpectNoBeforeNoAfterPrintEvent();
+
+  base::DictionaryValue dict;
+  CreatePrintSettingsDictionary(&dict);
+  OnPrintPreview(dict);
+
+  EXPECT_EQ(0, print_render_thread()->print_preview_pages_remaining());
+  VerifyDidPreviewPage(true, 0);
+  VerifyPreviewPageCount(1);
+  VerifyDefaultPageLayout(540, 720, 36, 36, 36, 36, false);
+  VerifyPrintPreviewCancelled(false);
+  VerifyPrintPreviewFailed(false);
+  VerifyPrintPreviewGenerated(true);
+  VerifyPagesPrinted(false);
+  ExpectOneBeforeNoAfterPrintEvent();
+
+  OnClosePrintPreviewDialog();
+  ExpectOneBeforeOneAfterPrintEvent();
+}
+
+// Regression test for https://crbug.com/912966
+TEST_F(MAYBE_PrintRenderFrameHelperPreviewTest,
+       WindowPrintBeforePrintAfterPrint) {
+  LoadHTML(kBeforeAfterPrintHtml);
+  gfx::Size new_size(200, 100);
+  Resize(new_size, false);
+  ExpectNoBeforeNoAfterPrintEvent();
+
+  gfx::Rect bounds = GetElementBounds("print");
+  ClickMouseButton(bounds);
+
+  VerifyPreviewRequest(true);
+  ExpectOneBeforeNoAfterPrintEvent();
+
+  OnClosePrintPreviewDialog();
+  ExpectOneBeforeOneAfterPrintEvent();
+}
+
 #endif  // BUILDFLAG(ENABLE_PRINT_PREVIEW)
 
 #endif  // !defined(OS_CHROMEOS)
diff --git a/components/ui_devtools/root_element.cc b/components/ui_devtools/root_element.cc
index 1a41288..5b508aa 100644
--- a/components/ui_devtools/root_element.cc
+++ b/components/ui_devtools/root_element.cc
@@ -41,8 +41,8 @@
   return nullptr;
 }
 
-std::pair<gfx::NativeWindow, gfx::Rect> RootElement::GetNodeWindowAndBounds()
-    const {
+std::pair<gfx::NativeWindow, gfx::Rect>
+RootElement::GetNodeWindowAndScreenBounds() const {
   NOTREACHED();
   return {};
 }
diff --git a/components/ui_devtools/root_element.h b/components/ui_devtools/root_element.h
index 7f62775..e0156baa 100644
--- a/components/ui_devtools/root_element.h
+++ b/components/ui_devtools/root_element.h
@@ -23,7 +23,7 @@
   void GetVisible(bool* visible) const override;
   void SetVisible(bool visible) override;
   std::unique_ptr<protocol::Array<std::string>> GetAttributes() const override;
-  std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndBounds()
+  std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndScreenBounds()
       const override;
 
  private:
diff --git a/components/ui_devtools/ui_element.h b/components/ui_devtools/ui_element.h
index e7578a9..10abb56 100644
--- a/components/ui_devtools/ui_element.h
+++ b/components/ui_devtools/ui_element.h
@@ -67,9 +67,9 @@
   virtual void GetVisible(bool* visible) const = 0;
   virtual void SetVisible(bool visible) = 0;
 
-  // If element exists, return its associated native window and its bounds.
-  // Otherwise, return null and empty bounds.
-  virtual std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndBounds()
+  // If element exists, return its associated native window and its screen
+  // bounds. Otherwise, return null and empty bounds.
+  virtual std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndScreenBounds()
       const = 0;
   // Get a list of interleaved keys and values of attributes to be displayed
   // on the element in the dev tools hierarchy view.
diff --git a/components/ui_devtools/views/overlay_agent_aura.cc b/components/ui_devtools/views/overlay_agent_aura.cc
index 4fd9c64..bd0614a3 100644
--- a/components/ui_devtools/views/overlay_agent_aura.cc
+++ b/components/ui_devtools/views/overlay_agent_aura.cc
@@ -461,9 +461,13 @@
 void OverlayAgentAura::ShowDistancesInHighlightOverlay(int pinned_id,
                                                        int element_id) {
   const std::pair<gfx::NativeWindow, gfx::Rect> pair_r2(
-      dom_agent()->GetElementFromNodeId(element_id)->GetNodeWindowAndBounds());
+      dom_agent()
+          ->GetElementFromNodeId(element_id)
+          ->GetNodeWindowAndScreenBounds());
   const std::pair<gfx::NativeWindow, gfx::Rect> pair_r1(
-      dom_agent()->GetElementFromNodeId(pinned_id)->GetNodeWindowAndBounds());
+      dom_agent()
+          ->GetElementFromNodeId(pinned_id)
+          ->GetNodeWindowAndScreenBounds());
   gfx::Rect r2(pair_r2.second);
   gfx::Rect r1(pair_r1.second);
   pinned_rect_ = r1;
@@ -520,7 +524,7 @@
   highlight_rect_config_ = HighlightRectsConfiguration::NO_DRAW;
   show_size_on_canvas_ = show_size;
   layer_for_highlighting_->SetVisible(
-      UpdateHighlight(element->GetNodeWindowAndBounds()));
+      UpdateHighlight(element->GetNodeWindowAndScreenBounds()));
   return Response::OK();
 }
 
diff --git a/components/ui_devtools/views/overlay_agent_aura.h b/components/ui_devtools/views/overlay_agent_aura.h
index d21c20ec..9659ca8 100644
--- a/components/ui_devtools/views/overlay_agent_aura.h
+++ b/components/ui_devtools/views/overlay_agent_aura.h
@@ -74,6 +74,7 @@
  private:
   FRIEND_TEST_ALL_PREFIXES(OverlayAgentTest,
                            MouseEventsGenerateFEEventsInInspectMode);
+  FRIEND_TEST_ALL_PREFIXES(OverlayAgentTest, HighlightRects);
   FRIEND_TEST_ALL_PREFIXES(OverlayAgentTest, HighlightNonexistentNode);
   FRIEND_TEST_ALL_PREFIXES(OverlayAgentTest, HighlightWidget);
 #if defined(USE_AURA)
@@ -83,7 +84,7 @@
   protocol::Response HighlightNode(int node_id, bool show_size = false);
   // Returns true when there is any visible element to highlight.
   bool UpdateHighlight(
-      const std::pair<gfx::NativeWindow, gfx::Rect>& window_and_bounds);
+      const std::pair<gfx::NativeWindow, gfx::Rect>& window_and_screen_bounds);
 
   // Shows the distances between the nodes identified by |pinned_id| and
   // |element_id| in the highlight overlay.
diff --git a/components/ui_devtools/views/overlay_agent_unittest.cc b/components/ui_devtools/views/overlay_agent_unittest.cc
index 77246475..8223fcec 100644
--- a/components/ui_devtools/views/overlay_agent_unittest.cc
+++ b/components/ui_devtools/views/overlay_agent_unittest.cc
@@ -105,18 +105,23 @@
     return window;
   }
 
-  std::unique_ptr<views::Widget> CreateWidget() {
+  std::unique_ptr<views::Widget> CreateWidget(const gfx::Rect& bounds) {
     auto widget = std::make_unique<views::Widget>();
     views::Widget::InitParams params;
     params.delegate = nullptr;
     params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
-    params.bounds = gfx::Rect(0, 0, 400, 400);
+    params.bounds = bounds;
     params.parent = GetContext();
     widget->Init(params);
     widget->Show();
     return widget;
   }
 
+  std::unique_ptr<views::Widget> CreateWidget() {
+    // Create a widget with default bounds.
+    return CreateWidget(gfx::Rect(0, 0, 400, 400));
+  }
+
   DOMAgent* dom_agent() { return dom_agent_.get(); }
   OverlayAgentAura* overlay_agent() { return overlay_agent_.get(); }
   FakeFrontendChannel* frontend_channel() {
@@ -216,9 +221,12 @@
       {"R1_INTERSECTS_R2", gfx::Rect(100, 100, 50, 50),
        gfx::Rect(120, 120, 50, 50), R1_INTERSECTS_R2},
   };
+  // Use a non-zero origin to test screen coordinates.
+  const gfx::Rect kWidgetBounds(10, 10, 510, 510);
+
   for (const auto& test_case : kTestCases) {
     SCOPED_TRACE(testing::Message() << "Case: " << test_case.name);
-    std::unique_ptr<views::Widget> widget = CreateWidget();
+    std::unique_ptr<views::Widget> widget = CreateWidget(kWidgetBounds);
 
     std::unique_ptr<protocol::DOM::Node> root;
     dom_agent()->getDocument(&root);
@@ -251,8 +259,18 @@
     // Highlight child 2. Now, the distance overlay is showing.
     generator.MoveMouseTo(GetOriginInScreen(child_2));
 
+    // Check calculated highlight config.
     EXPECT_EQ(test_case.expected_configuration,
               overlay_agent()->highlight_rect_config());
+    // Check results of pinned and hovered rectangles.
+    gfx::Rect expected_pinned_rect =
+        client_view->ConvertRectToParent(test_case.first_element_bounds);
+    expected_pinned_rect.Offset(kWidgetBounds.OffsetFromOrigin());
+    EXPECT_EQ(expected_pinned_rect, overlay_agent()->pinned_rect_);
+    gfx::Rect expected_hovered_rect =
+        client_view->ConvertRectToParent(test_case.second_element_bounds);
+    expected_hovered_rect.Offset(kWidgetBounds.OffsetFromOrigin());
+    EXPECT_EQ(expected_hovered_rect, overlay_agent()->hovered_rect_);
     // If we don't explicitly stop inspecting, we'll leave ourselves as
     // a pretarget handler for the root window and UAF in the next test.
     // TODO(lgrey): Fix this when refactoring to support Mac.
diff --git a/components/ui_devtools/views/view_element.cc b/components/ui_devtools/views/view_element.cc
index 167aca2..2caf7796 100644
--- a/components/ui_devtools/views/view_element.cc
+++ b/components/ui_devtools/views/view_element.cc
@@ -93,8 +93,8 @@
   return attributes;
 }
 
-std::pair<gfx::NativeWindow, gfx::Rect> ViewElement::GetNodeWindowAndBounds()
-    const {
+std::pair<gfx::NativeWindow, gfx::Rect>
+ViewElement::GetNodeWindowAndScreenBounds() const {
   return std::make_pair(view_->GetWidget()->GetNativeWindow(),
                         view_->GetBoundsInScreen());
 }
diff --git a/components/ui_devtools/views/view_element.h b/components/ui_devtools/views/view_element.h
index 0bccbc2b..ee84c75 100644
--- a/components/ui_devtools/views/view_element.h
+++ b/components/ui_devtools/views/view_element.h
@@ -38,7 +38,7 @@
   void GetVisible(bool* visible) const override;
   void SetVisible(bool visible) override;
   std::unique_ptr<protocol::Array<std::string>> GetAttributes() const override;
-  std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndBounds()
+  std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndScreenBounds()
       const override;
   static views::View* From(const UIElement* element);
 
diff --git a/components/ui_devtools/views/view_element_unittest.cc b/components/ui_devtools/views/view_element_unittest.cc
index 5ef8bca..ab63de0a 100644
--- a/components/ui_devtools/views/view_element_unittest.cc
+++ b/components/ui_devtools/views/view_element_unittest.cc
@@ -128,7 +128,7 @@
   EXPECT_EQ(props[0].second, "This is the tooltip");
 }
 
-TEST_F(ViewElementTest, GetNodeWindowAndBounds) {
+TEST_F(ViewElementTest, GetNodeWindowAndScreenBounds) {
   // For this to be meaningful, the view must be in
   // a widget.
   auto widget = std::make_unique<views::Widget>();
@@ -143,7 +143,7 @@
   view()->SetBoundsRect(bounds);
 
   std::pair<gfx::NativeWindow, gfx::Rect> window_and_bounds =
-      element()->GetNodeWindowAndBounds();
+      element()->GetNodeWindowAndScreenBounds();
   EXPECT_EQ(window_and_bounds.first, widget->GetNativeWindow());
   EXPECT_EQ(window_and_bounds.second, view()->GetBoundsInScreen());
 
diff --git a/components/ui_devtools/views/widget_element.cc b/components/ui_devtools/views/widget_element.cc
index 53967b9..78cb0f8 100644
--- a/components/ui_devtools/views/widget_element.cc
+++ b/components/ui_devtools/views/widget_element.cc
@@ -82,8 +82,8 @@
   return attributes;
 }
 
-std::pair<gfx::NativeWindow, gfx::Rect> WidgetElement::GetNodeWindowAndBounds()
-    const {
+std::pair<gfx::NativeWindow, gfx::Rect>
+WidgetElement::GetNodeWindowAndScreenBounds() const {
   return std::make_pair(widget_->GetNativeWindow(),
                         widget_->GetWindowBoundsInScreen());
 }
diff --git a/components/ui_devtools/views/widget_element.h b/components/ui_devtools/views/widget_element.h
index 51c4d271..24a90cca 100644
--- a/components/ui_devtools/views/widget_element.h
+++ b/components/ui_devtools/views/widget_element.h
@@ -43,7 +43,7 @@
   void GetVisible(bool* visible) const override;
   void SetVisible(bool visible) override;
   std::unique_ptr<protocol::Array<std::string>> GetAttributes() const override;
-  std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndBounds()
+  std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndScreenBounds()
       const override;
 
   static views::Widget* From(const UIElement* element);
diff --git a/components/ui_devtools/views/widget_element_unittest.cc b/components/ui_devtools/views/widget_element_unittest.cc
index c08adf9..3587e80 100644
--- a/components/ui_devtools/views/widget_element_unittest.cc
+++ b/components/ui_devtools/views/widget_element_unittest.cc
@@ -130,9 +130,9 @@
   EXPECT_EQ(attrs->get(3), "true");
 }
 
-TEST_F(WidgetElementTest, GetNodeWindowAndBounds) {
+TEST_F(WidgetElementTest, GetNodeWindowAndScreenBounds) {
   std::pair<gfx::NativeWindow, gfx::Rect> window_and_bounds =
-      element()->GetNodeWindowAndBounds();
+      element()->GetNodeWindowAndScreenBounds();
   EXPECT_EQ(widget()->GetNativeWindow(), window_and_bounds.first);
   EXPECT_EQ(widget()->GetWindowBoundsInScreen(), window_and_bounds.second);
 }
diff --git a/components/ui_devtools/views/window_element.cc b/components/ui_devtools/views/window_element.cc
index 81d7a03..366d13ee 100644
--- a/components/ui_devtools/views/window_element.cc
+++ b/components/ui_devtools/views/window_element.cc
@@ -100,8 +100,8 @@
   return attributes;
 }
 
-std::pair<gfx::NativeWindow, gfx::Rect> WindowElement::GetNodeWindowAndBounds()
-    const {
+std::pair<gfx::NativeWindow, gfx::Rect>
+WindowElement::GetNodeWindowAndScreenBounds() const {
   return std::make_pair(static_cast<aura::Window*>(window_),
                         window_->GetBoundsInScreen());
 }
diff --git a/components/ui_devtools/views/window_element.h b/components/ui_devtools/views/window_element.h
index 5e026ab..89c3280 100644
--- a/components/ui_devtools/views/window_element.h
+++ b/components/ui_devtools/views/window_element.h
@@ -41,7 +41,7 @@
   void GetVisible(bool* visible) const override;
   void SetVisible(bool visible) override;
   std::unique_ptr<protocol::Array<std::string>> GetAttributes() const override;
-  std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndBounds()
+  std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndScreenBounds()
       const override;
 
   static aura::Window* From(const UIElement* element);
diff --git a/components/ui_devtools/viz_views/frame_sink_element.cc b/components/ui_devtools/viz_views/frame_sink_element.cc
index 19e4c65..6b75b3da0 100644
--- a/components/ui_devtools/viz_views/frame_sink_element.cc
+++ b/components/ui_devtools/viz_views/frame_sink_element.cc
@@ -98,7 +98,7 @@
 }
 
 std::pair<gfx::NativeWindow, gfx::Rect>
-FrameSinkElement::GetNodeWindowAndBounds() const {
+FrameSinkElement::GetNodeWindowAndScreenBounds() const {
   return {};
 }
 
diff --git a/components/ui_devtools/viz_views/frame_sink_element.h b/components/ui_devtools/viz_views/frame_sink_element.h
index 07a6355a..76a52f0 100644
--- a/components/ui_devtools/viz_views/frame_sink_element.h
+++ b/components/ui_devtools/viz_views/frame_sink_element.h
@@ -43,7 +43,7 @@
   void GetVisible(bool* visible) const override;
   void SetVisible(bool visible) override;
   std::unique_ptr<protocol::Array<std::string>> GetAttributes() const override;
-  std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndBounds()
+  std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndScreenBounds()
       const override;
 
   static const viz::FrameSinkId& From(const UIElement* element);
diff --git a/components/ui_devtools/viz_views/surface_element.cc b/components/ui_devtools/viz_views/surface_element.cc
index 04bda027..56ac892 100644
--- a/components/ui_devtools/viz_views/surface_element.cc
+++ b/components/ui_devtools/viz_views/surface_element.cc
@@ -69,8 +69,8 @@
   return attributes;
 }
 
-std::pair<gfx::NativeWindow, gfx::Rect> SurfaceElement::GetNodeWindowAndBounds()
-    const {
+std::pair<gfx::NativeWindow, gfx::Rect>
+SurfaceElement::GetNodeWindowAndScreenBounds() const {
   return {};
 }
 
diff --git a/components/ui_devtools/viz_views/surface_element.h b/components/ui_devtools/viz_views/surface_element.h
index 38d50680..71b75c2d 100644
--- a/components/ui_devtools/viz_views/surface_element.h
+++ b/components/ui_devtools/viz_views/surface_element.h
@@ -32,7 +32,7 @@
   void GetVisible(bool* visible) const override;
   void SetVisible(bool visible) override;
   std::unique_ptr<protocol::Array<std::string>> GetAttributes() const override;
-  std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndBounds()
+  std::pair<gfx::NativeWindow, gfx::Rect> GetNodeWindowAndScreenBounds()
       const override;
 
   static const viz::SurfaceId& From(const UIElement* element);
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc
index dfc459a..ada8339c 100644
--- a/components/viz/common/features.cc
+++ b/components/viz/common/features.cc
@@ -26,8 +26,13 @@
 // Enables running the display compositor as part of the viz service in the GPU
 // process. This is also referred to as out-of-process display compositor
 // (OOP-D).
+#if defined(OS_ANDROID)
+const base::Feature kVizDisplayCompositor{"VizDisplayCompositor",
+                                          base::FEATURE_ENABLED_BY_DEFAULT};
+#else
 const base::Feature kVizDisplayCompositor{"VizDisplayCompositor",
                                           base::FEATURE_DISABLED_BY_DEFAULT};
+#endif
 
 // Enables running the Viz-assisted hit-test logic.
 #if defined(OS_CHROMEOS)
diff --git a/components/viz/host/hit_test/hit_test_query.cc b/components/viz/host/hit_test/hit_test_query.cc
index db94c3e..6f37135 100644
--- a/components/viz/host/hit_test/hit_test_query.cc
+++ b/components/viz/host/hit_test/hit_test_query.cc
@@ -7,6 +7,7 @@
 #include "base/containers/stack.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/timer/elapsed_timer.h"
+#include "components/viz/common/features.h"
 #include "components/viz/common/hit_test/hit_test_region_list.h"
 #include "ui/gfx/geometry/point_conversions.h"
 #include "ui/gfx/geometry/rect_f.h"
@@ -196,9 +197,11 @@
 
   size_t child_region = region_index + 1;
   size_t child_region_end = child_region + region_child_count;
-  gfx::PointF location_in_target =
-      location_transformed -
-      hit_test_data_[region_index].rect.OffsetFromOrigin();
+  gfx::PointF location_in_target = location_transformed;
+  if (!features::IsVizHitTestingSurfaceLayerEnabled()) {
+    location_in_target = location_transformed -
+                         hit_test_data_[region_index].rect.OffsetFromOrigin();
+  }
 
   const uint32_t flags = hit_test_data_[region_index].flags;
 
@@ -258,8 +261,10 @@
   }
 
   hit_test_data_[region_index].transform().TransformPoint(location_in_target);
-  location_in_target->Offset(-hit_test_data_[region_index].rect.x(),
-                             -hit_test_data_[region_index].rect.y());
+  if (!features::IsVizHitTestingSurfaceLayerEnabled()) {
+    location_in_target->Offset(-hit_test_data_[region_index].rect.x(),
+                               -hit_test_data_[region_index].rect.y());
+  }
   if (!target_ancestor)
     return true;
 
@@ -298,8 +303,10 @@
   // found immediately.
   if (hit_test_data_[region_index].frame_sink_id == target) {
     *transform = hit_test_data_[region_index].transform();
-    transform->Translate(-hit_test_data_[region_index].rect.x(),
-                         -hit_test_data_[region_index].rect.y());
+    if (!features::IsVizHitTestingSurfaceLayerEnabled()) {
+      transform->Translate(-hit_test_data_[region_index].rect.x(),
+                           -hit_test_data_[region_index].rect.y());
+    }
     return true;
   }
 
@@ -316,8 +323,10 @@
     if (GetTransformToTargetRecursively(target, child_region,
                                         &transform_to_child)) {
       gfx::Transform region_transform(hit_test_data_[region_index].transform());
-      region_transform.Translate(-hit_test_data_[region_index].rect.x(),
-                                 -hit_test_data_[region_index].rect.y());
+      if (!features::IsVizHitTestingSurfaceLayerEnabled()) {
+        region_transform.Translate(-hit_test_data_[region_index].rect.x(),
+                                   -hit_test_data_[region_index].rect.y());
+      }
       *transform = transform_to_child * region_transform;
       return true;
     }
diff --git a/content/app/DEPS b/content/app/DEPS
index cd56a2a..1bcd820 100644
--- a/content/app/DEPS
+++ b/content/app/DEPS
@@ -9,6 +9,7 @@
   "+gin/public/isolate_holder.h",
   "+gin/public/snapshot_fd_data.h",
   "+gin/v8_initializer.h",
+  "+services/network/public/cpp/features.h",
   "+services/service_manager/embedder",
   "+services/service_manager/runner/common",
   "+services/service_manager/sandbox/sandbox_type.h",
diff --git a/content/app/content_main_runner_impl.cc b/content/app/content_main_runner_impl.cc
index 88565a90..a62f2ec 100644
--- a/content/app/content_main_runner_impl.cc
+++ b/content/app/content_main_runner_impl.cc
@@ -56,11 +56,13 @@
 #include "content/public/common/content_paths.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/main_function_params.h"
+#include "content/public/common/network_service_util.h"
 #include "content/public/common/sandbox_init.h"
 #include "gin/v8_initializer.h"
 #include "media/base/media.h"
 #include "media/media_buildflags.h"
 #include "ppapi/buildflags/buildflags.h"
+#include "services/network/public/cpp/features.h"
 #include "services/service_manager/embedder/switches.h"
 #include "services/service_manager/sandbox/sandbox_type.h"
 #include "services/service_manager/sandbox/switches.h"
@@ -875,6 +877,7 @@
   if (is_browser_main_loop_started_)
     return -1;
 
+  bool should_start_service_manager_only = start_service_manager_only;
   if (!service_manager_context_) {
     if (delegate_->ShouldCreateFeatureList()) {
       DCHECK(!field_trial_list_);
@@ -915,6 +918,17 @@
     // incorrect to post to a BrowserThread before this point.
     BrowserTaskExecutor::Create();
 
+    if (!base::FeatureList::IsEnabled(
+            features::kAllowStartingServiceManagerOnly)) {
+      should_start_service_manager_only = false;
+    }
+
+    if (should_start_service_manager_only &&
+        base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+      // This must be called before creating the ServiceManagerContext.
+      ForceInProcessNetworkService(true);
+    }
+
     // The thread used to start the ServiceManager is handed-off to
     // BrowserMain() which may elect to promote it (e.g. to BrowserThread::IO).
     service_manager_thread_ = BrowserProcessSubThread::CreateIOThread();
@@ -922,16 +936,15 @@
         new ServiceManagerContext(service_manager_thread_->task_runner()));
     download::SetIOTaskRunner(service_manager_thread_->task_runner());
 #if defined(OS_ANDROID)
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(&ServiceManagerStartupComplete));
+    if (start_service_manager_only) {
+      base::ThreadTaskRunnerHandle::Get()->PostTask(
+          FROM_HERE, base::BindOnce(&ServiceManagerStartupComplete));
+    }
 #endif
   }
 
-  if (base::FeatureList::IsEnabled(
-          features::kAllowStartingServiceManagerOnly) &&
-      start_service_manager_only) {
+  if (should_start_service_manager_only)
     return -1;
-  }
 
   is_browser_main_loop_started_ = true;
   startup_data_ = std::make_unique<StartupDataImpl>();
diff --git a/content/browser/accessibility/accessibility_tree_formatter_blink.cc b/content/browser/accessibility/accessibility_tree_formatter_blink.cc
index 2c6b8db..f99eb20 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_blink.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_blink.cc
@@ -24,6 +24,29 @@
 namespace content {
 namespace {
 
+base::Optional<std::string> GetStringAttribute(
+    const BrowserAccessibility& node,
+    ax::mojom::StringAttribute attr) {
+  // Language and Font Family are different from other string attributes
+  // in that they inherit.
+  if (attr == ax::mojom::StringAttribute::kFontFamily ||
+      attr == ax::mojom::StringAttribute::kLanguage) {
+    std::string value = node.GetInheritedStringAttribute(attr);
+    if (value.empty()) {
+      return base::nullopt;
+    }
+    return value;
+  }
+
+  // Always return the attribute if the node has it, even if the value is an
+  // empty string.
+  std::string value;
+  if (node.GetStringAttribute(attr, &value)) {
+    return value;
+  }
+  return base::nullopt;
+}
+
 base::Optional<int32_t> GetCellAttribute(const ui::AXNode* ax_node,
                                          ax::mojom::IntAttribute attr) {
   switch (attr) {
@@ -235,17 +258,6 @@
   dict->SetInteger("unclippedBoundsWidth", unclipped_bounds.width());
   dict->SetInteger("unclippedBoundsHeight", unclipped_bounds.height());
 
-  // Language and Font Family are different from other string attributes
-  // in that they inherit.
-  std::string font_family =
-      node.GetInheritedStringAttribute(ax::mojom::StringAttribute::kFontFamily);
-  if (!font_family.empty())
-    dict->SetString("fontFamily", font_family);
-  std::string language =
-      node.GetInheritedStringAttribute(ax::mojom::StringAttribute::kLanguage);
-  if (!language.empty())
-    dict->SetString("language", language);
-
   for (int32_t state_index = static_cast<int32_t>(ax::mojom::State::kNone);
        state_index <= static_cast<int32_t>(ax::mojom::State::kMaxValue);
        ++state_index) {
@@ -263,11 +275,9 @@
        static_cast<int32_t>(ax::mojom::StringAttribute::kMaxValue);
        ++attr_index) {
     auto attr = static_cast<ax::mojom::StringAttribute>(attr_index);
-    if (attr != ax::mojom::StringAttribute::kFontFamily &&
-        attr != ax::mojom::StringAttribute::kLanguage) {
-      if (node.HasStringAttribute(attr))
-        dict->SetString(ui::ToString(attr), node.GetStringAttribute(attr));
-    }
+    auto maybe_value = GetStringAttribute(node, attr);
+    if (maybe_value.has_value())
+      dict->SetString(ui::ToString(attr), maybe_value.value());
   }
 
   for (int32_t attr_index =
diff --git a/content/browser/accessibility/browser_accessibility_manager.cc b/content/browser/accessibility/browser_accessibility_manager.cc
index ac9125a..1fcc3e7 100644
--- a/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/content/browser/accessibility/browser_accessibility_manager.cc
@@ -116,8 +116,7 @@
 BrowserAccessibilityManager::BrowserAccessibilityManager(
     BrowserAccessibilityDelegate* delegate,
     BrowserAccessibilityFactory* factory)
-    : AXEventGenerator(),
-      delegate_(delegate),
+    : delegate_(delegate),
       factory_(factory),
       tree_(new ui::AXSerializableTree()),
       user_is_navigating_away_(false),
@@ -126,16 +125,16 @@
       connected_to_parent_tree_node_(false),
       ax_tree_id_(ui::AXTreeIDUnknown()),
       device_scale_factor_(1.0f),
-      use_custom_device_scale_factor_for_testing_(false) {
-  SetTree(tree_.get());
+      use_custom_device_scale_factor_for_testing_(false),
+      event_generator_(tree_.get()) {
+  tree_->AddObserver(this);
 }
 
 BrowserAccessibilityManager::BrowserAccessibilityManager(
     const ui::AXTreeUpdate& initial_tree,
     BrowserAccessibilityDelegate* delegate,
     BrowserAccessibilityFactory* factory)
-    : AXEventGenerator(),
-      delegate_(delegate),
+    : delegate_(delegate),
       factory_(factory),
       tree_(new ui::AXSerializableTree()),
       user_is_navigating_away_(false),
@@ -143,14 +142,15 @@
       last_focused_manager_(nullptr),
       ax_tree_id_(ui::AXTreeIDUnknown()),
       device_scale_factor_(1.0f),
-      use_custom_device_scale_factor_for_testing_(false) {
-  SetTree(tree_.get());
+      use_custom_device_scale_factor_for_testing_(false),
+      event_generator_(tree_.get()) {
+  tree_->AddObserver(this);
   Initialize(initial_tree);
 }
 
 BrowserAccessibilityManager::~BrowserAccessibilityManager() {
   tree_.reset(nullptr);
-  ReleaseTree();
+  event_generator_.ReleaseTree();
   g_ax_tree_id_map.Get().erase(ax_tree_id_);
 }
 
@@ -233,7 +233,7 @@
   if (!tree_)
     return nullptr;
 
-  // tree_->root() can be null during AXTreeDelegate callbacks.
+  // tree_->root() can be null during AXTreeObserver callbacks.
   ui::AXNode* root = tree_->root();
   return root ? GetFromAXNode(root) : nullptr;
 }
@@ -349,7 +349,7 @@
 
   // If this page is hidden by an interstitial, suppress all events.
   if (GetRootManager()->hidden_by_interstitial_page()) {
-    ClearEvents();
+    event_generator_.ClearEvents();
     return;
   }
 
@@ -360,7 +360,7 @@
     if (!connected_to_parent_tree_node_) {
       parent->OnDataChanged();
       parent->UpdatePlatformAttributes();
-      FireGeneratedEvent(Event::CHILDREN_CHANGED, parent);
+      FireGeneratedEvent(ui::AXEventGenerator::Event::CHILDREN_CHANGED, parent);
       connected_to_parent_tree_node_ = true;
     }
   } else {
@@ -374,14 +374,14 @@
   GetRootManager()->FireFocusEventsIfNeeded();
 
   // Fire any events related to changes to the tree.
-  for (auto targeted_event : *this) {
+  for (auto targeted_event : event_generator_) {
     BrowserAccessibility* event_target = GetFromAXNode(targeted_event.node);
     if (!event_target || !event_target->CanFireEvents())
       continue;
 
     FireGeneratedEvent(targeted_event.event_params.event, event_target);
   }
-  ClearEvents();
+  event_generator_.ClearEvents();
 
   // Fire events from Blink.
   for (uint32_t index = 0; index < details.events.size(); index++) {
@@ -1066,7 +1066,6 @@
 
 void BrowserAccessibilityManager::OnNodeWillBeDeleted(ui::AXTree* tree,
                                                       ui::AXNode* node) {
-  AXEventGenerator::OnNodeWillBeDeleted(tree, node);
   DCHECK(node);
   if (id_wrapper_map_.find(node->id()) == id_wrapper_map_.end())
     return;
@@ -1076,7 +1075,6 @@
 
 void BrowserAccessibilityManager::OnSubtreeWillBeDeleted(ui::AXTree* tree,
                                                          ui::AXNode* node) {
-  AXEventGenerator::OnSubtreeWillBeDeleted(tree, node);
   DCHECK(node);
   BrowserAccessibility* obj = GetFromAXNode(node);
   if (obj)
@@ -1085,7 +1083,6 @@
 
 void BrowserAccessibilityManager::OnNodeCreated(ui::AXTree* tree,
                                                 ui::AXNode* node) {
-  AXEventGenerator::OnNodeCreated(tree, node);
   BrowserAccessibility* wrapper = factory_->Create();
   wrapper->Init(this, node);
   id_wrapper_map_[node->id()] = wrapper;
@@ -1094,7 +1091,6 @@
 
 void BrowserAccessibilityManager::OnNodeReparented(ui::AXTree* tree,
                                                    ui::AXNode* node) {
-  AXEventGenerator::OnNodeReparented(tree, node);
   BrowserAccessibility* wrapper = GetFromID(node->id());
   if (!wrapper) {
     wrapper = factory_->Create();
@@ -1107,7 +1103,6 @@
 
 void BrowserAccessibilityManager::OnNodeChanged(ui::AXTree* tree,
                                                 ui::AXNode* node) {
-  AXEventGenerator::OnNodeChanged(tree, node);
   DCHECK(node);
   GetFromAXNode(node)->OnDataChanged();
 }
@@ -1115,8 +1110,7 @@
 void BrowserAccessibilityManager::OnAtomicUpdateFinished(
     ui::AXTree* tree,
     bool root_changed,
-    const std::vector<ui::AXTreeDelegate::Change>& changes) {
-  AXEventGenerator::OnAtomicUpdateFinished(tree, root_changed, changes);
+    const std::vector<ui::AXTreeObserver::Change>& changes) {
   bool ax_tree_id_changed = false;
   if (GetTreeData().tree_id != ui::AXTreeIDUnknown() &&
       GetTreeData().tree_id != ax_tree_id_) {
diff --git a/content/browser/accessibility/browser_accessibility_manager.h b/content/browser/accessibility/browser_accessibility_manager.h
index 6a06f56..c1e9c2d 100644
--- a/content/browser/accessibility/browser_accessibility_manager.h
+++ b/content/browser/accessibility/browser_accessibility_manager.h
@@ -26,6 +26,7 @@
 #include "ui/accessibility/ax_range.h"
 #include "ui/accessibility/ax_serializable_tree.h"
 #include "ui/accessibility/ax_tree_id_registry.h"
+#include "ui/accessibility/ax_tree_observer.h"
 #include "ui/accessibility/ax_tree_update.h"
 #include "ui/gfx/native_widget_types.h"
 
@@ -111,7 +112,7 @@
 };
 
 // Manages a tree of BrowserAccessibility objects.
-class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXEventGenerator {
+class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeObserver {
  public:
   // Creates the platform-specific BrowserAccessibilityManager, but
   // with no parent window pointer. Only useful for unit tests.
@@ -132,7 +133,7 @@
   virtual void FireFocusEvent(BrowserAccessibility* node);
   virtual void FireBlinkEvent(ax::mojom::Event event_type,
                               BrowserAccessibility* node) {}
-  virtual void FireGeneratedEvent(AXEventGenerator::Event event_type,
+  virtual void FireGeneratedEvent(ui::AXEventGenerator::Event event_type,
                                   BrowserAccessibility* node) {}
 
   // Checks whether focus has changed since the last time it was checked,
@@ -343,7 +344,7 @@
   float device_scale_factor() const { return device_scale_factor_; }
   ui::AXTree* ax_tree() const { return tree_.get(); }
 
-  // AXTreeDelegate implementation.
+  // AXTreeObserver implementation.
   void OnNodeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override;
   void OnSubtreeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override;
   void OnNodeCreated(ui::AXTree* tree, ui::AXNode* node) override;
@@ -352,7 +353,7 @@
   void OnAtomicUpdateFinished(
       ui::AXTree* tree,
       bool root_changed,
-      const std::vector<ui::AXTreeDelegate::Change>& changes) override;
+      const std::vector<ui::AXTreeObserver::Change>& changes) override;
 
   BrowserAccessibilityDelegate* delegate() const { return delegate_; }
 
@@ -460,6 +461,8 @@
   // used and it won't be updated from the delegate.
   bool use_custom_device_scale_factor_for_testing_;
 
+  ui::AXEventGenerator event_generator_;
+
   // Fire all events regardless of focus and with no delay, to avoid test
   // flakiness. See NeverSuppressOrDelayEventsForTesting() for details.
   static bool never_suppress_or_delay_events_for_testing_;
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.cc b/content/browser/accessibility/browser_accessibility_manager_android.cc
index ed8b663..5065ad60 100644
--- a/content/browser/accessibility/browser_accessibility_manager_android.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -125,7 +125,7 @@
 }
 
 void BrowserAccessibilityManagerAndroid::FireGeneratedEvent(
-    AXEventGenerator::Event event_type,
+    ui::AXEventGenerator::Event event_type,
     BrowserAccessibility* node) {
   BrowserAccessibilityManager::FireGeneratedEvent(event_type, node);
   WebContentsAccessibilityAndroid* wcax = GetWebContentsAXFromRootManager();
@@ -156,30 +156,30 @@
   wcax->HandleContentChanged(android_node->unique_id());
 
   switch (event_type) {
-    case Event::LOAD_COMPLETE:
+    case ui::AXEventGenerator::Event::LOAD_COMPLETE:
       if (node->manager() == GetRootManager()) {
         auto* android_focused =
             static_cast<BrowserAccessibilityAndroid*>(GetFocus());
         wcax->HandlePageLoaded(android_focused->unique_id());
       }
       break;
-    case Event::CHECKED_STATE_CHANGED:
+    case ui::AXEventGenerator::Event::CHECKED_STATE_CHANGED:
       wcax->HandleCheckStateChanged(android_node->unique_id());
       break;
-    case Event::SCROLL_POSITION_CHANGED:
+    case ui::AXEventGenerator::Event::SCROLL_POSITION_CHANGED:
       wcax->HandleScrollPositionChanged(android_node->unique_id());
       break;
-    case Event::ALERT:
+    case ui::AXEventGenerator::Event::ALERT:
     // An alert is a special case of live region. Fall through to the
     // next case to handle it.
-    case Event::LIVE_REGION_NODE_CHANGED: {
+    case ui::AXEventGenerator::Event::LIVE_REGION_NODE_CHANGED: {
       // This event is fired when an object appears in a live region.
       // Speak its text.
       base::string16 text = android_node->GetText();
       wcax->AnnounceLiveRegionText(text);
       break;
     }
-    case Event::DOCUMENT_SELECTION_CHANGED: {
+    case ui::AXEventGenerator::Event::DOCUMENT_SELECTION_CHANGED: {
       int32_t focus_id = GetTreeData().sel_focus_object_id;
       BrowserAccessibility* focus_object = GetFromID(focus_id);
       if (focus_object) {
@@ -189,32 +189,32 @@
       }
       break;
     }
-    case Event::VALUE_CHANGED:
+    case ui::AXEventGenerator::Event::VALUE_CHANGED:
       if (android_node->IsEditableText() && GetFocus() == node) {
         wcax->HandleEditableTextChanged(android_node->unique_id());
       } else if (android_node->IsSlider()) {
         wcax->HandleSliderChanged(android_node->unique_id());
       }
       break;
-    case Event::ACTIVE_DESCENDANT_CHANGED:
-    case Event::CHILDREN_CHANGED:
-    case Event::COLLAPSED:
-    case Event::DESCRIPTION_CHANGED:
-    case Event::DOCUMENT_TITLE_CHANGED:
-    case Event::EXPANDED:
-    case Event::INVALID_STATUS_CHANGED:
-    case Event::LIVE_REGION_CHANGED:
-    case Event::LIVE_REGION_CREATED:
-    case Event::LOAD_START:
-    case Event::MENU_ITEM_SELECTED:
-    case Event::NAME_CHANGED:
-    case Event::OTHER_ATTRIBUTE_CHANGED:
-    case Event::RELATED_NODE_CHANGED:
-    case Event::ROLE_CHANGED:
-    case Event::ROW_COUNT_CHANGED:
-    case Event::SELECTED_CHANGED:
-    case Event::SELECTED_CHILDREN_CHANGED:
-    case Event::STATE_CHANGED:
+    case ui::AXEventGenerator::Event::ACTIVE_DESCENDANT_CHANGED:
+    case ui::AXEventGenerator::Event::CHILDREN_CHANGED:
+    case ui::AXEventGenerator::Event::COLLAPSED:
+    case ui::AXEventGenerator::Event::DESCRIPTION_CHANGED:
+    case ui::AXEventGenerator::Event::DOCUMENT_TITLE_CHANGED:
+    case ui::AXEventGenerator::Event::EXPANDED:
+    case ui::AXEventGenerator::Event::INVALID_STATUS_CHANGED:
+    case ui::AXEventGenerator::Event::LIVE_REGION_CHANGED:
+    case ui::AXEventGenerator::Event::LIVE_REGION_CREATED:
+    case ui::AXEventGenerator::Event::LOAD_START:
+    case ui::AXEventGenerator::Event::MENU_ITEM_SELECTED:
+    case ui::AXEventGenerator::Event::NAME_CHANGED:
+    case ui::AXEventGenerator::Event::OTHER_ATTRIBUTE_CHANGED:
+    case ui::AXEventGenerator::Event::RELATED_NODE_CHANGED:
+    case ui::AXEventGenerator::Event::ROLE_CHANGED:
+    case ui::AXEventGenerator::Event::ROW_COUNT_CHANGED:
+    case ui::AXEventGenerator::Event::SELECTED_CHANGED:
+    case ui::AXEventGenerator::Event::SELECTED_CHILDREN_CHANGED:
+    case ui::AXEventGenerator::Event::STATE_CHANGED:
       // There are some notifications that aren't meaningful on Android.
       // It's okay to skip them.
       break;
@@ -380,7 +380,7 @@
 void BrowserAccessibilityManagerAndroid::OnAtomicUpdateFinished(
     ui::AXTree* tree,
     bool root_changed,
-    const std::vector<ui::AXTreeDelegate::Change>& changes) {
+    const std::vector<ui::AXTreeObserver::Change>& changes) {
   BrowserAccessibilityManager::OnAtomicUpdateFinished(
       tree, root_changed, changes);
 
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.h b/content/browser/accessibility/browser_accessibility_manager_android.h
index 745e810..b7bd705 100644
--- a/content/browser/accessibility/browser_accessibility_manager_android.h
+++ b/content/browser/accessibility/browser_accessibility_manager_android.h
@@ -84,7 +84,7 @@
   void FireFocusEvent(BrowserAccessibility* node) override;
   void FireBlinkEvent(ax::mojom::Event event_type,
                       BrowserAccessibility* node) override;
-  void FireGeneratedEvent(AXEventGenerator::Event event_type,
+  void FireGeneratedEvent(ui::AXEventGenerator::Event event_type,
                           BrowserAccessibility* node) override;
   gfx::Rect GetViewBounds() override;
 
@@ -108,11 +108,11 @@
                              int32_t* end_index);
 
  private:
-  // AXTreeDelegate overrides.
+  // AXTreeObserver overrides.
   void OnAtomicUpdateFinished(
       ui::AXTree* tree,
       bool root_changed,
-      const std::vector<ui::AXTreeDelegate::Change>& changes) override;
+      const std::vector<ui::AXTreeObserver::Change>& changes) override;
 
   bool UseRootScrollOffsetsWhenComputingBounds() override;
 
diff --git a/content/browser/accessibility/browser_accessibility_manager_auralinux.cc b/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
index 74d1bd60..92d36f482 100644
--- a/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_auralinux.cc
@@ -113,31 +113,31 @@
 }
 
 void BrowserAccessibilityManagerAuraLinux::FireGeneratedEvent(
-    AXEventGenerator::Event event_type,
+    ui::AXEventGenerator::Event event_type,
     BrowserAccessibility* node) {
   BrowserAccessibilityManager::FireGeneratedEvent(event_type, node);
 
   switch (event_type) {
-    case Event::CHECKED_STATE_CHANGED:
+    case ui::AXEventGenerator::Event::CHECKED_STATE_CHANGED:
       FireEvent(node, ax::mojom::Event::kCheckedStateChanged);
       break;
-    case Event::COLLAPSED:
+    case ui::AXEventGenerator::Event::COLLAPSED:
       FireExpandedEvent(node, false);
       break;
-    case Event::EXPANDED:
+    case ui::AXEventGenerator::Event::EXPANDED:
       FireExpandedEvent(node, true);
       break;
-    case Event::LOAD_COMPLETE:
+    case ui::AXEventGenerator::Event::LOAD_COMPLETE:
       FireLoadingEvent(node, false);
       break;
-    case Event::LOAD_START:
+    case ui::AXEventGenerator::Event::LOAD_START:
       FireLoadingEvent(node, true);
       break;
-    case Event::MENU_ITEM_SELECTED:
-    case Event::SELECTED_CHANGED:
+    case ui::AXEventGenerator::Event::MENU_ITEM_SELECTED:
+    case ui::AXEventGenerator::Event::SELECTED_CHANGED:
       FireSelectedEvent(node);
       break;
-    case Event::VALUE_CHANGED:
+    case ui::AXEventGenerator::Event::VALUE_CHANGED:
       FireEvent(node, ax::mojom::Event::kValueChanged);
       break;
     default:
@@ -149,7 +149,7 @@
 void BrowserAccessibilityManagerAuraLinux::OnAtomicUpdateFinished(
     ui::AXTree* tree,
     bool root_changed,
-    const std::vector<ui::AXTreeDelegate::Change>& changes) {
+    const std::vector<ui::AXTreeObserver::Change>& changes) {
   BrowserAccessibilityManager::OnAtomicUpdateFinished(tree, root_changed,
                                                       changes);
 
diff --git a/content/browser/accessibility/browser_accessibility_manager_auralinux.h b/content/browser/accessibility/browser_accessibility_manager_auralinux.h
index a6e8579..29ce37d 100644
--- a/content/browser/accessibility/browser_accessibility_manager_auralinux.h
+++ b/content/browser/accessibility/browser_accessibility_manager_auralinux.h
@@ -31,7 +31,7 @@
   void FireFocusEvent(BrowserAccessibility* node) override;
   void FireBlinkEvent(ax::mojom::Event event_type,
                       BrowserAccessibility* node) override;
-  void FireGeneratedEvent(AXEventGenerator::Event event_type,
+  void FireGeneratedEvent(ui::AXEventGenerator::Event event_type,
                           BrowserAccessibility* node) override;
 
   void FireSelectedEvent(BrowserAccessibility* node);
@@ -41,11 +41,11 @@
   AtkObject* parent_object() { return parent_object_; }
 
  protected:
-  // AXTreeDelegate methods.
+  // AXTreeObserver methods.
   void OnAtomicUpdateFinished(
       ui::AXTree* tree,
       bool root_changed,
-      const std::vector<ui::AXTreeDelegate::Change>& changes) override;
+      const std::vector<ui::AXTreeObserver::Change>& changes) override;
 
  private:
   void FireEvent(BrowserAccessibility* node, ax::mojom::Event event);
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.h b/content/browser/accessibility/browser_accessibility_manager_mac.h
index 72ac6644..31a11ed 100644
--- a/content/browser/accessibility/browser_accessibility_manager_mac.h
+++ b/content/browser/accessibility/browser_accessibility_manager_mac.h
@@ -37,7 +37,7 @@
   void FireFocusEvent(BrowserAccessibility* node) override;
   void FireBlinkEvent(ax::mojom::Event event_type,
                       BrowserAccessibility* node) override;
-  void FireGeneratedEvent(AXEventGenerator::Event event_type,
+  void FireGeneratedEvent(ui::AXEventGenerator::Event event_type,
                           BrowserAccessibility* node) override;
 
   void OnAccessibilityEvents(
@@ -50,7 +50,7 @@
   void FireNativeMacNotification(NSString* mac_notification,
                                  BrowserAccessibility* node);
 
-  // AXTreeDelegate methods.
+  // AXTreeObserver methods.
   void OnAtomicUpdateFinished(ui::AXTree* tree,
                               bool root_changed,
                               const std::vector<Change>& changes) override;
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.mm b/content/browser/accessibility/browser_accessibility_manager_mac.mm
index 0b358c3..242a86dd 100644
--- a/content/browser/accessibility/browser_accessibility_manager_mac.mm
+++ b/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -193,7 +193,7 @@
 }
 
 void BrowserAccessibilityManagerMac::FireGeneratedEvent(
-    AXEventGenerator::Event event_type,
+    ui::AXEventGenerator::Event event_type,
     BrowserAccessibility* node) {
   BrowserAccessibilityManager::FireGeneratedEvent(event_type, node);
   if (!node->IsNative())
@@ -205,7 +205,7 @@
   // Refer to |AXObjectCache::postPlatformNotification| in WebKit source code.
   NSString* mac_notification = nullptr;
   switch (event_type) {
-    case Event::ACTIVE_DESCENDANT_CHANGED:
+    case ui::AXEventGenerator::Event::ACTIVE_DESCENDANT_CHANGED:
       if (node->GetRole() == ax::mojom::Role::kTree) {
         mac_notification = NSAccessibilitySelectedRowsChangedNotification;
       } else if (node->GetRole() == ax::mojom::Role::kTextFieldWithComboBox) {
@@ -220,7 +220,7 @@
         return;
       }
       break;
-    case Event::LOAD_COMPLETE:
+    case ui::AXEventGenerator::Event::LOAD_COMPLETE:
       // This notification should only be fired on the top document.
       // Iframes should use |ax::mojom::Event::kLayoutComplete| to signify that
       // they have finished loading.
@@ -230,17 +230,17 @@
         mac_notification = NSAccessibilityLayoutCompleteNotification;
       }
       break;
-    case Event::INVALID_STATUS_CHANGED:
+    case ui::AXEventGenerator::Event::INVALID_STATUS_CHANGED:
       mac_notification = NSAccessibilityInvalidStatusChangedNotification;
       break;
-    case Event::SELECTED_CHILDREN_CHANGED:
+    case ui::AXEventGenerator::Event::SELECTED_CHILDREN_CHANGED:
       if (ui::IsTableLike(node->GetRole())) {
         mac_notification = NSAccessibilitySelectedRowsChangedNotification;
       } else {
         mac_notification = NSAccessibilitySelectedChildrenChangedNotification;
       }
       break;
-    case Event::DOCUMENT_SELECTION_CHANGED: {
+    case ui::AXEventGenerator::Event::DOCUMENT_SELECTION_CHANGED: {
       mac_notification = NSAccessibilitySelectedTextChangedNotification;
       // WebKit fires a notification both on the focused object and the page
       // root.
@@ -274,10 +274,10 @@
       }
       break;
     }
-    case Event::CHECKED_STATE_CHANGED:
+    case ui::AXEventGenerator::Event::CHECKED_STATE_CHANGED:
       mac_notification = NSAccessibilityValueChangedNotification;
       break;
-    case Event::VALUE_CHANGED:
+    case ui::AXEventGenerator::Event::VALUE_CHANGED:
       mac_notification = NSAccessibilityValueChangedNotification;
       if (base::mac::IsAtLeastOS10_11() && !text_edits_.empty()) {
         base::string16 deleted_text;
@@ -304,17 +304,18 @@
         return;
       }
       break;
-    case Event::LIVE_REGION_CREATED:
+    case ui::AXEventGenerator::Event::LIVE_REGION_CREATED:
       mac_notification = NSAccessibilityLiveRegionCreatedNotification;
       break;
-    case Event::ALERT:
+    case ui::AXEventGenerator::Event::ALERT:
       NSAccessibilityPostNotification(
           native_node, NSAccessibilityLiveRegionCreatedNotification);
       // Voiceover requires a live region changed notification to actually
       // announce the live region.
-      FireGeneratedEvent(Event::LIVE_REGION_CHANGED, node);
+      FireGeneratedEvent(ui::AXEventGenerator::Event::LIVE_REGION_CHANGED,
+                         node);
       return;
-    case Event::LIVE_REGION_CHANGED: {
+    case ui::AXEventGenerator::Event::LIVE_REGION_CHANGED: {
       // Voiceover seems to drop live region changed notifications if they come
       // too soon after a live region created notification.
       // TODO(nektar): Limit the number of changed notifications as well.
@@ -352,10 +353,10 @@
           base::TimeDelta::FromMilliseconds(kLiveRegionChangeIntervalMS));
       return;
     }
-    case Event::ROW_COUNT_CHANGED:
+    case ui::AXEventGenerator::Event::ROW_COUNT_CHANGED:
       mac_notification = NSAccessibilityRowCountChangedNotification;
       break;
-    case Event::EXPANDED:
+    case ui::AXEventGenerator::Event::EXPANDED:
       if (node->GetRole() == ax::mojom::Role::kRow ||
           node->GetRole() == ax::mojom::Role::kTreeItem) {
         mac_notification = NSAccessibilityRowExpandedNotification;
@@ -363,7 +364,7 @@
         mac_notification = NSAccessibilityExpandedChanged;
       }
       break;
-    case Event::COLLAPSED:
+    case ui::AXEventGenerator::Event::COLLAPSED:
       if (node->GetRole() == ax::mojom::Role::kRow ||
           node->GetRole() == ax::mojom::Role::kTreeItem) {
         mac_notification = NSAccessibilityRowCollapsedNotification;
@@ -371,21 +372,21 @@
         mac_notification = NSAccessibilityExpandedChanged;
       }
       break;
-    case Event::MENU_ITEM_SELECTED:
+    case ui::AXEventGenerator::Event::MENU_ITEM_SELECTED:
       mac_notification = NSAccessibilityMenuItemSelectedNotification;
       break;
-    case Event::CHILDREN_CHANGED:
-    case Event::DESCRIPTION_CHANGED:
-    case Event::DOCUMENT_TITLE_CHANGED:
-    case Event::LIVE_REGION_NODE_CHANGED:
-    case Event::LOAD_START:
-    case Event::NAME_CHANGED:
-    case Event::OTHER_ATTRIBUTE_CHANGED:
-    case Event::RELATED_NODE_CHANGED:
-    case Event::ROLE_CHANGED:
-    case Event::SCROLL_POSITION_CHANGED:
-    case Event::SELECTED_CHANGED:
-    case Event::STATE_CHANGED:
+    case ui::AXEventGenerator::Event::CHILDREN_CHANGED:
+    case ui::AXEventGenerator::Event::DESCRIPTION_CHANGED:
+    case ui::AXEventGenerator::Event::DOCUMENT_TITLE_CHANGED:
+    case ui::AXEventGenerator::Event::LIVE_REGION_NODE_CHANGED:
+    case ui::AXEventGenerator::Event::LOAD_START:
+    case ui::AXEventGenerator::Event::NAME_CHANGED:
+    case ui::AXEventGenerator::Event::OTHER_ATTRIBUTE_CHANGED:
+    case ui::AXEventGenerator::Event::RELATED_NODE_CHANGED:
+    case ui::AXEventGenerator::Event::ROLE_CHANGED:
+    case ui::AXEventGenerator::Event::SCROLL_POSITION_CHANGED:
+    case ui::AXEventGenerator::Event::SELECTED_CHANGED:
+    case ui::AXEventGenerator::Event::STATE_CHANGED:
       // There are some notifications that aren't meaningful on Mac.
       // It's okay to skip them.
       return;
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.cc b/content/browser/accessibility/browser_accessibility_manager_win.cc
index d35cc31..3b6ddfe1 100644
--- a/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -104,12 +104,13 @@
 }
 
 void BrowserAccessibilityManagerWin::FireGeneratedEvent(
-    AXEventGenerator::Event event_type,
+    ui::AXEventGenerator::Event event_type,
     BrowserAccessibility* node) {
   BrowserAccessibilityManager::FireGeneratedEvent(event_type, node);
   bool can_fire_events = CanFireEvents();
 
-  if (event_type == Event::LOAD_COMPLETE && can_fire_events)
+  if (event_type == ui::AXEventGenerator::Event::LOAD_COMPLETE &&
+      can_fire_events)
     load_complete_pending_ = false;
 
   if (load_complete_pending_ && can_fire_events && GetRoot()) {
@@ -118,22 +119,22 @@
   }
 
   if (!can_fire_events && !load_complete_pending_ &&
-      event_type == Event::LOAD_COMPLETE && GetRoot() &&
+      event_type == ui::AXEventGenerator::Event::LOAD_COMPLETE && GetRoot() &&
       !GetRoot()->IsOffscreen() && GetRoot()->PlatformChildCount() > 0) {
     load_complete_pending_ = true;
   }
 
   switch (event_type) {
-    case Event::ACTIVE_DESCENDANT_CHANGED:
+    case ui::AXEventGenerator::Event::ACTIVE_DESCENDANT_CHANGED:
       FireWinAccessibilityEvent(IA2_EVENT_ACTIVE_DESCENDANT_CHANGED, node);
       break;
-    case Event::ALERT:
+    case ui::AXEventGenerator::Event::ALERT:
       FireWinAccessibilityEvent(EVENT_SYSTEM_ALERT, node);
       break;
-    case Event::CHILDREN_CHANGED:
+    case ui::AXEventGenerator::Event::CHILDREN_CHANGED:
       FireWinAccessibilityEvent(EVENT_OBJECT_REORDER, node);
       break;
-    case Event::LIVE_REGION_CHANGED:
+    case ui::AXEventGenerator::Event::LIVE_REGION_CHANGED:
       // This event is redundant with the IA2_EVENT_TEXT_INSERTED events;
       // however, JAWS 2018 and earlier do not process the text inserted
       // events when "virtual cursor mode" is turned off (Insert+Z).
@@ -147,16 +148,16 @@
       // EVENT_OBJECT_SHOW).
       FireWinAccessibilityEvent(EVENT_OBJECT_LIVEREGIONCHANGED, node);
       break;
-    case Event::LOAD_COMPLETE:
+    case ui::AXEventGenerator::Event::LOAD_COMPLETE:
       FireWinAccessibilityEvent(IA2_EVENT_DOCUMENT_LOAD_COMPLETE, node);
       break;
-    case Event::SCROLL_POSITION_CHANGED:
+    case ui::AXEventGenerator::Event::SCROLL_POSITION_CHANGED:
       FireWinAccessibilityEvent(EVENT_SYSTEM_SCROLLINGEND, node);
       break;
-    case Event::SELECTED_CHILDREN_CHANGED:
+    case ui::AXEventGenerator::Event::SELECTED_CHILDREN_CHANGED:
       FireWinAccessibilityEvent(EVENT_OBJECT_SELECTIONWITHIN, node);
       break;
-    case Event::DOCUMENT_SELECTION_CHANGED: {
+    case ui::AXEventGenerator::Event::DOCUMENT_SELECTION_CHANGED: {
       // Fire the event on the object where the focus of the selection is.
       int32_t focus_id = GetTreeData().sel_focus_object_id;
       BrowserAccessibility* focus_object = GetFromID(focus_id);
@@ -164,24 +165,24 @@
         FireWinAccessibilityEvent(IA2_EVENT_TEXT_CARET_MOVED, focus_object);
       break;
     }
-    case Event::CHECKED_STATE_CHANGED:
-    case Event::COLLAPSED:
-    case Event::DESCRIPTION_CHANGED:
-    case Event::DOCUMENT_TITLE_CHANGED:
-    case Event::EXPANDED:
-    case Event::INVALID_STATUS_CHANGED:
-    case Event::LIVE_REGION_CREATED:
-    case Event::LIVE_REGION_NODE_CHANGED:
-    case Event::LOAD_START:
-    case Event::MENU_ITEM_SELECTED:
-    case Event::NAME_CHANGED:
-    case Event::OTHER_ATTRIBUTE_CHANGED:
-    case Event::RELATED_NODE_CHANGED:
-    case Event::ROLE_CHANGED:
-    case Event::ROW_COUNT_CHANGED:
-    case Event::SELECTED_CHANGED:
-    case Event::STATE_CHANGED:
-    case Event::VALUE_CHANGED:
+    case ui::AXEventGenerator::Event::CHECKED_STATE_CHANGED:
+    case ui::AXEventGenerator::Event::COLLAPSED:
+    case ui::AXEventGenerator::Event::DESCRIPTION_CHANGED:
+    case ui::AXEventGenerator::Event::DOCUMENT_TITLE_CHANGED:
+    case ui::AXEventGenerator::Event::EXPANDED:
+    case ui::AXEventGenerator::Event::INVALID_STATUS_CHANGED:
+    case ui::AXEventGenerator::Event::LIVE_REGION_CREATED:
+    case ui::AXEventGenerator::Event::LIVE_REGION_NODE_CHANGED:
+    case ui::AXEventGenerator::Event::LOAD_START:
+    case ui::AXEventGenerator::Event::MENU_ITEM_SELECTED:
+    case ui::AXEventGenerator::Event::NAME_CHANGED:
+    case ui::AXEventGenerator::Event::OTHER_ATTRIBUTE_CHANGED:
+    case ui::AXEventGenerator::Event::RELATED_NODE_CHANGED:
+    case ui::AXEventGenerator::Event::ROLE_CHANGED:
+    case ui::AXEventGenerator::Event::ROW_COUNT_CHANGED:
+    case ui::AXEventGenerator::Event::SELECTED_CHANGED:
+    case ui::AXEventGenerator::Event::STATE_CHANGED:
+    case ui::AXEventGenerator::Event::VALUE_CHANGED:
       // There are some notifications that aren't meaningful on Windows.
       // It's okay to skip them.
       break;
@@ -246,7 +247,7 @@
 void BrowserAccessibilityManagerWin::OnAtomicUpdateFinished(
     ui::AXTree* tree,
     bool root_changed,
-    const std::vector<ui::AXTreeDelegate::Change>& changes) {
+    const std::vector<ui::AXTreeObserver::Change>& changes) {
   BrowserAccessibilityManager::OnAtomicUpdateFinished(
       tree, root_changed, changes);
 
@@ -290,7 +291,7 @@
     BrowserAccessibility* obj = GetFromAXNode(changed_node);
     if (obj && obj->IsNative()) {
       ToBrowserAccessibilityWin(obj)->GetCOM()->UpdateStep3FireEvents(
-          change.type == AXTreeDelegate::SUBTREE_CREATED);
+          change.type == AXTreeObserver::SUBTREE_CREATED);
     }
   }
 }
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.h b/content/browser/accessibility/browser_accessibility_manager_win.h
index 88fd18b4..e3a887e 100644
--- a/content/browser/accessibility/browser_accessibility_manager_win.h
+++ b/content/browser/accessibility/browser_accessibility_manager_win.h
@@ -41,7 +41,7 @@
   void FireFocusEvent(BrowserAccessibility* node) override;
   void FireBlinkEvent(ax::mojom::Event event_type,
                       BrowserAccessibility* node) override;
-  void FireGeneratedEvent(AXEventGenerator::Event event_type,
+  void FireGeneratedEvent(ui::AXEventGenerator::Event event_type,
                           BrowserAccessibility* node) override;
 
   void FireWinAccessibilityEvent(LONG win_event, BrowserAccessibility* node);
@@ -55,11 +55,11 @@
   void OnAccessibleHwndDeleted();
 
  protected:
-  // AXTreeDelegate methods.
+  // AXTreeObserver methods.
   void OnAtomicUpdateFinished(
       ui::AXTree* tree,
       bool root_changed,
-      const std::vector<ui::AXTreeDelegate::Change>& changes) override;
+      const std::vector<ui::AXTreeObserver::Change>& changes) override;
 
  private:
   // Give BrowserAccessibilityManager::Create access to our constructor.
diff --git a/content/browser/android/java/gin_java_bridge_dispatcher_host.cc b/content/browser/android/java/gin_java_bridge_dispatcher_host.cc
index 4d6da9c..d98096bb 100644
--- a/content/browser/android/java/gin_java_bridge_dispatcher_host.cc
+++ b/content/browser/android/java/gin_java_bridge_dispatcher_host.cc
@@ -79,11 +79,6 @@
     filter->RemoveHost(this);
 }
 
-void GinJavaBridgeDispatcherHost::RenderProcessGone(
-    base::TerminationStatus status) {
-  GinJavaBridgeMessageFilter::RemoveFilter(this);
-}
-
 void GinJavaBridgeDispatcherHost::RenderViewHostChanged(
     RenderViewHost* old_host,
     RenderViewHost* new_host) {
diff --git a/content/browser/android/java/gin_java_bridge_dispatcher_host.h b/content/browser/android/java/gin_java_bridge_dispatcher_host.h
index db327b40..6b363ef 100644
--- a/content/browser/android/java/gin_java_bridge_dispatcher_host.h
+++ b/content/browser/android/java/gin_java_bridge_dispatcher_host.h
@@ -51,7 +51,6 @@
   void RenderFrameCreated(RenderFrameHost* render_frame_host) override;
   void DocumentAvailableInMainFrame() override;
   void WebContentsDestroyed() override;
-  void RenderProcessGone(base::TerminationStatus status) override;
   void RenderViewHostChanged(RenderViewHost* old_host,
                              RenderViewHost* new_host) override;
 
diff --git a/content/browser/android/java/gin_java_bridge_message_filter.cc b/content/browser/android/java/gin_java_bridge_message_filter.cc
index 2a38722..f4ce393d 100644
--- a/content/browser/android/java/gin_java_bridge_message_filter.cc
+++ b/content/browser/android/java/gin_java_bridge_message_filter.cc
@@ -188,11 +188,4 @@
     host->OnObjectWrapperDeleted(current_routing_id_, object_id);
 }
 
-// static
-void GinJavaBridgeMessageFilter::RemoveFilter(
-    GinJavaBridgeDispatcherHost* host) {
-  RenderProcessHost* rph = host->web_contents()->GetMainFrame()->GetProcess();
-  rph->RemoveUserData(kGinJavaBridgeMessageFilterKey);
-}
-
 }  // namespace content
diff --git a/content/browser/android/java/gin_java_bridge_message_filter.h b/content/browser/android/java/gin_java_bridge_message_filter.h
index c15bc707..1847f24 100644
--- a/content/browser/android/java/gin_java_bridge_message_filter.h
+++ b/content/browser/android/java/gin_java_bridge_message_filter.h
@@ -52,11 +52,6 @@
   static scoped_refptr<GinJavaBridgeMessageFilter> FromHost(
       GinJavaBridgeDispatcherHost* host, bool create_if_not_exists);
 
-  // Removes the filter, which triggers its deletion. Needs to be called when
-  // the corresponding RenderProcessHost cleans itself up, e.g. on renderer
-  // process exit.
-  static void RemoveFilter(GinJavaBridgeDispatcherHost* host);
-
  private:
   friend class BrowserThread;
   friend class base::DeleteHelper<GinJavaBridgeMessageFilter>;
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index e7ad451..f88b5d3 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -863,8 +863,9 @@
   }
   ResetFeaturePolicy();
 
-  ax_tree_id_ = ui::AXTreeIDRegistry::GetInstance()->GetOrCreateAXTreeID(
-      GetProcess()->GetID(), routing_id_);
+  ui::AXTreeIDRegistry::GetInstance()->SetFrameIDForAXTreeID(
+      ui::AXTreeIDRegistry::FrameID(GetProcess()->GetID(), routing_id_),
+      GetAXTreeID());
 
   // Content-Security-Policy: The CSP source 'self' is usually the origin of the
   // current document, set by SetLastCommittedOrigin(). However, before a new
@@ -971,8 +972,6 @@
   // the corresponding RenderViewHost if it is no longer needed.
   frame_tree_->ReleaseRenderViewHostRef(render_view_host_);
 
-  ui::AXTreeIDRegistry::GetInstance()->RemoveAXTreeID(ax_tree_id_);
-
   // If another frame is waiting for a beforeunload ACK from this frame,
   // simulate it now.
   RenderFrameHostImpl* beforeunload_initiator = GetBeforeUnloadInitiator();
@@ -990,7 +989,7 @@
 }
 
 ui::AXTreeID RenderFrameHostImpl::GetAXTreeID() {
-  return ax_tree_id_;
+  return ax_tree_id();
 }
 
 const base::UnguessableToken& RenderFrameHostImpl::GetOverlayRoutingToken() {
@@ -1572,6 +1571,14 @@
   }
 }
 
+void RenderFrameHostImpl::PerformAction(const ui::AXActionData& data) {
+  AccessibilityPerformAction(data);
+}
+
+bool RenderFrameHostImpl::RequiresPerformActionPointInPixels() const {
+  return true;
+}
+
 bool RenderFrameHostImpl::SchemeShouldBypassCSP(
     const base::StringPiece& scheme) {
   // Blink uses its SchemeRegistry to check if a scheme should be bypassed.
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 0c56561..8bedc92 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -81,6 +81,7 @@
 #include "third_party/blink/public/web/commit_result.mojom.h"
 #include "third_party/blink/public/web/web_text_direction.h"
 #include "third_party/blink/public/web/web_tree_scope_type.h"
+#include "ui/accessibility/ax_host_delegate.h"
 #include "ui/accessibility/ax_mode.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/mojo/window_open_disposition.mojom.h"
@@ -166,7 +167,8 @@
       public BrowserAccessibilityDelegate,
       public SiteInstanceImpl::Observer,
       public service_manager::mojom::InterfaceProvider,
-      public CSPContext {
+      public CSPContext,
+      public ui::AXHostDelegate {
  public:
   using AXTreeSnapshotCallback =
       base::OnceCallback<void(const ui::AXTreeUpdate&)>;
@@ -294,6 +296,10 @@
       GURL* blocked_url,
       SourceLocation* source_location) const override;
 
+  // ui::AXHostDelegate:
+  void PerformAction(const ui::AXActionData& data) override;
+  bool RequiresPerformActionPointInPixels() const override;
+
   mojom::FrameInputHandler* GetFrameInputHandler();
 
   viz::mojom::InputTargetClient* GetInputTargetClient() {
@@ -1527,9 +1533,6 @@
   // The last AXContentTreeData for this frame received from the RenderFrame.
   AXContentTreeData ax_content_tree_data_;
 
-  // The AX tree ID of this frame.
-  ui::AXTreeID ax_tree_id_ = ui::AXTreeIDUnknown();
-
   // The AX tree ID of the embedder, if this is a browser plugin guest.
   ui::AXTreeID browser_plugin_embedder_ax_tree_id_;
 
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc
index 64ddda3..93a6eb8 100644
--- a/content/browser/site_per_process_hit_test_browsertest.cc
+++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -5219,6 +5219,101 @@
   NestedSurfaceHitTestTestHelper(shell(), embedded_test_server());
 }
 
+// Verify RenderWidgetHostInputEventRouter can successfully hit test
+// a MouseEvent and route it to a clipped OOPIF.
+IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, HitTestClippedFrame) {
+  GURL main_url(embedded_test_server()->GetURL(
+      "/frame_tree/page_with_positioned_clipped_iframe.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetFrameTree()
+                            ->root();
+  ASSERT_EQ(1U, root->child_count());
+
+  RenderWidgetHostViewBase* rwhv_root = static_cast<RenderWidgetHostViewBase*>(
+      root->current_frame_host()->GetRenderWidgetHost()->GetView());
+  RenderWidgetHostInputEventRouter* router =
+      web_contents()->GetInputEventRouter();
+
+  EXPECT_EQ(
+      " Site A ------------ proxies for B\n"
+      "   +--Site B ------- proxies for A\n"
+      "Where A = http://127.0.0.1/\n"
+      "      B = http://baz.com/",
+      DepictFrameTree(root));
+
+  FrameTreeNode* child_node = root->child_at(0);
+  RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
+      child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
+  WaitForHitTestDataOrChildSurfaceReady(child_node->current_frame_host());
+
+  RenderWidgetHostMouseEventMonitor root_monitor(
+      root->current_frame_host()->GetRenderWidgetHost());
+  RenderWidgetHostMouseEventMonitor child_monitor(
+      child_node->current_frame_host()->GetRenderWidgetHost());
+
+  gfx::PointF point_in_root(25, 25);
+  gfx::PointF point_in_child(100, 100);
+
+  blink::WebMouseEvent down_event(
+      blink::WebInputEvent::kMouseDown, blink::WebInputEvent::kNoModifiers,
+      blink::WebInputEvent::GetStaticTimeStampForTests());
+  down_event.button = blink::WebPointerProperties::Button::kLeft;
+  down_event.click_count = 1;
+  SetWebEventPositions(&down_event, point_in_root, rwhv_root);
+
+  blink::WebMouseEvent up_event(
+      blink::WebInputEvent::kMouseUp, blink::WebInputEvent::kNoModifiers,
+      blink::WebInputEvent::GetStaticTimeStampForTests());
+  up_event.button = blink::WebPointerProperties::Button::kLeft;
+  up_event.click_count = 1;
+  SetWebEventPositions(&up_event, point_in_root, rwhv_root);
+
+  // Target at root.
+  RouteMouseEventAndWaitUntilDispatch(router, rwhv_root, rwhv_root,
+                                      &down_event);
+  EXPECT_TRUE(root_monitor.EventWasReceived());
+  EXPECT_FALSE(child_monitor.EventWasReceived());
+  EXPECT_NEAR(25, root_monitor.event().PositionInWidget().x, kHitTestTolerance);
+  EXPECT_NEAR(25, root_monitor.event().PositionInWidget().y, kHitTestTolerance);
+
+  root_monitor.ResetEventReceived();
+  child_monitor.ResetEventReceived();
+  RouteMouseEventAndWaitUntilDispatch(router, rwhv_root, rwhv_root, &up_event);
+  EXPECT_TRUE(root_monitor.EventWasReceived());
+  EXPECT_FALSE(child_monitor.EventWasReceived());
+  EXPECT_NEAR(25, root_monitor.event().PositionInWidget().x, kHitTestTolerance);
+  EXPECT_NEAR(25, root_monitor.event().PositionInWidget().y, kHitTestTolerance);
+
+  // Target at child.
+  root_monitor.ResetEventReceived();
+  child_monitor.ResetEventReceived();
+  SetWebEventPositions(&down_event, point_in_child, rwhv_root);
+  SetWebEventPositions(&up_event, point_in_child, rwhv_root);
+  RouteMouseEventAndWaitUntilDispatch(router, rwhv_root, rwhv_child,
+                                      &down_event);
+  // In surface layer hit testing, we should not query client asynchronously.
+  EXPECT_FALSE(root_monitor.EventWasReceived());
+  EXPECT_TRUE(child_monitor.EventWasReceived());
+  EXPECT_NEAR(90, child_monitor.event().PositionInWidget().x,
+              kHitTestTolerance);
+  EXPECT_NEAR(100, child_monitor.event().PositionInWidget().y,
+              kHitTestTolerance);
+
+  root_monitor.ResetEventReceived();
+  child_monitor.ResetEventReceived();
+  RouteMouseEventAndWaitUntilDispatch(router, rwhv_root, rwhv_child, &up_event);
+  // We should reuse the target for mouse up.
+  EXPECT_FALSE(root_monitor.EventWasReceived());
+  EXPECT_TRUE(child_monitor.EventWasReceived());
+  EXPECT_TRUE(child_monitor.EventWasReceived());
+  EXPECT_NEAR(90, child_monitor.event().PositionInWidget().x,
+              kHitTestTolerance);
+  EXPECT_NEAR(100, child_monitor.event().PositionInWidget().y,
+              kHitTestTolerance);
+}
+
 // Verify InputTargetClient works within an OOPIF process.
 IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest, HitTestNestedFrames) {
   GURL main_url(embedded_test_server()->GetURL(
diff --git a/content/browser/speech/mock_tts_controller.cc b/content/browser/speech/mock_tts_controller.cc
index 76c8c15d..db1f17e9 100644
--- a/content/browser/speech/mock_tts_controller.cc
+++ b/content/browser/speech/mock_tts_controller.cc
@@ -55,6 +55,10 @@
 
   TtsEngineDelegate* GetTtsEngineDelegate() override { return nullptr; }
 
+  void SetTtsPlatform(TtsPlatform* tts_platform) override{};
+
+  int QueueSize() override { return 0; }
+
  private:
   friend struct base::DefaultSingletonTraits<MockTtsController>;
   DISALLOW_COPY_AND_ASSIGN(MockTtsController);
diff --git a/content/browser/speech/tts_controller_impl.cc b/content/browser/speech/tts_controller_impl.cc
index 47221ab5..bc25e9c 100644
--- a/content/browser/speech/tts_controller_impl.cc
+++ b/content/browser/speech/tts_controller_impl.cc
@@ -20,6 +20,9 @@
 
 namespace content {
 
+// A value to be used to indicate that there is no char index available.
+const int kInvalidCharIndex = -1;
+
 // Returns true if this event type is one that indicates an utterance
 // is finished and can be destroyed.
 bool IsFinalTtsEventType(TtsEventType event_type) {
@@ -95,6 +98,26 @@
   return TtsControllerImpl::GetInstance();
 }
 
+// IMPORTANT!
+// These values are written to logs.  Do not renumber or delete
+// existing items; add new entries to the end of the list.
+enum class UMATextToSpeechEvent {
+  START = 0,
+  END = 1,
+  WORD = 2,
+  SENTENCE = 3,
+  MARKER = 4,
+  INTERRUPTED = 5,
+  CANCELLED = 6,
+  SPEECH_ERROR = 7,
+  PAUSE = 8,
+  RESUME = 9,
+
+  // This must always be the last enum. It's okay for its value to
+  // increase, but none of the other enum values may change.
+  COUNT
+};
+
 //
 // TtsControllerImpl
 //
@@ -105,106 +128,396 @@
 }
 
 TtsControllerImpl::TtsControllerImpl()
-    : delegate_(GetContentClient()->browser()->GetTtsControllerDelegate()) {}
+    : delegate_(nullptr),
+      current_utterance_(nullptr),
+      paused_(false),
+      tts_platform_(nullptr) {}
 
-TtsControllerImpl::~TtsControllerImpl() {}
+TtsControllerImpl::~TtsControllerImpl() {
+  if (current_utterance_) {
+    current_utterance_->Finish();
+    delete current_utterance_;
+  }
+
+  // Clear any queued utterances too.
+  ClearUtteranceQueue(false);  // Don't sent events.
+}
 
 void TtsControllerImpl::SpeakOrEnqueue(Utterance* utterance) {
-  if (!delegate_)
+  // If we're paused and we get an utterance that can't be queued,
+  // flush the queue but stay in the paused state.
+  if (paused_ && !utterance->can_enqueue()) {
+    utterance_queue_.push(utterance);
+    Stop();
+    paused_ = true;
     return;
+  }
 
-  delegate_->SpeakOrEnqueue(utterance);
+  if (paused_ || (IsSpeaking() && utterance->can_enqueue())) {
+    utterance_queue_.push(utterance);
+  } else {
+    Stop();
+    SpeakNow(utterance);
+  }
 }
 
 void TtsControllerImpl::Stop() {
-  if (!delegate_)
-    return;
+  base::RecordAction(base::UserMetricsAction("TextToSpeech.Stop"));
 
-  delegate_->Stop();
+  paused_ = false;
+  if (current_utterance_ && !current_utterance_->engine_id().empty()) {
+    if (GetTtsControllerDelegate()->GetTtsEngineDelegate())
+      GetTtsControllerDelegate()->GetTtsEngineDelegate()->Stop(
+          current_utterance_);
+  } else {
+    GetTtsPlatform()->ClearError();
+    GetTtsPlatform()->StopSpeaking();
+  }
+
+  if (current_utterance_)
+    current_utterance_->OnTtsEvent(TTS_EVENT_INTERRUPTED, kInvalidCharIndex,
+                                   std::string());
+  FinishCurrentUtterance();
+  ClearUtteranceQueue(true);  // Send events.
 }
 
 void TtsControllerImpl::Pause() {
-  if (!delegate_)
-    return;
+  base::RecordAction(base::UserMetricsAction("TextToSpeech.Pause"));
 
-  delegate_->Pause();
+  paused_ = true;
+  if (current_utterance_ && !current_utterance_->engine_id().empty()) {
+    if (GetTtsControllerDelegate()->GetTtsEngineDelegate())
+      GetTtsControllerDelegate()->GetTtsEngineDelegate()->Pause(
+          current_utterance_);
+  } else if (current_utterance_) {
+    GetTtsPlatform()->ClearError();
+    GetTtsPlatform()->Pause();
+  }
 }
 
 void TtsControllerImpl::Resume() {
-  if (!delegate_)
-    return;
+  base::RecordAction(base::UserMetricsAction("TextToSpeech.Resume"));
 
-  delegate_->Resume();
+  paused_ = false;
+  if (current_utterance_ && !current_utterance_->engine_id().empty()) {
+    if (GetTtsControllerDelegate()->GetTtsEngineDelegate())
+      GetTtsControllerDelegate()->GetTtsEngineDelegate()->Resume(
+          current_utterance_);
+  } else if (current_utterance_) {
+    GetTtsPlatform()->ClearError();
+    GetTtsPlatform()->Resume();
+  } else {
+    SpeakNextUtterance();
+  }
 }
 
 void TtsControllerImpl::OnTtsEvent(int utterance_id,
                                    TtsEventType event_type,
                                    int char_index,
                                    const std::string& error_message) {
-  if (!delegate_)
+  // We may sometimes receive completion callbacks "late", after we've
+  // already finished the utterance (for example because another utterance
+  // interrupted or we got a call to Stop). This is normal and we can
+  // safely just ignore these events.
+  if (!current_utterance_ || utterance_id != current_utterance_->id()) {
     return;
+  }
 
-  delegate_->OnTtsEvent(utterance_id, event_type, char_index, error_message);
+  UMATextToSpeechEvent metric;
+  switch (event_type) {
+    case TTS_EVENT_START:
+      metric = UMATextToSpeechEvent::START;
+      break;
+    case TTS_EVENT_END:
+      metric = UMATextToSpeechEvent::END;
+      break;
+    case TTS_EVENT_WORD:
+      metric = UMATextToSpeechEvent::WORD;
+      break;
+    case TTS_EVENT_SENTENCE:
+      metric = UMATextToSpeechEvent::SENTENCE;
+      break;
+    case TTS_EVENT_MARKER:
+      metric = UMATextToSpeechEvent::MARKER;
+      break;
+    case TTS_EVENT_INTERRUPTED:
+      metric = UMATextToSpeechEvent::INTERRUPTED;
+      break;
+    case TTS_EVENT_CANCELLED:
+      metric = UMATextToSpeechEvent::CANCELLED;
+      break;
+    case TTS_EVENT_ERROR:
+      metric = UMATextToSpeechEvent::SPEECH_ERROR;
+      break;
+    case TTS_EVENT_PAUSE:
+      metric = UMATextToSpeechEvent::PAUSE;
+      break;
+    case TTS_EVENT_RESUME:
+      metric = UMATextToSpeechEvent::RESUME;
+      break;
+    default:
+      NOTREACHED();
+      return;
+  }
+  UMA_HISTOGRAM_ENUMERATION("TextToSpeech.Event", metric,
+                            UMATextToSpeechEvent::COUNT);
+
+  current_utterance_->OnTtsEvent(event_type, char_index, error_message);
+  if (current_utterance_->finished()) {
+    FinishCurrentUtterance();
+    SpeakNextUtterance();
+  }
 }
 
 void TtsControllerImpl::GetVoices(BrowserContext* browser_context,
                                   std::vector<VoiceData>* out_voices) {
-  if (!delegate_)
-    return;
+  TtsPlatform* tts_platform = GetTtsPlatform();
+  if (tts_platform) {
+    // Ensure we have all built-in voices loaded. This is a no-op if already
+    // loaded.
+    tts_platform->LoadBuiltInTtsEngine(browser_context);
+    if (tts_platform->PlatformImplAvailable())
+      tts_platform->GetVoices(out_voices);
+  }
 
-  delegate_->GetVoices(browser_context, out_voices);
+  if (browser_context && GetTtsControllerDelegate()->GetTtsEngineDelegate())
+    GetTtsControllerDelegate()->GetTtsEngineDelegate()->GetVoices(
+        browser_context, out_voices);
 }
 
 bool TtsControllerImpl::IsSpeaking() {
-  if (!delegate_)
-    return false;
-
-  return delegate_->IsSpeaking();
+  return current_utterance_ != nullptr || GetTtsPlatform()->IsSpeaking();
 }
 
 void TtsControllerImpl::VoicesChanged() {
-  if (!delegate_)
-    return;
-
-  delegate_->VoicesChanged();
+  // Existence of platform tts indicates explicit requests to tts. Since
+  // |VoicesChanged| can occur implicitly, only send if needed.
+  for (auto& delegate : voices_changed_delegates_)
+    delegate.OnVoicesChanged();
 }
 
 void TtsControllerImpl::AddVoicesChangedDelegate(
     VoicesChangedDelegate* delegate) {
-  if (!delegate_)
-    return;
-
-  delegate_->AddVoicesChangedDelegate(delegate);
+  voices_changed_delegates_.AddObserver(delegate);
 }
 
 void TtsControllerImpl::RemoveVoicesChangedDelegate(
     VoicesChangedDelegate* delegate) {
-  if (!delegate_)
-    return;
-
-  delegate_->RemoveVoicesChangedDelegate(delegate);
+  voices_changed_delegates_.RemoveObserver(delegate);
 }
 
 void TtsControllerImpl::RemoveUtteranceEventDelegate(
     UtteranceEventDelegate* delegate) {
-  if (!delegate_)
-    return;
+  // First clear any pending utterances with this delegate.
+  base::queue<Utterance*> old_queue = utterance_queue_;
+  utterance_queue_ = base::queue<Utterance*>();
+  while (!old_queue.empty()) {
+    Utterance* utterance = old_queue.front();
+    old_queue.pop();
+    if (utterance->event_delegate() != delegate)
+      utterance_queue_.push(utterance);
+    else
+      delete utterance;
+  }
 
-  delegate_->RemoveUtteranceEventDelegate(delegate);
+  if (current_utterance_ && current_utterance_->event_delegate() == delegate) {
+    current_utterance_->set_event_delegate(nullptr);
+    if (!current_utterance_->engine_id().empty()) {
+      if (GetTtsControllerDelegate()->GetTtsEngineDelegate())
+        GetTtsControllerDelegate()->GetTtsEngineDelegate()->Stop(
+            current_utterance_);
+    } else {
+      GetTtsPlatform()->ClearError();
+      GetTtsPlatform()->StopSpeaking();
+    }
+
+    FinishCurrentUtterance();
+    if (!paused_)
+      SpeakNextUtterance();
+  }
 }
 
 void TtsControllerImpl::SetTtsEngineDelegate(TtsEngineDelegate* delegate) {
-  if (!delegate_)
+  if (!GetTtsControllerDelegate())
     return;
 
-  delegate_->SetTtsEngineDelegate(delegate);
+  GetTtsControllerDelegate()->SetTtsEngineDelegate(delegate);
 }
 
 TtsEngineDelegate* TtsControllerImpl::GetTtsEngineDelegate() {
-  if (!delegate_)
+  if (!GetTtsControllerDelegate())
     return nullptr;
 
-  return delegate_->GetTtsEngineDelegate();
+  return GetTtsControllerDelegate()->GetTtsEngineDelegate();
+}
+
+void TtsControllerImpl::SetTtsPlatform(TtsPlatform* tts_platform) {
+  tts_platform_ = tts_platform;
+}
+
+int TtsControllerImpl::QueueSize() {
+  return static_cast<int>(utterance_queue_.size());
+}
+
+TtsPlatform* TtsControllerImpl::GetTtsPlatform() {
+  if (!tts_platform_)
+    tts_platform_ = TtsPlatform::GetInstance();
+  return tts_platform_;
+}
+
+void TtsControllerImpl::SpeakNow(Utterance* utterance) {
+  if (!GetTtsControllerDelegate())
+    return;
+
+  // Ensure we have all built-in voices loaded. This is a no-op if already
+  // loaded.
+  bool loaded_built_in =
+      GetTtsPlatform()->LoadBuiltInTtsEngine(utterance->browser_context());
+
+  // Get all available voices and try to find a matching voice.
+  std::vector<VoiceData> voices;
+  GetVoices(utterance->browser_context(), &voices);
+
+  // Get the best matching voice. If nothing matches, just set "native"
+  // to true because that might trigger deferred loading of native voices.
+  // TODO(katie): Move most of the GetMatchingVoice logic into content/ and
+  // use the TTS controller delegate to get chrome-specific info as needed.
+  int index = GetTtsControllerDelegate()->GetMatchingVoice(utterance, voices);
+  VoiceData voice;
+  if (index >= 0)
+    voice = voices[index];
+  else
+    voice.native = true;
+
+  UpdateUtteranceDefaults(utterance);
+
+  GetTtsPlatform()->WillSpeakUtteranceWithVoice(utterance, voice);
+
+  base::RecordAction(base::UserMetricsAction("TextToSpeech.Speak"));
+  UMA_HISTOGRAM_COUNTS_100000("TextToSpeech.Utterance.TextLength",
+                              utterance->text().size());
+  UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.FromExtensionAPI",
+                        !utterance->src_url().is_empty());
+  UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.HasVoiceName",
+                        !utterance->voice_name().empty());
+  UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.HasLang",
+                        !utterance->lang().empty());
+  UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.HasRate",
+                        utterance->continuous_parameters().rate != 1.0);
+  UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.HasPitch",
+                        utterance->continuous_parameters().pitch != 1.0);
+  UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.HasVolume",
+                        utterance->continuous_parameters().volume != 1.0);
+  UMA_HISTOGRAM_BOOLEAN("TextToSpeech.Utterance.Native", voice.native);
+
+  if (!voice.native) {
+#if !defined(OS_ANDROID)
+    DCHECK(!voice.engine_id.empty());
+    current_utterance_ = utterance;
+    utterance->set_engine_id(voice.engine_id);
+    if (GetTtsControllerDelegate()->GetTtsEngineDelegate())
+      GetTtsControllerDelegate()->GetTtsEngineDelegate()->Speak(utterance,
+                                                                voice);
+    bool sends_end_event =
+        voice.events.find(TTS_EVENT_END) != voice.events.end();
+    if (!sends_end_event) {
+      utterance->Finish();
+      delete utterance;
+      current_utterance_ = nullptr;
+      SpeakNextUtterance();
+    }
+#endif
+  } else {
+    // It's possible for certain platforms to send start events immediately
+    // during |speak|.
+    current_utterance_ = utterance;
+    GetTtsPlatform()->ClearError();
+    bool success = GetTtsPlatform()->Speak(utterance->id(), utterance->text(),
+                                           utterance->lang(), voice,
+                                           utterance->continuous_parameters());
+    if (!success)
+      current_utterance_ = nullptr;
+
+    // If the native voice wasn't able to process this speech, see if
+    // the browser has built-in TTS that isn't loaded yet.
+    if (!success && loaded_built_in) {
+      utterance_queue_.push(utterance);
+      return;
+    }
+
+    if (!success) {
+      utterance->OnTtsEvent(TTS_EVENT_ERROR, kInvalidCharIndex,
+                            GetTtsPlatform()->GetError());
+      delete utterance;
+      return;
+    }
+  }
+}
+
+void TtsControllerImpl::ClearUtteranceQueue(bool send_events) {
+  while (!utterance_queue_.empty()) {
+    Utterance* utterance = utterance_queue_.front();
+    utterance_queue_.pop();
+    if (send_events)
+      utterance->OnTtsEvent(TTS_EVENT_CANCELLED, kInvalidCharIndex,
+                            std::string());
+    else
+      utterance->Finish();
+    delete utterance;
+  }
+}
+
+void TtsControllerImpl::FinishCurrentUtterance() {
+  if (current_utterance_) {
+    if (!current_utterance_->finished())
+      current_utterance_->OnTtsEvent(TTS_EVENT_INTERRUPTED, kInvalidCharIndex,
+                                     std::string());
+    delete current_utterance_;
+    current_utterance_ = nullptr;
+  }
+}
+
+void TtsControllerImpl::SpeakNextUtterance() {
+  if (paused_)
+    return;
+
+  // Start speaking the next utterance in the queue.  Keep trying in case
+  // one fails but there are still more in the queue to try.
+  while (!utterance_queue_.empty() && !current_utterance_) {
+    Utterance* utterance = utterance_queue_.front();
+    utterance_queue_.pop();
+    SpeakNow(utterance);
+  }
+}
+
+void TtsControllerImpl::UpdateUtteranceDefaults(Utterance* utterance) {
+  double rate = utterance->continuous_parameters().rate;
+  double pitch = utterance->continuous_parameters().pitch;
+  double volume = utterance->continuous_parameters().volume;
+#if defined(OS_CHROMEOS)
+  GetTtsControllerDelegate()->UpdateUtteranceDefaultsFromPrefs(utterance, &rate,
+                                                               &pitch, &volume);
+#else
+  // Update pitch, rate and volume to defaults if not explicity set on
+  // this utterance.
+  if (rate == blink::kWebSpeechSynthesisDoublePrefNotSet)
+    rate = blink::kWebSpeechSynthesisDefaultTextToSpeechRate;
+  if (pitch == blink::kWebSpeechSynthesisDoublePrefNotSet)
+    pitch = blink::kWebSpeechSynthesisDefaultTextToSpeechPitch;
+  if (volume == blink::kWebSpeechSynthesisDoublePrefNotSet)
+    volume = blink::kWebSpeechSynthesisDefaultTextToSpeechVolume;
+#endif  // defined(OS_CHROMEOS)
+  utterance->set_continuous_parameters(rate, pitch, volume);
+}
+
+TtsControllerDelegate* TtsControllerImpl::GetTtsControllerDelegate() {
+  if (delegate_)
+    return delegate_;
+  if (GetContentClient() && GetContentClient()->browser()) {
+    delegate_ = GetContentClient()->browser()->GetTtsControllerDelegate();
+    return delegate_;
+  }
+  return nullptr;
 }
 
 }  // namespace content
diff --git a/content/browser/speech/tts_controller_impl.h b/content/browser/speech/tts_controller_impl.h
index 1bea0a9d..6675484 100644
--- a/content/browser/speech/tts_controller_impl.h
+++ b/content/browser/speech/tts_controller_impl.h
@@ -12,18 +12,26 @@
 
 #include "base/containers/queue.h"
 #include "base/gtest_prod_util.h"
+#include "base/json/json_reader.h"
 #include "base/macros.h"
 #include "base/memory/singleton.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/metrics/user_metrics.h"
+#include "base/observer_list.h"
+#include "base/values.h"
+#include "build/build_config.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/tts_controller.h"
 #include "content/public/browser/tts_controller_delegate.h"
+#include "content/public/browser/tts_platform.h"
+#include "third_party/blink/public/platform/web_speech_synthesis_constants.h"
 #include "url/gurl.h"
 
 namespace content {
 class BrowserContext;
 
-// Singleton class that manages text-to-speech for the TTS and TTS engine
-// extension APIs, maintaining a queue of pending utterances and keeping
+// Singleton class that manages text-to-speech for all TTS engines and
+// APIs, maintaining a queue of pending utterances and keeping
 // track of all state.
 class CONTENT_EXPORT TtsControllerImpl : public TtsController {
  public:
@@ -40,7 +48,7 @@
                   TtsEventType event_type,
                   int char_index,
                   const std::string& error_message) override;
-  void GetVoices(content::BrowserContext* browser_context,
+  void GetVoices(BrowserContext* browser_context,
                  std::vector<VoiceData>* out_voices) override;
   void VoicesChanged() override;
   void AddVoicesChangedDelegate(VoicesChangedDelegate* delegate) override;
@@ -49,6 +57,10 @@
   void SetTtsEngineDelegate(TtsEngineDelegate* delegate) override;
   TtsEngineDelegate* GetTtsEngineDelegate() override;
 
+  // Testing methods
+  void SetTtsPlatform(TtsPlatform* tts_platform) override;
+  int QueueSize() override;
+
  protected:
   TtsControllerImpl();
   ~TtsControllerImpl() override;
@@ -61,8 +73,48 @@
 
   friend struct base::DefaultSingletonTraits<TtsControllerImpl>;
 
+  // Get the platform TTS implementation (or injected mock).
+  TtsPlatform* GetTtsPlatform();
+
+  // Start speaking the given utterance. Will either take ownership of
+  // |utterance| or delete it if there's an error. Returns true on success.
+  void SpeakNow(Utterance* utterance);
+
+  // Clear the utterance queue. If send_events is true, will send
+  // TTS_EVENT_CANCELLED events on each one.
+  void ClearUtteranceQueue(bool send_events);
+
+  // Finalize and delete the current utterance.
+  void FinishCurrentUtterance();
+
+  // Start speaking the next utterance in the queue.
+  void SpeakNextUtterance();
+
+  // Updates the utterance to have default values for rate, pitch, and
+  // volume if they have not yet been set. On Chrome OS, defaults are
+  // pulled from user prefs, and may not be the same as other platforms.
+  void UpdateUtteranceDefaults(Utterance* utterance);
+
+  TtsControllerDelegate* GetTtsControllerDelegate();
+
   TtsControllerDelegate* delegate_;
 
+  // A set of delegates that want to be notified when the voices change.
+  base::ObserverList<VoicesChangedDelegate> voices_changed_delegates_;
+
+  // The current utterance being spoken.
+  Utterance* current_utterance_;
+
+  // Whether the queue is paused or not.
+  bool paused_;
+
+  // A pointer to the platform implementation of text-to-speech, for
+  // dependency injection.
+  TtsPlatform* tts_platform_;
+
+  // A queue of utterances to speak after the current one finishes.
+  base::queue<Utterance*> utterance_queue_;
+
   DISALLOW_COPY_AND_ASSIGN(TtsControllerImpl);
 };
 
diff --git a/content/browser/speech/tts_controller_unittest.cc b/content/browser/speech/tts_controller_unittest.cc
new file mode 100644
index 0000000..b0130b6
--- /dev/null
+++ b/content/browser/speech/tts_controller_unittest.cc
@@ -0,0 +1,127 @@
+// Copyright (c) 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.
+
+// Unit tests for the TTS Controller.
+
+#include "base/values.h"
+#include "content/browser/speech/tts_controller_impl.h"
+#include "content/public/browser/tts_controller_delegate.h"
+#include "content/public/browser/tts_platform.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/web_speech_synthesis_constants.h"
+
+namespace content {
+
+class TtsControllerTest : public testing::Test {};
+
+// Platform Tts implementation that does nothing.
+class MockTtsPlatformImpl : public TtsPlatform {
+ public:
+  MockTtsPlatformImpl() {}
+  virtual ~MockTtsPlatformImpl() {}
+  bool PlatformImplAvailable() override { return true; }
+  bool Speak(int utterance_id,
+             const std::string& utterance,
+             const std::string& lang,
+             const VoiceData& voice,
+             const UtteranceContinuousParameters& params) override {
+    return true;
+  }
+  bool IsSpeaking() override { return false; }
+  bool StopSpeaking() override { return true; }
+  void Pause() override {}
+  void Resume() override {}
+  void GetVoices(std::vector<VoiceData>* out_voices) override {}
+  bool LoadBuiltInTtsEngine(BrowserContext* browser_context) override {
+    return false;
+  }
+  void WillSpeakUtteranceWithVoice(const Utterance* utterance,
+                                   const VoiceData& voice_data) override {}
+  void SetError(const std::string& error) override {}
+  std::string GetError() override { return std::string(); }
+  void ClearError() override {}
+};
+
+class MockTtsControllerDelegate : public TtsControllerDelegate {
+ public:
+  MockTtsControllerDelegate() {}
+  ~MockTtsControllerDelegate() override {}
+
+  int GetMatchingVoice(const content::Utterance* utterance,
+                       std::vector<content::VoiceData>& voices) override {
+    // Below 0 implies a "native" voice.
+    return -1;
+  }
+
+  void UpdateUtteranceDefaultsFromPrefs(content::Utterance* utterance,
+                                        double* rate,
+                                        double* pitch,
+                                        double* volume) override{};
+
+  void SetTtsEngineDelegate(content::TtsEngineDelegate* delegate) override{};
+
+  content::TtsEngineDelegate* GetTtsEngineDelegate() override {
+    return nullptr;
+  }
+};
+
+// Subclass of TtsController with a public ctor and dtor.
+class TtsControllerForTesting : public TtsControllerImpl {
+ public:
+  TtsControllerForTesting() {}
+  ~TtsControllerForTesting() override {}
+};
+
+TEST_F(TtsControllerTest, TestTtsControllerShutdown) {
+  MockTtsPlatformImpl platform_impl;
+  TtsControllerForTesting* controller = new TtsControllerForTesting();
+  MockTtsControllerDelegate* delegate = new MockTtsControllerDelegate();
+  controller->delegate_ = delegate;
+
+  controller->SetTtsPlatform(&platform_impl);
+
+  Utterance* utterance1 = new Utterance(nullptr);
+  utterance1->set_can_enqueue(true);
+  utterance1->set_src_id(1);
+  controller->SpeakOrEnqueue(utterance1);
+
+  Utterance* utterance2 = new Utterance(nullptr);
+  utterance2->set_can_enqueue(true);
+  utterance2->set_src_id(2);
+  controller->SpeakOrEnqueue(utterance2);
+
+  // Make sure that deleting the controller when there are pending
+  // utterances doesn't cause a crash.
+  delete controller;
+
+  // Clean up.
+  delete delegate;
+}
+
+#if !defined(OS_CHROMEOS)
+TEST_F(TtsControllerTest, TestTtsControllerUtteranceDefaults) {
+  std::unique_ptr<TtsControllerForTesting> controller =
+      std::make_unique<TtsControllerForTesting>();
+
+  std::unique_ptr<Utterance> utterance1 = std::make_unique<Utterance>(nullptr);
+  // Initialized to default (unset constant) values.
+  EXPECT_EQ(blink::kWebSpeechSynthesisDoublePrefNotSet,
+            utterance1->continuous_parameters().rate);
+  EXPECT_EQ(blink::kWebSpeechSynthesisDoublePrefNotSet,
+            utterance1->continuous_parameters().pitch);
+  EXPECT_EQ(blink::kWebSpeechSynthesisDoublePrefNotSet,
+            utterance1->continuous_parameters().volume);
+
+  controller->UpdateUtteranceDefaults(utterance1.get());
+  // Updated to global defaults.
+  EXPECT_EQ(blink::kWebSpeechSynthesisDefaultTextToSpeechRate,
+            utterance1->continuous_parameters().rate);
+  EXPECT_EQ(blink::kWebSpeechSynthesisDefaultTextToSpeechPitch,
+            utterance1->continuous_parameters().pitch);
+  EXPECT_EQ(blink::kWebSpeechSynthesisDefaultTextToSpeechVolume,
+            utterance1->continuous_parameters().volume);
+}
+#endif  // !defined(OS_CHROMEOS)
+
+}  // namespace content
diff --git a/content/browser/speech/tts_platform_impl.cc b/content/browser/speech/tts_platform_impl.cc
index 0a9a1bd..44492180 100644
--- a/content/browser/speech/tts_platform_impl.cc
+++ b/content/browser/speech/tts_platform_impl.cc
@@ -24,7 +24,7 @@
 #endif
 }
 
-bool TtsPlatformImpl::LoadBuiltInTtsExtension(BrowserContext* browser_context) {
+bool TtsPlatformImpl::LoadBuiltInTtsEngine(BrowserContext* browser_context) {
   return false;
 }
 
diff --git a/content/browser/speech/tts_platform_impl.h b/content/browser/speech/tts_platform_impl.h
index 34d03ab..554f772 100644
--- a/content/browser/speech/tts_platform_impl.h
+++ b/content/browser/speech/tts_platform_impl.h
@@ -19,7 +19,7 @@
   static TtsPlatformImpl* GetInstance();
 
   // TtsPlatform overrides.
-  bool LoadBuiltInTtsExtension(BrowserContext* browser_context) override;
+  bool LoadBuiltInTtsEngine(BrowserContext* browser_context) override;
   void WillSpeakUtteranceWithVoice(const Utterance* utterance,
                                    const VoiceData& voice_data) override;
   std::string GetError() override;
diff --git a/content/public/android/java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java b/content/public/android/java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java
index 20439053..20ae0a70 100644
--- a/content/public/android/java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java
@@ -317,33 +317,34 @@
             // callbacks will be deferred until browser startup completes.
             mCurrentBrowserStartType = BROWSER_START_TYPE_FULL_BROWSER;
             if (contentStart() > 0) enqueueCallbackExecution(STARTUP_FAILURE);
-        } else if (mCurrentBrowserStartType == BROWSER_START_TYPE_SERVICE_MANAGER_ONLY) {
-            // If full browser startup is not needed, execute all the callbacks now.
-            executeEnqueuedCallbacks(STARTUP_SUCCESS);
+            return;
+        }
+
+        if (mCurrentBrowserStartType == BROWSER_START_TYPE_SERVICE_MANAGER_ONLY) {
+            executeServiceManagerCallbacks(STARTUP_SUCCESS);
         }
         recordStartupUma();
     }
 
     private void executeEnqueuedCallbacks(int startupResult) {
         assert ThreadUtils.runningOnUiThread() : "Callback from browser startup from wrong thread.";
-        // If only ServiceManager is launched, don't set mFullBrowserStartupDone, wait for the full
-        // browser launch to set this variable.
-        mFullBrowserStartupDone = mCurrentBrowserStartType == BROWSER_START_TYPE_FULL_BROWSER;
+        mFullBrowserStartupDone = true;
         mStartupSuccess = (startupResult <= 0);
-        if (mFullBrowserStartupDone) {
-            for (StartupCallback asyncStartupCallback : mAsyncStartupCallbacks) {
-                if (mStartupSuccess) {
-                    asyncStartupCallback.onSuccess();
-                } else {
-                    asyncStartupCallback.onFailure();
-                }
+        for (StartupCallback asyncStartupCallback : mAsyncStartupCallbacks) {
+            if (mStartupSuccess) {
+                asyncStartupCallback.onSuccess();
+            } else {
+                asyncStartupCallback.onFailure();
             }
-            // We don't want to hold on to any objects after we do not need them anymore.
-            mAsyncStartupCallbacks.clear();
         }
-        // The ServiceManager should have been started, call the callbacks now.
-        // TODO(qinmin): Handle mServiceManagerCallbacks in serviceManagerStarted() instead of
-        // here once http://crbug.com/854231 is fixed.
+        // We don't want to hold on to any objects after we do not need them anymore.
+        mAsyncStartupCallbacks.clear();
+
+        executeServiceManagerCallbacks(startupResult);
+    }
+
+    private void executeServiceManagerCallbacks(int startupResult) {
+        mStartupSuccess = (startupResult <= 0);
         for (StartupCallback serviceMangerCallback : mServiceManagerCallbacks) {
             if (mStartupSuccess) {
                 serviceMangerCallback.onSuccess();
diff --git a/content/public/browser/tts_controller.h b/content/public/browser/tts_controller.h
index 9e1f5a3..ef7c0fc 100644
--- a/content/public/browser/tts_controller.h
+++ b/content/public/browser/tts_controller.h
@@ -24,6 +24,7 @@
 namespace content {
 class Utterance;
 class BrowserContext;
+class TtsPlatform;
 
 // Events sent back from the TTS engine indicating the progress.
 enum TtsEventType {
@@ -56,7 +57,7 @@
 
   std::string name;
   std::string lang;
-  std::string extension_id;
+  std::string engine_id;
   std::set<TtsEventType> events;
 
   // If true, the synthesis engine is a remote network resource.
@@ -64,18 +65,18 @@
   bool remote;
 
   // If true, this is implemented by this platform's subclass of
-  // TtsPlatformImpl. If false, this is implemented by an extension.
+  // TtsPlatformImpl. If false, this is implemented in a content embedder.
   bool native;
   std::string native_voice_identifier;
 };
 
-// Interface that delegates TTS requests to user-installed extensions.
+// Interface that delegates TTS requests to engines in content embedders.
 class CONTENT_EXPORT TtsEngineDelegate {
  public:
   virtual ~TtsEngineDelegate() {}
 
   // Return a list of all available voices registered.
-  virtual void GetVoices(content::BrowserContext* browser_context,
+  virtual void GetVoices(BrowserContext* browser_context,
                          std::vector<VoiceData>* out_voices) = 0;
 
   // Speak the given utterance by sending an event to the given TTS engine.
@@ -91,9 +92,8 @@
   // Resume speaking this utterance.
   virtual void Resume(Utterance* utterance) = 0;
 
-  // Load the built-in component extension for ChromeOS.
-  virtual bool LoadBuiltInTtsExtension(
-      content::BrowserContext* browser_context) = 0;
+  // Load the built-in TTS engine.
+  virtual bool LoadBuiltInTtsEngine(BrowserContext* browser_context) = 0;
 };
 
 // Class that wants to receive events on utterances.
@@ -122,7 +122,7 @@
   // Construct an utterance given a profile and a completion task to call
   // when the utterance is done speaking. Before speaking this utterance,
   // its other parameters like text, rate, pitch, etc. should all be set.
-  explicit Utterance(content::BrowserContext* browser_context);
+  explicit Utterance(BrowserContext* browser_context);
   ~Utterance();
 
   // Sends an event to the delegate. If the event type is TTS_EVENT_END
@@ -184,10 +184,8 @@
     return desired_event_types_;
   }
 
-  const std::string& extension_id() const { return extension_id_; }
-  void set_extension_id(const std::string& extension_id) {
-    extension_id_ = extension_id;
-  }
+  const std::string& engine_id() const { return engine_id_; }
+  void set_engine_id(const std::string& engine_id) { engine_id_ = engine_id; }
 
   UtteranceEventDelegate* event_delegate() const { return event_delegate_; }
   void set_event_delegate(UtteranceEventDelegate* event_delegate) {
@@ -195,17 +193,17 @@
   }
 
   // Getters and setters for internal state.
-  content::BrowserContext* browser_context() const { return browser_context_; }
+  BrowserContext* browser_context() const { return browser_context_; }
   int id() const { return id_; }
   bool finished() const { return finished_; }
 
  private:
   // The BrowserContext that initiated this utterance.
-  content::BrowserContext* browser_context_;
+  BrowserContext* browser_context_;
 
-  // The extension ID of the extension providing TTS for this utterance, or
-  // empty if native TTS is being used.
-  std::string extension_id_;
+  // The content embedder engine ID of the engine providing TTS for this
+  // utterance, or empty if native TTS is being used.
+  std::string engine_id_;
 
   // The unique ID of this utterance, used to associate callback functions
   // with utterances.
@@ -222,11 +220,11 @@
   // other than the ones we explicitly parse, below.
   std::unique_ptr<base::Value> options_;
 
-  // The source extension's ID of this utterance, so that it can associate
+  // The source engine's ID of this utterance, so that it can associate
   // events with the appropriate callback.
   int src_id_;
 
-  // The URL of the page where the source extension called speak.
+  // The URL of the page where called speak was called.
   GURL src_url_;
 
   // The delegate to be called when an utterance event is fired.
@@ -247,8 +245,8 @@
   bool finished_;
 };
 
-// Singleton class that manages text-to-speech for the TTS and TTS engine
-// extension APIs, maintaining a queue of pending utterances and keeping
+// Singleton class that manages text-to-speech for all TTS engines and
+// APIs, maintaining a queue of pending utterances and keeping
 // track of all state.
 class CONTENT_EXPORT TtsController {
  public:
@@ -285,11 +283,11 @@
                           const std::string& error_message) = 0;
 
   // Return a list of all available voices, including the native voice,
-  // if supported, and all voices registered by extensions.
-  virtual void GetVoices(content::BrowserContext* browser_context,
+  // if supported, and all voices registered by engines.
+  virtual void GetVoices(BrowserContext* browser_context,
                          std::vector<VoiceData>* out_voices) = 0;
 
-  // Called by the extension system or platform implementation when the
+  // Called by the content embedder or platform implementation when the
   // list of voices may have changed and should be re-queried.
   virtual void VoicesChanged() = 0;
 
@@ -305,14 +303,18 @@
   virtual void RemoveUtteranceEventDelegate(
       UtteranceEventDelegate* delegate) = 0;
 
-  // Set the delegate that processes TTS requests with user-installed
-  // extensions.
+  // Set the delegate that processes TTS requests with engines in a content
+  // embedder.
   virtual void SetTtsEngineDelegate(TtsEngineDelegate* delegate) = 0;
 
-  // Get the delegate that processes TTS requests with user-installed
-  // extensions.
+  // Get the delegate that processes TTS requests with engines in a content
+  // embedder.
   virtual TtsEngineDelegate* GetTtsEngineDelegate() = 0;
 
+  // Visible for testing.
+  virtual void SetTtsPlatform(TtsPlatform* tts_platform) = 0;
+  virtual int QueueSize() = 0;
+
  protected:
   virtual ~TtsController() {}
 };
diff --git a/content/public/browser/tts_controller_delegate.h b/content/public/browser/tts_controller_delegate.h
index 650ff7c..96a16c1 100644
--- a/content/public/browser/tts_controller_delegate.h
+++ b/content/public/browser/tts_controller_delegate.h
@@ -10,60 +10,19 @@
 namespace content {
 
 // Allows embedders to access the current state of text-to-speech.
-// TODO(katie): This currently matches tts_controller.h but we want to move
-// functionality one at a time into tts_controller_impl from
-// tts_controller_delegate_impl, and remove most of these functions.
 class TtsControllerDelegate {
  public:
-  // Returns true if we're currently speaking an utterance.
-  virtual bool IsSpeaking() = 0;
+  // Given an utterance and a vector of voices, return the
+  // index of the voice that best matches the utterance.
+  virtual int GetMatchingVoice(const Utterance* utterance,
+                               std::vector<VoiceData>& voices) = 0;
 
-  // Speak the given utterance. If the utterance's can_enqueue flag is true
-  // and another utterance is in progress, adds it to the end of the queue.
-  // Otherwise, interrupts any current utterance and speaks this one
-  // immediately.
-  virtual void SpeakOrEnqueue(Utterance* utterance) = 0;
-
-  // Stop all utterances and flush the queue. Implies leaving pause mode
-  // as well.
-  virtual void Stop() = 0;
-
-  // Pause the speech queue. Some engines may support pausing in the middle
-  // of an utterance.
-  virtual void Pause() = 0;
-
-  // Resume speaking.
-  virtual void Resume() = 0;
-
-  // Handle events received from the speech engine. Events are forwarded to
-  // the callback function, and in addition, completion and error events
-  // trigger finishing the current utterance and starting the next one, if
-  // any.
-  virtual void OnTtsEvent(int utterance_id,
-                          TtsEventType event_type,
-                          int char_index,
-                          const std::string& error_message) = 0;
-
-  // Return a list of all available voices, including the native voice,
-  // if supported, and all voices registered by extensions.
-  virtual void GetVoices(content::BrowserContext* browser_context,
-                         std::vector<VoiceData>* out_voices) = 0;
-
-  // Called by the extension system or platform implementation when the
-  // list of voices may have changed and should be re-queried.
-  virtual void VoicesChanged() = 0;
-
-  // Add a delegate that wants to be notified when the set of voices changes.
-  virtual void AddVoicesChangedDelegate(VoicesChangedDelegate* delegate) = 0;
-
-  // Remove delegate that wants to be notified when the set of voices changes.
-  virtual void RemoveVoicesChangedDelegate(VoicesChangedDelegate* delegate) = 0;
-
-  // Remove delegate that wants to be notified when an utterance fires an event.
-  // Note: this cancels speech from any utterance with this delegate, and
-  // removes any utterances with this delegate from the queue.
-  virtual void RemoveUtteranceEventDelegate(
-      UtteranceEventDelegate* delegate) = 0;
+  // Uses the user preferences to update the |rate|, |pitch| and |volume| for
+  // a given |utterance|.
+  virtual void UpdateUtteranceDefaultsFromPrefs(Utterance* utterance,
+                                                double* rate,
+                                                double* pitch,
+                                                double* volume) = 0;
 
   // Set the delegate that processes TTS requests with user-installed
   // extensions.
diff --git a/content/public/browser/tts_platform.h b/content/public/browser/tts_platform.h
index dc87939f..0f8f64f 100644
--- a/content/public/browser/tts_platform.h
+++ b/content/public/browser/tts_platform.h
@@ -22,12 +22,12 @@
   // Returns true if this platform implementation is supported and available.
   virtual bool PlatformImplAvailable() = 0;
 
-  // Some platforms may provide a built-in TTS extension. Returns true
-  // if the extension was not previously loaded and is now loading, and
-  // false if it's already loaded or if there's no extension to load.
+  // Some platforms may provide a built-in TTS engine. Returns true
+  // if the engine was not previously loaded and is now loading, and
+  // false if it's already loaded or if there's no engine to load.
   // Will call TtsController::RetrySpeakingQueuedUtterances when
-  // the extension finishes loading.
-  virtual bool LoadBuiltInTtsExtension(BrowserContext* browser_context) = 0;
+  // the engine finishes loading.
+  virtual bool LoadBuiltInTtsEngine(BrowserContext* browser_context) = 0;
 
   // Speak the given utterance with the given parameters if possible,
   // and return true on success. Utterance will always be nonempty.
diff --git a/content/public/common/network_service_util.cc b/content/public/common/network_service_util.cc
index 87012d29..1f239d5 100644
--- a/content/public/common/network_service_util.cc
+++ b/content/public/common/network_service_util.cc
@@ -27,6 +27,10 @@
     1077};
 #endif
 
+// Indicates whether the network service is forced to be running in the browser
+// process.
+bool g_force_in_process_network_service = false;
+
 }  // namespace
 
 bool IsOutOfProcessNetworkService() {
@@ -38,7 +42,8 @@
   if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
     return false;
 
-  if (base::FeatureList::IsEnabled(features::kNetworkServiceInProcess) ||
+  if (g_force_in_process_network_service ||
+      base::FeatureList::IsEnabled(features::kNetworkServiceInProcess) ||
       base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kSingleProcess)) {
     return true;
@@ -51,4 +56,8 @@
   return false;
 }
 
+void ForceInProcessNetworkService(bool is_forced) {
+  g_force_in_process_network_service = is_forced;
+}
+
 }  // namespace content
diff --git a/content/public/common/network_service_util.h b/content/public/common/network_service_util.h
index 43d595d8..531c47a 100644
--- a/content/public/common/network_service_util.h
+++ b/content/public/common/network_service_util.h
@@ -17,6 +17,9 @@
 // browser process.
 CONTENT_EXPORT bool IsInProcessNetworkService();
 
+// Sets the flag of whether the network service is forced to be running in the
+// browser process. The flag will be checked in |IsInProcessNetworkService()|.
+void ForceInProcessNetworkService(bool is_forced);
 }  // namespace content
 
 #endif  // CONTENT_PUBLIC_COMMON_NETWORK_SERVICE_UTIL_H_
diff --git a/content/renderer/compositor/layer_tree_view.cc b/content/renderer/compositor/layer_tree_view.cc
index 0994118..e82b0c8 100644
--- a/content/renderer/compositor/layer_tree_view.cc
+++ b/content/renderer/compositor/layer_tree_view.cc
@@ -741,10 +741,6 @@
   delegate_->RecordEndOfFrameMetrics(frame_begin_time);
 }
 
-void LayerTreeView::RequestScheduleAnimation() {
-  delegate_->RequestScheduleAnimation();
-}
-
 void LayerTreeView::DidSubmitCompositorFrame() {}
 
 void LayerTreeView::DidLoseLayerTreeFrameSink() {}
diff --git a/content/renderer/compositor/layer_tree_view.h b/content/renderer/compositor/layer_tree_view.h
index aee5bfd3..dbc4dc67 100644
--- a/content/renderer/compositor/layer_tree_view.h
+++ b/content/renderer/compositor/layer_tree_view.h
@@ -83,7 +83,12 @@
 
   bool IsSurfaceSynchronizationEnabled() const;
 
-  // Like setNeedsRedraw but forces the frame to be drawn, without early-outs.
+  // Indicates that blink needs a BeginFrame, but that nothing might actually be
+  // dirty. Calls to this should never be done directly, but should go through
+  // WebWidgetClient::ScheduleAnimate() instead, or they can bypass test
+  // overrides.
+  void SetNeedsBeginFrame();
+  // Like SetNeedsRedraw but forces the frame to be drawn, without early-outs.
   // Redraw will be forced after the next commit
   void SetNeedsForcedRedraw();
   // Calling CreateLatencyInfoSwapPromiseMonitor() to get a scoped
@@ -139,7 +144,6 @@
                                double duration_sec) override;
   bool HasPendingPageScaleAnimation() const override;
   void HeuristicsForGpuRasterizationUpdated(bool matches_heuristics) override;
-  void SetNeedsBeginFrame() override;
   void LayoutAndPaintAsync(base::OnceClosure callback) override;
   void CompositeAndReadbackAsync(
       base::OnceCallback<void(const SkBitmap&)> callback) override;
@@ -207,7 +211,6 @@
   void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) override;
 
   // cc::LayerTreeHostSingleThreadClient implementation.
-  void RequestScheduleAnimation() override;
   void DidSubmitCompositorFrame() override;
   void DidLoseLayerTreeFrameSink() override;
   void RequestBeginMainFrameNotExpected(bool new_state) override;
@@ -225,6 +228,11 @@
 
   cc::LayerTreeHost* layer_tree_host() { return layer_tree_host_.get(); }
 
+  // Exposed for the WebTest harness to query.
+  bool CompositeIsSynchronousForTesting() const {
+    return CompositeIsSynchronous();
+  }
+
  protected:
   friend class RenderViewImplScaleFactorTest;
 
diff --git a/content/renderer/compositor/layer_tree_view_delegate.h b/content/renderer/compositor/layer_tree_view_delegate.h
index e6b2aea..faad249f 100644
--- a/content/renderer/compositor/layer_tree_view_delegate.h
+++ b/content/renderer/compositor/layer_tree_view_delegate.h
@@ -63,10 +63,6 @@
   // or committing a frame (at the same time Tracing measurements are taken).
   virtual void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) = 0;
 
-  // Requests that the client schedule a composite now, and calculate
-  // appropriate delay for potential future frame.
-  virtual void RequestScheduleAnimation() = 0;
-
   // Requests a visual frame-based update to the state of the delegate if there
   // is an update available. |record_main_frame_metrics| will be true if
   // this is a main frame for which we want metrics.
diff --git a/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc b/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc
index 64cc42c9..076bb8d3 100644
--- a/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc
+++ b/content/renderer/media/webrtc/rtc_video_decoder_adapter.cc
@@ -43,10 +43,6 @@
 namespace {
 
 // Any reasonable size, will be overridden by the decoder anyway.
-//
-// TODO(sandersd): DXVA VDA does not compute a visible rect itself; we should
-// not enable RTCVideoDecoderAdapter on Windows until that is fixed.
-// https://crbug.com/869660.
 const gfx::Size kDefaultSize(640, 480);
 
 // Assumed pixel format of the encoded content. WebRTC doesn't tell us, and in
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 29a4db1..43229b0 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -1053,6 +1053,10 @@
   return frame_widget_;
 }
 
+blink::WebWidgetClient* RenderViewImpl::GetWebWidgetClientForWidget() {
+  return WidgetClient();
+}
+
 bool RenderViewImpl::RenderWidgetWillHandleMouseEventForWidget(
     const blink::WebMouseEvent& event) {
   // If the mouse is locked, only the current owner of the mouse lock can
@@ -1152,12 +1156,6 @@
                                        browser_controls_shrink_blink_size);
 }
 
-void RenderViewImpl::RequestScheduleAnimationForWidget() {
-  // Schedule the animation on the WidgetClient() which may not be the
-  // RenderWidget directly in web tests.
-  WidgetClient()->ScheduleAnimation();
-}
-
 void RenderViewImpl::SetScreenMetricsEmulationParametersForWidget(
     bool enabled,
     const blink::WebDeviceEmulationParams& params) {
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 3f35d7ce..5419213 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -388,6 +388,7 @@
   // RenderWidgetOwnerDelegate implementation ----------------------------------
 
   blink::WebWidget* GetWebWidgetForWidget() const override;
+  blink::WebWidgetClient* GetWebWidgetClientForWidget() override;
   bool RenderWidgetWillHandleMouseEventForWidget(
       const blink::WebMouseEvent& event) override;
   void SetActiveForWidget(bool active) override;
@@ -412,7 +413,6 @@
       float top_controls_height,
       float bottom_controls_height,
       bool browser_controls_shrink_blink_size) override;
-  void RequestScheduleAnimationForWidget() override;
   void SetScreenMetricsEmulationParametersForWidget(
       bool enabled,
       const blink::WebDeviceEmulationParams& params) override;
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 53b1c634..198082a 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -934,10 +934,11 @@
 }
 
 void RenderWidget::SetNeedsMainFrame() {
-  LayerTreeView* ltv = layer_tree_view();
-  if (!ltv)
-    return;
-  ltv->SetNeedsBeginFrame();
+  // The WebWidgetClient is not |this| if tests override it for the WebView and
+  // WebViewClient.
+  blink::WebWidgetClient* client =
+      owner_delegate_ ? owner_delegate_->GetWebWidgetClientForWidget() : this;
+  client->ScheduleAnimation();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1056,12 +1057,11 @@
     owner_delegate_->DidCompletePageScaleAnimationForWidget();
 }
 
-void RenderWidget::RequestScheduleAnimation() {
-  if (owner_delegate_) {
-    owner_delegate_->RequestScheduleAnimationForWidget();
-    return;
-  }
-  ScheduleAnimation();
+void RenderWidget::ScheduleAnimation() {
+  // This call is not needed in single thread mode for tests without a
+  // scheduler, but they need to override the WebWidgetClient and replace this
+  // method in order to schedule a synchronous composite task themselves.
+  layer_tree_view_->SetNeedsBeginFrame();
 }
 
 void RenderWidget::UpdateVisualState(bool record_main_frame_metrics) {
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index 88c7ddf..6325a4ae 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -303,7 +303,6 @@
   void DidCommitCompositorFrame() override;
   void DidCompletePageScaleAnimation() override;
   void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) override;
-  void RequestScheduleAnimation() override;
   void UpdateVisualState(bool record_main_frame_metrics) override;
   void WillBeginCompositorFrame() override;
   std::unique_ptr<cc::SwapPromise> RequestCopyOfOutputForWebTest(
@@ -337,6 +336,7 @@
                       const gfx::Rect& window_screen_rect) override;
 
   // blink::WebWidgetClient
+  void ScheduleAnimation() override;
   void IntrinsicSizingInfoChanged(
       const blink::WebIntrinsicSizingInfo&) override;
   void DidMeaningfulLayout(blink::WebMeaningfulLayout layout_type) override;
diff --git a/content/renderer/render_widget_owner_delegate.h b/content/renderer/render_widget_owner_delegate.h
index 950763c..1b4cfd2 100644
--- a/content/renderer/render_widget_owner_delegate.h
+++ b/content/renderer/render_widget_owner_delegate.h
@@ -25,6 +25,10 @@
   // and RenderWidget will fall back to its own WebWidget.
   virtual blink::WebWidget* GetWebWidgetForWidget() const = 0;
 
+  // Returns the WebWidgetClient being provided from the delegate. Usually this
+  // is the RenderWidget itself, but tests can override and change it.
+  virtual blink::WebWidgetClient* GetWebWidgetClientForWidget() = 0;
+
   // As in RenderWidgetInputHandlerDelegate. Return true if the event was
   // handled.
   virtual bool RenderWidgetWillHandleMouseEventForWidget(
@@ -97,9 +101,6 @@
       float bottom_controls_height,
       bool browser_controls_shrink_blink_size) = 0;
 
-  // Called to schedule an animation on the WebWidgetClient.
-  virtual void RequestScheduleAnimationForWidget() = 0;
-
   // Called when RenderWidget services RenderWidgetScreenMetricsEmulatorDelegate
   // SetScreenMetricsEmulationParameters().
   virtual void SetScreenMetricsEmulationParametersForWidget(
diff --git a/content/renderer/render_widget_unittest.cc b/content/renderer/render_widget_unittest.cc
index c5e6bb8..2fe627a 100644
--- a/content/renderer/render_widget_unittest.cc
+++ b/content/renderer/render_widget_unittest.cc
@@ -473,6 +473,9 @@
 class StubRenderWidgetOwnerDelegate : public RenderWidgetOwnerDelegate {
  public:
   blink::WebWidget* GetWebWidgetForWidget() const override { return nullptr; }
+  blink::WebWidgetClient* GetWebWidgetClientForWidget() override {
+    return nullptr;
+  }
   bool RenderWidgetWillHandleMouseEventForWidget(
       const blink::WebMouseEvent& event) override {
     return false;
@@ -499,7 +502,6 @@
       float top_controls_height,
       float bottom_controls_height,
       bool browser_controls_shrink_blink_size) override {}
-  void RequestScheduleAnimationForWidget() override {}
   void SetScreenMetricsEmulationParametersForWidget(
       bool enabled,
       const blink::WebDeviceEmulationParams& params) override {}
diff --git a/content/shell/test_runner/web_view_test_proxy.cc b/content/shell/test_runner/web_view_test_proxy.cc
index d212d57c..7ccd0e1 100644
--- a/content/shell/test_runner/web_view_test_proxy.cc
+++ b/content/shell/test_runner/web_view_test_proxy.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include "content/renderer/compositor/layer_tree_view.h"
 #include "content/shell/test_runner/accessibility_controller.h"
 #include "content/shell/test_runner/test_interfaces.h"
 #include "content/shell/test_runner/test_runner.h"
@@ -22,15 +23,27 @@
 
 ProxyWebWidgetClient::ProxyWebWidgetClient(
     blink::WebWidgetClient* base_class_widget_client,
-    blink::WebWidgetClient* widget_test_client)
+    blink::WebWidgetClient* widget_test_client,
+    content::RenderWidget* render_widget)
     : base_class_widget_client_(base_class_widget_client),
-      widget_test_client_(widget_test_client) {}
+      widget_test_client_(widget_test_client),
+      render_widget_(render_widget) {}
 
 void ProxyWebWidgetClient::DidInvalidateRect(const blink::WebRect& r) {
   base_class_widget_client_->DidInvalidateRect(r);
 }
 void ProxyWebWidgetClient::ScheduleAnimation() {
-  widget_test_client_->ScheduleAnimation();
+  // When using threaded compositing, have the RenderWidget schedule a request
+  // for a frame, as we use the compositor's scheduler. Otherwise the testing
+  // WebWidgetClient schedules it.
+  // Note that for WebViewTestProxy the RenderWidget is not subclassed to
+  // override the WebWidgetClient, instead it is injected into RenderViewImpl,
+  // so if we call RenderWidget here we jump out of the test harness as
+  // intended.
+  if (!render_widget_->layer_tree_view()->CompositeIsSynchronousForTesting())
+    render_widget_->ScheduleAnimation();
+  else
+    widget_test_client_->ScheduleAnimation();
 }
 void ProxyWebWidgetClient::IntrinsicSizingInfoChanged(
     const blink::WebIntrinsicSizingInfo& info) {
@@ -178,7 +191,8 @@
   view_test_client_ = interfaces->CreateWebViewTestClient(this, nullptr);
   // This uses the widget_test_client set above on WebWidgetTestProxyBase.
   proxy_widget_client_ = std::make_unique<ProxyWebWidgetClient>(
-      RenderViewImpl::WidgetClient(), web_widget_client.get());
+      RenderViewImpl::WidgetClient(), web_widget_client.get(),
+      RenderViewImpl::GetWidget());
 
   // On WebWidgetTestProxyBase.
   // It's weird that the WebView has the proxy client, but the
diff --git a/content/shell/test_runner/web_view_test_proxy.h b/content/shell/test_runner/web_view_test_proxy.h
index 8ae927e..a6a3d61f 100644
--- a/content/shell/test_runner/web_view_test_proxy.h
+++ b/content/shell/test_runner/web_view_test_proxy.h
@@ -39,7 +39,6 @@
 }
 
 namespace test_runner {
-
 class AccessibilityController;
 class TestInterfaces;
 class TestRunnerForSpecificView;
@@ -56,7 +55,8 @@
 class TEST_RUNNER_EXPORT ProxyWebWidgetClient : public blink::WebWidgetClient {
  public:
   ProxyWebWidgetClient(blink::WebWidgetClient* base_class_widget_client,
-                       blink::WebWidgetClient* widget_test_client);
+                       blink::WebWidgetClient* widget_test_client,
+                       content::RenderWidget* render_widget);
 
   // blink::WebWidgetClient implementation.
   void DidInvalidateRect(const blink::WebRect&) override;
@@ -102,6 +102,7 @@
  private:
   blink::WebWidgetClient* base_class_widget_client_;
   blink::WebWidgetClient* widget_test_client_;
+  content::RenderWidget* render_widget_;
 };
 
 // WebViewTestProxyBase is the "brain" of WebViewTestProxy in the sense that
diff --git a/content/shell/test_runner/web_widget_test_client.cc b/content/shell/test_runner/web_widget_test_client.cc
index 799c17c..51509d5 100644
--- a/content/shell/test_runner/web_widget_test_client.cc
+++ b/content/shell/test_runner/web_widget_test_client.cc
@@ -52,9 +52,10 @@
   blink::WebWidget* web_widget = web_widget_test_proxy_base_->web_widget();
   web_widget->UpdateAllLifecyclePhasesAndCompositeForTesting(
       animation_requires_raster);
-  if (blink::WebPagePopup* popup = web_widget->GetPagePopup())
+  if (blink::WebPagePopup* popup = web_widget->GetPagePopup()) {
     popup->UpdateAllLifecyclePhasesAndCompositeForTesting(
         animation_requires_raster);
+  }
 }
 
 bool WebWidgetTestClient::RequestPointerLock() {
diff --git a/content/shell/test_runner/web_widget_test_proxy.cc b/content/shell/test_runner/web_widget_test_proxy.cc
index 33e6f3c..fdb685d 100644
--- a/content/shell/test_runner/web_widget_test_proxy.cc
+++ b/content/shell/test_runner/web_widget_test_proxy.cc
@@ -4,6 +4,7 @@
 
 #include "content/shell/test_runner/web_widget_test_proxy.h"
 
+#include "content/renderer/compositor/layer_tree_view.h"
 #include "content/shell/test_runner/event_sender.h"
 #include "content/shell/test_runner/web_test_interfaces.h"
 #include "content/shell/test_runner/web_view_test_proxy.h"
@@ -38,8 +39,16 @@
 }
 
 void WebWidgetTestProxy::ScheduleAnimation() {
-  RenderWidget::ScheduleAnimation();
-  widget_test_client()->ScheduleAnimation();
+  // When using threaded compositing, have the RenderWidget schedule a request
+  // for a frame, as we use the compositor's scheduler. Otherwise the testing
+  // WebWidgetClient schedules it.
+  // Note that for WebWidgetTestProxy the RenderWidget is subclassed to override
+  // the WebWidgetClient, so we must call up to the base class RenderWidget
+  // explicitly here to jump out of the test harness as intended.
+  if (!RenderWidget::layer_tree_view()->CompositeIsSynchronousForTesting())
+    RenderWidget::ScheduleAnimation();
+  else
+    widget_test_client()->ScheduleAnimation();
 }
 
 bool WebWidgetTestProxy::RequestPointerLock() {
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 81d728e7..d4ea50a 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1616,6 +1616,7 @@
     "../browser/service_worker/service_worker_write_to_cache_job_unittest.cc",
     "../browser/shareable_file_reference_unittest.cc",
     "../browser/site_instance_impl_unittest.cc",
+    "../browser/speech/tts_controller_unittest.cc",
     "../browser/startup_task_runner_unittest.cc",
     "../browser/storage_partition_impl_map_unittest.cc",
     "../browser/storage_partition_impl_unittest.cc",
diff --git a/content/test/data/frame_tree/page_with_positioned_clipped_iframe.html b/content/test/data/frame_tree/page_with_positioned_clipped_iframe.html
new file mode 100644
index 0000000..e2dba36
--- /dev/null
+++ b/content/test/data/frame_tree/page_with_positioned_clipped_iframe.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <style>
+    body {
+      margin: 0px;
+    }
+
+    iframe {
+      position: absolute;
+      top: -50px;
+      left: -50px;
+      width: 200px;
+      height: 200px;
+      border: none;
+    }
+
+    div {
+      position: absolute;
+    }
+
+    #clip {
+      top: 50px;
+      left: 50px;
+      width: 100px;
+      height: 100px;
+      background-color: red;
+      transform: TranslateX(10px);
+      overflow: hidden;
+    }
+    </style>
+  </head>
+  <body>
+    <div id="clip">
+          <iframe src="/cross-site/baz.com/title1.html"></iframe>
+    </div>
+  </body>
+</html>
diff --git a/content/test/gpu/gpu_tests/context_lost_expectations.py b/content/test/gpu/gpu_tests/context_lost_expectations.py
index 8ede0de..5eb0134 100644
--- a/content/test/gpu/gpu_tests/context_lost_expectations.py
+++ b/content/test/gpu/gpu_tests/context_lost_expectations.py
@@ -45,6 +45,10 @@
     # Flaking on Mac.
     self.Flaky('GpuCrash_GPUProcessCrashesExactlyOncePerVisitToAboutGpuCrash',
               ['mac'], bug=878258)
+    self.Flaky('ContextLost_WebGLBlockedAfterJSNavigation',
+              ['mac'], bug=900948)
+    self.Flaky('ContextLost_WebGLUnblockedAfterUserInitiatedReload',
+              ['mac'], bug=900948)
 
     # 'Browser must support tab control' raised on Android
     self.Skip('GpuCrash_GPUProcessCrashesExactlyOncePerVisitToAboutGpuCrash',
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
index fdb9102..36674f7e 100644
--- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -199,8 +199,6 @@
     self.Flaky('conformance/glsl/constructors/' +
               'glsl-construct-vec-mat-index.html',
               ['win'], bug=525188)
-    self.Fail('conformance/rendering/point-specific-shader-variables.html',
-        ['win'], bug=616335)
     self.Fail('deqp/data/gles2/shaders/functions.html',
         ['win'], bug=478572)
 
@@ -595,6 +593,10 @@
         ['linux', ('nvidia', 0x1cb3)], bug=715001)
     self.Fail('conformance/textures/misc/texture-size.html',
         ['linux', ('nvidia', 0x1cb3), 'opengl'], bug=703779)
+    self.Flaky('conformance/extensions/oes-texture-float-with-video.html',
+        ['linux', ('nvidia', 0x1cb3)], bug=913969)
+    self.Flaky('conformance/extensions/oes-texture-half-float-with-video.html',
+        ['linux', ('nvidia', 0x1cb3)], bug=913969)
 
     # AMD
     self.Fail('conformance/glsl/misc/fragcolor-fragdata-invariant.html',
@@ -755,6 +757,10 @@
         ['android', ('qualcomm', 'Adreno (TM) 418')], bug=912161)
     self.Flaky('conformance/glsl/functions/glsl-function-dot.html',
         ['android', ('qualcomm', 'Adreno (TM) 418')], bug=912161)
+    self.Flaky('conformance/glsl/functions/glsl-function-min-gentype.html',
+        ['android', ('qualcomm', 'Adreno (TM) 418')], bug=912161)
+    self.Flaky('conformance/glsl/implicit/add_ivec3_vec3.vert.html',
+        ['android', ('qualcomm', 'Adreno (TM) 418')], bug=912161)
     # This test is skipped because it is crashing the GPU process.
     self.Skip('conformance/glsl/misc/shader-with-non-reserved-words.html',
         ['android', ('qualcomm', 'Adreno (TM) 418'), 'no_passthrough'],
diff --git a/content/test/stub_layer_tree_view_delegate.h b/content/test/stub_layer_tree_view_delegate.h
index c43b54f..31ddc36f 100644
--- a/content/test/stub_layer_tree_view_delegate.h
+++ b/content/test/stub_layer_tree_view_delegate.h
@@ -26,7 +26,6 @@
   void DidCommitAndDrawCompositorFrame() override {}
   void DidCommitCompositorFrame() override {}
   void DidCompletePageScaleAnimation() override {}
-  void RequestScheduleAnimation() override {}
   void UpdateVisualState(bool record_main_frame_metrics) override {}
   void WillBeginCompositorFrame() override {}
   std::unique_ptr<cc::SwapPromise> RequestCopyOfOutputForWebTest(
diff --git a/extensions/browser/api/declarative/declarative_api.cc b/extensions/browser/api/declarative/declarative_api.cc
index 83c716a..7bb6107 100644
--- a/extensions/browser/api/declarative/declarative_api.cc
+++ b/extensions/browser/api/declarative/declarative_api.cc
@@ -217,18 +217,14 @@
 EventsEventAddRulesFunction::RunAsyncOnCorrectThread() {
   ConvertBinaryListElementsToBase64(args_.get());
 
-  // TODO(devlin): Remove the dependency on linked_ptr here.
-  std::vector<linked_ptr<api::events::Rule>> linked_rules;
-  for (api::events::Rule& rule : params_->rules) {
-    linked_rules.push_back(
-        make_linked_ptr(new api::events::Rule(std::move(rule))));
-  }
-  std::string error = rules_registry_->AddRules(extension_id(), linked_rules);
+  std::vector<const api::events::Rule*> rules_out;
+  std::string error = rules_registry_->AddRules(
+      extension_id(), std::move(params_->rules), &rules_out);
   if (!error.empty())
     return Error(error);
 
   auto rules_value = std::make_unique<base::ListValue>();
-  for (const auto& rule : linked_rules)
+  for (const auto* rule : rules_out)
     rules_value->Append(rule->ToValue());
   return OneArgument(std::move(rules_value));
 }
@@ -306,7 +302,7 @@
 
 ExtensionFunction::ResponseValue
 EventsEventGetRulesFunction::RunAsyncOnCorrectThread() {
-  std::vector<linked_ptr<Rule> > rules;
+  std::vector<const Rule*> rules;
   if (params_->rule_identifiers.get()) {
     rules_registry_->GetRules(extension_id(), *params_->rule_identifiers,
                               &rules);
@@ -315,7 +311,7 @@
   }
 
   auto rules_value = std::make_unique<base::ListValue>();
-  for (const auto& rule : rules)
+  for (const auto* rule : rules)
     rules_value->Append(rule->ToValue());
   return OneArgument(std::move(rules_value));
 }
diff --git a/extensions/browser/api/declarative/declarative_rule.h b/extensions/browser/api/declarative/declarative_rule.h
index cbe55e9..15854447 100644
--- a/extensions/browser/api/declarative/declarative_rule.h
+++ b/extensions/browser/api/declarative/declarative_rule.h
@@ -234,7 +234,7 @@
       content::BrowserContext* browser_context,
       const Extension* extension,
       base::Time extension_installation_time,
-      linked_ptr<JsonRule> rule,
+      const JsonRule& rule,
       ConsistencyChecker check_consistency,
       std::string* error);
 
@@ -448,20 +448,20 @@
     content::BrowserContext* browser_context,
     const Extension* extension,
     base::Time extension_installation_time,
-    linked_ptr<JsonRule> rule,
+    const JsonRule& rule,
     ConsistencyChecker check_consistency,
     std::string* error) {
   std::unique_ptr<DeclarativeRule> error_result;
 
   std::unique_ptr<ConditionSet> conditions = ConditionSet::Create(
-      extension, url_matcher_condition_factory, rule->conditions, error);
+      extension, url_matcher_condition_factory, rule.conditions, error);
   if (!error->empty())
     return std::move(error_result);
   CHECK(conditions.get());
 
   bool bad_message = false;
   std::unique_ptr<ActionSet> actions = ActionSet::Create(
-      browser_context, extension, rule->actions, error, &bad_message);
+      browser_context, extension, rule.actions, error, &bad_message);
   if (bad_message) {
     // TODO(battre) Export concept of bad_message to caller, the extension
     // should be killed in case it is true.
@@ -479,11 +479,11 @@
     return std::move(error_result);
   }
 
-  CHECK(rule->priority.get());
-  int priority = *(rule->priority);
+  CHECK(rule.priority.get());
+  int priority = *(rule.priority);
 
-  GlobalRuleId rule_id(extension->id(), *(rule->id));
-  Tags tags = rule->tags ? *rule->tags : Tags();
+  GlobalRuleId rule_id(extension->id(), *(rule.id));
+  Tags tags = rule.tags ? *rule.tags : Tags();
   return std::unique_ptr<DeclarativeRule>(
       new DeclarativeRule(rule_id, tags, extension_installation_time,
                           std::move(conditions), std::move(actions), priority));
diff --git a/extensions/browser/api/declarative/declarative_rule_unittest.cc b/extensions/browser/api/declarative/declarative_rule_unittest.cc
index 5b34330..04315c53d 100644
--- a/extensions/browser/api/declarative/declarative_rule_unittest.cc
+++ b/extensions/browser/api/declarative/declarative_rule_unittest.cc
@@ -299,22 +299,22 @@
 
 TEST(DeclarativeRuleTest, Create) {
   typedef DeclarativeRule<FulfillableCondition, SummingAction> Rule;
-  linked_ptr<Rule::JsonRule> json_rule(new Rule::JsonRule);
-  ASSERT_TRUE(Rule::JsonRule::Populate(
-      *ParseJson("{ \n"
-                 "  \"id\": \"rule1\", \n"
-                 "  \"conditions\": [ \n"
-                 "    {\"url_id\": 1, \"max\": 3}, \n"
-                 "    {\"url_id\": 2, \"max\": 5}, \n"
-                 "  ], \n"
-                 "  \"actions\": [ \n"
-                 "    { \n"
-                 "      \"value\": 2 \n"
-                 "    } \n"
-                 "  ], \n"
-                 "  \"priority\": 200 \n"
-                 "}"),
-      json_rule.get()));
+  Rule::JsonRule json_rule;
+  ASSERT_TRUE(
+      Rule::JsonRule::Populate(*ParseJson("{ \n"
+                                          "  \"id\": \"rule1\", \n"
+                                          "  \"conditions\": [ \n"
+                                          "    {\"url_id\": 1, \"max\": 3}, \n"
+                                          "    {\"url_id\": 2, \"max\": 5}, \n"
+                                          "  ], \n"
+                                          "  \"actions\": [ \n"
+                                          "    { \n"
+                                          "      \"value\": 2 \n"
+                                          "    } \n"
+                                          "  ], \n"
+                                          "  \"priority\": 200 \n"
+                                          "}"),
+                               &json_rule));
 
   const char kExtensionId[] = "ext1";
   scoped_refptr<const Extension> extension = ExtensionBuilder()
@@ -369,53 +369,48 @@
   typedef DeclarativeRule<FulfillableCondition, SummingAction> Rule;
   URLMatcher matcher;
   std::string error;
-  linked_ptr<Rule::JsonRule> json_rule(new Rule::JsonRule);
+  Rule::JsonRule json_rule;
   const char kExtensionId[] = "ext1";
   scoped_refptr<const Extension> extension = ExtensionBuilder()
                                                  .SetManifest(SimpleManifest())
                                                  .SetID(kExtensionId)
                                                  .Build();
 
-  ASSERT_TRUE(Rule::JsonRule::Populate(
-      *ParseJson("{ \n"
-                 "  \"id\": \"rule1\", \n"
-                 "  \"conditions\": [ \n"
-                 "    {\"url_id\": 1, \"max\": 3}, \n"
-                 "    {\"url_id\": 2, \"max\": 5}, \n"
-                 "  ], \n"
-                 "  \"actions\": [ \n"
-                 "    { \n"
-                 "      \"value\": 2 \n"
-                 "    } \n"
-                 "  ], \n"
-                 "  \"priority\": 200 \n"
-                 "}"),
-      json_rule.get()));
+  ASSERT_TRUE(
+      Rule::JsonRule::Populate(*ParseJson("{ \n"
+                                          "  \"id\": \"rule1\", \n"
+                                          "  \"conditions\": [ \n"
+                                          "    {\"url_id\": 1, \"max\": 3}, \n"
+                                          "    {\"url_id\": 2, \"max\": 5}, \n"
+                                          "  ], \n"
+                                          "  \"actions\": [ \n"
+                                          "    { \n"
+                                          "      \"value\": 2 \n"
+                                          "    } \n"
+                                          "  ], \n"
+                                          "  \"priority\": 200 \n"
+                                          "}"),
+                               &json_rule));
   std::unique_ptr<Rule> rule(Rule::Create(
       matcher.condition_factory(), NULL, extension.get(), base::Time(),
       json_rule, base::Bind(AtLeastOneCondition), &error));
   EXPECT_TRUE(rule);
   EXPECT_EQ("", error);
 
-  ASSERT_TRUE(Rule::JsonRule::Populate(
-      *ParseJson("{ \n"
-                 "  \"id\": \"rule1\", \n"
-                 "  \"conditions\": [ \n"
-                 "  ], \n"
-                 "  \"actions\": [ \n"
-                 "    { \n"
-                 "      \"value\": 2 \n"
-                 "    } \n"
-                 "  ], \n"
-                 "  \"priority\": 200 \n"
-                 "}"),
-      json_rule.get()));
-  rule = Rule::Create(matcher.condition_factory(),
-                      NULL,
-                      extension.get(),
-                      base::Time(),
-                      json_rule,
-                      base::Bind(AtLeastOneCondition),
+  ASSERT_TRUE(Rule::JsonRule::Populate(*ParseJson("{ \n"
+                                                  "  \"id\": \"rule1\", \n"
+                                                  "  \"conditions\": [ \n"
+                                                  "  ], \n"
+                                                  "  \"actions\": [ \n"
+                                                  "    { \n"
+                                                  "      \"value\": 2 \n"
+                                                  "    } \n"
+                                                  "  ], \n"
+                                                  "  \"priority\": 200 \n"
+                                                  "}"),
+                                       &json_rule));
+  rule = Rule::Create(matcher.condition_factory(), NULL, extension.get(),
+                      base::Time(), json_rule, base::Bind(AtLeastOneCondition),
                       &error);
   EXPECT_FALSE(rule);
   EXPECT_EQ("No conditions", error);
diff --git a/extensions/browser/api/declarative/rules_registry.cc b/extensions/browser/api/declarative/rules_registry.cc
index 4a2c90b..1159bed9 100644
--- a/extensions/browser/api/declarative/rules_registry.cc
+++ b/extensions/browser/api/declarative/rules_registry.cc
@@ -39,17 +39,15 @@
 const char kErrorCannotRemoveManifestRules[] =
     "Rules declared in the 'event_rules' manifest field cannot be removed";
 
-base::Value RulesToValue(
-    const std::vector<linked_ptr<api::events::Rule>>& rules) {
+base::Value RulesToValue(const std::vector<const api::events::Rule*>& rules) {
   base::Value value(base::Value::Type::LIST);
-  for (size_t i = 0; i < rules.size(); ++i)
-    value.GetList().push_back(std::move(*rules[i]->ToValue()));
+  for (const auto* rule : rules)
+    value.GetList().push_back(std::move(*rule->ToValue()));
   return value;
 }
 
-std::vector<linked_ptr<api::events::Rule>> RulesFromValue(
-    const base::Value* value) {
-  std::vector<linked_ptr<api::events::Rule>> rules;
+std::vector<api::events::Rule> RulesFromValue(const base::Value* value) {
+  std::vector<api::events::Rule> rules;
 
   const base::ListValue* list = NULL;
   if (!value || !value->GetAsList(&list))
@@ -60,9 +58,9 @@
     const base::DictionaryValue* dict = NULL;
     if (!list->GetDictionary(i, &dict))
       continue;
-    linked_ptr<api::events::Rule> rule(new api::events::Rule());
-    if (api::events::Rule::Populate(*dict, rule.get()))
-      rules.push_back(rule);
+    api::events::Rule rule;
+    if (api::events::Rule::Populate(*dict, &rule))
+      rules.push_back(std::move(rule));
   }
 
   return rules;
@@ -98,32 +96,46 @@
 
 std::string RulesRegistry::AddRulesNoFill(
     const std::string& extension_id,
-    const std::vector<linked_ptr<api::events::Rule>>& rules,
-    RulesDictionary* out) {
+    std::vector<api::events::Rule> rules_in,
+    RulesDictionary* destination,
+    std::vector<const api::events::Rule*>* rules_out) {
   DCHECK_CURRENTLY_ON(owner_thread());
 
   // Verify that all rule IDs are new.
-  for (auto i = rules.cbegin(); i != rules.cend(); ++i) {
-    const RuleId& rule_id = *((*i)->id);
+  for (const auto& rule : rules_in) {
+    const RuleId& rule_id = *(rule.id);
     // Every rule should have a priority assigned.
-    DCHECK((*i)->priority);
+    DCHECK(rule.priority);
     RulesDictionaryKey key(extension_id, rule_id);
     if (rules_.find(key) != rules_.end() ||
         manifest_rules_.find(key) != manifest_rules_.end())
       return base::StringPrintf(kDuplicateRuleId, rule_id.c_str());
   }
 
-  std::string error = AddRulesImpl(extension_id, rules);
+  std::vector<const api::events::Rule*> rule_ptrs;
+  rule_ptrs.reserve(rules_in.size());
+  for (auto& rule : rules_in)
+    rule_ptrs.push_back(&rule);
+  std::string error = AddRulesImpl(extension_id, rule_ptrs);
 
   if (!error.empty())
     return error;
 
   // Commit all rules into |rules_| on success.
-  for (auto i = rules.cbegin(); i != rules.cend(); ++i) {
-    const RuleId& rule_id = *((*i)->id);
+  rule_ptrs.clear();
+  for (auto& rule : rules_in) {
+    const RuleId& rule_id = *(rule.id);
     RulesDictionaryKey key(extension_id, rule_id);
-    (*out)[key] = *i;
+
+    auto insert_result = destination->emplace(key, std::move(rule));
+    // All rule IDs are new so insert had better not have failed.
+    DCHECK(insert_result.second);
+
+    if (rules_out)
+      rule_ptrs.push_back(&(insert_result.first->second));
   }
+  if (rules_out)
+    *rules_out = rule_ptrs;
 
   MaybeProcessChangedRules(extension_id);
   return kSuccess;
@@ -131,22 +143,26 @@
 
 std::string RulesRegistry::AddRules(
     const std::string& extension_id,
-    const std::vector<linked_ptr<api::events::Rule>>& rules) {
-  return AddRulesInternal(extension_id, rules, &rules_);
+    std::vector<api::events::Rule> rules_in,
+    std::vector<const api::events::Rule*>* rules_out) {
+  return AddRulesInternal(extension_id, std::move(rules_in), &rules_,
+                          rules_out);
 }
 
 std::string RulesRegistry::AddRulesInternal(
     const std::string& extension_id,
-    const std::vector<linked_ptr<api::events::Rule>>& rules,
-    RulesDictionary* out) {
+    std::vector<api::events::Rule> rules_in,
+    RulesDictionary* destination,
+    std::vector<const api::events::Rule*>* rules_out) {
   DCHECK_CURRENTLY_ON(owner_thread());
 
-  std::string error = CheckAndFillInOptionalRules(extension_id, rules);
+  std::string error = CheckAndFillInOptionalRules(extension_id, &rules_in);
   if (!error.empty())
     return error;
-  FillInOptionalPriorities(rules);
+  FillInOptionalPriorities(&rules_in);
 
-  return AddRulesNoFill(extension_id, rules, out);
+  return AddRulesNoFill(extension_id, std::move(rules_in), destination,
+                        rules_out);
 }
 
 std::string RulesRegistry::RemoveRules(
@@ -212,36 +228,35 @@
 
 void RulesRegistry::GetRules(const std::string& extension_id,
                              const std::vector<std::string>& rule_identifiers,
-                             std::vector<linked_ptr<api::events::Rule>>* out) {
+                             std::vector<const api::events::Rule*>* out) {
   DCHECK_CURRENTLY_ON(owner_thread());
 
   for (const auto& i : rule_identifiers) {
     RulesDictionaryKey lookup_key(extension_id, i);
     auto entry = rules_.find(lookup_key);
     if (entry != rules_.end())
-      out->push_back(entry->second);
+      out->push_back(&entry->second);
     entry = manifest_rules_.find(lookup_key);
     if (entry != manifest_rules_.end())
-      out->push_back(entry->second);
+      out->push_back(&entry->second);
   }
 }
 
 void RulesRegistry::GetRules(const std::string& extension_id,
-                             const RulesDictionary& rules,
-                             std::vector<linked_ptr<api::events::Rule>>* out) {
-  for (const auto& i : rules) {
+                             RulesDictionary* rules,
+                             std::vector<const api::events::Rule*>* out) {
+  for (auto& i : *rules) {
     const RulesDictionaryKey& key = i.first;
     if (key.first == extension_id)
-      out->push_back(i.second);
+      out->push_back(&i.second);
   }
 }
 
-void RulesRegistry::GetAllRules(
-    const std::string& extension_id,
-    std::vector<linked_ptr<api::events::Rule>>* out) {
+void RulesRegistry::GetAllRules(const std::string& extension_id,
+                                std::vector<const api::events::Rule*>* out) {
   DCHECK_CURRENTLY_ON(owner_thread());
-  GetRules(extension_id, manifest_rules_, out);
-  GetRules(extension_id, rules_, out);
+  GetRules(extension_id, &manifest_rules_, out);
+  GetRules(extension_id, &rules_, out);
 }
 
 void RulesRegistry::OnExtensionUnloaded(const Extension* extension) {
@@ -260,20 +275,24 @@
 
 void RulesRegistry::OnExtensionLoaded(const Extension* extension) {
   DCHECK_CURRENTLY_ON(owner_thread());
-  std::vector<linked_ptr<api::events::Rule>> rules;
+
+  std::vector<const api::events::Rule*> rules;
   GetAllRules(extension->id(), &rules);
+
   DeclarativeManifestData* declarative_data =
       DeclarativeManifestData::Get(extension);
   if (declarative_data) {
-    std::vector<linked_ptr<api::events::Rule>>& manifest_rules =
+    std::vector<api::events::Rule> manifest_rules =
         declarative_data->RulesForEvent(event_name_);
     if (manifest_rules.size()) {
       std::string error =
-          AddRulesInternal(extension->id(), manifest_rules, &manifest_rules_);
+          AddRulesInternal(extension->id(), std::move(manifest_rules),
+                           &manifest_rules_, nullptr);
       if (!error.empty())
         ReportInternalError(extension->id(), error);
     }
   }
+
   std::string error = AddRulesImpl(extension->id(), rules);
   if (!error.empty())
     ReportInternalError(extension->id(), error);
@@ -294,8 +313,8 @@
                                            std::unique_ptr<base::Value> rules) {
   DCHECK_CURRENTLY_ON(owner_thread());
 
-  std::string error =
-      AddRulesNoFill(extension_id, RulesFromValue(rules.get()), &rules_);
+  std::string error = AddRulesNoFill(extension_id, RulesFromValue(rules.get()),
+                                     &rules_, nullptr);
   if (!error.empty())
     ReportInternalError(extension_id, error);
 }
@@ -328,8 +347,8 @@
   DCHECK(base::ContainsKey(process_changed_rules_requested_, extension_id));
   process_changed_rules_requested_[extension_id] = NOT_SCHEDULED_FOR_PROCESSING;
 
-  std::vector<linked_ptr<api::events::Rule>> new_rules;
-  GetRules(extension_id, rules_, &new_rules);
+  std::vector<const api::events::Rule*> new_rules;
+  GetRules(extension_id, &rules_, &new_rules);
   base::PostTaskWithTraits(
       FROM_HERE, {content::BrowserThread::UI},
       base::BindOnce(&RulesCacheDelegate::UpdateRules, cache_delegate_,
@@ -370,16 +389,17 @@
 
 std::string RulesRegistry::CheckAndFillInOptionalRules(
     const std::string& extension_id,
-    const std::vector<linked_ptr<api::events::Rule>>& rules) {
+    std::vector<api::events::Rule>* rules) {
   // IDs we have inserted, in case we need to rollback this operation.
+  // TODO(rdevlin.cronin, avi): Um, this variable is never inserted into; is
+  // this a bug? https://crbug.com/913655
   std::vector<std::string> rollback_log;
 
   // First we insert all rules with existing identifier, so that generated
   // identifiers cannot collide with identifiers passed by the caller.
-  for (auto i = rules.cbegin(); i != rules.cend(); ++i) {
-    api::events::Rule* rule = i->get();
-    if (rule->id.get()) {
-      std::string id = *(rule->id);
+  for (const auto& rule : *rules) {
+    if (rule.id.get()) {
+      std::string id = *(rule.id);
       if (!IsUniqueId(extension_id, id)) {
         RemoveUsedRuleIdentifiers(extension_id, rollback_log);
         return "Id " + id + " was used multiple times.";
@@ -389,22 +409,20 @@
   }
   // Now we generate IDs in case they were not specified in the rules. This
   // cannot fail so we do not need to keep track of a rollback log.
-  for (auto i = rules.cbegin(); i != rules.cend(); ++i) {
-    api::events::Rule* rule = i->get();
-    if (!rule->id.get()) {
-      rule->id.reset(new std::string(GenerateUniqueId(extension_id)));
-      used_rule_identifiers_[extension_id].insert(*(rule->id));
+  for (auto& rule : *rules) {
+    if (!rule.id.get()) {
+      rule.id.reset(new std::string(GenerateUniqueId(extension_id)));
+      used_rule_identifiers_[extension_id].insert(*(rule.id));
     }
   }
   return std::string();
 }
 
 void RulesRegistry::FillInOptionalPriorities(
-    const std::vector<linked_ptr<api::events::Rule>>& rules) {
-  std::vector<linked_ptr<api::events::Rule>>::const_iterator i;
-  for (i = rules.begin(); i != rules.end(); ++i) {
-    if (!(*i)->priority.get())
-      (*i)->priority.reset(new int(DEFAULT_PRIORITY));
+    std::vector<api::events::Rule>* rules) {
+  for (auto& rule : *rules) {
+    if (!rule.priority.get())
+      rule.priority.reset(new int(DEFAULT_PRIORITY));
   }
 }
 
diff --git a/extensions/browser/api/declarative/rules_registry.h b/extensions/browser/api/declarative/rules_registry.h
index 99dfde2..7479a2a 100644
--- a/extensions/browser/api/declarative/rules_registry.h
+++ b/extensions/browser/api/declarative/rules_registry.h
@@ -16,7 +16,6 @@
 #include "base/callback_forward.h"
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "base/memory/linked_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_observer.h"
@@ -62,23 +61,24 @@
 
   // RulesRegistry implementation:
 
-  // Registers |rules|, owned by |extension_id| to this RulesRegistry.
-  // If a concrete RuleRegistry does not support some of the rules,
-  // it may ignore them.
+  // Registers |rules| in this RulesRegistry. If a concrete RuleRegistry does
+  // not support some of the rules, it may ignore them.
   //
   // |rules| is a list of Rule instances following the definition of the
   // declarative extension APIs. It is guaranteed that each rule in |rules| has
   // a unique name within the scope of |extension_id| that has not been
   // registered before, unless it has been removed again.
-  // The ownership of rules remains with the caller.
   //
-  // Returns an empty string if the function is successful or an error
-  // message otherwise.
+  // Returns an empty string if the function is successful or an error message
+  // otherwise. If the function is successful, and if the |rules_out| parameter
+  // is non-null, pointers to the added rules are returned.
   //
   // IMPORTANT: This function is atomic. Either all rules that are deemed
   // relevant are added or none.
-  std::string AddRules(const std::string& extension_id,
-                       const std::vector<linked_ptr<api::events::Rule>>& rules);
+  std::string AddRules(
+      const std::string& extension_id,
+      std::vector<api::events::Rule> rules_in,
+      std::vector<const api::events::Rule*>* rules_out = nullptr);
 
   // Unregisters all rules listed in |rule_identifiers| and owned by
   // |extension_id| from this RulesRegistry.
@@ -101,14 +101,14 @@
   // registered in this RuleRegistry. Entries in |rule_identifiers| that
   // are unknown are ignored.
   //
-  // The returned rules are stored in |out|. Ownership is passed to the caller.
+  // The returned rules are stored in |out|.
   void GetRules(const std::string& extension_id,
                 const std::vector<std::string>& rule_identifiers,
-                std::vector<linked_ptr<api::events::Rule>>* out);
+                std::vector<const api::events::Rule*>* out);
 
   // Same as GetRules but returns all rules owned by |extension_id|.
   void GetAllRules(const std::string& extension_id,
-                   std::vector<linked_ptr<api::events::Rule>>* out);
+                   std::vector<const api::events::Rule*>* out);
 
   // Called to notify the RulesRegistry that the extension availability has
   // changed, so that the registry can update which rules are active.
@@ -146,7 +146,7 @@
   // automatically cache the rules and re-call *Impl on browser startup.
   virtual std::string AddRulesImpl(
       const std::string& extension_id,
-      const std::vector<linked_ptr<api::events::Rule>>& rules) = 0;
+      const std::vector<const api::events::Rule*>& rules) = 0;
   virtual std::string RemoveRulesImpl(
       const std::string& extension_id,
       const std::vector<std::string>& rule_identifiers) = 0;
@@ -157,10 +157,14 @@
   friend class base::RefCountedThreadSafe<RulesRegistry>;
   friend class RulesCacheDelegate;
 
-  typedef std::string RuleId;
-  typedef std::pair<ExtensionId, RuleId> RulesDictionaryKey;
-  typedef std::map<RulesDictionaryKey, linked_ptr<api::events::Rule>>
-      RulesDictionary;
+  using RuleId = std::string;
+  using RulesDictionaryKey = std::pair<ExtensionId, RuleId>;
+
+  // NOTE: The property of stability of iterators of a map during insertion is
+  // relied upon here. If this type needs to change, beware that this will
+  // severely complicate returning valid pointers to callers of member functions
+  // of this class.
+  using RulesDictionary = std::map<RulesDictionaryKey, api::events::Rule>;
   enum ProcessChangedRulesState {
     // ProcessChangedRules can never be called, |cache_delegate_| is NULL.
     NEVER_PROCESS,
@@ -170,19 +174,22 @@
     // to schedule one.
     NOT_SCHEDULED_FOR_PROCESSING
   };
-  typedef std::map<ExtensionId, ProcessChangedRulesState> ProcessStateMap;
+  using ProcessStateMap = std::map<ExtensionId, ProcessChangedRulesState>;
 
   base::WeakPtr<RulesRegistry> GetWeakPtr() {
     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
     return weak_ptr_factory_.GetWeakPtr();
   }
 
-  // Internal implementation of the AddRules interface which adds
-  // |from_manifest| which is true when the source is the manifest.
+  // Internal implementation of the AddRules interface which adds the rules to
+  // the |destination| RulesDictionary. If the function is successful, and if
+  // the |rules_out| parameter is non-null, pointers to the added rules are
+  // returned.
   std::string AddRulesInternal(
       const std::string& extension_id,
-      const std::vector<linked_ptr<api::events::Rule>>& rules,
-      RulesDictionary* out);
+      std::vector<api::events::Rule> rules_in,
+      RulesDictionary* destination,
+      std::vector<const api::events::Rule*>* rules_out);
 
   // The precondition for calling this method is that all rules have unique IDs.
   // AddRules establishes this precondition and calls into this method.
@@ -190,17 +197,19 @@
   // CheckAndFillInOptionalRules for improved performance.
   //
   // Returns an empty string if the function is successful or an error
-  // message otherwise.
-  std::string AddRulesNoFill(
-      const std::string& extension_id,
-      const std::vector<linked_ptr<api::events::Rule>>& rules,
-      RulesDictionary* out);
+  // message otherwise. If the function is successful, and if the
+  // |rules_out| parameter is non-null, pointers to the added rules are
+  // returned.
+  std::string AddRulesNoFill(const std::string& extension_id,
+                             std::vector<api::events::Rule> rules_in,
+                             RulesDictionary* destination,
+                             std::vector<const api::events::Rule*>* rules_out);
 
   // Same as GetRules but returns all rules owned by |extension_id| for a given
   // |rules| dictionary.
   void GetRules(const std::string& extension_id,
-                const RulesDictionary& rules,
-                std::vector<linked_ptr<api::events::Rule>>* out);
+                RulesDictionary* rules,
+                std::vector<const api::events::Rule*>* out);
 
   // Common processing after extension's rules have changed.
   void ProcessChangedRules(const std::string& extension_id);
@@ -266,11 +275,10 @@
   // returns a non-empty error message.
   std::string CheckAndFillInOptionalRules(
       const std::string& extension_id,
-      const std::vector<linked_ptr<api::events::Rule>>& rules);
+      std::vector<api::events::Rule>* rules);
 
   // Initializes the priority fields in case they have not been set.
-  void FillInOptionalPriorities(
-      const std::vector<linked_ptr<api::events::Rule>>& rules);
+  void FillInOptionalPriorities(std::vector<api::events::Rule>* rules);
 
   // Removes all |identifiers| of |extension_id| from |used_rule_identifiers_|.
   void RemoveUsedRuleIdentifiers(const std::string& extension_id,
@@ -280,9 +288,8 @@
   // |extension_id|.
   void RemoveAllUsedRuleIdentifiers(const std::string& extension_id);
 
-  typedef std::string RuleIdentifier;
-  typedef std::map<ExtensionId, std::set<RuleIdentifier> > RuleIdentifiersMap;
-  RuleIdentifiersMap used_rule_identifiers_;
+  using RuleIdentifier = std::string;
+  std::map<ExtensionId, std::set<RuleIdentifier>> used_rule_identifiers_;
   int last_generated_rule_identifier_id_;
 
   // |cache_delegate_| is owned by the registry service. If |cache_delegate_| is
diff --git a/extensions/browser/api/declarative/rules_registry_unittest.cc b/extensions/browser/api/declarative/rules_registry_unittest.cc
index 07cc445..2b21e36 100644
--- a/extensions/browser/api/declarative/rules_registry_unittest.cc
+++ b/extensions/browser/api/declarative/rules_registry_unittest.cc
@@ -36,37 +36,44 @@
 
   // Add rules and check that their identifiers are filled and unique.
 
-  std::vector<linked_ptr<api::events::Rule>> add_rules;
-  add_rules.push_back(make_linked_ptr(new api::events::Rule));
-  add_rules.push_back(make_linked_ptr(new api::events::Rule));
-  error = registry->AddRules(kExtensionId, add_rules);
-  EXPECT_TRUE(error.empty()) << error;
+  {
+    std::vector<api::events::Rule> add_rules;
+    add_rules.emplace_back();
+    add_rules.emplace_back();
+    error = registry->AddRules(kExtensionId, std::move(add_rules));
+    EXPECT_TRUE(error.empty()) << error;
+  }
 
-  std::vector<linked_ptr<api::events::Rule>> get_rules;
+  std::vector<const api::events::Rule*> get_rules;
   registry->GetAllRules(kExtensionId, &get_rules);
 
   ASSERT_EQ(2u, get_rules.size());
 
   ASSERT_TRUE(get_rules[0]->id.get());
-  EXPECT_NE("", *get_rules[0]->id);
+  // Make a copy of the id that this rule was assigned so that we can try to
+  // reuse it later when the rule is gone.
+  std::string id0 = *get_rules[0]->id;
+  EXPECT_NE("", id0);
 
   ASSERT_TRUE(get_rules[1]->id.get());
   EXPECT_NE("", *get_rules[1]->id);
 
-  EXPECT_NE(*get_rules[0]->id, *get_rules[1]->id);
+  EXPECT_NE(id0, *get_rules[1]->id);
 
   EXPECT_EQ(1u /*extensions*/ + 2u /*rules*/,
             registry->GetNumberOfUsedRuleIdentifiersForTesting());
 
   // Check that we cannot add a new rule with the same ID.
 
-  std::vector<linked_ptr<api::events::Rule>> add_rules_2;
-  add_rules_2.push_back(make_linked_ptr(new api::events::Rule));
-  add_rules_2[0]->id.reset(new std::string(*get_rules[0]->id));
-  error = registry->AddRules(kExtensionId, add_rules_2);
-  EXPECT_FALSE(error.empty());
+  {
+    std::vector<api::events::Rule> add_rules;
+    add_rules.emplace_back();
+    add_rules[0].id.reset(new std::string(id0));
+    error = registry->AddRules(kExtensionId, std::move(add_rules));
+    EXPECT_FALSE(error.empty());
+  }
 
-  std::vector<linked_ptr<api::events::Rule>> get_rules_2;
+  std::vector<const api::events::Rule*> get_rules_2;
   registry->GetAllRules(kExtensionId, &get_rules_2);
   ASSERT_EQ(2u, get_rules_2.size());
   EXPECT_EQ(1u /*extensions*/ + 2u /*rules*/,
@@ -75,26 +82,28 @@
   // Check that we can register the old rule IDs once they were unregistered.
 
   std::vector<std::string> remove_rules_3;
-  remove_rules_3.push_back(*get_rules[0]->id);
+  remove_rules_3.push_back(id0);
   error = registry->RemoveRules(kExtensionId, remove_rules_3);
   EXPECT_TRUE(error.empty()) << error;
 
   EXPECT_EQ(1u /*extensions*/ + 1u /*rules*/,
             registry->GetNumberOfUsedRuleIdentifiersForTesting());
 
-  std::vector<linked_ptr<api::events::Rule>> get_rules_3a;
+  std::vector<const api::events::Rule*> get_rules_3a;
   registry->GetAllRules(kExtensionId, &get_rules_3a);
   ASSERT_EQ(1u, get_rules_3a.size());
 
-  std::vector<linked_ptr<api::events::Rule>> add_rules_3;
-  add_rules_3.push_back(make_linked_ptr(new api::events::Rule));
-  add_rules_3[0]->id.reset(new std::string(*get_rules[0]->id));
-  error = registry->AddRules(kExtensionId, add_rules_3);
-  EXPECT_TRUE(error.empty()) << error;
-  EXPECT_EQ(1u /*extensions*/ + 2u /*rules*/,
-            registry->GetNumberOfUsedRuleIdentifiersForTesting());
+  {
+    std::vector<api::events::Rule> add_rules;
+    add_rules.emplace_back();
+    add_rules[0].id.reset(new std::string(id0));
+    error = registry->AddRules(kExtensionId, std::move(add_rules));
+    EXPECT_TRUE(error.empty()) << error;
+    EXPECT_EQ(1u /*extensions*/ + 2u /*rules*/,
+              registry->GetNumberOfUsedRuleIdentifiersForTesting());
+  }
 
-  std::vector<linked_ptr<api::events::Rule>> get_rules_3b;
+  std::vector<const api::events::Rule*> get_rules_3b;
   registry->GetAllRules(kExtensionId, &get_rules_3b);
   ASSERT_EQ(2u, get_rules_3b.size());
 
@@ -105,20 +114,22 @@
   EXPECT_EQ(0u /*extensions*/ + 0u /*rules*/,
             registry->GetNumberOfUsedRuleIdentifiersForTesting());
 
-  std::vector<linked_ptr<api::events::Rule>> get_rules_4a;
+  std::vector<const api::events::Rule*> get_rules_4a;
   registry->GetAllRules(kExtensionId, &get_rules_4a);
   ASSERT_TRUE(get_rules_4a.empty());
 
-  std::vector<linked_ptr<api::events::Rule>> add_rules_4;
-  add_rules_4.push_back(make_linked_ptr(new api::events::Rule));
-  add_rules_4[0]->id.reset(new std::string(kRuleId));
-  error = registry->AddRules(kExtensionId, add_rules_4);
-  EXPECT_TRUE(error.empty()) << error;
+  {
+    std::vector<api::events::Rule> add_rules;
+    add_rules.emplace_back();
+    add_rules[0].id.reset(new std::string(kRuleId));
+    error = registry->AddRules(kExtensionId, std::move(add_rules));
+    EXPECT_TRUE(error.empty()) << error;
+  }
 
   EXPECT_EQ(1u /*extensions*/ + 1u /*rules*/,
             registry->GetNumberOfUsedRuleIdentifiersForTesting());
 
-  std::vector<linked_ptr<api::events::Rule>> get_rules_4b;
+  std::vector<const api::events::Rule*> get_rules_4b;
   registry->GetAllRules(kExtensionId, &get_rules_4b);
 
   ASSERT_EQ(1u, get_rules_4b.size());
@@ -147,14 +158,16 @@
 
   // Add rules and check that their priorities are filled if they are empty.
 
-  std::vector<linked_ptr<api::events::Rule>> add_rules;
-  add_rules.push_back(make_linked_ptr(new api::events::Rule));
-  add_rules[0]->priority.reset(new int(2));
-  add_rules.push_back(make_linked_ptr(new api::events::Rule));
-  error = registry->AddRules(kExtensionId, add_rules);
-  EXPECT_TRUE(error.empty()) << error;
+  {
+    std::vector<api::events::Rule> add_rules;
+    add_rules.emplace_back();
+    add_rules[0].priority.reset(new int(2));
+    add_rules.emplace_back();
+    error = registry->AddRules(kExtensionId, std::move(add_rules));
+    EXPECT_TRUE(error.empty()) << error;
+  }
 
-  std::vector<linked_ptr<api::events::Rule>> get_rules;
+  std::vector<const api::events::Rule*> get_rules;
   registry->GetAllRules(kExtensionId, &get_rules);
 
   ASSERT_EQ(2u, get_rules.size());
@@ -220,7 +233,7 @@
   // Simulate what RulesRegistryService would do on extension load.
   registry->OnExtensionLoaded(extension.get());
 
-  std::vector<linked_ptr<api::events::Rule>> get_rules;
+  std::vector<const api::events::Rule*> get_rules;
   registry->GetAllRules(kExtensionId, &get_rules);
 
   ASSERT_EQ(2u, get_rules.size());
@@ -287,17 +300,20 @@
       content::BrowserThread::UI, "declarativeContent.onPageChanged", key);
   // Simulate what RulesRegistryService would do on extension load.
   registry->OnExtensionLoaded(extension.get());
-  // Add some extra rules outside of the manifest.
-  std::vector<linked_ptr<api::events::Rule>> add_rules;
-  linked_ptr<api::events::Rule> rule_1 = make_linked_ptr(new api::events::Rule);
-  rule_1->id.reset(new std::string("rule_1"));
-  linked_ptr<api::events::Rule> rule_2 = make_linked_ptr(new api::events::Rule);
-  rule_2->id.reset(new std::string("rule_2"));
-  add_rules.push_back(rule_1);
-  add_rules.push_back(rule_2);
-  registry->AddRules(kExtensionId, add_rules);
 
-  std::vector<linked_ptr<api::events::Rule>> get_rules;
+  {
+    // Add some extra rules outside of the manifest.
+    std::vector<api::events::Rule> add_rules;
+    api::events::Rule rule_1;
+    rule_1.id.reset(new std::string("rule_1"));
+    api::events::Rule rule_2;
+    rule_2.id.reset(new std::string("rule_2"));
+    add_rules.push_back(std::move(rule_1));
+    add_rules.push_back(std::move(rule_2));
+    registry->AddRules(kExtensionId, std::move(add_rules));
+  }
+
+  std::vector<const api::events::Rule*> get_rules;
   registry->GetAllRules(kExtensionId, &get_rules);
   ASSERT_EQ(3u, get_rules.size());
   EXPECT_EQ("manifest_rule_0", *(get_rules[0]->id));
diff --git a/extensions/browser/api/declarative/test_rules_registry.cc b/extensions/browser/api/declarative/test_rules_registry.cc
index a8d35952..1aca74b2 100644
--- a/extensions/browser/api/declarative/test_rules_registry.cc
+++ b/extensions/browser/api/declarative/test_rules_registry.cc
@@ -32,7 +32,7 @@
 
 std::string TestRulesRegistry::AddRulesImpl(
     const std::string& extension_id,
-    const std::vector<linked_ptr<api::events::Rule>>& rules) {
+    const std::vector<const api::events::Rule*>& rules) {
   return result_;
 }
 
diff --git a/extensions/browser/api/declarative/test_rules_registry.h b/extensions/browser/api/declarative/test_rules_registry.h
index 3db50251..4df114f6 100644
--- a/extensions/browser/api/declarative/test_rules_registry.h
+++ b/extensions/browser/api/declarative/test_rules_registry.h
@@ -26,7 +26,7 @@
   // RulesRegistry implementation:
   std::string AddRulesImpl(
       const std::string& extension_id,
-      const std::vector<linked_ptr<api::events::Rule>>& rules) override;
+      const std::vector<const api::events::Rule*>& rules) override;
   std::string RemoveRulesImpl(
       const std::string& extension_id,
       const std::vector<std::string>& rule_identifiers) override;
diff --git a/extensions/browser/api/declarative_webrequest/webrequest_rules_registry.cc b/extensions/browser/api/declarative_webrequest/webrequest_rules_registry.cc
index fe3bec6..96bf7a8a3 100644
--- a/extensions/browser/api/declarative_webrequest/webrequest_rules_registry.cc
+++ b/extensions/browser/api/declarative_webrequest/webrequest_rules_registry.cc
@@ -151,7 +151,7 @@
 
 std::string WebRequestRulesRegistry::AddRulesImpl(
     const std::string& extension_id,
-    const std::vector<linked_ptr<api::events::Rule>>& rules) {
+    const std::vector<const api::events::Rule*>& rules) {
   typedef std::pair<WebRequestRule::RuleId, linked_ptr<const WebRequestRule>>
       IdRulePair;
   typedef std::vector<IdRulePair> RulesVector;
@@ -166,13 +166,13 @@
       extension_info_map_->extensions().GetByID(extension_id);
   RulesMap& registered_rules = webrequest_rules_[extension_id];
 
-  for (const linked_ptr<api::events::Rule>& rule : rules) {
+  for (auto* rule : rules) {
     const WebRequestRule::RuleId& rule_id(*rule->id);
     DCHECK(registered_rules.find(rule_id) == registered_rules.end());
 
     std::unique_ptr<WebRequestRule> webrequest_rule(WebRequestRule::Create(
         url_matcher_.condition_factory(), browser_context(), extension,
-        extension_installation_time, rule,
+        extension_installation_time, *rule,
         base::Bind(&Checker, base::Unretained(extension)), &error));
     if (!error.empty()) {
       // We don't return here, because we want to clear temporary
diff --git a/extensions/browser/api/declarative_webrequest/webrequest_rules_registry.h b/extensions/browser/api/declarative_webrequest/webrequest_rules_registry.h
index b30eb30..405ef7d 100644
--- a/extensions/browser/api/declarative_webrequest/webrequest_rules_registry.h
+++ b/extensions/browser/api/declarative_webrequest/webrequest_rules_registry.h
@@ -91,7 +91,7 @@
   // Implementation of RulesRegistry:
   std::string AddRulesImpl(
       const std::string& extension_id,
-      const std::vector<linked_ptr<api::events::Rule>>& rules) override;
+      const std::vector<const api::events::Rule*>& rules) override;
   std::string RemoveRulesImpl(
       const std::string& extension_id,
       const std::vector<std::string>& rule_identifiers) override;
diff --git a/extensions/browser/install/extension_install_ui.h b/extensions/browser/install/extension_install_ui.h
index 2637882..f27765e 100644
--- a/extensions/browser/install/extension_install_ui.h
+++ b/extensions/browser/install/extension_install_ui.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
 #include "ui/gfx/native_widget_types.h"
 
 class SkBitmap;
@@ -24,8 +25,9 @@
   virtual ~ExtensionInstallUI();
 
   // Called when an extension was installed.
-  virtual void OnInstallSuccess(const extensions::Extension* extension,
-                                const SkBitmap* icon) = 0;
+  virtual void OnInstallSuccess(
+      scoped_refptr<const extensions::Extension> extension,
+      const SkBitmap* icon) = 0;
 
   // Called when an extension failed to install.
   virtual void OnInstallFailure(const extensions::CrxInstallError& error) = 0;
diff --git a/extensions/common/api/declarative/declarative_manifest_data.cc b/extensions/common/api/declarative/declarative_manifest_data.cc
index 6a81a6f2..ce4c9c7e 100644
--- a/extensions/common/api/declarative/declarative_manifest_data.cc
+++ b/extensions/common/api/declarative/declarative_manifest_data.cc
@@ -143,23 +143,35 @@
       return std::unique_ptr<DeclarativeManifestData>();
     }
 
-    linked_ptr<Rule> rule(new Rule());
-    if (!Rule::Populate(*dict, rule.get())) {
+    Rule rule;
+    if (!Rule::Populate(*dict, &rule)) {
       error_builder.Append("rule failed to populate");
       return std::unique_ptr<DeclarativeManifestData>();
     }
 
-    if (!ConvertManifestRule(*rule, &error_builder))
+    if (!ConvertManifestRule(rule, &error_builder))
       return std::unique_ptr<DeclarativeManifestData>();
 
-    result->event_rules_map_[event].push_back(rule);
+    result->event_rules_map_[event].push_back(std::move(rule));
   }
   return result;
 }
 
-std::vector<linked_ptr<DeclarativeManifestData::Rule>>&
+std::vector<DeclarativeManifestData::Rule>
 DeclarativeManifestData::RulesForEvent(const std::string& event) {
-  return event_rules_map_[event];
+  const auto& rules = event_rules_map_[event];
+  std::vector<DeclarativeManifestData::Rule> result;
+  result.reserve(rules.size());
+  for (const auto& rule : rules) {
+    // TODO(rdevlin.cronin): It would be nice if we could have the RulesRegistry
+    // reference the rules owned here, but the ownership issues are a bit
+    // tricky. Revisit this.
+    std::unique_ptr<base::DictionaryValue> rule_value = rule.ToValue();
+    std::unique_ptr<DeclarativeManifestData::Rule> rule_copy =
+        DeclarativeManifestData::Rule::FromValue(*rule_value);
+    result.push_back(std::move(*rule_copy));
+  }
+  return result;
 }
 
 }  // namespace extensions
diff --git a/extensions/common/api/declarative/declarative_manifest_data.h b/extensions/common/api/declarative/declarative_manifest_data.h
index dba17438..4560979f 100644
--- a/extensions/common/api/declarative/declarative_manifest_data.h
+++ b/extensions/common/api/declarative/declarative_manifest_data.h
@@ -8,7 +8,6 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "base/memory/linked_ptr.h"
 #include "base/strings/string16.h"
 #include "extensions/common/api/events.h"
 #include "extensions/common/extension.h"
@@ -19,7 +18,7 @@
 // The parsed form of the "event_rules" manifest entry.
 class DeclarativeManifestData : public Extension::ManifestData {
  public:
-  typedef extensions::api::events::Rule Rule;
+  using Rule = extensions::api::events::Rule;
 
   DeclarativeManifestData();
   ~DeclarativeManifestData() override;
@@ -34,11 +33,10 @@
       const base::Value& value,
       base::string16* error);
 
-  std::vector<linked_ptr<DeclarativeManifestData::Rule>>& RulesForEvent(
-      const std::string& event);
+  std::vector<Rule> RulesForEvent(const std::string& event);
 
  private:
-  std::map<std::string, std::vector<linked_ptr<Rule>>> event_rules_map_;
+  std::map<std::string, std::vector<Rule>> event_rules_map_;
   DISALLOW_COPY_AND_ASSIGN(DeclarativeManifestData);
 };
 
diff --git a/extensions/common/api/declarative/declarative_manifest_unittest.cc b/extensions/common/api/declarative/declarative_manifest_unittest.cc
index 3990dde..56c00c1 100644
--- a/extensions/common/api/declarative/declarative_manifest_unittest.cc
+++ b/extensions/common/api/declarative/declarative_manifest_unittest.cc
@@ -18,7 +18,7 @@
   DeclarativeManifestData* manifest_data =
       DeclarativeManifestData::Get(extension.get());
   ASSERT_TRUE(manifest_data);
-  std::vector<linked_ptr<DeclarativeManifestData::Rule>>& rules =
+  std::vector<DeclarativeManifestData::Rule> rules =
       manifest_data->RulesForEvent("foo");
   EXPECT_EQ(1u, rules.size());
   std::unique_ptr<base::DictionaryValue> expected_rule = ParseDictionary(
@@ -30,7 +30,7 @@
       "    \"instanceType\" : \"condition_type\""
       "  }]"
       "}");
-  EXPECT_TRUE(expected_rule->Equals(rules[0]->ToValue().get()));
+  EXPECT_TRUE(expected_rule->Equals(rules[0].ToValue().get()));
 }
 
 TEST_F(DeclarativeManifestTest, ConditionMissingType) {
diff --git a/gpu/command_buffer/client/transfer_buffer.cc b/gpu/command_buffer/client/transfer_buffer.cc
index 44570ad..cf346c8b 100644
--- a/gpu/command_buffer/client/transfer_buffer.cc
+++ b/gpu/command_buffer/client/transfer_buffer.cc
@@ -153,7 +153,7 @@
   if (usable_ && (shrink || needed_buffer_size > current_size)) {
     // We should never attempt to reallocate the buffer if someone has a result
     // pointer that hasn't been released. This would cause a use-after-free.
-    CHECK(!outstanding_result_pointer_);
+    DCHECK(!outstanding_result_pointer_);
     if (HaveBuffer()) {
       Free();
     }
@@ -177,7 +177,7 @@
     unsigned int size_to_allocate) {
   // We should never attempt to shrink the buffer if someone has a result
   // pointer that hasn't been released.
-  CHECK(!outstanding_result_pointer_);
+  DCHECK(!outstanding_result_pointer_);
   // Don't resize the buffer while blocks are in use to avoid throwing away
   // live allocations.
   if (HaveBuffer() && ring_buffer_->NumUsedBlocks() > 0)
@@ -244,13 +244,17 @@
   // ensure this invariant.
   DCHECK(!outstanding_result_pointer_);
   ReallocateRingBuffer(result_size_);
+#if DCHECK_IS_ON()
   outstanding_result_pointer_ = true;
+#endif
   return result_buffer_;
 }
 
 void TransferBuffer::ReleaseResultBuffer() {
   DCHECK(outstanding_result_pointer_);
+#if DCHECK_IS_ON()
   outstanding_result_pointer_ = false;
+#endif
 }
 
 int TransferBuffer::GetResultOffset() {
diff --git a/gpu/command_buffer/client/transfer_buffer_unittest.cc b/gpu/command_buffer/client/transfer_buffer_unittest.cc
index 802961ba..b1884307 100644
--- a/gpu/command_buffer/client/transfer_buffer_unittest.cc
+++ b/gpu/command_buffer/client/transfer_buffer_unittest.cc
@@ -742,7 +742,7 @@
   EXPECT_EQ(transfer_buffer_->GetFragmentedFreeSize(), original_free_size);
 }
 
-#if defined(GTEST_HAS_DEATH_TEST)
+#if defined(GTEST_HAS_DEATH_TEST) && DCHECK_IS_ON()
 
 TEST_F(TransferBufferTest, ResizeDuringScopedResultPtr) {
   Initialize();
@@ -756,7 +756,6 @@
                "outstanding_result_pointer_");
 }
 
-#if DCHECK_IS_ON()
 TEST_F(TransferBufferTest, AllocDuringScopedResultPtr) {
   Initialize();
   ScopedResultPtr<int> ptr(transfer_buffer_.get());
@@ -776,7 +775,6 @@
                "outstanding_result_pointer_");
 }
 
-#endif  // DCHECK_IS_ON()
-#endif  // defined(GTEST_HAS_DEATH_TEST)
+#endif  // defined(GTEST_HAS_DEATH_TEST) && DCHECK_IS_ON()
 
 }  // namespace gpu
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg
index e869522..80522a4 100644
--- a/infra/config/global/cr-buildbucket.cfg
+++ b/infra/config/global/cr-buildbucket.cfg
@@ -2869,6 +2869,73 @@
 }
 
 buckets {
+  name: "master.chromium.android.fyi"
+  acl_sets: "waterfall"
+}
+
+buckets {
+  name: "master.chromium.perf"
+  acl_sets: "waterfall"
+}
+
+buckets {
+  name: "master.chromium.perf.fyi"
+  acl_sets: "waterfall"
+}
+
+# Defining blink build bucket in chromium/src repo because
+# blink will merge to chromium/src.
+# Also git admins are reluctant to create infra/config branches
+# in svn-based git repos (crbug.com/513580).
+buckets {
+  name: "master.tryserver.blink"
+  acl_sets: "tryserver"
+}
+
+buckets {
+  name: "master.tryserver.chromium.android"
+  acl_sets: "tryserver"
+}
+
+buckets {
+  name: "master.tryserver.chromium.chromiumos"
+  acl_sets: "tryserver"
+}
+
+buckets {
+  name: "master.tryserver.chromium.gpu"
+  acl_sets: "tryserver"
+}
+
+buckets {
+  name: "master.tryserver.chromium.linux"
+  acl_sets: "tryserver"
+}
+
+buckets {
+  name: "master.tryserver.chromium.mac"
+  acl_sets: "tryserver"
+}
+
+buckets {
+  name: "master.tryserver.chromium.perf"
+  acl_sets: "tryserver"
+  acls {
+    role: SCHEDULER
+    group: "service-account-chromium-bisect"
+  }
+  acls {
+    role: SCHEDULER
+    group: "service-account-chromeperf"
+  }
+}
+
+buckets {
+  name: "master.tryserver.chromium.win"
+  acl_sets: "tryserver"
+}
+
+buckets {
   name: "try"
 
   # NOTE: these ACLs should be kept in sync with those in the other
@@ -3345,11 +3412,6 @@
       mixins: "android-try"
     }
     builders {
-      name: "android_coverage"
-      dimensions: "os:Ubuntu-14.04"
-      mixins: "android-try"
-    }
-    builders {
       name: "linux_android_dbg_ng"
       dimensions: "os:Ubuntu-14.04"
       mixins: "android-try"
@@ -3540,70 +3602,3 @@
     builders { mixins: "win" name: "WebRTC Chromium FYI Win8 Tester" }
   }
 }
-
-buckets {
-  name: "master.chromium.android.fyi"
-  acl_sets: "waterfall"
-}
-
-buckets {
-  name: "master.chromium.perf"
-  acl_sets: "waterfall"
-}
-
-buckets {
-  name: "master.chromium.perf.fyi"
-  acl_sets: "waterfall"
-}
-
-# Defining blink build bucket in chromium/src repo because
-# blink will merge to chromium/src.
-# Also git admins are reluctant to create infra/config branches
-# in svn-based git repos (crbug.com/513580).
-buckets {
-  name: "master.tryserver.blink"
-  acl_sets: "tryserver"
-}
-
-buckets {
-  name: "master.tryserver.chromium.android"
-  acl_sets: "tryserver"
-}
-
-buckets {
-  name: "master.tryserver.chromium.chromiumos"
-  acl_sets: "tryserver"
-}
-
-buckets {
-  name: "master.tryserver.chromium.gpu"
-  acl_sets: "tryserver"
-}
-
-buckets {
-  name: "master.tryserver.chromium.linux"
-  acl_sets: "tryserver"
-}
-
-buckets {
-  name: "master.tryserver.chromium.mac"
-  acl_sets: "tryserver"
-}
-
-buckets {
-  name: "master.tryserver.chromium.perf"
-  acl_sets: "tryserver"
-  acls {
-    role: SCHEDULER
-    group: "service-account-chromium-bisect"
-  }
-  acls {
-    role: SCHEDULER
-    group: "service-account-chromeperf"
-  }
-}
-
-buckets {
-  name: "master.tryserver.chromium.win"
-  acl_sets: "tryserver"
-}
diff --git a/infra/config/global/luci-milo.cfg b/infra/config/global/luci-milo.cfg
index 161553e..55ebd1e 100644
--- a/infra/config/global/luci-milo.cfg
+++ b/infra/config/global/luci-milo.cfg
@@ -3987,9 +3987,6 @@
     name: "buildbot/tryserver.chromium.android/android_compile_x86_dbg"
   }
   builders {
-    name: "buildbucket/luci.chromium.try/android_coverage"
-  }
-  builders {
     name: "buildbucket/luci.chromium.try/android_cronet"
   }
   builders {
diff --git a/infra/config/global/luci-scheduler.cfg b/infra/config/global/luci-scheduler.cfg
index 27d8bd4..b1f59a8 100644
--- a/infra/config/global/luci-scheduler.cfg
+++ b/infra/config/global/luci-scheduler.cfg
@@ -310,6 +310,7 @@
   triggers: "ios12-sdk-device"
   triggers: "ios12-sdk-simulator"
   triggers: "linux-annotator-rel"
+  triggers: "linux-autofill-captured-sites-rel"
   triggers: "linux-blink-animation-use-time-delta"
   triggers: "linux-blink-heap-incremental-marking"
   triggers: "linux-blink-heap-verification"
@@ -325,6 +326,7 @@
   triggers: "linux-tcmalloc-rel"
   triggers: "linux-win_cross-rel"
   triggers: "linux-xenial-rel"
+  triggers: "mac-autofill-captured-sites-rel"
   triggers: "mac-code-coverage-generation"
   triggers: "mac-dbg"
   triggers: "mac-hermetic-upgrade-rel"
@@ -338,6 +340,7 @@
   triggers: "WebRTC Chromium Win Builder"
   triggers: "win-annotator-rel"
   triggers: "win-asan"
+  triggers: "win-autofill-captured-sites-rel"
   triggers: "win-dbg"
   triggers: "win-jumbo-rel"
   triggers: "win-rel"
diff --git a/ios/chrome/browser/sync/sessions/ios_chrome_local_session_event_router.h b/ios/chrome/browser/sync/sessions/ios_chrome_local_session_event_router.h
index 81deffa..82ac6ec 100644
--- a/ios/chrome/browser/sync/sessions/ios_chrome_local_session_event_router.h
+++ b/ios/chrome/browser/sync/sessions/ios_chrome_local_session_event_router.h
@@ -58,7 +58,7 @@
   // web::WebStateObserver:
   void NavigationItemsPruned(web::WebState* web_state,
                              size_t pruned_item_count) override;
-  void NavigationItemChanged(web::WebState* web_state) override;
+  void TitleWasSet(web::WebState* web_state) override;
   void DidFinishNavigation(web::WebState* web_state,
                            web::NavigationContext* navigation_context) override;
   void PageLoaded(
diff --git a/ios/chrome/browser/sync/sessions/ios_chrome_local_session_event_router.mm b/ios/chrome/browser/sync/sessions/ios_chrome_local_session_event_router.mm
index 851ea121..e56a5f6 100644
--- a/ios/chrome/browser/sync/sessions/ios_chrome_local_session_event_router.mm
+++ b/ios/chrome/browser/sync/sessions/ios_chrome_local_session_event_router.mm
@@ -117,8 +117,7 @@
   OnWebStateChange(web_state);
 }
 
-void IOSChromeLocalSessionEventRouter::NavigationItemChanged(
-    web::WebState* web_state) {
+void IOSChromeLocalSessionEventRouter::TitleWasSet(web::WebState* web_state) {
   OnWebStateChange(web_state);
 }
 
diff --git a/ios/chrome/browser/test/perf_test_with_bvc_ios.mm b/ios/chrome/browser/test/perf_test_with_bvc_ios.mm
index 1c4c4093..27f1817 100644
--- a/ios/chrome/browser/test/perf_test_with_bvc_ios.mm
+++ b/ios/chrome/browser/test/perf_test_with_bvc_ios.mm
@@ -17,6 +17,7 @@
 #import "ios/chrome/browser/sessions/session_service_ios.h"
 #import "ios/chrome/browser/sessions/session_window_ios.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
+#import "ios/chrome/browser/ui/browser_view_controller+private.h"
 #import "ios/chrome/browser/ui/browser_view_controller.h"
 #import "ios/chrome/browser/ui/browser_view_controller_dependency_factory.h"
 #import "ios/chrome/browser/ui/commands/command_dispatcher.h"
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn
index b7309f7..3d7ed141 100644
--- a/ios/chrome/browser/ui/BUILD.gn
+++ b/ios/chrome/browser/ui/BUILD.gn
@@ -231,6 +231,7 @@
 source_set("ui_internal") {
   configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
+    "browser_view_controller+private.h",
     "browser_view_controller.h",
     "browser_view_controller.mm",
     "browser_view_controller_dependency_factory.h",
diff --git a/ios/chrome/browser/ui/browser_view_controller+private.h b/ios/chrome/browser/ui/browser_view_controller+private.h
new file mode 100644
index 0000000..881c18d
--- /dev/null
+++ b/ios/chrome/browser/ui/browser_view_controller+private.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 IOS_CHROME_BROWSER_UI_BROWSER_VIEW_CONTROLLER_PRIVATE_H_
+#define IOS_CHROME_BROWSER_UI_BROWSER_VIEW_CONTROLLER_PRIVATE_H_
+
+#import "ios/chrome/browser/ui/browser_view_controller.h"
+
+#import "base/ios/block_types.h"
+
+// This is a private category that is intended to only be imported in
+// browser_coordinator.mm.
+@interface BrowserViewController (Private)
+
+// Activates/deactivates the object. This will enable/disable the ability for
+// this object to browse, and to have live UIWebViews associated with it. While
+// not active, the UI will not react to changes in the tab model, so generally
+// an inactive BVC should not be visible.
+@property(nonatomic, assign, getter=isActive) BOOL active;
+
+// Dismisses all presented views, excluding the omnibox if |dismissOmnibox| is
+// NO, then calls |completion|.
+- (void)clearPresentedStateWithCompletion:(ProceduralBlock)completion
+                           dismissOmnibox:(BOOL)dismissOmnibox;
+
+// Called when the browser state provided to this instance is being destroyed.
+// At this point the browser will no longer ever be active, and will likely be
+// deallocated soon.
+- (void)browserStateDestroyed;
+
+// Called before the instance is deallocated.
+- (void)shutdown;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_BROWSER_VIEW_CONTROLLER_PRIVATE_H_
diff --git a/ios/chrome/browser/ui/browser_view_controller.h b/ios/chrome/browser/ui/browser_view_controller.h
index a672a51..0010dab 100644
--- a/ios/chrome/browser/ui/browser_view_controller.h
+++ b/ios/chrome/browser/ui/browser_view_controller.h
@@ -73,12 +73,6 @@
 // Invisible button used to dismiss the keyboard.
 @property(nonatomic, strong) UIButton* typingShield;
 
-// Activates/deactivates the object. This will enable/disable the ability for
-// this object to browse, and to have live UIWebViews associated with it. While
-// not active, the UI will not react to changes in the tab model, so generally
-// an inactive BVC should not be visible.
-@property(nonatomic, assign, getter=isActive) BOOL active;
-
 // Returns whether or not text to speech is playing.
 @property(nonatomic, assign, readonly, getter=isPlayingTTS) BOOL playingTTS;
 
@@ -103,11 +97,6 @@
 // bubble will not be shown.
 - (void)presentBubblesIfEligible;
 
-// Called when the browser state provided to this instance is being destroyed.
-// At this point the browser will no longer ever be active, and will likely be
-// deallocated soon.
-- (void)browserStateDestroyed;
-
 // Opens a new tab as if originating from |originPoint| and |focusOmnibox|.
 - (void)openNewTabFromOriginPoint:(CGPoint)originPoint
                      focusOmnibox:(BOOL)focusOmnibox;
@@ -126,11 +115,6 @@
 // Shows the voice search UI.
 - (void)startVoiceSearch;
 
-// Dismisses all presented views, excluding the omnibox if |dismissOmnibox| is
-// NO, then calls |completion|.
-- (void)clearPresentedStateWithCompletion:(ProceduralBlock)completion
-                           dismissOmnibox:(BOOL)dismissOmnibox;
-
 // Returns a tab strip placeholder view created from the current state of the
 // tab strip. It is used to animate the transition from the browser view
 // controller to the tab switcher.
@@ -150,9 +134,6 @@
 // to browsing data changes.
 - (void)resetNTP;
 
-// Called before the instance is deallocated.
-- (void)shutdown;
-
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_BROWSER_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index 3ce44028..ea21dc9 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #import "ios/chrome/browser/ui/browser_view_controller.h"
+#import "ios/chrome/browser/ui/browser_view_controller+private.h"
 
 #import <AssetsLibrary/AssetsLibrary.h>
 #import <MessageUI/MessageUI.h>
@@ -556,6 +557,11 @@
   BrowserContainerCoordinator* _browserContainerCoordinator;
 }
 
+// Activates/deactivates the object. This will enable/disable the ability for
+// this object to browse, and to have live UIWebViews associated with it. While
+// not active, the UI will not react to changes in the tab model, so generally
+// an inactive BVC should not be visible.
+@property(nonatomic, assign, getter=isActive) BOOL active;
 // Command dispatcher.
 @property(nonatomic, weak) CommandDispatcher* commandDispatcher;
 // The browser's side swipe controller.  Lazily instantiated on the first call.
@@ -908,68 +914,6 @@
   return _browserContainerCoordinator.viewController.view;
 }
 
-- (void)setActive:(BOOL)active {
-  if (_active == active) {
-    return;
-  }
-  _active = active;
-
-  // If not active, display an activity indicator overlay over the view to
-  // prevent interaction with the web page.
-  // TODO(crbug.com/637093): This coordinator should be managed by the
-  // coordinator used to present BrowserViewController, when implemented.
-  if (active) {
-    [self.activityOverlayCoordinator stop];
-    self.activityOverlayCoordinator = nil;
-  } else if (!self.activityOverlayCoordinator) {
-    self.activityOverlayCoordinator =
-        [[ActivityOverlayCoordinator alloc] initWithBaseViewController:self];
-    [self.activityOverlayCoordinator start];
-  }
-
-  if (_browserState) {
-    ActiveStateManager* active_state_manager =
-        ActiveStateManager::FromBrowserState(_browserState);
-    active_state_manager->SetActive(active);
-
-    TextToSpeechPlaybackControllerFactory::GetInstance()
-        ->GetForBrowserState(_browserState)
-        ->SetEnabled(_active);
-  }
-
-  self.webUsageEnabled = active;
-  [self updateDialogPresenterActiveState];
-  [self updateBroadcastState];
-
-  // Stop the NTP on web usage toggle. This happens when clearing browser
-  // data, and forces the NTP to be recreated in -displayTab below.
-  // TODO(crbug.com/906199): Move this to the NewTabPageTabHelper when
-  // WebStateObserver has a webUsage callback.
-  if (!active) {
-    for (const auto& element : _ntpCoordinatorsForWebStates)
-      [element.second stop];
-  }
-
-  if (active) {
-    // Make sure the tab (if any; it's possible to get here without a current
-    // tab if the caller is about to create one) ends up on screen completely.
-    Tab* currentTab = [self.tabModel currentTab];
-    // Force loading the view in case it was not loaded yet.
-    [self loadViewIfNeeded];
-    if (currentTab && _expectingForegroundTab) {
-      PagePlaceholderTabHelper::FromWebState(currentTab.webState)
-          ->AddPlaceholderForNextNavigation();
-    }
-    if (currentTab)
-      [self displayTab:currentTab];
-  } else {
-    [_dialogPresenter cancelAllDialogs];
-  }
-  [_paymentRequestManager enablePaymentRequest:active];
-
-  [self setNeedsStatusBarAppearanceUpdate];
-}
-
 - (BOOL)isPlayingTTS {
   return _voiceSearchController && _voiceSearchController->IsPlayingAudio();
 }
@@ -1263,32 +1207,6 @@
   [self.bubblePresenter presentBubblesIfEligible];
 }
 
-- (void)browserStateDestroyed {
-  [self setActive:NO];
-  [_paymentRequestManager close];
-  _paymentRequestManager = nil;
-  [self.tabModel browserStateDestroyed];
-
-  TextToSpeechPlaybackControllerFactory::GetInstance()
-      ->GetForBrowserState(_browserState)
-      ->SetWebStateList(nullptr);
-
-  WebStateListWebUsageEnablerFactory::GetInstance()
-      ->GetForBrowserState(_browserState)
-      ->SetWebStateList(nullptr);
-
-  // Disconnect child coordinators.
-  [_activityServiceCoordinator disconnect];
-  [self.popupMenuCoordinator stop];
-  [self.tabStripCoordinator stop];
-  self.tabStripCoordinator = nil;
-  self.tabStripView = nil;
-
-  _browserState = nullptr;
-  [self.commandDispatcher stopDispatchingToTarget:self];
-  self.commandDispatcher = nil;
-}
-
 - (void)openNewTabFromOriginPoint:(CGPoint)originPoint
                      focusOmnibox:(BOOL)focusOmnibox {
   NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate];
@@ -1380,6 +1298,82 @@
   [self.dispatcher cancelOmniboxEdit];
 }
 
+- (UIView<TabStripFoldAnimation>*)tabStripPlaceholderView {
+  return [self.tabStripCoordinator placeholderView];
+}
+
+- (void)resetNTP {
+  for (const auto& element : _ntpCoordinatorsForWebStates)
+    [element.second stop];
+  [self loadViewIfNeeded];
+  if (self.tabModel.currentTab)
+    [self displayTab:self.tabModel.currentTab];
+}
+
+#pragma mark - browser_view_controller+private.h
+
+- (void)setActive:(BOOL)active {
+  if (_active == active) {
+    return;
+  }
+  _active = active;
+
+  // If not active, display an activity indicator overlay over the view to
+  // prevent interaction with the web page.
+  // TODO(crbug.com/637093): This coordinator should be managed by the
+  // coordinator used to present BrowserViewController, when implemented.
+  if (active) {
+    [self.activityOverlayCoordinator stop];
+    self.activityOverlayCoordinator = nil;
+  } else if (!self.activityOverlayCoordinator) {
+    self.activityOverlayCoordinator =
+        [[ActivityOverlayCoordinator alloc] initWithBaseViewController:self];
+    [self.activityOverlayCoordinator start];
+  }
+
+  if (_browserState) {
+    ActiveStateManager* active_state_manager =
+        ActiveStateManager::FromBrowserState(_browserState);
+    active_state_manager->SetActive(active);
+
+    TextToSpeechPlaybackControllerFactory::GetInstance()
+        ->GetForBrowserState(_browserState)
+        ->SetEnabled(_active);
+  }
+
+  self.webUsageEnabled = active;
+  [self updateDialogPresenterActiveState];
+  [self updateBroadcastState];
+
+  // Stop the NTP on web usage toggle. This happens when clearing browser
+  // data, and forces the NTP to be recreated in -displayTab below.
+  // TODO(crbug.com/906199): Move this to the NewTabPageTabHelper when
+  // WebStateObserver has a webUsage callback.
+  if (!active) {
+    for (const auto& element : _ntpCoordinatorsForWebStates)
+      [element.second stop];
+  }
+
+  if (active) {
+    // Make sure the tab (if any; it's possible to get here without a current
+    // tab if the caller is about to create one) ends up on screen completely.
+    Tab* currentTab = [self.tabModel currentTab];
+    // Force loading the view in case it was not loaded yet.
+    [self loadViewIfNeeded];
+    if (currentTab && _expectingForegroundTab) {
+      PagePlaceholderTabHelper::FromWebState(currentTab.webState)
+          ->AddPlaceholderForNextNavigation();
+    }
+    if (currentTab)
+      [self displayTab:currentTab];
+  } else {
+    [_dialogPresenter cancelAllDialogs];
+  }
+  [_paymentRequestManager enablePaymentRequest:active];
+
+  [self setNeedsStatusBarAppearanceUpdate];
+}
+
 - (void)clearPresentedStateWithCompletion:(ProceduralBlock)completion
                            dismissOmnibox:(BOOL)dismissOmnibox {
   [_activityServiceCoordinator cancelShare];
@@ -1448,16 +1442,30 @@
   }
 }
 
-- (UIView<TabStripFoldAnimation>*)tabStripPlaceholderView {
-  return [self.tabStripCoordinator placeholderView];
-}
+- (void)browserStateDestroyed {
+  [self setActive:NO];
+  [_paymentRequestManager close];
+  _paymentRequestManager = nil;
+  [self.tabModel browserStateDestroyed];
 
-- (void)resetNTP {
-  for (const auto& element : _ntpCoordinatorsForWebStates)
-    [element.second stop];
-  [self loadViewIfNeeded];
-  if (self.tabModel.currentTab)
-    [self displayTab:self.tabModel.currentTab];
+  TextToSpeechPlaybackControllerFactory::GetInstance()
+      ->GetForBrowserState(_browserState)
+      ->SetWebStateList(nullptr);
+
+  WebStateListWebUsageEnablerFactory::GetInstance()
+      ->GetForBrowserState(_browserState)
+      ->SetWebStateList(nullptr);
+
+  // Disconnect child coordinators.
+  [_activityServiceCoordinator disconnect];
+  [self.popupMenuCoordinator stop];
+  [self.tabStripCoordinator stop];
+  self.tabStripCoordinator = nil;
+  self.tabStripView = nil;
+
+  _browserState = nullptr;
+  [self.commandDispatcher stopDispatchingToTarget:self];
+  self.commandDispatcher = nil;
 }
 
 - (void)shutdown {
diff --git a/ios/chrome/browser/ui/browser_view_controller_unittest.mm b/ios/chrome/browser/ui/browser_view_controller_unittest.mm
index d9143a0..0412785 100644
--- a/ios/chrome/browser/ui/browser_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/browser_view_controller_unittest.mm
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#import "ios/chrome/browser/ui/browser_view_controller.h"
+#import "ios/chrome/browser/ui/browser_view_controller+private.h"
+
 #import <Foundation/Foundation.h>
 #import <PassKit/PassKit.h>
 
@@ -31,7 +34,6 @@
 #import "ios/chrome/browser/ui/activity_services/share_protocol.h"
 #import "ios/chrome/browser/ui/activity_services/share_to_data.h"
 #import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h"
-#import "ios/chrome/browser/ui/browser_view_controller.h"
 #import "ios/chrome/browser/ui/browser_view_controller_dependency_factory.h"
 #import "ios/chrome/browser/ui/browser_view_controller_helper.h"
 #import "ios/chrome/browser/ui/commands/application_commands.h"
diff --git a/ios/chrome/browser/ui/main/browser_coordinator.mm b/ios/chrome/browser/ui/main/browser_coordinator.mm
index 9b6a057..9c87978 100644
--- a/ios/chrome/browser/ui/main/browser_coordinator.mm
+++ b/ios/chrome/browser/ui/main/browser_coordinator.mm
@@ -21,6 +21,7 @@
 #import "ios/chrome/browser/ui/alert_coordinator/repost_form_coordinator.h"
 #import "ios/chrome/browser/ui/app_launcher/app_launcher_coordinator.h"
 #import "ios/chrome/browser/ui/autofill/form_input_accessory_coordinator.h"
+#import "ios/chrome/browser/ui/browser_view_controller+private.h"
 #import "ios/chrome/browser/ui/browser_view_controller.h"
 #import "ios/chrome/browser/ui/browser_view_controller_dependency_factory.h"
 #import "ios/chrome/browser/ui/commands/application_commands.h"
diff --git a/ios/web/navigation/navigation_manager_impl.h b/ios/web/navigation/navigation_manager_impl.h
index 2941923c..6681037 100644
--- a/ios/web/navigation/navigation_manager_impl.h
+++ b/ios/web/navigation/navigation_manager_impl.h
@@ -191,7 +191,7 @@
   int GetLastCommittedItemIndex() const final;
   NavigationItem* GetPendingItem() const final;
   NavigationItem* GetTransientItem() const final;
-  void LoadURLWithParams(const NavigationManager::WebLoadParams&) final;
+  void LoadURLWithParams(const NavigationManager::WebLoadParams&) override;
   void AddTransientURLRewriter(BrowserURLRewriter::URLRewriter rewriter) final;
   void GoToIndex(int index) final;
   void Reload(ReloadType reload_type, bool check_for_reposts) final;
diff --git a/ios/web/navigation/wk_based_navigation_manager_impl.h b/ios/web/navigation/wk_based_navigation_manager_impl.h
index 458fee9..9f90e34 100644
--- a/ios/web/navigation/wk_based_navigation_manager_impl.h
+++ b/ios/web/navigation/wk_based_navigation_manager_impl.h
@@ -135,6 +135,7 @@
   bool CanPruneAllButLastCommittedItem() const override;
   void Restore(int last_committed_item_index,
                std::vector<std::unique_ptr<NavigationItem>> items) override;
+  void LoadURLWithParams(const NavigationManager::WebLoadParams&) override;
   void AddRestoreCompletionCallback(base::OnceClosure callback) override;
   void LoadIfNecessary() override;
 
diff --git a/ios/web/navigation/wk_based_navigation_manager_impl.mm b/ios/web/navigation/wk_based_navigation_manager_impl.mm
index 224d66b..f0a6df0 100644
--- a/ios/web/navigation/wk_based_navigation_manager_impl.mm
+++ b/ios/web/navigation/wk_based_navigation_manager_impl.mm
@@ -522,6 +522,19 @@
   }
 }
 
+void WKBasedNavigationManagerImpl::LoadURLWithParams(
+    const NavigationManager::WebLoadParams& params) {
+  if (IsRestoreSessionInProgress() &&
+      !wk_navigation_util::IsRestoreSessionUrl(params.url)) {
+    AddRestoreCompletionCallback(
+        base::BindOnce(&NavigationManagerImpl::LoadURLWithParams,
+                       base::Unretained(this), params));
+    return;
+  }
+
+  NavigationManagerImpl::LoadURLWithParams(params);
+}
+
 void WKBasedNavigationManagerImpl::AddRestoreCompletionCallback(
     base::OnceClosure callback) {
   if (!is_restore_session_in_progress_) {
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index 87021e5..2e9b2d7 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -5535,7 +5535,10 @@
     }
   }
 
-  DCHECK_EQ(_documentURL.host(), newURL.host());
+  // Is it ok that newURL can be restore session URL?
+  if (!IsRestoreSessionUrl(_documentURL) && !IsRestoreSessionUrl(newURL)) {
+    DCHECK_EQ(_documentURL.host(), newURL.host());
+  }
   DCHECK(_documentURL != newURL);
 
   // If called during window.history.pushState or window.history.replaceState
diff --git a/ios/web/web_state/web_state_unittest.mm b/ios/web/web_state/web_state_unittest.mm
index 42d2ffa..70750bb6 100644
--- a/ios/web/web_state/web_state_unittest.mm
+++ b/ios/web/web_state/web_state_unittest.mm
@@ -474,6 +474,56 @@
   }));
 }
 
+// Verifies that calling NavigationManager::LoadURLWithParams() does not stop
+// the session restoration and eventually loads the requested URL.
+TEST_P(WebStateTest, CallLoadURLWithParamsDuringSessionRestore) {
+  // Create session storage with large number of items.
+  const int kItemCount = 10;
+  NSMutableArray<CRWNavigationItemStorage*>* item_storages =
+      [NSMutableArray arrayWithCapacity:kItemCount];
+  for (unsigned int i = 0; i < kItemCount; i++) {
+    CRWNavigationItemStorage* item = [[CRWNavigationItemStorage alloc] init];
+    item.virtualURL = GURL(base::StringPrintf("http://www.%u.test", i));
+    item.userAgentType = UserAgentType::MOBILE;
+    [item_storages addObject:item];
+  }
+
+  // Restore the session.
+  WebState::CreateParams params(GetBrowserState());
+  CRWSessionStorage* session_storage = [[CRWSessionStorage alloc] init];
+  session_storage.itemStorages = item_storages;
+  auto web_state = WebState::CreateWithStorageSession(params, session_storage);
+  WebState* web_state_ptr = web_state.get();
+  NavigationManager* navigation_manager = web_state->GetNavigationManager();
+  // TODO(crbug.com/873729): The session will not be restored until
+  // LoadIfNecessary call. Fix the bug and remove extra call.
+  navigation_manager->LoadIfNecessary();
+
+  // Attempt to interrupt the session restoration.
+  GURL url("http://foo.test/");
+  NavigationManager::WebLoadParams load_params(url);
+  navigation_manager->LoadURLWithParams(load_params);
+
+  // Verify that session was fully restored.
+  EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
+    bool restored = navigation_manager->GetItemCount() == kItemCount &&
+                    navigation_manager->CanGoForward();
+    if (!restored) {
+      // Attempt to interrupt the session restoration multiple times, which is
+      // something that the user can do on the slow network.
+      navigation_manager->LoadURLWithParams(load_params);
+    }
+    return restored;
+  }));
+  EXPECT_EQ(kItemCount, navigation_manager->GetItemCount());
+  EXPECT_TRUE(navigation_manager->CanGoForward());
+
+  // Now wait until the last committed item is fully loaded.
+  EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
+    return web_state_ptr->GetLastCommittedURL() == url;
+  }));
+}
+
 // Verifies that calling NavigationManager::Reload() does not stop the session
 // restoration. Session restoration should be opaque to the user and embedder,
 // so calling Reload() is no-op.
diff --git a/ipc/run_all_perftests.cc b/ipc/run_all_perftests.cc
index b5948e1..b60415fd 100644
--- a/ipc/run_all_perftests.cc
+++ b/ipc/run_all_perftests.cc
@@ -7,10 +7,15 @@
 #include "base/command_line.h"
 #include "base/test/perf_test_suite.h"
 #include "base/test/test_io_thread.h"
+#include "build/build_config.h"
 #include "mojo/core/embedder/embedder.h"
 #include "mojo/core/embedder/scoped_ipc_support.h"
 #include "mojo/core/test/test_support_impl.h"
 
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+#include "mojo/core/embedder/default_mach_broker.h"
+#endif
+
 int main(int argc, char** argv) {
   base::PerfTestSuite test(argc, argv);
 
@@ -20,6 +25,10 @@
       test_io_thread.task_runner(),
       mojo::core::ScopedIPCSupport::ShutdownPolicy::CLEAN);
   mojo::test::TestSupport::Init(new mojo::core::test::TestSupportImpl());
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+  mojo::core::SetMachPortProvider(
+      mojo::core::DefaultMachBroker::Get()->port_provider());
+#endif
 
   return test.Run();
 }
diff --git a/media/base/ipc/media_param_traits_macros.h b/media/base/ipc/media_param_traits_macros.h
index 26115f13..77f1fa2 100644
--- a/media/base/ipc/media_param_traits_macros.h
+++ b/media/base/ipc/media_param_traits_macros.h
@@ -57,9 +57,6 @@
 IPC_ENUM_TRAITS_MAX_VALUE(media::BufferingState,
                           media::BufferingState::BUFFERING_STATE_MAX)
 
-IPC_ENUM_TRAITS_MAX_VALUE(media::CdmKeyInformation::KeyStatus,
-                          media::CdmKeyInformation::KEY_STATUS_MAX)
-
 IPC_ENUM_TRAITS_MAX_VALUE(media::CdmMessageType,
                           media::CdmMessageType::MESSAGE_TYPE_MAX)
 
@@ -168,12 +165,6 @@
   IPC_STRUCT_TRAITS_MEMBER(use_hw_secure_codecs)
 IPC_STRUCT_TRAITS_END()
 
-IPC_STRUCT_TRAITS_BEGIN(media::CdmKeyInformation)
-  IPC_STRUCT_TRAITS_MEMBER(key_id)
-  IPC_STRUCT_TRAITS_MEMBER(status)
-  IPC_STRUCT_TRAITS_MEMBER(system_code)
-IPC_STRUCT_TRAITS_END()
-
 IPC_STRUCT_TRAITS_BEGIN(media::MediaLogEvent)
   IPC_STRUCT_TRAITS_MEMBER(id)
   IPC_STRUCT_TRAITS_MEMBER(type)
diff --git a/media/gpu/command_buffer_helper.cc b/media/gpu/command_buffer_helper.cc
index 857373ac..cdd3e2b 100644
--- a/media/gpu/command_buffer_helper.cc
+++ b/media/gpu/command_buffer_helper.cc
@@ -48,6 +48,13 @@
     return decoder_helper_->GetGLContext();
   }
 
+  bool HasStub() override {
+    DVLOG(4) << __func__;
+    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+    return stub_;
+  }
+
   bool MakeContextCurrent() override {
     DVLOG(2) << __func__;
     DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -55,20 +62,6 @@
     return decoder_helper_ && decoder_helper_->MakeContextCurrent();
   }
 
-  bool IsContextCurrent() const override {
-    DVLOG(2) << __func__;
-    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
-    if (!stub_)
-      return false;
-
-    gl::GLContext* context = stub_->decoder_context()->GetGLContext();
-    if (!context)
-      return false;
-
-    return context->IsCurrent(nullptr);
-  }
-
   GLuint CreateTexture(GLenum target,
                        GLenum internal_format,
                        GLsizei width,
diff --git a/media/gpu/command_buffer_helper.h b/media/gpu/command_buffer_helper.h
index d0fa4b1..13744e5 100644
--- a/media/gpu/command_buffer_helper.h
+++ b/media/gpu/command_buffer_helper.h
@@ -47,14 +47,12 @@
   // EGLImages. New clients should use more specialized accessors instead.
   virtual gl::GLContext* GetGLContext() = 0;
 
+  // Checks whether the stub has been destroyed.
+  virtual bool HasStub() = 0;
+
   // Makes the GL context current.
   virtual bool MakeContextCurrent() = 0;
 
-  // Returns whether or not the the context is current in the
-  // GLContext::IsCurrent(nullptr) sense.  Note that this is not necessarily the
-  // same for virtual contexts as "Did somebody run MakeContextCurrent?".
-  virtual bool IsContextCurrent() const = 0;
-
   // Creates a texture and returns its |service_id|.
   //
   // See glTexImage2D() for argument definitions.
@@ -117,7 +115,7 @@
   virtual void WaitForSyncToken(gpu::SyncToken sync_token,
                                 base::OnceClosure done_cb) = 0;
 
-  // Set the callback to be called when our stub is destroyed.  This callback
+  // Set the callback to be called when our stub is destroyed. This callback
   // may not change the current context.
   virtual void SetWillDestroyStubCB(WillDestroyStubCB will_destroy_stub_cb) = 0;
 
diff --git a/media/gpu/fake_command_buffer_helper.cc b/media/gpu/fake_command_buffer_helper.cc
index c0ff03c..6349d1b1 100644
--- a/media/gpu/fake_command_buffer_helper.cc
+++ b/media/gpu/fake_command_buffer_helper.cc
@@ -64,6 +64,10 @@
   return nullptr;
 }
 
+bool FakeCommandBufferHelper::HasStub() {
+  return has_stub_;
+}
+
 bool FakeCommandBufferHelper::MakeContextCurrent() {
   DVLOG(3) << __func__;
   DCHECK(task_runner_->BelongsToCurrentThread());
@@ -71,10 +75,6 @@
   return is_context_current_;
 }
 
-bool FakeCommandBufferHelper::IsContextCurrent() const {
-  return is_context_current_;
-}
-
 GLuint FakeCommandBufferHelper::CreateTexture(GLenum target,
                                               GLenum internal_format,
                                               GLsizei width,
diff --git a/media/gpu/fake_command_buffer_helper.h b/media/gpu/fake_command_buffer_helper.h
index 02cf0db80c..e99f114f 100644
--- a/media/gpu/fake_command_buffer_helper.h
+++ b/media/gpu/fake_command_buffer_helper.h
@@ -39,8 +39,8 @@
 
   // CommandBufferHelper implementation.
   gl::GLContext* GetGLContext() override;
+  bool HasStub() override;
   bool MakeContextCurrent() override;
-  bool IsContextCurrent() const override;
   GLuint CreateTexture(GLenum target,
                        GLenum internal_format,
                        GLsizei width,
diff --git a/media/gpu/ipc/service/picture_buffer_manager.cc b/media/gpu/ipc/service/picture_buffer_manager.cc
index f7002d0..9cd5b1e1 100644
--- a/media/gpu/ipc/service/picture_buffer_manager.cc
+++ b/media/gpu/ipc/service/picture_buffer_manager.cc
@@ -50,21 +50,23 @@
 
     base::AutoLock lock(picture_buffers_lock_);
 
-    // If there are no assigned picture buffers, predict that the VDA will
-    // request some.
-    if (picture_buffers_.empty())
-      return true;
-
-    // Predict that the VDA can output a picture if at least one picture buffer
-    // is not in use as an output.
+    // If at least one picture buffer is not in use, predict that the VDA can
+    // use it to output another picture.
+    bool has_assigned_picture_buffer = false;
     for (const auto& it : picture_buffers_) {
-      const auto& state = it.second.state;
-      if (std::find(state.begin(), state.end(), PictureBufferState::OUTPUT) ==
-          state.end())
-        return true;
+      if (!it.second.dismissed) {
+        // Note: If a picture buffer is waiting for SyncToken release, that
+        // release is already in some command buffer (or the wait is invalid).
+        // The wait will complete without further interaction from the client.
+        if (it.second.output_count == 0)
+          return true;
+        has_assigned_picture_buffer = true;
+      }
     }
 
-    return false;
+    // If there are no assigned picture buffers, predict that the VDA will
+    // request some.
+    return !has_assigned_picture_buffer;
   }
 
   std::vector<PictureBuffer> CreatePictureBuffers(
@@ -89,7 +91,6 @@
 
     std::vector<PictureBuffer> picture_buffers;
     for (uint32_t i = 0; i < count; i++) {
-      PictureBuffer::TextureIds service_ids;
       PictureBufferData picture_data = {pixel_format, texture_size};
 
       for (uint32_t j = 0; j < planes; j++) {
@@ -98,7 +99,7 @@
             texture_target, GL_RGBA, texture_size.width(),
             texture_size.height(), GL_RGBA, GL_UNSIGNED_BYTE);
         DCHECK(service_id);
-        service_ids.push_back(service_id);
+        picture_data.service_ids.push_back(service_id);
 
         // The texture is not cleared yet, but it will be before the VDA outputs
         // it. Rather than requiring output to happen on the GPU thread, mark
@@ -124,11 +125,9 @@
       //
       // TODO(sandersd): Refactor the bind image callback to use service IDs so
       // that we can get rid of the client IDs altogether.
-      picture_buffers.emplace_back(picture_buffer_id, texture_size, service_ids,
-                                   service_ids, texture_target, pixel_format);
-
-      // Record the textures used by the picture buffer.
-      picture_buffer_textures_[picture_buffer_id] = std::move(service_ids);
+      picture_buffers.emplace_back(
+          picture_buffer_id, texture_size, picture_data.service_ids,
+          picture_data.service_ids, texture_target, pixel_format);
     }
     return picture_buffers;
   }
@@ -138,26 +137,20 @@
 
     base::AutoLock lock(picture_buffers_lock_);
 
-    // Check the state of the picture buffer.
     const auto& it = picture_buffers_.find(picture_buffer_id);
-    if (it == picture_buffers_.end()) {
+    if (it == picture_buffers_.end() || it->second.dismissed) {
       DVLOG(1) << "Unknown picture buffer " << picture_buffer_id;
       return false;
     }
 
-    bool is_available = it->second.IsAvailable();
+    it->second.dismissed = true;
 
-    // Destroy the picture buffer data.
-    picture_buffers_.erase(it);
-
-    // If the picture was not bound to any VideoFrame, we can destroy its
-    // textures immediately.
-    if (is_available) {
+    // If the picture buffer is not in use, it should be destroyed immediately.
+    if (!it->second.IsInUse()) {
       gpu_task_runner_->PostTask(
           FROM_HERE,
-          base::BindOnce(
-              &PictureBufferManagerImpl::DestroyPictureBufferTextures, this,
-              picture_buffer_id));
+          base::BindOnce(&PictureBufferManagerImpl::DestroyPictureBuffer, this,
+                         picture_buffer_id));
     }
 
     return true;
@@ -169,8 +162,11 @@
     std::vector<int32_t> assigned_picture_buffer_ids;
     {
       base::AutoLock lock(picture_buffers_lock_);
-      for (const auto& it : picture_buffers_)
-        assigned_picture_buffer_ids.push_back(it.first);
+
+      for (const auto& it : picture_buffers_) {
+        if (!it.second.dismissed)
+          assigned_picture_buffer_ids.push_back(it.first);
+      }
     }
 
     for (int32_t picture_buffer_id : assigned_picture_buffer_ids)
@@ -192,13 +188,13 @@
 
     // Verify that the picture buffer is available.
     const auto& it = picture_buffers_.find(picture_buffer_id);
-    if (it == picture_buffers_.end()) {
+    if (it == picture_buffers_.end() || it->second.dismissed) {
       DVLOG(1) << "Unknown picture buffer " << picture_buffer_id;
       return nullptr;
     }
 
-    PictureBufferData& picture_buffer_data = it->second;
     // Ensure that the picture buffer is large enough.
+    PictureBufferData& picture_buffer_data = it->second;
     if (!gfx::Rect(picture_buffer_data.texture_size).Contains(visible_rect)) {
       DLOG(WARNING) << "visible_rect " << visible_rect.ToString()
                     << " exceeds coded_size "
@@ -209,8 +205,8 @@
       natural_size = GetNaturalSize(visible_rect, pixel_aspect_ratio);
     }
 
-    // Mark the picture as an output.
-    picture_buffer_data.state.push_back(PictureBufferState::OUTPUT);
+    // Record the output.
+    picture_buffer_data.output_count++;
 
     // Create and return a VideoFrame for the picture buffer.
     scoped_refptr<VideoFrame> frame = VideoFrame::WrapNativeTextures(
@@ -232,7 +228,10 @@
   }
 
  private:
-  ~PictureBufferManagerImpl() override { DVLOG(1) << __func__; }
+  ~PictureBufferManagerImpl() override {
+    DVLOG(1) << __func__;
+    DCHECK(picture_buffers_.empty() || !command_buffer_helper_->HasStub());
+  }
 
   void OnVideoFrameDestroyed(int32_t picture_buffer_id,
                              const gpu::SyncToken& sync_token) {
@@ -240,16 +239,13 @@
 
     base::AutoLock lock(picture_buffers_lock_);
 
-    // If the picture buffer is still assigned, mark it as unreleased.
+    // Record the picture buffer as waiting for SyncToken release (even if it
+    // has been dismissed already).
     const auto& it = picture_buffers_.find(picture_buffer_id);
-    if (it != picture_buffers_.end()) {
-      auto& state = it->second.state;
-      auto state_it =
-          std::find(state.begin(), state.end(), PictureBufferState::OUTPUT);
-      if (state_it != state.end())
-        state.erase(state_it);
-      state.push_back(PictureBufferState::WAITING_FOR_SYNCTOKEN);
-    }
+    DCHECK(it != picture_buffers_.end());
+    DCHECK_GT(it->second.output_count, 0);
+    it->second.output_count--;
+    it->second.waiting_for_synctoken_count++;
 
     // Wait for the SyncToken release.
     gpu_task_runner_->PostTask(
@@ -266,44 +262,55 @@
     DCHECK(gpu_task_runner_);
     DCHECK(gpu_task_runner_->BelongsToCurrentThread());
 
-    // If the picture buffer is still assigned, mark it as available.
+    // Remove the pending wait.
     bool is_assigned = false;
+    bool is_in_use = true;
     {
       base::AutoLock lock(picture_buffers_lock_);
       const auto& it = picture_buffers_.find(picture_buffer_id);
-      if (it != picture_buffers_.end()) {
-        auto& state = it->second.state;
-        auto state_it = std::find(state.begin(), state.end(),
-                                  PictureBufferState::WAITING_FOR_SYNCTOKEN);
-        if (state_it != state.end())
-          state.erase(state_it);
-        is_assigned = true;
-      }
+      DCHECK(it != picture_buffers_.end());
+
+      DCHECK_GT(it->second.waiting_for_synctoken_count, 0);
+      it->second.waiting_for_synctoken_count--;
+
+      is_assigned = !it->second.dismissed;
+      is_in_use = it->second.IsInUse();
     }
 
     // If the picture buffer is still assigned, it is ready to be reused.
-    // Otherwise it has been dismissed and we can now delete its textures.
-    // Neither of these operations should be done while holding the lock.
+    // Otherwise it should be destroyed if it is no longer in use. Neither of
+    // these operations should be done while holding the lock.
     if (is_assigned) {
+      // The callback is called even if the picture buffer is still in use; the
+      // client is expected to wait for all copies of a picture buffer to be
+      // returned before reusing any textures.
       reuse_picture_buffer_cb_.Run(picture_buffer_id);
-    } else {
-      DestroyPictureBufferTextures(picture_buffer_id);
+    } else if (!is_in_use) {
+      DestroyPictureBuffer(picture_buffer_id);
     }
   }
 
-  void DestroyPictureBufferTextures(int32_t picture_buffer_id) {
+  void DestroyPictureBuffer(int32_t picture_buffer_id) {
     DVLOG(3) << __func__ << "(" << picture_buffer_id << ")";
     DCHECK(gpu_task_runner_);
     DCHECK(gpu_task_runner_->BelongsToCurrentThread());
 
+    std::vector<GLuint> service_ids;
+    {
+      base::AutoLock lock(picture_buffers_lock_);
+      const auto& it = picture_buffers_.find(picture_buffer_id);
+      DCHECK(it != picture_buffers_.end());
+      DCHECK(it->second.dismissed);
+      DCHECK(!it->second.IsInUse());
+      service_ids = std::move(it->second.service_ids);
+      picture_buffers_.erase(it);
+    }
+
     if (!command_buffer_helper_->MakeContextCurrent())
       return;
 
-    const auto& it = picture_buffer_textures_.find(picture_buffer_id);
-    DCHECK(it != picture_buffer_textures_.end());
-    for (GLuint service_id : it->second)
+    for (GLuint service_id : service_ids)
       command_buffer_helper_->DestroyTexture(service_id);
-    picture_buffer_textures_.erase(it);
   }
 
   ReusePictureBufferCB reuse_picture_buffer_cb_;
@@ -312,30 +319,28 @@
   scoped_refptr<CommandBufferHelper> command_buffer_helper_;
 
   int32_t picture_buffer_id_ = 0;
-  // Includes picture puffers that have been dismissed if their textures have
-  // not been deleted yet.
-  std::map<int32_t, std::vector<GLuint>> picture_buffer_textures_;
 
-  base::Lock picture_buffers_lock_;
-  enum class PictureBufferState {
-    // Output by the VDA, still bound to a VideoFrame.
-    OUTPUT,
-    // Waiting on a SyncToken before being reused.
-    WAITING_FOR_SYNCTOKEN,
-  };
   struct PictureBufferData {
     VideoPixelFormat pixel_format;
     gfx::Size texture_size;
-    // The picture buffer might be sent from VDA multiple times. Therefore we
-    // use vector to track the status. The state is empty when the picture
-    // buffer is not bound to any VideoFrame.
-    std::vector<PictureBufferState> state;
+    std::vector<GLuint> service_ids;
     gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes];
+    bool dismissed = false;
 
-    // Available for use by the VDA.
-    bool IsAvailable() const { return state.empty(); }
+    // The same picture buffer can be output from the VDA multiple times
+    // concurrently, so the state is tracked using counts.
+    //   |output_count|: Number of VideoFrames this picture buffer is bound to.
+    //   |waiting_for_synctoken_count|: Number of returned frames that are
+    //       waiting for SyncToken release.
+    int output_count = 0;
+    int waiting_for_synctoken_count = 0;
+
+    bool IsInUse() const {
+      return output_count > 0 || waiting_for_synctoken_count > 0;
+    }
   };
-  // Pictures buffers that are assigned to the VDA.
+
+  base::Lock picture_buffers_lock_;
   std::map<int32_t, PictureBufferData> picture_buffers_
       GUARDED_BY(picture_buffers_lock_);
 
diff --git a/media/gpu/ipc/service/picture_buffer_manager_unittest.cc b/media/gpu/ipc/service/picture_buffer_manager_unittest.cc
index df51373..ccd950b 100644
--- a/media/gpu/ipc/service/picture_buffer_manager_unittest.cc
+++ b/media/gpu/ipc/service/picture_buffer_manager_unittest.cc
@@ -128,9 +128,9 @@
   Initialize();
   PictureBuffer pb = CreateARGBPictureBuffer();
   scoped_refptr<VideoFrame> frame = CreateVideoFrame(pb.id());
+  gpu::SyncToken sync_token = GenerateSyncToken(frame);
 
   // Dropping the frame does not immediately trigger reuse.
-  gpu::SyncToken sync_token = GenerateSyncToken(frame);
   frame = nullptr;
   environment_.RunUntilIdle();
 
@@ -140,28 +140,28 @@
   environment_.RunUntilIdle();
 }
 
-TEST_F(PictureBufferManagerImplTest, ReusePictureBuffer_MultipleTime) {
-  constexpr size_t kFrameNum = 3;
+TEST_F(PictureBufferManagerImplTest, ReusePictureBuffer_MultipleOutputs) {
+  constexpr size_t kOutputCountPerPictureBuffer = 3;
+
   Initialize();
   PictureBuffer pb = CreateARGBPictureBuffer();
   std::vector<scoped_refptr<VideoFrame>> frames;
-  for (size_t i = 0; i < kFrameNum; ++i) {
-    frames.push_back(CreateVideoFrame(pb.id()));
-  }
-
-  // Dropping the frame does not immediately trigger reuse.
   std::vector<gpu::SyncToken> sync_tokens;
-  for (auto& frame : frames) {
+  for (size_t i = 0; i < kOutputCountPerPictureBuffer; i++) {
+    scoped_refptr<VideoFrame> frame = CreateVideoFrame(pb.id());
+    frames.push_back(frame);
     sync_tokens.push_back(GenerateSyncToken(frame));
   }
+
+  // Dropping the frames does not immediately trigger reuse.
   frames.clear();
   environment_.RunUntilIdle();
 
-  // Completing the SyncToken wait does.
-  EXPECT_CALL(reuse_cb_, Run(pb.id())).Times(kFrameNum);
-  for (auto& sync_token : sync_tokens) {
+  // Completing the SyncToken waits does. (Clients are expected to wait for the
+  // output count to reach zero before actually reusing the picture buffer.)
+  EXPECT_CALL(reuse_cb_, Run(pb.id())).Times(kOutputCountPerPictureBuffer);
+  for (const auto& sync_token : sync_tokens)
     cbh_->ReleaseSyncToken(sync_token);
-  }
   environment_.RunUntilIdle();
 }
 
@@ -179,6 +179,7 @@
   Initialize();
   PictureBuffer pb = CreateARGBPictureBuffer();
   scoped_refptr<VideoFrame> frame = CreateVideoFrame(pb.id());
+  gpu::SyncToken sync_token = GenerateSyncToken(frame);
   pbm_->DismissPictureBuffer(pb.id());
 
   // Allocated textures should not be deleted while the VideoFrame exists.
@@ -186,18 +187,52 @@
   EXPECT_TRUE(cbh_->HasTexture(pb.client_texture_ids()[0]));
 
   // Or after it has been returned.
-  gpu::SyncToken sync_token = GenerateSyncToken(frame);
   frame = nullptr;
   environment_.RunUntilIdle();
   EXPECT_TRUE(cbh_->HasTexture(pb.client_texture_ids()[0]));
 
-  // Until the SyncToken has been waited for. (Reuse callback should not be
-  // called for a dismissed picture buffer.)
+  // The textures should be deleted once the the wait has completed. The reuse
+  // callback should not be called for a dismissed picture buffer.
   cbh_->ReleaseSyncToken(sync_token);
   environment_.RunUntilIdle();
   EXPECT_FALSE(cbh_->HasTexture(pb.client_texture_ids()[0]));
 }
 
+TEST_F(PictureBufferManagerImplTest, DismissPictureBuffer_MultipleOutputs) {
+  constexpr size_t kOutputCountPerPictureBuffer = 3;
+
+  Initialize();
+  PictureBuffer pb = CreateARGBPictureBuffer();
+  std::vector<scoped_refptr<VideoFrame>> frames;
+  std::vector<gpu::SyncToken> sync_tokens;
+  for (size_t i = 0; i < kOutputCountPerPictureBuffer; i++) {
+    scoped_refptr<VideoFrame> frame = CreateVideoFrame(pb.id());
+    frames.push_back(frame);
+    sync_tokens.push_back(GenerateSyncToken(frame));
+  }
+  pbm_->DismissPictureBuffer(pb.id());
+
+  // Allocated textures should not be deleted while the VideoFrames exists.
+  environment_.RunUntilIdle();
+  EXPECT_TRUE(cbh_->HasTexture(pb.client_texture_ids()[0]));
+
+  // Or after they have been returned.
+  frames.clear();
+  environment_.RunUntilIdle();
+  EXPECT_TRUE(cbh_->HasTexture(pb.client_texture_ids()[0]));
+
+  // The textures should be deleted only once all of the waits have completed.
+  for (size_t i = 0; i < kOutputCountPerPictureBuffer; i++) {
+    cbh_->ReleaseSyncToken(sync_tokens[i]);
+    environment_.RunUntilIdle();
+    if (i < kOutputCountPerPictureBuffer - 1) {
+      EXPECT_TRUE(cbh_->HasTexture(pb.client_texture_ids()[0]));
+    } else {
+      EXPECT_FALSE(cbh_->HasTexture(pb.client_texture_ids()[0]));
+    }
+  }
+}
+
 TEST_F(PictureBufferManagerImplTest, CanReadWithoutStalling) {
   // Works before Initialize().
   EXPECT_TRUE(pbm_->CanReadWithoutStalling());
diff --git a/media/gpu/ipc/service/vda_video_decoder.cc b/media/gpu/ipc/service/vda_video_decoder.cc
index e8824ab..9a9c533 100644
--- a/media/gpu/ipc/service/vda_video_decoder.cc
+++ b/media/gpu/ipc/service/vda_video_decoder.cc
@@ -285,7 +285,7 @@
   DCHECK(gpu_task_runner_->BelongsToCurrentThread());
   DCHECK(!vda_);
 
-  // Set up |command_buffer_helper_|.
+  // Set up |command_buffer_helper|.
   scoped_refptr<CommandBufferHelper> command_buffer_helper =
       std::move(create_command_buffer_helper_cb_).Run();
   if (!command_buffer_helper) {
diff --git a/media/gpu/ipc/service/vda_video_decoder.h b/media/gpu/ipc/service/vda_video_decoder.h
index 062d600..bf2fe0b 100644
--- a/media/gpu/ipc/service/vda_video_decoder.h
+++ b/media/gpu/ipc/service/vda_video_decoder.h
@@ -154,7 +154,6 @@
                                   gfx::Size texture_size,
                                   GLenum texture_target);
   void ReusePictureBuffer(int32_t picture_buffer_id);
-  void AddEventOnParentThread(std::unique_ptr<MediaLogEvent> event);
 
   // Error handling.
   void EnterErrorState();
@@ -191,9 +190,11 @@
   //
   // Shared state.
   //
+
   // Only read on GPU thread during initialization, which is mutually exclusive
   // with writes on the parent thread.
   VideoDecoderConfig config_;
+
   // Only written on the GPU thread during initialization, which is mutually
   // exclusive with reads on the parent thread.
   std::unique_ptr<VideoDecodeAccelerator> vda_;
diff --git a/media/gpu/vaapi/vaapi_video_decode_accelerator.cc b/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
index 6a91a18..b9f3e63d 100644
--- a/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
+++ b/media/gpu/vaapi/vaapi_video_decode_accelerator.cc
@@ -966,8 +966,8 @@
   }
 
   pending_output_cbs_.push(
-      base::Bind(&VaapiVideoDecodeAccelerator::OutputPicture, weak_this_,
-                 dec_surface, bitstream_id, visible_rect, color_space));
+      base::BindOnce(&VaapiVideoDecodeAccelerator::OutputPicture, weak_this_,
+                     dec_surface, bitstream_id, visible_rect, color_space));
   TryOutputPicture();
 }
 
diff --git a/media/mojo/clients/mojo_cdm.cc b/media/mojo/clients/mojo_cdm.cc
index 8654081d..cbe9ed3 100644
--- a/media/mojo/clients/mojo_cdm.cc
+++ b/media/mojo/clients/mojo_cdm.cc
@@ -352,7 +352,7 @@
 void MojoCdm::OnSessionKeysChange(
     const std::string& session_id,
     bool has_additional_usable_key,
-    std::vector<mojom::CdmKeyInformationPtr> keys_info) {
+    std::vector<std::unique_ptr<CdmKeyInformation>> keys_info) {
   DVLOG(2) << __func__;
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
@@ -368,13 +368,8 @@
     }
   }
 
-  CdmKeysInfo key_data;
-  key_data.reserve(keys_info.size());
-  for (size_t i = 0; i < keys_info.size(); ++i) {
-    key_data.push_back(keys_info[i].To<std::unique_ptr<CdmKeyInformation>>());
-  }
   session_keys_change_cb_.Run(session_id, has_additional_usable_key,
-                              std::move(key_data));
+                              std::move(keys_info));
 }
 
 void MojoCdm::OnSessionExpirationUpdate(const std::string& session_id,
diff --git a/media/mojo/clients/mojo_cdm.h b/media/mojo/clients/mojo_cdm.h
index a5fd3cf..2bd16b2a 100644
--- a/media/mojo/clients/mojo_cdm.h
+++ b/media/mojo/clients/mojo_cdm.h
@@ -114,7 +114,7 @@
   void OnSessionKeysChange(
       const std::string& session_id,
       bool has_additional_usable_key,
-      std::vector<mojom::CdmKeyInformationPtr> keys_info) final;
+      std::vector<std::unique_ptr<CdmKeyInformation>> keys_info) final;
   void OnSessionExpirationUpdate(const std::string& session_id,
                                  double new_expiry_time_sec) final;
 
diff --git a/media/mojo/common/media_type_converters.cc b/media/mojo/common/media_type_converters.cc
index 3841de4..ea1e77d 100644
--- a/media/mojo/common/media_type_converters.cc
+++ b/media/mojo/common/media_type_converters.cc
@@ -11,7 +11,6 @@
 #include "base/logging.h"
 #include "base/numerics/safe_conversions.h"
 #include "media/base/audio_buffer.h"
-#include "media/base/cdm_key_information.h"
 #include "media/base/decoder_buffer.h"
 #include "media/base/decrypt_config.h"
 #include "media/base/subsample_entry.h"
@@ -119,27 +118,6 @@
 }
 
 // static
-media::mojom::CdmKeyInformationPtr TypeConverter<
-    media::mojom::CdmKeyInformationPtr,
-    media::CdmKeyInformation>::Convert(const media::CdmKeyInformation& input) {
-  media::mojom::CdmKeyInformationPtr info(
-      media::mojom::CdmKeyInformation::New());
-  info->key_id = input.key_id;
-  info->status = input.status;
-  info->system_code = input.system_code;
-  return info;
-}
-
-// static
-std::unique_ptr<media::CdmKeyInformation>
-TypeConverter<std::unique_ptr<media::CdmKeyInformation>,
-              media::mojom::CdmKeyInformationPtr>::
-    Convert(const media::mojom::CdmKeyInformationPtr& input) {
-  return std::make_unique<media::CdmKeyInformation>(
-      input->key_id, input->status, input->system_code);
-}
-
-// static
 media::mojom::AudioBufferPtr
 TypeConverter<media::mojom::AudioBufferPtr, scoped_refptr<media::AudioBuffer>>::
     Convert(const scoped_refptr<media::AudioBuffer>& input) {
diff --git a/media/mojo/common/media_type_converters.h b/media/mojo/common/media_type_converters.h
index 3a8d219c..95bd75d 100644
--- a/media/mojo/common/media_type_converters.h
+++ b/media/mojo/common/media_type_converters.h
@@ -16,7 +16,6 @@
 class AudioBuffer;
 class DecoderBuffer;
 class DecryptConfig;
-struct CdmKeyInformation;
 }
 
 // These are specializations of mojo::TypeConverter and have to be in the mojo
@@ -48,19 +47,6 @@
 };
 
 template <>
-struct TypeConverter<media::mojom::CdmKeyInformationPtr,
-                     media::CdmKeyInformation> {
-  static media::mojom::CdmKeyInformationPtr Convert(
-      const media::CdmKeyInformation& input);
-};
-template <>
-struct TypeConverter<std::unique_ptr<media::CdmKeyInformation>,
-                     media::mojom::CdmKeyInformationPtr> {
-  static std::unique_ptr<media::CdmKeyInformation> Convert(
-      const media::mojom::CdmKeyInformationPtr& input);
-};
-
-template <>
 struct TypeConverter<media::mojom::AudioBufferPtr,
                      scoped_refptr<media::AudioBuffer>> {
   static media::mojom::AudioBufferPtr Convert(
diff --git a/media/mojo/interfaces/BUILD.gn b/media/mojo/interfaces/BUILD.gn
index fe46891f..66c2b1a 100644
--- a/media/mojo/interfaces/BUILD.gn
+++ b/media/mojo/interfaces/BUILD.gn
@@ -116,6 +116,7 @@
 
   sources = [
     "audio_decoder_config_struct_traits_unittest.cc",
+    "cdm_key_information_mojom_traits_unittest.cc",
     "encryption_scheme_struct_traits_unittest.cc",
     "video_decoder_config_struct_traits_unittest.cc",
     "video_frame_struct_traits_unittest.cc",
diff --git a/media/mojo/interfaces/cdm_key_information.typemap b/media/mojo/interfaces/cdm_key_information.typemap
new file mode 100644
index 0000000..89c2930
--- /dev/null
+++ b/media/mojo/interfaces/cdm_key_information.typemap
@@ -0,0 +1,23 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+mojom = "//media/mojo/interfaces/content_decryption_module.mojom"
+
+public_headers = [ "//media/base/cdm_key_information.h" ]
+
+traits_headers =
+    [ "//media/mojo/interfaces/cdm_key_information_mojom_traits.h" ]
+
+sources = [
+  "//media/mojo/interfaces/cdm_key_information_mojom_traits.cc",
+]
+
+public_deps = [
+  "//media",
+]
+
+type_mappings = [
+  "media.mojom.CdmKeyInformation=std::unique_ptr<media::CdmKeyInformation>[move_only]",
+  "media.mojom.CdmKeyStatus=media::CdmKeyInformation::KeyStatus",
+]
diff --git a/media/mojo/interfaces/cdm_key_information_mojom_traits.cc b/media/mojo/interfaces/cdm_key_information_mojom_traits.cc
new file mode 100644
index 0000000..7a3ce04
--- /dev/null
+++ b/media/mojo/interfaces/cdm_key_information_mojom_traits.cc
@@ -0,0 +1,85 @@
+// 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 "media/mojo/interfaces/cdm_key_information_mojom_traits.h"
+
+#include "base/logging.h"
+
+namespace mojo {
+
+using MojomKeyStatus = media::mojom::CdmKeyStatus;
+using NativeKeyStatus = media::CdmKeyInformation::KeyStatus;
+
+// static
+MojomKeyStatus EnumTraits<MojomKeyStatus, NativeKeyStatus>::ToMojom(
+    NativeKeyStatus error) {
+  switch (error) {
+    case NativeKeyStatus::USABLE:
+      return MojomKeyStatus::USABLE;
+    case NativeKeyStatus::INTERNAL_ERROR:
+      return MojomKeyStatus::INTERNAL_ERROR;
+    case NativeKeyStatus::EXPIRED:
+      return MojomKeyStatus::EXPIRED;
+    case NativeKeyStatus::OUTPUT_RESTRICTED:
+      return MojomKeyStatus::OUTPUT_RESTRICTED;
+    case NativeKeyStatus::OUTPUT_DOWNSCALED:
+      return MojomKeyStatus::OUTPUT_DOWNSCALED;
+    case NativeKeyStatus::KEY_STATUS_PENDING:
+      return MojomKeyStatus::KEY_STATUS_PENDING;
+    case NativeKeyStatus::RELEASED:
+      return MojomKeyStatus::RELEASED;
+  }
+  NOTREACHED();
+  return MojomKeyStatus::INTERNAL_ERROR;
+}
+
+// static
+bool EnumTraits<MojomKeyStatus, NativeKeyStatus>::FromMojom(
+    MojomKeyStatus error,
+    NativeKeyStatus* out) {
+  switch (error) {
+    case MojomKeyStatus::USABLE:
+      *out = NativeKeyStatus::USABLE;
+      return true;
+    case MojomKeyStatus::INTERNAL_ERROR:
+      *out = NativeKeyStatus::INTERNAL_ERROR;
+      return true;
+    case MojomKeyStatus::EXPIRED:
+      *out = NativeKeyStatus::EXPIRED;
+      return true;
+    case MojomKeyStatus::OUTPUT_RESTRICTED:
+      *out = NativeKeyStatus::OUTPUT_RESTRICTED;
+      return true;
+    case MojomKeyStatus::OUTPUT_DOWNSCALED:
+      *out = NativeKeyStatus::OUTPUT_DOWNSCALED;
+      return true;
+    case MojomKeyStatus::KEY_STATUS_PENDING:
+      *out = NativeKeyStatus::KEY_STATUS_PENDING;
+      return true;
+    case MojomKeyStatus::RELEASED:
+      *out = NativeKeyStatus::RELEASED;
+      return true;
+  }
+  NOTREACHED();
+  return false;
+}
+
+// static
+bool StructTraits<media::mojom::CdmKeyInformationDataView,
+                  std::unique_ptr<media::CdmKeyInformation>>::
+    Read(media::mojom::CdmKeyInformationDataView input,
+         std::unique_ptr<media::CdmKeyInformation>* output) {
+  mojo::ArrayDataView<uint8_t> key_id;
+  input.GetKeyIdDataView(&key_id);
+
+  NativeKeyStatus status;
+  if (!input.ReadStatus(&status))
+    return false;
+
+  *output = std::make_unique<media::CdmKeyInformation>(
+      key_id.data(), key_id.size(), status, input.system_code());
+  return true;
+}
+
+}  // namespace mojo
\ No newline at end of file
diff --git a/media/mojo/interfaces/cdm_key_information_mojom_traits.h b/media/mojo/interfaces/cdm_key_information_mojom_traits.h
new file mode 100644
index 0000000..eb04722
--- /dev/null
+++ b/media/mojo/interfaces/cdm_key_information_mojom_traits.h
@@ -0,0 +1,47 @@
+// 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 MEDIA_MOJO_INTERFACES_CDM_KEY_INFORMATION_MOJOM_TRAITS_H_
+#define MEDIA_MOJO_INTERFACES_CDM_KEY_INFORMATION_MOJOM_TRAITS_H_
+
+#include "media/base/cdm_key_information.h"
+#include "media/mojo/interfaces/content_decryption_module.mojom.h"
+
+namespace mojo {
+
+template <>
+struct EnumTraits<media::mojom::CdmKeyStatus,
+                  media::CdmKeyInformation::KeyStatus> {
+  static media::mojom::CdmKeyStatus ToMojom(
+      media::CdmKeyInformation::KeyStatus key_status);
+
+  static bool FromMojom(media::mojom::CdmKeyStatus input,
+                        media::CdmKeyInformation::KeyStatus* out);
+};
+
+template <>
+struct StructTraits<media::mojom::CdmKeyInformationDataView,
+                    std::unique_ptr<media::CdmKeyInformation>> {
+  static const std::vector<uint8_t>& key_id(
+      const std::unique_ptr<media::CdmKeyInformation>& input) {
+    return input->key_id;
+  }
+
+  static media::CdmKeyInformation::KeyStatus status(
+      const std::unique_ptr<media::CdmKeyInformation>& input) {
+    return input->status;
+  }
+
+  static uint32_t system_code(
+      const std::unique_ptr<media::CdmKeyInformation>& input) {
+    return input->system_code;
+  }
+
+  static bool Read(media::mojom::CdmKeyInformationDataView input,
+                   std::unique_ptr<media::CdmKeyInformation>* output);
+};
+
+}  // namespace mojo
+
+#endif  // MEDIA_MOJO_INTERFACES_CDM_KEY_INFORMATION_MOJOM_TRAITS_H_
diff --git a/media/mojo/interfaces/cdm_key_information_mojom_traits_unittest.cc b/media/mojo/interfaces/cdm_key_information_mojom_traits_unittest.cc
new file mode 100644
index 0000000..916b4c7
--- /dev/null
+++ b/media/mojo/interfaces/cdm_key_information_mojom_traits_unittest.cc
@@ -0,0 +1,26 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/mojo/interfaces/cdm_key_information_mojom_traits.h"
+
+#include "media/base/cdm_key_information.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+
+TEST(CdmKeyInformationStructTraitsTest, ConvertCdmKeyInformation) {
+  auto input = std::make_unique<CdmKeyInformation>(
+      "key_id", CdmKeyInformation::KeyStatus::USABLE, 23);
+  std::vector<uint8_t> data =
+      media::mojom::CdmKeyInformation::Serialize(&input);
+
+  std::unique_ptr<CdmKeyInformation> output;
+  EXPECT_TRUE(
+      media::mojom::CdmKeyInformation::Deserialize(std::move(data), &output));
+  EXPECT_EQ(input->key_id, output->key_id);
+  EXPECT_EQ(input->status, output->status);
+  EXPECT_EQ(input->system_code, output->system_code);
+}
+
+}  // namespace media
diff --git a/media/mojo/interfaces/content_decryption_module.mojom b/media/mojo/interfaces/content_decryption_module.mojom
index 612932f..61994ad3 100644
--- a/media/mojo/interfaces/content_decryption_module.mojom
+++ b/media/mojo/interfaces/content_decryption_module.mojom
@@ -21,8 +21,15 @@
 enum CdmMessageType;
 
 // See media::CdmKeyInformation::KeyStatus
-[Native]
-enum CdmKeyStatus;
+enum CdmKeyStatus {
+    USABLE,
+    INTERNAL_ERROR,
+    EXPIRED,
+    OUTPUT_RESTRICTED,
+    OUTPUT_DOWNSCALED,
+    KEY_STATUS_PENDING,
+    RELEASED,
+};
 
 // See media::HdcpVersion
 [Native]
diff --git a/media/mojo/interfaces/content_decryption_module.typemap b/media/mojo/interfaces/content_decryption_module.typemap
index 60c33b0..45160097 100644
--- a/media/mojo/interfaces/content_decryption_module.typemap
+++ b/media/mojo/interfaces/content_decryption_module.typemap
@@ -21,7 +21,6 @@
 
 type_mappings = [
   "media.mojom.CdmConfig=media::CdmConfig",
-  "media.mojom.CdmKeyStatus=media::CdmKeyInformation::KeyStatus",
   "media.mojom.CdmPromiseResult.Exception=media::CdmPromise::Exception",
   "media.mojom.CdmSessionType=media::CdmSessionType",
   "media.mojom.CdmMessageType=media::CdmMessageType",
diff --git a/media/mojo/interfaces/typemaps.gni b/media/mojo/interfaces/typemaps.gni
index 46aa55d4..d8cb918 100644
--- a/media/mojo/interfaces/typemaps.gni
+++ b/media/mojo/interfaces/typemaps.gni
@@ -5,6 +5,7 @@
 typemaps = [
   "//media/mojo/interfaces/audio_decoder_config.typemap",
   "//media/mojo/interfaces/audio_parameters.typemap",
+  "//media/mojo/interfaces/cdm_key_information.typemap",
   "//media/mojo/interfaces/cdm_proxy.typemap",
   "//media/mojo/interfaces/content_decryption_module.typemap",
   "//media/mojo/interfaces/decryptor.typemap",
diff --git a/media/mojo/services/mojo_cdm_service.cc b/media/mojo/services/mojo_cdm_service.cc
index 9790fcc..1ccfd2f 100644
--- a/media/mojo/services/mojo_cdm_service.cc
+++ b/media/mojo/services/mojo_cdm_service.cc
@@ -209,11 +209,8 @@
   DVLOG(2) << __func__
            << " has_additional_usable_key = " << has_additional_usable_key;
 
-  std::vector<mojom::CdmKeyInformationPtr> keys_data;
-  for (auto& key : keys_info)
-    keys_data.push_back(mojom::CdmKeyInformation::From(*(key.get())));
   client_->OnSessionKeysChange(session_id, has_additional_usable_key,
-                               std::move(keys_data));
+                               std::move(keys_info));
 }
 
 void MojoCdmService::OnSessionExpirationUpdate(const std::string& session_id,
diff --git a/mojo/core/test/mojo_test_base.cc b/mojo/core/test/mojo_test_base.cc
index cf3c7d9..7b299637 100644
--- a/mojo/core/test/mojo_test_base.cc
+++ b/mojo/core/test/mojo_test_base.cc
@@ -19,11 +19,6 @@
 #include "mojo/public/cpp/system/wait.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-#include "base/mac/mach_port_broker.h"
-#include "mojo/core/embedder/default_mach_broker.h"
-#endif
-
 namespace mojo {
 namespace core {
 namespace test {
@@ -43,20 +38,7 @@
                                                  MojoTestBase* test,
                                                  LaunchType launch_type) {
 #if !defined(OS_IOS)
-#if defined(OS_MACOSX)
-  // This lock needs to be held while launching the child because the Mach port
-  // broker only allows task ports to be received from known child processes.
-  // However, it can only know the child process's pid after the child has
-  // launched. To prevent a race where the child process sends its task port
-  // before the pid has been registered, the lock needs to be held over both
-  // launch and child pid registration.
-  auto* broker = DefaultMachBroker::Get();
-  base::AutoLock lock(broker->GetLock());
-#endif
   pipe_ = helper_.StartChild(client_name, launch_type);
-#if defined(OS_MACOSX)
-  broker->ExpectPid(helper_.test_child().Handle());
-#endif
 #endif
 }
 
@@ -69,11 +51,6 @@
   was_shutdown_ = true;
 #if !defined(OS_IOS)
   int retval = helper_.WaitForChildShutdown();
-#if defined(OS_MACOSX)
-  auto* broker = DefaultMachBroker::Get();
-  base::AutoLock lock(broker->GetLock());
-  broker->RemovePid(helper_.test_child().Handle());
-#endif
   return retval;
 #else
   NOTREACHED();
diff --git a/mojo/core/test/multiprocess_test_helper.cc b/mojo/core/test/multiprocess_test_helper.cc
index 803a2fa9..d4af9ff 100644
--- a/mojo/core/test/multiprocess_test_helper.cc
+++ b/mojo/core/test/multiprocess_test_helper.cc
@@ -202,8 +202,26 @@
       break;
   }
 
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+  // This lock needs to be held while launching the child because the Mach port
+  // broker only allows task ports to be received from known child processes.
+  // However, it can only know the child process's pid after the child has
+  // launched. To prevent a race where the child process sends its task port
+  // before the pid has been registered, the lock needs to be held over both
+  // launch and child pid registration.
+  auto* mach_broker = mojo::core::DefaultMachBroker::Get();
+  mach_broker->GetLock().Acquire();
+#endif
+
   test_child_ =
       base::SpawnMultiProcessTestChild(test_child_main, command_line, options);
+
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+  if (test_child_.IsValid())
+    mach_broker->ExpectPid(test_child_.Pid());
+  mach_broker->GetLock().Release();
+#endif
+
   if (launch_type == LaunchType::CHILD || launch_type == LaunchType::PEER)
     channel.RemoteProcessLaunchAttempted();
 
@@ -232,6 +250,13 @@
   int rv = -1;
   WaitForMultiprocessTestChildExit(test_child_, TestTimeouts::action_timeout(),
                                    &rv);
+
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+  auto* mach_broker = mojo::core::DefaultMachBroker::Get();
+  base::AutoLock lock(mach_broker->GetLock());
+  mach_broker->RemovePid(test_child_.Pid());
+#endif
+
   test_child_.Close();
   return rv;
 }
diff --git a/mojo/public/cpp/system/simple_watcher.cc b/mojo/public/cpp/system/simple_watcher.cc
index 6384c1ab..26f99c93 100644
--- a/mojo/public/cpp/system/simple_watcher.cc
+++ b/mojo/public/cpp/system/simple_watcher.cc
@@ -42,6 +42,8 @@
     *result = MojoAddTrigger(trap_handle.value(), handle.value(), signals,
                              condition, context->value(), nullptr);
     if (*result != MOJO_RESULT_OK) {
+      context->cancelled_ = true;
+
       // Balanced by the AddRef() above since MojoAddTrigger failed.
       context->Release();
       return nullptr;
@@ -76,7 +78,17 @@
       : weak_watcher_(weak_watcher),
         task_runner_(task_runner),
         watch_id_(watch_id) {}
-  ~Context() {}
+
+  ~Context() {
+    // TODO(https://crbug.com/896419): Remove this once it's been live for a
+    // while. This is intended to catch possible double-frees of SimpleWatchers,
+    // due to, e.g., invalid cross-thread usage of bindings endpoints. If this
+    // CHECK fails, then the Context is being destroyed before a cancellation
+    // notification fired. In that case we know a Context ref has been
+    // double-released and we can catch its stack.
+    base::AutoLock lock(lock_);
+    CHECK(cancelled_);
+  }
 
   void Notify(MojoResult result,
               MojoHandleSignalsState signals_state,
@@ -90,6 +102,7 @@
       // closed due to pipe error, all before the thread's TaskRunner has been
       // properly initialized.
       base::AutoLock lock(lock_);
+      cancelled_ = true;
       if (!enable_cancellation_notifications_)
         return;
     }
@@ -115,6 +128,7 @@
   const int watch_id_;
 
   base::Lock lock_;
+  bool cancelled_ = false;
   bool enable_cancellation_notifications_ = true;
 
   DISALLOW_COPY_AND_ASSIGN(Context);
diff --git a/mojo/public/tools/bindings/generators/js_templates/lite/interface_externs.tmpl b/mojo/public/tools/bindings/generators/js_templates/lite/interface_externs.tmpl
index e4dad5f5..2934557 100644
--- a/mojo/public/tools/bindings/generators/js_templates/lite/interface_externs.tmpl
+++ b/mojo/public/tools/bindings/generators/js_templates/lite/interface_externs.tmpl
@@ -91,3 +91,12 @@
    */
   removeListener(id) {}
 };
+
+{#--- Enum definitions #}
+{% for enum in interface.enums %}
+/** @enum {number} */
+{{module.namespace}}.{{interface.name}}.{{enum.name}} = {};
+{%-   for field in enum.fields %}
+{{module.namespace}}.{{interface.name}}.{{enum.name}}.{{field.name}};
+{%-   endfor %}
+{%- endfor %}
diff --git a/mojo/public/tools/bindings/generators/js_templates/lite/struct_externs.tmpl b/mojo/public/tools/bindings/generators/js_templates/lite/struct_externs.tmpl
index c64ce8d8..c3322e1 100644
--- a/mojo/public/tools/bindings/generators/js_templates/lite/struct_externs.tmpl
+++ b/mojo/public/tools/bindings/generators/js_templates/lite/struct_externs.tmpl
@@ -10,3 +10,12 @@
 {%-  endfor %}
   }
 };
+
+{#--- Enum definitions #}
+{% for enum in struct.enums %}
+/** @enum {number} */
+{{module.namespace}}.{{struct.name}}.{{enum.name}} = {};
+{%-   for field in enum.fields %}
+{{module.namespace}}.{{struct.name}}.{{enum.name}}.{{field.name}};
+{%-   endfor %}
+{%- endfor %}
diff --git a/mojo/public/tools/bindings/generators/mojom_js_generator.py b/mojo/public/tools/bindings/generators/mojom_js_generator.py
index fe53ec5..b9e3656 100644
--- a/mojo/public/tools/bindings/generators/mojom_js_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_js_generator.py
@@ -419,15 +419,6 @@
   def _LiteClosureType(self, kind):
     if kind in mojom.PRIMITIVES:
       return _kind_to_closure_type[kind]
-    if mojom.IsInterfaceKind(kind):
-      return kind.module.namespace + "." + kind.name + "Proxy"
-    if mojom.IsInterfaceRequestKind(kind):
-      return kind.kind.module.namespace + "." + kind.kind.name + "Request"
-    if (mojom.IsStructKind(kind) or
-        mojom.IsEnumKind(kind)):
-      return kind.module.namespace + "." + kind.name
-    if mojom.IsUnionKind(kind):
-      return kind.module.namespace + "." + kind.name
     if mojom.IsArrayKind(kind):
       return "Array<%s>" % self._ClosureType(kind.kind)
     if mojom.IsMapKind(kind) and self._IsStringableKind(kind.key_kind):
@@ -440,13 +431,33 @@
       return "Map<%s, %s>" % (
           self._LiteClosureType(kind.key_kind),
           self._LiteClosureType(kind.value_kind))
+
+    if mojom.IsAssociatedKind(kind) or mojom.IsInterfaceRequestKind(kind):
+      named_kind = kind.kind
+    else:
+      named_kind = kind
+
+    name = []
+    if named_kind.module:
+      name.append(named_kind.module.namespace)
+    if named_kind.parent_kind:
+      name.append(named_kind.parent_kind.name)
+    name.append("" + named_kind.name)
+    name = ".".join(name)
+
+    if (mojom.IsStructKind(kind) or mojom.IsUnionKind(kind) or
+        mojom.IsEnumKind(kind)):
+      return name
+    if mojom.IsInterfaceKind(kind):
+      return name + "Proxy"
+    if mojom.IsInterfaceRequestKind(kind):
+      return name + "Request"
     # TODO(calamity): Support associated interfaces properly.
     if mojom.IsAssociatedInterfaceKind(kind):
-      return "mojo.internal.AssociatedInterfaceProxy"
+      return "Object"
     # TODO(calamity): Support associated interface requests properly.
     if mojom.IsAssociatedInterfaceRequestKind(kind):
-      return "mojo.internal.AssociatedInterfaceRequest"
-    # TODO(calamity): Support enums properly.
+      return "Object"
 
     raise Exception("No valid closure type: %s" % kind)
 
diff --git a/net/network_error_logging/network_error_logging_end_to_end_test.cc b/net/network_error_logging/network_error_logging_end_to_end_test.cc
index e7a7e32..302a01e 100644
--- a/net/network_error_logging/network_error_logging_end_to_end_test.cc
+++ b/net/network_error_logging/network_error_logging_end_to_end_test.cc
@@ -165,7 +165,7 @@
   DISALLOW_COPY_AND_ASSIGN(NetworkErrorLoggingEndToEndTest);
 };
 
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_FUCHSIA)
 // TODO(https://crbug.com/829650): Fix and re-enable these tests.
 #define MAYBE_ReportNetworkError DISABLED_ReportNetworkError
 #else
@@ -208,7 +208,7 @@
   ExpectDictIntegerValue(0, *body_dict, "status_code");
 }
 
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_FUCHSIA)
 // TODO(https://crbug.com/829650): Fix and re-enable these tests.
 #define MAYBE_UploadAtShutdown DISABLED_UploadAtShutdown
 #else
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc
index 6925cb30..5d1fd75 100644
--- a/net/quic/quic_chromium_client_session.cc
+++ b/net/quic/quic_chromium_client_session.cc
@@ -1871,8 +1871,9 @@
                       quic::ConnectionCloseBehavior::SILENT_CLOSE);
 }
 
-void QuicChromiumClientSession::OnProbeNetworkSucceeded(
+void QuicChromiumClientSession::OnProbeSucceeded(
     NetworkChangeNotifier::NetworkHandle network,
+    const quic::QuicSocketAddress& peer_address,
     const quic::QuicSocketAddress& self_address,
     std::unique_ptr<DatagramClientSocket> socket,
     std::unique_ptr<QuicChromiumPacketWriter> writer,
@@ -1936,8 +1937,9 @@
   }
 }
 
-void QuicChromiumClientSession::OnProbeNetworkFailed(
-    NetworkChangeNotifier::NetworkHandle network) {
+void QuicChromiumClientSession::OnProbeFailed(
+    NetworkChangeNotifier::NetworkHandle network,
+    const quic::QuicSocketAddress& peer_address) {
   net_log_.AddEvent(
       NetLogEventType::QUIC_CONNECTION_CONNECTIVITY_PROBING_FAILED,
       NetLog::Int64Callback("network", network));
diff --git a/net/quic/quic_chromium_client_session.h b/net/quic/quic_chromium_client_session.h
index c30914f9..93bd7f26 100644
--- a/net/quic/quic_chromium_client_session.h
+++ b/net/quic/quic_chromium_client_session.h
@@ -433,15 +433,16 @@
   void OnWriteUnblocked() override;
 
   // QuicConnectivityProbingManager::Delegate override.
-  void OnProbeNetworkSucceeded(
+  void OnProbeSucceeded(
       NetworkChangeNotifier::NetworkHandle network,
+      const quic::QuicSocketAddress& peer_address,
       const quic::QuicSocketAddress& self_address,
       std::unique_ptr<DatagramClientSocket> socket,
       std::unique_ptr<QuicChromiumPacketWriter> writer,
       std::unique_ptr<QuicChromiumPacketReader> reader) override;
 
-  void OnProbeNetworkFailed(
-      NetworkChangeNotifier::NetworkHandle network) override;
+  void OnProbeFailed(NetworkChangeNotifier::NetworkHandle network,
+                     const quic::QuicSocketAddress& peer_address) override;
 
   bool OnSendConnectivityProbingPacket(
       QuicChromiumPacketWriter* writer,
diff --git a/net/quic/quic_connectivity_probing_manager.cc b/net/quic/quic_connectivity_probing_manager.cc
index c4af1da..3a4a27e 100644
--- a/net/quic/quic_connectivity_probing_manager.cc
+++ b/net/quic/quic_connectivity_probing_manager.cc
@@ -176,8 +176,9 @@
                       base::TimeTicks::Now() - probe_start_time_);
 
   // Notify the delegate that the probe succeeds and reset everything.
-  delegate_->OnProbeNetworkSucceeded(network_, self_address, std::move(socket_),
-                                     std::move(writer_), std::move(reader_));
+  delegate_->OnProbeSucceeded(network_, peer_address_, self_address,
+                              std::move(socket_), std::move(writer_),
+                              std::move(reader_));
   CancelProbingIfAny();
 }
 
@@ -200,7 +201,7 @@
 
 void QuicConnectivityProbingManager::NotifyDelegateProbeFailed() {
   if (network_ != NetworkChangeNotifier::kInvalidNetworkHandle) {
-    delegate_->OnProbeNetworkFailed(network_);
+    delegate_->OnProbeFailed(network_, peer_address_);
     CancelProbingIfAny();
   }
 }
diff --git a/net/quic/quic_connectivity_probing_manager.h b/net/quic/quic_connectivity_probing_manager.h
index 4611031..a197edf 100644
--- a/net/quic/quic_connectivity_probing_manager.h
+++ b/net/quic/quic_connectivity_probing_manager.h
@@ -20,23 +20,25 @@
 class NET_EXPORT_PRIVATE QuicConnectivityProbingManager
     : public QuicChromiumPacketWriter::Delegate {
  public:
-  // Delegate interface which receives notifications on network probing
-  // results.
+  // Delegate interface which receives notifications on probing results.
   class NET_EXPORT_PRIVATE Delegate {
    public:
     virtual ~Delegate() {}
-    // Called when probing on |network| succeeded. Caller hands off ownership
-    // of |socket|, |writer| and |reader| for |network| to delegate.
-    virtual void OnProbeNetworkSucceeded(
+
+    // Called when probing to |peer_address| on |network| succeeded.
+    // Caller hands off the ownership of |socket|, |writer| and |reader| for
+    // |peer_address| on |network| to delegate.
+    virtual void OnProbeSucceeded(
         NetworkChangeNotifier::NetworkHandle network,
+        const quic::QuicSocketAddress& peer_address,
         const quic::QuicSocketAddress& self_address,
         std::unique_ptr<DatagramClientSocket> socket,
         std::unique_ptr<QuicChromiumPacketWriter> writer,
         std::unique_ptr<QuicChromiumPacketReader> reader) = 0;
 
-    // Called when probing on |network| fails.
-    virtual void OnProbeNetworkFailed(
-        NetworkChangeNotifier::NetworkHandle network) = 0;
+    // Called when probing to |peer_address| on |network| failed.
+    virtual void OnProbeFailed(NetworkChangeNotifier::NetworkHandle network,
+                               const quic::QuicSocketAddress& peer_address) = 0;
 
     // Called when a connectivity probing packet needs to be sent to
     // |peer_address| using |writer|. Returns true if subsequent packets can be
diff --git a/net/quic/quic_connectivity_probing_manager_test.cc b/net/quic/quic_connectivity_probing_manager_test.cc
index 76e1b4a..2d36564 100644
--- a/net/quic/quic_connectivity_probing_manager_test.cc
+++ b/net/quic/quic_connectivity_probing_manager_test.cc
@@ -47,15 +47,17 @@
                     const quic::QuicSocketAddress& local_address,
                     const quic::QuicSocketAddress& peer_address));
 
-  MOCK_METHOD1(OnProbeNetworkFailed,
-               void(NetworkChangeNotifier::NetworkHandle network));
+  MOCK_METHOD2(OnProbeFailed,
+               void(NetworkChangeNotifier::NetworkHandle network,
+                    const quic::QuicSocketAddress& peer_address));
 
   MOCK_METHOD2(OnSendConnectivityProbingPacket,
                bool(QuicChromiumPacketWriter* writer,
                     const quic::QuicSocketAddress& peer_address));
 
-  void OnProbeNetworkSucceeded(
+  void OnProbeSucceeded(
       NetworkChangeNotifier::NetworkHandle network,
+      const quic::QuicSocketAddress& peer_address,
       const quic::QuicSocketAddress& self_address,
       std::unique_ptr<DatagramClientSocket> socket,
       std::unique_ptr<QuicChromiumPacketWriter> writer,
@@ -259,7 +261,8 @@
 
   // Move forward another 1600ms, expect probing manager will no longer send any
   // connectivity probing packet but declare probing as failed .
-  EXPECT_CALL(session_, OnProbeNetworkFailed(testNetworkHandle)).Times(1);
+  EXPECT_CALL(session_, OnProbeFailed(testNetworkHandle, testPeerAddress))
+      .Times(1);
   int timeout_ms = (1 << 4) * initial_timeout_ms;
   test_task_runner_->FastForwardBy(
       base::TimeDelta::FromMilliseconds(timeout_ms));
@@ -297,7 +300,7 @@
   // Request cancel probing, manager will no longer send connectivity probing
   // packet for this probing.
   EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, _)).Times(0);
-  EXPECT_CALL(session_, OnProbeNetworkFailed(_)).Times(0);
+  EXPECT_CALL(session_, OnProbeFailed(_, _)).Times(0);
   probing_manager_.CancelProbing(testNetworkHandle);
   test_task_runner_->RunUntilIdle();
 }
@@ -335,7 +338,8 @@
   // write error. Manager will notify session of the probe failure, cancel
   // probing to prevent future connectivity probing packet to be sent.
   EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, _)).Times(0);
-  EXPECT_CALL(session_, OnProbeNetworkFailed(testNetworkHandle)).Times(1);
+  EXPECT_CALL(session_, OnProbeFailed(testNetworkHandle, testPeerAddress))
+      .Times(1);
   writer_ptr->OnWriteComplete(ERR_CONNECTION_CLOSED);
   test_task_runner_->FastForwardBy(
       base::TimeDelta::FromMilliseconds(initial_timeout_ms));
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc
index 4afde89..59fdb39 100644
--- a/net/socket/ssl_client_socket_impl.cc
+++ b/net/socket/ssl_client_socket_impl.cc
@@ -835,15 +835,6 @@
 
   SSL_set_early_data_enabled(ssl_.get(), ssl_config_.early_data_enabled);
 
-  switch (ssl_config_.tls13_variant) {
-    case kTLS13VariantDraft23:
-      SSL_set_tls13_variant(ssl_.get(), tls13_draft23);
-      break;
-    case kTLS13VariantFinal:
-      SSL_set_tls13_variant(ssl_.get(), tls13_rfc);
-      break;
-  }
-
   if (!base::FeatureList::IsEnabled(features::kEnforceTLS13Downgrade) ||
       base::GetFieldTrialParamByFeatureAsBool(features::kEnforceTLS13Downgrade,
                                               "known_roots_only", false)) {
diff --git a/net/ssl/ssl_config.cc b/net/ssl/ssl_config.cc
index bde8eaeb..a21037f 100644
--- a/net/ssl/ssl_config.cc
+++ b/net/ssl/ssl_config.cc
@@ -14,8 +14,6 @@
 
 const uint16_t kDefaultSSLVersionMax = SSL_PROTOCOL_VERSION_TLS1_3;
 
-const TLS13Variant kDefaultTLS13Variant = kTLS13VariantFinal;
-
 SSLConfig::CertAndStatus::CertAndStatus() = default;
 SSLConfig::CertAndStatus::CertAndStatus(scoped_refptr<X509Certificate> cert_arg,
                                         CertStatus status)
@@ -26,7 +24,6 @@
 SSLConfig::SSLConfig()
     : version_min(kDefaultSSLVersionMin),
       version_max(kDefaultSSLVersionMax),
-      tls13_variant(kDefaultTLS13Variant),
       early_data_enabled(false),
       version_interference_probe(false),
       channel_id_enabled(false),
diff --git a/net/ssl/ssl_config.h b/net/ssl/ssl_config.h
index 931ae1d5..8d660542 100644
--- a/net/ssl/ssl_config.h
+++ b/net/ssl/ssl_config.h
@@ -29,20 +29,12 @@
   SSL_PROTOCOL_VERSION_TLS1_3 = 0x0304,
 };
 
-enum TLS13Variant {
-  kTLS13VariantDraft23,
-  kTLS13VariantFinal,
-};
-
 // Default minimum protocol version.
 NET_EXPORT extern const uint16_t kDefaultSSLVersionMin;
 
 // Default maximum protocol version.
 NET_EXPORT extern const uint16_t kDefaultSSLVersionMax;
 
-// Default TLS 1.3 variant.
-NET_EXPORT extern const TLS13Variant kDefaultTLS13Variant;
-
 // A collection of SSL-related configuration settings.
 struct NET_EXPORT SSLConfig {
   // Default to revocation checking.
@@ -67,10 +59,6 @@
   uint16_t version_min;
   uint16_t version_max;
 
-  // The TLS 1.3 variant that is enabled. This only takes affect if TLS 1.3 is
-  // also enabled via version_min and version_max.
-  TLS13Variant tls13_variant;
-
   // Whether early data is enabled on this connection. Note that early data has
   // weaker security properties than normal data and changes the
   // SSLClientSocket's behavior. The caller must only send replayable data prior
diff --git a/net/ssl/ssl_config_service.cc b/net/ssl/ssl_config_service.cc
index eeb1169..e81ffd90 100644
--- a/net/ssl/ssl_config_service.cc
+++ b/net/ssl/ssl_config_service.cc
@@ -16,13 +16,11 @@
 bool SSLConfigsAreEqual(const net::SSLConfig& config1,
                         const net::SSLConfig& config2) {
   return std::tie(config1.version_min, config1.version_max,
-                  config1.tls13_variant, config1.disabled_cipher_suites,
-                  config1.channel_id_enabled, config1.false_start_enabled,
-                  config1.require_ecdhe) ==
+                  config1.disabled_cipher_suites, config1.channel_id_enabled,
+                  config1.false_start_enabled, config1.require_ecdhe) ==
          std::tie(config2.version_min, config2.version_max,
-                  config2.tls13_variant, config2.disabled_cipher_suites,
-                  config2.channel_id_enabled, config2.false_start_enabled,
-                  config2.require_ecdhe);
+                  config2.disabled_cipher_suites, config2.channel_id_enabled,
+                  config2.false_start_enabled, config2.require_ecdhe);
 }
 
 }  // namespace
diff --git a/net/ssl/ssl_config_service.h b/net/ssl/ssl_config_service.h
index 9f32e86..3ec9da49 100644
--- a/net/ssl/ssl_config_service.h
+++ b/net/ssl/ssl_config_service.h
@@ -28,7 +28,6 @@
     // The following settings are considered user changes:
     //     version_min
     //     version_max
-    //     tls13_variant
     //     disabled_cipher_suites
     //     channel_id_enabled
     //     false_start_enabled
diff --git a/services/audio/service.cc b/services/audio/service.cc
index ef4fb4a8..b457b5e7cb 100644
--- a/services/audio/service.cc
+++ b/services/audio/service.cc
@@ -14,6 +14,7 @@
 #include "base/trace_event/trace_event.h"
 #include "components/crash/core/common/crash_key.h"
 #include "media/audio/audio_manager.h"
+#include "media/base/bind_to_current_loop.h"
 #include "services/audio/debug_recording.h"
 #include "services/audio/device_notifier.h"
 #include "services/audio/log_factory_manager.h"
@@ -203,6 +204,7 @@
 
 void Service::InitializeDeviceMonitor() {
   CHECK_EQ(magic_bytes_, 0x600DC0DEu);
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 #if defined(OS_MACOSX)
   if (audio_device_listener_mac_)
     return;
@@ -210,12 +212,12 @@
   TRACE_EVENT0("audio", "audio::Service::InitializeDeviceMonitor");
 
   audio_device_listener_mac_ = std::make_unique<media::AudioDeviceListenerMac>(
-      base::BindRepeating([] {
+      media::BindToCurrentLoop(base::BindRepeating([] {
         if (base::SystemMonitor::Get()) {
           base::SystemMonitor::Get()->ProcessDevicesChanged(
               base::SystemMonitor::DEVTYPE_AUDIO);
         }
-      }),
+      })),
       true /* monitor_default_input */, true /* monitor_addition_removal */,
       true /* monitor_sources */);
 #endif
diff --git a/services/network/public/mojom/ssl_config.mojom b/services/network/public/mojom/ssl_config.mojom
index bca851a6..84e56f99 100644
--- a/services/network/public/mojom/ssl_config.mojom
+++ b/services/network/public/mojom/ssl_config.mojom
@@ -11,12 +11,6 @@
   kTLS13,
 };
 
-// Versions of TLS 1.3 that are supported.
-enum TLS13Variant {
-  kDraft23,
-  kFinal,
-};
-
 // This contains the subset of net::SSLConfig members that are managed by the
 // net::SSLConfigService. See net::SSLConfig for field descriptions.
 struct SSLConfig {
@@ -31,8 +25,6 @@
   SSLVersion version_min = kTLS1;
   SSLVersion version_max = kTLS13;
 
-  TLS13Variant tls13_variant = kFinal;
-
   // Though cipher suites are sent in TLS as "uint8_t CipherSuite[2]", in
   // big-endian form, they should be declared in host byte order, with the
   // first uint8_t occupying the most significant byte.
diff --git a/services/network/ssl_config_service_mojo_unittest.cc b/services/network/ssl_config_service_mojo_unittest.cc
index 6259c9f..6af9826 100644
--- a/services/network/ssl_config_service_mojo_unittest.cc
+++ b/services/network/ssl_config_service_mojo_unittest.cc
@@ -276,7 +276,6 @@
   // Make sure the default TLS version range is as expected.
   EXPECT_EQ(net::kDefaultSSLVersionMin, GetSSLConfig().version_min);
   EXPECT_EQ(net::kDefaultSSLVersionMax, GetSSLConfig().version_max);
-  EXPECT_EQ(net::kDefaultTLS13Variant, GetSSLConfig().tls13_variant);
 }
 
 // Check that passing in the default mojom::SSLConfig matches the default
@@ -292,7 +291,6 @@
   // Make sure the default TLS version range is as expected.
   EXPECT_EQ(net::kDefaultSSLVersionMin, GetSSLConfig().version_min);
   EXPECT_EQ(net::kDefaultSSLVersionMax, GetSSLConfig().version_max);
-  EXPECT_EQ(net::kDefaultTLS13Variant, GetSSLConfig().tls13_variant);
 }
 
 // Check that passing in the default mojom::SSLConfig matches the default
diff --git a/services/network/ssl_config_type_converter.cc b/services/network/ssl_config_type_converter.cc
index 81d7cc0..bcc4abed 100644
--- a/services/network/ssl_config_type_converter.cc
+++ b/services/network/ssl_config_type_converter.cc
@@ -4,22 +4,6 @@
 
 #include "services/network/ssl_config_type_converter.h"
 
-namespace {
-
-net::TLS13Variant MojoTLS13VariantToNetTLS13Variant(
-    network::mojom::TLS13Variant tls13_variant) {
-  switch (tls13_variant) {
-    case network::mojom::TLS13Variant::kDraft23:
-      return net::kTLS13VariantDraft23;
-    case network::mojom::TLS13Variant::kFinal:
-      return net::kTLS13VariantFinal;
-  }
-  NOTREACHED();
-  return net::kTLS13VariantDraft23;
-}
-
-}  // namespace
-
 namespace mojo {
 
 int MojoSSLVersionToNetSSLVersion(network::mojom::SSLVersion mojo_version) {
@@ -50,9 +34,6 @@
       MojoSSLVersionToNetSSLVersion(mojo_config->version_max);
   DCHECK_LE(net_config.version_min, net_config.version_max);
 
-  net_config.tls13_variant =
-      MojoTLS13VariantToNetTLS13Variant(mojo_config->tls13_variant);
-
   for (uint16_t cipher_suite : mojo_config->disabled_cipher_suites) {
     net_config.disabled_cipher_suites.push_back(cipher_suite);
   }
diff --git a/services/ws/event_queue.cc b/services/ws/event_queue.cc
index 3b88500..f379fa7a 100644
--- a/services/ws/event_queue.cc
+++ b/services/ws/event_queue.cc
@@ -55,16 +55,17 @@
 }
 
 // static
-void EventQueue::DispatchOrQueueEvent(WindowService* service,
-                                      aura::WindowTreeHost* window_tree_host,
-                                      ui::Event* event,
-                                      bool honor_rewriters) {
+base::Optional<ui::EventDispatchDetails> EventQueue::DispatchOrQueueEvent(
+    WindowService* service,
+    aura::WindowTreeHost* window_tree_host,
+    ui::Event* event,
+    bool honor_rewriters) {
   DCHECK(window_tree_host);
   HostEventQueue* host_event_queue =
       service->event_queue()->GetHostEventQueueForDisplay(
           window_tree_host->GetDisplayId());
   DCHECK(host_event_queue);
-  host_event_queue->DispatchOrQueueEvent(event, honor_rewriters);
+  return host_event_queue->DispatchOrQueueEvent(event, honor_rewriters);
 }
 
 bool EventQueue::ShouldQueueEvent(HostEventQueue* host_queue,
diff --git a/services/ws/event_queue.h b/services/ws/event_queue.h
index eac1fb0..0f2d4ff 100644
--- a/services/ws/event_queue.h
+++ b/services/ws/event_queue.h
@@ -26,6 +26,7 @@
 
 namespace ui {
 class Event;
+struct EventDispatchDetails;
 }
 
 namespace ws {
@@ -54,11 +55,13 @@
   // is true, the event is passed through EventRewriters first. Events received
   // from the platform go through EventRewriters, so generally
   // |honor_rewriters| should be true, remote injection may need to circumvent
-  // that though.
-  static void DispatchOrQueueEvent(WindowService* service,
-                                   aura::WindowTreeHost* window_tree_host,
-                                   ui::Event* event,
-                                   bool honor_rewriters);
+  // that though. If the event was not queued, the return value contains the
+  // result of the event processing.
+  static base::Optional<ui::EventDispatchDetails> DispatchOrQueueEvent(
+      WindowService* service,
+      aura::WindowTreeHost* window_tree_host,
+      ui::Event* event,
+      bool honor_rewriters);
 
   // Returns true if |event| should be queued at this time.
   bool ShouldQueueEvent(HostEventQueue* host, const ui::Event& event);
diff --git a/services/ws/host_event_dispatcher.h b/services/ws/host_event_dispatcher.h
index e12ec3e..f5e9622 100644
--- a/services/ws/host_event_dispatcher.h
+++ b/services/ws/host_event_dispatcher.h
@@ -10,6 +10,7 @@
 
 namespace ui {
 class Event;
+struct EventDispatchDetails;
 }
 
 namespace ws {
@@ -20,7 +21,7 @@
   // NOTE: as with other event dispatch related functions, the *caller* owns
   // |event|, but HostEventDispatcher may modify |event| as necessary (but not
   // delete it).
-  virtual void DispatchEventFromQueue(ui::Event* event) = 0;
+  virtual ui::EventDispatchDetails DispatchEventFromQueue(ui::Event* event) = 0;
 
  protected:
   virtual ~HostEventDispatcher() = default;
diff --git a/services/ws/host_event_queue.cc b/services/ws/host_event_queue.cc
index 1fe7459..fc7e5afa 100644
--- a/services/ws/host_event_queue.cc
+++ b/services/ws/host_event_queue.cc
@@ -25,22 +25,22 @@
     event_queue_->OnHostEventQueueDestroyed(this);
 }
 
-void HostEventQueue::DispatchOrQueueEvent(ui::Event* event,
-                                          bool honor_rewriters) {
-  if (event_queue_ && event_queue_->ShouldQueueEvent(this, *event))
+base::Optional<ui::EventDispatchDetails> HostEventQueue::DispatchOrQueueEvent(
+    ui::Event* event,
+    bool honor_rewriters) {
+  if (event_queue_ && event_queue_->ShouldQueueEvent(this, *event)) {
     event_queue_->QueueEvent(this, *event, honor_rewriters);
-  else
-    DispatchEventDontQueue(event, honor_rewriters);
+    return base::nullopt;
+  }
+  return DispatchEventDontQueue(event, honor_rewriters);
 }
 
-void HostEventQueue::DispatchEventDontQueue(ui::Event* event,
-                                            bool honor_rewriters) {
-  if (honor_rewriters) {
-    host_event_dispatcher_->DispatchEventFromQueue(event);
-  } else {
-    // No need to do anything with the result of sending the event.
-    ignore_result(window_tree_host_->event_sink()->OnEventFromSource(event));
-  }
+ui::EventDispatchDetails HostEventQueue::DispatchEventDontQueue(
+    ui::Event* event,
+    bool honor_rewriters) {
+  if (honor_rewriters)
+    return host_event_dispatcher_->DispatchEventFromQueue(event);
+  return window_tree_host_->event_sink()->OnEventFromSource(event);
 }
 
 }  // namespace ws
diff --git a/services/ws/host_event_queue.h b/services/ws/host_event_queue.h
index 1015e81..98d367e 100644
--- a/services/ws/host_event_queue.h
+++ b/services/ws/host_event_queue.h
@@ -8,6 +8,7 @@
 #include "base/component_export.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/optional.h"
 
 namespace aura {
 class WindowTreeHost;
@@ -15,6 +16,7 @@
 
 namespace ui {
 class Event;
+struct EventDispatchDetails;
 }
 
 namespace ws {
@@ -37,8 +39,12 @@
   ~HostEventQueue();
 
   // If necessary, queues the event. If the event need not be queued,
-  // HostEventDispatcher::DispatchEventFromQueue() is called synchronously.
-  void DispatchOrQueueEvent(ui::Event* event, bool honor_rewriters = true);
+  // HostEventDispatcher::DispatchEventFromQueue() is called synchronously. If
+  // the event was not queued, the return value contains the result of the
+  // event processing.
+  base::Optional<ui::EventDispatchDetails> DispatchOrQueueEvent(
+      ui::Event* event,
+      bool honor_rewriters = true);
 
   aura::WindowTreeHost* window_tree_host() { return window_tree_host_; }
 
@@ -51,7 +57,8 @@
 
   // Dispatches an event directly, circumventing any queuing. This is private as
   // it's only useful internally.
-  void DispatchEventDontQueue(ui::Event* event, bool honor_rewriters);
+  ui::EventDispatchDetails DispatchEventDontQueue(ui::Event* event,
+                                                  bool honor_rewriters);
 
   // Because of shutdown ordering, HostEventQueue may be deleted *after*
   // EventQueue.
diff --git a/services/ws/injected_event_handler.cc b/services/ws/injected_event_handler.cc
index fd3d6996..caa047a 100644
--- a/services/ws/injected_event_handler.cc
+++ b/services/ws/injected_event_handler.cc
@@ -57,13 +57,19 @@
   auto this_ref = weak_factory_.GetWeakPtr();
   pre_target_register_ = std::make_unique<ScopedPreTargetRegister>(
       window_service_->delegate()->GetGlobalEventTarget(), this);
-  EventQueue::DispatchOrQueueEvent(window_service_, window_tree_host_,
-                                   event.get(), /* honors_rewriters */ true);
+  auto result = EventQueue::DispatchOrQueueEvent(window_service_,
+                                                 window_tree_host_, event.get(),
+                                                 /* honors_rewriters */ true);
   if (!this_ref)
     return;
   // |pre_target_register_| needs to be a member to ensure it's destroyed
   // if |this| is destroyed.
   pre_target_register_.reset();
+
+  if (result && result->event_discarded) {
+    DCHECK(!event_id_);
+    NotifyCallback();
+  }
 }
 
 void InjectedEventHandler::NotifyCallback() {
diff --git a/services/ws/injected_event_handler.h b/services/ws/injected_event_handler.h
index d7e3d317..02f3b98 100644
--- a/services/ws/injected_event_handler.h
+++ b/services/ws/injected_event_handler.h
@@ -34,12 +34,13 @@
 //
 // Implementation note: an event may be handled in any of the following
 // ways:
-// . It may be dispatched to remote client. This is detected by way of
+// . It may be dispatched to a remote client. This is detected by way of
 //   OnWillSendEventToClient().
 // . It may be handled locally.
 // . It may be held and processed later on. This happens if pointer events are
 //   being held if WindowEventDispatcher. See
 //   WindowEventDispatcher::HoldPointerMoves() for details.
+// . It may be discarded by an EventRewriter.
 // For the case of the event being sent to a remote client this has to ensure
 // if the remote client, or WindowTreeHost is destroyed, then no ack is
 // received.
diff --git a/services/ws/injected_event_handler_unittest.cc b/services/ws/injected_event_handler_unittest.cc
index e4ceb34..fd47e41 100644
--- a/services/ws/injected_event_handler_unittest.cc
+++ b/services/ws/injected_event_handler_unittest.cc
@@ -21,6 +21,9 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/aura/test/window_event_dispatcher_test_api.h"
 #include "ui/aura/window.h"
+#include "ui/events/event.h"
+#include "ui/events/event_rewriter.h"
+#include "ui/events/keycodes/dom/dom_code.h"
 #include "ui/platform_window/platform_window_init_properties.h"
 
 namespace ws {
@@ -150,4 +153,59 @@
   EXPECT_TRUE(was_callback_run);
 }
 
+class DiscardingEventRewriter : public ui::EventRewriter {
+ public:
+  DiscardingEventRewriter() = default;
+  ~DiscardingEventRewriter() override = default;
+
+  bool got_rewrite_event() const { return got_rewrite_event_; }
+
+  // ui::EventRewriter:
+  ui::EventRewriteStatus RewriteEvent(
+      const ui::Event& event,
+      std::unique_ptr<ui::Event>* new_event) override {
+    got_rewrite_event_ = true;
+    return ui::EVENT_REWRITE_DISCARD;
+  }
+  ui::EventRewriteStatus NextDispatchEvent(
+      const ui::Event& last_event,
+      std::unique_ptr<ui::Event>* new_event) override {
+    return ui::EVENT_REWRITE_DISPATCH_ANOTHER;
+  }
+
+ private:
+  bool got_rewrite_event_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(DiscardingEventRewriter);
+};
+
+TEST(InjectedEventHandlerTest, RewriterDiscards) {
+  // Create a single window and give it focus.
+  DiscardingEventRewriter rewriter;
+  WindowServiceTestSetup test_setup;
+  test_setup.aura_test_helper()->root_window()->GetHost()->AddEventRewriter(
+      &rewriter);
+  aura::Window* top_level =
+      test_setup.window_tree_test_helper()->NewTopLevelWindow();
+  ASSERT_TRUE(top_level);
+  top_level->SetBounds(gfx::Rect(0, 0, 100, 100));
+  top_level->Show();
+  top_level->Focus();
+  EXPECT_TRUE(top_level->HasFocus());
+
+  // Dispatch an event. Because the rewriter discards the event, the callback
+  // should be run immediately.
+  bool was_callback_run = false;
+  InjectedEventHandler injected_event_handler(test_setup.service(),
+                                              test_setup.root()->GetHost());
+
+  ui::KeyEvent char_event('A', ui::VKEY_A, ui::DomCode::NONE, 0);
+  injected_event_handler.Inject(
+      ui::Event::Clone(char_event),
+      base::BindOnce([](bool* was_run) { *was_run = true; },
+                     &was_callback_run));
+  EXPECT_TRUE(was_callback_run);
+  EXPECT_TRUE(rewriter.got_rewrite_event());
+}
+
 }  // namespace ws
diff --git a/services/ws/test_host_event_dispatcher.cc b/services/ws/test_host_event_dispatcher.cc
index 4c2dea5..828896e 100644
--- a/services/ws/test_host_event_dispatcher.cc
+++ b/services/ws/test_host_event_dispatcher.cc
@@ -18,9 +18,9 @@
 
 TestHostEventDispatcher::~TestHostEventDispatcher() = default;
 
-void TestHostEventDispatcher::DispatchEventFromQueue(ui::Event* event) {
-  ignore_result(
-      ui::EventSourceTestApi(window_tree_host_).SendEventToSink(event));
+ui::EventDispatchDetails TestHostEventDispatcher::DispatchEventFromQueue(
+    ui::Event* event) {
+  return ui::EventSourceTestApi(window_tree_host_).SendEventToSink(event);
 }
 
 }  // namespace ws
diff --git a/services/ws/test_host_event_dispatcher.h b/services/ws/test_host_event_dispatcher.h
index 3a9a642..688defa 100644
--- a/services/ws/test_host_event_dispatcher.h
+++ b/services/ws/test_host_event_dispatcher.h
@@ -21,7 +21,7 @@
   ~TestHostEventDispatcher() override;
 
   // HostEventDispatcher:
-  void DispatchEventFromQueue(ui::Event* event) override;
+  ui::EventDispatchDetails DispatchEventFromQueue(ui::Event* event) override;
 
  private:
   aura::WindowTreeHost* window_tree_host_;
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index 6db6d7b..767b496 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -485,13 +485,13 @@
   if (is_fuchsia) {
     sources += [
       "//third_party/skia/src/ports/SkFontMgr_custom.cpp",
+      "//third_party/skia/src/ports/SkFontMgr_fuchsia.cpp",
       "ext/fontmgr_default_fuchsia.cc",
       "ext/fontmgr_default_fuchsia.h",
-      "ext/fontmgr_fuchsia.cc",
-      "ext/fontmgr_fuchsia.h",
     ]
     deps += [
       "//third_party/fuchsia-sdk/sdk:fonts",
+      "//third_party/fuchsia-sdk/sdk:zx",
       "//third_party/icu:icuuc",
     ]
   }
diff --git a/skia/ext/fontmgr_default_fuchsia.cc b/skia/ext/fontmgr_default_fuchsia.cc
index 379a00c..42702d6 100644
--- a/skia/ext/fontmgr_default_fuchsia.cc
+++ b/skia/ext/fontmgr_default_fuchsia.cc
@@ -7,7 +7,8 @@
 #include <fuchsia/fonts/cpp/fidl.h>
 
 #include "base/fuchsia/component_context.h"
-#include "skia/ext/fontmgr_fuchsia.h"
+#include "third_party/skia/include/core/SkFontMgr.h"
+#include "third_party/skia/include/ports/SkFontMgr_fuchsia.h"
 
 namespace {
 // This is a purposefully leaky pointer that has ownership of the FontMgr.
@@ -23,7 +24,7 @@
   if (g_default_fontmgr) {
     return sk_ref_sp(g_default_fontmgr);
   }
-  return sk_make_sp<skia::FuchsiaFontManager>(
+  return SkFontMgr_New_Fuchsia(
       base::fuchsia::ComponentContext::GetDefault()
           ->ConnectToServiceSync<fuchsia::fonts::Provider>());
 }
diff --git a/skia/ext/fontmgr_fuchsia.cc b/skia/ext/fontmgr_fuchsia.cc
deleted file mode 100644
index 3c9a60fe..0000000
--- a/skia/ext/fontmgr_fuchsia.cc
+++ /dev/null
@@ -1,339 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "skia/ext/fontmgr_fuchsia.h"
-
-#include <lib/zx/vmar.h>
-
-#include <unordered_map>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/containers/small_map.h"
-#include "base/fuchsia/fuchsia_logging.h"
-#include "base/logging.h"
-#include "base/strings/string_util.h"
-#include "base/threading/thread_checker.h"
-#include "third_party/icu/source/common/unicode/uchar.h"
-#include "third_party/skia/src/core/SkFontDescriptor.h"
-#include "third_party/skia/src/core/SkMakeUnique.h"
-#include "third_party/skia/src/ports/SkFontHost_FreeType_common.h"
-#include "third_party/skia/src/ports/SkFontMgr_custom.h"
-
-namespace skia {
-
-namespace {
-
-constexpr char kDefaultFont[] = "Roboto";
-
-// Currently fonts::Provider doesn't support font aliases. The map below is
-// used to map common web fonts to font families that are expected to be present
-// in fonts::Provider.
-constexpr struct {
-  const char* font_name_in;
-  const char* font_name_out;
-} kFontMap[] = {{"sans", "Roboto"},
-                {"sans-serif", "Roboto"},
-                {"arial", "Roboto"},
-                {"helvetica", "Roboto"},
-                {"roboto", "Roboto"},
-                {"roboto slab", "RobotoSlab"},
-                {"serif", "RobotoSlab"},
-                {"georgia", "RobotoSlab"},
-                {"times", "RobotoSlab"},
-                {"times roman", "RobotoSlab"},
-                {"times new roman", "RobotoSlab"},
-                {"roboto mono", "RobotoMono"},
-                {"consolas", "RobotoMono"},
-                {"courier", "RobotoMono"},
-                {"courier new", "RobotoMono"},
-                {"monospace", "RobotoMono"}};
-
-fuchsia::fonts::Slant ToFontSlant(SkFontStyle::Slant slant) {
-  return (slant == SkFontStyle::kItalic_Slant) ? fuchsia::fonts::Slant::ITALIC
-                                               : fuchsia::fonts::Slant::UPRIGHT;
-}
-
-void UnmapMemory(const void* buffer, void* context) {
-  const uintptr_t size = reinterpret_cast<uintptr_t>(context);
-  zx::vmar::root_self()->unmap(reinterpret_cast<uintptr_t>(buffer), size);
-}
-
-sk_sp<SkData> BufferToSkData(fuchsia::mem::Buffer data) {
-  uintptr_t buffer = 0;
-  zx_status_t status = zx::vmar::root_self()->map(
-      0, data.vmo, 0, data.size, ZX_VM_FLAG_PERM_READ, &buffer);
-  if (status != ZX_OK) {
-    ZX_DLOG(ERROR, status) << "zx_vmar_map";
-    return nullptr;
-  }
-
-  return SkData::MakeWithProc(reinterpret_cast<void*>(buffer), data.size,
-                              UnmapMemory, reinterpret_cast<void*>(data.size));
-}
-
-// SkTypeface that notifies FontCache when it is being destroyed.
-class CachedTypeface : public SkTypeface_Stream {
- public:
-  CachedTypeface(std::unique_ptr<SkFontData> font_data,
-                 const SkFontStyle& style,
-                 bool is_fixed_pitch,
-                 const SkString family_name,
-                 base::OnceClosure on_deleted)
-      : SkTypeface_Stream(std::move(font_data),
-                          style,
-                          is_fixed_pitch,
-                          /*sys_font=*/true,
-                          family_name),
-        on_deleted_(std::move(on_deleted)) {}
-
-  ~CachedTypeface() override {
-    if (on_deleted_)
-      std::move(on_deleted_).Run();
-  }
-
- private:
-  base::OnceClosure on_deleted_;
-
-  DISALLOW_COPY_AND_ASSIGN(CachedTypeface);
-};
-
-sk_sp<SkTypeface> CreateTypefaceFromSkStream(
-    std::unique_ptr<SkStreamAsset> stream,
-    const SkFontArguments& args,
-    base::OnceClosure on_deleted) {
-  using Scanner = SkTypeface_FreeType::Scanner;
-  Scanner scanner;
-  bool is_fixed_pitch;
-  SkFontStyle style;
-  SkString name;
-  Scanner::AxisDefinitions axis_definitions;
-  if (!scanner.scanFont(stream.get(), args.getCollectionIndex(), &name, &style,
-                        &is_fixed_pitch, &axis_definitions)) {
-    return nullptr;
-  }
-
-  const SkFontArguments::VariationPosition position =
-      args.getVariationDesignPosition();
-  SkAutoSTMalloc<4, SkFixed> axis_values(axis_definitions.count());
-  Scanner::computeAxisValues(axis_definitions, position, axis_values, name);
-
-  auto font_data =
-      std::make_unique<SkFontData>(std::move(stream), args.getCollectionIndex(),
-                                   axis_values.get(), axis_definitions.count());
-  return sk_make_sp<CachedTypeface>(std::move(font_data), style, is_fixed_pitch,
-                                    name, std::move(on_deleted));
-}
-
-sk_sp<SkTypeface> CreateTypefaceFromBuffer(fuchsia::mem::Buffer buffer,
-                                           base::OnceClosure on_deleted) {
-  sk_sp<SkData> data = BufferToSkData(std::move(buffer));
-  if (!data)
-    return nullptr;
-
-  // TODO(https://crbug.com/800156): Initialize font arguments with font index
-  // when font collection support is implemented in Provider.
-  SkFontArguments args;
-
-  return CreateTypefaceFromSkStream(
-      std::make_unique<SkMemoryStream>(std::move(data)), args,
-      std::move(on_deleted));
-}
-
-}  // namespace
-
-class FuchsiaFontManager::FontCache {
- public:
-  FontCache();
-  ~FontCache();
-
-  sk_sp<SkTypeface> GetTypefaceFromBuffer(fuchsia::mem::Buffer buffer);
-
- private:
-  void OnTypefaceDeleted(zx_koid_t vmo_koid);
-
-  THREAD_CHECKER(thread_checker_);
-
-  // SkTypeface cache. They key is koid of the VMO that contains the typeface.
-  // This allows to reuse previously-created SkTypeface when fonts::Provider
-  // returns FontData with the same VMO.
-  base::small_map<std::unordered_map<zx_koid_t, SkTypeface*>> typefaces_;
-
-  base::WeakPtrFactory<FontCache> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(FontCache);
-};
-
-FuchsiaFontManager::FontCache::FontCache() : weak_factory_(this) {}
-
-FuchsiaFontManager::FontCache::~FontCache() = default;
-
-sk_sp<SkTypeface> FuchsiaFontManager::FontCache::GetTypefaceFromBuffer(
-    fuchsia::mem::Buffer buffer) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
-  zx_info_handle_basic_t vmo_info;
-  zx_status_t status = buffer.vmo.get_info(ZX_INFO_HANDLE_BASIC, &vmo_info,
-                                           sizeof(vmo_info), nullptr, nullptr);
-  if (status != ZX_OK) {
-    ZX_DLOG(ERROR, status) << "zx_object_get_info";
-    return nullptr;
-  }
-
-  sk_sp<SkTypeface> result;
-  SkTypeface** cached_typeface = &(typefaces_[vmo_info.koid]);
-  if (*cached_typeface) {
-    result = sk_ref_sp(*cached_typeface);
-  } else {
-    result = CreateTypefaceFromBuffer(
-        std::move(buffer),
-        base::BindOnce(&FontCache::OnTypefaceDeleted,
-                       weak_factory_.GetWeakPtr(), vmo_info.koid));
-    *cached_typeface = result.get();
-  }
-  return result;
-}
-
-void FuchsiaFontManager::FontCache::OnTypefaceDeleted(zx_koid_t vmo_koid) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
-  bool was_found = typefaces_.erase(vmo_koid) != 0;
-  DCHECK(was_found);
-}
-
-FuchsiaFontManager::FuchsiaFontManager(
-    fuchsia::fonts::ProviderSyncPtr font_provider)
-    : font_provider_(std::move(font_provider)), font_cache_(new FontCache()) {
-  for (auto& m : kFontMap) {
-    font_map_[m.font_name_in] = m.font_name_out;
-  }
-
-  // Get default font.
-  default_typeface_.reset(onMatchFamilyStyle(kDefaultFont, SkFontStyle()));
-  if (!default_typeface_) {
-    default_typeface_ = sk_make_sp<SkTypeface_Empty>();
-    LOG(ERROR) << "Failed to get default font from fonts::Provider.";
-  }
-}
-
-FuchsiaFontManager::~FuchsiaFontManager() = default;
-
-int FuchsiaFontManager::onCountFamilies() const {
-  NOTREACHED();
-  return 0;
-}
-
-void FuchsiaFontManager::onGetFamilyName(int index,
-                                         SkString* family_name) const {
-  NOTREACHED();
-}
-
-SkFontStyleSet* FuchsiaFontManager::onCreateStyleSet(int index) const {
-  NOTREACHED();
-  return nullptr;
-}
-
-SkFontStyleSet* FuchsiaFontManager::onMatchFamily(
-    const char family_name[]) const {
-  NOTREACHED();
-  return nullptr;
-}
-
-SkTypeface* FuchsiaFontManager::onMatchFamilyStyle(
-    const char family_name[],
-    const SkFontStyle& style) const {
-  std::string family_name_lowercase = base::ToLowerASCII(family_name);
-
-  fuchsia::fonts::Request request;
-  auto it = font_map_.find(family_name_lowercase);
-  request.family = (it != font_map_.end()) ? it->second.c_str() : family_name;
-  request.weight = style.weight();
-  request.width = style.width();
-  request.slant = ToFontSlant(style.slant());
-  request.language = fidl::VectorPtr<fidl::StringPtr>::New(0);
-
-  fuchsia::fonts::ResponsePtr response;
-  zx_status_t status = font_provider_->GetFont(std::move(request), &response);
-  if (status != ZX_OK) {
-    ZX_DLOG(ERROR, status) << "Failed to query font provider.";
-  } else if (response) {
-    sk_sp<SkTypeface> result =
-        font_cache_->GetTypefaceFromBuffer(std::move(response->buffer));
-    if (result)
-      return result.release();
-
-    LOG(ERROR) << "fonts::Provider returned invalid FontData for "
-               << family_name;
-  }
-
-  // If Sans was requested and we failed to get a valid response from
-  // fonts::Provider then return |default_typeface_|. blink::FontCache queries
-  // Sans as a last-resort font. Returning |default_typeface_| here ensures that
-  // the renderer doesn't crash when fonts::Provider stops working.
-  if (family_name_lowercase == "sans") {
-    // Copy |default_typeface_| to increment ref-count before returning it.
-    sk_sp<SkTypeface> result = default_typeface_;
-    return result.release();
-  }
-
-  return nullptr;
-}
-
-SkTypeface* FuchsiaFontManager::onMatchFamilyStyleCharacter(
-    const char family_name[],
-    const SkFontStyle& style,
-    const char* bcp47[],
-    int bcp47Count,
-    SkUnichar character) const {
-  if (u_hasBinaryProperty(character, UCHAR_EMOJI))
-    return onMatchFamilyStyle("Noto Color Emoji", style);
-
-  return nullptr;
-}
-
-SkTypeface* FuchsiaFontManager::onMatchFaceStyle(
-    const SkTypeface* typeface,
-    const SkFontStyle& style) const {
-  NOTREACHED();
-  return nullptr;
-}
-
-sk_sp<SkTypeface> FuchsiaFontManager::onMakeFromData(sk_sp<SkData> data,
-                                                     int ttc_index) const {
-  return makeFromStream(std::make_unique<SkMemoryStream>(std::move(data)),
-                        ttc_index);
-}
-
-sk_sp<SkTypeface> FuchsiaFontManager::onMakeFromStreamIndex(
-    std::unique_ptr<SkStreamAsset> stream,
-    int ttc_index) const {
-  return makeFromStream(std::move(stream),
-                        SkFontArguments().setCollectionIndex(ttc_index));
-}
-
-sk_sp<SkTypeface> FuchsiaFontManager::onMakeFromStreamArgs(
-    std::unique_ptr<SkStreamAsset> stream,
-    const SkFontArguments& args) const {
-  return CreateTypefaceFromSkStream(std::move(stream), args,
-                                    /*on_deleted=*/base::OnceClosure());
-}
-
-sk_sp<SkTypeface> FuchsiaFontManager::onMakeFromFile(const char path[],
-                                                     int ttc_index) const {
-  NOTREACHED();
-  return nullptr;
-}
-
-sk_sp<SkTypeface> FuchsiaFontManager::onLegacyMakeTypeface(
-    const char family_name[],
-    SkFontStyle style) const {
-  sk_sp<SkTypeface> typeface;
-
-  if (family_name)
-    typeface.reset(this->onMatchFamilyStyle(family_name, style));
-
-  return typeface;
-}
-
-}  // namespace skia
diff --git a/skia/ext/fontmgr_fuchsia.h b/skia/ext/fontmgr_fuchsia.h
deleted file mode 100644
index cb12997..0000000
--- a/skia/ext/fontmgr_fuchsia.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SKIA_EXT_FONTMGR_FUCHSIA_H_
-#define SKIA_EXT_FONTMGR_FUCHSIA_H_
-
-#include <memory>
-
-#include <fuchsia/fonts/cpp/fidl.h>
-
-#include "base/containers/flat_map.h"
-#include "base/macros.h"
-#include "third_party/skia/include/core/SkFontMgr.h"
-#include "third_party/skia/include/core/SkStream.h"
-#include "third_party/skia/include/core/SkTypeface.h"
-
-namespace skia {
-
-class SK_API FuchsiaFontManager : public SkFontMgr {
- public:
-  explicit FuchsiaFontManager(fuchsia::fonts::ProviderSyncPtr font_provider);
-
-  ~FuchsiaFontManager() override;
-
- protected:
-  // SkFontMgr overrides.
-  int onCountFamilies() const override;
-  void onGetFamilyName(int index, SkString* family_name) const override;
-  SkFontStyleSet* onMatchFamily(const char family_name[]) const override;
-  SkFontStyleSet* onCreateStyleSet(int index) const override;
-  SkTypeface* onMatchFamilyStyle(const char family_name[],
-                                 const SkFontStyle&) const override;
-  SkTypeface* onMatchFamilyStyleCharacter(const char family_name[],
-                                          const SkFontStyle&,
-                                          const char* bcp47[],
-                                          int bcp47_count,
-                                          SkUnichar character) const override;
-  SkTypeface* onMatchFaceStyle(const SkTypeface*,
-                               const SkFontStyle&) const override;
-  sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData>, int ttc_index) const override;
-  sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>,
-                                          int ttc_index) const override;
-  sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset>,
-                                         const SkFontArguments&) const override;
-  sk_sp<SkTypeface> onMakeFromFile(const char path[],
-                                   int ttc_index) const override;
-  sk_sp<SkTypeface> onLegacyMakeTypeface(const char family_name[],
-                                         SkFontStyle) const override;
-
- private:
-  class FontCache;
-
-  fuchsia::fonts::ProviderSyncPtr font_provider_;
-
-  // Map applied to font family name before sending requests to the FontService.
-  base::flat_map<std::string, std::string> font_map_;
-
-  // FontCache keeps all SkTypeface instances returned by the manager. It allows
-  // to ensure that SkTypeface object is created only once for each typeface.
-  std::unique_ptr<FontCache> font_cache_;
-
-  sk_sp<SkTypeface> default_typeface_;
-
-  DISALLOW_COPY_AND_ASSIGN(FuchsiaFontManager);
-};
-
-}  // namespace skia
-
-#endif  // SKIA_EXT_FONTMGR_FUCHSIA_H_
diff --git a/skia/ext/fontmgr_fuchsia_unittest.cc b/skia/ext/fontmgr_fuchsia_unittest.cc
index 8053a03..a5381b8 100644
--- a/skia/ext/fontmgr_fuchsia_unittest.cc
+++ b/skia/ext/fontmgr_fuchsia_unittest.cc
@@ -2,126 +2,28 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "skia/ext/fontmgr_fuchsia.h"
-
 #include <fuchsia/fonts/cpp/fidl.h>
 #include <lib/fidl/cpp/binding.h>
 
-#include "base/base_paths.h"
-#include "base/bind.h"
-#include "base/files/file_util.h"
-#include "base/fuchsia/fuchsia_logging.h"
-#include "base/location.h"
-#include "base/message_loop/message_loop.h"
+#include "base/fuchsia/component_context.h"
 #include "base/path_service.h"
-#include "base/task_runner.h"
-#include "base/threading/thread.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkFontMgr.h"
+#include "third_party/skia/include/core/SkTypeface.h"
+#include "third_party/skia/include/ports/SkFontMgr_fuchsia.h"
 
 namespace skia {
 
-namespace {
-
-constexpr zx_rights_t kFontDataRights =
-    ZX_RIGHTS_BASIC | ZX_RIGHT_READ | ZX_RIGHT_MAP;
-
-fuchsia::mem::Buffer LoadFont(const base::FilePath& file_path) {
-  std::string file_content;
-  CHECK(ReadFileToString(file_path, &file_content));
-  fuchsia::mem::Buffer buffer;
-  zx_status_t status = zx::vmo::create(file_content.size(), 0, &buffer.vmo);
-  ZX_CHECK(status == ZX_OK, status);
-  status = buffer.vmo.write(file_content.data(), 0, file_content.size());
-  ZX_CHECK(status == ZX_OK, status);
-  buffer.size = file_content.size();
-  return buffer;
-}
-
-class MockFontProvider : public fuchsia::fonts::Provider {
- public:
-  MockFontProvider() {
-    base::FilePath assets_dir;
-    EXPECT_TRUE(base::PathService::Get(base::DIR_ASSETS, &assets_dir));
-
-    // Roboto is not in test_fonts. Just load some arbitrary fonts for the
-    // tests.
-    roboto_ = LoadFont(assets_dir.Append("test_fonts/Arimo-Regular.ttf"));
-    roboto_slab_ = LoadFont(assets_dir.Append("test_fonts/Tinos-Regular.ttf"));
-  }
-
-  // fuchsia::fonts::Provider implementation.
-  void GetFont(fuchsia::fonts::Request request,
-               GetFontCallback callback) override {
-    fuchsia::mem::Buffer* font_buffer = nullptr;
-    if (*request.family == "Roboto") {
-      font_buffer = &roboto_;
-    } else if (*request.family == "RobotoSlab") {
-      font_buffer = &roboto_slab_;
-    }
-
-    if (!font_buffer) {
-      callback(nullptr);
-      return;
-    }
-
-    auto response = fuchsia::fonts::Response::New();
-    EXPECT_EQ(
-        font_buffer->vmo.duplicate(kFontDataRights, &(response->buffer.vmo)),
-        ZX_OK);
-    response->buffer.size = font_buffer->size;
-    callback(std::move(response));
-  }
-  void GetFamilyInfo(fidl::StringPtr family,
-                     GetFamilyInfoCallback callback) override {}
-
- private:
-  fuchsia::mem::Buffer roboto_;
-  fuchsia::mem::Buffer roboto_slab_;
-};
-
-class MockFontProviderService {
- public:
-  MockFontProviderService() : provider_thread_("MockFontProvider") {
-    provider_thread_.StartWithOptions(
-        base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
-  }
-
-  ~MockFontProviderService() {
-    provider_thread_.task_runner()->DeleteSoon(FROM_HERE,
-                                               std::move(provider_binding_));
-  }
-
-  void Bind(fidl::InterfaceRequest<fuchsia::fonts::Provider> request) {
-    provider_thread_.task_runner()->PostTask(
-        FROM_HERE, base::BindOnce(&MockFontProviderService::DoBind,
-                                  base::Unretained(this), std::move(request)));
-  }
-
- private:
-  void DoBind(fidl::InterfaceRequest<fuchsia::fonts::Provider> request) {
-    provider_binding_ =
-        std::make_unique<fidl::Binding<fuchsia::fonts::Provider>>(
-            &provider_, std::move(request));
-  }
-
-  base::Thread provider_thread_;
-
-  MockFontProvider provider_;
-  std::unique_ptr<fidl::Binding<fuchsia::fonts::Provider>> provider_binding_;
-};
-
-}  // namespace
-
+// Tests for SkFontMgr_Fuchsia in Skia.
 class FuchsiaFontManagerTest : public testing::Test {
  public:
   FuchsiaFontManagerTest() {
-    fuchsia::fonts::ProviderSyncPtr font_provider;
-    font_provider_service_.Bind(font_provider.NewRequest());
-    font_manager_ = sk_make_sp<FuchsiaFontManager>(std::move(font_provider));
+    font_manager_ = SkFontMgr_New_Fuchsia(
+        base::fuchsia::ComponentContext::GetDefault()
+            ->ConnectToServiceSync<fuchsia::fonts::Provider>());
   }
 
  protected:
-  MockFontProviderService font_provider_service_;
   sk_sp<SkFontMgr> font_manager_;
 };
 
@@ -129,6 +31,8 @@
 TEST_F(FuchsiaFontManagerTest, Caching) {
   sk_sp<SkTypeface> sans(
       font_manager_->matchFamilyStyle("sans", SkFontStyle()));
+  EXPECT_TRUE(sans);
+
   sk_sp<SkTypeface> sans2(
       font_manager_->matchFamilyStyle("sans", SkFontStyle()));
 
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json
index 900792d6..a765a08 100644
--- a/testing/buildbot/chromium.perf.fyi.json
+++ b/testing/buildbot/chromium.perf.fyi.json
@@ -113,7 +113,7 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 36000,
+          "hard_timeout": 14400,
           "ignore_task_failure": false,
           "io_timeout": 1800,
           "shards": 25,
@@ -204,7 +204,7 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 36000,
+          "hard_timeout": 18000,
           "ignore_task_failure": false,
           "io_timeout": 1800,
           "shards": 7,
@@ -250,7 +250,7 @@
             }
           ],
           "expiration": 7200,
-          "hard_timeout": 36000,
+          "hard_timeout": 14400,
           "ignore_task_failure": false,
           "io_timeout": 1800,
           "shards": 7,
diff --git a/testing/buildbot/filters/chromeos.single_process_mash.interactive_ui_tests.filter b/testing/buildbot/filters/chromeos.single_process_mash.interactive_ui_tests.filter
index 6c2a419..5a58ea9 100644
--- a/testing/buildbot/filters/chromeos.single_process_mash.interactive_ui_tests.filter
+++ b/testing/buildbot/filters/chromeos.single_process_mash.interactive_ui_tests.filter
@@ -21,11 +21,6 @@
 -SelectToSpeakTest.SmoothlyReadsAcrossMultipleLines
 -SelectToSpeakTest.SpeakStatusTray
 -SelectToSpeakTest.WorksWithStickyKeys
--StickyKeysBrowserTest.CtrlClickHomeButton
--StickyKeysBrowserTest.OpenNewTabs
--StickyKeysBrowserTest.OpenTrayMenu
--StickyKeysBrowserTest.OverlayShown
--StickyKeysBrowserTest.SearchLeftOmnibox
 -TestAsNormalAndGuestUser/SpokenFeedbackTest.ChromeVoxNextTabRecovery/0
 -TestAsNormalAndGuestUser/SpokenFeedbackTest.ChromeVoxNextTabRecovery/1
 -TestAsNormalAndGuestUser/SpokenFeedbackTest.ChromeVoxShiftSearch/0
@@ -37,6 +32,10 @@
 -TestAsNormalAndGuestUser/SpokenFeedbackTest.OverviewMode/0
 -TestAsNormalAndGuestUser/SpokenFeedbackTest.OverviewMode/1
 
+# crbug.com/913549
+-StickyKeysBrowserTest.OpenTrayMenu
+-StickyKeysBrowserTest.SearchLeftOmnibox
+
 # This test is flaky. https://crbug.com/897879
 -ExtensionApiTest.DisplayModeWindowIsInFullscreen
 
diff --git a/testing/buildbot/filters/fuchsia.net_unittests.filter b/testing/buildbot/filters/fuchsia.net_unittests.filter
index 293b51f7..2941e17 100644
--- a/testing/buildbot/filters/fuchsia.net_unittests.filter
+++ b/testing/buildbot/filters/fuchsia.net_unittests.filter
@@ -31,13 +31,6 @@
 -URLRequestTestHTTP.Redirect301Tests
 -URLRequestTestHTTP.Redirect302Tests
 
-# Flaky hangs, https://crbug.com/913155.
--NetworkErrorLoggingEndToEndTest.ReportNetworkError
--NetworkErrorLoggingEndToEndTest.UploadAtShutdown
-
-# Flaky test server spawning, https://crbug.com/913156.
--SSLClientSocketReadTest.*
-
 # SocketPosix::IsConnected has a different behavior on Fuchsia.
 # https://crbug.com/887587.
 -TCPSocketTest.BeforeConnectCallback
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index 5994a24..7cb68d8 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -546,7 +546,7 @@
     "type": "console_test_launcher",
   },
   "dawn_end2end_tests": {
-    "label": "//third_party/dawn:dawn_end2end_tests",
+    "label": "//third_party/dawn:dawn_end2end_tests_temp_group",
     "type": "raw",
     "args": [],
   },
@@ -1431,6 +1431,9 @@
       "--skip-expected-failures",
       "--additional-apk",
       "apks/SystemWebView.apk",
+      "--apk-under-test",
+      "apks/SystemWebView.apk",
+      "--use-apk-under-test-flags-file",
       "-v",
     ],
   },
diff --git a/testing/variations/PRESUBMIT.py b/testing/variations/PRESUBMIT.py
index c6ddb8bb..9bc9192 100644
--- a/testing/variations/PRESUBMIT.py
+++ b/testing/variations/PRESUBMIT.py
@@ -13,21 +13,11 @@
 
 from collections import OrderedDict
 
-VALID_EXPERIMENT_KEYS = ['name',
-                         'forcing_flag',
-                         'params',
-                         'enable_features',
-                         'disable_features',
-                         '//0',
-                         '//1',
-                         '//2',
-                         '//3',
-                         '//4',
-                         '//5',
-                         '//6',
-                         '//7',
-                         '//8',
-                         '//9']
+VALID_EXPERIMENT_KEYS = [
+    'name', 'forcing_flag', 'params', 'enable_features', 'disable_features',
+    '//0', '//1', '//2', '//3', '//4', '//5', '//6', '//7', '//8', '//9'
+]
+
 
 def PrettyPrint(contents):
   """Pretty prints a fieldtrial configuration.
@@ -70,9 +60,9 @@
     study = copy.deepcopy(config[key])
     ordered_study = []
     for experiment_config in study:
-      ordered_experiment_config = OrderedDict([
-          ('platforms', experiment_config['platforms']),
-          ('experiments', [])])
+      ordered_experiment_config = OrderedDict([('platforms',
+                                                experiment_config['platforms']),
+                                               ('experiments', [])])
       for experiment in experiment_config['experiments']:
         ordered_experiment = OrderedDict()
         for index in xrange(0, 10):
@@ -94,9 +84,9 @@
         ordered_experiment_config['experiments'].append(ordered_experiment)
       ordered_study.append(ordered_experiment_config)
     ordered_config[key] = ordered_study
-  return json.dumps(ordered_config,
-                    sort_keys=False, indent=4,
-                    separators=(',', ': ')) + '\n'
+  return json.dumps(
+      ordered_config, sort_keys=False, indent=4, separators=(',', ': ')) + '\n'
+
 
 def ValidateData(json_data, file_path, message_type):
   """Validates the format of a fieldtrial configuration.
@@ -105,79 +95,104 @@
     json_data: Parsed JSON object representing the fieldtrial config.
     file_path: String representing the path to the JSON file.
     message_type: Type of message from |output_api| to return in the case of
-        errors/warnings.
+      errors/warnings.
 
   Returns:
     A list of |message_type| messages. In the case of all tests passing with no
     warnings/errors, this will return [].
   """
-  if not isinstance(json_data, dict):
+
+  def _CreateMessage(message_format, *args):
     return _CreateMalformedConfigMessage(message_type, file_path,
-                                         'Expecting dict')
+                                         message_format, *args)
+
+  if not isinstance(json_data, dict):
+    return _CreateMessage('Expecting dict')
   for (study, experiment_configs) in json_data.iteritems():
-    if not isinstance(study, unicode):
-      return _CreateMalformedConfigMessage(message_type, file_path,
-          'Expecting keys to be string, got %s', type(study))
-    if not isinstance(experiment_configs, list):
-      return _CreateMalformedConfigMessage(message_type, file_path,
-          'Expecting list for study %s', study)
-    for experiment_config in experiment_configs:
-      if not isinstance(experiment_config, dict):
-        return _CreateMalformedConfigMessage(message_type, file_path,
-            'Expecting dict for experiment config in Study[%s]', study)
-      if not 'experiments' in experiment_config:
-        return _CreateMalformedConfigMessage(message_type, file_path,
-            'Missing valid experiments for experiment config in Study[%s]',
-            study)
-      if not isinstance(experiment_config['experiments'], list):
-        return _CreateMalformedConfigMessage(message_type, file_path,
-            'Expecting list for experiments in Study[%s]', study)
-      for experiment in experiment_config['experiments']:
-        if not 'name' in experiment or not isinstance(experiment['name'],
-                                                      unicode):
-          return _CreateMalformedConfigMessage(message_type, file_path,
-              'Missing valid name for experiment in Study[%s]', study)
-        if 'params' in experiment:
-          params = experiment['params']
-          if not isinstance(params, dict):
-            return _CreateMalformedConfigMessage(message_type, file_path,
-                'Expected dict for params for Experiment[%s] in Study[%s]',
-                experiment['name'], study)
-          for (key, value) in params.iteritems():
-            if not isinstance(key, unicode) or not isinstance(value, unicode):
-              return _CreateMalformedConfigMessage(message_type, file_path,
-                  'Invalid param (%s: %s) for Experiment[%s] in Study[%s]',
-                  key, value, experiment['name'], study)
-        for key in experiment.keys():
-          if key not in VALID_EXPERIMENT_KEYS:
-            return _CreateMalformedConfigMessage(message_type, file_path,
-                'Key[%s] in Experiment[%s] in Study[%s] is not a valid key.',
-                key, experiment['name'], study)
-      if not 'platforms' in experiment_config:
-        return _CreateMalformedConfigMessage(message_type, file_path,
-            'Missing valid platforms for experiment config in Study[%s]', study)
-      if not isinstance(experiment_config['platforms'], list):
-        return _CreateMalformedConfigMessage(message_type, file_path,
-            'Expecting list for platforms in Study[%s]', study)
-      supported_platforms = ['android', 'android_webview', 'chromeos', 'ios',
-                             'linux', 'mac', 'windows']
-      experiment_platforms = experiment_config['platforms']
-      unsupported_platforms = list(set(experiment_platforms).difference(
-                                       supported_platforms))
-      if unsupported_platforms:
-        return _CreateMalformedConfigMessage(message_type, file_path,
-                              'Unsupported platforms %s in Study[%s]',
-                              unsupported_platforms, study)
+    warnings = _ValidateEntry(study, experiment_configs, _CreateMessage)
+    if warnings:
+      return warnings
 
   return []
 
+
+def _ValidateEntry(study, experiment_configs, create_message_fn):
+  """Validates one entry of the field trial configuration."""
+  if not isinstance(study, unicode):
+    return create_message_fn('Expecting keys to be string, got %s', type(study))
+  if not isinstance(experiment_configs, list):
+    return create_message_fn('Expecting list for study %s', study)
+
+  # Add context to other messages.
+  def _CreateStudyMessage(message_format, *args):
+    suffix = ' in Study[%s]' % study
+    return create_message_fn(message_format + suffix, *args)
+
+  for experiment_config in experiment_configs:
+    warnings = _ValidateExperimentConfig(experiment_config, _CreateStudyMessage)
+    if warnings:
+      return warnings
+  return []
+
+
+def _ValidateExperimentConfig(experiment_config, create_message_fn):
+  """Validates one config in a configuration entry."""
+  if not isinstance(experiment_config, dict):
+    return create_message_fn('Expecting dict for experiment config')
+  if not 'experiments' in experiment_config:
+    return create_message_fn('Missing valid experiments for experiment config')
+  if not isinstance(experiment_config['experiments'], list):
+    return create_message_fn('Expecting list for experiments')
+  for experiment_group in experiment_config['experiments']:
+    warnings = _ValidateExperimentGroup(experiment_group, create_message_fn)
+    if warnings:
+      return warnings
+  if not 'platforms' in experiment_config:
+    return create_message_fn('Missing valid platforms for experiment config')
+  if not isinstance(experiment_config['platforms'], list):
+    return create_message_fn('Expecting list for platforms')
+  supported_platforms = [
+      'android', 'android_webview', 'chromeos', 'ios', 'linux', 'mac', 'windows'
+  ]
+  experiment_platforms = experiment_config['platforms']
+  unsupported_platforms = list(
+      set(experiment_platforms).difference(supported_platforms))
+  if unsupported_platforms:
+    return create_message_fn('Unsupported platforms %s', unsupported_platforms)
+  return []
+
+
+def _ValidateExperimentGroup(experiment_group, create_message_fn):
+  """Validates one group of one config in a configuration entry."""
+  name = experiment_group.get('name', '')
+  if not name or not isinstance(name, unicode):
+    return create_message_fn('Missing valid name for experiment')
+
+  # Add context to other messages.
+  def _CreateGroupMessage(message_format, *args):
+    suffix = ' in Group[%s]' % name
+    return create_message_fn(message_format + suffix, *args)
+
+  if 'params' in experiment_group:
+    params = experiment_group['params']
+    if not isinstance(params, dict):
+      return _CreateGroupMessage('Expected dict for params')
+    for (key, value) in params.iteritems():
+      if not isinstance(key, unicode) or not isinstance(value, unicode):
+        return _CreateGroupMessage('Invalid param (%s: %s)', key, value)
+  for key in experiment_group.keys():
+    if key not in VALID_EXPERIMENT_KEYS:
+      return _CreateGroupMessage('Key[%s] is not a valid key', key)
+  return []
+
+
 def _CreateMalformedConfigMessage(message_type, file_path, message_format,
                                   *args):
   """Returns a list containing one |message_type| with the error message.
 
   Args:
     message_type: Type of message from |output_api| to return in the case of
-        errors/warnings.
+      errors/warnings.
     message_format: The error message format string.
     file_path: The path to the config file.
     *args: The args for message_format.
@@ -190,6 +205,7 @@
   format_args = (file_path,) + args
   return [message_type(error_message_format % format_args)]
 
+
 def CheckPretty(contents, file_path, message_type):
   """Validates the pretty printing of fieldtrial configuration.
 
@@ -197,7 +213,7 @@
     contents: File contents as a string.
     file_path: String representing the path to the JSON file.
     message_type: Type of message from |output_api| to return in the case of
-        errors/warnings.
+      errors/warnings.
 
   Returns:
     A list of |message_type| messages. In the case of all tests passing with no
@@ -205,11 +221,13 @@
   """
   pretty = PrettyPrint(contents)
   if contents != pretty:
-    return [message_type(
-        'Pretty printing error: Run '
-        'python testing/variations/PRESUBMIT.py %s' % file_path)]
+    return [
+        message_type('Pretty printing error: Run '
+                     'python testing/variations/PRESUBMIT.py %s' % file_path)
+    ]
   return []
 
+
 def CommonChecks(input_api, output_api):
   affected_files = input_api.AffectedFiles(
       include_deletes=False,
@@ -225,13 +243,16 @@
       if len(result):
         return result
     except ValueError:
-      return [output_api.PresubmitError(
-          'Malformed JSON file: %s' % f.LocalPath())]
+      return [
+          output_api.PresubmitError('Malformed JSON file: %s' % f.LocalPath())
+      ]
   return []
 
+
 def CheckChangeOnUpload(input_api, output_api):
   return CommonChecks(input_api, output_api)
 
+
 def CheckChangeOnCommit(input_api, output_api):
   return CommonChecks(input_api, output_api)
 
@@ -241,5 +262,6 @@
   pretty = PrettyPrint(content)
   open(argv[1], 'wb').write(pretty)
 
-if __name__ == "__main__":
+
+if __name__ == '__main__':
   sys.exit(main(sys.argv))
diff --git a/third_party/arcore-android-sdk/README.chromium b/third_party/arcore-android-sdk/README.chromium
index b5036ba9..1d04387 100644
--- a/third_party/arcore-android-sdk/README.chromium
+++ b/third_party/arcore-android-sdk/README.chromium
@@ -29,6 +29,7 @@
  * https://github.com/google-ar/arcore-unity-sdk/blob/master/LICENSE
 
 Changes:
+2018-12-11 - Upgrade test-apks/arcore_current.apk to v1.6.
 2018-09-14 - Upgrade test-apks/arcore_current.apk to v1.4.
 2018-08-10 - First, removed arcore shim copy target from BUILD.gn since it is no
              longer needed. Second, added zero-byte dummy arcore library for AR
diff --git a/third_party/arcore-android-sdk/test-apks/arcore/apk_version_history.txt b/third_party/arcore-android-sdk/test-apks/arcore/apk_version_history.txt
index 3818323..8a7a8ac 100644
--- a/third_party/arcore-android-sdk/test-apks/arcore/apk_version_history.txt
+++ b/third_party/arcore-android-sdk/test-apks/arcore/apk_version_history.txt
@@ -1,2 +1,3 @@
 v1.3 f8004b83fc757d7724abdd492ac74cd7a9ab8e62
 v1.4 9c3ea648b0e3d1a5f837477f3efb02f87e305c0f
+v1.6 c79453295a1188afc8911d1760f297fef9187910
diff --git a/third_party/arcore-android-sdk/test-apks/arcore/arcore_current.apk.sha1 b/third_party/arcore-android-sdk/test-apks/arcore/arcore_current.apk.sha1
index 3988019..214aa7b 100644
--- a/third_party/arcore-android-sdk/test-apks/arcore/arcore_current.apk.sha1
+++ b/third_party/arcore-android-sdk/test-apks/arcore/arcore_current.apk.sha1
@@ -1 +1 @@
-9c3ea648b0e3d1a5f837477f3efb02f87e305c0f
\ No newline at end of file
+c79453295a1188afc8911d1760f297fef9187910
\ No newline at end of file
diff --git a/third_party/blink/public/platform/web_layer_tree_view.h b/third_party/blink/public/platform/web_layer_tree_view.h
index 3fae14b..0984c936 100644
--- a/third_party/blink/public/platform/web_layer_tree_view.h
+++ b/third_party/blink/public/platform/web_layer_tree_view.h
@@ -137,10 +137,6 @@
 
   // Flow control and scheduling ---------------------------------------
 
-  // Indicates that blink needs a BeginFrame, but that nothing might actually be
-  // dirty.
-  virtual void SetNeedsBeginFrame() {}
-
   // Run layout and paint of all pending document changes asynchronously.
   virtual void LayoutAndPaintAsync(base::OnceClosure callback) {}
 
diff --git a/third_party/blink/public/web/web_widget_client.h b/third_party/blink/public/web/web_widget_client.h
index 06522f0..b0abc6bc 100644
--- a/third_party/blink/public/web/web_widget_client.h
+++ b/third_party/blink/public/web/web_widget_client.h
@@ -67,7 +67,9 @@
   // Called when a region of the WebWidget needs to be re-painted.
   virtual void DidInvalidateRect(const WebRect&) {}
 
-  // Called when a call to WebWidget::animate is required
+  // Called to request a BeginMainFrame from the compositor. For tests with
+  // single thread and no scheduler, the impl should schedule a task to run
+  // a synchronous composite.
   virtual void ScheduleAnimation() {}
 
   // A notification callback for when the intrinsic sizing of the
diff --git a/third_party/blink/renderer/core/css/document_style_sheet_collection.cc b/third_party/blink/renderer/core/css/document_style_sheet_collection.cc
index f2564bb..81d15d5 100644
--- a/third_party/blink/renderer/core/css/document_style_sheet_collection.cc
+++ b/third_party/blink/renderer/core/css/document_style_sheet_collection.cc
@@ -91,20 +91,14 @@
   if (!GetTreeScope().HasAdoptedStyleSheets())
     return;
 
-  StyleSheetList& adopted_style_sheets = GetTreeScope().AdoptedStyleSheets();
-  unsigned length = adopted_style_sheets.length();
-  for (unsigned index = 0; index < length; ++index) {
-    StyleSheet* sheet = adopted_style_sheets.item(index);
-    if (!sheet)
-      continue;
-    CSSStyleSheet* css_sheet = ToCSSStyleSheet(sheet);
-    if (!css_sheet ||
-        !css_sheet->CanBeActivated(
+  for (CSSStyleSheet* sheet : GetTreeScope().AdoptedStyleSheets()) {
+    if (!sheet ||
+        !sheet->CanBeActivated(
             GetDocument().GetStyleEngine().PreferredStylesheetSetName()))
       continue;
     collector.AppendSheetForList(sheet);
     collector.AppendActiveStyleSheet(
-        std::make_pair(css_sheet, master_engine.RuleSetForSheet(*css_sheet)));
+        std::make_pair(sheet, master_engine.RuleSetForSheet(*sheet)));
   }
 }
 
diff --git a/third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.cc b/third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.cc
index 8a8867a..ffb4d59 100644
--- a/third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.cc
+++ b/third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.cc
@@ -65,17 +65,11 @@
   if (!GetTreeScope().HasAdoptedStyleSheets())
     return;
 
-  StyleSheetList& adopted_style_sheets = GetTreeScope().AdoptedStyleSheets();
-  unsigned length = adopted_style_sheets.length();
-  for (unsigned index = 0; index < length; ++index) {
-    StyleSheet* sheet = adopted_style_sheets.item(index);
-    if (!sheet)
-      continue;
-    CSSStyleSheet* css_sheet = ToCSSStyleSheet(sheet);
-    if (!css_sheet || !css_sheet->CanBeActivated(g_null_atom))
+  for (CSSStyleSheet* sheet : GetTreeScope().AdoptedStyleSheets()) {
+    if (!sheet || !sheet->CanBeActivated(g_null_atom))
       continue;
     collection.AppendActiveStyleSheet(
-        std::make_pair(css_sheet, master_engine.RuleSetForSheet(*css_sheet)));
+        std::make_pair(sheet, master_engine.RuleSetForSheet(*sheet)));
   }
 }
 
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc
index 177a16d..d08c036 100644
--- a/third_party/blink/renderer/core/css/style_engine.cc
+++ b/third_party/blink/renderer/core/css/style_engine.cc
@@ -288,19 +288,19 @@
     SetNeedsActiveStyleUpdate(node.GetTreeScope());
 }
 
-void StyleEngine::AdoptedStyleSheetsWillChange(TreeScope& tree_scope,
-                                               StyleSheetList* old_sheets,
-                                               StyleSheetList* new_sheets) {
+void StyleEngine::AdoptedStyleSheetsWillChange(
+    TreeScope& tree_scope,
+    const HeapVector<Member<CSSStyleSheet>>& old_sheets,
+    const HeapVector<Member<CSSStyleSheet>>& new_sheets) {
   if (GetDocument().IsDetached())
     return;
 
-  unsigned old_sheets_count = old_sheets ? old_sheets->length() : 0;
-  unsigned new_sheets_count = new_sheets ? new_sheets->length() : 0;
+  unsigned old_sheets_count = old_sheets.size();
+  unsigned new_sheets_count = new_sheets.size();
 
   unsigned min_count = std::min(old_sheets_count, new_sheets_count);
   unsigned index = 0;
-  while (index < min_count &&
-         old_sheets->item(index) == new_sheets->item(index)) {
+  while (index < min_count && old_sheets[index] == new_sheets[index]) {
     index++;
   }
 
@@ -308,11 +308,10 @@
     return;
 
   for (unsigned i = index; i < old_sheets_count; ++i) {
-    ToCSSStyleSheet(old_sheets->item(i))
-        ->RemovedAdoptedFromTreeScope(tree_scope);
+    old_sheets[i]->RemovedAdoptedFromTreeScope(tree_scope);
   }
   for (unsigned i = index; i < new_sheets_count; ++i) {
-    ToCSSStyleSheet(new_sheets->item(i))->AddedAdoptedToTreeScope(tree_scope);
+    new_sheets[i]->AddedAdoptedToTreeScope(tree_scope);
   }
 
   if (new_sheets_count) {
diff --git a/third_party/blink/renderer/core/css/style_engine.h b/third_party/blink/renderer/core/css/style_engine.h
index 354d1c7..d05f7cb 100644
--- a/third_party/blink/renderer/core/css/style_engine.h
+++ b/third_party/blink/renderer/core/css/style_engine.h
@@ -136,9 +136,10 @@
   void AddStyleSheetCandidateNode(Node&);
   void RemoveStyleSheetCandidateNode(Node&, ContainerNode& insertion_point);
   void ModifiedStyleSheetCandidateNode(Node&);
-  void AdoptedStyleSheetsWillChange(TreeScope&,
-                                    StyleSheetList* old_sheets,
-                                    StyleSheetList* new_sheets);
+  void AdoptedStyleSheetsWillChange(
+      TreeScope&,
+      const HeapVector<Member<CSSStyleSheet>>& old_sheets,
+      const HeapVector<Member<CSSStyleSheet>>& new_sheets);
   void AddedCustomElementDefaultStyles(
       const HeapVector<Member<CSSStyleSheet>>& default_styles);
   void MediaQueriesChangedInScope(TreeScope&);
diff --git a/third_party/blink/renderer/core/css/style_engine_test.cc b/third_party/blink/renderer/core/css/style_engine_test.cc
index 26cd17b..01ba56f 100644
--- a/third_party/blink/renderer/core/css/style_engine_test.cc
+++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -1189,30 +1189,32 @@
   EXPECT_FALSE(GetStyleEngine().NeedsActiveStyleUpdate());
 }
 
-class StyleEngineClient : public frame_test_helpers::TestWebViewClient {
+class StyleEngineClient : public frame_test_helpers::TestWebWidgetClient {
  public:
-  StyleEngineClient() : device_scale_factor_(1.f) {}
+  // WebWidgetClient overrides.
   void ConvertWindowToViewport(WebFloatRect* rect) override {
     rect->x *= device_scale_factor_;
     rect->y *= device_scale_factor_;
     rect->width *= device_scale_factor_;
     rect->height *= device_scale_factor_;
   }
+
   void set_device_scale_factor(float device_scale_factor) {
     device_scale_factor_ = device_scale_factor;
   }
 
  private:
-  float device_scale_factor_;
+  float device_scale_factor_ = 1.f;
 };
 
 TEST_F(StyleEngineTest, ViewportDescriptionForZoomDSF) {
   StyleEngineClient client;
+  frame_test_helpers::TestWebViewClient view_client(&client);
   client.set_device_scale_factor(1.f);
 
   frame_test_helpers::WebViewHelper web_view_helper;
   WebViewImpl* web_view_impl =
-      web_view_helper.Initialize(nullptr, &client, nullptr, nullptr);
+      web_view_helper.Initialize(nullptr, &view_client);
   web_view_impl->MainFrameWidget()->UpdateAllLifecyclePhases(
       WebWidget::LifecycleUpdateReason::kTest);
 
diff --git a/third_party/blink/renderer/core/css/style_sheet_list.cc b/third_party/blink/renderer/core/css/style_sheet_list.cc
index 2990d6a..b9e4fa6 100644
--- a/third_party/blink/renderer/core/css/style_sheet_list.cc
+++ b/third_party/blink/renderer/core/css/style_sheet_list.cc
@@ -34,20 +34,6 @@
   return MakeGarbageCollected<StyleSheetList>();
 }
 
-StyleSheetList* StyleSheetList::Create(
-    const HeapVector<Member<CSSStyleSheet>>& style_sheet_vector,
-    ExceptionState& exception_state) {
-  if (!RuntimeEnabledFeatures::ConstructableStylesheetsEnabled()) {
-    exception_state.ThrowTypeError("Illegal constructor");
-    return nullptr;
-  }
-  return MakeGarbageCollected<StyleSheetList>(style_sheet_vector);
-}
-
-StyleSheetList::StyleSheetList(
-    const HeapVector<Member<CSSStyleSheet>>& style_sheet_vector)
-    : style_sheet_vector_(style_sheet_vector) {}
-
 StyleSheetList::StyleSheetList(TreeScope* tree_scope)
     : tree_scope_(tree_scope) {
   CHECK(tree_scope);
diff --git a/third_party/blink/renderer/core/css/style_sheet_list.h b/third_party/blink/renderer/core/css/style_sheet_list.h
index 4533e7c..65ba830 100644
--- a/third_party/blink/renderer/core/css/style_sheet_list.h
+++ b/third_party/blink/renderer/core/css/style_sheet_list.h
@@ -38,14 +38,11 @@
 
  public:
   static StyleSheetList* Create();
-  static StyleSheetList* Create(const HeapVector<Member<CSSStyleSheet>>&,
-                                ExceptionState&);
 
   static StyleSheetList* Create(TreeScope* tree_scope) {
     return MakeGarbageCollected<StyleSheetList>(tree_scope);
   }
 
-  explicit StyleSheetList(const HeapVector<Member<CSSStyleSheet>>&);
   explicit StyleSheetList(TreeScope*);
   StyleSheetList() {}
 
diff --git a/third_party/blink/renderer/core/css/style_sheet_list.idl b/third_party/blink/renderer/core/css/style_sheet_list.idl
index 163c8f1d..2a7d00e 100644
--- a/third_party/blink/renderer/core/css/style_sheet_list.idl
+++ b/third_party/blink/renderer/core/css/style_sheet_list.idl
@@ -21,8 +21,6 @@
 // https://drafts.csswg.org/cssom/#the-stylesheetlist-interface
 
 [
-    RaisesException=Constructor,
-    Constructor(sequence<CSSStyleSheet> sheets),
     Exposed=Window
 ] interface StyleSheetList {
     [Measure] getter StyleSheet? item(unsigned long index);
diff --git a/third_party/blink/renderer/core/dom/document_or_shadow_root.h b/third_party/blink/renderer/core/dom/document_or_shadow_root.h
index a319c12..0b5d46d6 100644
--- a/third_party/blink/renderer/core/dom/document_or_shadow_root.h
+++ b/third_party/blink/renderer/core/dom/document_or_shadow_root.h
@@ -30,13 +30,15 @@
     return &shadow_root.StyleSheets();
   }
 
-  static StyleSheetList* adoptedStyleSheets(TreeScope& tree_scope) {
-    return &tree_scope.AdoptedStyleSheets();
+  static const HeapVector<Member<CSSStyleSheet>>& adoptedStyleSheets(
+      TreeScope& tree_scope) {
+    return tree_scope.AdoptedStyleSheets();
   }
 
-  static void setAdoptedStyleSheets(TreeScope& tree_scope,
-                                    StyleSheetList* adopted_style_sheets,
-                                    ExceptionState& exception_state) {
+  static void setAdoptedStyleSheets(
+      TreeScope& tree_scope,
+      HeapVector<Member<CSSStyleSheet>>& adopted_style_sheets,
+      ExceptionState& exception_state) {
     tree_scope.SetAdoptedStyleSheets(adopted_style_sheets, exception_state);
   }
 
diff --git a/third_party/blink/renderer/core/dom/document_or_shadow_root.idl b/third_party/blink/renderer/core/dom/document_or_shadow_root.idl
index ac5e1fc..50bb3346 100644
--- a/third_party/blink/renderer/core/dom/document_or_shadow_root.idl
+++ b/third_party/blink/renderer/core/dom/document_or_shadow_root.idl
@@ -23,5 +23,5 @@
     // Fullscreen API
     // https://fullscreen.spec.whatwg.org/
     [LenientSetter, RuntimeEnabled=FullscreenUnprefixed] readonly attribute Element? fullscreenElement;
-    [RuntimeEnabled=ConstructableStylesheets, RaisesException=Setter] attribute StyleSheetList adoptedStyleSheets;
+    [RuntimeEnabled=ConstructableStylesheets, RaisesException=Setter] attribute FrozenArray<CSSStyleSheet> adoptedStyleSheets;
 };
diff --git a/third_party/blink/renderer/core/dom/mutation_record.h b/third_party/blink/renderer/core/dom/mutation_record.h
index 16a695d..bc69247 100644
--- a/third_party/blink/renderer/core/dom/mutation_record.h
+++ b/third_party/blink/renderer/core/dom/mutation_record.h
@@ -31,6 +31,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_MUTATION_RECORD_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_MUTATION_RECORD_H_
 
+#include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -43,7 +44,7 @@
 class StaticNodeTypeList;
 using StaticNodeList = StaticNodeTypeList<Node>;
 
-class MutationRecord : public ScriptWrappable {
+class CORE_EXPORT MutationRecord : public ScriptWrappable {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
diff --git a/third_party/blink/renderer/core/dom/tree_scope.cc b/third_party/blink/renderer/core/dom/tree_scope.cc
index baa51c8..db23215 100644
--- a/third_party/blink/renderer/core/dom/tree_scope.cc
+++ b/third_party/blink/renderer/core/dom/tree_scope.cc
@@ -339,27 +339,23 @@
 }
 
 bool TreeScope::HasAdoptedStyleSheets() const {
-  return adopted_style_sheets_ && adopted_style_sheets_->length() > 0;
+  return adopted_style_sheets_.size() > 0;
 }
 
-StyleSheetList& TreeScope::AdoptedStyleSheets() {
-  if (!adopted_style_sheets_)
-    SetAdoptedStyleSheets(StyleSheetList::Create());
-  return *adopted_style_sheets_;
+const HeapVector<Member<CSSStyleSheet>>& TreeScope::AdoptedStyleSheets() {
+  return adopted_style_sheets_;
 }
 
-void TreeScope::SetAdoptedStyleSheets(StyleSheetList* adopted_style_sheets,
-                                      ExceptionState& exception_state) {
-  unsigned style_sheets_count =
-      adopted_style_sheets ? adopted_style_sheets->length() : 0;
-  for (unsigned i = 0; i < style_sheets_count; ++i) {
-    CSSStyleSheet* style_sheet = ToCSSStyleSheet(adopted_style_sheets->item(i));
-    if (!style_sheet->IsConstructed()) {
+void TreeScope::SetAdoptedStyleSheets(
+    HeapVector<Member<CSSStyleSheet>>& adopted_style_sheets,
+    ExceptionState& exception_state) {
+  for (CSSStyleSheet* sheet : adopted_style_sheets) {
+    if (!sheet->IsConstructed()) {
       exception_state.ThrowDOMException(
           DOMExceptionCode::kNotAllowedError,
           "Can't adopt non-constructed stylesheets.");
     }
-    Document* associated_document = style_sheet->AssociatedDocument();
+    Document* associated_document = sheet->AssociatedDocument();
     if (associated_document && *associated_document != GetDocument()) {
       exception_state.ThrowDOMException(DOMExceptionCode::kNotAllowedError,
                                         "Sharing constructed stylesheets in "
@@ -370,7 +366,8 @@
   SetAdoptedStyleSheets(adopted_style_sheets);
 }
 
-void TreeScope::SetAdoptedStyleSheets(StyleSheetList* adopted_style_sheets) {
+void TreeScope::SetAdoptedStyleSheets(
+    HeapVector<Member<CSSStyleSheet>>& adopted_style_sheets) {
   GetDocument().GetStyleEngine().AdoptedStyleSheetsWillChange(
       *this, adopted_style_sheets_, adopted_style_sheets);
   adopted_style_sheets_ = adopted_style_sheets;
diff --git a/third_party/blink/renderer/core/dom/tree_scope.h b/third_party/blink/renderer/core/dom/tree_scope.h
index 3668732..e467172c 100644
--- a/third_party/blink/renderer/core/dom/tree_scope.h
+++ b/third_party/blink/renderer/core/dom/tree_scope.h
@@ -38,6 +38,7 @@
 namespace blink {
 
 class ContainerNode;
+class CSSStyleSheet;
 class DOMSelection;
 class Document;
 class Element;
@@ -46,7 +47,6 @@
 class IdTargetObserverRegistry;
 class SVGTreeScopeResources;
 class ScopedStyleResolver;
-class StyleSheetList;
 
 // The root node of a document tree (in which case this is a Document) or of a
 // shadow tree (in which case this is a ShadowRoot). Various things, like
@@ -142,9 +142,10 @@
   SVGTreeScopeResources& EnsureSVGTreeScopedResources();
 
   bool HasAdoptedStyleSheets() const;
-  StyleSheetList& AdoptedStyleSheets();
-  void SetAdoptedStyleSheets(StyleSheetList*);
-  void SetAdoptedStyleSheets(StyleSheetList*, ExceptionState&);
+  const HeapVector<Member<CSSStyleSheet>>& AdoptedStyleSheets();
+  void SetAdoptedStyleSheets(HeapVector<Member<CSSStyleSheet>>&);
+  void SetAdoptedStyleSheets(HeapVector<Member<CSSStyleSheet>>&,
+                             ExceptionState&);
 
  protected:
   TreeScope(ContainerNode&, Document&);
@@ -176,7 +177,7 @@
 
   Member<SVGTreeScopeResources> svg_tree_scoped_resources_;
 
-  Member<StyleSheetList> adopted_style_sheets_;
+  HeapVector<Member<CSSStyleSheet>> adopted_style_sheets_;
 };
 
 inline bool TreeScope::HasElementWithId(const AtomicString& id) const {
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 7063a3a..bc67865 100644
--- a/third_party/blink/renderer/core/exported/web_frame_test.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -1298,7 +1298,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "fixed_layout.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    &client, ConfigureAndroid);
 
   Document* document =
       ToLocalFrame(web_view_helper.GetWebView()->GetPage()->MainFrame())
@@ -1329,7 +1329,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + html_file, nullptr, &client,
-                                    nullptr, ConfigureAndroid);
+                                    ConfigureAndroid);
 
   Document* document =
       ToLocalFrame(web_view_helper.GetWebView()->GetPage()->MainFrame())
@@ -1354,7 +1354,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "iframe_reload.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    &client, ConfigureAndroid);
 
   LocalFrame* main_frame =
       ToLocalFrame(web_view_helper.GetWebView()->GetPage()->MainFrame());
@@ -1398,7 +1398,7 @@
   int viewport_height = 0;
 
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+  web_view_helper.Initialize(nullptr, &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
   EXPECT_EQ(viewport_width, web_view_helper.GetWebView()
@@ -1424,7 +1424,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "no_viewport_tag.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    &client, ConfigureAndroid);
 
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -1453,7 +1453,7 @@
   // Make sure we initialize to minimum scale, even if the window size
   // only becomes available after the load begins.
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+  web_view_helper.Initialize(nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.25f, 5);
   frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
                                 base_url_ + "fixed_layout.html");
@@ -1496,7 +1496,7 @@
   // Make sure we initialize to minimum scale, even if the window size
   // only becomes available after the load begins.
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+  web_view_helper.Initialize(nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.25f, 5);
   frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
                                 base_url_ + "wide_document.html");
@@ -1537,7 +1537,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
-      base_url_ + "viewport-auto-initial-scale.html", nullptr, &client, nullptr,
+      base_url_ + "viewport-auto-initial-scale.html", nullptr, &client,
       ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -1564,7 +1564,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
-      base_url_ + "viewport-auto-initial-scale.html", nullptr, &client, nullptr,
+      base_url_ + "viewport-auto-initial-scale.html", nullptr, &client,
       ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
@@ -1585,7 +1585,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "large-div.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    &client, ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetLoadWithOverviewMode(false);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
@@ -1607,7 +1607,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
-      base_url_ + "viewport-auto-initial-scale.html", nullptr, &client, nullptr,
+      base_url_ + "viewport-auto-initial-scale.html", nullptr, &client,
       ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
@@ -1639,7 +1639,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport-wide-2x-initial-scale.html", nullptr, &client,
-      nullptr, ConfigureAndroid);
+      ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
   web_view_helper.GetWebView()->GetSettings()->SetUseWideViewport(false);
@@ -1670,7 +1670,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "no_viewport_tag.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    &client, ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
   web_view_helper.GetWebView()->GetSettings()->SetUseWideViewport(true);
@@ -1700,7 +1700,7 @@
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+  web_view_helper.Initialize(nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
   web_view_helper.GetWebView()->GetSettings()->SetUseWideViewport(true);
@@ -1731,8 +1731,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport-height-1000.html",
-                                    nullptr, &client, nullptr,
-                                    ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
   web_view_helper.GetWebView()->GetSettings()->SetUseWideViewport(false);
@@ -1755,7 +1754,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
-      base_url_ + "viewport-2x-initial-scale.html", nullptr, &client, nullptr,
+      base_url_ + "viewport-2x-initial-scale.html", nullptr, &client,
       ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
@@ -1786,7 +1785,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport-wide-2x-initial-scale.html", nullptr, &client,
-      nullptr, ConfigureAndroid);
+      ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetLoadWithOverviewMode(false);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -1804,7 +1803,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "fixed_layout.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    &client, ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
   web_view_helper.GetWebView()->GetSettings()->SetLoadWithOverviewMode(false);
@@ -1839,7 +1838,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
-      base_url_ + "viewport-auto-initial-scale.html", nullptr, &client, nullptr,
+      base_url_ + "viewport-auto-initial-scale.html", nullptr, &client,
       ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetLoadWithOverviewMode(false);
   web_view_helper.GetWebView()->SetInitialPageScaleOverride(
@@ -1863,7 +1862,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport-wide-2x-initial-scale.html", nullptr, &client,
-      nullptr, ConfigureAndroid);
+      ConfigureAndroid);
   web_view_helper.GetWebView()->SetInitialPageScaleOverride(
       enforced_page_scale_factor);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
@@ -1895,7 +1894,7 @@
     for (int quirk_enabled = 0; quirk_enabled <= 1; ++quirk_enabled) {
       frame_test_helpers::WebViewHelper web_view_helper;
       web_view_helper.InitializeAndLoad(base_url_ + pages[i], nullptr, &client,
-                                        nullptr, ConfigureAndroid);
+                                        ConfigureAndroid);
       web_view_helper.GetWebView()
           ->GetSettings()
           ->SetClobberUserAgentInitialScaleQuirk(quirk_enabled);
@@ -1921,7 +1920,7 @@
   float enforced_page_scale_factor = 0.5;
 
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.InitializeAndLoad("about:blank", nullptr, &client, nullptr,
+  web_view_helper.InitializeAndLoad("about:blank", nullptr, &client,
                                     ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
@@ -1952,7 +1951,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
 
   web_view_helper.InitializeAndLoad(base_url_ + "0-by-0.html", nullptr, &client,
-                                    nullptr, ConfigureAndroid);
+                                    ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetForceZeroLayoutHeight(true);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -1973,7 +1972,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
 
   web_view_helper.InitializeAndLoad(base_url_ + "0-by-0.html", nullptr, &client,
-                                    nullptr, ConfigureAndroid);
+                                    ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetForceZeroLayoutHeight(true);
   UpdateAllLifecyclePhases(web_view_helper.GetWebView());
 
@@ -2047,7 +2046,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
 
   web_view_helper.InitializeAndLoad(base_url_ + "200-by-300.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
   EXPECT_LE(viewport_height, web_view_helper.GetWebView()
@@ -2142,7 +2141,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
 
   web_view_helper.InitializeAndLoad(base_url_ + "button.html", nullptr, &client,
-                                    nullptr, ConfigureAndroid);
+                                    ConfigureAndroid);
   // set view height to zero so that if the height of the view is not
   // successfully updated during later resizes touch events will fail
   // (as in not hit content included in the view)
@@ -2246,7 +2245,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
 
   web_view_helper.InitializeAndLoad(base_url_ + "200-by-300.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    &client, ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetForceZeroLayoutHeight(true);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -2272,7 +2271,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
 
   web_view_helper.InitializeAndLoad(base_url_ + "200-by-300.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    &client, ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
   web_view_helper.GetWebView()->GetSettings()->SetUseWideViewport(true);
@@ -2296,7 +2295,7 @@
   int viewport_height = 800;
 
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.InitializeAndLoad("about:blank", nullptr, &client, nullptr,
+  web_view_helper.InitializeAndLoad("about:blank", nullptr, &client,
                                     ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
@@ -2327,7 +2326,7 @@
   int viewport_height = 800;
 
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.InitializeAndLoad("about:blank", nullptr, &client, nullptr,
+  web_view_helper.InitializeAndLoad("about:blank", nullptr, &client,
                                     ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
@@ -2357,7 +2356,7 @@
   int viewport_height = 800;
 
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.InitializeAndLoad("about:blank", nullptr, &client, nullptr,
+  web_view_helper.InitializeAndLoad("about:blank", nullptr, &client,
                                     ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
@@ -2438,7 +2437,7 @@
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+  web_view_helper.Initialize(nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetViewportMetaZeroValuesQuirk(
       true);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
@@ -2542,7 +2541,7 @@
   float expected_page_scale_factor = 0.5f;
 
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+  web_view_helper.Initialize(nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()->GetSettings()->SetViewportMetaZeroValuesQuirk(
       true);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
@@ -2583,7 +2582,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "fixed_layout.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
   unsigned prev_layout_count =
@@ -2609,7 +2608,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "fixed_layout.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
   unsigned prev_layout_count =
@@ -2635,7 +2634,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "fixed_layout.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
   web_view_helper.GetWebView()->SetPageScaleFactor(3);
@@ -2657,7 +2656,7 @@
   int viewport_height = 480;
 
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+  web_view_helper.Initialize(nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.25f, 5);
   frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
                                 base_url_ + "fixed_layout.html");
@@ -2686,7 +2685,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "large-div.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
   LocalFrameView* view = web_view_helper.LocalMainFrame()->GetFrameView();
@@ -2728,7 +2727,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "fixed_layout.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
   web_view_helper.GetWebView()->SetPageScaleFactor(2);
@@ -2764,7 +2763,7 @@
     frame_test_helpers::WebViewHelper web_view_helper;
     web_view_helper.InitializeAndLoad(
         base_url_ + "viewport-target-densitydpi-high.html", nullptr, &client,
-        nullptr, ConfigureAndroid);
+        ConfigureAndroid);
     web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
         true);
     web_view_helper.GetWebView()
@@ -2810,7 +2809,7 @@
     frame_test_helpers::WebViewHelper web_view_helper;
     web_view_helper.InitializeAndLoad(
         base_url_ + "viewport-target-densitydpi-device.html", nullptr, &client,
-        nullptr, ConfigureAndroid);
+        ConfigureAndroid);
     web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
         true);
     web_view_helper.GetWebView()
@@ -2853,7 +2852,7 @@
     frame_test_helpers::WebViewHelper web_view_helper;
     web_view_helper.InitializeAndLoad(
         base_url_ + "viewport-target-densitydpi-device-and-fixed-width.html",
-        nullptr, &client, nullptr, ConfigureAndroid);
+        nullptr, &client, ConfigureAndroid);
     web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
         true);
     web_view_helper.GetWebView()
@@ -2891,7 +2890,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport-initial-scale-less-than-1.html", nullptr, &client,
-      nullptr, ConfigureAndroid);
+      ConfigureAndroid);
   web_view_helper.GetWebView()
       ->GetSettings()
       ->SetSupportDeprecatedTargetDensityDPI(true);
@@ -2930,7 +2929,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport-initial-scale-less-than-1-device-width.html",
-      nullptr, &client, nullptr, ConfigureAndroid);
+      nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()
       ->GetSettings()
       ->SetSupportDeprecatedTargetDensityDPI(true);
@@ -2970,7 +2969,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "large-div.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    &client, ConfigureAndroid);
   web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.25f, 5);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
@@ -3007,7 +3006,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport-initial-scale-and-user-scalable-no.html", nullptr,
-      &client, nullptr, ConfigureAndroid);
+      &client, ConfigureAndroid);
   web_view_helper.GetWebView()
       ->GetSettings()
       ->SetViewportMetaNonUserScalableQuirk(true);
@@ -3042,7 +3041,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport-initial-scale-and-user-scalable-no.html", nullptr,
-      &client, nullptr, ConfigureAndroid);
+      &client, ConfigureAndroid);
   web_view_helper.GetWebView()
       ->GetSettings()
       ->SetSupportDeprecatedTargetDensityDPI(true);
@@ -3082,7 +3081,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport-2x-initial-scale-non-user-scalable.html", nullptr,
-      &client, nullptr, ConfigureAndroid);
+      &client, ConfigureAndroid);
   web_view_helper.GetWebView()
       ->GetSettings()
       ->SetViewportMetaNonUserScalableQuirk(true);
@@ -3117,7 +3116,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "no_viewport_tag.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    &client, ConfigureAndroid);
   web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.25f, 5);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
@@ -3137,8 +3136,7 @@
   FixedLayoutTestWebViewClient client;
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport-inside-media.html",
-                                    nullptr, &client, nullptr,
-                                    ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(640, 480));
 
   EXPECT_EQ(2000, web_view_helper.GetWebView()
@@ -3161,7 +3159,7 @@
 
   FixedLayoutTestWebViewClient client;
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+  web_view_helper.Initialize(nullptr, &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(640, 480));
   frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
                                 base_url_ + "viewport-and-media.html");
@@ -3187,7 +3185,7 @@
 
   FixedLayoutTestWebViewClient client;
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, &client, nullptr, ConfigureAndroid);
+  web_view_helper.Initialize(nullptr, &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(800, 600));
   frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
                                 base_url_ + "viewport-lengths.html");
@@ -3225,7 +3223,7 @@
 
     frame_test_helpers::WebViewHelper web_view_helper;
     web_view_helper.InitializeAndLoad(base_url_ + url, nullptr, nullptr,
-                                      nullptr, ConfigureAndroid);
+                                      ConfigureAndroid);
     web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.25f, 5);
 
     // Origin scrollOffsets preserved under resize.
@@ -3344,7 +3342,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "fixed_layout.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
   LocalFrameView* view = web_view_helper.LocalMainFrame()->GetFrameView();
@@ -3372,8 +3370,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "no_scale_for_you.html",
-                                    nullptr, &client, nullptr,
-                                    ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.25f, 5);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
 
@@ -3405,12 +3402,10 @@
   int view_width = 500;
   int view_height = 500;
 
-  std::unique_ptr<FakeCompositingWebViewClient>
-      fake_compositing_web_view_client =
-          std::make_unique<FakeCompositingWebViewClient>();
+  FakeCompositingWebViewClient fake_compositing_web_view_client;
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, fake_compositing_web_view_client.get(),
-                             nullptr, &ConfigureCompositingWebView);
+  web_view_helper.Initialize(nullptr, &fake_compositing_web_view_client,
+                             &ConfigureCompositingWebView);
 
   web_view_helper.Resize(WebSize(view_width, view_height));
   frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
@@ -3474,7 +3469,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "get_scale_for_auto_zoom_into_div_test.html", nullptr,
-      nullptr, nullptr, ConfigureAndroid);
+      nullptr, ConfigureAndroid);
   web_view_helper.GetWebView()->SetDeviceScaleFactor(kDeviceScaleFactor);
   web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.01f, 4);
   web_view_helper.GetWebView()->SetPageScaleFactor(0.5f);
@@ -3539,7 +3534,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "get_wide_div_for_auto_zoom_test.html", nullptr, nullptr,
-      nullptr, ConfigureAndroid);
+      ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
   web_view_helper.GetWebView()->SetDeviceScaleFactor(kDeviceScaleFactor);
   web_view_helper.GetWebView()->SetPageScaleFactor(1.0f);
@@ -3577,7 +3572,7 @@
   int viewport_height = 1280 / kDeviceScaleFactor;
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "very_tall_div.html", nullptr,
-                                    nullptr, nullptr, ConfigureAndroid);
+                                    nullptr, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
   web_view_helper.GetWebView()->SetDeviceScaleFactor(kDeviceScaleFactor);
   web_view_helper.GetWebView()->SetPageScaleFactor(1.0f);
@@ -3606,7 +3601,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "get_multiple_divs_for_auto_zoom_test.html", nullptr, nullptr,
-      nullptr, ConfigureAndroid);
+      ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
   web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.5f, 4);
   web_view_helper.GetWebView()->SetDeviceScaleFactor(kDeviceScaleFactor);
@@ -3673,7 +3668,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "get_scale_bounds_check_for_auto_zoom_test.html", nullptr,
-      nullptr, nullptr, ConfigureAndroid);
+      nullptr, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
   web_view_helper.GetWebView()->SetDeviceScaleFactor(1.5f);
   web_view_helper.GetWebView()->SetMaximumLegibleScale(1.f);
@@ -3759,7 +3754,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "get_scale_bounds_check_for_auto_zoom_test.html", nullptr,
-      nullptr, nullptr, ConfigureAndroid);
+      nullptr, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
   web_view_helper.GetWebView()->SetMaximumLegibleScale(
       maximum_legible_scale_factor);
@@ -3876,7 +3871,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "get_scale_bounds_check_for_auto_zoom_test.html", nullptr,
-      nullptr, nullptr, ConfigureAndroid);
+      nullptr, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
   web_view_helper.GetWebView()->SetMaximumLegibleScale(1.f);
   UpdateAllLifecyclePhases(web_view_helper.GetWebView());
@@ -3991,7 +3986,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "block_bound.html", nullptr,
-                                    nullptr, nullptr, ConfigureAndroid);
+                                    nullptr, ConfigureAndroid);
   web_view_helper.Resize(WebSize(300, 300));
 
   IntRect rect_back = IntRect(0, 0, 200, 200);
@@ -4373,7 +4368,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "get_scale_for_zoom_into_editable_test.html", nullptr,
-      nullptr, nullptr, ConfigureAndroid);
+      nullptr, ConfigureAndroid);
   web_view_helper.GetWebView()
       ->GetPage()
       ->GetSettings()
@@ -7722,7 +7717,7 @@
   TestSameDocumentWithImageWebFrameClient client;
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "foo_with_image.html", &client,
-                                    nullptr, nullptr,
+                                    nullptr,
                                     &ConfigureLoadsImagesAutomatically);
 
   WebCache::Clear();
@@ -8001,7 +7996,7 @@
           std::make_unique<FakeCompositingWebViewClient>();
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.Initialize(nullptr, fake_compositing_web_view_client.get(),
-                             nullptr, &ConfigureCompositingWebView);
+                             &ConfigureCompositingWebView);
 
   web_view_helper.Resize(WebSize(100, 100));
   frame_test_helpers::LoadFrame(web_view_helper.GetWebView()->MainFrameImpl(),
@@ -8095,7 +8090,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "fixed-position-in-fixed-viewport.html", nullptr, nullptr,
-      nullptr, ConfigureAndroid);
+      ConfigureAndroid);
 
   WebViewImpl* web_view = web_view_helper.GetWebView();
   web_view_helper.Resize(WebSize(100, 100));
@@ -8136,7 +8131,7 @@
   RegisterMockedHttpURLLoad("long_scroll.html");
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "long_scroll.html", nullptr,
-                                    &client, nullptr, ConfigureAndroid);
+                                    &client, ConfigureAndroid);
 
   WebViewImpl* web_view = web_view_helper.GetWebView();
   LocalFrameView* frame_view = web_view_helper.LocalMainFrame()->GetFrameView();
@@ -8230,8 +8225,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "rtl-overview-mode.html",
-                                    nullptr, &client, nullptr,
-                                    ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
   web_view_helper.GetWebView()->SetInitialPageScaleOverride(-1);
   web_view_helper.GetWebView()->GetSettings()->SetWideViewportQuirkEnabled(
       true);
@@ -8254,8 +8248,7 @@
   client.screen_info_.rect.width = viewport_width;
   client.screen_info_.rect.height = viewport_height;
   WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
-      base_url_ + "fullscreen_div.html", nullptr, &client, nullptr,
-      ConfigureAndroid);
+      base_url_ + "fullscreen_div.html", nullptr, &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
   UpdateAllLifecyclePhases(web_view_impl);
 
@@ -8293,8 +8286,7 @@
   int viewport_width = 640;
   int viewport_height = 480;
   WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
-      base_url_ + "fullscreen_div.html", nullptr, &client, nullptr,
-      ConfigureAndroid);
+      base_url_ + "fullscreen_div.html", nullptr, &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
   UpdateAllLifecyclePhases(web_view_impl);
 
@@ -8352,8 +8344,7 @@
   int viewport_width = 640;
   int viewport_height = 480;
   WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
-      base_url_ + "fullscreen_div.html", nullptr, &client, nullptr,
-      ConfigureAndroid);
+      base_url_ + "fullscreen_div.html", nullptr, &client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
   UpdateAllLifecyclePhases(web_view_impl);
 
@@ -8405,8 +8396,7 @@
   RegisterMockedHttpURLLoad("fullscreen_div.html");
   frame_test_helpers::WebViewHelper web_view_helper;
   WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
-      base_url_ + "fullscreen_iframe.html", nullptr, &client, nullptr,
-      ConfigureAndroid);
+      base_url_ + "fullscreen_iframe.html", nullptr, &client, ConfigureAndroid);
   int viewport_width = 640;
   int viewport_height = 480;
   client.screen_info_.rect.width = viewport_width;
@@ -8495,8 +8485,7 @@
   RegisterMockedHttpURLLoad("viewport-tiny.html");
   frame_test_helpers::WebViewHelper web_view_helper;
   WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
-      base_url_ + "viewport-tiny.html", nullptr, &client, nullptr,
-      ConfigureAndroid);
+      base_url_ + "viewport-tiny.html", nullptr, &client, ConfigureAndroid);
   int viewport_width = 384;
   int viewport_height = 640;
   client.screen_info_.rect.width = viewport_width;
@@ -8540,8 +8529,7 @@
   RegisterMockedHttpURLLoad("viewport-tiny.html");
   frame_test_helpers::WebViewHelper web_view_helper;
   WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
-      base_url_ + "viewport-tiny.html", nullptr, &client, nullptr,
-      ConfigureAndroid);
+      base_url_ + "viewport-tiny.html", nullptr, &client, ConfigureAndroid);
   int viewport_width = 384;
   int viewport_height = 640;
   client.screen_info_.rect.width = viewport_width;
@@ -8600,7 +8588,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
       base_url_ + "fullscreen_restore_scale_factor.html", nullptr, &client,
-      nullptr, &ConfigureAndroid);
+      &ConfigureAndroid);
   client.screen_info_.rect.width =
       screen_size_minus_status_bars_minus_url_bar.width;
   client.screen_info_.rect.height =
@@ -8667,8 +8655,7 @@
   int viewport_height = 200;
 
   WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
-      base_url_ + "viewport-tiny.html", nullptr, nullptr, nullptr,
-      ConfigureAndroid);
+      base_url_ + "viewport-tiny.html", nullptr, nullptr, ConfigureAndroid);
 
   web_view_helper.Resize(WebSize(viewport_width, viewport_height));
   UpdateAllLifecyclePhases(web_view_impl);
@@ -9744,18 +9731,15 @@
   Reset();
 }
 
-class RemoteWindowCloseClient : public frame_test_helpers::TestWebViewClient {
+class RemoteWindowCloseClient : public frame_test_helpers::TestWebWidgetClient {
  public:
-  RemoteWindowCloseClient() : closed_(false) {}
-  ~RemoteWindowCloseClient() override = default;
-
-  // frame_test_helpers::TestWebViewClient:
+  // WebWidgetClient implementation.
   void CloseWidgetSoon() override { closed_ = true; }
 
   bool Closed() const { return closed_; }
 
  private:
-  bool closed_;
+  bool closed_ = false;
 };
 
 TEST_F(WebFrameTest, WindowOpenRemoteClose) {
@@ -9763,7 +9747,8 @@
   main_web_view.Initialize();
 
   // Create a remote window that will be closed later in the test.
-  RemoteWindowCloseClient view_client;
+  RemoteWindowCloseClient client;
+  frame_test_helpers::TestWebViewClient view_client(&client);
   frame_test_helpers::WebViewHelper popup;
   popup.InitializeRemote(nullptr, nullptr, &view_client);
   popup.RemoteMainFrame()->SetOpener(main_web_view.LocalMainFrame());
@@ -9774,12 +9759,12 @@
   // Attempt to close the window, which should fail as it isn't opened
   // by a script.
   remote_frame->DomWindow()->close(local_frame->DomWindow());
-  EXPECT_FALSE(view_client.Closed());
+  EXPECT_FALSE(client.Closed());
 
   // Marking it as opened by a script should now allow it to be closed.
   remote_frame->GetPage()->SetOpenedByDOM();
   remote_frame->DomWindow()->close(local_frame->DomWindow());
-  EXPECT_TRUE(view_client.Closed());
+  EXPECT_TRUE(client.Closed());
 }
 
 TEST_F(WebFrameTest, NavigateRemoteToLocalWithOpener) {
@@ -9975,8 +9960,7 @@
   FixedLayoutTestWebViewClient client;
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "device_media_queries.html",
-                                    nullptr, &client, nullptr,
-                                    ConfigureAndroid);
+                                    nullptr, &client, ConfigureAndroid);
   LocalFrame* frame =
       ToLocalFrame(web_view_helper.GetWebView()->GetPage()->MainFrame());
   Element* element = frame->GetDocument()->getElementById("test");
@@ -10202,7 +10186,8 @@
       local_child->GetDocument()->Fetcher()->Context().DefersLoading());
 }
 
-class OverscrollWebViewClient : public frame_test_helpers::TestWebViewClient {
+class OverscrollWebWidgetClient
+    : public frame_test_helpers::TestWebWidgetClient {
  public:
   MOCK_METHOD5(DidOverscroll,
                void(const WebFloatSize&,
@@ -10266,12 +10251,12 @@
 
 TEST_P(WebFrameOverscrollTest,
        AccumulatedRootOverscrollAndUnsedDeltaValuesOnOverscroll) {
-  OverscrollWebViewClient client;
+  OverscrollWebWidgetClient client;
+  frame_test_helpers::TestWebViewClient view_client(&client);
   RegisterMockedHttpURLLoad("overscroll/overscroll.html");
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "overscroll/overscroll.html",
-                                    nullptr, &client, nullptr,
-                                    ConfigureAndroid);
+                                    nullptr, &view_client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(200, 200));
 
   // Calculation of accumulatedRootOverscroll and unusedDelta on multiple
@@ -10320,11 +10305,12 @@
 
 TEST_P(WebFrameOverscrollTest,
        AccumulatedOverscrollAndUnusedDeltaValuesOnDifferentAxesOverscroll) {
-  OverscrollWebViewClient client;
+  OverscrollWebWidgetClient client;
+  frame_test_helpers::TestWebViewClient view_client(&client);
   RegisterMockedHttpURLLoad("overscroll/div-overscroll.html");
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
-      base_url_ + "overscroll/div-overscroll.html", nullptr, &client, nullptr,
+      base_url_ + "overscroll/div-overscroll.html", nullptr, &view_client,
       ConfigureAndroid);
   web_view_helper.Resize(WebSize(200, 200));
 
@@ -10369,11 +10355,12 @@
 }
 
 TEST_P(WebFrameOverscrollTest, RootLayerOverscrolledOnInnerDivOverScroll) {
-  OverscrollWebViewClient client;
+  OverscrollWebWidgetClient client;
+  frame_test_helpers::TestWebViewClient view_client(&client);
   RegisterMockedHttpURLLoad("overscroll/div-overscroll.html");
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
-      base_url_ + "overscroll/div-overscroll.html", nullptr, &client, nullptr,
+      base_url_ + "overscroll/div-overscroll.html", nullptr, &view_client,
       ConfigureAndroid);
   web_view_helper.Resize(WebSize(200, 200));
 
@@ -10396,13 +10383,14 @@
 }
 
 TEST_P(WebFrameOverscrollTest, RootLayerOverscrolledOnInnerIFrameOverScroll) {
-  OverscrollWebViewClient client;
+  OverscrollWebWidgetClient client;
+  frame_test_helpers::TestWebViewClient view_client(&client);
   RegisterMockedHttpURLLoad("overscroll/iframe-overscroll.html");
   RegisterMockedHttpURLLoad("overscroll/scrollable-iframe.html");
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
-      base_url_ + "overscroll/iframe-overscroll.html", nullptr, &client,
-      nullptr, ConfigureAndroid);
+      base_url_ + "overscroll/iframe-overscroll.html", nullptr, &view_client,
+      ConfigureAndroid);
   web_view_helper.Resize(WebSize(200, 200));
 
   ScrollBegin(&web_view_helper, 0, -320);
@@ -10432,11 +10420,12 @@
 }
 
 TEST_P(WebFrameOverscrollTest, ScaledPageRootLayerOverscrolled) {
-  OverscrollWebViewClient client;
+  OverscrollWebWidgetClient client;
+  frame_test_helpers::TestWebViewClient view_client(&client);
   RegisterMockedHttpURLLoad("overscroll/overscroll.html");
   frame_test_helpers::WebViewHelper web_view_helper;
   WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
-      base_url_ + "overscroll/overscroll.html", nullptr, &client, nullptr,
+      base_url_ + "overscroll/overscroll.html", nullptr, &view_client,
       ConfigureAndroid);
   web_view_helper.Resize(WebSize(200, 200));
   web_view_impl->SetPageScaleFactor(3.0);
@@ -10478,12 +10467,12 @@
 }
 
 TEST_P(WebFrameOverscrollTest, NoOverscrollForSmallvalues) {
-  OverscrollWebViewClient client;
+  OverscrollWebWidgetClient client;
+  frame_test_helpers::TestWebViewClient view_client(&client);
   RegisterMockedHttpURLLoad("overscroll/overscroll.html");
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "overscroll/overscroll.html",
-                                    nullptr, &client, nullptr,
-                                    ConfigureAndroid);
+                                    nullptr, &view_client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(200, 200));
 
   ScrollBegin(&web_view_helper, 10, 10);
@@ -10540,12 +10529,12 @@
 }
 
 TEST_P(WebFrameOverscrollTest, OverscrollBehaviorAffectsDidOverscroll) {
-  OverscrollWebViewClient client;
+  OverscrollWebWidgetClient client;
+  frame_test_helpers::TestWebViewClient view_client(&client);
   RegisterMockedHttpURLLoad("overscroll/overscroll.html");
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "overscroll/overscroll.html",
-                                    nullptr, &client, nullptr,
-                                    ConfigureAndroid);
+                                    nullptr, &view_client, ConfigureAndroid);
   web_view_helper.Resize(WebSize(200, 200));
 
   WebLocalFrame* mainFrame =
@@ -10594,13 +10583,14 @@
 }
 
 TEST_P(WebFrameOverscrollTest, OnlyMainFrameOverscrollBehaviorHasEffect) {
-  OverscrollWebViewClient client;
+  OverscrollWebWidgetClient client;
+  frame_test_helpers::TestWebViewClient view_client(&client);
   RegisterMockedHttpURLLoad("overscroll/iframe-overscroll.html");
   RegisterMockedHttpURLLoad("overscroll/scrollable-iframe.html");
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
-      base_url_ + "overscroll/iframe-overscroll.html", nullptr, &client,
-      nullptr, ConfigureAndroid);
+      base_url_ + "overscroll/iframe-overscroll.html", nullptr, &view_client,
+      ConfigureAndroid);
   web_view_helper.Resize(WebSize(200, 200));
 
   WebLocalFrame* mainFrame =
@@ -10849,8 +10839,7 @@
 // injected script before the initial navigation.
 TEST(WebFrameGlobalReuseTest, ChildFrame) {
   frame_test_helpers::WebViewHelper helper;
-  helper.Initialize(nullptr, nullptr, nullptr,
-                    EnableGlobalReuseForUnownedMainFrames);
+  helper.Initialize(nullptr, nullptr, EnableGlobalReuseForUnownedMainFrames);
 
   WebLocalFrame* main_frame = helper.LocalMainFrame();
   frame_test_helpers::LoadFrame(main_frame, "data:text/html,<iframe></iframe>");
@@ -10872,8 +10861,7 @@
   opener_helper.Initialize();
   frame_test_helpers::WebViewHelper helper;
   helper.InitializeWithOpener(opener_helper.GetWebView()->MainFrame(), nullptr,
-                              nullptr, nullptr,
-                              EnableGlobalReuseForUnownedMainFrames);
+                              nullptr, EnableGlobalReuseForUnownedMainFrames);
 
   WebLocalFrame* main_frame = helper.LocalMainFrame();
   v8::HandleScope scope(v8::Isolate::GetCurrent());
@@ -10891,8 +10879,7 @@
 // to persist on the first navigation away from the initial empty document.
 TEST(WebFrameGlobalReuseTest, ReuseForMainFrameIfEnabled) {
   frame_test_helpers::WebViewHelper helper;
-  helper.Initialize(nullptr, nullptr, nullptr,
-                    EnableGlobalReuseForUnownedMainFrames);
+  helper.Initialize(nullptr, nullptr, EnableGlobalReuseForUnownedMainFrames);
 
   WebLocalFrame* main_frame = helper.LocalMainFrame();
   v8::HandleScope scope(v8::Isolate::GetCurrent());
@@ -11198,7 +11185,7 @@
   constexpr int kBrowserControlsHeight = 100;
 
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, nullptr, nullptr, ConfigureAndroid);
+  web_view_helper.Initialize(nullptr, nullptr, ConfigureAndroid);
   WebViewImpl* web_view = web_view_helper.GetWebView();
   web_view->ResizeWithBrowserControls(
       WebSize(kViewportWidth, kViewportHeight - kBrowserControlsHeight),
@@ -11295,8 +11282,7 @@
 
 TEST_F(WebFrameTest, MouseOverDifferntNodeClearsTooltip) {
   frame_test_helpers::WebViewHelper web_view_helper;
-  web_view_helper.Initialize(nullptr, nullptr, nullptr,
-                             [](WebSettings* settings) {});
+  web_view_helper.Initialize();
   web_view_helper.Resize(WebSize(200, 200));
   WebViewImpl* web_view = web_view_helper.GetWebView();
 
diff --git a/third_party/blink/renderer/core/exported/web_layer_test.cc b/third_party/blink/renderer/core/exported/web_layer_test.cc
index 6e9ff4f..03c6ae9 100644
--- a/third_party/blink/renderer/core/exported/web_layer_test.cc
+++ b/third_party/blink/renderer/core/exported/web_layer_test.cc
@@ -34,7 +34,7 @@
 
   void SetUp() override {
     web_view_helper_ = std::make_unique<frame_test_helpers::WebViewHelper>();
-    web_view_helper_->Initialize(nullptr, &web_view_client_, nullptr,
+    web_view_helper_->Initialize(nullptr, &web_view_client_,
                                  &ConfigureCompositingWebView);
     web_view_helper_->Resize(WebSize(200, 200));
 
@@ -44,6 +44,8 @@
     paint_artifact_compositor()->EnableExtraDataForTesting();
   }
 
+  void TearDown() override { web_view_helper_.reset(); }
+
   // Both sets the inner html and runs the document lifecycle.
   void InitializeWithHTML(LocalFrame& frame, const String& html_content) {
     frame.GetDocument()->body()->SetInnerHTMLFromString(html_content);
diff --git a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
index 37e97dc..c25191a2 100644
--- a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
@@ -125,19 +125,18 @@
   }
 
   void ScheduleAnimation(const LocalFrameView*) override {
-    // Calling scheduleAnimation on m_webView so WebViewTestProxy will call
-    // beginFrame.
     if (WebTestSupport::IsRunningWebTest()) {
-      popup_->web_view_->MainFrameImpl()
-          ->FrameWidgetImpl()
-          ->ScheduleAnimation();
-    }
-
-    if (popup_->layer_tree_view_) {
-      popup_->layer_tree_view_->SetNeedsBeginFrame();
+      // In single threaded web tests, the main frame's WebWidgetClient
+      // (provided by WebViewTestProxy or WebWidgetTestProxy) runs the composite
+      // step for the current popup. We don't run popup tests with a compositor
+      // thread.
+      popup_->web_view_->WidgetClient()->ScheduleAnimation();
       return;
     }
-    popup_->widget_client_->ScheduleAnimation();
+
+    // TODO(danakj): Why null check? Can ScheduleAnimation() happen after the
+    // call to WillCloseLayerTreeView()?
+    popup_->WidgetClient()->ScheduleAnimation();
   }
 
   void AttachCompositorAnimationTimeline(CompositorAnimationTimeline* timeline,
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc
index b261cd6ba..d912653a 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -3233,15 +3233,6 @@
   return root_graphics_layer_;
 }
 
-void WebViewImpl::ScheduleAnimationForWidget() {
-  if (layer_tree_view_) {
-    layer_tree_view_->SetNeedsBeginFrame();
-    return;
-  }
-  if (client_)
-    client_->WidgetClient()->ScheduleAnimation();
-}
-
 void WebViewImpl::SetLayerTreeView(WebLayerTreeView* layer_tree_view) {
   DCHECK(does_composite_);
   layer_tree_view_ = layer_tree_view;
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h
index 650fad4..ed5ac69 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.h
+++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -476,9 +476,6 @@
                                float bottom_controls_height,
                                bool browser_controls_shrink_layout);
 
-  // TODO(lfg): Remove once WebViewFrameWidget is deleted.
-  void ScheduleAnimationForWidget();
-
   void UpdateBaseBackgroundColor();
 
   friend class WebView;  // So WebView::Create can call our constructor
diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc
index 9d707da7..dbe98d02 100644
--- a/third_party/blink/renderer/core/exported/web_view_test.cc
+++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -194,9 +194,10 @@
   TestData test_data_;
 };
 
-class TapHandlingWebViewClient : public frame_test_helpers::TestWebViewClient {
+class TapHandlingWebWidgetClient
+    : public frame_test_helpers::TestWebWidgetClient {
  public:
-  // WebViewClient methods
+  // WebWidgetClient overrides.
   void DidHandleGestureEvent(const WebGestureEvent& event,
                              bool event_cancelled) override {
     if (event.GetType() == WebInputEvent::kGestureTap) {
@@ -488,7 +489,7 @@
   // initialization code between WebView and WebLocalFrame creation.
   frame_test_helpers::TestWebViewClient web_view_client;
   WebViewImpl* web_view = static_cast<WebViewImpl*>(
-      WebView::Create(&web_view_client, &web_view_client,
+      WebView::Create(&web_view_client, web_view_client.WidgetClient(),
                       /*is_hidden=*/false,
                       /*compositing_enabled=*/true, nullptr));
   EXPECT_NE(SK_ColorBLUE, web_view->MainFrameWidget()->BackgroundColor());
@@ -2530,9 +2531,10 @@
 }
 
 TEST_F(WebViewTest, ClientTapHandling) {
-  TapHandlingWebViewClient client;
+  TapHandlingWebWidgetClient client;
+  frame_test_helpers::TestWebViewClient view_client(&client);
   WebView* web_view =
-      web_view_helper_.InitializeAndLoad("about:blank", nullptr, &client);
+      web_view_helper_.InitializeAndLoad("about:blank", nullptr, &view_client);
   WebGestureEvent event(WebInputEvent::kGestureTap, WebInputEvent::kNoModifiers,
                         WebInputEvent::GetStaticTimeStampForTests(),
                         kWebGestureDeviceTouchscreen);
@@ -3163,11 +3165,12 @@
 
 TEST_F(WebViewTest, MiddleClickAutoscrollCursor) {
   MiddleClickAutoscrollWebWidgetClient client;
+  frame_test_helpers::TestWebViewClient view_client(&client);
   ScopedMiddleClickAutoscrollForTest middle_click_autoscroll(true);
   RegisterMockedHttpURLLoad("content-width-1000.html");
 
   WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
-      base_url_ + "content-width-1000.html", nullptr, nullptr, &client);
+      base_url_ + "content-width-1000.html", nullptr, &view_client);
   web_view->MainFrameWidget()->Resize(WebSize(100, 100));
   UpdateAllLifecyclePhases();
   RunPendingTasks();
@@ -3208,6 +3211,9 @@
   web_view->GetChromeClient().SetCursorForPlugin(WebCursorInfo(IBeamCursor()),
                                                  local_frame);
   EXPECT_EQ(IBeamCursor().GetType(), client.GetLastCursorType());
+
+  // Explicitly reset to break dependency on locally scoped client.
+  web_view_helper_.Reset();
 }
 
 static void ConfigueCompositingWebView(WebSettings* settings) {
@@ -3216,8 +3222,8 @@
 
 TEST_F(WebViewTest, ShowPressOnTransformedLink) {
   frame_test_helpers::WebViewHelper web_view_helper;
-  WebViewImpl* web_view_impl = web_view_helper.Initialize(
-      nullptr, nullptr, nullptr, &ConfigueCompositingWebView);
+  WebViewImpl* web_view_impl =
+      web_view_helper.Initialize(nullptr, nullptr, &ConfigueCompositingWebView);
 
   int page_width = 640;
   int page_height = 480;
@@ -3782,9 +3788,10 @@
 // correctly is the job of web_tests/fast/events/event-handler-count.html.
 TEST_F(WebViewTest, HasTouchEventHandlers) {
   TouchEventHandlerWebWidgetClient client;
+  frame_test_helpers::TestWebViewClient view_client(&client);
   std::string url = RegisterMockedHttpURLLoad("has_touch_event_handlers.html");
   WebViewImpl* web_view_impl =
-      web_view_helper_.InitializeAndLoad(url, nullptr, nullptr, &client);
+      web_view_helper_.InitializeAndLoad(url, nullptr, &view_client);
   const EventHandlerRegistry::EventHandlerClass kTouchEvent =
       EventHandlerRegistry::kTouchStartOrMoveEventBlocking;
 
@@ -4223,12 +4230,14 @@
   MojoTestHelper(const String& test_file,
                  frame_test_helpers::WebViewHelper& web_view_helper)
       : web_view_helper_(web_view_helper) {
-    web_view_ = web_view_helper.InitializeAndLoad(
-        WebString(test_file).Utf8(), &web_frame_client_, &web_view_client_);
+    web_view_ = web_view_helper.InitializeAndLoad(WebString(test_file).Utf8(),
+                                                  &web_frame_client_);
   }
+
   ~MojoTestHelper() {
     web_view_helper_.Reset();  // Remove dependency on locally scoped client.
   }
+
   // Bind the test API to a service with the given |name| and repeating Bind
   // method given by |callback|.
   void BindTestApi(
@@ -4245,7 +4254,6 @@
   WebViewImpl* web_view_;
   frame_test_helpers::WebViewHelper& web_view_helper_;
   frame_test_helpers::TestWebFrameClient web_frame_client_;
-  frame_test_helpers::TestWebViewClient web_view_client_;
   std::unique_ptr<service_manager::InterfaceProvider::TestApi> test_api_;
 };
 
diff --git a/third_party/blink/renderer/core/frame/browser_controls_test.cc b/third_party/blink/renderer/core/frame/browser_controls_test.cc
index 5cc681e..15588503 100644
--- a/third_party/blink/renderer/core/frame/browser_controls_test.cc
+++ b/third_party/blink/renderer/core/frame/browser_controls_test.cc
@@ -81,7 +81,7 @@
   WebViewImpl* Initialize(const std::string& page_name = "large-div.html") {
     // Load a page with large body and set viewport size to 400x400 to ensure
     // main frame is scrollable.
-    helper_.InitializeAndLoad(base_url_ + page_name, nullptr, nullptr, nullptr,
+    helper_.InitializeAndLoad(base_url_ + page_name, nullptr, nullptr,
                               &ConfigureSettings);
 
     GetWebView()->MainFrameWidget()->Resize(IntSize(400, 400));
diff --git a/third_party/blink/renderer/core/frame/frame_serializer_test.cc b/third_party/blink/renderer/core/frame/frame_serializer_test.cc
index c17c0a7..8ae1e3d 100644
--- a/third_party/blink/renderer/core/frame/frame_serializer_test.cc
+++ b/third_party/blink/renderer/core/frame/frame_serializer_test.cc
@@ -66,7 +66,7 @@
  protected:
   void SetUp() override {
     // We want the images to load.
-    helper_.Initialize(nullptr, nullptr, nullptr, &ConfigureSettings);
+    helper_.Initialize(nullptr, nullptr, &ConfigureSettings);
   }
 
   void TearDown() override {
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.cc b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
index b668cad..801a76c 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.cc
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
@@ -288,6 +288,8 @@
 WebViewHelper::WebViewHelper() : web_view_(nullptr) {}
 
 WebViewHelper::~WebViewHelper() {
+  // Close the WebViewImpl before the WebViewClient/WebWidgetClient are
+  // destroyed.
   Reset();
 }
 
@@ -295,7 +297,6 @@
     WebFrame* opener,
     TestWebFrameClient* web_frame_client,
     TestWebViewClient* web_view_client,
-    TestWebWidgetClient* test_web_widget_client,
     void (*update_settings_func)(WebSettings*)) {
   Reset();
 
@@ -312,10 +313,8 @@
 
   // TODO(dcheng): The main frame widget currently has a special case.
   // Eliminate this once WebView is no longer a WebWidget.
-  WebWidgetClient* web_widget_client = test_web_widget_client;
-  if (!web_widget_client)
-    web_widget_client = test_web_view_client_->WidgetClient();
-  blink::WebFrameWidget::CreateForMainFrame(web_widget_client, frame);
+  blink::WebFrameWidget::CreateForMainFrame(
+      test_web_view_client_->WidgetClient(), frame);
   // Set an initial size for subframes.
   if (frame->Parent())
     frame->FrameWidget()->Resize(WebSize());
@@ -326,20 +325,17 @@
 WebViewImpl* WebViewHelper::Initialize(
     TestWebFrameClient* web_frame_client,
     TestWebViewClient* web_view_client,
-    TestWebWidgetClient* web_widget_client,
     void (*update_settings_func)(WebSettings*)) {
   return InitializeWithOpener(nullptr, web_frame_client, web_view_client,
-                              web_widget_client, update_settings_func);
+                              update_settings_func);
 }
 
 WebViewImpl* WebViewHelper::InitializeAndLoad(
     const std::string& url,
     TestWebFrameClient* web_frame_client,
     TestWebViewClient* web_view_client,
-    TestWebWidgetClient* web_widget_client,
     void (*update_settings_func)(WebSettings*)) {
-  Initialize(web_frame_client, web_view_client, web_widget_client,
-             update_settings_func);
+  Initialize(web_frame_client, web_view_client, update_settings_func);
 
   LoadFrame(GetWebView()->MainFrameImpl(), url);
 
@@ -393,20 +389,17 @@
 }
 
 void WebViewHelper::Resize(WebSize size) {
-  test_web_view_client_->ClearAnimationScheduled();
   GetWebView()->MainFrameWidget()->Resize(size);
-  EXPECT_FALSE(test_web_view_client_->AnimationScheduled());
-  test_web_view_client_->ClearAnimationScheduled();
 }
 
 void WebViewHelper::InitializeWebView(TestWebViewClient* web_view_client,
                                       class WebView* opener) {
-  web_view_client =
+  test_web_view_client_ =
       CreateDefaultClientIfNeeded(web_view_client, owned_test_web_view_client_);
-  web_view_ = static_cast<WebViewImpl*>(
-      WebView::Create(web_view_client, web_view_client,
-                      /*is_hidden=*/false,
-                      /*compositing_enabled=*/true, opener));
+  web_view_ = static_cast<WebViewImpl*>(WebView::Create(
+      test_web_view_client_, test_web_view_client_->WidgetClient(),
+      /*is_hidden=*/false,
+      /*compositing_enabled=*/true, opener));
   web_view_->GetSettings()->SetJavaScriptEnabled(true);
   web_view_->GetSettings()->SetPluginsEnabled(true);
   // Enable (mocked) network loads of image URLs, as this simplifies
@@ -417,12 +410,10 @@
   web_view_->GetSettings()->SetLoadsImagesAutomatically(true);
 
   web_view_->MainFrameWidget()->SetLayerTreeView(
-      web_view_client->layer_tree_view());
+      test_web_view_client_->layer_tree_view());
   web_view_->SetDeviceScaleFactor(
-      web_view_client->GetScreenInfo().device_scale_factor);
+      test_web_view_client_->GetScreenInfo().device_scale_factor);
   web_view_->SetDefaultPageScaleLimits(1, 4);
-
-  test_web_view_client_ = web_view_client;
 }
 
 int TestWebFrameClient::loads_in_progress_ = 0;
@@ -539,7 +530,12 @@
   layer_tree_view_ = layer_tree_view_factory_.Initialize();
 }
 
-TestWebViewClient::TestWebViewClient(content::LayerTreeViewDelegate* delegate) {
+TestWebViewClient::TestWebViewClient(TestWebWidgetClient* widget_client,
+                                     content::LayerTreeViewDelegate* delegate) {
+  // NOTE: The WebWidgetClient* could possibly be |this|, so do not call any
+  // virtual methods on it here!
+  test_web_widget_client_ =
+      CreateDefaultClientIfNeeded(widget_client, owned_test_web_widget_client_);
   layer_tree_view_ = layer_tree_view_factory_.Initialize(delegate);
 }
 
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.h b/third_party/blink/renderer/core/frame/frame_test_helpers.h
index 4e5009c8..ad24426 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.h
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.h
@@ -184,29 +184,10 @@
   TestWebWidgetClient();
   ~TestWebWidgetClient() override = default;
 
-  content::LayerTreeView* layer_tree_view() { return layer_tree_view_; }
-
- private:
-  content::LayerTreeView* layer_tree_view_ = nullptr;
-  LayerTreeViewFactory layer_tree_view_factory_;
-};
-
-class TestWebViewClient : public WebViewClient, public WebWidgetClient {
- public:
-  // If no delegate is given, a stub is used.
-  explicit TestWebViewClient(content::LayerTreeViewDelegate* = nullptr);
-  ~TestWebViewClient() override = default;
-
-  content::LayerTreeView* layer_tree_view() { return layer_tree_view_; }
-
   // WebWidgetClient:
   void ScheduleAnimation() override { animation_scheduled_ = true; }
 
-  // WebViewClient:
-  bool CanHandleGestureEvent() override { return true; }
-  bool CanUpdateLayout() override { return true; }
-  WebWidgetClient* WidgetClient() override { return this; }
-  blink::WebScreenInfo GetScreenInfo() override { return {}; }
+  content::LayerTreeView* layer_tree_view() { return layer_tree_view_; }
 
   bool AnimationScheduled() { return animation_scheduled_; }
   void ClearAnimationScheduled() { animation_scheduled_ = false; }
@@ -217,6 +198,30 @@
   bool animation_scheduled_ = false;
 };
 
+class TestWebViewClient : public WebViewClient {
+ public:
+  // If no delegate is given, a stub is used. If no TestWebWidgetClient is
+  // given, an instance of TestWebWidgetClient is created and used.
+  explicit TestWebViewClient(TestWebWidgetClient* = nullptr,
+                             content::LayerTreeViewDelegate* = nullptr);
+  ~TestWebViewClient() override = default;
+
+  content::LayerTreeView* layer_tree_view() { return layer_tree_view_; }
+  TestWebWidgetClient* TestWidgetClient() { return test_web_widget_client_; }
+
+  // WebViewClient overrides.
+  bool CanHandleGestureEvent() override { return true; }
+  bool CanUpdateLayout() override { return true; }
+  WebWidgetClient* WidgetClient() override { return test_web_widget_client_; }
+  blink::WebScreenInfo GetScreenInfo() override { return {}; }
+
+ private:
+  std::unique_ptr<TestWebWidgetClient> owned_test_web_widget_client_;
+  TestWebWidgetClient* test_web_widget_client_;
+  content::LayerTreeView* layer_tree_view_ = nullptr;
+  LayerTreeViewFactory layer_tree_view_factory_;
+};
+
 // Convenience class for handling the lifetime of a WebView and its associated
 // mainframe in tests.
 class WebViewHelper {
@@ -235,13 +240,11 @@
       WebFrame* opener,
       TestWebFrameClient* = nullptr,
       TestWebViewClient* = nullptr,
-      TestWebWidgetClient* = nullptr,
       void (*update_settings_func)(WebSettings*) = nullptr);
 
   // Same as InitializeWithOpener(), but always sets the opener to null.
   WebViewImpl* Initialize(TestWebFrameClient* = nullptr,
                           TestWebViewClient* = nullptr,
-                          TestWebWidgetClient* = nullptr,
                           void (*update_settings_func)(WebSettings*) = nullptr);
 
   // Same as Initialize() but also performs the initial load of the url. Only
@@ -250,7 +253,6 @@
       const std::string& url,
       TestWebFrameClient* = nullptr,
       TestWebViewClient* = nullptr,
-      TestWebWidgetClient* = nullptr,
       void (*update_settings_func)(WebSettings*) = nullptr);
 
   // Creates and initializes the WebView with a main WebRemoteFrame. Passing
@@ -283,7 +285,6 @@
 
   WebViewImpl* web_view_;
   UseMockScrollbarSettings mock_scrollbar_settings_;
-  // Non-null if the WebViewHelper owns the TestWebViewClient.
   std::unique_ptr<TestWebViewClient> owned_test_web_view_client_;
   TestWebViewClient* test_web_view_client_;
 
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc
index 98b0b06..152e5b9e 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -2919,7 +2919,10 @@
                            LocalFrameUkmAggregator::kCompositingCommit);
 
   PaintArtifactCompositor::ViewportProperties viewport_properties;
-  viewport_properties.page_scale = page->GetVisualViewport().GetPageScaleNode();
+  const auto& viewport = page->GetVisualViewport();
+  viewport_properties.page_scale = viewport.GetPageScaleNode();
+  viewport_properties.inner_scroll_translation =
+      viewport.GetScrollTranslationNode();
 
   PaintArtifactCompositor::Settings settings;
   settings.prefer_compositing_to_lcd_text =
diff --git a/third_party/blink/renderer/core/frame/visual_viewport_test.cc b/third_party/blink/renderer/core/frame/visual_viewport_test.cc
index d17d1c7..a827875 100644
--- a/third_party/blink/renderer/core/frame/visual_viewport_test.cc
+++ b/third_party/blink/renderer/core/frame/visual_viewport_test.cc
@@ -88,8 +88,7 @@
       void (*override_settings_func)(WebSettings*) = nullptr) {
     if (!override_settings_func)
       override_settings_func = &ConfigureSettings;
-    helper_.Initialize(nullptr, &mock_web_view_client_, nullptr,
-                       override_settings_func);
+    helper_.Initialize(nullptr, &web_view_client_, override_settings_func);
     WebView()->SetDefaultPageScaleLimits(1, 4);
   }
 
@@ -97,8 +96,7 @@
       void (*override_settings_func)(WebSettings*) = nullptr) {
     if (!override_settings_func)
       override_settings_func = &ConfigureAndroidSettings;
-    helper_.Initialize(nullptr, &mock_web_view_client_, nullptr,
-                       override_settings_func);
+    helper_.Initialize(nullptr, &web_view_client_, override_settings_func);
     WebView()->SetDefaultPageScaleLimits(0.25f, 5);
   }
 
@@ -208,7 +206,7 @@
 
  protected:
   std::string base_url_;
-  frame_test_helpers::TestWebViewClient mock_web_view_client_;
+  frame_test_helpers::TestWebViewClient web_view_client_;
   frame_test_helpers::WebViewHelper helper_;
 };
 
@@ -1765,8 +1763,8 @@
 // Test that the various window.scroll and document.body.scroll properties and
 // methods don't change with the visual viewport.
 TEST_P(VisualViewportTest, visualViewportIsInert) {
-  WebViewImpl* web_view_impl = helper_.Initialize(nullptr, nullptr, nullptr,
-                                                  &ConfigureAndroidCompositing);
+  WebViewImpl* web_view_impl =
+      helper_.Initialize(nullptr, nullptr, &ConfigureAndroidCompositing);
 
   web_view_impl->MainFrameWidget()->Resize(IntSize(200, 300));
 
@@ -2118,8 +2116,8 @@
   if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
     return;
 
-  WebViewImpl* web_view_impl = helper_.Initialize(nullptr, nullptr, nullptr,
-                                                  &ConfigureAndroidCompositing);
+  WebViewImpl* web_view_impl =
+      helper_.Initialize(nullptr, nullptr, &ConfigureAndroidCompositing);
 
   int page_width = 640;
   int page_height = 480;
@@ -2192,8 +2190,8 @@
   if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
     return;
 
-  WebViewImpl* web_view_impl = helper_.Initialize(
-      nullptr, nullptr, nullptr, &ConfigureAndroidNonCompositing);
+  WebViewImpl* web_view_impl =
+      helper_.Initialize(nullptr, nullptr, &ConfigureAndroidNonCompositing);
 
   int page_width = 640;
   int page_height = 480;
@@ -2262,8 +2260,8 @@
 // Make sure a browser control resize with background-attachment:not-fixed
 // background doesn't cause invalidation or layout.
 TEST_P(VisualViewportTest, ResizeNonFixedBackgroundNoLayoutOrInvalidation) {
-  WebViewImpl* web_view_impl = helper_.Initialize(nullptr, nullptr, nullptr,
-                                                  &ConfigureAndroidCompositing);
+  WebViewImpl* web_view_impl =
+      helper_.Initialize(nullptr, nullptr, &ConfigureAndroidCompositing);
 
   int page_width = 640;
   int page_height = 480;
@@ -2325,8 +2323,8 @@
 }
 
 TEST_P(VisualViewportTest, InvalidateLayoutViewWhenDocumentSmallerThanView) {
-  WebViewImpl* web_view_impl = helper_.Initialize(nullptr, nullptr, nullptr,
-                                                  &ConfigureAndroidCompositing);
+  WebViewImpl* web_view_impl =
+      helper_.Initialize(nullptr, nullptr, &ConfigureAndroidCompositing);
 
   int page_width = 320;
   int page_height = 590;
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_base.h b/third_party/blink/renderer/core/frame/web_frame_widget_base.h
index 85f7be0..91bcfbc7 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_base.h
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_base.h
@@ -56,7 +56,6 @@
   // Called once the local root is bound via |BindLocalRoot()|.
   virtual void Initialize() = 0;
   virtual bool ForSubframe() const = 0;
-  virtual void ScheduleAnimation() = 0;
   virtual void IntrinsicSizingInfoChanged(const IntrinsicSizingInfo&) {}
   virtual base::WeakPtr<AnimationWorkletMutatorDispatcherImpl>
   EnsureCompositorMutatorDispatcher(
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
index 036997d0..fbc3fb4 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -578,15 +578,6 @@
     SetBackgroundColorOverride(Color::kTransparent);
 }
 
-void WebFrameWidgetImpl::ScheduleAnimation() {
-  if (layer_tree_view_) {
-    layer_tree_view_->SetNeedsBeginFrame();
-    return;
-  }
-  DCHECK(Client());
-  Client()->ScheduleAnimation();
-}
-
 void WebFrameWidgetImpl::IntrinsicSizingInfoChanged(
     const IntrinsicSizingInfo& sizing_info) {
   WebIntrinsicSizingInfo web_sizing_info;
@@ -891,15 +882,15 @@
       // Touch pinch zoom and scroll on the page (outside of a popup) must hide
       // the popup. In case of a touch scroll or pinch zoom, this function is
       // called with GestureTapDown rather than a GSB/GSU/GSE or GPB/GPU/GPE.
-      // When we close a popup because of a GestureTapDown, we also save it so
-      // we can prevent the following GestureTap from immediately reopening the
-      // same popup.
-      view_impl->SetLastHiddenPagePopup(view_impl->GetPagePopup());
+      // WebViewImpl takes additional steps to avoid the following GestureTap
+      // from re-opening the popup being closed here, but since GestureTap will
+      // unconditionally close the current popup here, it is not used/needed.
+      // TODO(wjmaclean): We should maybe mirror what WebViewImpl does, the
+      // HandleGestureEvent() needs to happen inside or before the GestureTap
+      // case to do so.
       View()->HidePopups();
-      FALLTHROUGH;
-    case WebInputEvent::kGestureTapCancel:
-      View()->SetLastHiddenPagePopup(nullptr);
       break;
+    case WebInputEvent::kGestureTapCancel:
     case WebInputEvent::kGestureShowPress:
       break;
     case WebInputEvent::kGestureDoubleTap:
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
index dc907a4..feb14bb 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
@@ -138,7 +138,6 @@
   void Initialize() override;
   void SetLayerTreeView(WebLayerTreeView*) override;
   bool ForSubframe() const override { return true; }
-  void ScheduleAnimation() override;
   void IntrinsicSizingInfoChanged(const IntrinsicSizingInfo&) override;
   void DidCreateLocalRootView() override;
 
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
index 5f68cec..2efe85a 100644
--- a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
+++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
@@ -178,10 +178,6 @@
   NOTREACHED();
 }
 
-void WebViewFrameWidget::ScheduleAnimation() {
-  web_view_->ScheduleAnimationForWidget();
-}
-
 base::WeakPtr<AnimationWorkletMutatorDispatcherImpl>
 WebViewFrameWidget::EnsureCompositorMutatorDispatcher(
     scoped_refptr<base::SingleThreadTaskRunner>* mutator_task_runner) {
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.h b/third_party/blink/renderer/core/frame/web_view_frame_widget.h
index 31d009a..05eb3b11 100644
--- a/third_party/blink/renderer/core/frame/web_view_frame_widget.h
+++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.h
@@ -88,7 +88,6 @@
   void Initialize() override;
   void SetLayerTreeView(WebLayerTreeView*) override;
   bool ForSubframe() const override { return false; }
-  void ScheduleAnimation() override;
   base::WeakPtr<AnimationWorkletMutatorDispatcherImpl>
   EnsureCompositorMutatorDispatcher(
       scoped_refptr<base::SingleThreadTaskRunner>*) override;
diff --git a/third_party/blink/renderer/core/html/html_table_col_element.h b/third_party/blink/renderer/core/html/html_table_col_element.h
index 1e7ff08..0d0e3a3 100644
--- a/third_party/blink/renderer/core/html/html_table_col_element.h
+++ b/third_party/blink/renderer/core/html/html_table_col_element.h
@@ -30,7 +30,7 @@
 
 namespace blink {
 
-class HTMLTableColElement final : public HTMLTablePartElement {
+class CORE_EXPORT HTMLTableColElement final : public HTMLTablePartElement {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
diff --git a/third_party/blink/renderer/core/html/media/autoplay_policy.h b/third_party/blink/renderer/core/html/media/autoplay_policy.h
index 3937336..18fbfcb 100644
--- a/third_party/blink/renderer/core/html/media/autoplay_policy.h
+++ b/third_party/blink/renderer/core/html/media/autoplay_policy.h
@@ -18,7 +18,8 @@
 class HTMLMediaElement;
 
 // AutoplayPolicy is the class for handles autoplay logics.
-class AutoplayPolicy final : public GarbageCollected<AutoplayPolicy> {
+class CORE_EXPORT AutoplayPolicy final
+    : public GarbageCollected<AutoplayPolicy> {
  public:
   // Different autoplay policy types.
   enum class Type {
@@ -33,7 +34,7 @@
     kDocumentUserActivationRequired,
   };
 
-  CORE_EXPORT static Type GetAutoplayPolicyForDocument(const Document&);
+  static Type GetAutoplayPolicyForDocument(const Document&);
 
   // Return true if the given |document| is allowed to play.
   // This method may check parent frames if allow=autoplay (Feature Policy) was
@@ -41,7 +42,7 @@
   // and so on.
   // Otherwise, frames are allowed to play if they have been activated or, for
   // the main frame, if it has a high MEI.
-  CORE_EXPORT static bool IsDocumentAllowedToPlay(const Document&);
+  static bool IsDocumentAllowedToPlay(const Document&);
 
   // Returns true if the given |document| has high media engagement.
   static bool DocumentHasHighMediaEngagement(const Document&);
@@ -86,7 +87,7 @@
 
   // Indicates the media element is or will autoplay because of being
   // muted.
-  CORE_EXPORT bool IsOrWillBeAutoplayingMuted() const;
+  bool IsOrWillBeAutoplayingMuted() const;
 
   // Unlock user gesture if a user gesture can be utilized.
   void TryUnlockingUserGesture();
diff --git a/third_party/blink/renderer/core/html/media/html_media_element_controls_list.h b/third_party/blink/renderer/core/html/media/html_media_element_controls_list.h
index e2f0d14..d7787fa9 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element_controls_list.h
+++ b/third_party/blink/renderer/core/html/media/html_media_element_controls_list.h
@@ -13,7 +13,7 @@
 
 class HTMLMediaElement;
 
-class HTMLMediaElementControlsList final : public DOMTokenList {
+class CORE_EXPORT HTMLMediaElementControlsList final : public DOMTokenList {
  public:
   static HTMLMediaElementControlsList* Create(HTMLMediaElement* element) {
     return MakeGarbageCollected<HTMLMediaElementControlsList>(element);
@@ -22,9 +22,9 @@
   explicit HTMLMediaElementControlsList(HTMLMediaElement*);
 
   // Whether the list dictates to hide a certain control.
-  CORE_EXPORT bool ShouldHideDownload() const;
-  CORE_EXPORT bool ShouldHideFullscreen() const;
-  CORE_EXPORT bool ShouldHideRemotePlayback() const;
+  bool ShouldHideDownload() const;
+  bool ShouldHideFullscreen() const;
+  bool ShouldHideRemotePlayback() const;
 
  private:
   bool ValidateTokenValue(const AtomicString&, ExceptionState&) const override;
diff --git a/third_party/blink/renderer/core/html/media/html_video_element.cc b/third_party/blink/renderer/core/html/media/html_video_element.cc
index 5eebce7..bd93b44 100644
--- a/third_party/blink/renderer/core/html/media/html_video_element.cc
+++ b/third_party/blink/renderer/core/html/media/html_video_element.cc
@@ -376,6 +376,7 @@
   } else {
     media_flags.setAlpha(0xFF);
     media_flags.setFilterQuality(kLow_SkFilterQuality);
+    media_flags.setBlendMode(SkBlendMode::kSrc);
   }
 
   GetWebMediaPlayer()->Paint(canvas, dest_rect, media_flags,
diff --git a/third_party/blink/renderer/core/html/media/html_video_element.h b/third_party/blink/renderer/core/html/media/html_video_element.h
index 9ac6f0f4..59f5b17 100644
--- a/third_party/blink/renderer/core/html/media/html_video_element.h
+++ b/third_party/blink/renderer/core/html/media/html_video_element.h
@@ -87,6 +87,8 @@
   unsigned webkitDroppedFrameCount() const;
 
   // Used by canvas to gain raw pixel access
+  //
+  // PaintFlags is optional. If unspecified, its blend mode defaults to kSrc.
   void PaintCurrentFrame(
       cc::PaintCanvas*,
       const IntRect&,
diff --git a/third_party/blink/renderer/core/html/portal/html_portal_element.h b/third_party/blink/renderer/core/html/portal/html_portal_element.h
index 6c801cc2..c43eafb 100644
--- a/third_party/blink/renderer/core/html/portal/html_portal_element.h
+++ b/third_party/blink/renderer/core/html/portal/html_portal_element.h
@@ -21,9 +21,7 @@
 // element can be used to embed another top-level browsing context, which can be
 // activated using script. The portal element is still under development and not
 // part of the HTML standard. It can be enabled by passing
-// --enable-features=Portals. See
-// https://github.com/KenjiBaheux/portals/blob/master/explainer.md for more
-// details.
+// --enable-features=Portals. See also https://github.com/WICG/portals.
 class CORE_EXPORT HTMLPortalElement : public HTMLFrameOwnerElement {
   DEFINE_WRAPPERTYPEINFO();
 
diff --git a/third_party/blink/renderer/core/html/portal/html_portal_element.idl b/third_party/blink/renderer/core/html/portal/html_portal_element.idl
index c6890dd..ba90bbd 100644
--- a/third_party/blink/renderer/core/html/portal/html_portal_element.idl
+++ b/third_party/blink/renderer/core/html/portal/html_portal_element.idl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// https://github.com/KenjiBaheux/portals/blob/master/explainer.md
+// https://wicg.github.io/portals/#the-portal-element
 
 [HTMLConstructor, RuntimeEnabled=Portals]
 interface HTMLPortalElement : HTMLElement {
diff --git a/third_party/blink/renderer/core/input/ime_on_focus_test.cc b/third_party/blink/renderer/core/input/ime_on_focus_test.cc
index 67b6913d..8a3bb14 100644
--- a/third_party/blink/renderer/core/input/ime_on_focus_test.cc
+++ b/third_party/blink/renderer/core/input/ime_on_focus_test.cc
@@ -22,10 +22,10 @@
 
 namespace blink {
 
-class ImeRequestTrackingWebViewClient
+class ImeRequestTrackingWebWidgetClient
     : public frame_test_helpers::TestWebWidgetClient {
  public:
-  ImeRequestTrackingWebViewClient() : virtual_keyboard_request_count_(0) {}
+  ImeRequestTrackingWebWidgetClient() : virtual_keyboard_request_count_(0) {}
 
   // WebWidgetClient methods
   void ShowVirtualKeyboardOnElementFocus() override {
@@ -92,12 +92,12 @@
     IntPoint tap_point,
     const AtomicString& focus_element,
     std::string frame) {
-  ImeRequestTrackingWebViewClient client;
+  ImeRequestTrackingWebWidgetClient client;
+  frame_test_helpers::TestWebViewClient view_client(&client);
   RegisterMockedURLLoadFromBase(WebString::FromUTF8(base_url_),
                                 test::CoreTestDataPath(),
                                 WebString::FromUTF8(file_name));
-  WebViewImpl* web_view =
-      web_view_helper_.Initialize(nullptr, nullptr, &client);
+  WebViewImpl* web_view = web_view_helper_.Initialize(nullptr, &view_client);
   web_view->MainFrameWidget()->Resize(WebSize(800, 1200));
   LoadFrame(web_view->MainFrameImpl(), base_url_ + file_name);
   document_ = web_view_helper_.GetWebView()
diff --git a/third_party/blink/renderer/core/input/touch_action_test.cc b/third_party/blink/renderer/core/input/touch_action_test.cc
index 453e18d8e..5cd9c4c 100644
--- a/third_party/blink/renderer/core/input/touch_action_test.cc
+++ b/third_party/blink/renderer/core/input/touch_action_test.cc
@@ -115,12 +115,13 @@
   void RunShadowDOMTest(std::string file);
   void RunIFrameTest(std::string file);
   void SendTouchEvent(WebView*, WebInputEvent::Type, IntPoint client_point);
-  WebViewImpl* SetupTest(std::string file, TouchActionTrackingWebWidgetClient&);
+  WebViewImpl* SetupTest(std::string file, TouchActionTrackingWebWidgetClient*);
   void RunTestOnTree(ContainerNode* root,
                      WebView*,
                      TouchActionTrackingWebWidgetClient&);
 
   std::string base_url_;
+  std::unique_ptr<frame_test_helpers::TestWebViewClient> web_view_client_;
   frame_test_helpers::WebViewHelper web_view_helper_;
 };
 
@@ -137,7 +138,7 @@
   // turn them into persistent, stack allocated references. This
   // workaround is sufficient to handle this artificial test
   // scenario.
-  WebViewImpl* web_view = SetupTest(file, client);
+  WebViewImpl* web_view = SetupTest(file, &client);
 
   Persistent<Document> document =
       static_cast<Document*>(web_view->MainFrameImpl()->GetDocument());
@@ -150,7 +151,7 @@
 void TouchActionTest::RunShadowDOMTest(std::string file) {
   TouchActionTrackingWebWidgetClient client;
 
-  WebViewImpl* web_view = SetupTest(file, client);
+  WebViewImpl* web_view = SetupTest(file, &client);
 
   DummyExceptionStateForTesting es;
 
@@ -178,7 +179,7 @@
 void TouchActionTest::RunIFrameTest(std::string file) {
   TouchActionTrackingWebWidgetClient client;
 
-  WebViewImpl* web_view = SetupTest(file, client);
+  WebViewImpl* web_view = SetupTest(file, &client);
   WebFrame* cur_frame = web_view->MainFrame()->FirstChild();
   ASSERT_TRUE(cur_frame);
 
@@ -196,13 +197,19 @@
 
 WebViewImpl* TouchActionTest::SetupTest(
     std::string file,
-    TouchActionTrackingWebWidgetClient& client) {
+    TouchActionTrackingWebWidgetClient* client) {
+  if (client) {
+    web_view_client_ =
+        std::make_unique<frame_test_helpers::TestWebViewClient>(client);
+  } else {
+    web_view_client_.reset();
+  }
   url_test_helpers::RegisterMockedURLLoadFromBase(
       WebString::FromUTF8(base_url_), test::CoreTestDataPath(),
       WebString::FromUTF8(file));
   // Note that JavaScript must be enabled for shadow DOM tests.
   WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(
-      base_url_ + file, nullptr, nullptr, &client);
+      base_url_ + file, nullptr, web_view_client_.get());
 
   // Set size to enable hit testing, and avoid line wrapping for consistency
   // with browser.
diff --git a/third_party/blink/renderer/core/layout/flexible_box_algorithm.h b/third_party/blink/renderer/core/layout/flexible_box_algorithm.h
index 6e0c48e..09e604c6b 100644
--- a/third_party/blink/renderer/core/layout/flexible_box_algorithm.h
+++ b/third_party/blink/renderer/core/layout/flexible_box_algorithm.h
@@ -67,6 +67,7 @@
 class FlexItem {
  public:
   // flex_base_content_size includes scrollbar width but not border or padding.
+  // min_max_sizes is the min and max size in the main axis direction.
   FlexItem(LayoutBox*,
            LayoutUnit flex_base_content_size,
            MinMaxSize min_max_sizes,
diff --git a/third_party/blink/renderer/core/layout/layout_html_canvas.h b/third_party/blink/renderer/core/layout/layout_html_canvas.h
index c3e989ed..d0d2845 100644
--- a/third_party/blink/renderer/core/layout/layout_html_canvas.h
+++ b/third_party/blink/renderer/core/layout/layout_html_canvas.h
@@ -32,7 +32,7 @@
 
 class HTMLCanvasElement;
 
-class LayoutHTMLCanvas final : public LayoutReplaced {
+class CORE_EXPORT LayoutHTMLCanvas final : public LayoutReplaced {
  public:
   explicit LayoutHTMLCanvas(HTMLCanvasElement*);
 
diff --git a/third_party/blink/renderer/core/layout/layout_list_box.h b/third_party/blink/renderer/core/layout/layout_list_box.h
index 874f7e5..10ebb01 100644
--- a/third_party/blink/renderer/core/layout/layout_list_box.h
+++ b/third_party/blink/renderer/core/layout/layout_list_box.h
@@ -37,7 +37,7 @@
 
 class HTMLSelectElement;
 
-class LayoutListBox final : public LayoutBlockFlow {
+class CORE_EXPORT LayoutListBox final : public LayoutBlockFlow {
  public:
   explicit LayoutListBox(Element*);
   ~LayoutListBox() override;
diff --git a/third_party/blink/renderer/core/layout/layout_list_marker.h b/third_party/blink/renderer/core/layout/layout_list_marker.h
index 0f53c66..69c6ed6 100644
--- a/third_party/blink/renderer/core/layout/layout_list_marker.h
+++ b/third_party/blink/renderer/core/layout/layout_list_marker.h
@@ -33,7 +33,7 @@
 
 // Used to layout the list item's marker.
 // The LayoutListMarker always has to be a child of a LayoutListItem.
-class LayoutListMarker final : public LayoutBox {
+class CORE_EXPORT LayoutListMarker final : public LayoutBox {
  public:
   static LayoutListMarker* CreateAnonymous(LayoutListItem*);
   ~LayoutListMarker() override;
@@ -42,7 +42,7 @@
   const String& GetText() const { return text_; }
 
   // Marker text with suffix, e.g. "1. ", for use in accessibility.
-  CORE_EXPORT String TextAlternative() const;
+  String TextAlternative() const;
 
   // A reduced set of list style categories allowing for more concise expression
   // of list style specific logic.
diff --git a/third_party/blink/renderer/core/layout/layout_slider.h b/third_party/blink/renderer/core/layout/layout_slider.h
index 6bfcca8..09d6282 100644
--- a/third_party/blink/renderer/core/layout/layout_slider.h
+++ b/third_party/blink/renderer/core/layout/layout_slider.h
@@ -29,14 +29,14 @@
 class HTMLInputElement;
 class SliderThumbElement;
 
-class LayoutSlider final : public LayoutFlexibleBox {
+class CORE_EXPORT LayoutSlider final : public LayoutFlexibleBox {
  public:
   static const int kDefaultTrackLength;
 
   explicit LayoutSlider(HTMLInputElement*);
   ~LayoutSlider() override;
 
-  CORE_EXPORT bool InDragMode() const;
+  bool InDragMode() const;
 
   const char* GetName() const override { return "LayoutSlider"; }
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc
index 2b3e9f6..a3f4737 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_fragment.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_space_utils.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -24,24 +25,40 @@
   container_builder_.SetIsNewFormattingContext(space.IsNewFormattingContext());
 }
 
+bool NGFlexLayoutAlgorithm::MainAxisIsInlineAxis(NGBlockNode child) {
+  return child.Style().IsHorizontalWritingMode() ==
+         FlexLayoutAlgorithm::IsHorizontalFlow(Style());
+}
+
+LayoutUnit NGFlexLayoutAlgorithm::MainAxisContentExtent(
+    LayoutUnit sum_hypothetical_main_size) {
+  if (Style().IsColumnFlexDirection()) {
+    return ComputeBlockSizeForFragment(
+               ConstraintSpace(), Style(),
+               sum_hypothetical_main_size + (borders_ + padding_).BlockSum()) -
+           border_scrollbar_padding_.BlockSum();
+  }
+  return content_box_size_.inline_size;
+}
+
 scoped_refptr<NGLayoutResult> NGFlexLayoutAlgorithm::Layout() {
-  DCHECK(!Style().IsColumnFlexDirection())
-      << "Column flexboxes aren't supported yet";
   DCHECK(!NeedMinMaxSize(ConstraintSpace(), Style()))
       << "Don't support that yet";
 
-  NGLogicalSize flex_container_border_box_size =
-      CalculateBorderBoxSize(ConstraintSpace(), Node());
-  NGBoxStrut flex_container_border_scrollbar_padding =
+  borders_ = ComputeBorders(ConstraintSpace(), Style());
+  padding_ = ComputePadding(ConstraintSpace(), Style());
+  // TODO(dgrogan): Pass padding+borders as optimization.
+  border_box_size_ = CalculateBorderBoxSize(ConstraintSpace(), Node());
+  border_scrollbar_padding_ =
       CalculateBorderScrollbarPadding(ConstraintSpace(), Node());
-  NGLogicalSize flex_container_content_box_size = ShrinkAvailableSize(
-      flex_container_border_box_size, flex_container_border_scrollbar_padding);
-  LayoutUnit flex_container_border_box_inline_size =
-      flex_container_border_box_size.inline_size;
-  LayoutUnit flex_container_content_inline_size =
-      flex_container_content_box_size.inline_size;
+  content_box_size_ =
+      ShrinkAvailableSize(border_box_size_, border_scrollbar_padding_);
 
-  FlexLayoutAlgorithm algorithm(&Style(), flex_container_content_inline_size);
+  const LayoutUnit line_break_length = MainAxisContentExtent(LayoutUnit::Max());
+  FlexLayoutAlgorithm algorithm(&Style(), line_break_length);
+  bool is_column = Style().IsColumnFlexDirection();
+  bool is_horizontal_flow = algorithm.IsHorizontalFlow();
+
   for (NGLayoutInputNode generic_child = Node().FirstChild(); generic_child;
        generic_child = generic_child.NextSibling()) {
     NGBlockNode child = ToNGBlockNode(generic_child);
@@ -49,39 +66,67 @@
       continue;
 
     const ComputedStyle& child_style = child.Style();
-    NGConstraintSpaceBuilder builder(ConstraintSpace(),
-                                     child_style.GetWritingMode(),
-                                     /* is_new_fc */ true);
-    SetOrthogonalFallbackInlineSizeIfNeeded(Style(), child, &builder);
+    NGConstraintSpaceBuilder space_builder(ConstraintSpace(),
+                                           child_style.GetWritingMode(),
+                                           /* is_new_fc */ true);
+    SetOrthogonalFallbackInlineSizeIfNeeded(Style(), child, &space_builder);
 
+    // TODO(dgrogan): Set IsShrinkToFit here when cross axis size is auto, at
+    // least for correctness. For perf, don't set it if the item will later be
+    // stretched or we won't hit the cache later.
     NGConstraintSpace child_space =
-        builder.SetAvailableSize(flex_container_content_box_size)
-            .SetPercentageResolutionSize(flex_container_content_box_size)
+        space_builder.SetAvailableSize(content_box_size_)
+            .SetPercentageResolutionSize(content_box_size_)
             .ToConstraintSpace();
 
+    NGBoxStrut border_padding_in_child_writing_mode =
+        ComputeBorders(child_space, child_style) +
+        ComputePadding(child_space, child_style);
+    NGPhysicalBoxStrut physical_border_padding(
+        border_padding_in_child_writing_mode.ConvertToPhysical(
+            child_style.GetWritingMode(), child_style.Direction()));
     LayoutUnit main_axis_border_and_padding =
-        ComputeBorders(child_space, child_style).InlineSum() +
-        ComputePadding(child_space, child_style).InlineSum();
+        is_horizontal_flow ? physical_border_padding.HorizontalSum()
+                           : physical_border_padding.VerticalSum();
+
     // ComputeMinMaxSize will layout the child if it has an orthogonal writing
     // mode. MinMaxSize will be in the container's inline direction.
     MinMaxSizeInput zero_input;
     MinMaxSize min_max_sizes_border_box = child.ComputeMinMaxSize(
         ConstraintSpace().GetWritingMode(), zero_input, &child_space);
+    // TODO(dgrogan): Don't layout every time, just when you need to.
+    scoped_refptr<NGLayoutResult> layout_result =
+        child.Layout(child_space, nullptr /*break token*/);
+    NGFragment fragment_in_child_writing_mode(
+        child_style.GetWritingMode(), *layout_result->PhysicalFragment());
 
     LayoutUnit flex_base_border_box;
-    if (child_style.FlexBasis().IsAuto() && child_style.Width().IsAuto()) {
-      flex_base_border_box = min_max_sizes_border_box.max_size;
+    Length length_in_main_axis =
+        is_horizontal_flow ? child_style.Width() : child_style.Height();
+    if (child_style.FlexBasis().IsAuto() && length_in_main_axis.IsAuto()) {
+      if (MainAxisIsInlineAxis(child))
+        flex_base_border_box = min_max_sizes_border_box.max_size;
+      else
+        flex_base_border_box = fragment_in_child_writing_mode.BlockSize();
     } else {
       Length length_to_resolve = child_style.FlexBasis();
       if (length_to_resolve.IsAuto())
-        length_to_resolve = child_style.Width();
+        length_to_resolve = length_in_main_axis;
       DCHECK(!length_to_resolve.IsAuto());
 
-      // TODO(dgrogan): Use ResolveBlockLength here for column flex boxes.
-
-      flex_base_border_box = ResolveInlineLength(
-          child_space, child_style, min_max_sizes_border_box, length_to_resolve,
-          LengthResolveType::kContentSize, LengthResolvePhase::kLayout);
+      if (MainAxisIsInlineAxis(child)) {
+        flex_base_border_box = ResolveInlineLength(
+            child_space, child_style, min_max_sizes_border_box,
+            length_to_resolve, LengthResolveType::kContentSize,
+            LengthResolvePhase::kLayout);
+      } else {
+        // Flex container's main axis is in child's block direction. Child's
+        // flex basis is in child's block direction.
+        flex_base_border_box = ResolveBlockLength(
+            child_space, child_style, length_to_resolve,
+            fragment_in_child_writing_mode.BlockSize(),
+            LengthResolveType::kContentSize, LengthResolvePhase::kLayout);
+      }
     }
 
     // Spec calls this "flex base size"
@@ -91,8 +136,11 @@
     LayoutUnit flex_base_content_size =
         flex_base_border_box - main_axis_border_and_padding;
 
-    LayoutUnit main_axis_margin =
-        ComputeMarginsForSelf(child_space, child_style).InlineSum();
+    NGPhysicalBoxStrut physical_child_margins =
+        ComputePhysicalMargins(child_space, child_style);
+    LayoutUnit main_axis_margin = is_horizontal_flow
+                                      ? physical_child_margins.HorizontalSum()
+                                      : physical_child_margins.VerticalSum();
 
     // TODO(dgrogan): When child has a min/max-{width,height} set, call
     // Resolve{Inline,Block}Length here with child's style and constraint space.
@@ -110,15 +158,17 @@
         .ng_input_node = child;
   }
 
-  LayoutUnit main_axis_offset =
-      flex_container_border_scrollbar_padding.inline_start;
-  LayoutUnit cross_axis_offset =
-      flex_container_border_scrollbar_padding.block_start;
+  LayoutUnit main_axis_offset = border_scrollbar_padding_.inline_start;
+  LayoutUnit cross_axis_offset = border_scrollbar_padding_.block_start;
+  if (is_column) {
+    main_axis_offset = border_scrollbar_padding_.block_start;
+    cross_axis_offset = border_scrollbar_padding_.inline_start;
+  }
   FlexLine* line;
-  while ((line = algorithm.ComputeNextFlexLine(
-              flex_container_border_box_inline_size))) {
-    // TODO(dgrogan): This parameter is more complicated for columns.
-    line->SetContainerMainInnerSize(flex_container_content_inline_size);
+  LayoutUnit max_main_axis_extent;
+  while ((line = algorithm.ComputeNextFlexLine(border_box_size_.inline_size))) {
+    line->SetContainerMainInnerSize(
+        MainAxisContentExtent(line->sum_hypothetical_main_size));
     line->FreezeInflexibleItems();
     while (!line->ResolveFlexibleLengths()) {
       continue;
@@ -128,23 +178,34 @@
 
       WritingMode child_writing_mode =
           flex_item.box->StyleRef().GetWritingMode();
-      NGConstraintSpaceBuilder builder(ConstraintSpace(), child_writing_mode,
-                                       /* is_new_fc */ true);
+      NGConstraintSpaceBuilder space_builder(ConstraintSpace(),
+                                             child_writing_mode,
+                                             /* is_new_fc */ true);
       SetOrthogonalFallbackInlineSizeIfNeeded(Style(), flex_item.ng_input_node,
-                                              &builder);
+                                              &space_builder);
 
-      NGLogicalSize available_size(flex_item.flexed_content_size +
-                                       flex_item.main_axis_border_and_padding,
-                                   flex_container_content_box_size.block_size);
-      builder.SetAvailableSize(available_size);
-      builder.SetPercentageResolutionSize(flex_container_content_box_size);
-      builder.SetIsFixedSizeInline(true);
-      NGConstraintSpace child_space = builder.ToConstraintSpace();
+      NGLogicalSize available_size;
+      if (is_column) {
+        available_size.inline_size = content_box_size_.inline_size;
+        available_size.block_size = flex_item.flexed_content_size +
+                                    flex_item.main_axis_border_and_padding;
+        space_builder.SetIsFixedSizeBlock(true);
+      } else {
+        available_size.inline_size = flex_item.flexed_content_size +
+                                     flex_item.main_axis_border_and_padding;
+        available_size.block_size = content_box_size_.block_size;
+        space_builder.SetIsFixedSizeInline(true);
+      }
+      space_builder.SetAvailableSize(available_size);
+      space_builder.SetPercentageResolutionSize(content_box_size_);
+      NGConstraintSpace child_space = space_builder.ToConstraintSpace();
       flex_item.layout_result =
           ToNGBlockNode(flex_item.ng_input_node)
               .Layout(child_space, nullptr /*break token*/);
       flex_item.cross_axis_size =
-          flex_item.layout_result->PhysicalFragment()->Size().height;
+          is_horizontal_flow
+              ? flex_item.layout_result->PhysicalFragment()->Size().height
+              : flex_item.layout_result->PhysicalFragment()->Size().width;
       // TODO(dgrogan): Port logic from
       // LayoutFlexibleBox::CrossAxisIntrinsicExtentForChild?
       flex_item.cross_axis_intrinsic_size = flex_item.cross_axis_size;
@@ -152,27 +213,28 @@
     // cross_axis_offset is updated in each iteration of the loop, for passing
     // in to the next iteration.
     line->ComputeLineItemsPosition(main_axis_offset, cross_axis_offset);
-
-
-    // TODO(dgrogan): For column flex containers, keep track of tallest flex
-    // line and pass to ComputeBlockSizeForFragment as content_size.
+    max_main_axis_extent =
+        std::max(max_main_axis_extent, line->main_axis_extent);
   }
   LayoutUnit intrinsic_block_content_size = cross_axis_offset;
+  if (is_column)
+    intrinsic_block_content_size = max_main_axis_extent;
   LayoutUnit intrinsic_block_size =
-      intrinsic_block_content_size +
-      flex_container_border_scrollbar_padding.BlockSum();
+      intrinsic_block_content_size + border_scrollbar_padding_.BlockSum();
   LayoutUnit block_size = ComputeBlockSizeForFragment(
       ConstraintSpace(), Style(), intrinsic_block_size);
 
   // Apply stretch alignment.
   // TODO(dgrogan): Move this to its own method, which means making some of the
   // container-specific local variables into data members.
-  // TODO(dgrogan): Change this to final_content_cross_size when column
-  // flexboxes are supported.
-  LayoutUnit final_content_block_size =
-      block_size - flex_container_border_scrollbar_padding.BlockSum();
+  LayoutUnit final_content_cross_size =
+      block_size - border_scrollbar_padding_.BlockSum();
+  if (is_column) {
+    final_content_cross_size =
+        border_box_size_.inline_size - border_scrollbar_padding_.InlineSum();
+  }
   if (!algorithm.IsMultiline() && !algorithm.FlexLines().IsEmpty())
-    algorithm.FlexLines()[0].cross_axis_extent = final_content_block_size;
+    algorithm.FlexLines()[0].cross_axis_extent = final_content_cross_size;
 
   for (FlexLine& line_context : algorithm.FlexLines()) {
     for (wtf_size_t child_number = 0;
@@ -183,19 +245,22 @@
 
         WritingMode child_writing_mode =
             flex_item.box->StyleRef().GetWritingMode();
-        NGConstraintSpaceBuilder builder(ConstraintSpace(), child_writing_mode,
-                                         /* is_new_fc */ true);
+        NGConstraintSpaceBuilder space_builder(ConstraintSpace(),
+                                               child_writing_mode,
+                                               /* is_new_fc */ true);
         SetOrthogonalFallbackInlineSizeIfNeeded(
-            Style(), flex_item.ng_input_node, &builder);
+            Style(), flex_item.ng_input_node, &space_builder);
 
         NGLogicalSize available_size(flex_item.flexed_content_size +
                                          flex_item.main_axis_border_and_padding,
                                      flex_item.cross_axis_size);
-        builder.SetAvailableSize(available_size);
-        builder.SetPercentageResolutionSize(flex_container_content_box_size);
-        builder.SetIsFixedSizeInline(true);
-        builder.SetIsFixedSizeBlock(true);
-        NGConstraintSpace child_space = builder.ToConstraintSpace();
+        if (is_column)
+          available_size.Flip();
+        space_builder.SetAvailableSize(available_size);
+        space_builder.SetPercentageResolutionSize(content_box_size_);
+        space_builder.SetIsFixedSizeInline(true);
+        space_builder.SetIsFixedSizeBlock(true);
+        NGConstraintSpace child_space = space_builder.ToConstraintSpace();
         flex_item.layout_result =
             ToNGBlockNode(flex_item.ng_input_node)
                 .Layout(child_space, /* break_token */ nullptr);
@@ -207,7 +272,7 @@
   }
 
   container_builder_.SetBlockSize(block_size);
-  container_builder_.SetInlineSize(flex_container_border_box_inline_size);
+  container_builder_.SetInlineSize(border_box_size_.inline_size);
   container_builder_.SetBorders(ComputeBorders(ConstraintSpace(), Style()));
   container_builder_.SetPadding(ComputePadding(ConstraintSpace(), Style()));
   return container_builder_.ToBoxFragment();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h
index bdea54d..44d9263 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.h
@@ -29,6 +29,18 @@
 
   base::Optional<MinMaxSize> ComputeMinMaxSize(
       const MinMaxSizeInput&) const override;
+
+ private:
+  // This is same method as FlexItem but we need that logic before FlexItem is
+  // constructed.
+  bool MainAxisIsInlineAxis(NGBlockNode child);
+  LayoutUnit MainAxisContentExtent(LayoutUnit sum_hypothetical_main_size);
+
+  NGLogicalSize border_box_size_;
+  NGBoxStrut border_scrollbar_padding_;
+  NGLogicalSize content_box_size_;
+  NGBoxStrut borders_;
+  NGBoxStrut padding_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/ng_length_utils.h b/third_party/blink/renderer/core/layout/ng/ng_length_utils.h
index 20bb742..6127283b 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_length_utils.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_length_utils.h
@@ -130,10 +130,11 @@
     NGLayoutInputNode child,
     const MinMaxSizeInput& input);
 
-// Resolves the computed value in style.logicalWidth (Length) to a layout unit,
-// then constrains the result by the resolved min logical width and max logical
-// width from the ComputedStyle object. Calls Node::ComputeMinMaxSize if needed.
-// override_minmax is provided *solely* for use by unit tests.
+// Returns inline size of the node's border box by resolving the computed value
+// in style.logicalWidth (Length) to a layout unit, adding border and padding,
+// then constraining the result by the resolved min logical width and max
+// logical width from the ComputedStyle object. Calls Node::ComputeMinMaxSize if
+// needed. override_minmax is provided *solely* for use by unit tests.
 // border_padding can be passed in as an optimization; otherwise this function
 // will compute it itself.
 CORE_EXPORT LayoutUnit ComputeInlineSizeForFragment(
diff --git a/third_party/blink/renderer/core/layout/scrollbars_test.cc b/third_party/blink/renderer/core/layout/scrollbars_test.cc
index 2d23ebb..e23b26b 100644
--- a/third_party/blink/renderer/core/layout/scrollbars_test.cc
+++ b/third_party/blink/renderer/core/layout/scrollbars_test.cc
@@ -180,14 +180,17 @@
               layout_viewport->HorizontalScrollbar());
 }
 
-class ScrollbarsWebViewClient : public frame_test_helpers::TestWebViewClient {
+class ScrollbarsWebWidgetClient
+    : public frame_test_helpers::TestWebWidgetClient {
  public:
+  // WebWidgetClient overrides.
   void ConvertWindowToViewport(WebFloatRect* rect) override {
     rect->x *= device_scale_factor_;
     rect->y *= device_scale_factor_;
     rect->width *= device_scale_factor_;
     rect->height *= device_scale_factor_;
   }
+
   void set_device_scale_factor(float device_scale_factor) {
     device_scale_factor_ = device_scale_factor;
   }
@@ -197,12 +200,13 @@
 };
 
 TEST_F(ScrollbarsTest, ScrollbarSizeForUseZoomDSF) {
-  ScrollbarsWebViewClient client;
+  ScrollbarsWebWidgetClient client;
+  frame_test_helpers::TestWebViewClient view_client(&client);
   client.set_device_scale_factor(1.f);
 
   frame_test_helpers::WebViewHelper web_view_helper;
   WebViewImpl* web_view_impl =
-      web_view_helper.Initialize(nullptr, &client, nullptr, nullptr);
+      web_view_helper.Initialize(nullptr, &view_client);
 
   // Needed so visual viewport supplies its own scrollbars.
   web_view_impl->GetSettings()->SetViewportEnabled(true);
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.cc b/third_party/blink/renderer/core/page/chrome_client_impl.cc
index 38d9935..ce4e12b 100644
--- a/third_party/blink/renderer/core/page/chrome_client_impl.cc
+++ b/third_party/blink/renderer/core/page/chrome_client_impl.cc
@@ -416,7 +416,10 @@
   // WebFrameWidget needs to be initialized before initializing the core frame?
   if (!web_frame->LocalRootFrameWidget())
     return;
-  web_frame->LocalRootFrameWidget()->ScheduleAnimation();
+  // LocalRootFrameWidget() is a WebWidget, its client is the embedder.
+  WebWidgetClient* web_widget_client =
+      web_frame->LocalRootFrameWidget()->Client();
+  web_widget_client->ScheduleAnimation();
 }
 
 IntRect ChromeClientImpl::ViewportToScreen(
@@ -933,10 +936,10 @@
 
 void ChromeClientImpl::BeginLifecycleUpdates() {
   web_view_->StopDeferringCommits();
-
-  if (WebLayerTreeView* tree_view = web_view_->LayerTreeView()) {
-    tree_view->SetNeedsBeginFrame();
-  }
+  // The WidgetClient is null for some WebViews, in which case they can not
+  // composite.
+  if (web_view_->WidgetClient())
+    web_view_->WidgetClient()->ScheduleAnimation();
 }
 
 cc::EventListenerProperties ChromeClientImpl::EventListenerProperties(
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl_test.cc b/third_party/blink/renderer/core/page/chrome_client_impl_test.cc
index ed4769d..da6c5b4 100644
--- a/third_party/blink/renderer/core/page/chrome_client_impl_test.cc
+++ b/third_party/blink/renderer/core/page/chrome_client_impl_test.cc
@@ -53,21 +53,6 @@
 
 namespace blink {
 
-namespace {
-
-class TestWebViewClient : public frame_test_helpers::TestWebViewClient {
- public:
-  explicit TestWebViewClient(WebNavigationPolicy* target) : target_(target) {}
-  ~TestWebViewClient() override = default;
-
-  void Show(WebNavigationPolicy policy) override { *target_ = policy; }
-
- private:
-  WebNavigationPolicy* target_;
-};
-
-}  // anonymous namespace
-
 class ViewCreatingClient : public frame_test_helpers::TestWebViewClient {
  public:
   WebView* CreateView(WebLocalFrame* opener,
diff --git a/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc b/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
index 8a36b16e..4a7dbdc 100644
--- a/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
@@ -79,7 +79,7 @@
   }
 
   WebViewImpl* Initialize(const std::string& page_name,
-                          frame_test_helpers::TestWebViewClient* client) {
+                          frame_test_helpers::TestWebWidgetClient* client) {
     return InitializeInternal(base_url_ + page_name, client);
   }
 
@@ -178,8 +178,14 @@
 
   WebViewImpl* InitializeInternal(
       const std::string& url,
-      frame_test_helpers::TestWebViewClient* client) {
-    helper_.InitializeAndLoad(url, nullptr, client, nullptr,
+      frame_test_helpers::TestWebWidgetClient* client) {
+    if (client) {
+      view_client_ =
+          std::make_unique<frame_test_helpers::TestWebViewClient>(client);
+    } else {
+      view_client_.reset();
+    }
+    helper_.InitializeAndLoad(url, nullptr, view_client_.get(),
                               &ConfigureSettings);
 
     // Initialize browser controls to be shown.
@@ -197,6 +203,7 @@
   }
 
   std::string base_url_;
+  std::unique_ptr<frame_test_helpers::TestWebViewClient> view_client_;
   frame_test_helpers::WebViewHelper helper_;
   RuntimeEnabledFeatures::Backup features_backup_;
 };
@@ -235,8 +242,8 @@
             EffectiveRootScroller(MainFrame()->GetDocument()));
 }
 
-class OverscrollTestWebViewClient
-    : public frame_test_helpers::TestWebViewClient {
+class OverscrollTestWebWidgetClient
+    : public frame_test_helpers::TestWebWidgetClient {
  public:
   MOCK_METHOD5(DidOverscroll,
                void(const WebFloatSize&,
@@ -249,7 +256,7 @@
 // Tests that setting an element as the root scroller causes it to control url
 // bar hiding and overscroll.
 TEST_F(RootScrollerTest, TestSetRootScroller) {
-  OverscrollTestWebViewClient client;
+  OverscrollTestWebWidgetClient client;
   Initialize("root-scroller.html", &client);
 
   Element* container = MainFrame()->GetDocument()->getElementById("container");
diff --git a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc
index 220adff..feb1251 100644
--- a/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc
@@ -72,7 +72,7 @@
   ScrollingCoordinatorTest()
       : ScopedPaintTouchActionRectsForTest(GetParam()),
         base_url_("http://www.test.com/") {
-    helper_.Initialize(nullptr, nullptr, nullptr, &ConfigureSettings);
+    helper_.Initialize(nullptr, nullptr, &ConfigureSettings);
     GetWebView()->MainFrameWidget()->Resize(IntSize(320, 240));
 
     // macOS attaches main frame scrollbars to the VisualViewport so the
diff --git a/third_party/blink/renderer/core/page/spatial_navigation_test.cc b/third_party/blink/renderer/core/page/spatial_navigation_test.cc
index ca2fdfb..132a6d2 100644
--- a/third_party/blink/renderer/core/page/spatial_navigation_test.cc
+++ b/third_party/blink/renderer/core/page/spatial_navigation_test.cc
@@ -611,7 +611,7 @@
 
 TEST_F(SpatialNavigationTest, HasRemoteFrame) {
   frame_test_helpers::WebViewHelper helper;
-  helper.InitializeAndLoad("about:blank", nullptr, nullptr, nullptr, nullptr);
+  helper.InitializeAndLoad("about:blank");
 
   WebViewImpl* webview = helper.GetWebView();
   WebURL base_url = url_test_helpers::ToKURL("http://www.test.com/");
diff --git a/third_party/blink/renderer/core/page/viewport_test.cc b/third_party/blink/renderer/core/page/viewport_test.cc
index 5049147..ad676013 100644
--- a/third_party/blink/renderer/core/page/viewport_test.cc
+++ b/third_party/blink/renderer/core/page/viewport_test.cc
@@ -120,8 +120,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-1.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -139,8 +138,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-2.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -158,8 +156,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-3.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -177,8 +174,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-4.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -196,8 +192,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-5.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -215,8 +210,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-6.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -234,8 +228,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-7.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -253,8 +246,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-8.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -272,8 +264,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-9.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -291,8 +282,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-10.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -310,8 +300,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-11.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -329,8 +318,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-12.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -348,8 +336,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-13.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -367,8 +354,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-14.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -386,8 +372,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-15.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -405,8 +390,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-16.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -424,8 +408,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-17.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -443,8 +426,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-18.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -462,8 +444,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-19.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -481,8 +462,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-20.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -500,8 +480,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-21.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -519,8 +498,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-22.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -538,8 +516,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-23.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -557,8 +534,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-24.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -576,8 +552,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-25.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -595,8 +570,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-26.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -614,8 +588,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-27.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -633,8 +606,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-28.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -652,8 +624,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-29.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -671,8 +642,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-30.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -690,8 +660,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-31.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -709,8 +678,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-32.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -728,8 +696,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-33.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -747,8 +714,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-34.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -766,8 +732,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-35.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -785,8 +750,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-36.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -804,8 +768,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-37.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -823,8 +786,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-38.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -842,8 +804,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-39.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -861,8 +822,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-40.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -880,8 +840,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-41.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -899,8 +858,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-42.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -918,8 +876,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-43.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -937,8 +894,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-44.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -956,8 +912,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-45.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -975,8 +930,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-46.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -994,8 +948,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-47.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1013,8 +966,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-48.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1032,8 +984,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-49.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1051,8 +1002,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-50.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1070,8 +1020,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-51.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1089,8 +1038,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-52.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1108,8 +1056,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-53.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1127,8 +1074,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-54.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1146,8 +1092,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-55.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1165,8 +1110,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-56.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1184,8 +1128,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-57.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1203,8 +1146,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-58.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1222,8 +1164,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-59.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1241,8 +1182,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-60.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1260,8 +1200,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-61.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1279,8 +1218,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-62.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1298,8 +1236,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-63.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1317,8 +1254,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-64.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1336,8 +1272,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-65.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1355,8 +1290,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-66.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1374,8 +1308,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-67.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1393,8 +1326,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-68.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1412,8 +1344,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-69.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1431,8 +1362,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-70.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1450,8 +1380,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-71.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1469,8 +1398,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-72.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1488,8 +1416,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-73.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1507,8 +1434,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-74.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1526,8 +1452,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-75.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1545,8 +1470,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-76.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1564,8 +1488,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-77.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1583,8 +1506,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-78.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1602,8 +1524,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-79.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1621,8 +1542,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-80.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1640,8 +1560,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-81.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1659,8 +1578,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-82.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1678,8 +1596,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-83.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1697,8 +1614,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-84.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1716,8 +1632,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-85.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1735,8 +1650,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-86.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1754,8 +1668,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-87.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1773,8 +1686,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-88.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1792,8 +1704,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-90.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1811,8 +1722,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-100.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1830,8 +1740,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-101.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1849,8 +1758,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-102.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1868,8 +1776,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-103.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1887,8 +1794,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-104.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1906,8 +1812,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-105.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1925,8 +1830,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-106.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1944,8 +1848,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-107.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1963,8 +1866,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-108.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -1982,8 +1884,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-109.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2001,8 +1902,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-110.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2020,8 +1920,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-111.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2039,8 +1938,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-112.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2058,8 +1956,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-113.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2077,8 +1974,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-114.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2096,8 +1992,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-115.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2115,8 +2010,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-116.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2134,8 +2028,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-117.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2153,8 +2046,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-118.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2172,8 +2064,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-119.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2191,8 +2082,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-120.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2210,8 +2100,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-121.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2229,8 +2118,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-122.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2248,8 +2136,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-123.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2267,8 +2154,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-124.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2286,8 +2172,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-125.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2305,8 +2190,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-126.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2324,8 +2208,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-127.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2343,8 +2226,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-129.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2362,8 +2244,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-130.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2381,8 +2262,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-131.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2400,8 +2280,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-132.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2419,8 +2298,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-133.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2438,8 +2316,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-134.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2457,8 +2334,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-135.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2476,8 +2352,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-136.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2495,8 +2370,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-137.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2514,8 +2388,7 @@
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-138.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2534,7 +2407,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-handheldfriendly.html", nullptr,
-      nullptr, nullptr, SetViewportSettings);
+      nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2560,7 +2433,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-merge-quirk-1.html", nullptr,
-      nullptr, nullptr, SetQuirkViewportSettings);
+      nullptr, SetQuirkViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2579,7 +2452,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-merge-quirk-2.html", nullptr,
-      nullptr, nullptr, SetQuirkViewportSettings);
+      nullptr, SetQuirkViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
 
@@ -2601,7 +2474,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-mobileoptimized.html", nullptr,
-      nullptr, nullptr, SetViewportSettings);
+      nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
 
@@ -2621,7 +2494,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-mobileoptimized-2.html", nullptr,
-      nullptr, nullptr, SetViewportSettings);
+      nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
 
@@ -2641,7 +2514,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-mobileoptimized-2.html", nullptr,
-      nullptr, nullptr, SetViewportSettings);
+      nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
 
@@ -2661,7 +2534,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-ordering-2.html", nullptr, nullptr,
-      nullptr, SetViewportSettings);
+      SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
 
@@ -2681,7 +2554,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-ordering-3.html", nullptr, nullptr,
-      nullptr, SetViewportSettings);
+      SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
 
@@ -2701,7 +2574,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-ordering-4.html", nullptr, nullptr,
-      nullptr, SetViewportSettings);
+      SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
 
@@ -2721,7 +2594,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-ordering-5.html", nullptr, nullptr,
-      nullptr, SetViewportSettings);
+      SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
 
@@ -2741,7 +2614,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-ordering-6.html", nullptr, nullptr,
-      nullptr, SetViewportSettings);
+      SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
 
@@ -2761,7 +2634,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-ordering-7.html", nullptr, nullptr,
-      nullptr, SetViewportSettings);
+      SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
 
@@ -2781,7 +2654,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-ordering-8.html", nullptr, nullptr,
-      nullptr, SetViewportSettings);
+      SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
 
@@ -2801,7 +2674,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-ordering-10.html", nullptr, nullptr,
-      nullptr, SetViewportSettings);
+      SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 800, 600);
@@ -2815,7 +2688,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-xhtmlmp.html", nullptr, nullptr,
-      nullptr, SetViewportSettings);
+      SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2836,7 +2709,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-xhtmlmp-misplaced-doctype.html",
-      nullptr, nullptr, nullptr, SetViewportSettings);
+      nullptr, nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2855,7 +2728,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-xhtmlmp-ordering.html", nullptr,
-      nullptr, nullptr, SetViewportSettings);
+      nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2874,7 +2747,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-xhtmlmp.html", nullptr, nullptr,
-      nullptr, SetViewportSettings);
+      SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -2919,7 +2792,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-limits-adjusted-for-no-user-scale.html",
-      nullptr, nullptr, nullptr, SetViewportSettings);
+      nullptr, nullptr, SetViewportSettings);
 
   web_view_helper.GetWebView()->MainFrameWidget()->UpdateAllLifecyclePhases(
       WebWidget::LifecycleUpdateReason::kTest);
@@ -2938,7 +2811,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-limits-adjusted-for-user-scale.html",
-      nullptr, nullptr, nullptr, SetViewportSettings);
+      nullptr, nullptr, SetViewportSettings);
   web_view_helper.GetWebView()->MainFrameWidget()->UpdateAllLifecyclePhases(
       WebWidget::LifecycleUpdateReason::kTest);
   Page* page = web_view_helper.GetWebView()->GetPage();
@@ -2957,7 +2830,7 @@
   web_view_helper.InitializeAndLoad(
       base_url_ +
           "viewport/viewport-gpu-rasterization-disabled-without-viewport.html",
-      nullptr, nullptr, nullptr, SetViewportSettings);
+      nullptr, nullptr, SetViewportSettings);
   web_view_helper.GetWebView()->MainFrameWidget()->Resize(WebSize(640, 480));
   EXPECT_FALSE(web_view_helper.GetWebView()
                    ->MatchesHeuristicsForGpuRasterizationForTesting());
@@ -2973,7 +2846,7 @@
   RegisterMockedHttpURLLoad("viewport/viewport-gpu-rasterization.html");
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-gpu-rasterization.html", nullptr, nullptr,
-      nullptr, SetViewportSettings);
+      SetViewportSettings);
   web_view_helper.GetWebView()->MainFrameWidget()->Resize(WebSize(640, 480));
   EXPECT_TRUE(web_view_helper.GetWebView()
                   ->MatchesHeuristicsForGpuRasterizationForTesting());
@@ -2983,31 +2856,28 @@
   web_view_helper.InitializeAndLoad(
       base_url_ +
           "viewport/viewport-gpu-rasterization-expanded-heuristics.html",
-      nullptr, nullptr, nullptr, SetViewportSettings);
+      nullptr, nullptr, SetViewportSettings);
   web_view_helper.GetWebView()->MainFrameWidget()->Resize(WebSize(640, 480));
   EXPECT_TRUE(web_view_helper.GetWebView()
                   ->MatchesHeuristicsForGpuRasterizationForTesting());
 
   RegisterMockedHttpURLLoad("viewport/viewport-1.html");
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-1.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
   web_view_helper.GetWebView()->MainFrameWidget()->Resize(WebSize(640, 480));
   EXPECT_TRUE(web_view_helper.GetWebView()
                   ->MatchesHeuristicsForGpuRasterizationForTesting());
 
   RegisterMockedHttpURLLoad("viewport/viewport-15.html");
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-15.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
   web_view_helper.GetWebView()->MainFrameWidget()->Resize(WebSize(640, 480));
   EXPECT_TRUE(web_view_helper.GetWebView()
                   ->MatchesHeuristicsForGpuRasterizationForTesting());
 
   RegisterMockedHttpURLLoad("viewport/viewport-130.html");
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-130.html",
-                                    nullptr, nullptr, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, nullptr, SetViewportSettings);
   web_view_helper.GetWebView()->MainFrameWidget()->Resize(WebSize(640, 480));
   EXPECT_TRUE(web_view_helper.GetWebView()
                   ->MatchesHeuristicsForGpuRasterizationForTesting());
@@ -3015,7 +2885,7 @@
   RegisterMockedHttpURLLoad("viewport/viewport-legacy-handheldfriendly.html");
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-handheldfriendly.html", nullptr,
-      nullptr, nullptr, SetViewportSettings);
+      nullptr, SetViewportSettings);
   web_view_helper.GetWebView()->MainFrameWidget()->Resize(WebSize(640, 480));
   EXPECT_TRUE(web_view_helper.GetWebView()
                   ->MatchesHeuristicsForGpuRasterizationForTesting());
@@ -3023,7 +2893,7 @@
   RegisterMockedHttpURLLoad("viewport/viewport-legacy-mobileoptimized.html");
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-handheldfriendly.html", nullptr,
-      nullptr, nullptr, SetViewportSettings);
+      nullptr, SetViewportSettings);
   web_view_helper.GetWebView()->MainFrameWidget()->Resize(WebSize(640, 480));
   EXPECT_TRUE(web_view_helper.GetWebView()
                   ->MatchesHeuristicsForGpuRasterizationForTesting());
@@ -3050,7 +2920,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-warnings-1.html", &web_frame_client,
-      nullptr, nullptr, SetViewportSettings);
+      nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -3073,7 +2943,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-warnings-2.html", &web_frame_client,
-      nullptr, nullptr, SetViewportSettings);
+      nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -3100,7 +2970,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-warnings-3.html", &web_frame_client,
-      nullptr, nullptr, SetViewportSettings);
+      nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -3129,7 +2999,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-warnings-4.html", &web_frame_client,
-      nullptr, nullptr, SetViewportSettings);
+      nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -3158,7 +3028,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-warnings-5.html", &web_frame_client,
-      nullptr, nullptr, SetViewportSettings);
+      nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -3188,7 +3058,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-warnings-6.html", &web_frame_client,
-      nullptr, nullptr, SetViewportSettings);
+      nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   PageScaleConstraints constraints = RunViewportTest(page, 320, 352);
@@ -3216,7 +3086,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-warnings-7.html", &web_frame_client,
-      nullptr, nullptr, SetViewportSettings);
+      nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   RunViewportTest(page, 320, 352);
@@ -3232,7 +3102,7 @@
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-warnings-8.html", &web_frame_client,
-      nullptr, nullptr, SetViewportSettings);
+      nullptr, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   RunViewportTest(page, 320, 352);
@@ -3240,32 +3110,34 @@
   EXPECT_EQ(0U, web_frame_client.messages.size());
 }
 
-class ViewportClient : public frame_test_helpers::TestWebViewClient {
+class ViewportClient : public frame_test_helpers::TestWebWidgetClient {
  public:
-  ViewportClient() : device_scale_factor_(1.f) {}
+  // WebWidgetClient overrides.
   void ConvertWindowToViewport(WebFloatRect* rect) override {
     rect->x *= device_scale_factor_;
     rect->y *= device_scale_factor_;
     rect->width *= device_scale_factor_;
     rect->height *= device_scale_factor_;
   }
+
   void set_device_scale_factor(float device_scale_factor) {
     device_scale_factor_ = device_scale_factor;
   }
 
  private:
-  float device_scale_factor_;
+  float device_scale_factor_ = 1.f;
 };
 
 TEST_F(ViewportTest, viewportUseZoomForDSF1) {
   ViewportClient client;
+  frame_test_helpers::TestWebViewClient view_client(&client);
   client.set_device_scale_factor(3);
   RegisterMockedHttpURLLoad("viewport/viewport-legacy-merge-quirk-1.html");
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-merge-quirk-1.html", nullptr,
-      &client, nullptr, SetQuirkViewportSettings);
+      &view_client, SetQuirkViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   // Initial width and height must be scaled by DSF when --use-zoom-for-dsf
@@ -3286,13 +3158,14 @@
 
 TEST_F(ViewportTest, viewportUseZoomForDSF2) {
   ViewportClient client;
+  frame_test_helpers::TestWebViewClient view_client(&client);
   client.set_device_scale_factor(3);
   RegisterMockedHttpURLLoad("viewport/viewport-legacy-merge-quirk-2.html");
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(
       base_url_ + "viewport/viewport-legacy-merge-quirk-2.html", nullptr,
-      &client, nullptr, SetQuirkViewportSettings);
+      &view_client, SetQuirkViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
 
@@ -3316,13 +3189,13 @@
 
 TEST_F(ViewportTest, viewportUseZoomForDSF3) {
   ViewportClient client;
+  frame_test_helpers::TestWebViewClient view_client(&client);
   client.set_device_scale_factor(3);
   RegisterMockedHttpURLLoad("viewport/viewport-48.html");
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-48.html",
-                                    nullptr, &client, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, &view_client, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   // Initial width and height must be scaled by DSF when --use-zoom-for-dsf
@@ -3341,13 +3214,13 @@
 
 TEST_F(ViewportTest, viewportUseZoomForDSF4) {
   ViewportClient client;
+  frame_test_helpers::TestWebViewClient view_client(&client);
   client.set_device_scale_factor(3);
   RegisterMockedHttpURLLoad("viewport/viewport-39.html");
 
   frame_test_helpers::WebViewHelper web_view_helper;
   web_view_helper.InitializeAndLoad(base_url_ + "viewport/viewport-39.html",
-                                    nullptr, &client, nullptr,
-                                    SetViewportSettings);
+                                    nullptr, &view_client, SetViewportSettings);
 
   Page* page = web_view_helper.GetWebView()->GetPage();
   // Initial width and height must be scaled by DSF when --use-zoom-for-dsf
diff --git a/third_party/blink/renderer/core/resize_observer/resize_observer_entry.h b/third_party/blink/renderer/core/resize_observer/resize_observer_entry.h
index 27a6223..379cc05 100644
--- a/third_party/blink/renderer/core/resize_observer/resize_observer_entry.h
+++ b/third_party/blink/renderer/core/resize_observer/resize_observer_entry.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_RESIZE_OBSERVER_RESIZE_OBSERVER_ENTRY_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_RESIZE_OBSERVER_RESIZE_OBSERVER_ENTRY_H_
 
+#include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
@@ -14,7 +15,7 @@
 class DOMRectReadOnly;
 class LayoutRect;
 
-class ResizeObserverEntry final : public ScriptWrappable {
+class CORE_EXPORT ResizeObserverEntry final : public ScriptWrappable {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
diff --git a/third_party/blink/renderer/core/testing/sim/sim_compositor.cc b/third_party/blink/renderer/core/testing/sim/sim_compositor.cc
index 7881ce55a..39c4646 100644
--- a/third_party/blink/renderer/core/testing/sim/sim_compositor.cc
+++ b/third_party/blink/renderer/core/testing/sim/sim_compositor.cc
@@ -30,10 +30,13 @@
 }
 
 void SimCompositor::SetWebView(WebViewImpl& web_view,
-                               content::LayerTreeView& layer_tree_view) {
+                               content::LayerTreeView& layer_tree_view,
+                               frame_test_helpers::TestWebViewClient& client) {
   web_view_ = &web_view;
   layer_tree_view_ = &layer_tree_view;
   DCHECK_EQ(&layer_tree_view, web_view_->LayerTreeView());
+  test_web_view_client_ = &client;
+  DCHECK_EQ(test_web_view_client_, web_view_->Client());
 
   // SimCompositor starts with defer commits enabled, but uses synchronous
   // compositing which does not use defer commits anyhow, it only uses it for
@@ -44,9 +47,13 @@
 SimCanvas::Commands SimCompositor::BeginFrame(double time_delta_in_seconds) {
   DCHECK(web_view_);
   DCHECK(!layer_tree_view_->layer_tree_host()->defer_main_frame_update());
-  DCHECK(layer_tree_view_->layer_tree_host()->RequestedMainFramePending());
+  // Verify that the need for a BeginMainFrame has been registered, and would
+  // have caused the compositor to schedule one if we were using its scheduler.
+  DCHECK(NeedsBeginFrame());
   DCHECK_GT(time_delta_in_seconds, 0);
 
+  test_web_view_client_->TestWidgetClient()->ClearAnimationScheduled();
+
   last_frame_time_ += base::TimeDelta::FromSecondsD(time_delta_in_seconds);
 
   SimCanvas::Commands commands;
diff --git a/third_party/blink/renderer/core/testing/sim/sim_compositor.h b/third_party/blink/renderer/core/testing/sim/sim_compositor.h
index 8a3b8ea..6f542747 100644
--- a/third_party/blink/renderer/core/testing/sim/sim_compositor.h
+++ b/third_party/blink/renderer/core/testing/sim/sim_compositor.h
@@ -39,7 +39,15 @@
   // to composite the WebViewImpl is passed separately as the underlying
   // content::LayerTreeView type, in order to bypass the Web* API surface
   // provided to blink.
-  void SetWebView(WebViewImpl&, content::LayerTreeView&);
+  // The WebWidget client is overridden (via the WebViewClient) to control
+  // BeginMainFrame scheduling since this test suite does not use the
+  // compositor's scheduler. The SimCompositor wants to monitor and verify
+  // expectations around this scheduling, so receives the WebViewClient. We
+  // pass it here explicitly to provide type safety, though it is the client
+  // available on the WebViewImpl as well.
+  void SetWebView(WebViewImpl&,
+                  content::LayerTreeView&,
+                  frame_test_helpers::TestWebViewClient&);
 
   // Executes the BeginMainFrame processing steps, an approximation of what
   // cc::ThreadProxy::BeginMainFrame would do.
@@ -57,9 +65,13 @@
   // Helpers to query the state of the compositor from tests.
   //
   // Returns true if a main frame has been requested from blink, until the
-  // BeginFrame() step occurs.
+  // BeginFrame() step occurs. The AnimationScheduled() checks if an explicit
+  // requet for BeginFrame() was made, vs an implicit one by making changes
+  // to the compositor's state.
   bool NeedsBeginFrame() const {
-    return layer_tree_view_->layer_tree_host()->RequestedMainFramePending();
+    cc::LayerTreeHost* layer_tree_host = layer_tree_view_->layer_tree_host();
+    return test_web_view_client_->TestWidgetClient()->AnimationScheduled() ||
+           layer_tree_host->RequestedMainFramePendingForTesting();
   }
   // Returns true if commits are deferred in the compositor. Since these tests
   // use synchronous compositing through BeginFrame(), the deferred state has no
@@ -87,14 +99,15 @@
   void BeginMainFrame(base::TimeTicks frame_time) override;
 
   WebViewImpl* web_view_ = nullptr;
+  content::LayerTreeView* layer_tree_view_ = nullptr;
+  frame_test_helpers::TestWebViewClient* test_web_view_client_ = nullptr;
+
   base::TimeTicks last_frame_time_;
 
   // During BeginFrame(), painting is done, and the result is stored here to
   // be returned from BeginFrame().
   SimCanvas::Commands* paint_commands_;
 
-  content::LayerTreeView* layer_tree_view_ = nullptr;
-
   std::unique_ptr<cc::ScopedDeferMainFrameUpdate>
       scoped_defer_main_frame_update_;
 };
diff --git a/third_party/blink/renderer/core/testing/sim/sim_test.cc b/third_party/blink/renderer/core/testing/sim/sim_test.cc
index ab8aff7c..c050b89 100644
--- a/third_party/blink/renderer/core/testing/sim/sim_test.cc
+++ b/third_party/blink/renderer/core/testing/sim/sim_test.cc
@@ -22,7 +22,7 @@
       // SimCompositor overrides the LayerTreeViewDelegate to respond to
       // BeginMainFrame(), which will update and paint the WebViewImpl given to
       // SetWebView().
-      web_view_client_(&compositor_) {
+      web_view_client_(&web_widget_client_, &compositor_) {
   Document::SetThreadedParsingEnabledForTesting(false);
   // Use the mock theme to get more predictable code paths, this also avoids
   // the OS callbacks in ScrollAnimatorMac which can schedule frames
@@ -56,7 +56,8 @@
   Test::SetUp();
 
   web_view_helper_.Initialize(&web_frame_client_, &web_view_client_);
-  compositor_.SetWebView(WebView(), *web_view_client_.layer_tree_view());
+  compositor_.SetWebView(WebView(), *web_view_client_.layer_tree_view(),
+                         web_view_client_);
   page_.SetPage(WebView().GetPage());
 }
 
diff --git a/third_party/blink/renderer/core/testing/sim/sim_test.h b/third_party/blink/renderer/core/testing/sim/sim_test.h
index 1d446c0..3f1c9c7 100644
--- a/third_party/blink/renderer/core/testing/sim/sim_test.h
+++ b/third_party/blink/renderer/core/testing/sim/sim_test.h
@@ -53,6 +53,7 @@
   SimNetwork network_;
   SimCompositor compositor_;
   SimWebFrameClient web_frame_client_;
+  SimWebWidgetClient web_widget_client_;
   SimWebViewClient web_view_client_;
   SimPage page_;
   frame_test_helpers::WebViewHelper web_view_helper_;
diff --git a/third_party/blink/renderer/core/testing/sim/sim_web_view_client.cc b/third_party/blink/renderer/core/testing/sim/sim_web_view_client.cc
index f4d26638..adffbff8 100644
--- a/third_party/blink/renderer/core/testing/sim/sim_web_view_client.cc
+++ b/third_party/blink/renderer/core/testing/sim/sim_web_view_client.cc
@@ -8,10 +8,7 @@
 
 namespace blink {
 
-SimWebViewClient::SimWebViewClient(content::LayerTreeViewDelegate* delegate)
-    : frame_test_helpers::TestWebViewClient(delegate) {}
-
-void SimWebViewClient::DidMeaningfulLayout(
+void SimWebWidgetClient::DidMeaningfulLayout(
     WebMeaningfulLayout meaningful_layout) {
   switch (meaningful_layout) {
     case WebMeaningfulLayout::kVisuallyNonEmpty:
@@ -26,6 +23,11 @@
   }
 }
 
+SimWebViewClient::SimWebViewClient(SimWebWidgetClient* sim_web_widget_client,
+                                   content::LayerTreeViewDelegate* delegate)
+    : frame_test_helpers::TestWebViewClient(sim_web_widget_client, delegate),
+      widget_client_(sim_web_widget_client) {}
+
 WebView* SimWebViewClient::CreateView(WebLocalFrame* opener,
                                       const WebURLRequest&,
                                       const WebWindowFeatures&,
diff --git a/third_party/blink/renderer/core/testing/sim/sim_web_view_client.h b/third_party/blink/renderer/core/testing/sim/sim_web_view_client.h
index c38e6a7b..8da3e19b 100644
--- a/third_party/blink/renderer/core/testing/sim/sim_web_view_client.h
+++ b/third_party/blink/renderer/core/testing/sim/sim_web_view_client.h
@@ -9,9 +9,11 @@
 
 namespace blink {
 
-class SimWebViewClient final : public frame_test_helpers::TestWebViewClient {
+class SimWebWidgetClient final
+    : public frame_test_helpers::TestWebWidgetClient {
  public:
-  explicit SimWebViewClient(content::LayerTreeViewDelegate* delegate);
+  // WebWidgetClient overrides.
+  void DidMeaningfulLayout(WebMeaningfulLayout) override;
 
   int VisuallyNonEmptyLayoutCount() const {
     return visually_non_empty_layout_count_;
@@ -23,6 +25,17 @@
     return finished_loading_layout_count_;
   }
 
+ private:
+  int visually_non_empty_layout_count_ = 0;
+  int finished_parsing_layout_count_ = 0;
+  int finished_loading_layout_count_ = 0;
+};
+
+class SimWebViewClient final : public frame_test_helpers::TestWebViewClient {
+ public:
+  explicit SimWebViewClient(SimWebWidgetClient*,
+                            content::LayerTreeViewDelegate*);
+
   // WebViewClient implementation.
   WebView* CreateView(WebLocalFrame* opener,
                       const WebURLRequest&,
@@ -33,13 +46,18 @@
                       WebSandboxFlags,
                       const SessionStorageNamespaceId&) override;
 
- private:
-  // WebWidgetClient overrides.
-  void DidMeaningfulLayout(WebMeaningfulLayout) override;
+  int VisuallyNonEmptyLayoutCount() const {
+    return widget_client_->VisuallyNonEmptyLayoutCount();
+  }
+  int FinishedParsingLayoutCount() const {
+    return widget_client_->FinishedParsingLayoutCount();
+  }
+  int FinishedLoadingLayoutCount() const {
+    return widget_client_->FinishedLoadingLayoutCount();
+  }
 
-  int visually_non_empty_layout_count_ = 0;
-  int finished_parsing_layout_count_ = 0;
-  int finished_loading_layout_count_ = 0;
+ private:
+  SimWebWidgetClient* const widget_client_;
 
   frame_test_helpers::WebViewHelper web_view_helper_;
 };
diff --git a/third_party/blink/renderer/core/workers/shared_worker_global_scope.h b/third_party/blink/renderer/core/workers/shared_worker_global_scope.h
index 8b5a667..688de8a 100644
--- a/third_party/blink/renderer/core/workers/shared_worker_global_scope.h
+++ b/third_party/blink/renderer/core/workers/shared_worker_global_scope.h
@@ -42,7 +42,7 @@
 
 class SharedWorkerThread;
 
-class SharedWorkerGlobalScope final : public WorkerGlobalScope {
+class CORE_EXPORT SharedWorkerGlobalScope final : public WorkerGlobalScope {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
diff --git a/third_party/blink/renderer/devtools/front_end/coverage/CoverageModel.js b/third_party/blink/renderer/devtools/front_end/coverage/CoverageModel.js
index ff58087..a76a687 100644
--- a/third_party/blink/renderer/devtools/front_end/coverage/CoverageModel.js
+++ b/third_party/blink/renderer/devtools/front_end/coverage/CoverageModel.js
@@ -274,6 +274,65 @@
     urlCoverage._usedSize += coverageInfo._usedSize - oldUsedSize;
     return coverageInfo;
   }
+
+  /**
+   * @param {!Bindings.FileOutputStream} fos
+   */
+  async exportReport(fos) {
+    const result = [];
+    for (const urlInfo of this._coverageByURL.values()) {
+      const url = urlInfo.url();
+      if (url.startsWith('extensions::') || url.startsWith('chrome-extension://'))
+        continue;
+
+      // For .html resources, multiple scripts share URL, but have different offsets.
+      let useFullText = false;
+      for (const info of urlInfo._coverageInfoByLocation.values()) {
+        if (info._lineOffset || info._columnOffset) {
+          useFullText = !!url;
+          break;
+        }
+      }
+
+      let fullText = null;
+      if (useFullText) {
+        const resource = SDK.ResourceTreeModel.resourceForURL(url);
+        fullText = resource ? new TextUtils.Text(await resource.requestContent()) : null;
+      }
+
+      // We have full text for this resource, resolve the offsets using the text line endings.
+      if (fullText) {
+        const entry = {url, ranges: [], text: fullText.value()};
+        for (const info of urlInfo._coverageInfoByLocation.values()) {
+          const offset = fullText ? fullText.offsetFromPosition(info._lineOffset, info._columnOffset) : 0;
+          let start = 0;
+          for (const segment of info._segments) {
+            if (segment.count)
+              entry.ranges.push({start: start + offset, end: segment.end + offset});
+            else
+              start = segment.end;
+          }
+        }
+        result.push(entry);
+        continue;
+      }
+
+      // Fall back to the per-script operation.
+      for (const info of urlInfo._coverageInfoByLocation.values()) {
+        const entry = {url, ranges: [], text: await info.contentProvider().requestContent()};
+        let start = 0;
+        for (const segment of info._segments) {
+          if (segment.count)
+            entry.ranges.push({start: start, end: segment.end});
+          else
+            start = segment.end;
+        }
+        result.push(entry);
+      }
+    }
+    await fos.write(JSON.stringify(result, undefined, 2));
+    fos.close();
+  }
 };
 
 Coverage.URLCoverageInfo = class {
@@ -357,7 +416,7 @@
     if ((type & Coverage.CoverageType.JavaScript) && !this._coverageInfoByLocation.size)
       this._isContentScript = /** @type {!SDK.Script} */ (contentProvider).isContentScript();
 
-    entry = new Coverage.CoverageInfo(contentProvider, contentLength, type);
+    entry = new Coverage.CoverageInfo(contentProvider, contentLength, lineOffset, columnOffset, type);
     this._coverageInfoByLocation.set(key, entry);
     this._size += contentLength;
 
@@ -369,12 +428,16 @@
   /**
    * @param {!Common.ContentProvider} contentProvider
    * @param {number} size
+   * @param {number} lineOffset
+   * @param {number} columnOffset
    * @param {!Coverage.CoverageType} type
    */
-  constructor(contentProvider, size, type) {
+  constructor(contentProvider, size, lineOffset, columnOffset, type) {
     this._contentProvider = contentProvider;
     this._size = size;
     this._usedSize = 0;
+    this._lineOffset = lineOffset;
+    this._columnOffset = columnOffset;
     this._coverageType = type;
 
     /** !Array<!Coverage.CoverageSegment> */
diff --git a/third_party/blink/renderer/devtools/front_end/coverage/CoverageView.js b/third_party/blink/renderer/devtools/front_end/coverage/CoverageView.js
index b0367faa..c4816ee2 100644
--- a/third_party/blink/renderer/devtools/front_end/coverage/CoverageView.js
+++ b/third_party/blink/renderer/devtools/front_end/coverage/CoverageView.js
@@ -36,9 +36,13 @@
     this._clearButton.addEventListener(UI.ToolbarButton.Events.Click, this._clear.bind(this));
     toolbar.appendToolbarItem(this._clearButton);
 
+    toolbar.appendSeparator();
+    const saveButton = new UI.ToolbarButton(Common.UIString('Export...'), 'largeicon-download');
+    saveButton.addEventListener(UI.ToolbarButton.Events.Click, () => this._exportReport());
+    toolbar.appendToolbarItem(saveButton);
+
     /** @type {?RegExp} */
     this._textFilterRegExp = null;
-
     toolbar.appendSeparator();
     this._filterInput = new UI.ToolbarInput(Common.UIString('URL filter'), 0.4, 1);
     this._filterInput.setEnabled(false);
@@ -222,6 +226,15 @@
       return false;
     return ignoreTextFilter || !this._textFilterRegExp || this._textFilterRegExp.test(url);
   }
+
+  async _exportReport() {
+    const fos = new Bindings.FileOutputStream();
+    const fileName = `Coverage-${new Date().toISO8601Compact()}.json`;
+    const accepted = await fos.open(fileName);
+    if (!accepted)
+      return;
+    this._model.exportReport(fos);
+  }
 };
 
 Coverage.CoverageView._extensionBindingsURLPrefix = 'extensions::';
diff --git a/third_party/blink/renderer/devtools/front_end/coverage_test_runner/CoverageTestRunner.js b/third_party/blink/renderer/devtools/front_end/coverage_test_runner/CoverageTestRunner.js
index 0757efb..c944baf 100644
--- a/third_party/blink/renderer/devtools/front_end/coverage_test_runner/CoverageTestRunner.js
+++ b/third_party/blink/renderer/devtools/front_end/coverage_test_runner/CoverageTestRunner.js
@@ -30,6 +30,16 @@
 };
 
 /**
+ * @return {!Promise<string>}
+ */
+CoverageTestRunner.exportReport = async function() {
+  const coverageView = self.runtime.sharedInstance(Coverage.CoverageView);
+  let data;
+  await coverageView._model.exportReport({write: d => data = d, close: _ => 0});
+  return data;
+};
+
+/**
  * @return {!Promise<!SourceFrame.SourceFrame>}
  */
 CoverageTestRunner.sourceDecorated = async function(source) {
diff --git a/third_party/blink/renderer/modules/accessibility/ax_selection.cc b/third_party/blink/renderer/modules/accessibility/ax_selection.cc
index 02371460..0aceee8 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_selection.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_selection.cc
@@ -15,6 +15,7 @@
 #include "third_party/blink/renderer/core/editing/text_affinity.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/modules/accessibility/ax_object.h"
+#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
 
 namespace blink {
 
@@ -119,11 +120,11 @@
 AXSelection AXSelection::FromCurrentSelection(
     const Document& document,
     const AXSelectionBehavior selection_behavior) {
-  LocalFrame* frame = document.GetFrame();
+  const LocalFrame* frame = document.GetFrame();
   if (!frame)
     return {};
 
-  FrameSelection& frame_selection = frame->Selection();
+  const FrameSelection& frame_selection = frame->Selection();
   if (!frame_selection.IsAvailable())
     return {};
 
@@ -132,6 +133,30 @@
 }
 
 // static
+AXSelection AXSelection::FromCurrentSelection(
+    const TextControlElement& text_control) {
+  const Document& document = text_control.GetDocument();
+  AXObjectCache* ax_object_cache = document.ExistingAXObjectCache();
+  if (!ax_object_cache)
+    return {};
+
+  auto* ax_object_cache_impl = static_cast<AXObjectCacheImpl*>(ax_object_cache);
+  const AXObject* ax_text_control =
+      ax_object_cache_impl->GetOrCreate(&text_control);
+  DCHECK(ax_text_control);
+  const TextAffinity affinity = text_control.Selection().Affinity();
+  const auto ax_base = AXPosition::CreatePositionInTextObject(
+      *ax_text_control, static_cast<int>(text_control.selectionStart()));
+  const auto ax_extent = AXPosition::CreatePositionInTextObject(
+      *ax_text_control, static_cast<int>(text_control.selectionEnd()),
+      affinity);
+
+  AXSelection::Builder selection_builder;
+  selection_builder.SetBase(ax_base).SetExtent(ax_extent);
+  return selection_builder.Build();
+}
+
+// static
 AXSelection AXSelection::FromSelection(
     const SelectionInDOMTree& selection,
     const AXSelectionBehavior selection_behavior) {
diff --git a/third_party/blink/renderer/modules/accessibility/ax_selection.h b/third_party/blink/renderer/modules/accessibility/ax_selection.h
index 3c9bafcd..24dc036 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_selection.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_selection.h
@@ -47,6 +47,8 @@
       const Document&,
       const AXSelectionBehavior = AXSelectionBehavior::kExtendToValidDOMRange);
 
+  static AXSelection FromCurrentSelection(const TextControlElement&);
+
   static AXSelection FromSelection(
       const SelectionInDOMTree&,
       const AXSelectionBehavior = AXSelectionBehavior::kExtendToValidDOMRange);
diff --git a/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc b/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc
index c673d130..c3ad8c9 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc
@@ -438,6 +438,158 @@
 // Tests that involve selection inside, outside, and spanning text controls.
 //
 
+TEST_F(AccessibilitySelectionTest, FromCurrentSelectionInTextField) {
+  GetPage().GetSettings().SetScriptEnabled(true);
+  SetBodyInnerHTML(R"HTML(
+      <input id="input" value="Inside text field.">
+      )HTML");
+
+  ASSERT_FALSE(AXSelection::FromCurrentSelection(GetDocument()).IsValid());
+
+  Element* const script_element =
+      GetDocument().CreateRawElement(html_names::kScriptTag);
+  ASSERT_NE(nullptr, script_element);
+  script_element->setTextContent(R"SCRIPT(
+      let input = document.querySelector('input');
+      input.focus();
+      input.selectionStart = 0;
+      input.selectionEnd = input.value.length;
+      )SCRIPT");
+  GetDocument().body()->AppendChild(script_element);
+  UpdateAllLifecyclePhasesForTest();
+
+  const Element* input = GetDocument().QuerySelector("input");
+  ASSERT_NE(nullptr, input);
+  ASSERT_TRUE(IsTextControl(input));
+
+  const AXObject* ax_input = GetAXObjectByElementId("input");
+  ASSERT_NE(nullptr, ax_input);
+  ASSERT_EQ(ax::mojom::Role::kTextField, ax_input->RoleValue());
+
+  const auto ax_selection =
+      AXSelection::FromCurrentSelection(ToTextControl(*input));
+  ASSERT_TRUE(ax_selection.IsValid());
+
+  EXPECT_TRUE(ax_selection.Base().IsTextPosition());
+  EXPECT_EQ(ax_input, ax_selection.Base().ContainerObject());
+  EXPECT_EQ(0, ax_selection.Base().TextOffset());
+  EXPECT_TRUE(ax_selection.Extent().IsTextPosition());
+  EXPECT_EQ(ax_input, ax_selection.Extent().ContainerObject());
+  EXPECT_EQ(18, ax_selection.Extent().TextOffset());
+}
+
+TEST_F(AccessibilitySelectionTest, FromCurrentSelectionInTextarea) {
+  GetPage().GetSettings().SetScriptEnabled(true);
+  SetBodyInnerHTML(R"HTML(
+      <textarea id="textarea">
+        Inside
+        textarea
+        field.
+      </textarea>
+      )HTML");
+
+  ASSERT_FALSE(AXSelection::FromCurrentSelection(GetDocument()).IsValid());
+
+  Element* const script_element =
+      GetDocument().CreateRawElement(html_names::kScriptTag);
+  ASSERT_NE(nullptr, script_element);
+  script_element->setTextContent(R"SCRIPT(
+      let textarea = document.querySelector('textarea');
+      textarea.focus();
+      textarea.selectionStart = 0;
+      textarea.selectionEnd = textarea.textLength;
+      )SCRIPT");
+  GetDocument().body()->AppendChild(script_element);
+  UpdateAllLifecyclePhasesForTest();
+
+  const Element* textarea = GetDocument().QuerySelector("textarea");
+  ASSERT_NE(nullptr, textarea);
+  ASSERT_TRUE(IsTextControl(textarea));
+
+  const AXObject* ax_textarea = GetAXObjectByElementId("textarea");
+  ASSERT_NE(nullptr, ax_textarea);
+  ASSERT_EQ(ax::mojom::Role::kTextField, ax_textarea->RoleValue());
+
+  const auto ax_selection =
+      AXSelection::FromCurrentSelection(ToTextControl(*textarea));
+  ASSERT_TRUE(ax_selection.IsValid());
+
+  EXPECT_TRUE(ax_selection.Base().IsTextPosition());
+  EXPECT_EQ(ax_textarea, ax_selection.Base().ContainerObject());
+  EXPECT_EQ(0, ax_selection.Base().TextOffset());
+  EXPECT_TRUE(ax_selection.Extent().IsTextPosition());
+  EXPECT_EQ(ax_textarea, ax_selection.Extent().ContainerObject());
+  EXPECT_EQ(53, ax_selection.Extent().TextOffset());
+}
+
+TEST_F(AccessibilitySelectionTest, ClearCurrentSelectionInTextField) {
+  GetPage().GetSettings().SetScriptEnabled(true);
+  SetBodyInnerHTML(R"HTML(
+      <input id="input" value="Inside text field.">
+      )HTML");
+
+  ASSERT_FALSE(AXSelection::FromCurrentSelection(GetDocument()).IsValid());
+
+  Element* const script_element =
+      GetDocument().CreateRawElement(html_names::kScriptTag);
+  ASSERT_NE(nullptr, script_element);
+  script_element->setTextContent(R"SCRIPT(
+      let input = document.querySelector('input');
+      input.focus();
+      input.selectionStart = 0;
+      input.selectionEnd = input.textLength;
+      )SCRIPT");
+  GetDocument().body()->AppendChild(script_element);
+  UpdateAllLifecyclePhasesForTest();
+
+  SelectionInDOMTree selection = Selection().GetSelectionInDOMTree();
+  ASSERT_FALSE(selection.IsNone());
+
+  AXSelection::ClearCurrentSelection(GetDocument());
+  selection = Selection().GetSelectionInDOMTree();
+  EXPECT_TRUE(selection.IsNone());
+
+  const auto ax_selection = AXSelection::FromCurrentSelection(GetDocument());
+  EXPECT_FALSE(ax_selection.IsValid());
+  EXPECT_EQ("", GetSelectionText(ax_selection));
+}
+
+TEST_F(AccessibilitySelectionTest, ClearCurrentSelectionInTextarea) {
+  GetPage().GetSettings().SetScriptEnabled(true);
+  SetBodyInnerHTML(R"HTML(
+      <textarea id="textarea">
+        Inside
+        textarea
+        field.
+      </textarea>
+      )HTML");
+
+  ASSERT_FALSE(AXSelection::FromCurrentSelection(GetDocument()).IsValid());
+
+  Element* const script_element =
+      GetDocument().CreateRawElement(html_names::kScriptTag);
+  ASSERT_NE(nullptr, script_element);
+  script_element->setTextContent(R"SCRIPT(
+      let textarea = document.querySelector('textarea');
+      textarea.focus();
+      textarea.selectionStart = 0;
+      textarea.selectionEnd = textarea.textLength;
+      )SCRIPT");
+  GetDocument().body()->AppendChild(script_element);
+  UpdateAllLifecyclePhasesForTest();
+
+  SelectionInDOMTree selection = Selection().GetSelectionInDOMTree();
+  ASSERT_FALSE(selection.IsNone());
+
+  AXSelection::ClearCurrentSelection(GetDocument());
+  selection = Selection().GetSelectionInDOMTree();
+  EXPECT_TRUE(selection.IsNone());
+
+  const auto ax_selection = AXSelection::FromCurrentSelection(GetDocument());
+  EXPECT_FALSE(ax_selection.IsValid());
+  EXPECT_EQ("", GetSelectionText(ax_selection));
+}
+
 TEST_F(AccessibilitySelectionTest, ForwardSelectionInTextField) {
   SetBodyInnerHTML(R"HTML(
       <input id="input" value="Inside text field.">
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
index c88080a..892424be 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -752,6 +752,27 @@
   return synthesized_clip.GetLayer();
 }
 
+static void UpdateCompositorViewportProperties(
+    const PaintArtifactCompositor::ViewportProperties& properties,
+    PropertyTreeManager& property_tree_manager,
+    cc::LayerTreeHost* layer_tree_host) {
+  cc::LayerTreeHost::ViewportPropertyIds ids;
+  // This is also needed by pre-CompositeAfterPaint, so is not guarded by
+  // CompositeAfterPaintEnabled().
+  if (properties.page_scale) {
+    ids.page_scale_transform =
+        property_tree_manager.EnsureCompositorPageScaleTransformNode(
+            properties.page_scale);
+  }
+  if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
+    if (properties.inner_scroll_translation) {
+      ids.inner_scroll = property_tree_manager.EnsureCompositorScrollNode(
+          properties.inner_scroll_translation);
+    }
+    layer_tree_host->RegisterViewportPropertyIds(ids);
+  }
+}
+
 void PaintArtifactCompositor::Update(
     scoped_refptr<const PaintArtifact> paint_artifact,
     CompositorElementIdSet& composited_element_ids,
@@ -784,14 +805,8 @@
   Vector<PendingLayer, 0> pending_layers;
   CollectPendingLayers(*paint_artifact, settings, pending_layers);
 
-  cc::LayerTreeHost::ViewportPropertyIds viewport_property_ids;
-  if (viewport_properties.page_scale) {
-    viewport_property_ids.page_scale_transform =
-        property_tree_manager.EnsureCompositorPageScaleTransformNode(
-            viewport_properties.page_scale);
-  }
-  if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled())
-    host->RegisterViewportPropertyIds(viewport_property_ids);
+  UpdateCompositorViewportProperties(viewport_properties, property_tree_manager,
+                                     host);
 
   Vector<std::unique_ptr<ContentLayerClientImpl>> new_content_layer_clients;
   new_content_layer_clients.ReserveCapacity(pending_layers.size());
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
index b14654f..a582b24 100644
--- a/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
+++ b/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
@@ -71,6 +71,9 @@
 
   struct ViewportProperties {
     const TransformPaintPropertyNode* page_scale = nullptr;
+    const TransformPaintPropertyNode* inner_scroll_translation = nullptr;
+    // TODO(crbug.com/909750): Add other viewport properties, e.g.
+    // outer_scroll_translation.
   };
 
   struct Settings {
diff --git a/third_party/blink/renderer/platform/graphics/paint/display_item.h b/third_party/blink/renderer/platform/graphics/paint/display_item.h
index 83fb773..03f980dc 100644
--- a/third_party/blink/renderer/platform/graphics/paint/display_item.h
+++ b/third_party/blink/renderer/platform/graphics/paint/display_item.h
@@ -18,14 +18,8 @@
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 #endif
 
-namespace cc {
-class DisplayItemList;
-}
-
 namespace blink {
 
-class GraphicsContext;
-class FloatSize;
 enum class PaintPhase;
 
 class PLATFORM_EXPORT DisplayItem {
@@ -147,11 +141,15 @@
 
   // Some fields are copied from |client|, because we need to access them in
   // later paint cycles when |client| may have been destroyed.
-  DisplayItem(const DisplayItemClient& client, Type type, size_t derived_size)
+  DisplayItem(const DisplayItemClient& client,
+              Type type,
+              size_t derived_size,
+              bool draws_content = false)
       : client_(&client),
         visual_rect_(client.VisualRect()),
         outset_for_raster_effects_(client.VisualRectOutsetForRasterEffects()),
         type_(type),
+        draws_content_(draws_content),
         fragment_(0),
         is_cacheable_(client.IsCacheable()),
         is_tombstone_(false) {
@@ -181,8 +179,6 @@
 
   Id GetId() const { return Id(*client_, GetType(), fragment_); }
 
-  virtual void Replay(GraphicsContext&) const {}
-
   const DisplayItemClient& Client() const {
     DCHECK(client_);
     return *client_;
@@ -216,13 +212,6 @@
     fragment_ = fragment;
   }
 
-  // Appends this display item to the cc::DisplayItemList, if applicable.
-  // |visual_rect_offset| is the offset between the space of the GraphicsLayer
-  // which owns the display item and the coordinate space of VisualRect().
-  // TODO(wangxianzhu): Remove the parameter for CompositeAfterPaint.
-  virtual void AppendToDisplayItemList(const FloatSize& visual_rect_offset,
-                                       cc::DisplayItemList&) const {}
-
 // See comments of enum Type for usage of the following macros.
 #define DEFINE_CATEGORY_METHODS(Category)                           \
   static constexpr bool Is##Category##Type(Type type) {             \
@@ -269,7 +258,7 @@
   // DisplayItem.
   bool IsTombstone() const { return is_tombstone_; }
 
-  virtual bool DrawsContent() const { return false; }
+  bool DrawsContent() const { return draws_content_; }
 
 #if DCHECK_IS_ON()
   static WTF::String TypeAsDebugString(DisplayItem::Type);
@@ -284,18 +273,19 @@
 
   // The default DisplayItem constructor is only used by ContiguousContainer::
   // AppendByMoving() where a tombstone DisplayItem is constructed at the source
-  // location. Only set is_tombstone_ to true, leaving other fields as-is so
-  // that we can get their original values. |visual_rect_| and
-  // |outset_for_raster_effects_| are special, see DisplayItemList::
-  // AppendByMoving().
-  DisplayItem() : is_tombstone_(true) {}
+  // location. Only set draws_content_ to false and is_tombstone_ to true,
+  // leaving other fields as-is so that we can get their original values.
+  // |visual_rect_| and |outset_for_raster_effects_| are special, see
+  // DisplayItemList::AppendByMoving().
+  DisplayItem() : draws_content_(false), is_tombstone_(true) {}
 
   const DisplayItemClient* client_;
   FloatRect visual_rect_;
   float outset_for_raster_effects_;
 
-  static_assert(kTypeLast < (1 << 8), "DisplayItem::Type should fit in 8 bits");
-  unsigned type_ : 8;
+  static_assert(kTypeLast < (1 << 7), "DisplayItem::Type should fit in 7 bits");
+  unsigned type_ : 7;
+  unsigned draws_content_ : 1;
   unsigned derived_size_ : 8;  // size of the actual derived class
   unsigned fragment_ : 14;
   unsigned is_cacheable_ : 1;
diff --git a/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc b/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc
index a9bf22f..750ac8d 100644
--- a/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc
@@ -13,28 +13,6 @@
 
 namespace blink {
 
-void DrawingDisplayItem::Replay(GraphicsContext& context) const {
-  if (record_)
-    context.DrawRecord(record_);
-}
-
-void DrawingDisplayItem::AppendToDisplayItemList(
-    const FloatSize& visual_rect_offset,
-    cc::DisplayItemList& list) const {
-  if (record_) {
-    list.StartPaint();
-    list.push<cc::DrawRecordOp>(record_);
-    // Convert visual rect into the GraphicsLayer's coordinate space.
-    auto visual_rect = VisualRect();
-    visual_rect.Move(-visual_rect_offset);
-    list.EndPaintOfUnpaired(EnclosingIntRect(visual_rect));
-  }
-}
-
-bool DrawingDisplayItem::DrawsContent() const {
-  return record_.get();
-}
-
 #if DCHECK_IS_ON()
 void DrawingDisplayItem::PropertiesAsJSON(JSONObject& json) const {
   DisplayItem::PropertiesAsJSON(json);
diff --git a/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h b/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h
index 80c35cc..9f3c691c 100644
--- a/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h
+++ b/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h
@@ -33,11 +33,6 @@
                      sk_sp<const PaintRecord> record,
                      bool known_to_be_opaque = false);
 
-  void Replay(GraphicsContext&) const final;
-  void AppendToDisplayItemList(const FloatSize& visual_rect_offset,
-                               cc::DisplayItemList&) const final;
-  bool DrawsContent() const final;
-
   const sk_sp<const PaintRecord>& GetPaintRecord() const { return record_; }
 
   bool KnownToBeOpaque() const {
@@ -64,8 +59,11 @@
                                               Type type,
                                               sk_sp<const PaintRecord> record,
                                               bool known_to_be_opaque)
-    : DisplayItem(client, type, sizeof(*this)),
-      record_(record && record->size() ? std::move(record) : nullptr),
+    : DisplayItem(client,
+                  type,
+                  sizeof(*this),
+                  /* draws_content*/ record && record->size()),
+      record_(DrawsContent() ? std::move(record) : nullptr),
       known_to_be_opaque_(known_to_be_opaque) {
   DCHECK(IsDrawingType(type));
 }
diff --git a/third_party/blink/renderer/platform/graphics/paint/drawing_display_item_test.cc b/third_party/blink/renderer/platform/graphics/paint/drawing_display_item_test.cc
index 36d2fab..bde9029 100644
--- a/third_party/blink/renderer/platform/graphics/paint/drawing_display_item_test.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/drawing_display_item_test.cc
@@ -45,7 +45,7 @@
   return recorder.finishRecordingAsPicture();
 }
 
-TEST_F(DrawingDisplayItemTest, VisualRectAndDrawingBounds) {
+TEST_F(DrawingDisplayItemTest, DrawsContent) {
   FloatRect record_bounds(5.5, 6.6, 7.7, 8.8);
   LayoutRect drawing_bounds(record_bounds);
   client_.SetVisualRect(drawing_bounds);
@@ -53,18 +53,19 @@
   DrawingDisplayItem item(client_, DisplayItem::Type::kDocumentBackground,
                           CreateRectRecord(record_bounds));
   EXPECT_EQ(FloatRect(drawing_bounds), item.VisualRect());
+  EXPECT_TRUE(item.DrawsContent());
+}
 
-  auto list1 = base::MakeRefCounted<cc::DisplayItemList>();
-  item.AppendToDisplayItemList(FloatSize(), *list1);
-  EXPECT_EQ(EnclosingIntRect(drawing_bounds), list1->VisualRectForTesting(0));
+TEST_F(DrawingDisplayItemTest, NullPaintRecord) {
+  DrawingDisplayItem item(client_, DisplayItem::Type::kDocumentBackground,
+                          nullptr);
+  EXPECT_FALSE(item.DrawsContent());
+}
 
-  FloatSize offset(2.1, 3.6);
-  auto list2 = base::MakeRefCounted<cc::DisplayItemList>();
-  item.AppendToDisplayItemList(offset, *list2);
-  FloatRect visual_rect_with_offset(drawing_bounds);
-  visual_rect_with_offset.Move(-offset);
-  EXPECT_EQ(EnclosingIntRect(visual_rect_with_offset),
-            list2->VisualRectForTesting(0));
+TEST_F(DrawingDisplayItemTest, EmptyPaintRecord) {
+  DrawingDisplayItem item(client_, DisplayItem::Type::kDocumentBackground,
+                          sk_make_sp<PaintRecord>());
+  EXPECT_FALSE(item.DrawsContent());
 }
 
 TEST_F(DrawingDisplayItemTest, Equals) {
diff --git a/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc b/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc
index 44b4ed1..5413eb3 100644
--- a/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.cc
@@ -55,20 +55,6 @@
   return static_cast<const ForeignLayerDisplayItemClient&>(Client()).GetLayer();
 }
 
-void ForeignLayerDisplayItem::Replay(GraphicsContext&) const {
-  NOTREACHED();
-}
-
-void ForeignLayerDisplayItem::AppendToDisplayItemList(
-    const FloatSize&,
-    cc::DisplayItemList&) const {
-  NOTREACHED();
-}
-
-bool ForeignLayerDisplayItem::DrawsContent() const {
-  return false;
-}
-
 bool ForeignLayerDisplayItem::Equals(const DisplayItem& other) const {
   return DisplayItem::Equals(other) &&
          GetLayer() ==
diff --git a/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h b/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h
index 6bb3bde..19765ba 100644
--- a/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h
+++ b/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h
@@ -28,10 +28,6 @@
   cc::Layer* GetLayer() const;
 
   // DisplayItem
-  void Replay(GraphicsContext&) const override;
-  void AppendToDisplayItemList(const FloatSize&,
-                               cc::DisplayItemList&) const override;
-  bool DrawsContent() const override;
   bool Equals(const DisplayItem&) const override;
 #if DCHECK_IS_ON()
   void PropertiesAsJSON(JSONObject&) const override;
diff --git a/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h b/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h
index 51af360..9fbce5ff 100644
--- a/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h
+++ b/third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h
@@ -11,6 +11,8 @@
 
 namespace blink {
 
+class GraphicsContext;
+
 // A special DisplayItem containing hit test data.
 class PLATFORM_EXPORT HitTestDisplayItem final : public DisplayItem {
  public:
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
index 22747be..f22f66e6 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
@@ -130,14 +130,6 @@
   canvas.drawPicture(display_item_list->ReleaseAsRecord());
 }
 
-DISABLE_CFI_PERF
-void PaintArtifact::AppendToDisplayItemList(const FloatSize& visual_rect_offset,
-                                            cc::DisplayItemList& list) const {
-  TRACE_EVENT0("blink,benchmark", "PaintArtifact::AppendToDisplayItemList");
-  for (const DisplayItem& item : display_item_list_)
-    item.AppendToDisplayItemList(visual_rect_offset, list);
-}
-
 void PaintArtifact::FinishCycle() {
   // BlinkGenPropertyTrees uses PaintController::ClearPropertyTreeChangedStateTo
   // for clearing the property tree changed state at the end of paint instead of
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h
index a4fe34d..cebd03d4 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h
@@ -81,10 +81,6 @@
               const PropertyTreeState& replay_state,
               const IntPoint& offset = IntPoint()) const;
 
-  // Writes the paint artifact into a cc::DisplayItemList.
-  void AppendToDisplayItemList(const FloatSize& visual_rect_offset,
-                               cc::DisplayItemList& display_list) const;
-
   // Called when the caller finishes updating a full document life cycle.
   // Will cleanup data (e.g. raster invalidations) that will no longer be used
   // for the next cycle, and update status to be ready for the next cycle.
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc b/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc
index a96ab6fc..b1c253e 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc
@@ -33,12 +33,6 @@
   TestChunkerDisplayItem(const DisplayItemClient& client,
                          DisplayItem::Type type = DisplayItem::kDrawingFirst)
       : DisplayItem(client, type, sizeof(*this)) {}
-
-  void Replay(GraphicsContext&) const final { NOTREACHED(); }
-  void AppendToDisplayItemList(const FloatSize&,
-                               cc::DisplayItemList&) const final {
-    NOTREACHED();
-  }
 };
 
 class TestDisplayItemRequiringSeparateChunk : public TestChunkerDisplayItem {
diff --git a/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc b/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc
index f9b8e4ff..d5631ea 100644
--- a/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc
@@ -22,16 +22,6 @@
 
 ScrollHitTestDisplayItem::~ScrollHitTestDisplayItem() = default;
 
-void ScrollHitTestDisplayItem::Replay(GraphicsContext&) const {
-  NOTREACHED();
-}
-
-void ScrollHitTestDisplayItem::AppendToDisplayItemList(
-    const FloatSize&,
-    cc::DisplayItemList&) const {
-  NOTREACHED();
-}
-
 bool ScrollHitTestDisplayItem::Equals(const DisplayItem& other) const {
   return DisplayItem::Equals(other) &&
          &scroll_node() ==
diff --git a/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h b/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h
index 4642790..082b202 100644
--- a/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h
+++ b/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h
@@ -34,9 +34,6 @@
   }
 
   // DisplayItem
-  void Replay(GraphicsContext&) const override;
-  void AppendToDisplayItemList(const FloatSize&,
-                               cc::DisplayItemList&) const override;
   bool Equals(const DisplayItem&) const override;
 #if DCHECK_IS_ON()
   void PropertiesAsJSON(JSONObject&) const override;
diff --git a/third_party/blink/renderer/platform/heap/heap_page.h b/third_party/blink/renderer/platform/heap/heap_page.h
index b2625f0..063a6e0 100644
--- a/third_party/blink/renderer/platform/heap/heap_page.h
+++ b/third_party/blink/renderer/platform/heap/heap_page.h
@@ -584,7 +584,7 @@
 // In order to use the same memory allocation routines for everything allocated
 // in the heap, large objects are considered heap pages containing only one
 // object.
-class LargeObjectPage final : public BasePage {
+class PLATFORM_EXPORT LargeObjectPage final : public BasePage {
  public:
   static size_t PageHeaderSize() {
     // Compute the amount of padding we have to add to a header to make the size
diff --git a/third_party/blink/tools/blinkpy/common/net/buildbot.py b/third_party/blink/tools/blinkpy/common/net/buildbot.py
index 58ecbe1..6ce8d6b 100644
--- a/third_party/blink/tools/blinkpy/common/net/buildbot.py
+++ b/third_party/blink/tools/blinkpy/common/net/buildbot.py
@@ -170,11 +170,7 @@
         if results_file is None:
             _log.debug('Got 404 response from:\n%s/%s', results_url, base_filename)
             return None
-        revision = NetworkTransaction(return_none_on_404=True).run(
-            lambda: self.fetch_file('%s/LAST_CHANGE' % results_url))
-        if revision is None:
-            _log.debug('Got 404 response from:\n%s/LAST_CHANGE', results_url)
-        return WebTestResults.results_from_string(results_file, revision)
+        return WebTestResults.results_from_string(results_file)
 
     def fetch_file(self, url):
         # It seems this can return None if the url redirects and then returns 404.
diff --git a/third_party/blink/tools/blinkpy/common/net/web_test_results.py b/third_party/blink/tools/blinkpy/common/net/web_test_results.py
index 65b8259..27bfbaed 100644
--- a/third_party/blink/tools/blinkpy/common/net/web_test_results.py
+++ b/third_party/blink/tools/blinkpy/common/net/web_test_results.py
@@ -84,15 +84,11 @@
 class WebTestResults(object):
 
     @classmethod
-    def results_from_string(cls, string, chromium_revision=None):
+    def results_from_string(cls, string):
         """Creates a WebTestResults object from a test result JSON string.
 
         Args:
             string: JSON string containing web test result.
-            chromium_revision: If given, it will override the chromium_revision
-                field in json, to indicate the last revision that has completed
-                uploading onto the storage server. chromium_revision can be a
-                git hash or position number.
         """
 
         if not string:
@@ -103,7 +99,7 @@
         if not json_dict:
             return None
 
-        return cls(json_dict, chromium_revision)
+        return cls(json_dict)
 
     def __init__(self, parsed_json, chromium_revision=None):
         self._results = parsed_json
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/base.py b/third_party/blink/tools/blinkpy/web_tests/port/base.py
index 522662e1..d97470d7 100644
--- a/third_party/blink/tools/blinkpy/web_tests/port/base.py
+++ b/third_party/blink/tools/blinkpy/web_tests/port/base.py
@@ -1128,7 +1128,6 @@
         if self.host.platform.is_win():
             variables_to_copy += [
                 'PATH',
-                'GYP_DEFINES',  # Required to locate win sdk.
             ]
 
         for variable in variables_to_copy:
diff --git a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
index a80b8fb..32b6067 100644
--- a/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
+++ b/third_party/blink/web_tests/FlagExpectations/enable-blink-features=CompositeAfterPaint
@@ -369,18 +369,17 @@
 
 # virtual/threaded variants of sub-directories and tests already skipped or marked as failing above.
 Bug(none) virtual/threaded/http/tests/devtools/ [ Skip ]
-Bug(none) virtual/threaded/fast/events/pinch/gesture-pinch-zoom-scroll-bubble.html [ Failure Crash ]
-Bug(none) virtual/threaded/fast/events/pinch/gesture-pinch-zoom-prevent-in-handler.html [ Failure Crash ]
-Bug(none) virtual/threaded/fast/events/pinch/scroll-visual-viewport-send-boundary-events.html [ Failure Crash ]
-Bug(none) virtual/threaded/fast/events/pointerevents/pinch/pointerevent_touch-action-pinch_zoom_touch.html [ Pass Failure ]
+Bug(none) virtual/threaded/fast/events/pinch/gesture-pinch-zoom-scroll-bubble.html [ Timeout ]
+Bug(none) virtual/threaded/fast/events/pinch/pinch-zoom-pan-within-zoomed-viewport.html [ Failure ]
+Bug(none) virtual/threaded/fast/events/pinch/scroll-visual-viewport-send-boundary-events.html [ Timeout ]
 Bug(none) virtual/threaded/fast/scroll-behavior/ [ Skip ]
 Bug(none) virtual/threaded/compositing/visibility/layer-visible-content.html [ Failure ]
-Bug(none) virtual/threaded/compositing/visibility/overlays.html [ Failure Crash ]
-Bug(none) virtual/threaded/compositing/visibility/visibility-image-layers-dynamic.html [ Crash Failure ]
+Bug(none) virtual/threaded/compositing/visibility/overlays.html [ Failure ]
+Bug(none) virtual/threaded/compositing/visibility/visibility-image-layers-dynamic.html [ Failure ]
 Bug(none) virtual/threaded/compositing/webgl/webgl-reflection.html [ Failure Pass ]
 Bug(none) virtual/threaded/compositing/webgl/webgl-with-accelerated-background-color.html [ Failure Pass ]
 Bug(none) virtual/threaded/printing/ [ Skip ]
-Bug(none) virtual/threaded/synthetic_gestures/ [ Failure Pass Crash ]
+Bug(none) virtual/threaded/synthetic_gestures/smooth-scroll-tiny-delta.html [ Failure ]
 
 Bug(none) fast/forms/validation-bubble-appearance-edge.html [ Failure ]
 Bug(none) fast/forms/validation-bubble-appearance-iframe.html [ Failure ]
@@ -479,14 +478,8 @@
 crbug.com/833083 paint/invalidation/compositing/composited-layers-move-in-subpixels.html [ Failure ]
 
 Bug(none) compositing/squashing/frame-clip-squashed-scrolled.html [ Failure ]
-
 Bug(none) paint/invalidation/selection/japanese-rl-selection-repaint.html [ Failure ]
 Bug(none) virtual/threaded/external/wpt/feature-policy/experimental-features/vertical-scroll-touch-block-manual.tentative.html [ Failure ]
-
-Bug(none) virtual/threaded/fast/events/pinch/gesture-pinch-fake-mouse-wheel.html [ Pass Failure Crash ]
-Bug(none) virtual/threaded/fast/events/pinch/pinch-zoom-into-center.html [ Pass Failure Crash ]
-Bug(none) virtual/threaded/fast/events/pinch/pinch-zoom-pan-position-fixed.html [ Pass Failure Crash ]
-Bug(none) virtual/threaded/fast/events/pinch/pinch-zoom-pan-within-zoomed-viewport.html [ Pass Failure Crash ]
 Bug(none) compositing/overflow/scrollbar-layer-placement-negative-z-index-child-positioned.html [ Failure ]
 
 Bug(none) paint/float/float-under-inline-self-painting-change.html [ Failure ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 54d4566..cafe3f94 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1505,57 +1505,38 @@
 # Flexbox in NG
 #
 ### virtual/layout_ng_experimental/css3/flexbox/
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/align-baseline.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/auto-height-column-with-border-and-padding.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/auto-height-dynamic.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/auto-height-with-flex.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/box-sizing-min-max-sizes.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/box-sizing.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/bug527039.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/bug580586.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/bug604346.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/bug633212.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/bug646288.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/bug669714.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/bug750553.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/canvas-dynamic-change.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/change-column-flex-width.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/child-overflow.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/column-flex-child-with-overflow-scroll.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/columns-auto-size.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/columns-center-with-margins-and-wrap.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/columns-center-with-margins.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/columns-height-set-via-top-bottom.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/content-height-with-scrollbars.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/auto-height-column-with-border-and-padding.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/auto-height-with-flex.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/box-sizing-min-max-sizes.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/box-sizing.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/bug604346.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/canvas-dynamic-change.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/columns-auto-size.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/columns-height-set-via-top-bottom.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/content-height-with-scrollbars.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/crash-removing-out-of-flow-child.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/cross-axis-scrollbar.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/definite-main-size.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/cross-axis-scrollbar.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/display-flexbox-set-get.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-algorithm-min-max.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-algorithm.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-align-baseline.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-align-column.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-align-end.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-align-max.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-align-stretch.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-align-column.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-align-end.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-align-vertical-writing-mode.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-align.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-column-relayout-assert.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-factor-less-than-one.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-flow-2.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-flow-auto-margins-no-available-space.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-flow-auto-margins.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-flow-border.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-factor-less-than-one.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-flow-2.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-flow-auto-margins-no-available-space.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-flow-auto-margins.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-flow-border.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-flow-margins-auto-size.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-flow-margins.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-flow-orientations.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-flow-overflow.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-flow-padding.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-flow.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-item-child-overflow.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-flow-margins.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-flow-orientations.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-flow-overflow.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-flow-padding.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-flow.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-item-contains-strict.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-justify-content.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-no-flex.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-one-sets-flex-basis-to-zero-px.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flex-order.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flexbox-baseline-margins.html [ Skip ]
@@ -1563,49 +1544,43 @@
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flexbox-height-with-overflow-auto.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flexbox-ignore-firstLetter.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flexbox-lines-must-be-stretched-by-default.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flexbox-overflow-auto.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flexbox-overflow-auto.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flexbox-width-with-overflow-auto.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flexitem.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/flexitem.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/float-inside-flexitem.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/floated-flexbox.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/inline-flexbox-ignore-firstLine.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/inline-flexbox-wrap-vertically-width-calculation.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/intrinsic-min-width-applies-with-fixed-width.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/intrinsic-width-orthogonal-writing-mode.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/justify-content-space-between.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/line-wrapping.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/max-width-violation.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/min-size-auto.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/minimum-size-image.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/multiline-align-content-horizontal-column.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/minimum-size-image.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/multiline-align-content-horizontal-column.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/multiline-align-self.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/multiline-column-auto.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/multiline-column-overflow.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/multiline-column-auto.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/multiline-column-overflow.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/multiline-justify-content.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/multiline-min-max.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/multiline-min-preferred-width.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/multiline-reverse-wrap-baseline.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/multiline-reverse-wrap-overflow.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/multiline-reverse-wrap-overflow.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/multiline-shrink-to-fit.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/multiline.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/negative-flex-rounding-assert.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/negative-overflow.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/nested-orthogonal-flexbox-relayout.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/nested-stretch.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/nested-stretch.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/order-painting.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/orthogonal-flex-directions.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/orthogonal-writing-modes-and-intrinsic-sizing.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/orthogonal-flex-directions.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/orthogonal-writing-modes-and-intrinsic-sizing.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/overflow-and-padding.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/overflow-auto-dynamic-changes.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/overflow-auto-resizes-correctly.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/overflow-auto-resizes-correctly.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/overflow-keep-scrollpos.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/percent-margins.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/percentage-height-replaced-element.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/percentage-heights.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/percentage-max-width-cross-axis.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/percentage-sizes-quirks.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/percentage-sizes.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/perpendicular-writing-modes-inside-flex-item.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/percentage-height-replaced-element.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/percentage-heights.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/percentage-sizes-quirks.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/percentage-sizes.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/position-absolute-child.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/preferred-widths-orthogonal.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/preferred-widths.html [ Skip ]
@@ -1613,25 +1588,20 @@
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/relayout-align-items.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/relayout-image-load.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/relpos-with-percentage-top.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/resize-min-content-flexbox.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/resize-min-content-flexbox.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/scrollbars-auto.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/scrollbars.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/shrinking-column-flexbox.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/stretch-input-in-column.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/stretch-table-child.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/stretched-child-shrink-on-relayout.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/stretching-orthogonal-flows.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/stretch-input-in-column.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/stretched-child-shrink-on-relayout.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/stretching-orthogonal-flows.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/style-change.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/true-centering.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/undefined-min-width.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/vertical-flexbox-percentage-ignored.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/width-change-and-relayout-children.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/wrapping-column-dynamic-changes.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/true-centering.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/wrapping-column-dynamic-changes.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/writing-modes.html [ Failure ]
 
 ### virtual/layout_ng_experimental/css3/flexbox/mozilla/
 crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/mozilla/flexbox-items-as-stacking-contexts-2.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/mozilla/flexbox-sizing-vert-1.xhtml [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/css3/flexbox/mozilla/flexbox-sizing-vert-1.xhtml [ Failure ]
 
 ### virtual/layout_ng_experimental/external/wpt/css/css-flexbox/
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/Flexible-order.html [ Failure ]
@@ -1647,13 +1617,13 @@
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/align-content-005.htm [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/align-content-006.htm [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/align-content-wrap-001.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/align-content-wrap-002.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/align-content-wrap-002.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/align-content-wrap-003.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/align-content-wrap-004.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/align-content-wrap-004.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/align-items-001.htm [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/align-items-003.htm [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/align-items-004.htm [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/align-items-006.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/align-items-006.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/align-self-002.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/align-self-003.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/align-self-008.html [ Failure ]
@@ -1671,44 +1641,37 @@
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/css-flexbox-column-wrap.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/css-flexbox-column.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/css-flexbox-row-reverse-wrap-reverse.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/css-flexbox-row-reverse-wrap.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/css-flexbox-row-reverse.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/css-flexbox-row-wrap-reverse.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/css-flexbox-row-wrap.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/css-flexbox-row.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/css-flexbox-test1.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/display_inline-flex_exist.html [ Skip ]
-crbug.com/894457 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/dynamic-bsize-change.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-align-items-center.html [ Skip ]
-crbug.com/467127 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-aspect-ratio-img-column-001.html [ Skip ]
-crbug.com/467127 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-aspect-ratio-img-column-002.html [ Skip ]
-crbug.com/467127 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-aspect-ratio-img-column-003.html [ Skip ]
+crbug.com/467127 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-aspect-ratio-img-column-001.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-aspect-ratio-img-row-002.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-aspect-ratio-img-row-003.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-box-wrap.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-direction-with-element-insert.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-direction.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-direction-with-element-insert.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-direction.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-flow-003.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-flow-006.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-flow-007.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-flow-008.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-flow-009.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-flow-010.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-flow-011.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-flow-012.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-flow-007.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-flow-008.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-flow-009.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-flow-010.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-flow-011.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-flow-012.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-items-flexibility.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-margin-no-collapse.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-001.xht [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-002.xht [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-003.xht [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-004.xht [ Skip ]
-crbug.com/249112 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-005.xht [ Skip ]
-crbug.com/467127 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-006.xht [ Skip ]
-crbug.com/249112 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-007.xht [ Skip ]
-crbug.com/467127 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-008.xht [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-009.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-010.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-011.xht [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-001.xht [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-002.xht [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-003.xht [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-004.xht [ Failure ]
+crbug.com/249112 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-005.xht [ Failure ]
+crbug.com/467127 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-006.xht [ Failure ]
+crbug.com/249112 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-007.xht [ Failure ]
+crbug.com/467127 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-008.xht [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-height-flex-items-011.xht [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-width-flex-items-001.xht [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-width-flex-items-002.xht [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-width-flex-items-003.xht [ Failure ]
@@ -1718,10 +1681,9 @@
 crbug.com/249112 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-width-flex-items-007.xht [ Failure ]
 crbug.com/467127 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-minimum-width-flex-items-008.xht [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-order.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-wrap-002.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-wrap-003.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox-flex-direction-column-reverse.htm [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox-flex-direction-column.htm [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-wrap-002.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox-flex-direction-column-reverse.htm [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox-flex-direction-column.htm [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox-flex-wrap-flexing.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox-flex-wrap-wrap-reverse.htm [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_absolute-atomic.html [ Skip ]
@@ -1742,8 +1704,8 @@
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_align-self-flexend.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_align-self-flexstart.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_align-self-stretch.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_direction-column-reverse.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_direction-column.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_direction-column-reverse.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_direction-column.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_flex-0-0-0-unitless.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_flex-0-0-0.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_flex-0-0.html [ Failure ]
@@ -1753,10 +1715,10 @@
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_flex-0-N-0-unitless.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_flex-0-N-0.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_flex-0-N.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_flow-column-reverse-wrap-reverse.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_flow-column-reverse-wrap.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_flow-column-wrap-reverse.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_flow-column-wrap.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_flow-column-reverse-wrap-reverse.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_flow-column-reverse-wrap.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_flow-column-wrap-reverse.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_flow-column-wrap.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_flow-row-wrap-reverse.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_flow-row-wrap.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_generated-nested-flex.html [ Failure ]
@@ -1772,11 +1734,11 @@
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_justifycontent-spacearound.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_justifycontent-spacebetween-only.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_justifycontent-spacebetween.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_margin-collapse.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_margin-collapse.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_nested-flex.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_order-abspos-space-around.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_order-box.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_order.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_order.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_quirks_body.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_rtl-direction.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_rtl-flow-reverse.html [ Skip ]
@@ -1790,47 +1752,41 @@
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_wrap-reverse.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexbox_wrap.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flexible-box-float.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/layout-algorithm_algo-cross-line-002.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/layout-algorithm_algo-cross-line-002.html [ Failure ]
 crbug.com/467127 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/negative-margins-001.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/order_value.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/percentage-heights-000.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/percentage-heights-001.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/percentage-heights-002.html [ Skip ]
-crbug.com/467127 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/percentage-heights-003.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/percentage-heights-000.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/percentage-heights-002.html [ Failure ]
+crbug.com/467127 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/percentage-heights-003.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/percentage-heights-004.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/percentage-heights-005.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/percentage-heights-quirks-node.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/percentage-size-subitems-001.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/position-absolute-001.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/position-absolute-002.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/position-absolute-003.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/position-absolute-005.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/table-as-item-auto-min-width.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/table-as-item-change-cell.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/ttwf-reftest-flex-align-content-center.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/ttwf-reftest-flex-align-content-end.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/ttwf-reftest-flex-align-content-space-around.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/ttwf-reftest-flex-align-content-space-between.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/ttwf-reftest-flex-direction-column-reverse.html [ Skip ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/ttwf-reftest-flex-direction-column.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/ttwf-reftest-flex-direction-column-reverse.html [ Failure ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/ttwf-reftest-flex-direction-column.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/ttwf-reftest-flex-direction-row-reverse.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/ttwf-reftest-flex-inline.html [ Skip ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/ttwf-reftest-flex-order.html [ Failure ]
 crbug.com/467127 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/ttwf-reftest-flex-wrap-reverse.html [ Failure ]
 
 ### virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-lines/
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-lines/multi-line-wrap-reverse-column-reverse.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-lines/multi-line-wrap-reverse-column-reverse.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-lines/multi-line-wrap-reverse-row-reverse.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-lines/multi-line-wrap-with-column-reverse.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/flex-lines/multi-line-wrap-with-column-reverse.html [ Failure ]
 
 ### virtual/layout_ng_experimental/external/wpt/css/css-flexbox/getcomputedstyle/
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/getcomputedstyle/flexbox_computedstyle_display-inline.html [ Skip ]
 crbug.com/467127 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/getcomputedstyle/flexbox_computedstyle_flex-basis-0percent.html [ Failure ]
 crbug.com/467127 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/getcomputedstyle/flexbox_computedstyle_flex-shorthand-number.html [ Failure ]
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/getcomputedstyle/flexbox_computedstyle_min-height-auto.html [ Skip ]
 
 ### virtual/layout_ng_experimental/external/wpt/css/css-flexbox/order/
-crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/order/order-with-column-reverse.html [ Skip ]
+crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/order/order-with-column-reverse.html [ Failure ]
 crbug.com/591099 virtual/layout_ng_experimental/external/wpt/css/css-flexbox/order/order-with-row-reverse.html [ Failure ]
 
 # Fieldset in NG
@@ -1990,9 +1946,6 @@
 ### See crbug.com/891427 comment near the top of this file:
 ####crbug.com/613672 [ Mac ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchscreen-desktop.html [ Skip ]
 
-# This test are currently flaky.
-crbug.com/877361 virtual/threaded/fast/events/pinch/gesture-pinch-zoom-scroll-bubble.html [ Timeout Pass ]
-
 crbug.com/522648 fast/events/touch/compositor-touch-hit-rects-iframes.html [ Crash Failure Pass ]
 crbug.com/522648 virtual/mouseevent_fractional/fast/events/touch/compositor-touch-hit-rects-iframes.html [ Crash Failure Pass ]
 crbug.com/522648 virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects-iframes.html [ Skip ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
index 5d5fc92b..27ad5119 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
@@ -168704,6 +168704,11 @@
      {}
     ]
    ],
+   "html/webappapis/dynamic-markup-insertion/document-write/047-1.html": [
+    [
+     {}
+    ]
+   ],
    "html/webappapis/dynamic-markup-insertion/document-write/OWNERS": [
     [
      {}
@@ -242276,12 +242281,6 @@
      {}
     ]
    ],
-   "html/webappapis/dynamic-markup-insertion/document-write/048.html": [
-    [
-     "/html/webappapis/dynamic-markup-insertion/document-write/048.html",
-     {}
-    ]
-   ],
    "html/webappapis/dynamic-markup-insertion/document-write/049.html": [
     [
      "/html/webappapis/dynamic-markup-insertion/document-write/049.html",
@@ -327126,7 +327125,7 @@
    "support"
   ],
   "css/css-conditional/test_group_insertRule.html": [
-   "f34245ec472aa11a4ce35b4d6551e43f8d588260",
+   "5326501913db15e90a80e5ffc4eb93d62dc2e732",
    "testharness"
   ],
   "css/css-contain/META.yml": [
@@ -360546,7 +360545,7 @@
    "testharness"
   ],
   "css/css-transitions/currentcolor-animation-001.html": [
-   "4fd982a8cc77aa999c947d5c47e0aec8df8b9a92",
+   "1ffa1a358cade02d20006bd30bcab9110580ee21",
    "testharness"
   ],
   "css/css-transitions/detached-container-001.html": [
@@ -408437,12 +408436,12 @@
    "e87e9cc825dc46b3c07fa57044320508be5040d0",
    "testharness"
   ],
-  "html/webappapis/dynamic-markup-insertion/document-write/047.html": [
-   "51faf6c85f18e37422b22ec8babd491f9da523c2",
-   "testharness"
+  "html/webappapis/dynamic-markup-insertion/document-write/047-1.html": [
+   "6a43faec51071fec146390475adcd12bad3d23a6",
+   "support"
   ],
-  "html/webappapis/dynamic-markup-insertion/document-write/048.html": [
-   "51faf6c85f18e37422b22ec8babd491f9da523c2",
+  "html/webappapis/dynamic-markup-insertion/document-write/047.html": [
+   "677d3e17869f5c8fc744464c6e2c7e7bf51ebab6",
    "testharness"
   ],
   "html/webappapis/dynamic-markup-insertion/document-write/049.html": [
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-dttext-read-dttext-manual.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-dttext-read-dttext-manual.https.html
index 1fe946a..75cf3a3 100644
--- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-dttext-read-dttext-manual.https.html
+++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-dttext-read-dttext-manual.https.html
@@ -4,25 +4,20 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
-async_test(function(t) {
-  var test_data = "Clipboard write (dt/text) -> read (dt/text) test data";
-  var cb = navigator.clipboard;
-  var dt = new DataTransfer();
-  dt.items.add(test_data, "text/plain");
+promise_test(async (t) => {
+  const input = "Clipboard write (dt/text) -> read (dt/text) test data";
+  const dt = new DataTransfer();
+  dt.items.add(input, "text/plain");
 
-  cb.write(dt).then(t.step_func(() => {
-    cb.read().then(t.step_func((data) => {
-      assert_equals(data.items.length, 1);
-      data.items[0].getAsString(t.step_func((s) => {
-        assert_equals(s, test_data);
-        t.done();
-      }));
-    }), function() {
-      t.unreached_func("clipboard.read() fail");
-    });
-  }), function() {
-    t.unreached_func("clipboard.write() fail");
+  await navigator.clipboard.write(dt);
+  const output = await navigator.clipboard.read();
+
+  assert_equals(output.items.length, 1);
+  const result_promise = new Promise(resolve => {
+    output.items[0].getAsString(resolve);
   });
+  const string_output = await result_promise;
+  assert_equals(string_output, input);
 }, "Verify write and read clipboard (DataTransfer/text)");
 </script>
 Note: This is a manual test because it writes/reads to the shared system
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-dttext-read-text-manual.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-dttext-read-text-manual.https.html
index b341d92..3e68f9a5 100644
--- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-dttext-read-text-manual.https.html
+++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-dttext-read-text-manual.https.html
@@ -4,22 +4,15 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
-async_test(function(t) {
-  var test_data = "Clipboard write (dt/text) -> readText test data";
-  var cb = navigator.clipboard;
-  var dt = new DataTransfer();
-  dt.items.add(test_data, "text/plain");
+promise_test(async (t) => {
+  const input = "Clipboard write (dt/text) -> readText test data";
+  const dt = new DataTransfer();
+  dt.items.add(input, "text/plain");
 
-  cb.write(dt).then(t.step_func(() => {
-    cb.readText().then(t.step_func((data) => {
-      assert_equals(data, test_data);
-      t.done();
-    }), function() {
-      t.unreached_func("clipboard.read() fail");
-    });
-  }), function() {
-    t.unreached_func("clipboard.write() fail");
-  });
+  await navigator.clipboard.write(dt);
+  const output = await navigator.clipboard.readText();
+
+  assert_equals(output, input);
 }, "Verify write and read clipboard (DataTransfer/text)");
 </script>
 Note: This is a manual test because it writes/reads to the shared system
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-dttext-manual.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-dttext-manual.https.html
index ab11ab9..232e144 100644
--- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-dttext-manual.https.html
+++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-dttext-manual.https.html
@@ -4,22 +4,18 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
-async_test(function(t) {
-  var test_data = "Clipboard writeText -> read(dt/text) test data";
-  var cb = navigator.clipboard;
-  cb.writeText(test_data).then(t.step_func(() => {
-    cb.read().then(t.step_func((data) => {
-      assert_equals(data.items.length, 1);
-      data.items[0].getAsString(t.step_func((s) => {
-        assert_equals(s, test_data);
-        t.done();
-      }));
-    }), function() {
-      t.unreached_func("clipboard.read() fail");
-    });
-  }), function() {
-    t.unreached_func("clipboard.writeText() fail");
+promise_test(async (t) => {
+  const input = "Clipboard writeText -> read (dt/text) test data";
+
+  await navigator.clipboard.writeText(input);
+  const output = await navigator.clipboard.read();
+
+  assert_equals(output.items.length, 1);
+  const result_promise = new Promise(resolve => {
+    output.items[0].getAsString(resolve);
   });
+  const string_output = await result_promise;
+  assert_equals(string_output, input);
 }, "Verify write and read clipboard (DOMString)");
 </script>
 Note: This is a manual test because it writes/reads to the shared system
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-text-manual.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-text-manual.https.html
index a557216..783683e 100644
--- a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-text-manual.https.html
+++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-write-text-read-text-manual.https.html
@@ -4,19 +4,13 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
-async_test(function(t) {
-  var test_data = "Clipboard writeText -> readText test data";
-  var cb = navigator.clipboard;
-  cb.writeText(test_data).then(t.step_func(() => {
-    cb.readText().then(t.step_func((data) => {
-      assert_equals(data, test_data);
-      t.done();
-    }), function() {
-      t.unreached_func("clipboard.readText() fail");
-    });
-  }), function() {
-    t.unreached_func("clipboard.writeText() fail");
-  });
+promise_test(async (t) => {
+  const input = "Clipboard writeText -> readText test data";
+
+  await navigator.clipboard.writeText(input);
+  const output = await navigator.clipboard.readText();
+
+  assert_equals(output, input);
 }, "Verify write and read clipboard (DOMString)");
 </script>
 Note: This is a manual test because it writes/reads to the shared system
diff --git a/third_party/blink/web_tests/external/wpt/css/css-conditional/test_group_insertRule.html b/third_party/blink/web_tests/external/wpt/css/css-conditional/test_group_insertRule.html
index f34245ec..5326501 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-conditional/test_group_insertRule.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-conditional/test_group_insertRule.html
@@ -12,7 +12,7 @@
 @media print {}
 </style>
 </head>
-<body onload="run()">
+<body>
 <div id=log></div>
 <div id="test"></div>
 <script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/currentcolor-animation-001.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/currentcolor-animation-001.html
index 4fd982a8..1ffa1a3 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transitions/currentcolor-animation-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/currentcolor-animation-001.html
@@ -10,7 +10,7 @@
   <script src="/resources/testharnessreport.js"></script>
 <style id="style"></style>
 </head>
-<body onload="run()">
+<body>
 <div id=log></div>
 <div id="test"></div>
 <script>
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom/interfaces-expected.txt b/third_party/blink/web_tests/external/wpt/css/cssom/interfaces-expected.txt
index f66a1fe..c108aed 100644
--- a/third_party/blink/web_tests/external/wpt/css/cssom/interfaces-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/cssom/interfaces-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 376 tests; 320 PASS, 56 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 376 tests; 321 PASS, 55 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS Partial interface Document: original interface defined
 PASS Partial interface Window: original interface defined
@@ -66,7 +66,7 @@
 PASS StyleSheet interface: sheet must inherit property "media" with the proper type
 PASS StyleSheet interface: sheet must inherit property "disabled" with the proper type
 PASS StyleSheetList interface: existence and properties of interface object
-FAIL StyleSheetList interface object length assert_equals: wrong value for StyleSheetList.length expected 0 but got 1
+PASS StyleSheetList interface object length
 PASS StyleSheetList interface object name
 PASS StyleSheetList interface: existence and properties of interface prototype object
 PASS StyleSheetList interface: existence and properties of interface prototype object's "constructor" property
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/dynamic-markup-insertion/document-write/047-1.html b/third_party/blink/web_tests/external/wpt/html/webappapis/dynamic-markup-insertion/document-write/047-1.html
new file mode 100644
index 0000000..6a43fae
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/webappapis/dynamic-markup-insertion/document-write/047-1.html
@@ -0,0 +1,7 @@
+<script>
+onload = opener.t.step_func_done(function() {
+    document.write("<body>Filler Text<div id='log'></div>");
+    opener.assert_equals(document.body.textContent, "Filler Text");
+});
+</script>
+<body>FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/dynamic-markup-insertion/document-write/047.html b/third_party/blink/web_tests/external/wpt/html/webappapis/dynamic-markup-insertion/document-write/047.html
index 51faf6c8..677d3e1 100644
--- a/third_party/blink/web_tests/external/wpt/html/webappapis/dynamic-markup-insertion/document-write/047.html
+++ b/third_party/blink/web_tests/external/wpt/html/webappapis/dynamic-markup-insertion/document-write/047.html
@@ -1,15 +1,11 @@
 <!doctype html>
 <title>document.write</title>
-<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
 <script>
-var t = async_test();
-onload = function() {
-  t.step(function() {
-    document.write("<body>Filler Text<div id='log'></div>");
-    assert_equals(document.body.textContent, "Filler Text");
-  });
-  t.done();
-};
+var win;
+var t = async_test(() => {
+  win = window.open("047-1.html");
+});
+t.add_cleanup(() => win.close());
 </script>
-<body>FAIL
-<div id="log"></div>
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/dynamic-markup-insertion/document-write/048.html b/third_party/blink/web_tests/external/wpt/html/webappapis/dynamic-markup-insertion/document-write/048.html
deleted file mode 100644
index 51faf6c8..0000000
--- a/third_party/blink/web_tests/external/wpt/html/webappapis/dynamic-markup-insertion/document-write/048.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!doctype html>
-<title>document.write</title>
-<script src="/resources/testharness.js"></script><script src="/resources/testharnessreport.js"></script>
-<script>
-var t = async_test();
-onload = function() {
-  t.step(function() {
-    document.write("<body>Filler Text<div id='log'></div>");
-    assert_equals(document.body.textContent, "Filler Text");
-  });
-  t.done();
-};
-</script>
-<body>FAIL
-<div id="log"></div>
diff --git a/third_party/blink/web_tests/external/wpt/media-source/mediasource-errors-expected.txt b/third_party/blink/web_tests/external/wpt/media-source/mediasource-errors-expected.txt
deleted file mode 100644
index f090a4d..0000000
--- a/third_party/blink/web_tests/external/wpt/media-source/mediasource-errors-expected.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-This is a testharness.js-based test.
-PASS Appending media segment before the first initialization segment.
-PASS Signaling 'decode' error via endOfStream() before initialization segment has been appended.
-PASS Signaling 'network' error via endOfStream() before initialization segment has been appended.
-PASS Signaling 'decode' error via endOfStream() after initialization segment has been appended and the HTMLMediaElement has reached HAVE_METADATA.
-PASS Signaling 'network' error via endOfStream() after initialization segment has been appended and the HTMLMediaElement has reached HAVE_METADATA.
-PASS Signaling 'decode' error via segment parser loop algorithm after initialization segment has been appended.
-FAIL Signaling 'decode' error via segment parser loop algorithm. assert_unreached: 'loadedmetadata' should not be fired on mediaElement Reached unreachable code
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/media-source/mediasource-errors.html b/third_party/blink/web_tests/external/wpt/media-source/mediasource-errors.html
index 3df1ded..b2224aa 100644
--- a/third_party/blink/web_tests/external/wpt/media-source/mediasource-errors.html
+++ b/third_party/blink/web_tests/external/wpt/media-source/mediasource-errors.html
@@ -207,28 +207,67 @@
     {
         assert_equals(mediaElement.readyState, HTMLMediaElement.HAVE_NOTHING);
 
-        // Fail if the append error algorithm occurs, since the network
-        // error will be provided by us directly via endOfStream().
-        mediaElement.addEventListener("loadedmetadata", test.unreached_func("'loadedmetadata' should not be fired on mediaElement"));
-
         var mediaSegment = MediaSourceUtil.extractSegmentData(mediaData, segmentInfo.media[0]);
         var index = segmentInfo.init.size + (mediaSegment.length - 1) / 2;
         // Corrupt the media data from index of mediaData, so it can signal 'decode' error.
         // Here use mediaSegment to replace the original mediaData[index, index + mediaSegment.length]
         mediaData.set(mediaSegment, index);
 
+        // Depending on implementation, mediaElement transition to
+        // HAVE_METADATA and dispatching 'loadedmetadata' may occur, since the
+        // initialization segment is uncorrupted and forms the initial part of
+        // the appended bytes. The segment parser loop continues and
+        // eventually should observe decode error. Other implementations may
+        // delay such transition until some larger portion of the append's
+        // parsing is completed or until the media element is configured to
+        // handle the playback of media with the associated metadata (which may
+        // not occur in this case before the MSE append error algorithm executes.)
+        // So we cannot reliably expect the lack or presence of
+        // 'loadedmetadata' before the MSE append error algortihm executes in
+        // this case; similarly, mediaElement's resulting readyState may be
+        // either HAVE_NOTHING or HAVE_METADATA after the append error
+        // algorithm executes, and the resulting MediaError code would
+        // respectively be MEDIA_ERR_SRC_NOT_SUPPORTED or MEDIA_ERR_DECODE.
+        let loaded = false;
+        mediaElement.addEventListener("loadedmetadata", test.step_func(() => { loaded = true; }));
+        let errored = false;
+        mediaElement.addEventListener("error", test.step_func(() => { errored = true; }));
+
         test.expectEvent(sourceBuffer, "error", "sourceBuffer error.");
         test.expectEvent(sourceBuffer, "updateend", "mediaSegment append ended.");
-        test.expectEvent(mediaElement, "error", "mediaElement error.");
         test.expectEvent(mediaSource, "sourceended", "mediaSource ended.");
         sourceBuffer.appendBuffer(mediaData);
 
+        let verifyFinalState = test.step_func(function() {
+            if (loaded) {
+                assert_greater_than(mediaElement.readyState, HTMLMediaElement.HAVE_NOTHING);
+                assert_true(mediaElement.error != null);
+                assert_equals(mediaElement.error.code, MediaError.MEDIA_ERR_DECODE);
+                test.done();
+            } else {
+                assert_equals(mediaElement.readyState, HTMLMediaElement.HAVE_NOTHING);
+                assert_true(mediaElement.error != null);
+                assert_equals(mediaElement.error.code, MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED);
+                test.done();
+            }
+        });
+
+        let awaitMediaElementError = test.step_func(function() {
+            if (!errored) {
+                test.step_timeout(awaitMediaElementError, 100);
+            } else {
+                verifyFinalState();
+            }
+        });
+
         test.waitForExpectedEvents(function()
         {
-            assert_equals(mediaElement.readyState, HTMLMediaElement.HAVE_NOTHING);
-            assert_true(mediaElement.error != null);
-            assert_equals(mediaElement.error.code, MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED);
-            test.done();
+            // Not all implementations will reliably fire a "loadedmetadata"
+            // event, so we use custom logic to verify mediaElement state based
+            // on whether or not "loadedmetadata" was ever fired. But first
+            // we must ensure "error" was fired on the mediaElement.
+            awaitMediaElementError();
         });
-    }, "Signaling 'decode' error via segment parser loop algorithm.");
+
+    }, "Signaling 'decode' error via segment parser loop algorithm of append containing init plus corrupted media segment.");
 </script>
diff --git a/third_party/blink/web_tests/fast/css/CSSStyleSheet-constructable.html b/third_party/blink/web_tests/fast/css/CSSStyleSheet-constructable.html
index aa9546e8..a2809c6 100644
--- a/third_party/blink/web_tests/fast/css/CSSStyleSheet-constructable.html
+++ b/third_party/blink/web_tests/fast/css/CSSStyleSheet-constructable.html
@@ -137,8 +137,7 @@
     const yellowStyleSheet = values[4];
 
     // Lists of style sheets can be created, assigned and read.
-    const whiteList = new StyleSheetList([whiteStyleSheet]);
-    document.adoptedStyleSheets = whiteList;
+    document.adoptedStyleSheets = [whiteStyleSheet];
     // alternate stylesheets aren't applied when title != current preferable name
     assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(redSpan).color, "rgb(0, 0, 0)");
@@ -146,7 +145,7 @@
     assert_equals(getComputedStyle(whiteSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(yellowSpan).color, "rgb(0, 0, 0)");
 
-    document.adoptedStyleSheets = new StyleSheetList([greenStyleSheet, blueStyleSheet]);
+    document.adoptedStyleSheets = [greenStyleSheet, blueStyleSheet];
     // disabled stylesheets aren't applied
     assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 128, 0)");
     assert_equals(getComputedStyle(redSpan).color, "rgb(0, 0, 0)");
@@ -154,8 +153,7 @@
     assert_equals(getComputedStyle(whiteSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(yellowSpan).color, "rgb(0, 0, 0)");
 
-    const orangeList = new StyleSheetList([redStyleSheet, yellowStyleSheet]);
-    document.adoptedStyleSheets = orangeList;
+    document.adoptedStyleSheets = [redStyleSheet, yellowStyleSheet];
 
     assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(redSpan).color, "rgb(255, 0, 0)");
@@ -163,7 +161,7 @@
     assert_equals(getComputedStyle(whiteSpan).color, "rgb(255, 0, 0)");
     assert_equals(getComputedStyle(yellowSpan).color, "rgb(255, 255, 0)");
 
-    document.adoptedStyleSheets = new StyleSheetList([redStyleSheet, yellowStyleSheet, greenStyleSheet, blueStyleSheet]);
+    document.adoptedStyleSheets = [redStyleSheet, yellowStyleSheet, greenStyleSheet, blueStyleSheet];
     assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 128, 0)");
     assert_equals(getComputedStyle(redSpan).color, "rgb(255, 0, 0)");
     assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
@@ -179,29 +177,28 @@
     const blueStyleSheet = values[2];
     const whiteStyleSheet = values[3];
     const yellowStyleSheet = values[4];
-    shadowRoot.adoptedStyleSheets = new StyleSheetList([whiteStyleSheet]);
+    shadowRoot.adoptedStyleSheets = [whiteStyleSheet];
     assert_equals(getComputedStyle(greenShadowSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(redShadowSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(blueShadowSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(whiteShadowSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(yellowShadowSpan).color, "rgb(0, 0, 0)");
 
-    shadowRoot.adoptedStyleSheets = new StyleSheetList([greenStyleSheet, blueStyleSheet]);
+    shadowRoot.adoptedStyleSheets = [greenStyleSheet, blueStyleSheet];
     assert_equals(getComputedStyle(greenShadowSpan).color, "rgb(0, 128, 0)");
     assert_equals(getComputedStyle(redShadowSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(blueShadowSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(whiteShadowSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(yellowShadowSpan).color, "rgb(0, 0, 0)");
 
-    const orangeList = new StyleSheetList([redStyleSheet, yellowStyleSheet]);
-    shadowRoot.adoptedStyleSheets = orangeList;
+    shadowRoot.adoptedStyleSheets = [redStyleSheet, yellowStyleSheet];
     assert_equals(getComputedStyle(greenShadowSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(redShadowSpan).color, "rgb(255, 0, 0)");
     assert_equals(getComputedStyle(blueShadowSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(whiteShadowSpan).color, "rgb(255, 0, 0)");
     assert_equals(getComputedStyle(yellowShadowSpan).color, "rgb(255, 255, 0)");
 
-    shadowRoot.adoptedStyleSheets = new StyleSheetList([redStyleSheet, yellowStyleSheet, greenStyleSheet, blueStyleSheet]);
+    shadowRoot.adoptedStyleSheets = [redStyleSheet, yellowStyleSheet, greenStyleSheet, blueStyleSheet];
     assert_equals(getComputedStyle(greenShadowSpan).color, "rgb(0, 128, 0)");
     assert_equals(getComputedStyle(redShadowSpan).color, "rgb(255, 0, 0)");
     assert_equals(getComputedStyle(blueShadowSpan).color, "rgb(0, 0, 0)");
@@ -214,7 +211,7 @@
   const plainSheet = new CSSStyleSheet();
   const redStyleSheetPromise = plainSheet.replace(redStyleTexts[0]);
   return redStyleSheetPromise.then(function(redStyleSheet) {
-    document.adoptedStyleSheets = new StyleSheetList([redStyleSheet]);
+    document.adoptedStyleSheets = [redStyleSheet];
     assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(redSpan).color, "rgb(255, 0, 0)");
     assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
@@ -248,8 +245,8 @@
   const plainSheet = new CSSStyleSheet();
   const redStyleSheetPromise = plainSheet.replace(redStyleTexts[0]);
   return redStyleSheetPromise.then(function(redStyleSheet) {
-    document.adoptedStyleSheets = new StyleSheetList([redStyleSheet]);
-    shadowRoot.adoptedStyleSheets = new StyleSheetList([redStyleSheet]);
+    document.adoptedStyleSheets = [redStyleSheet];
+    shadowRoot.adoptedStyleSheets = [redStyleSheet];
     assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(redSpan).color, "rgb(255, 0, 0)");
     assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
@@ -291,14 +288,14 @@
   const plainSheet = new CSSStyleSheet();
   const redStyleSheetPromise = plainSheet.replace(redStyleTexts[0]);
   return redStyleSheetPromise.then(function(redStyleSheet) {
-    assert_throws('NotAllowedError', () => { iframe.contentDocument.adoptedStyleSheets = new StyleSheetList([redStyleSheet]); });
+    assert_throws('NotAllowedError', () => { iframe.contentDocument.adoptedStyleSheets = [redStyleSheet]; });
     assert_equals(getComputedStyle(greenIframeSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(redIframeSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(blueIframeSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(whiteIframeSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(yellowIframeSpan).color, "rgb(0, 0, 0)");
 
-    document.adoptedStyleSheets = new StyleSheetList([redStyleSheet]);
+    document.adoptedStyleSheets = [redStyleSheet];
     assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(redSpan).color, "rgb(255, 0, 0)");
     assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
@@ -327,7 +324,7 @@
 
   // Make sure both the main Document and the iframe are not styled
   const emptyStyleSheet = new CSSStyleSheet();
-  document.adoptedStyleSheets = new StyleSheetList([emptyStyleSheet]);
+  document.adoptedStyleSheets = [emptyStyleSheet];
   assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 0, 0)");
   assert_equals(getComputedStyle(redSpan).color, "rgb(0, 0, 0)");
   assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
@@ -343,14 +340,14 @@
   const iframePlainSheet = new iframe.contentWindow.CSSStyleSheet();
   const iframeRedStyleSheetPromise = iframePlainSheet.replace(redStyleTexts[0]);
   return iframeRedStyleSheetPromise.then(function(iframeRedStyleSheet) {
-    assert_throws('NotAllowedError', () => { document.adoptedStyleSheets = new StyleSheetList([iframeRedStyleSheet]); });
+    assert_throws('NotAllowedError', () => { document.adoptedStyleSheets = [iframeRedStyleSheet]; });
     assert_equals(getComputedStyle(greenSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(redSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(blueSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(whiteSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(yellowSpan).color, "rgb(0, 0, 0)");
 
-    iframe.contentDocument.adoptedStyleSheets = new StyleSheetList([iframeRedStyleSheet]);
+    iframe.contentDocument.adoptedStyleSheets = [iframeRedStyleSheet];
     assert_equals(getComputedStyle(greenIframeSpan).color, "rgb(0, 0, 0)");
     assert_equals(getComputedStyle(redIframeSpan).color, "rgb(255, 0, 0)");
     assert_equals(getComputedStyle(blueIframeSpan).color, "rgb(0, 0, 0)");
@@ -380,7 +377,7 @@
 
 test(() => {
   assert_equals(getComputedStyle(divNonConstructed).color, "rgb(0, 0, 0)");
-  assert_throws('NotAllowedError', () => { document.adoptedStyleSheets = new StyleSheetList([nonConstructedStyleSheet]); });
+  assert_throws('NotAllowedError', () => { document.adoptedStyleSheets = [nonConstructedStyleSheet]; });
 }, 'Adding non-constructed stylesheet to AdoptedStyleSheets is not allowed when the owner document of the stylesheet is in the same document tree as the AdoptedStyleSheets');
 
 test(() => {
@@ -391,7 +388,7 @@
   iframe.contentDocument.body.appendChild(iframeDiv);
 
   assert_equals(getComputedStyle(iframeDiv).color, "rgb(0, 0, 0)");
-  assert_throws('NotAllowedError', () => { iframe.contentDocument.adoptedStyleSheets = new StyleSheetList([nonConstructedStyleSheet]); });
+  assert_throws('NotAllowedError', () => { iframe.contentDocument.adoptedStyleSheets = [nonConstructedStyleSheet]; });
   assert_equals(getComputedStyle(iframeDiv).color, "rgb(0, 0, 0)");
 
   iframeStyle = iframe.contentDocument.createElement("style");
@@ -403,7 +400,7 @@
   divNonConstructed.appendChild(nonConstructedSpan);
 
   assert_equals(getComputedStyle(iframeDiv).color, "rgb(0, 0, 0)");
-  assert_throws('NotAllowedError', () => { document.adoptedStyleSheets = new StyleSheetList([iframeStyleSheet]); });
+  assert_throws('NotAllowedError', () => { document.adoptedStyleSheets = [iframeStyleSheet]; });
   assert_equals(getComputedStyle(iframeDiv).color, "rgb(0, 0, 0)");
 }, 'Adding non-constructed stylesheet to AdoptedStyleSheets is not allowed when the owner document of the stylesheet and the AdoptedStyleSheets are in different document trees');
 
@@ -422,7 +419,7 @@
   shadowDiv.classList.add("red");
   // Create empty stylesheet.
   const sheet = new CSSStyleSheet();
-  span.shadowRoot.adoptedStyleSheets = new StyleSheetList([sheet]);
+  span.shadowRoot.adoptedStyleSheets = [sheet];
   assert_equals(getComputedStyle(shadowDiv).color, "rgb(0, 0, 0)");
   // Replace the stylesheet text that will color it red.
   sheet.replaceSync(redStyleTexts[0]);
@@ -449,7 +446,7 @@
   thirdSection.appendChild(span);
   const shadowDiv = attachShadowDiv(span);
   const sheet = new CSSStyleSheet();
-  span.shadowRoot.adoptedStyleSheets = new StyleSheetList([sheet]);
+  span.shadowRoot.adoptedStyleSheets = [sheet];
   assert_equals(getComputedStyle(shadowDiv).color, "rgb(0, 0, 0)");
   // Replace and assert that the imported rule is applied.
   const sheet_promise = sheet.replace(import_text);
diff --git a/third_party/blink/web_tests/http/tests/devtools/coverage/coverage-export-expected.txt b/third_party/blink/web_tests/http/tests/devtools/coverage/coverage-export-expected.txt
new file mode 100644
index 0000000..8d20964
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/devtools/coverage/coverage-export-expected.txt
@@ -0,0 +1,73 @@
+Tests the coverage export functionality and format.
+
+
+
+File: http://127.0.0.1:8000/devtools/coverage/resources/highlight-in-source.css
+
+Usage:
+body {
+    background-color: lightblue;
+}
+
+Usage:
+.class {
+    color: red;
+}
+
+
+File: http://127.0.0.1:8000/devtools/coverage/resources/basic-coverage.html
+
+Usage:
+function foo() {}
+foo();
+
+Usage:
+function bar() {}
+bar();
+
+
+File: http://127.0.0.1:8000/devtools/coverage/resources/coverage.js
+
+Usage:
+function outer(index) {
+
+Usage:
+function inner2(a) {
+    return a + 2;
+
+Usage:
+}
+
+Usage:
+function inner4(a) { return a + 4;
+
+Usage:
+}
+
+Usage:
+if (index === 7)
+
+Usage:
+// Make sure these are not collected.
+  if (!self.__funcs)
+    self.__funcs = [inner1, inner2, inner3, inner4, inner5];
+  return self.__funcs[index];
+
+Usage:
+}
+
+function performActions() {
+  return outer(1)(0) + outer(3)(0);
+
+Usage:
+}
+
+Usage:
+
+
+
+File: test://evaluations/0/coverage-export.js
+
+Usage:
+performActions()//# sourceURL=test://evaluations/0/coverage-export.js
+
diff --git a/third_party/blink/web_tests/http/tests/devtools/coverage/coverage-export.js b/third_party/blink/web_tests/http/tests/devtools/coverage/coverage-export.js
new file mode 100644
index 0000000..789d57d
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/devtools/coverage/coverage-export.js
@@ -0,0 +1,22 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(async function() {
+  TestRunner.addResult(`Tests the coverage export functionality and format.\n`);
+  await TestRunner.loadModule('coverage_test_runner');
+  await TestRunner.navigatePromise(TestRunner.url('resources/basic-coverage.html'));
+
+  CoverageTestRunner.startCoverage();
+  await TestRunner.evaluateInPagePromise('performActions()');
+  await CoverageTestRunner.stopCoverage();
+  const report = JSON.parse(await CoverageTestRunner.exportReport());
+  for (const entry of report) {
+    TestRunner.addResult('\n\nFile: ' + entry.url);
+    for (const range of entry.ranges) {
+      TestRunner.addResult('\nUsage:');
+      TestRunner.addResult(entry.text.substring(range.start, range.end).trim());
+    }
+  }
+  TestRunner.completeTest();
+})();
diff --git a/third_party/blink/web_tests/http/tests/devtools/coverage/coverage-view-expected.txt b/third_party/blink/web_tests/http/tests/devtools/coverage/coverage-view-expected.txt
index 8cd67b1..202ff8f 100644
--- a/third_party/blink/web_tests/http/tests/devtools/coverage/coverage-view-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/coverage/coverage-view-expected.txt
@@ -2,8 +2,10 @@
 
 .../devtools/coverage/resources/coverage.js JS (coarse) used: 411 unused: 157 total: 568
 .../devtools/coverage/resources/highlight-in-source.css CSS used: 67 unused: 142 total: 209
+.../devtools/coverage/resources/basic-coverage.html JS (coarse) used: 51 unused: 0 total: 51
 Reloading Page
 Page reloaded.
 .../devtools/coverage/resources/coverage.js JS used: 354 unused: 214 total: 568
 .../devtools/coverage/resources/highlight-in-source.css CSS used: 67 unused: 142 total: 209
+.../devtools/coverage/resources/basic-coverage.html JS used: 51 unused: 0 total: 51
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/coverage/coverage-view-filter-expected.txt b/third_party/blink/web_tests/http/tests/devtools/coverage/coverage-view-filter-expected.txt
index be6ff9b..d6a1202 100644
--- a/third_party/blink/web_tests/http/tests/devtools/coverage/coverage-view-filter-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/coverage/coverage-view-filter-expected.txt
@@ -3,10 +3,12 @@
 Filter: devtools
 .../devtools/coverage/resources/coverage.js JS used: 354 unused: 214 total: 568
 .../devtools/coverage/resources/highlight-in-source.css CSS used: 67 unused: 142 total: 209
+.../devtools/coverage/resources/basic-coverage.html JS used: 51 unused: 0 total: 51
 Filter: CES/COV
 .../devtools/coverage/resources/coverage.js JS used: 354 unused: 214 total: 568
 Filter: no pasaran
 Filter: 
 .../devtools/coverage/resources/coverage.js JS used: 354 unused: 214 total: 568
 .../devtools/coverage/resources/highlight-in-source.css CSS used: 67 unused: 142 total: 209
+.../devtools/coverage/resources/basic-coverage.html JS used: 51 unused: 0 total: 51
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/coverage/resources/basic-coverage.html b/third_party/blink/web_tests/http/tests/devtools/coverage/resources/basic-coverage.html
index 11186425..937aa5c 100644
--- a/third_party/blink/web_tests/http/tests/devtools/coverage/resources/basic-coverage.html
+++ b/third_party/blink/web_tests/http/tests/devtools/coverage/resources/basic-coverage.html
@@ -3,6 +3,15 @@
 <link rel="stylesheet" type="text/css" href="highlight-in-source.css">
 </head>
 <body>
+<script>
+function foo() {}
+foo();
+</script>
+
+                 <script>function bar() {}
+bar();
+</script>
+
 <script src="coverage.js"></script>
 <p class="class"></p>
 </body>
diff --git a/third_party/libaom/README.chromium b/third_party/libaom/README.chromium
index e7c3dc0..b4825e2 100644
--- a/third_party/libaom/README.chromium
+++ b/third_party/libaom/README.chromium
@@ -2,9 +2,9 @@
 Short Name: libaom
 URL: https://aomedia.googlesource.com/aom/
 Version: 0
-Date: Monday November 26 2018
-Branch: m72
-Commit: 67223a304e098da309776bac253456f75f613fc2
+Date: Friday December 07 2018
+Branch: master
+Commit: 98dae942edd3032c89b0e8bae9b4d50398931405
 License: BSD
 License File: source/libaom/LICENSE
 Security Critical: yes
diff --git a/third_party/libaom/libaom_srcs.gni b/third_party/libaom/libaom_srcs.gni
index dc3407b..786bfa6 100644
--- a/third_party/libaom/libaom_srcs.gni
+++ b/third_party/libaom/libaom_srcs.gni
@@ -211,6 +211,9 @@
   "//third_party/libaom/source/libaom/av1/encoder/x86/wedge_utils_sse2.c",
 ]
 
+aom_av1_encoder_intrin_sse3 =
+    [ "//third_party/libaom/source/libaom/av1/encoder/x86/ml_sse3.c" ]
+
 aom_av1_encoder_intrin_sse4_1 = [
   "//third_party/libaom/source/libaom/av1/encoder/x86/av1_fwd_txfm1d_sse4.c",
   "//third_party/libaom/source/libaom/av1/encoder/x86/av1_fwd_txfm2d_sse4.c",
diff --git a/third_party/libaom/source/config/config/aom_version.h b/third_party/libaom/source/config/config/aom_version.h
index dca5744..47e75fa 100644
--- a/third_party/libaom/source/config/config/aom_version.h
+++ b/third_party/libaom/source/config/config/aom_version.h
@@ -12,8 +12,8 @@
 #define VERSION_MAJOR 1
 #define VERSION_MINOR 0
 #define VERSION_PATCH 0
-#define VERSION_EXTRA "900-g67223a304"
+#define VERSION_EXTRA "1012-g98dae942e"
 #define VERSION_PACKED \
   ((VERSION_MAJOR << 16) | (VERSION_MINOR << 8) | (VERSION_PATCH))
-#define VERSION_STRING_NOSP "1.0.0-900-g67223a304"
-#define VERSION_STRING " 1.0.0-900-g67223a304"
+#define VERSION_STRING_NOSP "1.0.0-1012-g98dae942e"
+#define VERSION_STRING " 1.0.0-1012-g98dae942e"
diff --git a/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/aom_config.asm b/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/aom_config.asm
index e1142f1f..a95c691 100644
--- a/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/aom_config.asm
+++ b/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/aom_config.asm
@@ -25,6 +25,7 @@
 CONFIG_COLLECT_RD_STATS equ 0
 CONFIG_DEBUG equ 0
 CONFIG_DENOISE equ 1
+CONFIG_DISABLE_FULL_PIXEL_SPLIT_8X8 equ 1
 CONFIG_DIST_8X8 equ 0
 CONFIG_ENTROPY_STATS equ 0
 CONFIG_FILEOPTIONS equ 1
diff --git a/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/aom_config.h b/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/aom_config.h
index 7cdea33..8b17412 100644
--- a/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/aom_config.h
+++ b/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/aom_config.h
@@ -27,6 +27,7 @@
 #define CONFIG_COLLECT_RD_STATS 0
 #define CONFIG_DEBUG 0
 #define CONFIG_DENOISE 1
+#define CONFIG_DISABLE_FULL_PIXEL_SPLIT_8X8 1
 #define CONFIG_DIST_8X8 0
 #define CONFIG_ENTROPY_STATS 0
 #define CONFIG_FILEOPTIONS 1
diff --git a/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/aom_dsp_rtcd.h b/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/aom_dsp_rtcd.h
index f1e8d1c..db63827 100644
--- a/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/aom_dsp_rtcd.h
+++ b/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/aom_dsp_rtcd.h
@@ -3452,10 +3452,6 @@
                                         const uint8_t* above,
                                         const uint8_t* left);
 
-void av1_round_shift_array_c(int32_t* arr, int size, int bit);
-void av1_round_shift_array_neon(int32_t* arr, int size, int bit);
-RTCD_EXTERN void (*av1_round_shift_array)(int32_t* arr, int size, int bit);
-
 void aom_dsp_rtcd(void);
 
 #include "config/aom_config.h"
@@ -3587,9 +3583,6 @@
   aom_v_predictor_8x8 = aom_v_predictor_8x8_c;
   if (flags & HAS_NEON)
     aom_v_predictor_8x8 = aom_v_predictor_8x8_neon;
-  av1_round_shift_array = av1_round_shift_array_c;
-  if (flags & HAS_NEON)
-    av1_round_shift_array = av1_round_shift_array_neon;
 }
 #endif
 
diff --git a/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/aom_scale_rtcd.h b/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/aom_scale_rtcd.h
index ac22c47..c8fa3a4 100644
--- a/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/aom_scale_rtcd.h
+++ b/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/aom_scale_rtcd.h
@@ -92,28 +92,58 @@
                                      const int num_planes);
 #define aom_yv12_extend_frame_borders aom_yv12_extend_frame_borders_c
 
+void aom_yv12_partial_coloc_copy_u_c(const struct yv12_buffer_config* src_bc,
+                                     struct yv12_buffer_config* dst_bc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_u aom_yv12_partial_coloc_copy_u_c
+
+void aom_yv12_partial_coloc_copy_v_c(const struct yv12_buffer_config* src_bc,
+                                     struct yv12_buffer_config* dst_bc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_v aom_yv12_partial_coloc_copy_v_c
+
+void aom_yv12_partial_coloc_copy_y_c(const struct yv12_buffer_config* src_ybc,
+                                     struct yv12_buffer_config* dst_ybc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_y aom_yv12_partial_coloc_copy_y_c
+
 void aom_yv12_partial_copy_u_c(const struct yv12_buffer_config* src_bc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_bc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_u aom_yv12_partial_copy_u_c
 
 void aom_yv12_partial_copy_v_c(const struct yv12_buffer_config* src_bc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_bc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_v aom_yv12_partial_copy_v_c
 
 void aom_yv12_partial_copy_y_c(const struct yv12_buffer_config* src_ybc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_ybc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_y aom_yv12_partial_copy_y_c
 
 void aom_scale_rtcd(void);
diff --git a/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/av1_rtcd.h b/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/av1_rtcd.h
index d232554..887c3b6 100644
--- a/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/linux/arm-neon-cpu-detect/config/av1_rtcd.h
@@ -31,6 +31,8 @@
 struct aom_variance_vtable;
 struct search_site_config;
 struct yv12_buffer_config;
+struct NN_CONFIG;
+typedef struct NN_CONFIG NN_CONFIG;
 
 /* Function pointers return by CfL functions */
 typedef void (*cfl_subsample_lbd_fn)(const uint8_t* input,
@@ -1024,6 +1026,10 @@
     const int subpel_y_q4,
     ConvolveParams* conv_params);
 
+void av1_round_shift_array_c(int32_t* arr, int size, int bit);
+void av1_round_shift_array_neon(int32_t* arr, int size, int bit);
+RTCD_EXTERN void (*av1_round_shift_array)(int32_t* arr, int size, int bit);
+
 int av1_selfguided_restoration_c(const uint8_t* dgd8,
                                  int width,
                                  int height,
@@ -1323,6 +1329,9 @@
   av1_jnt_convolve_y = av1_jnt_convolve_y_c;
   if (flags & HAS_NEON)
     av1_jnt_convolve_y = av1_jnt_convolve_y_neon;
+  av1_round_shift_array = av1_round_shift_array_c;
+  if (flags & HAS_NEON)
+    av1_round_shift_array = av1_round_shift_array_neon;
   av1_selfguided_restoration = av1_selfguided_restoration_c;
   if (flags & HAS_NEON)
     av1_selfguided_restoration = av1_selfguided_restoration_neon;
diff --git a/third_party/libaom/source/config/linux/arm-neon/config/aom_config.asm b/third_party/libaom/source/config/linux/arm-neon/config/aom_config.asm
index 1562f51..1193fe26 100644
--- a/third_party/libaom/source/config/linux/arm-neon/config/aom_config.asm
+++ b/third_party/libaom/source/config/linux/arm-neon/config/aom_config.asm
@@ -25,6 +25,7 @@
 CONFIG_COLLECT_RD_STATS equ 0
 CONFIG_DEBUG equ 0
 CONFIG_DENOISE equ 1
+CONFIG_DISABLE_FULL_PIXEL_SPLIT_8X8 equ 1
 CONFIG_DIST_8X8 equ 0
 CONFIG_ENTROPY_STATS equ 0
 CONFIG_FILEOPTIONS equ 1
diff --git a/third_party/libaom/source/config/linux/arm-neon/config/aom_config.h b/third_party/libaom/source/config/linux/arm-neon/config/aom_config.h
index 76a27fea..cd3baad 100644
--- a/third_party/libaom/source/config/linux/arm-neon/config/aom_config.h
+++ b/third_party/libaom/source/config/linux/arm-neon/config/aom_config.h
@@ -27,6 +27,7 @@
 #define CONFIG_COLLECT_RD_STATS 0
 #define CONFIG_DEBUG 0
 #define CONFIG_DENOISE 1
+#define CONFIG_DISABLE_FULL_PIXEL_SPLIT_8X8 1
 #define CONFIG_DIST_8X8 0
 #define CONFIG_ENTROPY_STATS 0
 #define CONFIG_FILEOPTIONS 1
diff --git a/third_party/libaom/source/config/linux/arm-neon/config/aom_dsp_rtcd.h b/third_party/libaom/source/config/linux/arm-neon/config/aom_dsp_rtcd.h
index 8acb85d..dd882516 100644
--- a/third_party/libaom/source/config/linux/arm-neon/config/aom_dsp_rtcd.h
+++ b/third_party/libaom/source/config/linux/arm-neon/config/aom_dsp_rtcd.h
@@ -3300,10 +3300,6 @@
                               const uint8_t* left);
 #define aom_v_predictor_8x8 aom_v_predictor_8x8_neon
 
-void av1_round_shift_array_c(int32_t* arr, int size, int bit);
-void av1_round_shift_array_neon(int32_t* arr, int size, int bit);
-#define av1_round_shift_array av1_round_shift_array_neon
-
 void aom_dsp_rtcd(void);
 
 #include "config/aom_config.h"
diff --git a/third_party/libaom/source/config/linux/arm-neon/config/aom_scale_rtcd.h b/third_party/libaom/source/config/linux/arm-neon/config/aom_scale_rtcd.h
index ac22c47..c8fa3a4 100644
--- a/third_party/libaom/source/config/linux/arm-neon/config/aom_scale_rtcd.h
+++ b/third_party/libaom/source/config/linux/arm-neon/config/aom_scale_rtcd.h
@@ -92,28 +92,58 @@
                                      const int num_planes);
 #define aom_yv12_extend_frame_borders aom_yv12_extend_frame_borders_c
 
+void aom_yv12_partial_coloc_copy_u_c(const struct yv12_buffer_config* src_bc,
+                                     struct yv12_buffer_config* dst_bc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_u aom_yv12_partial_coloc_copy_u_c
+
+void aom_yv12_partial_coloc_copy_v_c(const struct yv12_buffer_config* src_bc,
+                                     struct yv12_buffer_config* dst_bc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_v aom_yv12_partial_coloc_copy_v_c
+
+void aom_yv12_partial_coloc_copy_y_c(const struct yv12_buffer_config* src_ybc,
+                                     struct yv12_buffer_config* dst_ybc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_y aom_yv12_partial_coloc_copy_y_c
+
 void aom_yv12_partial_copy_u_c(const struct yv12_buffer_config* src_bc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_bc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_u aom_yv12_partial_copy_u_c
 
 void aom_yv12_partial_copy_v_c(const struct yv12_buffer_config* src_bc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_bc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_v aom_yv12_partial_copy_v_c
 
 void aom_yv12_partial_copy_y_c(const struct yv12_buffer_config* src_ybc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_ybc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_y aom_yv12_partial_copy_y_c
 
 void aom_scale_rtcd(void);
diff --git a/third_party/libaom/source/config/linux/arm-neon/config/av1_rtcd.h b/third_party/libaom/source/config/linux/arm-neon/config/av1_rtcd.h
index e7dfcc6..17bde5be 100644
--- a/third_party/libaom/source/config/linux/arm-neon/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/linux/arm-neon/config/av1_rtcd.h
@@ -31,6 +31,8 @@
 struct aom_variance_vtable;
 struct search_site_config;
 struct yv12_buffer_config;
+struct NN_CONFIG;
+typedef struct NN_CONFIG NN_CONFIG;
 
 /* Function pointers return by CfL functions */
 typedef void (*cfl_subsample_lbd_fn)(const uint8_t* input,
@@ -916,6 +918,10 @@
                              ConvolveParams* conv_params);
 #define av1_jnt_convolve_y av1_jnt_convolve_y_neon
 
+void av1_round_shift_array_c(int32_t* arr, int size, int bit);
+void av1_round_shift_array_neon(int32_t* arr, int size, int bit);
+#define av1_round_shift_array av1_round_shift_array_neon
+
 int av1_selfguided_restoration_c(const uint8_t* dgd8,
                                  int width,
                                  int height,
diff --git a/third_party/libaom/source/config/linux/arm/config/aom_config.asm b/third_party/libaom/source/config/linux/arm/config/aom_config.asm
index 2f62800c..bc29245 100644
--- a/third_party/libaom/source/config/linux/arm/config/aom_config.asm
+++ b/third_party/libaom/source/config/linux/arm/config/aom_config.asm
@@ -25,6 +25,7 @@
 CONFIG_COLLECT_RD_STATS equ 0
 CONFIG_DEBUG equ 0
 CONFIG_DENOISE equ 1
+CONFIG_DISABLE_FULL_PIXEL_SPLIT_8X8 equ 1
 CONFIG_DIST_8X8 equ 0
 CONFIG_ENTROPY_STATS equ 0
 CONFIG_FILEOPTIONS equ 1
diff --git a/third_party/libaom/source/config/linux/arm/config/aom_config.h b/third_party/libaom/source/config/linux/arm/config/aom_config.h
index 2f841ba..2706da50 100644
--- a/third_party/libaom/source/config/linux/arm/config/aom_config.h
+++ b/third_party/libaom/source/config/linux/arm/config/aom_config.h
@@ -27,6 +27,7 @@
 #define CONFIG_COLLECT_RD_STATS 0
 #define CONFIG_DEBUG 0
 #define CONFIG_DENOISE 1
+#define CONFIG_DISABLE_FULL_PIXEL_SPLIT_8X8 1
 #define CONFIG_DIST_8X8 0
 #define CONFIG_ENTROPY_STATS 0
 #define CONFIG_FILEOPTIONS 1
diff --git a/third_party/libaom/source/config/linux/arm/config/aom_dsp_rtcd.h b/third_party/libaom/source/config/linux/arm/config/aom_dsp_rtcd.h
index 90e6c9da..30775ae 100644
--- a/third_party/libaom/source/config/linux/arm/config/aom_dsp_rtcd.h
+++ b/third_party/libaom/source/config/linux/arm/config/aom_dsp_rtcd.h
@@ -3108,9 +3108,6 @@
                            const uint8_t* left);
 #define aom_v_predictor_8x8 aom_v_predictor_8x8_c
 
-void av1_round_shift_array_c(int32_t* arr, int size, int bit);
-#define av1_round_shift_array av1_round_shift_array_c
-
 void aom_dsp_rtcd(void);
 
 #include "config/aom_config.h"
diff --git a/third_party/libaom/source/config/linux/arm/config/aom_scale_rtcd.h b/third_party/libaom/source/config/linux/arm/config/aom_scale_rtcd.h
index ac22c47..c8fa3a4 100644
--- a/third_party/libaom/source/config/linux/arm/config/aom_scale_rtcd.h
+++ b/third_party/libaom/source/config/linux/arm/config/aom_scale_rtcd.h
@@ -92,28 +92,58 @@
                                      const int num_planes);
 #define aom_yv12_extend_frame_borders aom_yv12_extend_frame_borders_c
 
+void aom_yv12_partial_coloc_copy_u_c(const struct yv12_buffer_config* src_bc,
+                                     struct yv12_buffer_config* dst_bc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_u aom_yv12_partial_coloc_copy_u_c
+
+void aom_yv12_partial_coloc_copy_v_c(const struct yv12_buffer_config* src_bc,
+                                     struct yv12_buffer_config* dst_bc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_v aom_yv12_partial_coloc_copy_v_c
+
+void aom_yv12_partial_coloc_copy_y_c(const struct yv12_buffer_config* src_ybc,
+                                     struct yv12_buffer_config* dst_ybc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_y aom_yv12_partial_coloc_copy_y_c
+
 void aom_yv12_partial_copy_u_c(const struct yv12_buffer_config* src_bc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_bc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_u aom_yv12_partial_copy_u_c
 
 void aom_yv12_partial_copy_v_c(const struct yv12_buffer_config* src_bc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_bc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_v aom_yv12_partial_copy_v_c
 
 void aom_yv12_partial_copy_y_c(const struct yv12_buffer_config* src_ybc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_ybc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_y aom_yv12_partial_copy_y_c
 
 void aom_scale_rtcd(void);
diff --git a/third_party/libaom/source/config/linux/arm/config/av1_rtcd.h b/third_party/libaom/source/config/linux/arm/config/av1_rtcd.h
index 321db50..09d2012 100644
--- a/third_party/libaom/source/config/linux/arm/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/linux/arm/config/av1_rtcd.h
@@ -31,6 +31,8 @@
 struct aom_variance_vtable;
 struct search_site_config;
 struct yv12_buffer_config;
+struct NN_CONFIG;
+typedef struct NN_CONFIG NN_CONFIG;
 
 /* Function pointers return by CfL functions */
 typedef void (*cfl_subsample_lbd_fn)(const uint8_t* input,
@@ -803,6 +805,9 @@
                           ConvolveParams* conv_params);
 #define av1_jnt_convolve_y av1_jnt_convolve_y_c
 
+void av1_round_shift_array_c(int32_t* arr, int size, int bit);
+#define av1_round_shift_array av1_round_shift_array_c
+
 int av1_selfguided_restoration_c(const uint8_t* dgd8,
                                  int width,
                                  int height,
diff --git a/third_party/libaom/source/config/linux/arm64/config/aom_config.asm b/third_party/libaom/source/config/linux/arm64/config/aom_config.asm
index 1562f51..1193fe26 100644
--- a/third_party/libaom/source/config/linux/arm64/config/aom_config.asm
+++ b/third_party/libaom/source/config/linux/arm64/config/aom_config.asm
@@ -25,6 +25,7 @@
 CONFIG_COLLECT_RD_STATS equ 0
 CONFIG_DEBUG equ 0
 CONFIG_DENOISE equ 1
+CONFIG_DISABLE_FULL_PIXEL_SPLIT_8X8 equ 1
 CONFIG_DIST_8X8 equ 0
 CONFIG_ENTROPY_STATS equ 0
 CONFIG_FILEOPTIONS equ 1
diff --git a/third_party/libaom/source/config/linux/arm64/config/aom_config.h b/third_party/libaom/source/config/linux/arm64/config/aom_config.h
index 76a27fea..cd3baad 100644
--- a/third_party/libaom/source/config/linux/arm64/config/aom_config.h
+++ b/third_party/libaom/source/config/linux/arm64/config/aom_config.h
@@ -27,6 +27,7 @@
 #define CONFIG_COLLECT_RD_STATS 0
 #define CONFIG_DEBUG 0
 #define CONFIG_DENOISE 1
+#define CONFIG_DISABLE_FULL_PIXEL_SPLIT_8X8 1
 #define CONFIG_DIST_8X8 0
 #define CONFIG_ENTROPY_STATS 0
 #define CONFIG_FILEOPTIONS 1
diff --git a/third_party/libaom/source/config/linux/arm64/config/aom_dsp_rtcd.h b/third_party/libaom/source/config/linux/arm64/config/aom_dsp_rtcd.h
index 8acb85d..dd882516 100644
--- a/third_party/libaom/source/config/linux/arm64/config/aom_dsp_rtcd.h
+++ b/third_party/libaom/source/config/linux/arm64/config/aom_dsp_rtcd.h
@@ -3300,10 +3300,6 @@
                               const uint8_t* left);
 #define aom_v_predictor_8x8 aom_v_predictor_8x8_neon
 
-void av1_round_shift_array_c(int32_t* arr, int size, int bit);
-void av1_round_shift_array_neon(int32_t* arr, int size, int bit);
-#define av1_round_shift_array av1_round_shift_array_neon
-
 void aom_dsp_rtcd(void);
 
 #include "config/aom_config.h"
diff --git a/third_party/libaom/source/config/linux/arm64/config/aom_scale_rtcd.h b/third_party/libaom/source/config/linux/arm64/config/aom_scale_rtcd.h
index ac22c47..c8fa3a4 100644
--- a/third_party/libaom/source/config/linux/arm64/config/aom_scale_rtcd.h
+++ b/third_party/libaom/source/config/linux/arm64/config/aom_scale_rtcd.h
@@ -92,28 +92,58 @@
                                      const int num_planes);
 #define aom_yv12_extend_frame_borders aom_yv12_extend_frame_borders_c
 
+void aom_yv12_partial_coloc_copy_u_c(const struct yv12_buffer_config* src_bc,
+                                     struct yv12_buffer_config* dst_bc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_u aom_yv12_partial_coloc_copy_u_c
+
+void aom_yv12_partial_coloc_copy_v_c(const struct yv12_buffer_config* src_bc,
+                                     struct yv12_buffer_config* dst_bc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_v aom_yv12_partial_coloc_copy_v_c
+
+void aom_yv12_partial_coloc_copy_y_c(const struct yv12_buffer_config* src_ybc,
+                                     struct yv12_buffer_config* dst_ybc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_y aom_yv12_partial_coloc_copy_y_c
+
 void aom_yv12_partial_copy_u_c(const struct yv12_buffer_config* src_bc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_bc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_u aom_yv12_partial_copy_u_c
 
 void aom_yv12_partial_copy_v_c(const struct yv12_buffer_config* src_bc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_bc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_v aom_yv12_partial_copy_v_c
 
 void aom_yv12_partial_copy_y_c(const struct yv12_buffer_config* src_ybc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_ybc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_y aom_yv12_partial_copy_y_c
 
 void aom_scale_rtcd(void);
diff --git a/third_party/libaom/source/config/linux/arm64/config/av1_rtcd.h b/third_party/libaom/source/config/linux/arm64/config/av1_rtcd.h
index e7dfcc6..17bde5be 100644
--- a/third_party/libaom/source/config/linux/arm64/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/linux/arm64/config/av1_rtcd.h
@@ -31,6 +31,8 @@
 struct aom_variance_vtable;
 struct search_site_config;
 struct yv12_buffer_config;
+struct NN_CONFIG;
+typedef struct NN_CONFIG NN_CONFIG;
 
 /* Function pointers return by CfL functions */
 typedef void (*cfl_subsample_lbd_fn)(const uint8_t* input,
@@ -916,6 +918,10 @@
                              ConvolveParams* conv_params);
 #define av1_jnt_convolve_y av1_jnt_convolve_y_neon
 
+void av1_round_shift_array_c(int32_t* arr, int size, int bit);
+void av1_round_shift_array_neon(int32_t* arr, int size, int bit);
+#define av1_round_shift_array av1_round_shift_array_neon
+
 int av1_selfguided_restoration_c(const uint8_t* dgd8,
                                  int width,
                                  int height,
diff --git a/third_party/libaom/source/config/linux/generic/config/aom_config.asm b/third_party/libaom/source/config/linux/generic/config/aom_config.asm
index 7936b602..731c139 100644
--- a/third_party/libaom/source/config/linux/generic/config/aom_config.asm
+++ b/third_party/libaom/source/config/linux/generic/config/aom_config.asm
@@ -25,6 +25,7 @@
 CONFIG_COLLECT_RD_STATS equ 0
 CONFIG_DEBUG equ 0
 CONFIG_DENOISE equ 1
+CONFIG_DISABLE_FULL_PIXEL_SPLIT_8X8 equ 1
 CONFIG_DIST_8X8 equ 0
 CONFIG_ENTROPY_STATS equ 0
 CONFIG_FILEOPTIONS equ 1
diff --git a/third_party/libaom/source/config/linux/generic/config/aom_config.h b/third_party/libaom/source/config/linux/generic/config/aom_config.h
index 21dad090..161f424e 100644
--- a/third_party/libaom/source/config/linux/generic/config/aom_config.h
+++ b/third_party/libaom/source/config/linux/generic/config/aom_config.h
@@ -27,6 +27,7 @@
 #define CONFIG_COLLECT_RD_STATS 0
 #define CONFIG_DEBUG 0
 #define CONFIG_DENOISE 1
+#define CONFIG_DISABLE_FULL_PIXEL_SPLIT_8X8 1
 #define CONFIG_DIST_8X8 0
 #define CONFIG_ENTROPY_STATS 0
 #define CONFIG_FILEOPTIONS 1
diff --git a/third_party/libaom/source/config/linux/generic/config/aom_dsp_rtcd.h b/third_party/libaom/source/config/linux/generic/config/aom_dsp_rtcd.h
index 07ca82e..df3feaf 100644
--- a/third_party/libaom/source/config/linux/generic/config/aom_dsp_rtcd.h
+++ b/third_party/libaom/source/config/linux/generic/config/aom_dsp_rtcd.h
@@ -3108,9 +3108,6 @@
                            const uint8_t* left);
 #define aom_v_predictor_8x8 aom_v_predictor_8x8_c
 
-void av1_round_shift_array_c(int32_t* arr, int size, int bit);
-#define av1_round_shift_array av1_round_shift_array_c
-
 void aom_dsp_rtcd(void);
 
 #include "config/aom_config.h"
diff --git a/third_party/libaom/source/config/linux/generic/config/aom_scale_rtcd.h b/third_party/libaom/source/config/linux/generic/config/aom_scale_rtcd.h
index d8703dfa..0e95dc3 100644
--- a/third_party/libaom/source/config/linux/generic/config/aom_scale_rtcd.h
+++ b/third_party/libaom/source/config/linux/generic/config/aom_scale_rtcd.h
@@ -92,28 +92,58 @@
                                      const int num_planes);
 #define aom_yv12_extend_frame_borders aom_yv12_extend_frame_borders_c
 
+void aom_yv12_partial_coloc_copy_u_c(const struct yv12_buffer_config* src_bc,
+                                     struct yv12_buffer_config* dst_bc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_u aom_yv12_partial_coloc_copy_u_c
+
+void aom_yv12_partial_coloc_copy_v_c(const struct yv12_buffer_config* src_bc,
+                                     struct yv12_buffer_config* dst_bc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_v aom_yv12_partial_coloc_copy_v_c
+
+void aom_yv12_partial_coloc_copy_y_c(const struct yv12_buffer_config* src_ybc,
+                                     struct yv12_buffer_config* dst_ybc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_y aom_yv12_partial_coloc_copy_y_c
+
 void aom_yv12_partial_copy_u_c(const struct yv12_buffer_config* src_bc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_bc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_u aom_yv12_partial_copy_u_c
 
 void aom_yv12_partial_copy_v_c(const struct yv12_buffer_config* src_bc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_bc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_v aom_yv12_partial_copy_v_c
 
 void aom_yv12_partial_copy_y_c(const struct yv12_buffer_config* src_ybc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_ybc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_y aom_yv12_partial_copy_y_c
 
 void aom_scale_rtcd(void);
diff --git a/third_party/libaom/source/config/linux/generic/config/av1_rtcd.h b/third_party/libaom/source/config/linux/generic/config/av1_rtcd.h
index 9f053113..848280a 100644
--- a/third_party/libaom/source/config/linux/generic/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/linux/generic/config/av1_rtcd.h
@@ -31,6 +31,8 @@
 struct aom_variance_vtable;
 struct search_site_config;
 struct yv12_buffer_config;
+struct NN_CONFIG;
+typedef struct NN_CONFIG NN_CONFIG;
 
 /* Function pointers return by CfL functions */
 typedef void (*cfl_subsample_lbd_fn)(const uint8_t* input,
@@ -803,6 +805,9 @@
                           ConvolveParams* conv_params);
 #define av1_jnt_convolve_y av1_jnt_convolve_y_c
 
+void av1_round_shift_array_c(int32_t* arr, int size, int bit);
+#define av1_round_shift_array av1_round_shift_array_c
+
 int av1_selfguided_restoration_c(const uint8_t* dgd8,
                                  int width,
                                  int height,
diff --git a/third_party/libaom/source/config/linux/ia32/config/aom_config.asm b/third_party/libaom/source/config/linux/ia32/config/aom_config.asm
index 491e9c50..20ccc7c 100644
--- a/third_party/libaom/source/config/linux/ia32/config/aom_config.asm
+++ b/third_party/libaom/source/config/linux/ia32/config/aom_config.asm
@@ -15,6 +15,7 @@
 %define CONFIG_COLLECT_RD_STATS 0
 %define CONFIG_DEBUG 0
 %define CONFIG_DENOISE 1
+%define CONFIG_DISABLE_FULL_PIXEL_SPLIT_8X8 1
 %define CONFIG_DIST_8X8 0
 %define CONFIG_ENTROPY_STATS 0
 %define CONFIG_FILEOPTIONS 1
diff --git a/third_party/libaom/source/config/linux/ia32/config/aom_config.h b/third_party/libaom/source/config/linux/ia32/config/aom_config.h
index 1fceced..4cfde25 100644
--- a/third_party/libaom/source/config/linux/ia32/config/aom_config.h
+++ b/third_party/libaom/source/config/linux/ia32/config/aom_config.h
@@ -27,6 +27,7 @@
 #define CONFIG_COLLECT_RD_STATS 0
 #define CONFIG_DEBUG 0
 #define CONFIG_DENOISE 1
+#define CONFIG_DISABLE_FULL_PIXEL_SPLIT_8X8 1
 #define CONFIG_DIST_8X8 0
 #define CONFIG_ENTROPY_STATS 0
 #define CONFIG_FILEOPTIONS 1
diff --git a/third_party/libaom/source/config/linux/ia32/config/aom_dsp_rtcd.h b/third_party/libaom/source/config/linux/ia32/config/aom_dsp_rtcd.h
index dc78172c9..340f39c 100644
--- a/third_party/libaom/source/config/linux/ia32/config/aom_dsp_rtcd.h
+++ b/third_party/libaom/source/config/linux/ia32/config/aom_dsp_rtcd.h
@@ -1575,6 +1575,17 @@
                                   int w,
                                   int h,
                                   int bps);
+void aom_highbd_convolve8_horiz_sse2(const uint8_t* src,
+                                     ptrdiff_t src_stride,
+                                     uint8_t* dst,
+                                     ptrdiff_t dst_stride,
+                                     const int16_t* filter_x,
+                                     int x_step_q4,
+                                     const int16_t* filter_y,
+                                     int y_step_q4,
+                                     int w,
+                                     int h,
+                                     int bps);
 void aom_highbd_convolve8_horiz_avx2(const uint8_t* src,
                                      ptrdiff_t src_stride,
                                      uint8_t* dst,
@@ -1609,6 +1620,17 @@
                                  int w,
                                  int h,
                                  int bps);
+void aom_highbd_convolve8_vert_sse2(const uint8_t* src,
+                                    ptrdiff_t src_stride,
+                                    uint8_t* dst,
+                                    ptrdiff_t dst_stride,
+                                    const int16_t* filter_x,
+                                    int x_step_q4,
+                                    const int16_t* filter_y,
+                                    int y_step_q4,
+                                    int w,
+                                    int h,
+                                    int bps);
 void aom_highbd_convolve8_vert_avx2(const uint8_t* src,
                                     ptrdiff_t src_stride,
                                     uint8_t* dst,
@@ -5356,10 +5378,6 @@
                               const uint8_t* left);
 #define aom_v_predictor_8x8 aom_v_predictor_8x8_sse2
 
-void av1_round_shift_array_c(int32_t* arr, int size, int bit);
-void av1_round_shift_array_sse4_1(int32_t* arr, int size, int bit);
-RTCD_EXTERN void (*av1_round_shift_array)(int32_t* arr, int size, int bit);
-
 void aom_dsp_rtcd(void);
 
 #ifdef RTCD_C
@@ -5479,10 +5497,10 @@
   aom_highbd_blend_a64_vmask = aom_highbd_blend_a64_vmask_c;
   if (flags & HAS_SSE4_1)
     aom_highbd_blend_a64_vmask = aom_highbd_blend_a64_vmask_sse4_1;
-  aom_highbd_convolve8_horiz = aom_highbd_convolve8_horiz_c;
+  aom_highbd_convolve8_horiz = aom_highbd_convolve8_horiz_sse2;
   if (flags & HAS_AVX2)
     aom_highbd_convolve8_horiz = aom_highbd_convolve8_horiz_avx2;
-  aom_highbd_convolve8_vert = aom_highbd_convolve8_vert_c;
+  aom_highbd_convolve8_vert = aom_highbd_convolve8_vert_sse2;
   if (flags & HAS_AVX2)
     aom_highbd_convolve8_vert = aom_highbd_convolve8_vert_avx2;
   aom_highbd_convolve_copy = aom_highbd_convolve_copy_sse2;
@@ -5777,9 +5795,6 @@
   aom_v_predictor_64x64 = aom_v_predictor_64x64_sse2;
   if (flags & HAS_AVX2)
     aom_v_predictor_64x64 = aom_v_predictor_64x64_avx2;
-  av1_round_shift_array = av1_round_shift_array_c;
-  if (flags & HAS_SSE4_1)
-    av1_round_shift_array = av1_round_shift_array_sse4_1;
 }
 #endif
 
diff --git a/third_party/libaom/source/config/linux/ia32/config/aom_scale_rtcd.h b/third_party/libaom/source/config/linux/ia32/config/aom_scale_rtcd.h
index 9fe39d9..57e5fea 100644
--- a/third_party/libaom/source/config/linux/ia32/config/aom_scale_rtcd.h
+++ b/third_party/libaom/source/config/linux/ia32/config/aom_scale_rtcd.h
@@ -92,28 +92,58 @@
                                      const int num_planes);
 #define aom_yv12_extend_frame_borders aom_yv12_extend_frame_borders_c
 
+void aom_yv12_partial_coloc_copy_u_c(const struct yv12_buffer_config* src_bc,
+                                     struct yv12_buffer_config* dst_bc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_u aom_yv12_partial_coloc_copy_u_c
+
+void aom_yv12_partial_coloc_copy_v_c(const struct yv12_buffer_config* src_bc,
+                                     struct yv12_buffer_config* dst_bc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_v aom_yv12_partial_coloc_copy_v_c
+
+void aom_yv12_partial_coloc_copy_y_c(const struct yv12_buffer_config* src_ybc,
+                                     struct yv12_buffer_config* dst_ybc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_y aom_yv12_partial_coloc_copy_y_c
+
 void aom_yv12_partial_copy_u_c(const struct yv12_buffer_config* src_bc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_bc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_u aom_yv12_partial_copy_u_c
 
 void aom_yv12_partial_copy_v_c(const struct yv12_buffer_config* src_bc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_bc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_v aom_yv12_partial_copy_v_c
 
 void aom_yv12_partial_copy_y_c(const struct yv12_buffer_config* src_ybc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_ybc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_y aom_yv12_partial_copy_y_c
 
 void aom_scale_rtcd(void);
diff --git a/third_party/libaom/source/config/linux/ia32/config/av1_rtcd.h b/third_party/libaom/source/config/linux/ia32/config/av1_rtcd.h
index 4dd9cf5..213461ba 100644
--- a/third_party/libaom/source/config/linux/ia32/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/linux/ia32/config/av1_rtcd.h
@@ -31,6 +31,8 @@
 struct aom_variance_vtable;
 struct search_site_config;
 struct yv12_buffer_config;
+struct NN_CONFIG;
+typedef struct NN_CONFIG NN_CONFIG;
 
 /* Function pointers return by CfL functions */
 typedef void (*cfl_subsample_lbd_fn)(const uint8_t* input,
@@ -883,7 +885,26 @@
                                    int dx,
                                    int dy,
                                    int bd);
-#define av1_highbd_dr_prediction_z1 av1_highbd_dr_prediction_z1_c
+void av1_highbd_dr_prediction_z1_avx2(uint16_t* dst,
+                                      ptrdiff_t stride,
+                                      int bw,
+                                      int bh,
+                                      const uint16_t* above,
+                                      const uint16_t* left,
+                                      int upsample_above,
+                                      int dx,
+                                      int dy,
+                                      int bd);
+RTCD_EXTERN void (*av1_highbd_dr_prediction_z1)(uint16_t* dst,
+                                                ptrdiff_t stride,
+                                                int bw,
+                                                int bh,
+                                                const uint16_t* above,
+                                                const uint16_t* left,
+                                                int upsample_above,
+                                                int dx,
+                                                int dy,
+                                                int bd);
 
 void av1_highbd_dr_prediction_z2_c(uint16_t* dst,
                                    ptrdiff_t stride,
@@ -908,7 +929,26 @@
                                    int dx,
                                    int dy,
                                    int bd);
-#define av1_highbd_dr_prediction_z3 av1_highbd_dr_prediction_z3_c
+void av1_highbd_dr_prediction_z3_avx2(uint16_t* dst,
+                                      ptrdiff_t stride,
+                                      int bw,
+                                      int bh,
+                                      const uint16_t* above,
+                                      const uint16_t* left,
+                                      int upsample_left,
+                                      int dx,
+                                      int dy,
+                                      int bd);
+RTCD_EXTERN void (*av1_highbd_dr_prediction_z3)(uint16_t* dst,
+                                                ptrdiff_t stride,
+                                                int bw,
+                                                int bh,
+                                                const uint16_t* above,
+                                                const uint16_t* left,
+                                                int upsample_left,
+                                                int dx,
+                                                int dy,
+                                                int bd);
 
 void av1_highbd_inv_txfm_add_c(const tran_low_t* dqcoeff,
                                uint8_t* dst,
@@ -935,6 +975,10 @@
                                           uint8_t* dst,
                                           int stride,
                                           const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_16x16_avx2(const tran_low_t* dqcoeff,
+                                        uint8_t* dst,
+                                        int stride,
+                                        const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_16x16)(const tran_low_t* dqcoeff,
                                                   uint8_t* dst,
                                                   int stride,
@@ -948,6 +992,10 @@
                                           uint8_t* dst,
                                           int stride,
                                           const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_16x32_avx2(const tran_low_t* dqcoeff,
+                                        uint8_t* dst,
+                                        int stride,
+                                        const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_16x32)(const tran_low_t* dqcoeff,
                                                   uint8_t* dst,
                                                   int stride,
@@ -974,6 +1022,10 @@
                                          uint8_t* dst,
                                          int stride,
                                          const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_16x8_avx2(const tran_low_t* dqcoeff,
+                                       uint8_t* dst,
+                                       int stride,
+                                       const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_16x8)(const tran_low_t* dqcoeff,
                                                  uint8_t* dst,
                                                  int stride,
@@ -987,6 +1039,10 @@
                                           uint8_t* dst,
                                           int stride,
                                           const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_32x16_avx2(const tran_low_t* dqcoeff,
+                                        uint8_t* dst,
+                                        int stride,
+                                        const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_32x16)(const tran_low_t* dqcoeff,
                                                   uint8_t* dst,
                                                   int stride,
@@ -1017,6 +1073,10 @@
                                          uint8_t* dst,
                                          int stride,
                                          const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_32x8_avx2(const tran_low_t* dqcoeff,
+                                       uint8_t* dst,
+                                       int stride,
+                                       const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_32x8)(const tran_low_t* dqcoeff,
                                                  uint8_t* dst,
                                                  int stride,
@@ -1069,6 +1129,10 @@
                                          uint8_t* dst,
                                          int stride,
                                          const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_8x16_avx2(const tran_low_t* dqcoeff,
+                                       uint8_t* dst,
+                                       int stride,
+                                       const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_8x16)(const tran_low_t* dqcoeff,
                                                  uint8_t* dst,
                                                  int stride,
@@ -1082,6 +1146,10 @@
                                          uint8_t* dst,
                                          int stride,
                                          const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_8x32_avx2(const tran_low_t* dqcoeff,
+                                       uint8_t* dst,
+                                       int stride,
+                                       const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_8x32)(const tran_low_t* dqcoeff,
                                                  uint8_t* dst,
                                                  int stride,
@@ -1108,6 +1176,10 @@
                                         uint8_t* dst,
                                         int stride,
                                         const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_8x8_avx2(const tran_low_t* dqcoeff,
+                                      uint8_t* dst,
+                                      int stride,
+                                      const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_8x8)(const tran_low_t* dqcoeff,
                                                 uint8_t* dst,
                                                 int stride,
@@ -1800,6 +1872,10 @@
     const int subpel_y_q4,
     ConvolveParams* conv_params);
 
+void av1_round_shift_array_c(int32_t* arr, int size, int bit);
+void av1_round_shift_array_sse4_1(int32_t* arr, int size, int bit);
+RTCD_EXTERN void (*av1_round_shift_array)(int32_t* arr, int size, int bit);
+
 int av1_selfguided_restoration_c(const uint8_t* dgd8,
                                  int width,
                                  int height,
@@ -2252,6 +2328,12 @@
     av1_highbd_convolve_y_sr = av1_highbd_convolve_y_sr_ssse3;
   if (flags & HAS_AVX2)
     av1_highbd_convolve_y_sr = av1_highbd_convolve_y_sr_avx2;
+  av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_c;
+  if (flags & HAS_AVX2)
+    av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_avx2;
+  av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_c;
+  if (flags & HAS_AVX2)
+    av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_avx2;
   av1_highbd_inv_txfm_add = av1_highbd_inv_txfm_add_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add = av1_highbd_inv_txfm_add_sse4_1;
@@ -2260,18 +2342,26 @@
   av1_highbd_inv_txfm_add_16x16 = av1_highbd_inv_txfm_add_16x16_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_16x16 = av1_highbd_inv_txfm_add_16x16_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_16x16 = av1_highbd_inv_txfm_add_16x16_avx2;
   av1_highbd_inv_txfm_add_16x32 = av1_highbd_inv_txfm_add_16x32_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_16x32 = av1_highbd_inv_txfm_add_16x32_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_16x32 = av1_highbd_inv_txfm_add_16x32_avx2;
   av1_highbd_inv_txfm_add_16x4 = av1_highbd_inv_txfm_add_16x4_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_16x4 = av1_highbd_inv_txfm_add_16x4_sse4_1;
   av1_highbd_inv_txfm_add_16x8 = av1_highbd_inv_txfm_add_16x8_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_16x8 = av1_highbd_inv_txfm_add_16x8_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_16x8 = av1_highbd_inv_txfm_add_16x8_avx2;
   av1_highbd_inv_txfm_add_32x16 = av1_highbd_inv_txfm_add_32x16_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_32x16 = av1_highbd_inv_txfm_add_32x16_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_32x16 = av1_highbd_inv_txfm_add_32x16_avx2;
   av1_highbd_inv_txfm_add_32x32 = av1_highbd_inv_txfm_add_32x32_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_32x32 = av1_highbd_inv_txfm_add_32x32_sse4_1;
@@ -2280,6 +2370,8 @@
   av1_highbd_inv_txfm_add_32x8 = av1_highbd_inv_txfm_add_32x8_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_32x8 = av1_highbd_inv_txfm_add_32x8_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_32x8 = av1_highbd_inv_txfm_add_32x8_avx2;
   av1_highbd_inv_txfm_add_4x16 = av1_highbd_inv_txfm_add_4x16_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_4x16 = av1_highbd_inv_txfm_add_4x16_sse4_1;
@@ -2292,15 +2384,21 @@
   av1_highbd_inv_txfm_add_8x16 = av1_highbd_inv_txfm_add_8x16_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_8x16 = av1_highbd_inv_txfm_add_8x16_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_8x16 = av1_highbd_inv_txfm_add_8x16_avx2;
   av1_highbd_inv_txfm_add_8x32 = av1_highbd_inv_txfm_add_8x32_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_8x32 = av1_highbd_inv_txfm_add_8x32_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_8x32 = av1_highbd_inv_txfm_add_8x32_avx2;
   av1_highbd_inv_txfm_add_8x4 = av1_highbd_inv_txfm_add_8x4_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_8x4 = av1_highbd_inv_txfm_add_8x4_sse4_1;
   av1_highbd_inv_txfm_add_8x8 = av1_highbd_inv_txfm_add_8x8_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_8x8 = av1_highbd_inv_txfm_add_8x8_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_8x8 = av1_highbd_inv_txfm_add_8x8_avx2;
   av1_highbd_jnt_convolve_2d = av1_highbd_jnt_convolve_2d_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_jnt_convolve_2d = av1_highbd_jnt_convolve_2d_sse4_1;
@@ -2356,6 +2454,9 @@
   av1_jnt_convolve_y = av1_jnt_convolve_y_sse2;
   if (flags & HAS_AVX2)
     av1_jnt_convolve_y = av1_jnt_convolve_y_avx2;
+  av1_round_shift_array = av1_round_shift_array_c;
+  if (flags & HAS_SSE4_1)
+    av1_round_shift_array = av1_round_shift_array_sse4_1;
   av1_selfguided_restoration = av1_selfguided_restoration_c;
   if (flags & HAS_SSE4_1)
     av1_selfguided_restoration = av1_selfguided_restoration_sse4_1;
diff --git a/third_party/libaom/source/config/linux/x64/config/aom_config.asm b/third_party/libaom/source/config/linux/x64/config/aom_config.asm
index 0d33e6b..abb116c 100644
--- a/third_party/libaom/source/config/linux/x64/config/aom_config.asm
+++ b/third_party/libaom/source/config/linux/x64/config/aom_config.asm
@@ -15,6 +15,7 @@
 %define CONFIG_COLLECT_RD_STATS 0
 %define CONFIG_DEBUG 0
 %define CONFIG_DENOISE 1
+%define CONFIG_DISABLE_FULL_PIXEL_SPLIT_8X8 1
 %define CONFIG_DIST_8X8 0
 %define CONFIG_ENTROPY_STATS 0
 %define CONFIG_FILEOPTIONS 1
diff --git a/third_party/libaom/source/config/linux/x64/config/aom_config.h b/third_party/libaom/source/config/linux/x64/config/aom_config.h
index d4c0b53..737f207 100644
--- a/third_party/libaom/source/config/linux/x64/config/aom_config.h
+++ b/third_party/libaom/source/config/linux/x64/config/aom_config.h
@@ -27,6 +27,7 @@
 #define CONFIG_COLLECT_RD_STATS 0
 #define CONFIG_DEBUG 0
 #define CONFIG_DENOISE 1
+#define CONFIG_DISABLE_FULL_PIXEL_SPLIT_8X8 1
 #define CONFIG_DIST_8X8 0
 #define CONFIG_ENTROPY_STATS 0
 #define CONFIG_FILEOPTIONS 1
diff --git a/third_party/libaom/source/config/linux/x64/config/aom_dsp_rtcd.h b/third_party/libaom/source/config/linux/x64/config/aom_dsp_rtcd.h
index 44024bd0..340f39c 100644
--- a/third_party/libaom/source/config/linux/x64/config/aom_dsp_rtcd.h
+++ b/third_party/libaom/source/config/linux/x64/config/aom_dsp_rtcd.h
@@ -5378,10 +5378,6 @@
                               const uint8_t* left);
 #define aom_v_predictor_8x8 aom_v_predictor_8x8_sse2
 
-void av1_round_shift_array_c(int32_t* arr, int size, int bit);
-void av1_round_shift_array_sse4_1(int32_t* arr, int size, int bit);
-RTCD_EXTERN void (*av1_round_shift_array)(int32_t* arr, int size, int bit);
-
 void aom_dsp_rtcd(void);
 
 #ifdef RTCD_C
@@ -5799,9 +5795,6 @@
   aom_v_predictor_64x64 = aom_v_predictor_64x64_sse2;
   if (flags & HAS_AVX2)
     aom_v_predictor_64x64 = aom_v_predictor_64x64_avx2;
-  av1_round_shift_array = av1_round_shift_array_c;
-  if (flags & HAS_SSE4_1)
-    av1_round_shift_array = av1_round_shift_array_sse4_1;
 }
 #endif
 
diff --git a/third_party/libaom/source/config/linux/x64/config/aom_scale_rtcd.h b/third_party/libaom/source/config/linux/x64/config/aom_scale_rtcd.h
index 9fe39d9..57e5fea 100644
--- a/third_party/libaom/source/config/linux/x64/config/aom_scale_rtcd.h
+++ b/third_party/libaom/source/config/linux/x64/config/aom_scale_rtcd.h
@@ -92,28 +92,58 @@
                                      const int num_planes);
 #define aom_yv12_extend_frame_borders aom_yv12_extend_frame_borders_c
 
+void aom_yv12_partial_coloc_copy_u_c(const struct yv12_buffer_config* src_bc,
+                                     struct yv12_buffer_config* dst_bc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_u aom_yv12_partial_coloc_copy_u_c
+
+void aom_yv12_partial_coloc_copy_v_c(const struct yv12_buffer_config* src_bc,
+                                     struct yv12_buffer_config* dst_bc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_v aom_yv12_partial_coloc_copy_v_c
+
+void aom_yv12_partial_coloc_copy_y_c(const struct yv12_buffer_config* src_ybc,
+                                     struct yv12_buffer_config* dst_ybc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_y aom_yv12_partial_coloc_copy_y_c
+
 void aom_yv12_partial_copy_u_c(const struct yv12_buffer_config* src_bc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_bc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_u aom_yv12_partial_copy_u_c
 
 void aom_yv12_partial_copy_v_c(const struct yv12_buffer_config* src_bc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_bc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_v aom_yv12_partial_copy_v_c
 
 void aom_yv12_partial_copy_y_c(const struct yv12_buffer_config* src_ybc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_ybc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_y aom_yv12_partial_copy_y_c
 
 void aom_scale_rtcd(void);
diff --git a/third_party/libaom/source/config/linux/x64/config/av1_rtcd.h b/third_party/libaom/source/config/linux/x64/config/av1_rtcd.h
index e570d52..a8a8ae7 100644
--- a/third_party/libaom/source/config/linux/x64/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/linux/x64/config/av1_rtcd.h
@@ -31,6 +31,8 @@
 struct aom_variance_vtable;
 struct search_site_config;
 struct yv12_buffer_config;
+struct NN_CONFIG;
+typedef struct NN_CONFIG NN_CONFIG;
 
 /* Function pointers return by CfL functions */
 typedef void (*cfl_subsample_lbd_fn)(const uint8_t* input,
@@ -916,7 +918,26 @@
                                    int dx,
                                    int dy,
                                    int bd);
-#define av1_highbd_dr_prediction_z1 av1_highbd_dr_prediction_z1_c
+void av1_highbd_dr_prediction_z1_avx2(uint16_t* dst,
+                                      ptrdiff_t stride,
+                                      int bw,
+                                      int bh,
+                                      const uint16_t* above,
+                                      const uint16_t* left,
+                                      int upsample_above,
+                                      int dx,
+                                      int dy,
+                                      int bd);
+RTCD_EXTERN void (*av1_highbd_dr_prediction_z1)(uint16_t* dst,
+                                                ptrdiff_t stride,
+                                                int bw,
+                                                int bh,
+                                                const uint16_t* above,
+                                                const uint16_t* left,
+                                                int upsample_above,
+                                                int dx,
+                                                int dy,
+                                                int bd);
 
 void av1_highbd_dr_prediction_z2_c(uint16_t* dst,
                                    ptrdiff_t stride,
@@ -941,7 +962,26 @@
                                    int dx,
                                    int dy,
                                    int bd);
-#define av1_highbd_dr_prediction_z3 av1_highbd_dr_prediction_z3_c
+void av1_highbd_dr_prediction_z3_avx2(uint16_t* dst,
+                                      ptrdiff_t stride,
+                                      int bw,
+                                      int bh,
+                                      const uint16_t* above,
+                                      const uint16_t* left,
+                                      int upsample_left,
+                                      int dx,
+                                      int dy,
+                                      int bd);
+RTCD_EXTERN void (*av1_highbd_dr_prediction_z3)(uint16_t* dst,
+                                                ptrdiff_t stride,
+                                                int bw,
+                                                int bh,
+                                                const uint16_t* above,
+                                                const uint16_t* left,
+                                                int upsample_left,
+                                                int dx,
+                                                int dy,
+                                                int bd);
 
 void av1_highbd_inv_txfm_add_c(const tran_low_t* dqcoeff,
                                uint8_t* dst,
@@ -968,6 +1008,10 @@
                                           uint8_t* dst,
                                           int stride,
                                           const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_16x16_avx2(const tran_low_t* dqcoeff,
+                                        uint8_t* dst,
+                                        int stride,
+                                        const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_16x16)(const tran_low_t* dqcoeff,
                                                   uint8_t* dst,
                                                   int stride,
@@ -981,6 +1025,10 @@
                                           uint8_t* dst,
                                           int stride,
                                           const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_16x32_avx2(const tran_low_t* dqcoeff,
+                                        uint8_t* dst,
+                                        int stride,
+                                        const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_16x32)(const tran_low_t* dqcoeff,
                                                   uint8_t* dst,
                                                   int stride,
@@ -1007,6 +1055,10 @@
                                          uint8_t* dst,
                                          int stride,
                                          const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_16x8_avx2(const tran_low_t* dqcoeff,
+                                       uint8_t* dst,
+                                       int stride,
+                                       const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_16x8)(const tran_low_t* dqcoeff,
                                                  uint8_t* dst,
                                                  int stride,
@@ -1020,6 +1072,10 @@
                                           uint8_t* dst,
                                           int stride,
                                           const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_32x16_avx2(const tran_low_t* dqcoeff,
+                                        uint8_t* dst,
+                                        int stride,
+                                        const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_32x16)(const tran_low_t* dqcoeff,
                                                   uint8_t* dst,
                                                   int stride,
@@ -1050,6 +1106,10 @@
                                          uint8_t* dst,
                                          int stride,
                                          const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_32x8_avx2(const tran_low_t* dqcoeff,
+                                       uint8_t* dst,
+                                       int stride,
+                                       const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_32x8)(const tran_low_t* dqcoeff,
                                                  uint8_t* dst,
                                                  int stride,
@@ -1102,6 +1162,10 @@
                                          uint8_t* dst,
                                          int stride,
                                          const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_8x16_avx2(const tran_low_t* dqcoeff,
+                                       uint8_t* dst,
+                                       int stride,
+                                       const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_8x16)(const tran_low_t* dqcoeff,
                                                  uint8_t* dst,
                                                  int stride,
@@ -1115,6 +1179,10 @@
                                          uint8_t* dst,
                                          int stride,
                                          const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_8x32_avx2(const tran_low_t* dqcoeff,
+                                       uint8_t* dst,
+                                       int stride,
+                                       const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_8x32)(const tran_low_t* dqcoeff,
                                                  uint8_t* dst,
                                                  int stride,
@@ -1141,6 +1209,10 @@
                                         uint8_t* dst,
                                         int stride,
                                         const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_8x8_avx2(const tran_low_t* dqcoeff,
+                                      uint8_t* dst,
+                                      int stride,
+                                      const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_8x8)(const tran_low_t* dqcoeff,
                                                 uint8_t* dst,
                                                 int stride,
@@ -1833,6 +1905,10 @@
     const int subpel_y_q4,
     ConvolveParams* conv_params);
 
+void av1_round_shift_array_c(int32_t* arr, int size, int bit);
+void av1_round_shift_array_sse4_1(int32_t* arr, int size, int bit);
+RTCD_EXTERN void (*av1_round_shift_array)(int32_t* arr, int size, int bit);
+
 int av1_selfguided_restoration_c(const uint8_t* dgd8,
                                  int width,
                                  int height,
@@ -2285,6 +2361,12 @@
     av1_highbd_convolve_y_sr = av1_highbd_convolve_y_sr_ssse3;
   if (flags & HAS_AVX2)
     av1_highbd_convolve_y_sr = av1_highbd_convolve_y_sr_avx2;
+  av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_c;
+  if (flags & HAS_AVX2)
+    av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_avx2;
+  av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_c;
+  if (flags & HAS_AVX2)
+    av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_avx2;
   av1_highbd_inv_txfm_add = av1_highbd_inv_txfm_add_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add = av1_highbd_inv_txfm_add_sse4_1;
@@ -2293,18 +2375,26 @@
   av1_highbd_inv_txfm_add_16x16 = av1_highbd_inv_txfm_add_16x16_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_16x16 = av1_highbd_inv_txfm_add_16x16_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_16x16 = av1_highbd_inv_txfm_add_16x16_avx2;
   av1_highbd_inv_txfm_add_16x32 = av1_highbd_inv_txfm_add_16x32_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_16x32 = av1_highbd_inv_txfm_add_16x32_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_16x32 = av1_highbd_inv_txfm_add_16x32_avx2;
   av1_highbd_inv_txfm_add_16x4 = av1_highbd_inv_txfm_add_16x4_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_16x4 = av1_highbd_inv_txfm_add_16x4_sse4_1;
   av1_highbd_inv_txfm_add_16x8 = av1_highbd_inv_txfm_add_16x8_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_16x8 = av1_highbd_inv_txfm_add_16x8_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_16x8 = av1_highbd_inv_txfm_add_16x8_avx2;
   av1_highbd_inv_txfm_add_32x16 = av1_highbd_inv_txfm_add_32x16_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_32x16 = av1_highbd_inv_txfm_add_32x16_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_32x16 = av1_highbd_inv_txfm_add_32x16_avx2;
   av1_highbd_inv_txfm_add_32x32 = av1_highbd_inv_txfm_add_32x32_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_32x32 = av1_highbd_inv_txfm_add_32x32_sse4_1;
@@ -2313,6 +2403,8 @@
   av1_highbd_inv_txfm_add_32x8 = av1_highbd_inv_txfm_add_32x8_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_32x8 = av1_highbd_inv_txfm_add_32x8_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_32x8 = av1_highbd_inv_txfm_add_32x8_avx2;
   av1_highbd_inv_txfm_add_4x16 = av1_highbd_inv_txfm_add_4x16_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_4x16 = av1_highbd_inv_txfm_add_4x16_sse4_1;
@@ -2325,15 +2417,21 @@
   av1_highbd_inv_txfm_add_8x16 = av1_highbd_inv_txfm_add_8x16_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_8x16 = av1_highbd_inv_txfm_add_8x16_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_8x16 = av1_highbd_inv_txfm_add_8x16_avx2;
   av1_highbd_inv_txfm_add_8x32 = av1_highbd_inv_txfm_add_8x32_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_8x32 = av1_highbd_inv_txfm_add_8x32_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_8x32 = av1_highbd_inv_txfm_add_8x32_avx2;
   av1_highbd_inv_txfm_add_8x4 = av1_highbd_inv_txfm_add_8x4_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_8x4 = av1_highbd_inv_txfm_add_8x4_sse4_1;
   av1_highbd_inv_txfm_add_8x8 = av1_highbd_inv_txfm_add_8x8_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_8x8 = av1_highbd_inv_txfm_add_8x8_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_8x8 = av1_highbd_inv_txfm_add_8x8_avx2;
   av1_highbd_jnt_convolve_2d = av1_highbd_jnt_convolve_2d_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_jnt_convolve_2d = av1_highbd_jnt_convolve_2d_sse4_1;
@@ -2389,6 +2487,9 @@
   av1_jnt_convolve_y = av1_jnt_convolve_y_sse2;
   if (flags & HAS_AVX2)
     av1_jnt_convolve_y = av1_jnt_convolve_y_avx2;
+  av1_round_shift_array = av1_round_shift_array_c;
+  if (flags & HAS_SSE4_1)
+    av1_round_shift_array = av1_round_shift_array_sse4_1;
   av1_selfguided_restoration = av1_selfguided_restoration_c;
   if (flags & HAS_SSE4_1)
     av1_selfguided_restoration = av1_selfguided_restoration_sse4_1;
diff --git a/third_party/libaom/source/config/win/ia32/config/aom_config.asm b/third_party/libaom/source/config/win/ia32/config/aom_config.asm
index 2451f55..6795fc1 100644
--- a/third_party/libaom/source/config/win/ia32/config/aom_config.asm
+++ b/third_party/libaom/source/config/win/ia32/config/aom_config.asm
@@ -15,6 +15,7 @@
 %define CONFIG_COLLECT_RD_STATS 0
 %define CONFIG_DEBUG 0
 %define CONFIG_DENOISE 1
+%define CONFIG_DISABLE_FULL_PIXEL_SPLIT_8X8 1
 %define CONFIG_DIST_8X8 0
 %define CONFIG_ENTROPY_STATS 0
 %define CONFIG_FILEOPTIONS 1
diff --git a/third_party/libaom/source/config/win/ia32/config/aom_config.h b/third_party/libaom/source/config/win/ia32/config/aom_config.h
index 6389f82..c5456fc 100644
--- a/third_party/libaom/source/config/win/ia32/config/aom_config.h
+++ b/third_party/libaom/source/config/win/ia32/config/aom_config.h
@@ -27,6 +27,7 @@
 #define CONFIG_COLLECT_RD_STATS 0
 #define CONFIG_DEBUG 0
 #define CONFIG_DENOISE 1
+#define CONFIG_DISABLE_FULL_PIXEL_SPLIT_8X8 1
 #define CONFIG_DIST_8X8 0
 #define CONFIG_ENTROPY_STATS 0
 #define CONFIG_FILEOPTIONS 1
diff --git a/third_party/libaom/source/config/win/ia32/config/aom_dsp_rtcd.h b/third_party/libaom/source/config/win/ia32/config/aom_dsp_rtcd.h
index dc78172c9..340f39c 100644
--- a/third_party/libaom/source/config/win/ia32/config/aom_dsp_rtcd.h
+++ b/third_party/libaom/source/config/win/ia32/config/aom_dsp_rtcd.h
@@ -1575,6 +1575,17 @@
                                   int w,
                                   int h,
                                   int bps);
+void aom_highbd_convolve8_horiz_sse2(const uint8_t* src,
+                                     ptrdiff_t src_stride,
+                                     uint8_t* dst,
+                                     ptrdiff_t dst_stride,
+                                     const int16_t* filter_x,
+                                     int x_step_q4,
+                                     const int16_t* filter_y,
+                                     int y_step_q4,
+                                     int w,
+                                     int h,
+                                     int bps);
 void aom_highbd_convolve8_horiz_avx2(const uint8_t* src,
                                      ptrdiff_t src_stride,
                                      uint8_t* dst,
@@ -1609,6 +1620,17 @@
                                  int w,
                                  int h,
                                  int bps);
+void aom_highbd_convolve8_vert_sse2(const uint8_t* src,
+                                    ptrdiff_t src_stride,
+                                    uint8_t* dst,
+                                    ptrdiff_t dst_stride,
+                                    const int16_t* filter_x,
+                                    int x_step_q4,
+                                    const int16_t* filter_y,
+                                    int y_step_q4,
+                                    int w,
+                                    int h,
+                                    int bps);
 void aom_highbd_convolve8_vert_avx2(const uint8_t* src,
                                     ptrdiff_t src_stride,
                                     uint8_t* dst,
@@ -5356,10 +5378,6 @@
                               const uint8_t* left);
 #define aom_v_predictor_8x8 aom_v_predictor_8x8_sse2
 
-void av1_round_shift_array_c(int32_t* arr, int size, int bit);
-void av1_round_shift_array_sse4_1(int32_t* arr, int size, int bit);
-RTCD_EXTERN void (*av1_round_shift_array)(int32_t* arr, int size, int bit);
-
 void aom_dsp_rtcd(void);
 
 #ifdef RTCD_C
@@ -5479,10 +5497,10 @@
   aom_highbd_blend_a64_vmask = aom_highbd_blend_a64_vmask_c;
   if (flags & HAS_SSE4_1)
     aom_highbd_blend_a64_vmask = aom_highbd_blend_a64_vmask_sse4_1;
-  aom_highbd_convolve8_horiz = aom_highbd_convolve8_horiz_c;
+  aom_highbd_convolve8_horiz = aom_highbd_convolve8_horiz_sse2;
   if (flags & HAS_AVX2)
     aom_highbd_convolve8_horiz = aom_highbd_convolve8_horiz_avx2;
-  aom_highbd_convolve8_vert = aom_highbd_convolve8_vert_c;
+  aom_highbd_convolve8_vert = aom_highbd_convolve8_vert_sse2;
   if (flags & HAS_AVX2)
     aom_highbd_convolve8_vert = aom_highbd_convolve8_vert_avx2;
   aom_highbd_convolve_copy = aom_highbd_convolve_copy_sse2;
@@ -5777,9 +5795,6 @@
   aom_v_predictor_64x64 = aom_v_predictor_64x64_sse2;
   if (flags & HAS_AVX2)
     aom_v_predictor_64x64 = aom_v_predictor_64x64_avx2;
-  av1_round_shift_array = av1_round_shift_array_c;
-  if (flags & HAS_SSE4_1)
-    av1_round_shift_array = av1_round_shift_array_sse4_1;
 }
 #endif
 
diff --git a/third_party/libaom/source/config/win/ia32/config/aom_scale_rtcd.h b/third_party/libaom/source/config/win/ia32/config/aom_scale_rtcd.h
index 9fe39d9..57e5fea 100644
--- a/third_party/libaom/source/config/win/ia32/config/aom_scale_rtcd.h
+++ b/third_party/libaom/source/config/win/ia32/config/aom_scale_rtcd.h
@@ -92,28 +92,58 @@
                                      const int num_planes);
 #define aom_yv12_extend_frame_borders aom_yv12_extend_frame_borders_c
 
+void aom_yv12_partial_coloc_copy_u_c(const struct yv12_buffer_config* src_bc,
+                                     struct yv12_buffer_config* dst_bc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_u aom_yv12_partial_coloc_copy_u_c
+
+void aom_yv12_partial_coloc_copy_v_c(const struct yv12_buffer_config* src_bc,
+                                     struct yv12_buffer_config* dst_bc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_v aom_yv12_partial_coloc_copy_v_c
+
+void aom_yv12_partial_coloc_copy_y_c(const struct yv12_buffer_config* src_ybc,
+                                     struct yv12_buffer_config* dst_ybc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_y aom_yv12_partial_coloc_copy_y_c
+
 void aom_yv12_partial_copy_u_c(const struct yv12_buffer_config* src_bc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_bc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_u aom_yv12_partial_copy_u_c
 
 void aom_yv12_partial_copy_v_c(const struct yv12_buffer_config* src_bc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_bc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_v aom_yv12_partial_copy_v_c
 
 void aom_yv12_partial_copy_y_c(const struct yv12_buffer_config* src_ybc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_ybc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_y aom_yv12_partial_copy_y_c
 
 void aom_scale_rtcd(void);
diff --git a/third_party/libaom/source/config/win/ia32/config/av1_rtcd.h b/third_party/libaom/source/config/win/ia32/config/av1_rtcd.h
index 4dd9cf5..213461ba 100644
--- a/third_party/libaom/source/config/win/ia32/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/win/ia32/config/av1_rtcd.h
@@ -31,6 +31,8 @@
 struct aom_variance_vtable;
 struct search_site_config;
 struct yv12_buffer_config;
+struct NN_CONFIG;
+typedef struct NN_CONFIG NN_CONFIG;
 
 /* Function pointers return by CfL functions */
 typedef void (*cfl_subsample_lbd_fn)(const uint8_t* input,
@@ -883,7 +885,26 @@
                                    int dx,
                                    int dy,
                                    int bd);
-#define av1_highbd_dr_prediction_z1 av1_highbd_dr_prediction_z1_c
+void av1_highbd_dr_prediction_z1_avx2(uint16_t* dst,
+                                      ptrdiff_t stride,
+                                      int bw,
+                                      int bh,
+                                      const uint16_t* above,
+                                      const uint16_t* left,
+                                      int upsample_above,
+                                      int dx,
+                                      int dy,
+                                      int bd);
+RTCD_EXTERN void (*av1_highbd_dr_prediction_z1)(uint16_t* dst,
+                                                ptrdiff_t stride,
+                                                int bw,
+                                                int bh,
+                                                const uint16_t* above,
+                                                const uint16_t* left,
+                                                int upsample_above,
+                                                int dx,
+                                                int dy,
+                                                int bd);
 
 void av1_highbd_dr_prediction_z2_c(uint16_t* dst,
                                    ptrdiff_t stride,
@@ -908,7 +929,26 @@
                                    int dx,
                                    int dy,
                                    int bd);
-#define av1_highbd_dr_prediction_z3 av1_highbd_dr_prediction_z3_c
+void av1_highbd_dr_prediction_z3_avx2(uint16_t* dst,
+                                      ptrdiff_t stride,
+                                      int bw,
+                                      int bh,
+                                      const uint16_t* above,
+                                      const uint16_t* left,
+                                      int upsample_left,
+                                      int dx,
+                                      int dy,
+                                      int bd);
+RTCD_EXTERN void (*av1_highbd_dr_prediction_z3)(uint16_t* dst,
+                                                ptrdiff_t stride,
+                                                int bw,
+                                                int bh,
+                                                const uint16_t* above,
+                                                const uint16_t* left,
+                                                int upsample_left,
+                                                int dx,
+                                                int dy,
+                                                int bd);
 
 void av1_highbd_inv_txfm_add_c(const tran_low_t* dqcoeff,
                                uint8_t* dst,
@@ -935,6 +975,10 @@
                                           uint8_t* dst,
                                           int stride,
                                           const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_16x16_avx2(const tran_low_t* dqcoeff,
+                                        uint8_t* dst,
+                                        int stride,
+                                        const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_16x16)(const tran_low_t* dqcoeff,
                                                   uint8_t* dst,
                                                   int stride,
@@ -948,6 +992,10 @@
                                           uint8_t* dst,
                                           int stride,
                                           const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_16x32_avx2(const tran_low_t* dqcoeff,
+                                        uint8_t* dst,
+                                        int stride,
+                                        const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_16x32)(const tran_low_t* dqcoeff,
                                                   uint8_t* dst,
                                                   int stride,
@@ -974,6 +1022,10 @@
                                          uint8_t* dst,
                                          int stride,
                                          const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_16x8_avx2(const tran_low_t* dqcoeff,
+                                       uint8_t* dst,
+                                       int stride,
+                                       const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_16x8)(const tran_low_t* dqcoeff,
                                                  uint8_t* dst,
                                                  int stride,
@@ -987,6 +1039,10 @@
                                           uint8_t* dst,
                                           int stride,
                                           const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_32x16_avx2(const tran_low_t* dqcoeff,
+                                        uint8_t* dst,
+                                        int stride,
+                                        const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_32x16)(const tran_low_t* dqcoeff,
                                                   uint8_t* dst,
                                                   int stride,
@@ -1017,6 +1073,10 @@
                                          uint8_t* dst,
                                          int stride,
                                          const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_32x8_avx2(const tran_low_t* dqcoeff,
+                                       uint8_t* dst,
+                                       int stride,
+                                       const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_32x8)(const tran_low_t* dqcoeff,
                                                  uint8_t* dst,
                                                  int stride,
@@ -1069,6 +1129,10 @@
                                          uint8_t* dst,
                                          int stride,
                                          const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_8x16_avx2(const tran_low_t* dqcoeff,
+                                       uint8_t* dst,
+                                       int stride,
+                                       const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_8x16)(const tran_low_t* dqcoeff,
                                                  uint8_t* dst,
                                                  int stride,
@@ -1082,6 +1146,10 @@
                                          uint8_t* dst,
                                          int stride,
                                          const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_8x32_avx2(const tran_low_t* dqcoeff,
+                                       uint8_t* dst,
+                                       int stride,
+                                       const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_8x32)(const tran_low_t* dqcoeff,
                                                  uint8_t* dst,
                                                  int stride,
@@ -1108,6 +1176,10 @@
                                         uint8_t* dst,
                                         int stride,
                                         const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_8x8_avx2(const tran_low_t* dqcoeff,
+                                      uint8_t* dst,
+                                      int stride,
+                                      const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_8x8)(const tran_low_t* dqcoeff,
                                                 uint8_t* dst,
                                                 int stride,
@@ -1800,6 +1872,10 @@
     const int subpel_y_q4,
     ConvolveParams* conv_params);
 
+void av1_round_shift_array_c(int32_t* arr, int size, int bit);
+void av1_round_shift_array_sse4_1(int32_t* arr, int size, int bit);
+RTCD_EXTERN void (*av1_round_shift_array)(int32_t* arr, int size, int bit);
+
 int av1_selfguided_restoration_c(const uint8_t* dgd8,
                                  int width,
                                  int height,
@@ -2252,6 +2328,12 @@
     av1_highbd_convolve_y_sr = av1_highbd_convolve_y_sr_ssse3;
   if (flags & HAS_AVX2)
     av1_highbd_convolve_y_sr = av1_highbd_convolve_y_sr_avx2;
+  av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_c;
+  if (flags & HAS_AVX2)
+    av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_avx2;
+  av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_c;
+  if (flags & HAS_AVX2)
+    av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_avx2;
   av1_highbd_inv_txfm_add = av1_highbd_inv_txfm_add_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add = av1_highbd_inv_txfm_add_sse4_1;
@@ -2260,18 +2342,26 @@
   av1_highbd_inv_txfm_add_16x16 = av1_highbd_inv_txfm_add_16x16_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_16x16 = av1_highbd_inv_txfm_add_16x16_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_16x16 = av1_highbd_inv_txfm_add_16x16_avx2;
   av1_highbd_inv_txfm_add_16x32 = av1_highbd_inv_txfm_add_16x32_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_16x32 = av1_highbd_inv_txfm_add_16x32_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_16x32 = av1_highbd_inv_txfm_add_16x32_avx2;
   av1_highbd_inv_txfm_add_16x4 = av1_highbd_inv_txfm_add_16x4_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_16x4 = av1_highbd_inv_txfm_add_16x4_sse4_1;
   av1_highbd_inv_txfm_add_16x8 = av1_highbd_inv_txfm_add_16x8_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_16x8 = av1_highbd_inv_txfm_add_16x8_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_16x8 = av1_highbd_inv_txfm_add_16x8_avx2;
   av1_highbd_inv_txfm_add_32x16 = av1_highbd_inv_txfm_add_32x16_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_32x16 = av1_highbd_inv_txfm_add_32x16_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_32x16 = av1_highbd_inv_txfm_add_32x16_avx2;
   av1_highbd_inv_txfm_add_32x32 = av1_highbd_inv_txfm_add_32x32_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_32x32 = av1_highbd_inv_txfm_add_32x32_sse4_1;
@@ -2280,6 +2370,8 @@
   av1_highbd_inv_txfm_add_32x8 = av1_highbd_inv_txfm_add_32x8_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_32x8 = av1_highbd_inv_txfm_add_32x8_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_32x8 = av1_highbd_inv_txfm_add_32x8_avx2;
   av1_highbd_inv_txfm_add_4x16 = av1_highbd_inv_txfm_add_4x16_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_4x16 = av1_highbd_inv_txfm_add_4x16_sse4_1;
@@ -2292,15 +2384,21 @@
   av1_highbd_inv_txfm_add_8x16 = av1_highbd_inv_txfm_add_8x16_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_8x16 = av1_highbd_inv_txfm_add_8x16_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_8x16 = av1_highbd_inv_txfm_add_8x16_avx2;
   av1_highbd_inv_txfm_add_8x32 = av1_highbd_inv_txfm_add_8x32_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_8x32 = av1_highbd_inv_txfm_add_8x32_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_8x32 = av1_highbd_inv_txfm_add_8x32_avx2;
   av1_highbd_inv_txfm_add_8x4 = av1_highbd_inv_txfm_add_8x4_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_8x4 = av1_highbd_inv_txfm_add_8x4_sse4_1;
   av1_highbd_inv_txfm_add_8x8 = av1_highbd_inv_txfm_add_8x8_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_8x8 = av1_highbd_inv_txfm_add_8x8_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_8x8 = av1_highbd_inv_txfm_add_8x8_avx2;
   av1_highbd_jnt_convolve_2d = av1_highbd_jnt_convolve_2d_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_jnt_convolve_2d = av1_highbd_jnt_convolve_2d_sse4_1;
@@ -2356,6 +2454,9 @@
   av1_jnt_convolve_y = av1_jnt_convolve_y_sse2;
   if (flags & HAS_AVX2)
     av1_jnt_convolve_y = av1_jnt_convolve_y_avx2;
+  av1_round_shift_array = av1_round_shift_array_c;
+  if (flags & HAS_SSE4_1)
+    av1_round_shift_array = av1_round_shift_array_sse4_1;
   av1_selfguided_restoration = av1_selfguided_restoration_c;
   if (flags & HAS_SSE4_1)
     av1_selfguided_restoration = av1_selfguided_restoration_sse4_1;
diff --git a/third_party/libaom/source/config/win/x64/config/aom_config.asm b/third_party/libaom/source/config/win/x64/config/aom_config.asm
index d4480745..b35162ed 100644
--- a/third_party/libaom/source/config/win/x64/config/aom_config.asm
+++ b/third_party/libaom/source/config/win/x64/config/aom_config.asm
@@ -15,6 +15,7 @@
 %define CONFIG_COLLECT_RD_STATS 0
 %define CONFIG_DEBUG 0
 %define CONFIG_DENOISE 1
+%define CONFIG_DISABLE_FULL_PIXEL_SPLIT_8X8 1
 %define CONFIG_DIST_8X8 0
 %define CONFIG_ENTROPY_STATS 0
 %define CONFIG_FILEOPTIONS 1
diff --git a/third_party/libaom/source/config/win/x64/config/aom_config.h b/third_party/libaom/source/config/win/x64/config/aom_config.h
index f5743322..a3c9390f 100644
--- a/third_party/libaom/source/config/win/x64/config/aom_config.h
+++ b/third_party/libaom/source/config/win/x64/config/aom_config.h
@@ -27,6 +27,7 @@
 #define CONFIG_COLLECT_RD_STATS 0
 #define CONFIG_DEBUG 0
 #define CONFIG_DENOISE 1
+#define CONFIG_DISABLE_FULL_PIXEL_SPLIT_8X8 1
 #define CONFIG_DIST_8X8 0
 #define CONFIG_ENTROPY_STATS 0
 #define CONFIG_FILEOPTIONS 1
diff --git a/third_party/libaom/source/config/win/x64/config/aom_dsp_rtcd.h b/third_party/libaom/source/config/win/x64/config/aom_dsp_rtcd.h
index 44024bd0..340f39c 100644
--- a/third_party/libaom/source/config/win/x64/config/aom_dsp_rtcd.h
+++ b/third_party/libaom/source/config/win/x64/config/aom_dsp_rtcd.h
@@ -5378,10 +5378,6 @@
                               const uint8_t* left);
 #define aom_v_predictor_8x8 aom_v_predictor_8x8_sse2
 
-void av1_round_shift_array_c(int32_t* arr, int size, int bit);
-void av1_round_shift_array_sse4_1(int32_t* arr, int size, int bit);
-RTCD_EXTERN void (*av1_round_shift_array)(int32_t* arr, int size, int bit);
-
 void aom_dsp_rtcd(void);
 
 #ifdef RTCD_C
@@ -5799,9 +5795,6 @@
   aom_v_predictor_64x64 = aom_v_predictor_64x64_sse2;
   if (flags & HAS_AVX2)
     aom_v_predictor_64x64 = aom_v_predictor_64x64_avx2;
-  av1_round_shift_array = av1_round_shift_array_c;
-  if (flags & HAS_SSE4_1)
-    av1_round_shift_array = av1_round_shift_array_sse4_1;
 }
 #endif
 
diff --git a/third_party/libaom/source/config/win/x64/config/aom_scale_rtcd.h b/third_party/libaom/source/config/win/x64/config/aom_scale_rtcd.h
index 9fe39d9..57e5fea 100644
--- a/third_party/libaom/source/config/win/x64/config/aom_scale_rtcd.h
+++ b/third_party/libaom/source/config/win/x64/config/aom_scale_rtcd.h
@@ -92,28 +92,58 @@
                                      const int num_planes);
 #define aom_yv12_extend_frame_borders aom_yv12_extend_frame_borders_c
 
+void aom_yv12_partial_coloc_copy_u_c(const struct yv12_buffer_config* src_bc,
+                                     struct yv12_buffer_config* dst_bc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_u aom_yv12_partial_coloc_copy_u_c
+
+void aom_yv12_partial_coloc_copy_v_c(const struct yv12_buffer_config* src_bc,
+                                     struct yv12_buffer_config* dst_bc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_v aom_yv12_partial_coloc_copy_v_c
+
+void aom_yv12_partial_coloc_copy_y_c(const struct yv12_buffer_config* src_ybc,
+                                     struct yv12_buffer_config* dst_ybc,
+                                     int hstart,
+                                     int hend,
+                                     int vstart,
+                                     int vend);
+#define aom_yv12_partial_coloc_copy_y aom_yv12_partial_coloc_copy_y_c
+
 void aom_yv12_partial_copy_u_c(const struct yv12_buffer_config* src_bc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_bc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_u aom_yv12_partial_copy_u_c
 
 void aom_yv12_partial_copy_v_c(const struct yv12_buffer_config* src_bc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_bc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_v aom_yv12_partial_copy_v_c
 
 void aom_yv12_partial_copy_y_c(const struct yv12_buffer_config* src_ybc,
+                               int hstart1,
+                               int hend1,
+                               int vstart1,
+                               int vend1,
                                struct yv12_buffer_config* dst_ybc,
-                               int hstart,
-                               int hend,
-                               int vstart,
-                               int vend);
+                               int hstart2,
+                               int vstart2);
 #define aom_yv12_partial_copy_y aom_yv12_partial_copy_y_c
 
 void aom_scale_rtcd(void);
diff --git a/third_party/libaom/source/config/win/x64/config/av1_rtcd.h b/third_party/libaom/source/config/win/x64/config/av1_rtcd.h
index e570d52..a8a8ae7 100644
--- a/third_party/libaom/source/config/win/x64/config/av1_rtcd.h
+++ b/third_party/libaom/source/config/win/x64/config/av1_rtcd.h
@@ -31,6 +31,8 @@
 struct aom_variance_vtable;
 struct search_site_config;
 struct yv12_buffer_config;
+struct NN_CONFIG;
+typedef struct NN_CONFIG NN_CONFIG;
 
 /* Function pointers return by CfL functions */
 typedef void (*cfl_subsample_lbd_fn)(const uint8_t* input,
@@ -916,7 +918,26 @@
                                    int dx,
                                    int dy,
                                    int bd);
-#define av1_highbd_dr_prediction_z1 av1_highbd_dr_prediction_z1_c
+void av1_highbd_dr_prediction_z1_avx2(uint16_t* dst,
+                                      ptrdiff_t stride,
+                                      int bw,
+                                      int bh,
+                                      const uint16_t* above,
+                                      const uint16_t* left,
+                                      int upsample_above,
+                                      int dx,
+                                      int dy,
+                                      int bd);
+RTCD_EXTERN void (*av1_highbd_dr_prediction_z1)(uint16_t* dst,
+                                                ptrdiff_t stride,
+                                                int bw,
+                                                int bh,
+                                                const uint16_t* above,
+                                                const uint16_t* left,
+                                                int upsample_above,
+                                                int dx,
+                                                int dy,
+                                                int bd);
 
 void av1_highbd_dr_prediction_z2_c(uint16_t* dst,
                                    ptrdiff_t stride,
@@ -941,7 +962,26 @@
                                    int dx,
                                    int dy,
                                    int bd);
-#define av1_highbd_dr_prediction_z3 av1_highbd_dr_prediction_z3_c
+void av1_highbd_dr_prediction_z3_avx2(uint16_t* dst,
+                                      ptrdiff_t stride,
+                                      int bw,
+                                      int bh,
+                                      const uint16_t* above,
+                                      const uint16_t* left,
+                                      int upsample_left,
+                                      int dx,
+                                      int dy,
+                                      int bd);
+RTCD_EXTERN void (*av1_highbd_dr_prediction_z3)(uint16_t* dst,
+                                                ptrdiff_t stride,
+                                                int bw,
+                                                int bh,
+                                                const uint16_t* above,
+                                                const uint16_t* left,
+                                                int upsample_left,
+                                                int dx,
+                                                int dy,
+                                                int bd);
 
 void av1_highbd_inv_txfm_add_c(const tran_low_t* dqcoeff,
                                uint8_t* dst,
@@ -968,6 +1008,10 @@
                                           uint8_t* dst,
                                           int stride,
                                           const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_16x16_avx2(const tran_low_t* dqcoeff,
+                                        uint8_t* dst,
+                                        int stride,
+                                        const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_16x16)(const tran_low_t* dqcoeff,
                                                   uint8_t* dst,
                                                   int stride,
@@ -981,6 +1025,10 @@
                                           uint8_t* dst,
                                           int stride,
                                           const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_16x32_avx2(const tran_low_t* dqcoeff,
+                                        uint8_t* dst,
+                                        int stride,
+                                        const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_16x32)(const tran_low_t* dqcoeff,
                                                   uint8_t* dst,
                                                   int stride,
@@ -1007,6 +1055,10 @@
                                          uint8_t* dst,
                                          int stride,
                                          const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_16x8_avx2(const tran_low_t* dqcoeff,
+                                       uint8_t* dst,
+                                       int stride,
+                                       const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_16x8)(const tran_low_t* dqcoeff,
                                                  uint8_t* dst,
                                                  int stride,
@@ -1020,6 +1072,10 @@
                                           uint8_t* dst,
                                           int stride,
                                           const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_32x16_avx2(const tran_low_t* dqcoeff,
+                                        uint8_t* dst,
+                                        int stride,
+                                        const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_32x16)(const tran_low_t* dqcoeff,
                                                   uint8_t* dst,
                                                   int stride,
@@ -1050,6 +1106,10 @@
                                          uint8_t* dst,
                                          int stride,
                                          const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_32x8_avx2(const tran_low_t* dqcoeff,
+                                       uint8_t* dst,
+                                       int stride,
+                                       const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_32x8)(const tran_low_t* dqcoeff,
                                                  uint8_t* dst,
                                                  int stride,
@@ -1102,6 +1162,10 @@
                                          uint8_t* dst,
                                          int stride,
                                          const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_8x16_avx2(const tran_low_t* dqcoeff,
+                                       uint8_t* dst,
+                                       int stride,
+                                       const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_8x16)(const tran_low_t* dqcoeff,
                                                  uint8_t* dst,
                                                  int stride,
@@ -1115,6 +1179,10 @@
                                          uint8_t* dst,
                                          int stride,
                                          const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_8x32_avx2(const tran_low_t* dqcoeff,
+                                       uint8_t* dst,
+                                       int stride,
+                                       const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_8x32)(const tran_low_t* dqcoeff,
                                                  uint8_t* dst,
                                                  int stride,
@@ -1141,6 +1209,10 @@
                                         uint8_t* dst,
                                         int stride,
                                         const TxfmParam* txfm_param);
+void av1_highbd_inv_txfm_add_8x8_avx2(const tran_low_t* dqcoeff,
+                                      uint8_t* dst,
+                                      int stride,
+                                      const TxfmParam* txfm_param);
 RTCD_EXTERN void (*av1_highbd_inv_txfm_add_8x8)(const tran_low_t* dqcoeff,
                                                 uint8_t* dst,
                                                 int stride,
@@ -1833,6 +1905,10 @@
     const int subpel_y_q4,
     ConvolveParams* conv_params);
 
+void av1_round_shift_array_c(int32_t* arr, int size, int bit);
+void av1_round_shift_array_sse4_1(int32_t* arr, int size, int bit);
+RTCD_EXTERN void (*av1_round_shift_array)(int32_t* arr, int size, int bit);
+
 int av1_selfguided_restoration_c(const uint8_t* dgd8,
                                  int width,
                                  int height,
@@ -2285,6 +2361,12 @@
     av1_highbd_convolve_y_sr = av1_highbd_convolve_y_sr_ssse3;
   if (flags & HAS_AVX2)
     av1_highbd_convolve_y_sr = av1_highbd_convolve_y_sr_avx2;
+  av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_c;
+  if (flags & HAS_AVX2)
+    av1_highbd_dr_prediction_z1 = av1_highbd_dr_prediction_z1_avx2;
+  av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_c;
+  if (flags & HAS_AVX2)
+    av1_highbd_dr_prediction_z3 = av1_highbd_dr_prediction_z3_avx2;
   av1_highbd_inv_txfm_add = av1_highbd_inv_txfm_add_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add = av1_highbd_inv_txfm_add_sse4_1;
@@ -2293,18 +2375,26 @@
   av1_highbd_inv_txfm_add_16x16 = av1_highbd_inv_txfm_add_16x16_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_16x16 = av1_highbd_inv_txfm_add_16x16_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_16x16 = av1_highbd_inv_txfm_add_16x16_avx2;
   av1_highbd_inv_txfm_add_16x32 = av1_highbd_inv_txfm_add_16x32_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_16x32 = av1_highbd_inv_txfm_add_16x32_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_16x32 = av1_highbd_inv_txfm_add_16x32_avx2;
   av1_highbd_inv_txfm_add_16x4 = av1_highbd_inv_txfm_add_16x4_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_16x4 = av1_highbd_inv_txfm_add_16x4_sse4_1;
   av1_highbd_inv_txfm_add_16x8 = av1_highbd_inv_txfm_add_16x8_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_16x8 = av1_highbd_inv_txfm_add_16x8_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_16x8 = av1_highbd_inv_txfm_add_16x8_avx2;
   av1_highbd_inv_txfm_add_32x16 = av1_highbd_inv_txfm_add_32x16_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_32x16 = av1_highbd_inv_txfm_add_32x16_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_32x16 = av1_highbd_inv_txfm_add_32x16_avx2;
   av1_highbd_inv_txfm_add_32x32 = av1_highbd_inv_txfm_add_32x32_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_32x32 = av1_highbd_inv_txfm_add_32x32_sse4_1;
@@ -2313,6 +2403,8 @@
   av1_highbd_inv_txfm_add_32x8 = av1_highbd_inv_txfm_add_32x8_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_32x8 = av1_highbd_inv_txfm_add_32x8_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_32x8 = av1_highbd_inv_txfm_add_32x8_avx2;
   av1_highbd_inv_txfm_add_4x16 = av1_highbd_inv_txfm_add_4x16_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_4x16 = av1_highbd_inv_txfm_add_4x16_sse4_1;
@@ -2325,15 +2417,21 @@
   av1_highbd_inv_txfm_add_8x16 = av1_highbd_inv_txfm_add_8x16_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_8x16 = av1_highbd_inv_txfm_add_8x16_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_8x16 = av1_highbd_inv_txfm_add_8x16_avx2;
   av1_highbd_inv_txfm_add_8x32 = av1_highbd_inv_txfm_add_8x32_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_8x32 = av1_highbd_inv_txfm_add_8x32_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_8x32 = av1_highbd_inv_txfm_add_8x32_avx2;
   av1_highbd_inv_txfm_add_8x4 = av1_highbd_inv_txfm_add_8x4_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_8x4 = av1_highbd_inv_txfm_add_8x4_sse4_1;
   av1_highbd_inv_txfm_add_8x8 = av1_highbd_inv_txfm_add_8x8_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_inv_txfm_add_8x8 = av1_highbd_inv_txfm_add_8x8_sse4_1;
+  if (flags & HAS_AVX2)
+    av1_highbd_inv_txfm_add_8x8 = av1_highbd_inv_txfm_add_8x8_avx2;
   av1_highbd_jnt_convolve_2d = av1_highbd_jnt_convolve_2d_c;
   if (flags & HAS_SSE4_1)
     av1_highbd_jnt_convolve_2d = av1_highbd_jnt_convolve_2d_sse4_1;
@@ -2389,6 +2487,9 @@
   av1_jnt_convolve_y = av1_jnt_convolve_y_sse2;
   if (flags & HAS_AVX2)
     av1_jnt_convolve_y = av1_jnt_convolve_y_avx2;
+  av1_round_shift_array = av1_round_shift_array_c;
+  if (flags & HAS_SSE4_1)
+    av1_round_shift_array = av1_round_shift_array_sse4_1;
   av1_selfguided_restoration = av1_selfguided_restoration_c;
   if (flags & HAS_SSE4_1)
     av1_selfguided_restoration = av1_selfguided_restoration_sse4_1;
diff --git a/third_party/libwebp/BUILD.gn b/third_party/libwebp/BUILD.gn
index 1f93409a..a78690d 100644
--- a/third_party/libwebp/BUILD.gn
+++ b/third_party/libwebp/BUILD.gn
@@ -632,18 +632,3 @@
   defines = [ "WEBP_MAX_IMAGE_SIZE=838860800" ]
   additional_configs = [ ":libwebp_config_internal" ]
 }
-
-fuzzer_test("libwebp_anim_encoder_fuzzer") {
-  sources = [
-    "fuzzing/fuzz_webp_animencoder.cc",
-  ]
-  dict = "fuzzing/fuzz.dict"
-  seed_corpus = "fuzzing/fuzz_seed_corpus"
-  deps = [
-    ":libwebp",
-    ":libwebp_webp",
-  ]
-  cflags_cc = [ "-Wno-unused-function" ]
-  defines = [ "WEBP_MAX_IMAGE_SIZE=838860800" ]
-  additional_configs = [ ":libwebp_config_internal" ]
-}
diff --git a/third_party/libwebp/fuzzing/fuzz_advanced_api.cc b/third_party/libwebp/fuzzing/fuzz_advanced_api.cc
index 27cb439..5520588 100644
--- a/third_party/libwebp/fuzzing/fuzz_advanced_api.cc
+++ b/third_party/libwebp/fuzzing/fuzz_advanced_api.cc
@@ -54,7 +54,13 @@
     config.options.scaled_height = (int)(config.input.height * factor * 2);
   }
 
+#if defined(WEBP_REDUCE_CSP)
+  config.output.colorspace = (value & 1)
+                                 ? ((value & 2) ? MODE_RGBA : MODE_BGRA)
+                                 : ((value & 2) ? MODE_rgbA : MODE_bgrA);
+#else
   config.output.colorspace = (WEBP_CSP_MODE)(value % MODE_LAST);
+#endif  // WEBP_REDUCE_CSP
 
   if (size % 3) {
     // Decodes incrementally in chunks of increasing size.
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index b7c0138..1cfa061 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -1494,7 +1494,7 @@
     ],
 
     'libfuzzer_ubsan_release_bot': [
-      'libfuzzer', 'ubsan_security', 'release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing',
+      'libfuzzer', 'ubsan_security', 'shared_release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing',
     ],
 
     'libfuzzer_mac_asan_release_bot': [
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index be6269c..df54b37c 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -3479,7 +3479,8 @@
   <int value="13" label="Download resumption task"/>
   <int value="14" label="Feed refresh task"/>
   <int value="15" label="Component update task"/>
-  <int value="16" label="Explore Sites refresh task"/>
+  <int value="16" label="Deprecated Explore Sites refresh task"/>
+  <int value="17" label="Explore Sites refresh task"/>
 </enum>
 
 <enum name="BackgroundTracingState">
@@ -21980,6 +21981,11 @@
   <int value="14" label="DRIVE_FAKE_ROOT"/>
   <int value="15" label="ADD_NEW_SERVICES_MENU"/>
   <int value="16" label="CROSTINI"/>
+  <int value="17" label="ANDROID_FILES"/>
+  <int value="18" label="MY_FILES"/>
+  <int value="19" label="COMPUTERS_GRAND_ROOT"/>
+  <int value="20" label="COMPUTER"/>
+  <int value="21" label="EXTERNAL_MEDIA"/>
 </enum>
 
 <enum name="FileManagerTaskType">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 9c98f0f..2920429 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -35023,7 +35023,7 @@
 </histogram>
 
 <histogram name="FileBrowser.ChangeDirectory.RootType"
-    enum="FileManagerRootType">
+    enum="FileManagerRootType" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35034,6 +35034,9 @@
 
 <histogram name="FileBrowser.CloudImport.UserAction"
     enum="CloudImportUserAction">
+  <obsolete>
+    Was removed from the code at an unknown time.
+  </obsolete>
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35044,7 +35047,7 @@
 </histogram>
 
 <histogram name="FileBrowser.ComputersCount" units="Computers"
-    expires_after="M76">
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35055,7 +35058,7 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.Create" enum="FileDialogType">
+<histogram name="FileBrowser.Create" enum="FileDialogType" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>Chrome OS File Browser opening mode.</summary>
@@ -35079,7 +35082,7 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.DirectoryScan" units="ms">
+<histogram name="FileBrowser.DirectoryScan" units="ms" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35089,7 +35092,7 @@
 </histogram>
 
 <histogram name="FileBrowser.DownloadDestination.IsGoogleDrive.Changed"
-    enum="BooleanEnabled">
+    enum="BooleanEnabled" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35099,7 +35102,7 @@
 </histogram>
 
 <histogram name="FileBrowser.DownloadDestination.IsGoogleDrive.Started"
-    enum="BooleanEnabled">
+    enum="BooleanEnabled" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35108,7 +35111,7 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.DownloadsCount">
+<histogram name="FileBrowser.DownloadsCount" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35138,7 +35141,7 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.FolderShortcut.Add">
+<histogram name="FileBrowser.FolderShortcut.Add" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35147,7 +35150,7 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.FolderShortcut.Count">
+<histogram name="FileBrowser.FolderShortcut.Count" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35156,7 +35159,7 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.FolderShortcut.Navigate">
+<histogram name="FileBrowser.FolderShortcut.Navigate" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35165,7 +35168,7 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.FolderShortcut.Remove">
+<histogram name="FileBrowser.FolderShortcut.Remove" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35175,7 +35178,7 @@
 </histogram>
 
 <histogram name="FileBrowser.HardUnpluggedAroundSuspend.TimeSinceResume"
-    units="ms">
+    units="ms" expires_after="M79">
   <obsolete>
     The bug which the UMA was investigating got fixed.
   </obsolete>
@@ -35188,7 +35191,7 @@
 </histogram>
 
 <histogram name="FileBrowser.HardUnpluggedAroundSuspend.TimeUntilSuspend"
-    units="ms">
+    units="ms" expires_after="M79">
   <obsolete>
     The bug which the UMA was investigating got fixed.
   </obsolete>
@@ -35217,7 +35220,7 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.Load" units="ms">
+<histogram name="FileBrowser.Load" units="ms" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35229,7 +35232,7 @@
 </histogram>
 
 <histogram name="FileBrowser.Location.OnEntryExpandedOrCollapsed.NonTopLevel"
-    enum="FileManagerRootType">
+    enum="FileManagerRootType" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35240,7 +35243,7 @@
 </histogram>
 
 <histogram name="FileBrowser.Location.OnEntryExpandedOrCollapsed.TopLevel"
-    enum="FileManagerRootType">
+    enum="FileManagerRootType" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35251,7 +35254,7 @@
 </histogram>
 
 <histogram name="FileBrowser.Location.OnEntrySelected.NonTopLevel"
-    enum="FileManagerRootType">
+    enum="FileManagerRootType" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35261,7 +35264,7 @@
 </histogram>
 
 <histogram name="FileBrowser.Location.OnEntrySelected.TopLevel"
-    enum="FileManagerRootType">
+    enum="FileManagerRootType" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35323,7 +35326,8 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.MenuItemSelected" enum="FileManagerMenuCommands">
+<histogram name="FileBrowser.MenuItemSelected" enum="FileManagerMenuCommands"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>wiefangsun@chromium.org</owner>
   <summary>
@@ -35342,7 +35346,8 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.OpenFiles.RootType" enum="FileManagerRootType">
+<histogram name="FileBrowser.OpenFiles.RootType" enum="FileManagerRootType"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>wiefangsun@chromium.org</owner>
   <summary>
@@ -35360,7 +35365,8 @@
   <summary>File types that were tried to be opened through browser.</summary>
 </histogram>
 
-<histogram name="FileBrowser.PhotoEditor.DisplayTime" units="ms">
+<histogram name="FileBrowser.PhotoEditor.DisplayTime" units="ms"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35370,26 +35376,29 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.PhotoEditor.FileType" enum="PhotoEditorFileType">
+<histogram name="FileBrowser.PhotoEditor.FileType" enum="PhotoEditorFileType"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>Chrome OS Photo Editor: the type of the file opened.</summary>
 </histogram>
 
-<histogram name="FileBrowser.PhotoEditor.LoadMode" enum="PhotoEditorLoadMode">
+<histogram name="FileBrowser.PhotoEditor.LoadMode" enum="PhotoEditorLoadMode"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>Chrome OS Photo Editor: the way the image has been loaded.</summary>
 </histogram>
 
-<histogram name="FileBrowser.PhotoEditor.LoadTime" units="ms">
+<histogram name="FileBrowser.PhotoEditor.LoadTime" units="ms"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>Chrome OS Photo Editor: time to load an image from a file.</summary>
 </histogram>
 
 <histogram name="FileBrowser.PhotoEditor.SaveResult"
-    enum="PhotoEditorSaveResult">
+    enum="PhotoEditorSaveResult" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35397,13 +35406,15 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.PhotoEditor.SaveTime" units="ms">
+<histogram name="FileBrowser.PhotoEditor.SaveTime" units="ms"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>Chrome OS Photo Editor: time to save an image to a file.</summary>
 </histogram>
 
-<histogram name="FileBrowser.PhotoEditor.Size.MB" units="MBytes">
+<histogram name="FileBrowser.PhotoEditor.Size.MB" units="MBytes"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35412,7 +35423,8 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.PhotoEditor.Size.MPix" units="MPixels">
+<histogram name="FileBrowser.PhotoEditor.Size.MPix" units="MPixels"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35421,7 +35433,8 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.PhotoEditor.Tool" enum="PhotoEditorToolType">
+<histogram name="FileBrowser.PhotoEditor.Tool" enum="PhotoEditorToolType"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>Chrome OS Photo Editor: the button which the user clicked.</summary>
@@ -35495,32 +35508,36 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.QuickView.FileType" enum="ViewFileType">
+<histogram name="FileBrowser.QuickView.FileType" enum="ViewFileType"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>File types that were tried to be opened with quick view.</summary>
 </histogram>
 
-<histogram name="FileBrowser.QuickView.FileTypeOnLaunch" enum="ViewFileType">
+<histogram name="FileBrowser.QuickView.FileTypeOnLaunch" enum="ViewFileType"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>File types that were selected when quick view is launched.</summary>
 </histogram>
 
-<histogram name="FileBrowser.QuickView.VolumeType" enum="FileManagerVolumeType">
+<histogram name="FileBrowser.QuickView.VolumeType" enum="FileManagerVolumeType"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>The volume type where quick view is opened.</summary>
 </histogram>
 
 <histogram name="FileBrowser.QuickView.WayToOpen"
-    enum="FileManagerQuickViewWayToOpen">
+    enum="FileManagerQuickViewWayToOpen" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>How quick view was opened.</summary>
 </histogram>
 
-<histogram name="FileBrowser.Recent.LoadArcMedia" units="ms">
+<histogram name="FileBrowser.Recent.LoadArcMedia" units="ms"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35529,7 +35546,8 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.Recent.LoadDownloads" units="ms">
+<histogram name="FileBrowser.Recent.LoadDownloads" units="ms"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35538,7 +35556,7 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.Recent.LoadDrive" units="ms">
+<histogram name="FileBrowser.Recent.LoadDrive" units="ms" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35547,7 +35565,7 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.Recent.LoadTotal" units="ms">
+<histogram name="FileBrowser.Recent.LoadTotal" units="ms" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35557,7 +35575,7 @@
 </histogram>
 
 <histogram name="FileBrowser.SuggestApps.CloseDialog"
-    enum="SuggestAppsDialogCloseReason">
+    enum="SuggestAppsDialogCloseReason" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35566,7 +35584,7 @@
 </histogram>
 
 <histogram name="FileBrowser.SuggestApps.Install"
-    enum="SuggestAppsDialogInstall">
+    enum="SuggestAppsDialogInstall" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35575,7 +35593,8 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.SuggestApps.Load" enum="SuggestAppsDialogLoad">
+<histogram name="FileBrowser.SuggestApps.Load" enum="SuggestAppsDialogLoad"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35584,7 +35603,8 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.SuggestApps.LoadTime" units="ms">
+<histogram name="FileBrowser.SuggestApps.LoadTime" units="ms"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35595,7 +35615,7 @@
 </histogram>
 
 <histogram name="FileBrowser.TeamDrivesCount" units="Team Drives"
-    expires_after="M75">
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35606,7 +35626,8 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.ToggleFileListType" enum="FileManagerListType">
+<histogram name="FileBrowser.ToggleFileListType" enum="FileManagerListType"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35615,7 +35636,8 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.ViewingFileType" enum="ViewFileType">
+<histogram name="FileBrowser.ViewingFileType" enum="ViewFileType"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35625,7 +35647,7 @@
 </histogram>
 
 <histogram name="FileBrowser.ViewingFileType.Offline" enum="ViewFileType"
-    expires_after="2019-12-31">
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35636,7 +35658,7 @@
 </histogram>
 
 <histogram name="FileBrowser.ViewingFileType.Online" enum="ViewFileType"
-    expires_after="2019-12-31">
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35646,7 +35668,8 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.ViewingRootType" enum="FileManagerRootType">
+<histogram name="FileBrowser.ViewingRootType" enum="FileManagerRootType"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35656,7 +35679,7 @@
 </histogram>
 
 <histogram name="FileBrowser.ViewingRootType.Offline"
-    enum="FileManagerRootType" expires_after="2019-12-31">
+    enum="FileManagerRootType" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35667,7 +35690,7 @@
 </histogram>
 
 <histogram name="FileBrowser.ViewingRootType.Online" enum="FileManagerRootType"
-    expires_after="2019-12-31">
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35677,7 +35700,8 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.ViewingTaskType" enum="FileManagerTaskType">
+<histogram name="FileBrowser.ViewingTaskType" enum="FileManagerTaskType"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35687,7 +35711,7 @@
 </histogram>
 
 <histogram name="FileBrowser.ViewingTaskType.Offline"
-    enum="FileManagerTaskType" expires_after="2019-12-31">
+    enum="FileManagerTaskType" expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35698,7 +35722,7 @@
 </histogram>
 
 <histogram name="FileBrowser.ViewingTaskType.Online" enum="FileManagerTaskType"
-    expires_after="2019-12-31">
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35708,7 +35732,8 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.VolumeType" enum="FileManagerVolumeType">
+<histogram name="FileBrowser.VolumeType" enum="FileManagerVolumeType"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
@@ -35717,7 +35742,8 @@
   </summary>
 </histogram>
 
-<histogram name="FileBrowser.ZipFileTask" enum="FileManagerZipHandlerType">
+<histogram name="FileBrowser.ZipFileTask" enum="FileManagerZipHandlerType"
+    expires_after="M79">
   <owner>slangley@chromium.org</owner>
   <owner>weifangsun@chromium.org</owner>
   <summary>
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn
index e092d55..155ebb3 100644
--- a/ui/accessibility/BUILD.gn
+++ b/ui/accessibility/BUILD.gn
@@ -76,6 +76,8 @@
     "ax_tree_id.h",
     "ax_tree_id_registry.cc",
     "ax_tree_id_registry.h",
+    "ax_tree_observer.cc",
+    "ax_tree_observer.h",
     "ax_tree_serializer.cc",
     "ax_tree_serializer.h",
     "ax_tree_source.h",
diff --git a/ui/accessibility/ax_enums.mojom b/ui/accessibility/ax_enums.mojom
index 439f15c..95b4b9b 100644
--- a/ui/accessibility/ax_enums.mojom
+++ b/ui/accessibility/ax_enums.mojom
@@ -877,8 +877,6 @@
 // For internal use by ui::AXTreeID / ax::mojom::AXTreeID.
 enum AXTreeIDType {
   kUnknown,  // The Tree ID is unknown.
-  kDesktop,  // The Tree ID is the desktop / root tree, which doesn't
-             // need to have an unguessable token.
   kToken,    // Every other tree ID must have a valid unguessable token.
 };
 
diff --git a/ui/accessibility/ax_event_generator.cc b/ui/accessibility/ax_event_generator.cc
index d96824cb..0a0d613 100644
--- a/ui/accessibility/ax_event_generator.cc
+++ b/ui/accessibility/ax_event_generator.cc
@@ -68,20 +68,20 @@
 
 AXEventGenerator::AXEventGenerator(AXTree* tree) : tree_(tree) {
   if (tree_)
-    tree_->SetDelegate(this);
+    tree_->AddObserver(this);
 }
 
 AXEventGenerator::~AXEventGenerator() {
   if (tree_)
-    tree_->SetDelegate(nullptr);
+    tree_->RemoveObserver(this);
 }
 
 void AXEventGenerator::SetTree(AXTree* new_tree) {
   if (tree_)
-    tree_->SetDelegate(nullptr);
+    tree_->RemoveObserver(this);
   tree_ = new_tree;
   if (tree_)
-    tree_->SetDelegate(this);
+    tree_->AddObserver(this);
 }
 
 void AXEventGenerator::ReleaseTree() {
@@ -290,15 +290,6 @@
   AddEvent(node, Event::OTHER_ATTRIBUTE_CHANGED);
 }
 
-void AXEventGenerator::OnStringListAttributeChanged(
-    AXTree* tree,
-    AXNode* node,
-    ax::mojom::StringListAttribute attr,
-    const std::vector<std::string>& old_value,
-    const std::vector<std::string>& new_value) {
-  DCHECK_EQ(tree_, tree);
-}
-
 void AXEventGenerator::OnTreeDataChanged(AXTree* tree,
                                          const ui::AXTreeData& old_tree_data,
                                          const ui::AXTreeData& new_tree_data) {
@@ -340,18 +331,6 @@
   DCHECK_EQ(tree_, tree);
 }
 
-void AXEventGenerator::OnNodeCreated(AXTree* tree, AXNode* node) {
-  DCHECK_EQ(tree_, tree);
-}
-
-void AXEventGenerator::OnNodeReparented(AXTree* tree, AXNode* node) {
-  DCHECK_EQ(tree_, tree);
-}
-
-void AXEventGenerator::OnNodeChanged(AXTree* tree, AXNode* node) {
-  DCHECK_EQ(tree_, tree);
-}
-
 void AXEventGenerator::OnAtomicUpdateFinished(
     AXTree* tree,
     bool root_changed,
diff --git a/ui/accessibility/ax_event_generator.h b/ui/accessibility/ax_event_generator.h
index 4e84982..268dd3f 100644
--- a/ui/accessibility/ax_event_generator.h
+++ b/ui/accessibility/ax_event_generator.h
@@ -11,14 +11,15 @@
 
 #include "ui/accessibility/ax_export.h"
 #include "ui/accessibility/ax_tree.h"
+#include "ui/accessibility/ax_tree_observer.h"
 
 namespace ui {
 
-// Subclass of AXTreeDelegate that automatically generates AXEvents to fire
+// Subclass of AXTreeObserver that automatically generates AXEvents to fire
 // based on changes to an accessibility tree.  Every platform
 // tends to want different events, so this class lets each platform
 // handle the events it wants and ignore the others.
-class AX_EXPORT AXEventGenerator : public AXTreeDelegate {
+class AX_EXPORT AXEventGenerator : public AXTreeObserver {
  public:
   enum class Event : int32_t {
     ACTIVE_DESCENDANT_CHANGED,
@@ -87,14 +88,14 @@
   // before using this class.
   AXEventGenerator();
 
-  // Automatically registers itself as the delegate of |tree| and
+  // Automatically registers itself as the observer of |tree| and
   // clears it on desctruction. |tree| must be valid for the lifetime
   // of this object.
   explicit AXEventGenerator(AXTree* tree);
 
   ~AXEventGenerator() override;
 
-  // Clears this class as the delegate of the previous tree that was
+  // Clears this class as the observer of the previous tree that was
   // being monitored, if any, and starts monitoring |new_tree|, if not
   // nullptr. Note that |new_tree| must be valid for the lifetime of
   // this object or until you call SetTree again.
@@ -112,7 +113,7 @@
   void ClearEvents();
 
   // This is called automatically based on changes to the tree observed
-  // by AXTreeDelegate, but you can also call it directly to add events
+  // by AXTreeObserver, but you can also call it directly to add events
   // and retrieve them later.
   //
   // Note that events are organized by node and then by event id to
@@ -126,7 +127,7 @@
   }
 
  protected:
-  // AXTreeDelegate overrides.
+  // AXTreeObserver overrides.
   void OnNodeDataWillChange(AXTree* tree,
                             const AXNodeData& old_node_data,
                             const AXNodeData& new_node_data) override;
@@ -163,12 +164,6 @@
       ax::mojom::IntListAttribute attr,
       const std::vector<int32_t>& old_value,
       const std::vector<int32_t>& new_value) override;
-  void OnStringListAttributeChanged(
-      AXTree* tree,
-      AXNode* node,
-      ax::mojom::StringListAttribute attr,
-      const std::vector<std::string>& old_value,
-      const std::vector<std::string>& new_value) override;
   void OnTreeDataChanged(AXTree* tree,
                          const ui::AXTreeData& old_data,
                          const ui::AXTreeData& new_data) override;
@@ -176,9 +171,6 @@
   void OnSubtreeWillBeDeleted(AXTree* tree, AXNode* node) override;
   void OnNodeWillBeReparented(AXTree* tree, AXNode* node) override;
   void OnSubtreeWillBeReparented(AXTree* tree, AXNode* node) override;
-  void OnNodeCreated(AXTree* tree, AXNode* node) override;
-  void OnNodeReparented(AXTree* tree, AXNode* node) override;
-  void OnNodeChanged(AXTree* tree, AXNode* node) override;
   void OnAtomicUpdateFinished(AXTree* tree,
                               bool root_changed,
                               const std::vector<Change>& changes) override;
diff --git a/ui/accessibility/ax_host_delegate.cc b/ui/accessibility/ax_host_delegate.cc
index 9e7104d..6c680678 100644
--- a/ui/accessibility/ax_host_delegate.cc
+++ b/ui/accessibility/ax_host_delegate.cc
@@ -8,13 +8,13 @@
 
 namespace ui {
 
+bool AXHostDelegate::RequiresPerformActionPointInPixels() const {
+  return false;
+}
+
 AXHostDelegate::AXHostDelegate()
     : tree_id_(AXTreeIDRegistry::GetInstance()->GetOrCreateAXTreeID(this)) {}
 
-AXHostDelegate::AXHostDelegate(AXTreeID tree_id) : tree_id_(tree_id) {
-  AXTreeIDRegistry::GetInstance()->SetDelegateForID(this, tree_id);
-}
-
 AXHostDelegate::~AXHostDelegate() {
   AXTreeIDRegistry::GetInstance()->RemoveAXTreeID(tree_id_);
 }
diff --git a/ui/accessibility/ax_host_delegate.h b/ui/accessibility/ax_host_delegate.h
index 4d49609..4c8bcc1 100644
--- a/ui/accessibility/ax_host_delegate.h
+++ b/ui/accessibility/ax_host_delegate.h
@@ -23,20 +23,20 @@
   virtual ~AXHostDelegate();
 
   // Handle an action from an accessibility client.
-  virtual void PerformAction(const ui::AXActionData& data) = 0;
+  virtual void PerformAction(const AXActionData& data) = 0;
+
+  // Returns whether this delegate expects points in pixels (true) or dips
+  // (false) for data passed to |PerformAction|.
+  virtual bool RequiresPerformActionPointInPixels() const;
 
   // A tree id appropriate for annotating events sent to an accessibility
   // client.
-  AXTreeID tree_id() const { return tree_id_; }
+  const AXTreeID& ax_tree_id() const { return tree_id_; };
 
  protected:
   // A delegate with an automatically assigned tree id.
   AXHostDelegate();
 
-  // A delegate with an explicit tree id. The caller is responsible for ensuring
-  // the uniqueness of the id.
-  explicit AXHostDelegate(AXTreeID tree_id);
-
  private:
   // Register or unregister this class with |AXTreeIDRegistry|.
   void UpdateActiveState(bool active);
diff --git a/ui/accessibility/ax_node_position_unittest.cc b/ui/accessibility/ax_node_position_unittest.cc
index 5aeeff0..f1b8e81 100644
--- a/ui/accessibility/ax_node_position_unittest.cc
+++ b/ui/accessibility/ax_node_position_unittest.cc
@@ -201,7 +201,7 @@
   initial_state.nodes.push_back(static_text2_);
   initial_state.nodes.push_back(inline_box2_);
   initial_state.has_tree_data = true;
-  initial_state.tree_data.tree_id = AXTreeID::FromString("0");
+  initial_state.tree_data.tree_id = AXTreeID::CreateNewAXTreeID();
   initial_state.tree_data.title = "Dialog title";
   AXSerializableTree src_tree(initial_state);
 
@@ -1691,22 +1691,22 @@
                   }),
                   ROOT_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=6 "
+                  {"TextPosition anchor_id=1 text_offset=6 "
                    "affinity=downstream annotated_text=Button<C>heck boxLine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=12 "
+                   "TextPosition anchor_id=1 text_offset=12 "
                    "affinity=downstream annotated_text=ButtonCheck <b>oxLine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+                   "TextPosition anchor_id=1 text_offset=15 "
                    "affinity=downstream annotated_text=ButtonCheck box<L>ine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=20 "
+                   "TextPosition anchor_id=1 text_offset=20 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "<1>\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=22 "
+                   "TextPosition anchor_id=1 text_offset=22 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\n<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=27 "
+                   "TextPosition anchor_id=1 text_offset=27 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\nLine <2>",
                    "NullPosition"}},
@@ -1716,11 +1716,11 @@
                   }),
                   TEXT_FIELD_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=5 "
+                  {"TextPosition anchor_id=4 text_offset=5 "
                    "affinity=downstream annotated_text=Line <1>\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=7 "
+                   "TextPosition anchor_id=4 text_offset=7 "
                    "affinity=downstream annotated_text=Line 1\n<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=12 "
+                   "TextPosition anchor_id=4 text_offset=12 "
                    "affinity=downstream annotated_text=Line 1\nLine <2>",
                    "NullPosition"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -1729,11 +1729,11 @@
                   }),
                   STATIC_TEXT1_ID,
                   1 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=5 text_offset=5 "
+                  {"TextPosition anchor_id=5 text_offset=5 "
                    "affinity=downstream annotated_text=Line <1>",
-                   "TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+                   "TextPosition anchor_id=9 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=9 text_offset=5 "
+                   "TextPosition anchor_id=9 text_offset=5 "
                    "affinity=downstream annotated_text=Line <2>",
                    "NullPosition"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -1742,7 +1742,7 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=5 "
+                  {"TextPosition anchor_id=9 text_offset=5 "
                    "affinity=downstream annotated_text=Line <2>",
                    "NullPosition"}}));
 
@@ -1756,25 +1756,25 @@
                   }),
                   ROOT_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=6 "
+                  {"TextPosition anchor_id=1 text_offset=6 "
                    "affinity=downstream annotated_text=Button<C>heck boxLine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=12 "
+                   "TextPosition anchor_id=1 text_offset=12 "
                    "affinity=downstream annotated_text=ButtonCheck <b>oxLine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+                   "TextPosition anchor_id=1 text_offset=15 "
                    "affinity=downstream annotated_text=ButtonCheck box<L>ine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=20 "
+                   "TextPosition anchor_id=1 text_offset=20 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "<1>\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=22 "
+                   "TextPosition anchor_id=1 text_offset=22 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\n<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=27 "
+                   "TextPosition anchor_id=1 text_offset=27 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\nLine <2>",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=28 "
+                   "TextPosition anchor_id=1 text_offset=28 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\nLine 2<>"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -1783,13 +1783,13 @@
                   }),
                   TEXT_FIELD_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=5 "
+                  {"TextPosition anchor_id=4 text_offset=5 "
                    "affinity=downstream annotated_text=Line <1>\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=7 "
+                   "TextPosition anchor_id=4 text_offset=7 "
                    "affinity=downstream annotated_text=Line 1\n<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=12 "
+                   "TextPosition anchor_id=4 text_offset=12 "
                    "affinity=downstream annotated_text=Line 1\nLine <2>",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=13 "
+                   "TextPosition anchor_id=4 text_offset=13 "
                    "affinity=downstream annotated_text=Line 1\nLine 2<>"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreateNextWordStartPosition(
@@ -1797,9 +1797,9 @@
                   }),
                   STATIC_TEXT1_ID,
                   1 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=5 text_offset=5 "
+                  {"TextPosition anchor_id=5 text_offset=5 "
                    "affinity=downstream annotated_text=Line <1>",
-                   "TextPosition tree_id=0 anchor_id=5 text_offset=6 "
+                   "TextPosition anchor_id=5 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<>"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreateNextWordStartPosition(
@@ -1807,9 +1807,9 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=5 "
+                  {"TextPosition anchor_id=9 text_offset=5 "
                    "affinity=downstream annotated_text=Line <2>",
-                   "TextPosition tree_id=0 anchor_id=9 text_offset=6 "
+                   "TextPosition anchor_id=9 text_offset=6 "
                    "affinity=downstream annotated_text=Line 2<>"}}));
 
 INSTANTIATE_TEST_CASE_P(
@@ -1822,10 +1822,10 @@
                   }),
                   ROOT_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=0 "
+                  {"TextPosition anchor_id=1 text_offset=0 "
                    "affinity=downstream annotated_text=<B>uttonCheck boxLine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=0 "
+                   "TextPosition anchor_id=1 text_offset=0 "
                    "affinity=downstream annotated_text=<B>uttonCheck boxLine "
                    "1\nLine 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -1834,9 +1834,9 @@
                   }),
                   TEXT_FIELD_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=0 "
+                  {"TextPosition anchor_id=4 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=0 "
+                   "TextPosition anchor_id=4 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreateNextWordStartPosition(
@@ -1844,9 +1844,9 @@
                   }),
                   STATIC_TEXT1_ID,
                   1 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=5 text_offset=5 "
+                  {"TextPosition anchor_id=5 text_offset=5 "
                    "affinity=downstream annotated_text=Line <1>",
-                   "TextPosition tree_id=0 anchor_id=5 text_offset=5 "
+                   "TextPosition anchor_id=5 text_offset=5 "
                    "affinity=downstream annotated_text=Line <1>"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreateNextWordStartPosition(
@@ -1854,9 +1854,9 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=5 "
+                  {"TextPosition anchor_id=9 text_offset=5 "
                    "affinity=downstream annotated_text=Line <2>",
-                   "TextPosition tree_id=0 anchor_id=9 text_offset=5 "
+                   "TextPosition anchor_id=9 text_offset=5 "
                    "affinity=downstream annotated_text=Line <2>"}}));
 
 INSTANTIATE_TEST_CASE_P(
@@ -1869,25 +1869,25 @@
                   }),
                   ROOT_ID,
                   28 /* text_offset at end of root. */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=27 "
+                  {"TextPosition anchor_id=1 text_offset=27 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\nLine <2>",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=22 "
+                   "TextPosition anchor_id=1 text_offset=22 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\n<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=20 "
+                   "TextPosition anchor_id=1 text_offset=20 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "<1>\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+                   "TextPosition anchor_id=1 text_offset=15 "
                    "affinity=downstream annotated_text=ButtonCheck box<L>ine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=12 "
+                   "TextPosition anchor_id=1 text_offset=12 "
                    "affinity=downstream annotated_text=ButtonCheck <b>oxLine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=6 "
+                   "TextPosition anchor_id=1 text_offset=6 "
                    "affinity=downstream annotated_text=Button<C>heck boxLine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=0 "
+                   "TextPosition anchor_id=1 text_offset=0 "
                    "affinity=downstream annotated_text=<B>uttonCheck boxLine "
                    "1\nLine 2",
                    "NullPosition"}},
@@ -1897,19 +1897,19 @@
                   }),
                   TEXT_FIELD_ID,
                   13 /* text_offset at end of text field */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=12 "
+                  {"TextPosition anchor_id=4 text_offset=12 "
                    "affinity=downstream annotated_text=Line 1\nLine <2>",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=7 "
+                   "TextPosition anchor_id=4 text_offset=7 "
                    "affinity=downstream annotated_text=Line 1\n<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=5 "
+                   "TextPosition anchor_id=4 text_offset=5 "
                    "affinity=downstream annotated_text=Line <1>\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=0 "
+                   "TextPosition anchor_id=4 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=3 text_offset=6 "
+                   "TextPosition anchor_id=3 text_offset=6 "
                    "affinity=downstream annotated_text=Check <b>ox",
-                   "TextPosition tree_id=0 anchor_id=3 text_offset=0 "
+                   "TextPosition anchor_id=3 text_offset=0 "
                    "affinity=downstream annotated_text=<C>heck box",
-                   "TextPosition tree_id=0 anchor_id=2 text_offset=0 "
+                   "TextPosition anchor_id=2 text_offset=0 "
                    "affinity=downstream annotated_text=<B>utton",
                    "NullPosition"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -1918,13 +1918,13 @@
                   }),
                   STATIC_TEXT1_ID,
                   5 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=5 text_offset=0 "
+                  {"TextPosition anchor_id=5 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1",
-                   "TextPosition tree_id=0 anchor_id=3 text_offset=6 "
+                   "TextPosition anchor_id=3 text_offset=6 "
                    "affinity=downstream annotated_text=Check <b>ox",
-                   "TextPosition tree_id=0 anchor_id=3 text_offset=0 "
+                   "TextPosition anchor_id=3 text_offset=0 "
                    "affinity=downstream annotated_text=<C>heck box",
-                   "TextPosition tree_id=0 anchor_id=2 text_offset=0 "
+                   "TextPosition anchor_id=2 text_offset=0 "
                    "affinity=downstream annotated_text=<B>utton",
                    "NullPosition"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -1933,17 +1933,17 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+                  {"TextPosition anchor_id=9 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=6 text_offset=5 "
+                   "TextPosition anchor_id=6 text_offset=5 "
                    "affinity=downstream annotated_text=Line <1>",
-                   "TextPosition tree_id=0 anchor_id=6 text_offset=0 "
+                   "TextPosition anchor_id=6 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1",
-                   "TextPosition tree_id=0 anchor_id=3 text_offset=6 "
+                   "TextPosition anchor_id=3 text_offset=6 "
                    "affinity=downstream annotated_text=Check <b>ox",
-                   "TextPosition tree_id=0 anchor_id=3 text_offset=0 "
+                   "TextPosition anchor_id=3 text_offset=0 "
                    "affinity=downstream annotated_text=<C>heck box",
-                   "TextPosition tree_id=0 anchor_id=2 text_offset=0 "
+                   "TextPosition anchor_id=2 text_offset=0 "
                    "affinity=downstream annotated_text=<B>utton",
                    "NullPosition"}}));
 
@@ -1957,28 +1957,28 @@
                   }),
                   ROOT_ID,
                   28 /* text_offset at end of root. */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=27 "
+                  {"TextPosition anchor_id=1 text_offset=27 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\nLine <2>",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=22 "
+                   "TextPosition anchor_id=1 text_offset=22 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\n<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=20 "
+                   "TextPosition anchor_id=1 text_offset=20 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "<1>\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+                   "TextPosition anchor_id=1 text_offset=15 "
                    "affinity=downstream annotated_text=ButtonCheck box<L>ine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=12 "
+                   "TextPosition anchor_id=1 text_offset=12 "
                    "affinity=downstream annotated_text=ButtonCheck <b>oxLine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=6 "
+                   "TextPosition anchor_id=1 text_offset=6 "
                    "affinity=downstream annotated_text=Button<C>heck boxLine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=0 "
+                   "TextPosition anchor_id=1 text_offset=0 "
                    "affinity=downstream annotated_text=<B>uttonCheck boxLine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=0 "
+                   "TextPosition anchor_id=1 text_offset=0 "
                    "affinity=downstream annotated_text=<B>uttonCheck boxLine "
                    "1\nLine 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -1987,15 +1987,15 @@
                   }),
                   TEXT_FIELD_ID,
                   13 /* text_offset at end of text field */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=12 "
+                  {"TextPosition anchor_id=4 text_offset=12 "
                    "affinity=downstream annotated_text=Line 1\nLine <2>",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=7 "
+                   "TextPosition anchor_id=4 text_offset=7 "
                    "affinity=downstream annotated_text=Line 1\n<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=5 "
+                   "TextPosition anchor_id=4 text_offset=5 "
                    "affinity=downstream annotated_text=Line <1>\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=0 "
+                   "TextPosition anchor_id=4 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=0 "
+                   "TextPosition anchor_id=4 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreatePreviousWordStartPosition(
@@ -2003,9 +2003,9 @@
                   }),
                   STATIC_TEXT1_ID,
                   5 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=5 text_offset=0 "
+                  {"TextPosition anchor_id=5 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1",
-                   "TextPosition tree_id=0 anchor_id=5 text_offset=0 "
+                   "TextPosition anchor_id=5 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreatePreviousWordStartPosition(
@@ -2013,9 +2013,9 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+                  {"TextPosition anchor_id=9 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+                   "TextPosition anchor_id=9 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 2"}}));
 
 INSTANTIATE_TEST_CASE_P(
@@ -2028,10 +2028,10 @@
                   }),
                   ROOT_ID,
                   28 /* text_offset at end of root. */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=27 "
+                  {"TextPosition anchor_id=1 text_offset=27 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\nLine <2>",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=27 "
+                   "TextPosition anchor_id=1 text_offset=27 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\nLine <2>"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2040,9 +2040,9 @@
                   }),
                   TEXT_FIELD_ID,
                   13 /* text_offset at end of text field */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=12 "
+                  {"TextPosition anchor_id=4 text_offset=12 "
                    "affinity=downstream annotated_text=Line 1\nLine <2>",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=12 "
+                   "TextPosition anchor_id=4 text_offset=12 "
                    "affinity=downstream annotated_text=Line 1\nLine <2>"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreatePreviousWordStartPosition(
@@ -2050,7 +2050,7 @@
                   }),
                   STATIC_TEXT1_ID,
                   5 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=5 text_offset=5 "
+                  {"TextPosition anchor_id=5 text_offset=5 "
                    "affinity=downstream annotated_text=Line <1>"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreatePreviousWordStartPosition(
@@ -2058,9 +2058,9 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+                  {"TextPosition anchor_id=9 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+                   "TextPosition anchor_id=9 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 2"}}));
 
 INSTANTIATE_TEST_CASE_P(
@@ -2073,25 +2073,25 @@
                   }),
                   ROOT_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=6 "
+                  {"TextPosition anchor_id=1 text_offset=6 "
                    "affinity=downstream annotated_text=Button<C>heck boxLine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=11 "
+                   "TextPosition anchor_id=1 text_offset=11 "
                    "affinity=downstream annotated_text=ButtonCheck< >boxLine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+                   "TextPosition anchor_id=1 text_offset=15 "
                    "affinity=upstream annotated_text=ButtonCheck box<L>ine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=19 "
+                   "TextPosition anchor_id=1 text_offset=19 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine< "
                    ">1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=21 "
+                   "TextPosition anchor_id=1 text_offset=21 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1<\n>Line 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=26 "
+                   "TextPosition anchor_id=1 text_offset=26 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\nLine< >2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=28 "
+                   "TextPosition anchor_id=1 text_offset=28 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\nLine 2<>",
                    "NullPosition"}},
@@ -2101,13 +2101,13 @@
                   }),
                   TEXT_FIELD_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=4 "
+                  {"TextPosition anchor_id=4 text_offset=4 "
                    "affinity=downstream annotated_text=Line< >1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+                   "TextPosition anchor_id=4 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<\n>Line 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=11 "
+                   "TextPosition anchor_id=4 text_offset=11 "
                    "affinity=downstream annotated_text=Line 1\nLine< >2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=13 "
+                   "TextPosition anchor_id=4 text_offset=13 "
                    "affinity=downstream annotated_text=Line 1\nLine 2<>",
                    "NullPosition"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2116,13 +2116,13 @@
                   }),
                   STATIC_TEXT1_ID,
                   1 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=5 text_offset=4 "
+                  {"TextPosition anchor_id=5 text_offset=4 "
                    "affinity=downstream annotated_text=Line< >1",
-                   "TextPosition tree_id=0 anchor_id=5 text_offset=6 "
+                   "TextPosition anchor_id=5 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<>",
-                   "TextPosition tree_id=0 anchor_id=9 text_offset=4 "
+                   "TextPosition anchor_id=9 text_offset=4 "
                    "affinity=downstream annotated_text=Line< >2",
-                   "TextPosition tree_id=0 anchor_id=9 text_offset=6 "
+                   "TextPosition anchor_id=9 text_offset=6 "
                    "affinity=downstream annotated_text=Line 2<>",
                    "NullPosition"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2131,7 +2131,7 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=6 "
+                  {"TextPosition anchor_id=9 text_offset=6 "
                    "affinity=downstream annotated_text=Line 2<>",
                    "NullPosition"}}));
 
@@ -2145,28 +2145,28 @@
                   }),
                   ROOT_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=6 "
+                  {"TextPosition anchor_id=1 text_offset=6 "
                    "affinity=downstream annotated_text=Button<C>heck boxLine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=11 "
+                   "TextPosition anchor_id=1 text_offset=11 "
                    "affinity=downstream annotated_text=ButtonCheck< >boxLine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+                   "TextPosition anchor_id=1 text_offset=15 "
                    "affinity=upstream annotated_text=ButtonCheck box<L>ine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=19 "
+                   "TextPosition anchor_id=1 text_offset=19 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine< "
                    ">1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=21 "
+                   "TextPosition anchor_id=1 text_offset=21 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1<\n>Line 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=26 "
+                   "TextPosition anchor_id=1 text_offset=26 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\nLine< >2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=28 "
+                   "TextPosition anchor_id=1 text_offset=28 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\nLine 2<>",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=28 "
+                   "TextPosition anchor_id=1 text_offset=28 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\nLine 2<>"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2175,15 +2175,15 @@
                   }),
                   TEXT_FIELD_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=4 "
+                  {"TextPosition anchor_id=4 text_offset=4 "
                    "affinity=downstream annotated_text=Line< >1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+                   "TextPosition anchor_id=4 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<\n>Line 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=11 "
+                   "TextPosition anchor_id=4 text_offset=11 "
                    "affinity=downstream annotated_text=Line 1\nLine< >2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=13 "
+                   "TextPosition anchor_id=4 text_offset=13 "
                    "affinity=downstream annotated_text=Line 1\nLine 2<>",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=13 "
+                   "TextPosition anchor_id=4 text_offset=13 "
                    "affinity=downstream annotated_text=Line 1\nLine 2<>"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreateNextWordEndPosition(
@@ -2191,11 +2191,11 @@
                   }),
                   STATIC_TEXT1_ID,
                   1 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=5 text_offset=4 "
+                  {"TextPosition anchor_id=5 text_offset=4 "
                    "affinity=downstream annotated_text=Line< >1",
-                   "TextPosition tree_id=0 anchor_id=5 text_offset=6 "
+                   "TextPosition anchor_id=5 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<>",
-                   "TextPosition tree_id=0 anchor_id=5 text_offset=6 "
+                   "TextPosition anchor_id=5 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<>"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreateNextWordEndPosition(
@@ -2203,9 +2203,9 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=6 "
+                  {"TextPosition anchor_id=9 text_offset=6 "
                    "affinity=downstream annotated_text=Line 2<>",
-                   "TextPosition tree_id=0 anchor_id=9 text_offset=6 "
+                   "TextPosition anchor_id=9 text_offset=6 "
                    "affinity=downstream annotated_text=Line 2<>"}}));
 
 INSTANTIATE_TEST_CASE_P(
@@ -2218,10 +2218,10 @@
                   }),
                   ROOT_ID,
                   7 /* text_offset after the first character of "Check". */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=11 "
+                  {"TextPosition anchor_id=1 text_offset=11 "
                    "affinity=downstream annotated_text=ButtonCheck< >boxLine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=11 "
+                   "TextPosition anchor_id=1 text_offset=11 "
                    "affinity=downstream annotated_text=ButtonCheck< >boxLine "
                    "1\nLine 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2230,9 +2230,9 @@
                   }),
                   TEXT_FIELD_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=4 "
+                  {"TextPosition anchor_id=4 text_offset=4 "
                    "affinity=downstream annotated_text=Line< >1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=4 "
+                   "TextPosition anchor_id=4 text_offset=4 "
                    "affinity=downstream annotated_text=Line< >1\nLine 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreateNextWordEndPosition(
@@ -2240,9 +2240,9 @@
                   }),
                   STATIC_TEXT1_ID,
                   1 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=5 text_offset=4 "
+                  {"TextPosition anchor_id=5 text_offset=4 "
                    "affinity=downstream annotated_text=Line< >1",
-                   "TextPosition tree_id=0 anchor_id=5 text_offset=4 "
+                   "TextPosition anchor_id=5 text_offset=4 "
                    "affinity=downstream annotated_text=Line< >1"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreateNextWordEndPosition(
@@ -2250,7 +2250,7 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=4 "
+                  {"TextPosition anchor_id=9 text_offset=4 "
                    "affinity=downstream annotated_text=Line< >2"}}));
 
 INSTANTIATE_TEST_CASE_P(
@@ -2263,22 +2263,22 @@
                   }),
                   ROOT_ID,
                   28 /* text_offset at end of root. */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=26 "
+                  {"TextPosition anchor_id=1 text_offset=26 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\nLine< >2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=21 "
+                   "TextPosition anchor_id=1 text_offset=21 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1<\n>Line 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=19 "
+                   "TextPosition anchor_id=1 text_offset=19 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine< "
                    ">1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+                   "TextPosition anchor_id=1 text_offset=15 "
                    "affinity=upstream annotated_text=ButtonCheck box<L>ine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=11 "
+                   "TextPosition anchor_id=1 text_offset=11 "
                    "affinity=downstream annotated_text=ButtonCheck< >boxLine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=6 "
+                   "TextPosition anchor_id=1 text_offset=6 "
                    "affinity=downstream annotated_text=Button<C>heck boxLine "
                    "1\nLine 2",
                    "NullPosition"}},
@@ -2288,17 +2288,17 @@
                   }),
                   TEXT_FIELD_ID,
                   13 /* text_offset at end of text field */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=11 "
+                  {"TextPosition anchor_id=4 text_offset=11 "
                    "affinity=downstream annotated_text=Line 1\nLine< >2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+                   "TextPosition anchor_id=4 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<\n>Line 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=4 "
+                   "TextPosition anchor_id=4 text_offset=4 "
                    "affinity=downstream annotated_text=Line< >1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=3 text_offset=9 "
+                   "TextPosition anchor_id=3 text_offset=9 "
                    "affinity=downstream annotated_text=Check box<>",
-                   "TextPosition tree_id=0 anchor_id=3 text_offset=5 "
+                   "TextPosition anchor_id=3 text_offset=5 "
                    "affinity=downstream annotated_text=Check< >box",
-                   "TextPosition tree_id=0 anchor_id=2 text_offset=6 "
+                   "TextPosition anchor_id=2 text_offset=6 "
                    "affinity=downstream annotated_text=Button<>",
                    "NullPosition"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2307,13 +2307,13 @@
                   }),
                   STATIC_TEXT1_ID,
                   5 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=5 text_offset=4 "
+                  {"TextPosition anchor_id=5 text_offset=4 "
                    "affinity=downstream annotated_text=Line< >1",
-                   "TextPosition tree_id=0 anchor_id=3 text_offset=9 "
+                   "TextPosition anchor_id=3 text_offset=9 "
                    "affinity=downstream annotated_text=Check box<>",
-                   "TextPosition tree_id=0 anchor_id=3 text_offset=5 "
+                   "TextPosition anchor_id=3 text_offset=5 "
                    "affinity=downstream annotated_text=Check< >box",
-                   "TextPosition tree_id=0 anchor_id=2 text_offset=6 "
+                   "TextPosition anchor_id=2 text_offset=6 "
                    "affinity=downstream annotated_text=Button<>",
                    "NullPosition"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2322,15 +2322,15 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=6 text_offset=6 "
+                  {"TextPosition anchor_id=6 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<>",
-                   "TextPosition tree_id=0 anchor_id=6 text_offset=4 "
+                   "TextPosition anchor_id=6 text_offset=4 "
                    "affinity=downstream annotated_text=Line< >1",
-                   "TextPosition tree_id=0 anchor_id=3 text_offset=9 "
+                   "TextPosition anchor_id=3 text_offset=9 "
                    "affinity=downstream annotated_text=Check box<>",
-                   "TextPosition tree_id=0 anchor_id=3 text_offset=5 "
+                   "TextPosition anchor_id=3 text_offset=5 "
                    "affinity=downstream annotated_text=Check< >box",
-                   "TextPosition tree_id=0 anchor_id=2 text_offset=6 "
+                   "TextPosition anchor_id=2 text_offset=6 "
                    "affinity=downstream annotated_text=Button<>",
                    "NullPosition"}}));
 
@@ -2344,25 +2344,25 @@
                   }),
                   ROOT_ID,
                   28 /* text_offset at end of root. */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=26 "
+                  {"TextPosition anchor_id=1 text_offset=26 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\nLine< >2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=21 "
+                   "TextPosition anchor_id=1 text_offset=21 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1<\n>Line 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=19 "
+                   "TextPosition anchor_id=1 text_offset=19 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine< "
                    ">1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+                   "TextPosition anchor_id=1 text_offset=15 "
                    "affinity=upstream annotated_text=ButtonCheck box<L>ine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=11 "
+                   "TextPosition anchor_id=1 text_offset=11 "
                    "affinity=downstream annotated_text=ButtonCheck< >boxLine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=6 "
+                   "TextPosition anchor_id=1 text_offset=6 "
                    "affinity=downstream annotated_text=Button<C>heck boxLine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=0 "
+                   "TextPosition anchor_id=1 text_offset=0 "
                    "affinity=downstream annotated_text=<B>uttonCheck boxLine "
                    "1\nLine 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2371,13 +2371,13 @@
                   }),
                   TEXT_FIELD_ID,
                   13 /* text_offset at end of text field */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=11 "
+                  {"TextPosition anchor_id=4 text_offset=11 "
                    "affinity=downstream annotated_text=Line 1\nLine< >2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+                   "TextPosition anchor_id=4 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<\n>Line 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=4 "
+                   "TextPosition anchor_id=4 text_offset=4 "
                    "affinity=downstream annotated_text=Line< >1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=0 "
+                   "TextPosition anchor_id=4 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreatePreviousWordEndPosition(
@@ -2385,9 +2385,9 @@
                   }),
                   STATIC_TEXT1_ID,
                   5 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=5 text_offset=4 "
+                  {"TextPosition anchor_id=5 text_offset=4 "
                    "affinity=downstream annotated_text=Line< >1",
-                   "TextPosition tree_id=0 anchor_id=5 text_offset=0 "
+                   "TextPosition anchor_id=5 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreatePreviousWordEndPosition(
@@ -2395,7 +2395,7 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+                  {"TextPosition anchor_id=9 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 2"}}));
 
 INSTANTIATE_TEST_CASE_P(
@@ -2408,7 +2408,7 @@
                   }),
                   ROOT_ID,
                   28 /* text_offset at end of root. */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=28 "
+                  {"TextPosition anchor_id=1 text_offset=28 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\nLine 2<>"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2417,7 +2417,7 @@
                   }),
                   TEXT_FIELD_ID,
                   13 /* text_offset at end of text field */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=13 "
+                  {"TextPosition anchor_id=4 text_offset=13 "
                    "affinity=downstream annotated_text=Line 1\nLine 2<>"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreatePreviousWordEndPosition(
@@ -2425,9 +2425,9 @@
                   }),
                   STATIC_TEXT1_ID,
                   5 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=5 text_offset=4 "
+                  {"TextPosition anchor_id=5 text_offset=4 "
                    "affinity=downstream annotated_text=Line< >1",
-                   "TextPosition tree_id=0 anchor_id=5 text_offset=4 "
+                   "TextPosition anchor_id=5 text_offset=4 "
                    "affinity=downstream annotated_text=Line< >1"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreatePreviousWordEndPosition(
@@ -2435,7 +2435,7 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=4 "
+                  {"TextPosition anchor_id=9 text_offset=4 "
                    "affinity=downstream annotated_text=Line< >2"}}));
 
 INSTANTIATE_TEST_CASE_P(
@@ -2448,10 +2448,10 @@
                   }),
                   ROOT_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+                  {"TextPosition anchor_id=1 text_offset=15 "
                    "affinity=downstream annotated_text=ButtonCheck box<L>ine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=22 "
+                   "TextPosition anchor_id=1 text_offset=22 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\n<L>ine 2",
                    "NullPosition"}},
@@ -2461,7 +2461,7 @@
                   }),
                   TEXT_FIELD_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=7 "
+                  {"TextPosition anchor_id=4 text_offset=7 "
                    "affinity=downstream annotated_text=Line 1\n<L>ine 2",
                    "NullPosition"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2470,7 +2470,7 @@
                   }),
                   STATIC_TEXT1_ID,
                   1 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+                  {"TextPosition anchor_id=9 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 2",
                    "NullPosition"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2491,13 +2491,13 @@
                   }),
                   ROOT_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+                  {"TextPosition anchor_id=1 text_offset=15 "
                    "affinity=downstream annotated_text=ButtonCheck box<L>ine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=22 "
+                   "TextPosition anchor_id=1 text_offset=22 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\n<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=28 "
+                   "TextPosition anchor_id=1 text_offset=28 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\nLine 2<>"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2506,9 +2506,9 @@
                   }),
                   TEXT_FIELD_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=7 "
+                  {"TextPosition anchor_id=4 text_offset=7 "
                    "affinity=downstream annotated_text=Line 1\n<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=13 "
+                   "TextPosition anchor_id=4 text_offset=13 "
                    "affinity=downstream annotated_text=Line 1\nLine 2<>"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreateNextLineStartPosition(
@@ -2516,7 +2516,7 @@
                   }),
                   STATIC_TEXT1_ID,
                   1 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=5 text_offset=6 "
+                  {"TextPosition anchor_id=5 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<>"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreateNextLineStartPosition(
@@ -2524,7 +2524,7 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=6 "
+                  {"TextPosition anchor_id=9 text_offset=6 "
                    "affinity=downstream annotated_text=Line 2<>"}}));
 
 INSTANTIATE_TEST_CASE_P(
@@ -2537,7 +2537,7 @@
                   }),
                   ROOT_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=0 "
+                  {"TextPosition anchor_id=1 text_offset=0 "
                    "affinity=downstream annotated_text=<B>uttonCheck boxLine "
                    "1\nLine 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2546,7 +2546,7 @@
                   }),
                   TEXT_FIELD_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=0 "
+                  {"TextPosition anchor_id=4 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreateNextLineStartPosition(
@@ -2554,9 +2554,9 @@
                   }),
                   STATIC_TEXT1_ID,
                   1 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+                  {"TextPosition anchor_id=9 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+                   "TextPosition anchor_id=9 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreateNextLineStartPosition(
@@ -2576,13 +2576,13 @@
                   }),
                   ROOT_ID,
                   28 /* text_offset at the end of root. */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=22 "
+                  {"TextPosition anchor_id=1 text_offset=22 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\n<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+                   "TextPosition anchor_id=1 text_offset=15 "
                    "affinity=downstream annotated_text=ButtonCheck box<L>ine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=0 "
+                   "TextPosition anchor_id=1 text_offset=0 "
                    "affinity=downstream annotated_text=<B>uttonCheck boxLine "
                    "1\nLine 2",
                    "NullPosition"}},
@@ -2592,11 +2592,11 @@
                   }),
                   TEXT_FIELD_ID,
                   13 /* text_offset at end of text field */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=7 "
+                  {"TextPosition anchor_id=4 text_offset=7 "
                    "affinity=downstream annotated_text=Line 1\n<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=0 "
+                   "TextPosition anchor_id=4 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=2 text_offset=0 "
+                   "TextPosition anchor_id=2 text_offset=0 "
                    "affinity=downstream annotated_text=<B>utton",
                    "NullPosition"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2605,9 +2605,9 @@
                   }),
                   STATIC_TEXT1_ID,
                   5 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=5 text_offset=0 "
+                  {"TextPosition anchor_id=5 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1",
-                   "TextPosition tree_id=0 anchor_id=2 text_offset=0 "
+                   "TextPosition anchor_id=2 text_offset=0 "
                    "affinity=downstream annotated_text=<B>utton",
                    "NullPosition"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2616,11 +2616,11 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+                  {"TextPosition anchor_id=9 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=6 text_offset=0 "
+                   "TextPosition anchor_id=6 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1",
-                   "TextPosition tree_id=0 anchor_id=2 text_offset=0 "
+                   "TextPosition anchor_id=2 text_offset=0 "
                    "affinity=downstream annotated_text=<B>utton",
                    "NullPosition"}}));
 
@@ -2634,16 +2634,16 @@
                   }),
                   ROOT_ID,
                   28 /* text_offset at the end of root. */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=22 "
+                  {"TextPosition anchor_id=1 text_offset=22 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\n<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+                   "TextPosition anchor_id=1 text_offset=15 "
                    "affinity=downstream annotated_text=ButtonCheck box<L>ine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=0 "
+                   "TextPosition anchor_id=1 text_offset=0 "
                    "affinity=downstream annotated_text=<B>uttonCheck boxLine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=0 "
+                   "TextPosition anchor_id=1 text_offset=0 "
                    "affinity=downstream annotated_text=<B>uttonCheck boxLine "
                    "1\nLine 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2652,11 +2652,11 @@
                   }),
                   TEXT_FIELD_ID,
                   13 /* text_offset at end of text field */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=7 "
+                  {"TextPosition anchor_id=4 text_offset=7 "
                    "affinity=downstream annotated_text=Line 1\n<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=0 "
+                   "TextPosition anchor_id=4 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=0 "
+                   "TextPosition anchor_id=4 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreatePreviousLineStartPosition(
@@ -2664,9 +2664,9 @@
                   }),
                   STATIC_TEXT1_ID,
                   5 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=5 text_offset=0 "
+                  {"TextPosition anchor_id=5 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1",
-                   "TextPosition tree_id=0 anchor_id=5 text_offset=0 "
+                   "TextPosition anchor_id=5 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreatePreviousLineStartPosition(
@@ -2674,9 +2674,9 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+                  {"TextPosition anchor_id=9 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+                   "TextPosition anchor_id=9 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 2"}}));
 
 INSTANTIATE_TEST_CASE_P(
@@ -2689,10 +2689,10 @@
                   }),
                   ROOT_ID,
                   28 /* text_offset at the end of root. */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=22 "
+                  {"TextPosition anchor_id=1 text_offset=22 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\n<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=22 "
+                   "TextPosition anchor_id=1 text_offset=22 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\n<L>ine 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2701,9 +2701,9 @@
                   }),
                   TEXT_FIELD_ID,
                   13 /* text_offset at end of text field */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=7 "
+                  {"TextPosition anchor_id=4 text_offset=7 "
                    "affinity=downstream annotated_text=Line 1\n<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=7 "
+                   "TextPosition anchor_id=4 text_offset=7 "
                    "affinity=downstream annotated_text=Line 1\n<L>ine 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreatePreviousLineStartPosition(
@@ -2711,9 +2711,9 @@
                   }),
                   STATIC_TEXT1_ID,
                   5 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=5 text_offset=0 "
+                  {"TextPosition anchor_id=5 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1",
-                   "TextPosition tree_id=0 anchor_id=5 text_offset=0 "
+                   "TextPosition anchor_id=5 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreatePreviousLineStartPosition(
@@ -2721,9 +2721,9 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+                  {"TextPosition anchor_id=9 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 2",
-                   "TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+                   "TextPosition anchor_id=9 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 2"}}));
 
 INSTANTIATE_TEST_CASE_P(
@@ -2736,13 +2736,13 @@
                   }),
                   ROOT_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+                  {"TextPosition anchor_id=1 text_offset=15 "
                    "affinity=upstream annotated_text=ButtonCheck box<L>ine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=21 "
+                   "TextPosition anchor_id=1 text_offset=21 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine 1"
                    "<\n>Line 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=28 "
+                   "TextPosition anchor_id=1 text_offset=28 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\nLine 2<>",
                    "NullPosition"}},
@@ -2752,9 +2752,9 @@
                   }),
                   TEXT_FIELD_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+                  {"TextPosition anchor_id=4 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<\n>Line 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=13 "
+                   "TextPosition anchor_id=4 text_offset=13 "
                    "affinity=downstream annotated_text=Line 1\nLine 2<>",
                    "NullPosition"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2763,9 +2763,9 @@
                   }),
                   STATIC_TEXT1_ID,
                   1 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=5 text_offset=6 "
+                  {"TextPosition anchor_id=5 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<>",
-                   "TextPosition tree_id=0 anchor_id=9 text_offset=6 "
+                   "TextPosition anchor_id=9 text_offset=6 "
                    "affinity=downstream annotated_text=Line 2<>",
                    "NullPosition"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2774,7 +2774,7 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=6 "
+                  {"TextPosition anchor_id=9 text_offset=6 "
                    "affinity=downstream annotated_text=Line 2<>",
                    "NullPosition"}}));
 
@@ -2788,16 +2788,16 @@
                   }),
                   ROOT_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+                  {"TextPosition anchor_id=1 text_offset=15 "
                    "affinity=upstream annotated_text=ButtonCheck box<L>ine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=21 "
+                   "TextPosition anchor_id=1 text_offset=21 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine 1"
                    "<\n>Line 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=28 "
+                   "TextPosition anchor_id=1 text_offset=28 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\nLine 2<>",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=28 "
+                   "TextPosition anchor_id=1 text_offset=28 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1\nLine 2<>"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2806,11 +2806,11 @@
                   }),
                   TEXT_FIELD_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+                  {"TextPosition anchor_id=4 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<\n>Line 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=13 "
+                   "TextPosition anchor_id=4 text_offset=13 "
                    "affinity=downstream annotated_text=Line 1\nLine 2<>",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=13 "
+                   "TextPosition anchor_id=4 text_offset=13 "
                    "affinity=downstream annotated_text=Line 1\nLine 2<>"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreateNextLineEndPosition(
@@ -2818,9 +2818,9 @@
                   }),
                   STATIC_TEXT1_ID,
                   1 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=5 text_offset=6 "
+                  {"TextPosition anchor_id=5 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<>",
-                   "TextPosition tree_id=0 anchor_id=5 text_offset=6 "
+                   "TextPosition anchor_id=5 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<>"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreateNextLineEndPosition(
@@ -2828,9 +2828,9 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=6 "
+                  {"TextPosition anchor_id=9 text_offset=6 "
                    "affinity=downstream annotated_text=Line 2<>",
-                   "TextPosition tree_id=0 anchor_id=9 text_offset=6 "
+                   "TextPosition anchor_id=9 text_offset=6 "
                    "affinity=downstream annotated_text=Line 2<>"}}));
 
 INSTANTIATE_TEST_CASE_P(
@@ -2843,10 +2843,10 @@
                   }),
                   ROOT_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+                  {"TextPosition anchor_id=1 text_offset=15 "
                    "affinity=upstream annotated_text=ButtonCheck box<L>ine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+                   "TextPosition anchor_id=1 text_offset=15 "
                    "affinity=upstream annotated_text=ButtonCheck box<L>ine "
                    "1\nLine 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2855,9 +2855,9 @@
                   }),
                   TEXT_FIELD_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+                  {"TextPosition anchor_id=4 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<\n>Line 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+                   "TextPosition anchor_id=4 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<\n>Line 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreateNextLineEndPosition(
@@ -2865,9 +2865,9 @@
                   }),
                   STATIC_TEXT1_ID,
                   1 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=5 text_offset=6 "
+                  {"TextPosition anchor_id=5 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<>",
-                   "TextPosition tree_id=0 anchor_id=5 text_offset=6 "
+                   "TextPosition anchor_id=5 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<>"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreateNextLineEndPosition(
@@ -2875,9 +2875,9 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=6 "
+                  {"TextPosition anchor_id=9 text_offset=6 "
                    "affinity=downstream annotated_text=Line 2<>",
-                   "TextPosition tree_id=0 anchor_id=9 text_offset=6 "
+                   "TextPosition anchor_id=9 text_offset=6 "
                    "affinity=downstream annotated_text=Line 2<>"}}));
 
 INSTANTIATE_TEST_CASE_P(
@@ -2894,10 +2894,10 @@
                   }),
                   ROOT_ID,
                   28 /* text_offset at end of root. */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=21 "
+                  {"TextPosition anchor_id=1 text_offset=21 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1<\n>Line 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=21 "
+                   "TextPosition anchor_id=1 text_offset=21 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1<\n>Line 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2906,9 +2906,9 @@
                   }),
                   TEXT_FIELD_ID,
                   13 /* text_offset at end of text field */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+                  {"TextPosition anchor_id=4 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<\n>Line 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+                   "TextPosition anchor_id=4 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<\n>Line 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreatePreviousLineEndPosition(
@@ -2916,7 +2916,7 @@
                   }),
                   ROOT_ID,
                   20 /* text_offset on the last character of "line 1". */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+                  {"TextPosition anchor_id=1 text_offset=15 "
                    "affinity=upstream annotated_text=ButtonCheck box<L>ine "
                    "1\nLine 2",
                    "NullPosition"}},
@@ -2926,7 +2926,7 @@
                   }),
                   TEXT_FIELD_ID,
                   5 /* text_offset on the last character of "Line 1". */,
-                  {"TextPosition tree_id=0 anchor_id=3 text_offset=9 "
+                  {"TextPosition anchor_id=3 text_offset=9 "
                    "affinity=downstream annotated_text=Check box<>",
                    "NullPosition"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2935,11 +2935,11 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=7 text_offset=0 "
+                  {"TextPosition anchor_id=7 text_offset=0 "
                    "affinity=downstream annotated_text=<\n>",
-                   "TextPosition tree_id=0 anchor_id=6 text_offset=6 "
+                   "TextPosition anchor_id=6 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<>",
-                   "TextPosition tree_id=0 anchor_id=3 text_offset=9 "
+                   "TextPosition anchor_id=3 text_offset=9 "
                    "affinity=downstream annotated_text=Check box<>",
                    "NullPosition"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2948,11 +2948,11 @@
                   }),
                   INLINE_BOX2_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=7 text_offset=0 "
+                  {"TextPosition anchor_id=7 text_offset=0 "
                    "affinity=downstream annotated_text=<\n>",
-                   "TextPosition tree_id=0 anchor_id=6 text_offset=6 "
+                   "TextPosition anchor_id=6 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<>",
-                   "TextPosition tree_id=0 anchor_id=3 text_offset=9 "
+                   "TextPosition anchor_id=3 text_offset=9 "
                    "affinity=downstream annotated_text=Check box<>",
                    "NullPosition"}}));
 
@@ -2970,10 +2970,10 @@
                   }),
                   ROOT_ID,
                   28 /* text_offset at end of root. */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=21 "
+                  {"TextPosition anchor_id=1 text_offset=21 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1<\n>Line 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=21 "
+                   "TextPosition anchor_id=1 text_offset=21 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1<\n>Line 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -2982,9 +2982,9 @@
                   }),
                   TEXT_FIELD_ID,
                   13 /* text_offset at end of text field */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+                  {"TextPosition anchor_id=4 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<\n>Line 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+                   "TextPosition anchor_id=4 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<\n>Line 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreatePreviousLineEndPosition(
@@ -2992,10 +2992,10 @@
                   }),
                   ROOT_ID,
                   20 /* text_offset on the last character of "line 1". */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+                  {"TextPosition anchor_id=1 text_offset=15 "
                    "affinity=upstream annotated_text=ButtonCheck box<L>ine "
                    "1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=0 "
+                   "TextPosition anchor_id=1 text_offset=0 "
                    "affinity=downstream annotated_text=<B>uttonCheck boxLine "
                    "1\nLine 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -3004,9 +3004,9 @@
                   }),
                   TEXT_FIELD_ID,
                   5 /* text_offset on the last character of "Line 1". */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=0 "
+                  {"TextPosition anchor_id=4 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1\nLine 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=0 "
+                   "TextPosition anchor_id=4 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreatePreviousLineEndPosition(
@@ -3014,7 +3014,7 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+                  {"TextPosition anchor_id=9 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreatePreviousLineEndPosition(
@@ -3022,7 +3022,7 @@
                   }),
                   INLINE_BOX2_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+                  {"TextPosition anchor_id=9 text_offset=0 "
                    "affinity=downstream annotated_text=<L>ine 2"}}));
 
 INSTANTIATE_TEST_CASE_P(
@@ -3035,10 +3035,10 @@
                   }),
                   ROOT_ID,
                   27 /* text_offset one before the end of root. */,
-                  {"TextPosition tree_id=0 anchor_id=1 text_offset=21 "
+                  {"TextPosition anchor_id=1 text_offset=21 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1<\n>Line 2",
-                   "TextPosition tree_id=0 anchor_id=1 text_offset=21 "
+                   "TextPosition anchor_id=1 text_offset=21 "
                    "affinity=downstream annotated_text=ButtonCheck boxLine "
                    "1<\n>Line 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
@@ -3047,9 +3047,9 @@
                   }),
                   TEXT_FIELD_ID,
                   12 /* text_offset one before the end of text field */,
-                  {"TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+                  {"TextPosition anchor_id=4 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<\n>Line 2",
-                   "TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+                   "TextPosition anchor_id=4 text_offset=6 "
                    "affinity=downstream annotated_text=Line 1<\n>Line 2"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreatePreviousLineEndPosition(
@@ -3057,9 +3057,9 @@
                   }),
                   INLINE_BOX2_ID,
                   4 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=7 text_offset=0 "
+                  {"TextPosition anchor_id=7 text_offset=0 "
                    "affinity=downstream annotated_text=<\n>",
-                   "TextPosition tree_id=0 anchor_id=7 text_offset=0 "
+                   "TextPosition anchor_id=7 text_offset=0 "
                    "affinity=downstream annotated_text=<\n>"}},
         TestParam{base::BindRepeating([](const TestPositionType& position) {
                     return position->CreatePreviousLineEndPosition(
@@ -3067,9 +3067,9 @@
                   }),
                   INLINE_BOX2_ID,
                   0 /* text_offset */,
-                  {"TextPosition tree_id=0 anchor_id=7 text_offset=0 "
+                  {"TextPosition anchor_id=7 text_offset=0 "
                    "affinity=downstream annotated_text=<\n>",
-                   "TextPosition tree_id=0 anchor_id=7 text_offset=0 "
+                   "TextPosition anchor_id=7 text_offset=0 "
                    "affinity=downstream annotated_text=<\n>"}}));
 
 //
diff --git a/ui/accessibility/ax_position.h b/ui/accessibility/ax_position.h
index 0f3e6296..4bd039c 100644
--- a/ui/accessibility/ax_position.h
+++ b/ui/accessibility/ax_position.h
@@ -152,8 +152,7 @@
         } else {
           str_text_offset = base::IntToString(text_offset_);
         }
-        str = "TextPosition tree_id=" + tree_id_.ToString() +
-              " anchor_id=" + base::IntToString(anchor_id_) +
+        str = "TextPosition anchor_id=" + base::IntToString(anchor_id_) +
               " text_offset=" + str_text_offset + " affinity=" +
               ui::ToString(static_cast<ax::mojom::TextAffinity>(affinity_));
         break;
diff --git a/ui/accessibility/ax_table_info.cc b/ui/accessibility/ax_table_info.cc
index b3f79cc..1986ac75 100644
--- a/ui/accessibility/ax_table_info.cc
+++ b/ui/accessibility/ax_table_info.cc
@@ -7,6 +7,7 @@
 #include "ui/accessibility/ax_node.h"
 #include "ui/accessibility/ax_role_properties.h"
 #include "ui/accessibility/ax_tree.h"
+#include "ui/accessibility/ax_tree_observer.h"
 #include "ui/gfx/geometry/rect_f.h"
 
 using ax::mojom::IntAttribute;
@@ -348,8 +349,8 @@
   data.id = id;
   data.role = ax::mojom::Role::kColumn;
   node->SetData(data);
-  if (tree_->delegate())
-    tree_->delegate()->OnNodeCreated(tree_, node);
+  for (AXTreeObserver& observer : tree_->observers())
+    observer.OnNodeCreated(tree_, node);
   return node;
 }
 
@@ -361,8 +362,8 @@
   data.id = id;
   data.role = ax::mojom::Role::kTableHeaderContainer;
   node->SetData(data);
-  if (tree_->delegate())
-    tree_->delegate()->OnNodeCreated(tree_, node);
+  for (AXTreeObserver& observer : tree_->observers())
+    observer.OnNodeCreated(tree_, node);
 
   return node;
 }
@@ -397,8 +398,8 @@
 
 void AXTableInfo::ClearExtraMacNodes() {
   for (size_t i = 0; i < extra_mac_nodes.size(); i++) {
-    if (tree_->delegate())
-      tree_->delegate()->OnNodeWillBeDeleted(tree_, extra_mac_nodes[i]);
+    for (AXTreeObserver& observer : tree_->observers())
+      observer.OnNodeWillBeDeleted(tree_, extra_mac_nodes[i]);
     delete extra_mac_nodes[i];
   }
 }
diff --git a/ui/accessibility/ax_tree.cc b/ui/accessibility/ax_tree.cc
index 2ef2aff..7bb289d 100644
--- a/ui/accessibility/ax_tree.cc
+++ b/ui/accessibility/ax_tree.cc
@@ -15,6 +15,7 @@
 #include "ui/accessibility/ax_node.h"
 #include "ui/accessibility/ax_role_properties.h"
 #include "ui/accessibility/ax_table_info.h"
+#include "ui/accessibility/ax_tree_observer.h"
 #include "ui/gfx/transform.h"
 
 namespace ui {
@@ -112,7 +113,7 @@
   // This is similar to above, but we store node ids here because this list gets
   // generated before any nodes get created or re-used. Its purpose is to allow
   // us to know what nodes will be updated so we can make more intelligent
-  // decisions about when to notify delegates of removals or reparenting.
+  // decisions about when to notify observers of removals or reparenting.
   std::set<int> changed_node_ids;
 
   // Keeps track of new nodes created during this update.
@@ -125,9 +126,6 @@
   std::set<int> removed_node_ids;
 };
 
-AXTreeDelegate::AXTreeDelegate() = default;
-AXTreeDelegate::~AXTreeDelegate() = default;
-
 AXTree::AXTree() {
   AXNodeData root;
   root.id = -1;
@@ -150,8 +148,16 @@
   table_info_map_.clear();
 }
 
-void AXTree::SetDelegate(AXTreeDelegate* delegate) {
-  delegate_ = delegate;
+void AXTree::AddObserver(AXTreeObserver* observer) {
+  observers_.AddObserver(observer);
+}
+
+bool AXTree::HasObserver(AXTreeObserver* observer) {
+  return observers_.HasObserver(observer);
+}
+
+void AXTree::RemoveObserver(const AXTreeObserver* observer) {
+  observers_.RemoveObserver(observer);
 }
 
 AXNode* AXTree::GetFromId(int32_t id) const {
@@ -165,8 +171,8 @@
 
   AXTreeData old_data = data_;
   data_ = new_data;
-  if (delegate_)
-    delegate_->OnTreeDataChanged(this, old_data, new_data);
+  for (AXTreeObserver& observer : observers_)
+    observer.OnTreeDataChanged(this, old_data, new_data);
 }
 
 gfx::RectF AXTree::RelativeToTreeBounds(const AXNode* node,
@@ -425,48 +431,46 @@
     }
   }
 
-  if (delegate_) {
-    std::set<AXNode*>& new_nodes = update_state.new_nodes;
-    std::vector<AXTreeDelegate::Change> changes;
-    changes.reserve(update.nodes.size());
-    for (size_t i = 0; i < update.nodes.size(); ++i) {
-      AXNode* node = GetFromId(update.nodes[i].id);
-      if (!node)
-        continue;
+  std::set<AXNode*>& new_nodes = update_state.new_nodes;
+  std::vector<AXTreeObserver::Change> changes;
+  changes.reserve(update.nodes.size());
+  for (size_t i = 0; i < update.nodes.size(); ++i) {
+    AXNode* node = GetFromId(update.nodes[i].id);
+    if (!node)
+      continue;
 
-      bool is_new_node = new_nodes.find(node) != new_nodes.end();
-      bool is_reparented_node =
-          is_new_node && update_state.HasRemovedNode(node);
+    bool is_new_node = new_nodes.find(node) != new_nodes.end();
+    bool is_reparented_node = is_new_node && update_state.HasRemovedNode(node);
 
-      AXTreeDelegate::ChangeType change = AXTreeDelegate::NODE_CHANGED;
-      if (is_new_node) {
-        if (is_reparented_node) {
-          // A reparented subtree is any new node whose parent either doesn't
-          // exist, or whose parent is not new.
-          // Note that we also need to check for the special case when we update
-          // the root without replacing it.
-          bool is_subtree = !node->parent() ||
-                            new_nodes.find(node->parent()) == new_nodes.end() ||
-                            (node->parent() == root_ && root_updated);
-          change = is_subtree ? AXTreeDelegate::SUBTREE_REPARENTED
-                              : AXTreeDelegate::NODE_REPARENTED;
-        } else {
-          // A new subtree is any new node whose parent is either not new, or
-          // whose parent happens to be new only because it has been reparented.
-          // Note that we also need to check for the special case when we update
-          // the root without replacing it.
-          bool is_subtree = !node->parent() ||
-                            new_nodes.find(node->parent()) == new_nodes.end() ||
-                            update_state.HasRemovedNode(node->parent()) ||
-                            (node->parent() == root_ && root_updated);
-          change = is_subtree ? AXTreeDelegate::SUBTREE_CREATED
-                              : AXTreeDelegate::NODE_CREATED;
-        }
+    AXTreeObserver::ChangeType change = AXTreeObserver::NODE_CHANGED;
+    if (is_new_node) {
+      if (is_reparented_node) {
+        // A reparented subtree is any new node whose parent either doesn't
+        // exist, or whose parent is not new.
+        // Note that we also need to check for the special case when we update
+        // the root without replacing it.
+        bool is_subtree = !node->parent() ||
+                          new_nodes.find(node->parent()) == new_nodes.end() ||
+                          (node->parent() == root_ && root_updated);
+        change = is_subtree ? AXTreeObserver::SUBTREE_REPARENTED
+                            : AXTreeObserver::NODE_REPARENTED;
+      } else {
+        // A new subtree is any new node whose parent is either not new, or
+        // whose parent happens to be new only because it has been reparented.
+        // Note that we also need to check for the special case when we update
+        // the root without replacing it.
+        bool is_subtree = !node->parent() ||
+                          new_nodes.find(node->parent()) == new_nodes.end() ||
+                          update_state.HasRemovedNode(node->parent()) ||
+                          (node->parent() == root_ && root_updated);
+        change = is_subtree ? AXTreeObserver::SUBTREE_CREATED
+                            : AXTreeObserver::NODE_CREATED;
       }
-      changes.push_back(AXTreeDelegate::Change(node, change));
     }
-    delegate_->OnAtomicUpdateFinished(
-        this, root_->id() != old_root_id, changes);
+    changes.push_back(AXTreeObserver::Change(node, change));
+  }
+  for (AXTreeObserver& observer : observers_) {
+    observer.OnAtomicUpdateFinished(this, root_->id() != old_root_id, changes);
   }
 
   // Clear list_info_map_
@@ -499,8 +503,8 @@
         table_info_map_.erase(table_node->id());
       }
       // See note about const_cast, above.
-      if (delegate_)
-        delegate_->OnNodeChanged(tree, table_node);
+      for (AXTreeObserver& observer : observers_)
+        observer.OnNodeChanged(tree, table_node);
     }
     return table_info;
   }
@@ -510,8 +514,8 @@
     return nullptr;
 
   table_info_map_[table_node->id()] = table_info;
-  if (delegate_)
-    delegate_->OnNodeChanged(tree, table_node);
+  for (AXTreeObserver& observer : observers_)
+    observer.OnNodeChanged(tree, table_node);
 
   return table_info;
 }
@@ -526,12 +530,12 @@
                            AXTreeUpdateState* update_state) {
   AXNode* new_node = new AXNode(this, parent, id, index_in_parent);
   id_map_[new_node->id()] = new_node;
-  if (delegate_) {
+  for (AXTreeObserver& observer : observers_) {
     if (update_state->HasChangedNode(new_node) &&
         !update_state->HasRemovedNode(new_node))
-      delegate_->OnNodeCreated(this, new_node);
+      observer.OnNodeCreated(this, new_node);
     else
-      delegate_->OnNodeReparented(this, new_node);
+      observer.OnNodeReparented(this, new_node);
   }
   return new_node;
 }
@@ -571,8 +575,8 @@
     node->SetData(src);
   }
 
-  if (delegate_)
-    delegate_->OnNodeChanged(this, node);
+  for (AXTreeObserver& observer : observers_)
+    observer.OnNodeChanged(this, node);
 
   // First, delete nodes that used to be children of this node but aren't
   // anymore.
@@ -618,29 +622,33 @@
 }
 
 void AXTree::CallNodeChangeCallbacks(AXNode* node, const AXNodeData& new_data) {
-  if (!delegate_)
-    return;
-
   const AXNodeData& old_data = node->data();
-  delegate_->OnNodeDataWillChange(this, old_data, new_data);
+  for (AXTreeObserver& observer : observers_)
+    observer.OnNodeDataWillChange(this, old_data, new_data);
 
-  if (old_data.role != new_data.role)
-    delegate_->OnRoleChanged(this, node, old_data.role, new_data.role);
+  if (old_data.role != new_data.role) {
+    for (AXTreeObserver& observer : observers_)
+      observer.OnRoleChanged(this, node, old_data.role, new_data.role);
+  }
 
   if (old_data.state != new_data.state) {
     for (int32_t i = static_cast<int32_t>(ax::mojom::State::kNone) + 1;
          i <= static_cast<int32_t>(ax::mojom::State::kMaxValue); ++i) {
       ax::mojom::State state = static_cast<ax::mojom::State>(i);
-      if (old_data.HasState(state) != new_data.HasState(state))
-        delegate_->OnStateChanged(this, node, state, new_data.HasState(state));
+      if (old_data.HasState(state) != new_data.HasState(state)) {
+        for (AXTreeObserver& observer : observers_)
+          observer.OnStateChanged(this, node, state, new_data.HasState(state));
+      }
     }
   }
 
   auto string_callback = [this, node](ax::mojom::StringAttribute attr,
                                       const std::string& old_string,
                                       const std::string& new_string) {
-    delegate_->OnStringAttributeChanged(this, node, attr, old_string,
+    for (AXTreeObserver& observer : observers_) {
+      observer.OnStringAttributeChanged(this, node, attr, old_string,
                                         new_string);
+    }
   };
   CallIfAttributeValuesChanged(old_data.string_attributes,
                                new_data.string_attributes, std::string(),
@@ -649,7 +657,8 @@
   auto bool_callback = [this, node](ax::mojom::BoolAttribute attr,
                                     const bool& old_bool,
                                     const bool& new_bool) {
-    delegate_->OnBoolAttributeChanged(this, node, attr, new_bool);
+    for (AXTreeObserver& observer : observers_)
+      observer.OnBoolAttributeChanged(this, node, attr, new_bool);
   };
   CallIfAttributeValuesChanged(old_data.bool_attributes,
                                new_data.bool_attributes, false, bool_callback);
@@ -657,14 +666,16 @@
   auto float_callback = [this, node](ax::mojom::FloatAttribute attr,
                                      const float& old_float,
                                      const float& new_float) {
-    delegate_->OnFloatAttributeChanged(this, node, attr, old_float, new_float);
+    for (AXTreeObserver& observer : observers_)
+      observer.OnFloatAttributeChanged(this, node, attr, old_float, new_float);
   };
   CallIfAttributeValuesChanged(old_data.float_attributes,
                                new_data.float_attributes, 0.0f, float_callback);
 
   auto int_callback = [this, node](ax::mojom::IntAttribute attr,
                                    const int& old_int, const int& new_int) {
-    delegate_->OnIntAttributeChanged(this, node, attr, old_int, new_int);
+    for (AXTreeObserver& observer : observers_)
+      observer.OnIntAttributeChanged(this, node, attr, old_int, new_int);
   };
   CallIfAttributeValuesChanged(old_data.int_attributes, new_data.int_attributes,
                                0, int_callback);
@@ -673,7 +684,8 @@
                               ax::mojom::IntListAttribute attr,
                               const std::vector<int32_t>& old_intlist,
                               const std::vector<int32_t>& new_intlist) {
-    delegate_->OnIntListAttributeChanged(this, node, attr, old_intlist,
+    for (AXTreeObserver& observer : observers_)
+      observer.OnIntListAttributeChanged(this, node, attr, old_intlist,
                                          new_intlist);
   };
   CallIfAttributeValuesChanged(old_data.intlist_attributes,
@@ -684,7 +696,8 @@
       [this, node](ax::mojom::StringListAttribute attr,
                    const std::vector<std::string>& old_stringlist,
                    const std::vector<std::string>& new_stringlist) {
-        delegate_->OnStringListAttributeChanged(this, node, attr,
+        for (AXTreeObserver& observer : observers_)
+          observer.OnStringListAttributeChanged(this, node, attr,
                                                 old_stringlist, new_stringlist);
       };
   CallIfAttributeValuesChanged(old_data.stringlist_attributes,
@@ -769,11 +782,11 @@
 void AXTree::DestroySubtree(AXNode* node,
                             AXTreeUpdateState* update_state) {
   DCHECK(update_state);
-  if (delegate_) {
+  for (AXTreeObserver& observer : observers_) {
     if (!update_state->HasChangedNode(node))
-      delegate_->OnSubtreeWillBeDeleted(this, node);
+      observer.OnSubtreeWillBeDeleted(this, node);
     else
-      delegate_->OnSubtreeWillBeReparented(this, node);
+      observer.OnSubtreeWillBeReparented(this, node);
   }
   DestroyNodeAndSubtree(node, update_state);
 }
@@ -792,11 +805,11 @@
     table_info_map_.erase(node->id());
   }
 
-  if (delegate_) {
+  for (AXTreeObserver& observer : observers_) {
     if (!update_state || !update_state->HasChangedNode(node))
-      delegate_->OnNodeWillBeDeleted(this, node);
+      observer.OnNodeWillBeDeleted(this, node);
     else
-      delegate_->OnNodeWillBeReparented(this, node);
+      observer.OnNodeWillBeReparented(this, node);
   }
   id_map_.erase(node->id());
   for (int i = 0; i < node->child_count(); ++i)
diff --git a/ui/accessibility/ax_tree.h b/ui/accessibility/ax_tree.h
index c01aa3cb..c2b0d80 100644
--- a/ui/accessibility/ax_tree.h
+++ b/ui/accessibility/ax_tree.h
@@ -10,6 +10,7 @@
 #include <set>
 
 #include "base/containers/hash_tables.h"
+#include "base/observer_list.h"
 #include "ui/accessibility/ax_export.h"
 #include "ui/accessibility/ax_node.h"
 #include "ui/accessibility/ax_node_data.h"
@@ -20,138 +21,9 @@
 
 class AXTableInfo;
 class AXTree;
+class AXTreeObserver;
 struct AXTreeUpdateState;
 
-// Used when you want to be notified when changes happen to the tree.
-//
-// Some of the notifications are called in the middle of an update operation.
-// Be careful, as the tree may be in an inconsistent state at this time;
-// don't walk the parents and children at this time:
-//   OnNodeWillBeDeleted
-//   OnSubtreeWillBeDeleted
-//   OnNodeWillBeReparented
-//   OnSubtreeWillBeReparented
-//   OnNodeCreated
-//   OnNodeReparented
-//   OnNodeChanged
-//
-// In addition, one additional notification is fired at the end of an
-// atomic update, and it provides a vector of nodes that were added or
-// changed, for final postprocessing:
-//   OnAtomicUpdateFinished
-//
-class AX_EXPORT AXTreeDelegate {
- public:
-  AXTreeDelegate();
-  virtual ~AXTreeDelegate();
-
-  // Called before a node's data gets updated.
-  virtual void OnNodeDataWillChange(AXTree* tree,
-                                    const AXNodeData& old_node_data,
-                                    const AXNodeData& new_node_data) = 0;
-
-  // Individual callbacks for every attribute of AXNodeData that can change.
-  virtual void OnRoleChanged(AXTree* tree,
-                             AXNode* node,
-                             ax::mojom::Role old_role,
-                             ax::mojom::Role new_role) {}
-  virtual void OnStateChanged(AXTree* tree,
-                              AXNode* node,
-                              ax::mojom::State state,
-                              bool new_value) {}
-  virtual void OnStringAttributeChanged(AXTree* tree,
-                                        AXNode* node,
-                                        ax::mojom::StringAttribute attr,
-                                        const std::string& old_value,
-                                        const std::string& new_value) {}
-  virtual void OnIntAttributeChanged(AXTree* tree,
-                                     AXNode* node,
-                                     ax::mojom::IntAttribute attr,
-                                     int32_t old_value,
-                                     int32_t new_value) {}
-  virtual void OnFloatAttributeChanged(AXTree* tree,
-                                       AXNode* node,
-                                       ax::mojom::FloatAttribute attr,
-                                       float old_value,
-                                       float new_value) {}
-  virtual void OnBoolAttributeChanged(AXTree* tree,
-                                      AXNode* node,
-                                      ax::mojom::BoolAttribute attr,
-                                      bool new_value) {}
-  virtual void OnIntListAttributeChanged(
-      AXTree* tree,
-      AXNode* node,
-      ax::mojom::IntListAttribute attr,
-      const std::vector<int32_t>& old_value,
-      const std::vector<int32_t>& new_value) {}
-  virtual void OnStringListAttributeChanged(
-      AXTree* tree,
-      AXNode* node,
-      ax::mojom::StringListAttribute attr,
-      const std::vector<std::string>& old_value,
-      const std::vector<std::string>& new_value) {}
-
-  // Called when tree data changes.
-  virtual void OnTreeDataChanged(AXTree* tree,
-                                 const ui::AXTreeData& old_data,
-                                 const ui::AXTreeData& new_data) = 0;
-  // Called just before a node is deleted. Its id and data will be valid,
-  // but its links to parents and children are invalid. This is called
-  // in the middle of an update, the tree may be in an invalid state!
-  virtual void OnNodeWillBeDeleted(AXTree* tree, AXNode* node) = 0;
-
-  // Same as OnNodeWillBeDeleted, but only called once for an entire subtree.
-  // This is called in the middle of an update, the tree may be in an
-  // invalid state!
-  virtual void OnSubtreeWillBeDeleted(AXTree* tree, AXNode* node) = 0;
-
-  // Called just before a node is deleted for reparenting. See
-  // |OnNodeWillBeDeleted| for additional information.
-  virtual void OnNodeWillBeReparented(AXTree* tree, AXNode* node) = 0;
-
-  // Called just before a subtree is deleted for reparenting. See
-  // |OnSubtreeWillBeDeleted| for additional information.
-  virtual void OnSubtreeWillBeReparented(AXTree* tree, AXNode* node) = 0;
-
-  // Called immediately after a new node is created. The tree may be in
-  // the middle of an update, don't walk the parents and children now.
-  virtual void OnNodeCreated(AXTree* tree, AXNode* node) = 0;
-
-  // Called immediately after a node is reparented. The tree may be in the
-  // middle of an update, don't walk the parents and children now.
-  virtual void OnNodeReparented(AXTree* tree, AXNode* node) = 0;
-
-  // Called when a node changes its data or children. The tree may be in
-  // the middle of an update, don't walk the parents and children now.
-  virtual void OnNodeChanged(AXTree* tree, AXNode* node) = 0;
-
-  enum ChangeType {
-    NODE_CREATED,
-    SUBTREE_CREATED,
-    NODE_CHANGED,
-    NODE_REPARENTED,
-    SUBTREE_REPARENTED
-  };
-
-  struct Change {
-    Change(AXNode* node, ChangeType type) {
-      this->node = node;
-      this->type = type;
-    }
-    AXNode* node;
-    ChangeType type;
-  };
-
-  // Called at the end of the update operation. Every node that was added
-  // or changed will be included in |changes|, along with an enum indicating
-  // the type of change - either (1) a node was created, (2) a node was created
-  // and it's the root of a new subtree, or (3) a node was changed. Finally,
-  // a bool indicates if the root of the tree was changed or not.
-  virtual void OnAtomicUpdateFinished(AXTree* tree,
-                                      bool root_changed,
-                                      const std::vector<Change>& changes) = 0;
-};
-
 // AXTree is a live, managed tree of AXNode objects that can receive
 // updates from another AXTreeSource via AXTreeUpdates, and it can be
 // used as a source for sending updates to another client tree.
@@ -170,8 +42,11 @@
   explicit AXTree(const AXTreeUpdate& initial_state);
   virtual ~AXTree();
 
-  virtual void SetDelegate(AXTreeDelegate* delegate);
-  AXTreeDelegate* delegate() const { return delegate_; }
+  void AddObserver(AXTreeObserver* observer);
+  bool HasObserver(AXTreeObserver* observer);
+  void RemoveObserver(const AXTreeObserver* observer);
+
+  base::ObserverList<AXTreeObserver>& observers() { return observers_; }
 
   AXNode* root() const { return root_; }
 
@@ -327,7 +202,7 @@
                             std::vector<AXNode*>* new_children,
                             AXTreeUpdateState* update_state);
 
-  AXTreeDelegate* delegate_ = nullptr;
+  base::ObserverList<AXTreeObserver> observers_;
   AXNode* root_ = nullptr;
   base::hash_map<int32_t, AXNode*> id_map_;
   std::string error_;
diff --git a/ui/accessibility/ax_tree_fuzzer.cc b/ui/accessibility/ax_tree_fuzzer.cc
index 6f04976..f2ad7271 100644
--- a/ui/accessibility/ax_tree_fuzzer.cc
+++ b/ui/accessibility/ax_tree_fuzzer.cc
@@ -3,27 +3,12 @@
 // found in the LICENSE file.
 
 #include "ui/accessibility/ax_tree.h"
+#include "ui/accessibility/ax_tree_observer.h"
 
-class EmptyAXTreeDelegate : public ui::AXTreeDelegate {
+class EmptyAXTreeObserver : public ui::AXTreeObserver {
  public:
-  EmptyAXTreeDelegate() {}
-
-  void OnNodeDataWillChange(ui::AXTree* tree,
-                            const ui::AXNodeData& old_node_data,
-                            const ui::AXNodeData& new_node_data) override {}
-  void OnTreeDataChanged(ui::AXTree* tree,
-                         const ui::AXTreeData& old_data,
-                         const ui::AXTreeData& new_data) override {}
-  void OnNodeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override {}
-  void OnSubtreeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override {}
-  void OnNodeWillBeReparented(ui::AXTree* tree, ui::AXNode* node) override {}
-  void OnSubtreeWillBeReparented(ui::AXTree* tree, ui::AXNode* node) override {}
-  void OnNodeCreated(ui::AXTree* tree, ui::AXNode* node) override {}
-  void OnNodeReparented(ui::AXTree* tree, ui::AXNode* node) override {}
-  void OnNodeChanged(ui::AXTree* tree, ui::AXNode* node) override {}
-  void OnAtomicUpdateFinished(ui::AXTree* tree,
-                              bool root_changed,
-                              const std::vector<Change>& changes) override {}
+  EmptyAXTreeObserver() {}
+  ~EmptyAXTreeObserver() override{};
 };
 
 // Entry point for LibFuzzer.
@@ -44,10 +29,11 @@
   // Run with --v=1 to aid in debugging a specific crash.
   VLOG(1) << "Input accessibility tree:\n" << initial_state.ToString();
 
-  EmptyAXTreeDelegate delegate;
+  EmptyAXTreeObserver observer;
   ui::AXTree tree;
-  tree.SetDelegate(&delegate);
+  tree.AddObserver(&observer);
   tree.Unserialize(initial_state);
+  tree.RemoveObserver(&observer);
 
   return 0;
 }
diff --git a/ui/accessibility/ax_tree_id.cc b/ui/accessibility/ax_tree_id.cc
index 52ea30f..2469e37 100644
--- a/ui/accessibility/ax_tree_id.cc
+++ b/ui/accessibility/ax_tree_id.cc
@@ -24,8 +24,6 @@
 AXTreeID::AXTreeID(const std::string& string) {
   if (string.empty()) {
     type_ = ax::mojom::AXTreeIDType::kUnknown;
-  } else if (string == "0") {
-    type_ = ax::mojom::AXTreeIDType::kDesktop;
   } else {
     type_ = ax::mojom::AXTreeIDType::kToken;
     base::Value string_value(string);
@@ -49,8 +47,6 @@
   switch (type_) {
     case ax::mojom::AXTreeIDType::kUnknown:
       return "";
-    case ax::mojom::AXTreeIDType::kDesktop:
-      return "0";
     case ax::mojom::AXTreeIDType::kToken:
       return base::CreateUnguessableTokenValue(*token_).GetString();
   }
@@ -93,10 +89,4 @@
   return *ax_tree_id_unknown;
 }
 
-const AXTreeID& DesktopAXTreeID() {
-  static const base::NoDestructor<AXTreeID> desktop_ax_tree_id(
-      ax::mojom::AXTreeIDType::kDesktop);
-  return *desktop_ax_tree_id;
-}
-
 }  // namespace ui
diff --git a/ui/accessibility/ax_tree_id.h b/ui/accessibility/ax_tree_id.h
index 57ccfbb..47490b3 100644
--- a/ui/accessibility/ax_tree_id.h
+++ b/ui/accessibility/ax_tree_id.h
@@ -70,9 +70,6 @@
 // The value to use when an AXTreeID is unknown.
 AX_EXPORT extern const AXTreeID& AXTreeIDUnknown();
 
-// The AXTreeID of the desktop.
-AX_EXPORT extern const AXTreeID& DesktopAXTreeID();
-
 }  // namespace ui
 
 #endif  // UI_ACCESSIBILITY_AX_TREE_ID_H_
diff --git a/ui/accessibility/ax_tree_id_registry.cc b/ui/accessibility/ax_tree_id_registry.cc
index 78c12ca..005b9ba8 100644
--- a/ui/accessibility/ax_tree_id_registry.cc
+++ b/ui/accessibility/ax_tree_id_registry.cc
@@ -15,20 +15,20 @@
   return base::Singleton<AXTreeIDRegistry>::get();
 }
 
-AXTreeID AXTreeIDRegistry::GetOrCreateAXTreeID(int process_id, int routing_id) {
-  FrameID frame_id(process_id, routing_id);
+void AXTreeIDRegistry::SetFrameIDForAXTreeID(const FrameID& frame_id,
+                                             const AXTreeID& ax_tree_id) {
   auto it = frame_to_ax_tree_id_map_.find(frame_id);
-  if (it != frame_to_ax_tree_id_map_.end())
-    return it->second;
+  if (it != frame_to_ax_tree_id_map_.end()) {
+    NOTREACHED();
+    return;
+  }
 
-  AXTreeID new_id = AXTreeID::CreateNewAXTreeID();
-  frame_to_ax_tree_id_map_[frame_id] = new_id;
-  ax_tree_to_frame_id_map_[new_id] = frame_id;
-
-  return new_id;
+  frame_to_ax_tree_id_map_[frame_id] = ax_tree_id;
+  ax_tree_to_frame_id_map_[ax_tree_id] = frame_id;
 }
 
-AXTreeIDRegistry::FrameID AXTreeIDRegistry::GetFrameID(AXTreeID ax_tree_id) {
+AXTreeIDRegistry::FrameID AXTreeIDRegistry::GetFrameID(
+    const AXTreeID& ax_tree_id) {
   auto it = ax_tree_to_frame_id_map_.find(ax_tree_id);
   if (it != ax_tree_to_frame_id_map_.end())
     return it->second;
@@ -36,6 +36,14 @@
   return FrameID(-1, -1);
 }
 
+AXTreeID AXTreeIDRegistry::GetAXTreeID(AXTreeIDRegistry::FrameID frame_id) {
+  auto it = frame_to_ax_tree_id_map_.find(frame_id);
+  if (it != frame_to_ax_tree_id_map_.end())
+    return it->second;
+
+  return ui::AXTreeIDUnknown();
+}
+
 AXTreeID AXTreeIDRegistry::GetOrCreateAXTreeID(AXHostDelegate* delegate) {
   for (auto it : id_to_host_delegate_) {
     if (it.second == delegate)
@@ -53,16 +61,11 @@
   return it->second;
 }
 
-void AXTreeIDRegistry::SetDelegateForID(AXHostDelegate* delegate, AXTreeID id) {
-  id_to_host_delegate_[id] = delegate;
-}
-
 void AXTreeIDRegistry::RemoveAXTreeID(AXTreeID ax_tree_id) {
   auto frame_it = ax_tree_to_frame_id_map_.find(ax_tree_id);
   if (frame_it != ax_tree_to_frame_id_map_.end()) {
     frame_to_ax_tree_id_map_.erase(frame_it->second);
     ax_tree_to_frame_id_map_.erase(frame_it);
-    return;
   }
 
   auto action_it = id_to_host_delegate_.find(ax_tree_id);
@@ -71,8 +74,6 @@
 }
 
 AXTreeIDRegistry::AXTreeIDRegistry() {
-  // Always populate default desktop tree value (0 -> 0, 0).
-  GetOrCreateAXTreeID(0, 0);
 }
 
 AXTreeIDRegistry::~AXTreeIDRegistry() {}
diff --git a/ui/accessibility/ax_tree_id_registry.h b/ui/accessibility/ax_tree_id_registry.h
index 254adbc..077ccf5 100644
--- a/ui/accessibility/ax_tree_id_registry.h
+++ b/ui/accessibility/ax_tree_id_registry.h
@@ -37,22 +37,29 @@
   // Get the single instance of this class.
   static AXTreeIDRegistry* GetInstance();
 
-  // Methods for FrameID ax tree id generation, and retrieval.
-  AXTreeID GetOrCreateAXTreeID(int process_id, int routing_id);
-  FrameID GetFrameID(AXTreeID ax_tree_id);
+  // Gets the frame id based on an ax tree id.
+  FrameID GetFrameID(const AXTreeID& ax_tree_id);
 
-  // Retrieve an |AXHostDelegate|.
+  // Gets an ax tree id from a frame id.
+  AXTreeID GetAXTreeID(FrameID frame_id);
+
+  // Retrieve an |AXHostDelegate| based on an ax tree id.
   AXHostDelegate* GetHostDelegate(AXTreeID ax_tree_id);
 
+  // Removes an ax tree id, and its associated delegate and frame id (if it
+  // exists).
   void RemoveAXTreeID(AXTreeID ax_tree_id);
 
+  // Associate a frame id with an ax tree id.
+  void SetFrameIDForAXTreeID(const FrameID& frame_id,
+                             const AXTreeID& ax_tree_id);
+
  private:
   friend struct base::DefaultSingletonTraits<AXTreeIDRegistry>;
   friend AXHostDelegate;
 
-  // Methods for AXHostDelegate ax tree id generation.
+  // Get or create a ax tree id keyed on |delegate|.
   AXTreeID GetOrCreateAXTreeID(AXHostDelegate* delegate);
-  void SetDelegateForID(AXHostDelegate* delegate, AXTreeID id);
 
   AXTreeIDRegistry();
   virtual ~AXTreeIDRegistry();
diff --git a/ui/accessibility/ax_tree_observer.cc b/ui/accessibility/ax_tree_observer.cc
new file mode 100644
index 0000000..9080e81
--- /dev/null
+++ b/ui/accessibility/ax_tree_observer.cc
@@ -0,0 +1,12 @@
+// 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 "ui/accessibility/ax_tree_observer.h"
+
+namespace ui {
+
+AXTreeObserver::AXTreeObserver() = default;
+AXTreeObserver::~AXTreeObserver() = default;
+
+}  // namespace ui
diff --git a/ui/accessibility/ax_tree_observer.h b/ui/accessibility/ax_tree_observer.h
new file mode 100644
index 0000000..7c38cf99
--- /dev/null
+++ b/ui/accessibility/ax_tree_observer.h
@@ -0,0 +1,152 @@
+// 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 UI_ACCESSIBILITY_AX_TREE_OBSERVER_H_
+#define UI_ACCESSIBILITY_AX_TREE_OBSERVER_H_
+
+#include "base/observer_list_types.h"
+#include "ui/accessibility/ax_enums.mojom.h"
+#include "ui/accessibility/ax_export.h"
+
+namespace ui {
+
+class AXNode;
+struct AXNodeData;
+class AXTree;
+struct AXTreeData;
+
+// Used when you want to be notified when changes happen to an AXTree.
+//
+// Some of the notifications are called in the middle of an update operation.
+// Be careful, as the tree may be in an inconsistent state at this time;
+// don't walk the parents and children at this time:
+//   OnNodeWillBeDeleted
+//   OnSubtreeWillBeDeleted
+//   OnNodeWillBeReparented
+//   OnSubtreeWillBeReparented
+//   OnNodeCreated
+//   OnNodeReparented
+//   OnNodeChanged
+//
+// In addition, one additional notification is fired at the end of an
+// atomic update, and it provides a vector of nodes that were added or
+// changed, for final postprocessing:
+//   OnAtomicUpdateFinished
+//
+class AX_EXPORT AXTreeObserver : public base::CheckedObserver {
+ public:
+  AXTreeObserver();
+  ~AXTreeObserver() override;
+
+  // Called before a node's data gets updated.
+  virtual void OnNodeDataWillChange(AXTree* tree,
+                                    const AXNodeData& old_node_data,
+                                    const AXNodeData& new_node_data) {}
+
+  // Individual callbacks for every attribute of AXNodeData that can change.
+  virtual void OnRoleChanged(AXTree* tree,
+                             AXNode* node,
+                             ax::mojom::Role old_role,
+                             ax::mojom::Role new_role) {}
+  virtual void OnStateChanged(AXTree* tree,
+                              AXNode* node,
+                              ax::mojom::State state,
+                              bool new_value) {}
+  virtual void OnStringAttributeChanged(AXTree* tree,
+                                        AXNode* node,
+                                        ax::mojom::StringAttribute attr,
+                                        const std::string& old_value,
+                                        const std::string& new_value) {}
+  virtual void OnIntAttributeChanged(AXTree* tree,
+                                     AXNode* node,
+                                     ax::mojom::IntAttribute attr,
+                                     int32_t old_value,
+                                     int32_t new_value) {}
+  virtual void OnFloatAttributeChanged(AXTree* tree,
+                                       AXNode* node,
+                                       ax::mojom::FloatAttribute attr,
+                                       float old_value,
+                                       float new_value) {}
+  virtual void OnBoolAttributeChanged(AXTree* tree,
+                                      AXNode* node,
+                                      ax::mojom::BoolAttribute attr,
+                                      bool new_value) {}
+  virtual void OnIntListAttributeChanged(
+      AXTree* tree,
+      AXNode* node,
+      ax::mojom::IntListAttribute attr,
+      const std::vector<int32_t>& old_value,
+      const std::vector<int32_t>& new_value) {}
+  virtual void OnStringListAttributeChanged(
+      AXTree* tree,
+      AXNode* node,
+      ax::mojom::StringListAttribute attr,
+      const std::vector<std::string>& old_value,
+      const std::vector<std::string>& new_value) {}
+
+  // Called when tree data changes.
+  virtual void OnTreeDataChanged(AXTree* tree,
+                                 const ui::AXTreeData& old_data,
+                                 const ui::AXTreeData& new_data) {}
+
+  // Called just before a node is deleted. Its id and data will be valid,
+  // but its links to parents and children are invalid. This is called
+  // in the middle of an update, the tree may be in an invalid state!
+  virtual void OnNodeWillBeDeleted(AXTree* tree, AXNode* node) {}
+
+  // Same as OnNodeWillBeDeleted, but only called once for an entire subtree.
+  // This is called in the middle of an update, the tree may be in an
+  // invalid state!
+  virtual void OnSubtreeWillBeDeleted(AXTree* tree, AXNode* node) {}
+
+  // Called just before a node is deleted for reparenting. See
+  // |OnNodeWillBeDeleted| for additional information.
+  virtual void OnNodeWillBeReparented(AXTree* tree, AXNode* node) {}
+
+  // Called just before a subtree is deleted for reparenting. See
+  // |OnSubtreeWillBeDeleted| for additional information.
+  virtual void OnSubtreeWillBeReparented(AXTree* tree, AXNode* node) {}
+
+  // Called immediately after a new node is created. The tree may be in
+  // the middle of an update, don't walk the parents and children now.
+  virtual void OnNodeCreated(AXTree* tree, AXNode* node) {}
+
+  // Called immediately after a node is reparented. The tree may be in the
+  // middle of an update, don't walk the parents and children now.
+  virtual void OnNodeReparented(AXTree* tree, AXNode* node) {}
+
+  // Called when a node changes its data or children. The tree may be in
+  // the middle of an update, don't walk the parents and children now.
+  virtual void OnNodeChanged(AXTree* tree, AXNode* node) {}
+
+  enum ChangeType {
+    NODE_CREATED,
+    SUBTREE_CREATED,
+    NODE_CHANGED,
+    NODE_REPARENTED,
+    SUBTREE_REPARENTED
+  };
+
+  struct Change {
+    Change(AXNode* node, ChangeType type) {
+      this->node = node;
+      this->type = type;
+    }
+    AXNode* node;
+    ChangeType type;
+  };
+
+  // Called at the end of the update operation. Every node that was added
+  // or changed will be included in |changes|, along with an enum indicating
+  // the type of change - either (1) a node was created, (2) a node was created
+  // and it's the root of a new subtree, or (3) a node was changed. Finally,
+  // a bool indicates if the root of the tree was changed or not.
+  virtual void OnAtomicUpdateFinished(AXTree* tree,
+                                      bool root_changed,
+                                      const std::vector<Change>& changes) {}
+};
+
+}  // namespace ui
+
+#endif  // UI_ACCESSIBILITY_AX_TREE_OBSERVER_H_
diff --git a/ui/accessibility/ax_tree_unittest.cc b/ui/accessibility/ax_tree_unittest.cc
index 7b11f104..1fbc265b 100644
--- a/ui/accessibility/ax_tree_unittest.cc
+++ b/ui/accessibility/ax_tree_unittest.cc
@@ -16,6 +16,7 @@
 #include "ui/accessibility/ax_enum_util.h"
 #include "ui/accessibility/ax_node.h"
 #include "ui/accessibility/ax_serializable_tree.h"
+#include "ui/accessibility/ax_tree_observer.h"
 #include "ui/accessibility/ax_tree_serializer.h"
 #include "ui/gfx/transform.h"
 
@@ -54,11 +55,13 @@
   return result;
 }
 
-class FakeAXTreeDelegate : public AXTreeDelegate {
+class TestAXTreeObserver : public AXTreeObserver {
  public:
-  FakeAXTreeDelegate()
-      : tree_data_changed_(false),
-        root_changed_(false) {}
+  TestAXTreeObserver(AXTree* tree)
+      : tree_(tree), tree_data_changed_(false), root_changed_(false) {
+    tree_->AddObserver(this);
+  }
+  ~TestAXTreeObserver() final { tree_->RemoveObserver(this); }
 
   void OnNodeDataWillChange(AXTree* tree,
                             const AXNodeData& old_node_data,
@@ -210,6 +213,7 @@
   }
 
  private:
+  AXTree* tree_;
   bool tree_data_changed_;
   bool root_changed_;
   std::vector<int32_t> deleted_ids_;
@@ -431,29 +435,26 @@
   update.node_id_to_clear = root.id;
   update.nodes = {root, child1, child2};
 
-  FakeAXTreeDelegate fake_delegate;
-  tree.SetDelegate(&fake_delegate);
+  TestAXTreeObserver test_observer(&tree);
   ASSERT_TRUE(tree.Unserialize(update));
 
-  EXPECT_EQ(0U, fake_delegate.deleted_ids().size());
-  EXPECT_EQ(0U, fake_delegate.subtree_deleted_ids().size());
-  EXPECT_EQ(0U, fake_delegate.created_ids().size());
+  EXPECT_EQ(0U, test_observer.deleted_ids().size());
+  EXPECT_EQ(0U, test_observer.subtree_deleted_ids().size());
+  EXPECT_EQ(0U, test_observer.created_ids().size());
 
-  EXPECT_EQ(0U, fake_delegate.node_creation_finished_ids().size());
-  EXPECT_EQ(0U, fake_delegate.subtree_creation_finished_ids().size());
-  EXPECT_EQ(0U, fake_delegate.node_reparented_finished_ids().size());
+  EXPECT_EQ(0U, test_observer.node_creation_finished_ids().size());
+  EXPECT_EQ(0U, test_observer.subtree_creation_finished_ids().size());
+  EXPECT_EQ(0U, test_observer.node_reparented_finished_ids().size());
 
-  ASSERT_EQ(2U, fake_delegate.subtree_reparented_finished_ids().size());
-  EXPECT_EQ(child1.id, fake_delegate.subtree_reparented_finished_ids()[0]);
-  EXPECT_EQ(child2.id, fake_delegate.subtree_reparented_finished_ids()[1]);
+  ASSERT_EQ(2U, test_observer.subtree_reparented_finished_ids().size());
+  EXPECT_EQ(child1.id, test_observer.subtree_reparented_finished_ids()[0]);
+  EXPECT_EQ(child2.id, test_observer.subtree_reparented_finished_ids()[1]);
 
-  ASSERT_EQ(1U, fake_delegate.change_finished_ids().size());
-  EXPECT_EQ(root.id, fake_delegate.change_finished_ids()[0]);
+  ASSERT_EQ(1U, test_observer.change_finished_ids().size());
+  EXPECT_EQ(root.id, test_observer.change_finished_ids()[0]);
 
-  EXPECT_FALSE(fake_delegate.root_changed());
-  EXPECT_FALSE(fake_delegate.tree_data_changed());
-
-  tree.SetDelegate(nullptr);
+  EXPECT_FALSE(test_observer.root_changed());
+  EXPECT_FALSE(test_observer.tree_data_changed());
 }
 
 TEST(AXTreeTest, ReparentRootIfRootChanged) {
@@ -484,39 +485,36 @@
   update.node_id_to_clear = root.id;
   update.nodes = {root2, child1, child2};
 
-  FakeAXTreeDelegate fake_delegate;
-  tree.SetDelegate(&fake_delegate);
+  TestAXTreeObserver test_observer(&tree);
   ASSERT_TRUE(tree.Unserialize(update));
 
-  ASSERT_EQ(1U, fake_delegate.deleted_ids().size());
-  EXPECT_EQ(root.id, fake_delegate.deleted_ids()[0]);
+  ASSERT_EQ(1U, test_observer.deleted_ids().size());
+  EXPECT_EQ(root.id, test_observer.deleted_ids()[0]);
 
-  ASSERT_EQ(1U, fake_delegate.subtree_deleted_ids().size());
-  EXPECT_EQ(root.id, fake_delegate.subtree_deleted_ids()[0]);
+  ASSERT_EQ(1U, test_observer.subtree_deleted_ids().size());
+  EXPECT_EQ(root.id, test_observer.subtree_deleted_ids()[0]);
 
-  ASSERT_EQ(1U, fake_delegate.created_ids().size());
-  EXPECT_EQ(root2.id, fake_delegate.created_ids()[0]);
+  ASSERT_EQ(1U, test_observer.created_ids().size());
+  EXPECT_EQ(root2.id, test_observer.created_ids()[0]);
 
-  EXPECT_EQ(0U, fake_delegate.node_creation_finished_ids().size());
+  EXPECT_EQ(0U, test_observer.node_creation_finished_ids().size());
 
-  ASSERT_EQ(1U, fake_delegate.subtree_creation_finished_ids().size());
-  EXPECT_EQ(root2.id, fake_delegate.subtree_creation_finished_ids()[0]);
+  ASSERT_EQ(1U, test_observer.subtree_creation_finished_ids().size());
+  EXPECT_EQ(root2.id, test_observer.subtree_creation_finished_ids()[0]);
 
-  ASSERT_EQ(2U, fake_delegate.node_reparented_finished_ids().size());
-  EXPECT_EQ(child1.id, fake_delegate.node_reparented_finished_ids()[0]);
-  EXPECT_EQ(child2.id, fake_delegate.node_reparented_finished_ids()[1]);
+  ASSERT_EQ(2U, test_observer.node_reparented_finished_ids().size());
+  EXPECT_EQ(child1.id, test_observer.node_reparented_finished_ids()[0]);
+  EXPECT_EQ(child2.id, test_observer.node_reparented_finished_ids()[1]);
 
-  EXPECT_EQ(0U, fake_delegate.subtree_reparented_finished_ids().size());
+  EXPECT_EQ(0U, test_observer.subtree_reparented_finished_ids().size());
 
-  EXPECT_EQ(0U, fake_delegate.change_finished_ids().size());
+  EXPECT_EQ(0U, test_observer.change_finished_ids().size());
 
-  EXPECT_TRUE(fake_delegate.root_changed());
-  EXPECT_FALSE(fake_delegate.tree_data_changed());
-
-  tree.SetDelegate(nullptr);
+  EXPECT_TRUE(test_observer.root_changed());
+  EXPECT_FALSE(test_observer.tree_data_changed());
 }
 
-TEST(AXTreeTest, TreeDelegateIsCalled) {
+TEST(AXTreeTest, TreeObserverIsCalled) {
   AXTreeUpdate initial_state;
   initial_state.root_id = 1;
   initial_state.nodes.resize(2);
@@ -533,34 +531,30 @@
   update.nodes[0].child_ids.push_back(4);
   update.nodes[1].id = 4;
 
-  FakeAXTreeDelegate fake_delegate;
-  tree.SetDelegate(&fake_delegate);
-
+  TestAXTreeObserver test_observer(&tree);
   ASSERT_TRUE(tree.Unserialize(update));
 
-  ASSERT_EQ(2U, fake_delegate.deleted_ids().size());
-  EXPECT_EQ(1, fake_delegate.deleted_ids()[0]);
-  EXPECT_EQ(2, fake_delegate.deleted_ids()[1]);
+  ASSERT_EQ(2U, test_observer.deleted_ids().size());
+  EXPECT_EQ(1, test_observer.deleted_ids()[0]);
+  EXPECT_EQ(2, test_observer.deleted_ids()[1]);
 
-  ASSERT_EQ(1U, fake_delegate.subtree_deleted_ids().size());
-  EXPECT_EQ(1, fake_delegate.subtree_deleted_ids()[0]);
+  ASSERT_EQ(1U, test_observer.subtree_deleted_ids().size());
+  EXPECT_EQ(1, test_observer.subtree_deleted_ids()[0]);
 
-  ASSERT_EQ(2U, fake_delegate.created_ids().size());
-  EXPECT_EQ(3, fake_delegate.created_ids()[0]);
-  EXPECT_EQ(4, fake_delegate.created_ids()[1]);
+  ASSERT_EQ(2U, test_observer.created_ids().size());
+  EXPECT_EQ(3, test_observer.created_ids()[0]);
+  EXPECT_EQ(4, test_observer.created_ids()[1]);
 
-  ASSERT_EQ(1U, fake_delegate.subtree_creation_finished_ids().size());
-  EXPECT_EQ(3, fake_delegate.subtree_creation_finished_ids()[0]);
+  ASSERT_EQ(1U, test_observer.subtree_creation_finished_ids().size());
+  EXPECT_EQ(3, test_observer.subtree_creation_finished_ids()[0]);
 
-  ASSERT_EQ(1U, fake_delegate.node_creation_finished_ids().size());
-  EXPECT_EQ(4, fake_delegate.node_creation_finished_ids()[0]);
+  ASSERT_EQ(1U, test_observer.node_creation_finished_ids().size());
+  EXPECT_EQ(4, test_observer.node_creation_finished_ids()[0]);
 
-  ASSERT_TRUE(fake_delegate.root_changed());
-
-  tree.SetDelegate(nullptr);
+  ASSERT_TRUE(test_observer.root_changed());
 }
 
-TEST(AXTreeTest, TreeDelegateIsCalledForTreeDataChanges) {
+TEST(AXTreeTest, TreeObserverIsCalledForTreeDataChanges) {
   AXTreeUpdate initial_state;
   initial_state.root_id = 1;
   initial_state.nodes.resize(1);
@@ -569,13 +563,12 @@
   initial_state.tree_data.title = "Initial";
   AXTree tree(initial_state);
 
-  FakeAXTreeDelegate fake_delegate;
-  tree.SetDelegate(&fake_delegate);
+  TestAXTreeObserver test_observer(&tree);
 
   // An empty update shouldn't change tree data.
   AXTreeUpdate empty_update;
   EXPECT_TRUE(tree.Unserialize(empty_update));
-  EXPECT_FALSE(fake_delegate.tree_data_changed());
+  EXPECT_FALSE(test_observer.tree_data_changed());
   EXPECT_EQ("Initial", tree.data().title);
 
   // An update with tree data shouldn't change tree data if
@@ -583,7 +576,7 @@
   AXTreeUpdate ignored_tree_data_update;
   ignored_tree_data_update.tree_data.title = "Ignore Me";
   EXPECT_TRUE(tree.Unserialize(ignored_tree_data_update));
-  EXPECT_FALSE(fake_delegate.tree_data_changed());
+  EXPECT_FALSE(test_observer.tree_data_changed());
   EXPECT_EQ("Initial", tree.data().title);
 
   // An update with |has_tree_data| set should update the tree data.
@@ -591,10 +584,8 @@
   tree_data_update.has_tree_data = true;
   tree_data_update.tree_data.title = "New Title";
   EXPECT_TRUE(tree.Unserialize(tree_data_update));
-  EXPECT_TRUE(fake_delegate.tree_data_changed());
+  EXPECT_TRUE(test_observer.tree_data_changed());
   EXPECT_EQ("New Title", tree.data().title);
-
-  tree.SetDelegate(nullptr);
 }
 
 TEST(AXTreeTest, ReparentingDoesNotTriggerNodeCreated) {
@@ -607,9 +598,8 @@
   initial_state.nodes[1].child_ids.push_back(3);
   initial_state.nodes[2].id = 3;
 
-  FakeAXTreeDelegate fake_delegate;
   AXTree tree(initial_state);
-  tree.SetDelegate(&fake_delegate);
+  TestAXTreeObserver test_observer(&tree);
 
   AXTreeUpdate update;
   update.nodes.resize(2);
@@ -619,17 +609,17 @@
   update.nodes[0].child_ids.push_back(3);
   update.nodes[1].id = 3;
   EXPECT_TRUE(tree.Unserialize(update)) << tree.error();
-  std::vector<int> created = fake_delegate.node_creation_finished_ids();
+  std::vector<int> created = test_observer.node_creation_finished_ids();
   std::vector<int> subtree_reparented =
-      fake_delegate.subtree_reparented_finished_ids();
+      test_observer.subtree_reparented_finished_ids();
   std::vector<int> node_reparented =
-      fake_delegate.node_reparented_finished_ids();
+      test_observer.node_reparented_finished_ids();
   ASSERT_FALSE(base::ContainsValue(created, 3));
   ASSERT_TRUE(base::ContainsValue(subtree_reparented, 3));
   ASSERT_FALSE(base::ContainsValue(node_reparented, 3));
 }
 
-TEST(AXTreeTest, TreeDelegateIsNotCalledForReparenting) {
+TEST(AXTreeTest, TreeObserverIsNotCalledForReparenting) {
   AXTreeUpdate initial_state;
   initial_state.root_id = 1;
   initial_state.nodes.resize(2);
@@ -646,32 +636,29 @@
   update.nodes[0].child_ids.push_back(4);
   update.nodes[1].id = 4;
 
-  FakeAXTreeDelegate fake_delegate;
-  tree.SetDelegate(&fake_delegate);
+  TestAXTreeObserver test_observer(&tree);
 
   EXPECT_TRUE(tree.Unserialize(update));
 
-  ASSERT_EQ(1U, fake_delegate.deleted_ids().size());
-  EXPECT_EQ(1, fake_delegate.deleted_ids()[0]);
+  ASSERT_EQ(1U, test_observer.deleted_ids().size());
+  EXPECT_EQ(1, test_observer.deleted_ids()[0]);
 
-  ASSERT_EQ(1U, fake_delegate.subtree_deleted_ids().size());
-  EXPECT_EQ(1, fake_delegate.subtree_deleted_ids()[0]);
+  ASSERT_EQ(1U, test_observer.subtree_deleted_ids().size());
+  EXPECT_EQ(1, test_observer.subtree_deleted_ids()[0]);
 
-  ASSERT_EQ(1U, fake_delegate.created_ids().size());
-  EXPECT_EQ(4, fake_delegate.created_ids()[0]);
+  ASSERT_EQ(1U, test_observer.created_ids().size());
+  EXPECT_EQ(4, test_observer.created_ids()[0]);
 
-  ASSERT_EQ(1U, fake_delegate.subtree_creation_finished_ids().size());
-  EXPECT_EQ(4, fake_delegate.subtree_creation_finished_ids()[0]);
+  ASSERT_EQ(1U, test_observer.subtree_creation_finished_ids().size());
+  EXPECT_EQ(4, test_observer.subtree_creation_finished_ids()[0]);
 
-  ASSERT_EQ(1U, fake_delegate.subtree_reparented_finished_ids().size());
-  EXPECT_EQ(2, fake_delegate.subtree_reparented_finished_ids()[0]);
+  ASSERT_EQ(1U, test_observer.subtree_reparented_finished_ids().size());
+  EXPECT_EQ(2, test_observer.subtree_reparented_finished_ids()[0]);
 
-  EXPECT_EQ(0U, fake_delegate.node_creation_finished_ids().size());
-  EXPECT_EQ(0U, fake_delegate.node_reparented_finished_ids().size());
+  EXPECT_EQ(0U, test_observer.node_creation_finished_ids().size());
+  EXPECT_EQ(0U, test_observer.node_reparented_finished_ids().size());
 
-  ASSERT_TRUE(fake_delegate.root_changed());
-
-  tree.SetDelegate(nullptr);
+  ASSERT_TRUE(test_observer.root_changed());
 }
 
 // UAF caught by ax_tree_fuzzer
@@ -728,8 +715,7 @@
   initial_state.nodes[0].AddState(ax::mojom::State::kFocusable);
   AXTree tree(initial_state);
 
-  FakeAXTreeDelegate fake_delegate;
-  tree.SetDelegate(&fake_delegate);
+  TestAXTreeObserver test_observer(&tree);
 
   // Change the role and state.
   AXTreeUpdate update;
@@ -743,13 +729,11 @@
   EXPECT_TRUE(tree.Unserialize(update));
 
   const std::vector<std::string>& change_log =
-      fake_delegate.attribute_change_log();
+      test_observer.attribute_change_log();
   ASSERT_EQ(3U, change_log.size());
   EXPECT_EQ("Role changed from button to checkBox", change_log[0]);
   EXPECT_EQ("visited changed to true", change_log[1]);
   EXPECT_EQ("checkedState changed from 2 to 1", change_log[2]);
-
-  tree.SetDelegate(nullptr);
 }
 
 TEST(AXTreeTest, AttributeChangeCallbacks) {
@@ -776,8 +760,7 @@
                                          1);
   AXTree tree(initial_state);
 
-  FakeAXTreeDelegate fake_delegate;
-  tree.SetDelegate(&fake_delegate);
+  TestAXTreeObserver test_observer(&tree);
 
   // Change existing attributes.
   AXTreeUpdate update0;
@@ -801,7 +784,7 @@
   EXPECT_TRUE(tree.Unserialize(update0));
 
   const std::vector<std::string>& change_log =
-      fake_delegate.attribute_change_log();
+      test_observer.attribute_change_log();
   ASSERT_EQ(9U, change_log.size());
   EXPECT_EQ("name changed from N1 to N2", change_log[0]);
   EXPECT_EQ("description changed from D1 to D2", change_log[1]);
@@ -813,8 +796,7 @@
   EXPECT_EQ("scrollX changed from 5 to 6", change_log[7]);
   EXPECT_EQ("scrollXMin changed from 1 to 2", change_log[8]);
 
-  FakeAXTreeDelegate fake_delegate2;
-  tree.SetDelegate(&fake_delegate2);
+  TestAXTreeObserver test_observer2(&tree);
 
   // Add and remove attributes.
   AXTreeUpdate update1;
@@ -834,7 +816,7 @@
   EXPECT_TRUE(tree.Unserialize(update1));
 
   const std::vector<std::string>& change_log2 =
-      fake_delegate2.attribute_change_log();
+      test_observer2.attribute_change_log();
   ASSERT_EQ(11U, change_log2.size());
   EXPECT_EQ("name changed from N2 to ", change_log2[0]);
   EXPECT_EQ("description changed from D2 to D3", change_log2[1]);
@@ -847,8 +829,6 @@
   EXPECT_EQ("scrollXMin changed from 2 to 0", change_log2[8]);
   EXPECT_EQ("scrollX changed from 6 to 7", change_log2[9]);
   EXPECT_EQ("scrollXMax changed from 0 to 10", change_log2[10]);
-
-  tree.SetDelegate(nullptr);
 }
 
 TEST(AXTreeTest, IntListChangeCallbacks) {
@@ -872,8 +852,7 @@
       ax::mojom::IntListAttribute::kRadioGroupIds, two);
   AXTree tree(initial_state);
 
-  FakeAXTreeDelegate fake_delegate;
-  tree.SetDelegate(&fake_delegate);
+  TestAXTreeObserver test_observer(&tree);
 
   // Change existing attributes.
   AXTreeUpdate update0;
@@ -887,13 +866,12 @@
   EXPECT_TRUE(tree.Unserialize(update0));
 
   const std::vector<std::string>& change_log =
-      fake_delegate.attribute_change_log();
+      test_observer.attribute_change_log();
   ASSERT_EQ(2U, change_log.size());
   EXPECT_EQ("controlsIds changed from 1 to 2,2", change_log[0]);
   EXPECT_EQ("radioGroupIds changed from 2,2 to 3", change_log[1]);
 
-  FakeAXTreeDelegate fake_delegate2;
-  tree.SetDelegate(&fake_delegate2);
+  TestAXTreeObserver test_observer2(&tree);
 
   // Add and remove attributes.
   AXTreeUpdate update1;
@@ -907,13 +885,11 @@
   EXPECT_TRUE(tree.Unserialize(update1));
 
   const std::vector<std::string>& change_log2 =
-      fake_delegate2.attribute_change_log();
+      test_observer2.attribute_change_log();
   ASSERT_EQ(3U, change_log2.size());
   EXPECT_EQ("controlsIds changed from 2,2 to ", change_log2[0]);
   EXPECT_EQ("radioGroupIds changed from 3 to 2,2", change_log2[1]);
   EXPECT_EQ("flowtoIds changed from  to 3", change_log2[2]);
-
-  tree.SetDelegate(nullptr);
 }
 
 // Create a very simple tree and make sure that we can get the bounds of
diff --git a/ui/accessibility/mojom/ax_tree_id.mojom b/ui/accessibility/mojom/ax_tree_id.mojom
index b798fe2..0f3c7943 100644
--- a/ui/accessibility/mojom/ax_tree_id.mojom
+++ b/ui/accessibility/mojom/ax_tree_id.mojom
@@ -11,9 +11,6 @@
   // Placeholder for an unknown AXTreeID. The value of this field is not used.
   uint8 unknown;
 
-  // Placeholder for the desktop AXTreeID. The value of this field is not used.
-  uint8 desktop;
-
-  // Any AXTreeID that's not unknown or the desktop must be an UnguessableToken.
+  // Any AXTreeID that's not unknown must be an UnguessableToken.
   mojo_base.mojom.UnguessableToken token;
 };
diff --git a/ui/accessibility/mojom/ax_tree_id_mojom_traits.cc b/ui/accessibility/mojom/ax_tree_id_mojom_traits.cc
index 93273042..d801177 100644
--- a/ui/accessibility/mojom/ax_tree_id_mojom_traits.cc
+++ b/ui/accessibility/mojom/ax_tree_id_mojom_traits.cc
@@ -14,9 +14,6 @@
     case ax::mojom::AXTreeIDDataView::Tag::UNKNOWN:
       out->type_ = ax::mojom::AXTreeIDType::kUnknown;
       return true;
-    case ax::mojom::AXTreeIDDataView::Tag::DESKTOP:
-      out->type_ = ax::mojom::AXTreeIDType::kDesktop;
-      return true;
     case ax::mojom::AXTreeIDDataView::Tag::TOKEN:
       out->type_ = ax::mojom::AXTreeIDType::kToken;
       if (!data.ReadToken(&out->token_))
diff --git a/ui/accessibility/mojom/ax_tree_id_mojom_traits.h b/ui/accessibility/mojom/ax_tree_id_mojom_traits.h
index 3a87a52..13fc696 100644
--- a/ui/accessibility/mojom/ax_tree_id_mojom_traits.h
+++ b/ui/accessibility/mojom/ax_tree_id_mojom_traits.h
@@ -17,14 +17,11 @@
     switch (p.type()) {
       case ax::mojom::AXTreeIDType::kUnknown:
         return ax::mojom::AXTreeIDDataView::Tag::UNKNOWN;
-      case ax::mojom::AXTreeIDType::kDesktop:
-        return ax::mojom::AXTreeIDDataView::Tag::DESKTOP;
       case ax::mojom::AXTreeIDType::kToken:
         return ax::mojom::AXTreeIDDataView::Tag::TOKEN;
     }
   }
   static uint8_t unknown(const ui::AXTreeID& p) { return 0; }
-  static uint8_t desktop(const ui::AXTreeID& p) { return 0; }
   static const base::UnguessableToken token(const ui::AXTreeID& p) {
     DCHECK_EQ(p.type(), ax::mojom::AXTreeIDType::kToken);
     return *p.token();
diff --git a/ui/accessibility/mojom/ax_tree_id_mojom_traits_unittest.cc b/ui/accessibility/mojom/ax_tree_id_mojom_traits_unittest.cc
index 3ead478..fadf6cc 100644
--- a/ui/accessibility/mojom/ax_tree_id_mojom_traits_unittest.cc
+++ b/ui/accessibility/mojom/ax_tree_id_mojom_traits_unittest.cc
@@ -25,13 +25,6 @@
   EXPECT_EQ(unknown_input, unknown_output);
   EXPECT_EQ("", unknown_output.ToString());
 
-  ui::AXTreeID desktop_input = ui::DesktopAXTreeID();
-  ui::AXTreeID desktop_output;
-  EXPECT_TRUE(SerializeAndDeserialize<ax::mojom::AXTreeID>(&desktop_input,
-                                                           &desktop_output));
-  EXPECT_EQ(desktop_input, desktop_output);
-  EXPECT_EQ("0", desktop_output.ToString());
-
   ui::AXTreeID token_input = ui::AXTreeID::CreateNewAXTreeID();
   ui::AXTreeID token_output;
   EXPECT_TRUE(SerializeAndDeserialize<ax::mojom::AXTreeID>(&token_input,
diff --git a/ui/accessibility/platform/test_ax_node_wrapper.cc b/ui/accessibility/platform/test_ax_node_wrapper.cc
index 1df93f5..511cf8c 100644
--- a/ui/accessibility/platform/test_ax_node_wrapper.cc
+++ b/ui/accessibility/platform/test_ax_node_wrapper.cc
@@ -8,6 +8,7 @@
 #include "base/stl_util.h"
 #include "ui/accessibility/ax_action_data.h"
 #include "ui/accessibility/ax_table_info.h"
+#include "ui/accessibility/ax_tree_observer.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 
 namespace ui {
@@ -20,15 +21,10 @@
 // A global coordinate offset.
 gfx::Vector2d g_offset;
 
-// A simple implementation of AXTreeDelegate to catch when AXNodes are
+// A simple implementation of AXTreeObserver to catch when AXNodes are
 // deleted so we can delete their wrappers.
-class TestAXTreeDelegate : public AXTreeDelegate {
-  void OnNodeDataWillChange(AXTree* tree,
-                            const AXNodeData& old_node_data,
-                            const AXNodeData& new_node_data) override {}
-  void OnTreeDataChanged(AXTree* tree,
-                         const AXTreeData& old_data,
-                         const AXTreeData& new_data) override {}
+class TestAXTreeObserver : public AXTreeObserver {
+ private:
   void OnNodeWillBeDeleted(AXTree* tree, AXNode* node) override {
     auto iter = g_node_to_wrapper_map.find(node);
     if (iter != g_node_to_wrapper_map.end()) {
@@ -37,18 +33,9 @@
       g_node_to_wrapper_map.erase(iter->first);
     }
   }
-  void OnSubtreeWillBeDeleted(AXTree* tree, AXNode* node) override {}
-  void OnNodeWillBeReparented(AXTree* tree, AXNode* node) override {}
-  void OnSubtreeWillBeReparented(AXTree* tree, AXNode* node) override {}
-  void OnNodeCreated(AXTree* tree, AXNode* node) override {}
-  void OnNodeReparented(AXTree* tree, AXNode* node) override {}
-  void OnNodeChanged(AXTree* tree, AXNode* node) override {}
-  void OnAtomicUpdateFinished(AXTree* tree,
-                              bool root_changed,
-                              const std::vector<Change>& changes) override {}
 };
 
-TestAXTreeDelegate g_ax_tree_delegate;
+TestAXTreeObserver g_ax_tree_observer;
 
 }  // namespace
 
@@ -57,7 +44,8 @@
   if (!tree || !node)
     return nullptr;
 
-  tree->SetDelegate(&g_ax_tree_delegate);
+  if (!tree->HasObserver(&g_ax_tree_observer))
+    tree->AddObserver(&g_ax_tree_observer);
   auto iter = g_node_to_wrapper_map.find(node);
   if (iter != g_node_to_wrapper_map.end())
     return iter->second;
diff --git a/ui/accessibility/platform/test_ax_node_wrapper.h b/ui/accessibility/platform/test_ax_node_wrapper.h
index 0f96cded..07a5fb7b 100644
--- a/ui/accessibility/platform/test_ax_node_wrapper.h
+++ b/ui/accessibility/platform/test_ax_node_wrapper.h
@@ -17,8 +17,6 @@
 class TestAXNodeWrapper : public AXPlatformNodeDelegateBase {
  public:
   // Create TestAXNodeWrapper instances on-demand from an AXTree and AXNode.
-  // Note that this sets the AXTreeDelegate, you can't use this class if
-  // you also want to implement AXTreeDelegate.
   static TestAXNodeWrapper* GetOrCreate(AXTree* tree, AXNode* node);
 
   // Set a global coordinate offset for testing.
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index 85cf181..9f9b0e7 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -372,6 +372,12 @@
 
   if (is_mac) {
     sources += [ "accelerators/media_keys_listener_mac.mm" ]
+  } else if (is_win) {
+    sources += [
+      "accelerators/global_media_keys_listener_win.cc",
+      "accelerators/global_media_keys_listener_win.h",
+      "accelerators/media_keys_listener_win.cc",
+    ]
   } else {
     sources += [ "accelerators/media_keys_listener_stub.cc" ]
   }
@@ -1118,3 +1124,22 @@
     ]
   }
 }
+
+# This target is added as a dependency of browser interactive_ui_tests. It must
+# be source_set, otherwise the linker will drop the tests as dead code.
+source_set("base_interactive_ui_tests") {
+  testonly = true
+  if (is_win) {
+    sources = [
+      "accelerators/global_media_keys_listener_win_interactive_test.cc",
+    ]
+
+    deps = [
+      ":base",
+      ":test_support",
+      "//base/test:test_support",
+      "//testing/gtest",
+      "//ui/events:events",
+    ]
+  }
+}
diff --git a/ui/base/accelerators/global_media_keys_listener_win.cc b/ui/base/accelerators/global_media_keys_listener_win.cc
new file mode 100644
index 0000000..91c2911
--- /dev/null
+++ b/ui/base/accelerators/global_media_keys_listener_win.cc
@@ -0,0 +1,99 @@
+// 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 "ui/base/accelerators/global_media_keys_listener_win.h"
+
+#include "base/bind.h"
+#include "base/sequenced_task_runner.h"
+#include "base/threading/thread.h"
+#include "ui/base/accelerators/accelerator.h"
+#include "ui/events/event.h"
+#include "ui/events/keyboard_hook.h"
+
+namespace ui {
+
+// static
+bool GlobalMediaKeysListenerWin::has_instance_ = false;
+
+GlobalMediaKeysListenerWin::GlobalMediaKeysListenerWin(
+    MediaKeysListener::Delegate* delegate)
+    : delegate_(delegate), thread_("KeyboardHookThread") {
+  DCHECK(delegate_);
+  DCHECK(!has_instance_);
+  has_instance_ = true;
+}
+
+GlobalMediaKeysListenerWin::~GlobalMediaKeysListenerWin() {
+  // This will reset |hook_| (if necessary) and then join on |thread_| if it's
+  // currently running. This guarantees that |hook_| will be empty before its
+  // destructor is called on this thread, so we will avoid accessing |hook_| on
+  // this thread.
+  StopWatchingMediaKeys();
+  has_instance_ = false;
+}
+
+void GlobalMediaKeysListenerWin::StartWatchingMediaKeys() {
+  // Create the keyboard hook if it doesn't already exist.
+  if (!thread_.IsRunning()) {
+    bool started = thread_.StartWithOptions(
+        base::Thread::Options(base::MessageLoop::TYPE_UI, 0));
+    LOG_IF(ERROR, !started) << "failed to start KeyboardHookThread";
+    thread_.task_runner()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&GlobalMediaKeysListenerWin::EnsureHookOnInternalThread,
+                       base::Unretained(this)));
+  }
+}
+
+void GlobalMediaKeysListenerWin::StopWatchingMediaKeys() {
+  // Delete the keyboard hook if it exists.
+  if (thread_.IsRunning()) {
+    thread_.task_runner()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&GlobalMediaKeysListenerWin::DeleteHookOnInternalThread,
+                       base::Unretained(this)));
+    thread_.Stop();
+  }
+}
+
+bool GlobalMediaKeysListenerWin::IsWatchingMediaKeys() const {
+  return thread_.IsRunning();
+}
+
+void GlobalMediaKeysListenerWin::EnsureHookOnInternalThread() {
+  DCHECK(thread_.task_runner()->RunsTasksInCurrentSequence());
+  DCHECK(!hook_);
+  hook_ = KeyboardHook::CreateMediaKeyboardHook(base::BindRepeating(
+      &GlobalMediaKeysListenerWin::KeyEventCallbackOnInternalThread,
+      base::Unretained(this)));
+
+  if (hook_) {
+    // Notify the delegate that the keyboard hook has been registered.
+    delegate_->OnStartedWatchingMediaKeys();
+  } else {
+    LOG(ERROR) << "failed to create keyboard hook";
+  }
+}
+
+void GlobalMediaKeysListenerWin::DeleteHookOnInternalThread() {
+  DCHECK(thread_.task_runner()->RunsTasksInCurrentSequence());
+  hook_.reset();
+}
+
+void GlobalMediaKeysListenerWin::KeyEventCallbackOnInternalThread(
+    KeyEvent* event) {
+  DCHECK(thread_.task_runner()->RunsTasksInCurrentSequence());
+  Accelerator::KeyState state = (event->type() == ET_KEY_PRESSED)
+                                    ? Accelerator::KeyState::PRESSED
+                                    : Accelerator::KeyState::RELEASED;
+  const ui::Accelerator accelerator(event->key_code(), 0, state);
+  if (delegate_->OnMediaKeysAccelerator(accelerator) ==
+      MediaKeysListener::MediaKeysHandleResult::kSuppressPropagation) {
+    // Marking the event as handled will prevent propagation in the
+    // KeyboardHook.
+    event->SetHandled();
+  }
+}
+
+}  // namespace ui
\ No newline at end of file
diff --git a/ui/base/accelerators/global_media_keys_listener_win.h b/ui/base/accelerators/global_media_keys_listener_win.h
new file mode 100644
index 0000000..c7cf447e
--- /dev/null
+++ b/ui/base/accelerators/global_media_keys_listener_win.h
@@ -0,0 +1,50 @@
+// 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 UI_BASE_ACCELERATORS_GLOBAL_MEDIA_KEYS_LISTENER_WIN_H_
+#define UI_BASE_ACCELERATORS_GLOBAL_MEDIA_KEYS_LISTENER_WIN_H_
+
+#include "base/threading/thread.h"
+#include "ui/base/accelerators/media_keys_listener.h"
+#include "ui/base/ui_base_export.h"
+
+namespace ui {
+
+class KeyboardHook;
+class KeyEvent;
+
+// Implementation of MediaKeysListener that uses a KeyboardHook to globally
+// listen for media key presses. It only allows for a single instance to be
+// created in order to prevent multiple low-level keyboard hooks from being
+// installed on a system. It also runs the hook on a dedicated thread to help
+// reduce keyboard input delays.
+class UI_BASE_EXPORT GlobalMediaKeysListenerWin : public MediaKeysListener {
+ public:
+  explicit GlobalMediaKeysListenerWin(MediaKeysListener::Delegate* delegate);
+  ~GlobalMediaKeysListenerWin() override;
+
+  static bool has_instance() { return has_instance_; }
+
+  // MediaKeysListener implementation.
+  void StartWatchingMediaKeys() override;
+  void StopWatchingMediaKeys() override;
+  bool IsWatchingMediaKeys() const override;
+
+ private:
+  void EnsureHookOnInternalThread();
+  void DeleteHookOnInternalThread();
+  void KeyEventCallbackOnInternalThread(KeyEvent* event);
+
+  static bool has_instance_;
+
+  MediaKeysListener::Delegate* delegate_;
+  std::unique_ptr<KeyboardHook> hook_;
+  base::Thread thread_;
+
+  DISALLOW_COPY_AND_ASSIGN(GlobalMediaKeysListenerWin);
+};
+
+}  // namespace ui
+
+#endif  // UI_BASE_ACCELERATORS_GLOBAL_MEDIA_KEYS_LISTENER_WIN_H_
diff --git a/ui/base/accelerators/global_media_keys_listener_win_interactive_test.cc b/ui/base/accelerators/global_media_keys_listener_win_interactive_test.cc
new file mode 100644
index 0000000..e5e0fe6b
--- /dev/null
+++ b/ui/base/accelerators/global_media_keys_listener_win_interactive_test.cc
@@ -0,0 +1,169 @@
+// 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 "ui/base/accelerators/global_media_keys_listener_win.h"
+
+#include "base/callback.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/accelerators/accelerator.h"
+#include "ui/events/event.h"
+
+namespace ui {
+
+namespace {
+
+class MockMediaKeysListenerDelegate : public MediaKeysListener::Delegate {
+ public:
+  MockMediaKeysListenerDelegate() = default;
+  ~MockMediaKeysListenerDelegate() override = default;
+
+  // MediaKeysListener::Delegate implementation.
+  MediaKeysListener::MediaKeysHandleResult OnMediaKeysAccelerator(
+      const Accelerator& accelerator) override {
+    received_events_.push_back(accelerator.ToKeyEvent());
+
+    // If we've received the events we're waiting for, stop waiting.
+    if (key_event_wait_loop_ &&
+        received_events_.size() >= num_key_events_to_wait_for_) {
+      key_event_wait_loop_->Quit();
+    }
+
+    // Never let the test key presses out to the OS.
+    return MediaKeysListener::MediaKeysHandleResult::kSuppressPropagation;
+  }
+
+  void OnStartedWatchingMediaKeys() override {
+    std::move(hook_registration_callback_).Run();
+  }
+
+  // Set the callback to be called when the keyboard hook has been registered.
+  void SetHookRegistrationCallback(base::OnceClosure callback) {
+    hook_registration_callback_ = std::move(callback);
+  }
+
+  // Loop until we've received |num_events| key events from the listener.
+  void WaitForKeyEvents(uint32_t num_events) {
+    key_event_wait_loop_ = std::make_unique<base::RunLoop>();
+    if (received_events_.size() >= num_events)
+      return;
+
+    num_key_events_to_wait_for_ = num_events;
+    key_event_wait_loop_->Run();
+  }
+
+  // Expect that we have received the correct number of key events.
+  void ExpectReceivedEventsCount(uint32_t count) {
+    EXPECT_EQ(count, received_events_.size());
+  }
+
+  // Expect that the key event received at |index| has the specified key code
+  // and type.
+  void ExpectReceivedEvent(uint32_t index, KeyboardCode code, EventType type) {
+    ASSERT_LT(index, received_events_.size());
+    KeyEvent* key_event = &received_events_.at(index);
+    EXPECT_EQ(code, key_event->key_code());
+    EXPECT_EQ(type, key_event->type());
+  }
+
+ private:
+  std::vector<KeyEvent> received_events_;
+  std::unique_ptr<base::RunLoop> key_event_wait_loop_;
+  uint32_t num_key_events_to_wait_for_ = 0;
+  base::OnceClosure hook_registration_callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockMediaKeysListenerDelegate);
+};
+
+}  // anonymous namespace
+
+class GlobalMediaKeysListenerWinInteractiveTest : public testing::Test {
+ public:
+  GlobalMediaKeysListenerWinInteractiveTest()
+      : scoped_task_environment_(
+            base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+
+ protected:
+  void SendKeyDown(KeyboardCode code) {
+    INPUT input;
+    input.type = INPUT_KEYBOARD;
+    input.ki.wVk = code;
+    input.ki.time = time_stamp_++;
+    input.ki.dwFlags = 0;
+    SendInput(1, &input, sizeof(INPUT));
+  }
+
+  void SendKeyUp(KeyboardCode code) {
+    INPUT input;
+    input.type = INPUT_KEYBOARD;
+    input.ki.wVk = code;
+    input.ki.time = time_stamp_++;
+    input.ki.dwFlags = KEYEVENTF_KEYUP;
+    SendInput(1, &input, sizeof(INPUT));
+  }
+
+ private:
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  DWORD time_stamp_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(GlobalMediaKeysListenerWinInteractiveTest);
+};
+
+TEST_F(GlobalMediaKeysListenerWinInteractiveTest, SimplePlayPauseTest) {
+  MockMediaKeysListenerDelegate delegate;
+  GlobalMediaKeysListenerWin listener(&delegate);
+
+  // Start listening and wait for hook registration.
+  base::RunLoop hook_registration_loop;
+  delegate.SetHookRegistrationCallback(hook_registration_loop.QuitClosure());
+  listener.StartWatchingMediaKeys();
+  hook_registration_loop.Run();
+
+  // Send a key down event and validate that it was received by the delegate.
+  SendKeyDown(ui::VKEY_MEDIA_PLAY_PAUSE);
+  delegate.WaitForKeyEvents(1);
+  delegate.ExpectReceivedEvent(/*index=*/0, ui::VKEY_MEDIA_PLAY_PAUSE,
+                               ET_KEY_PRESSED);
+
+  // Send a key up event and validate that it was received by the delegate.
+  SendKeyUp(ui::VKEY_MEDIA_PLAY_PAUSE);
+  delegate.WaitForKeyEvents(2);
+  delegate.ExpectReceivedEvent(/*index=*/1, ui::VKEY_MEDIA_PLAY_PAUSE,
+                               ET_KEY_RELEASED);
+}
+
+TEST_F(GlobalMediaKeysListenerWinInteractiveTest, HookCanBeRestarted) {
+  MockMediaKeysListenerDelegate delegate;
+  GlobalMediaKeysListenerWin listener(&delegate);
+
+  // Start listening to create the hook.
+  base::RunLoop hook_registration_loop1;
+  delegate.SetHookRegistrationCallback(hook_registration_loop1.QuitClosure());
+  listener.StartWatchingMediaKeys();
+  hook_registration_loop1.Run();
+
+  // Stop listening to delete the hook.
+  listener.StopWatchingMediaKeys();
+
+  // Start listening to recreate the hook.
+  base::RunLoop hook_registration_loop2;
+  delegate.SetHookRegistrationCallback(hook_registration_loop2.QuitClosure());
+  listener.StartWatchingMediaKeys();
+  hook_registration_loop2.Run();
+
+  // Send a key down event and validate that it was received by the delegate.
+  SendKeyDown(ui::VKEY_MEDIA_PREV_TRACK);
+  delegate.WaitForKeyEvents(1);
+  delegate.ExpectReceivedEvent(/*index=*/0, ui::VKEY_MEDIA_PREV_TRACK,
+                               ET_KEY_PRESSED);
+
+  // Send a key up event and validate that it was received by the delegate.
+  SendKeyUp(ui::VKEY_MEDIA_PREV_TRACK);
+  delegate.WaitForKeyEvents(2);
+  delegate.ExpectReceivedEvent(/*index=*/1, ui::VKEY_MEDIA_PREV_TRACK,
+                               ET_KEY_RELEASED);
+}
+
+}  // namespace ui
\ No newline at end of file
diff --git a/ui/base/accelerators/media_keys_listener.h b/ui/base/accelerators/media_keys_listener.h
index 5ffeafc..82b9b861 100644
--- a/ui/base/accelerators/media_keys_listener.h
+++ b/ui/base/accelerators/media_keys_listener.h
@@ -38,6 +38,14 @@
     // be suppressed.
     virtual MediaKeysHandleResult OnMediaKeysAccelerator(
         const Accelerator& accelerator) = 0;
+
+    // Called after a call to StartWatchingMediaKeys, once the listener is
+    // ready to receive key input. This will not be called after a call to
+    // StartWatchingMediaKeys if the listener was already listening. This may
+    // be called synchronously or asynchronously depending on the underlying
+    // implementation. For the Windows implementation, this is called on a
+    // background thread.
+    virtual void OnStartedWatchingMediaKeys() {}
   };
 
   // Can return nullptr if media keys listening is not implemented.
diff --git a/ui/base/accelerators/media_keys_listener_mac.mm b/ui/base/accelerators/media_keys_listener_mac.mm
index cd595b0..20ae388 100644
--- a/ui/base/accelerators/media_keys_listener_mac.mm
+++ b/ui/base/accelerators/media_keys_listener_mac.mm
@@ -103,6 +103,9 @@
 
   CFRunLoopAddSource(CFRunLoopGetCurrent(), event_tap_source_,
                      kCFRunLoopCommonModes);
+
+  // Notify the delegate that we're ready to receive key events.
+  delegate_->OnStartedWatchingMediaKeys();
 }
 
 void MediaKeysListenerImpl::StopWatchingMediaKeys() {
diff --git a/ui/base/accelerators/media_keys_listener_win.cc b/ui/base/accelerators/media_keys_listener_win.cc
new file mode 100644
index 0000000..5a24b96
--- /dev/null
+++ b/ui/base/accelerators/media_keys_listener_win.cc
@@ -0,0 +1,26 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/accelerators/media_keys_listener.h"
+
+#include "ui/base/accelerators/global_media_keys_listener_win.h"
+
+namespace ui {
+
+std::unique_ptr<MediaKeysListener> MediaKeysListener::Create(
+    MediaKeysListener::Delegate* delegate,
+    MediaKeysListener::Scope scope) {
+  DCHECK(delegate);
+
+  if (scope == Scope::kGlobal) {
+    if (!GlobalMediaKeysListenerWin::has_instance())
+      return std::make_unique<GlobalMediaKeysListenerWin>(delegate);
+    // We shouldn't try to create more than one GlobalMediaKeysListenerWin
+    // instance.
+    NOTREACHED();
+  }
+  return nullptr;
+}
+
+}  // namespace ui
\ No newline at end of file
diff --git a/ui/events/event_dispatcher.h b/ui/events/event_dispatcher.h
index bc9cd5b8..f3fd2e3 100644
--- a/ui/events/event_dispatcher.h
+++ b/ui/events/event_dispatcher.h
@@ -18,11 +18,11 @@
 class EventTarget;
 
 struct EventDispatchDetails {
-  EventDispatchDetails()
-      : dispatcher_destroyed(false),
-        target_destroyed(false) {}
-  bool dispatcher_destroyed;
-  bool target_destroyed;
+  bool dispatcher_destroyed = false;
+  bool target_destroyed = false;
+
+  // Set to true if an EventRewriter discards the event.
+  bool event_discarded = false;
 };
 
 class EVENTS_EXPORT EventDispatcherDelegate {
diff --git a/ui/events/event_source.cc b/ui/events/event_source.cc
index d2c955c..323e8b4 100644
--- a/ui/events/event_source.cc
+++ b/ui/events/event_source.cc
@@ -71,7 +71,9 @@
     status = (*it)->RewriteEvent(*event_for_rewriting, &rewritten_event);
     if (status == EVENT_REWRITE_DISCARD) {
       CHECK(!rewritten_event);
-      return EventDispatchDetails();
+      EventDispatchDetails details;
+      details.event_discarded = true;
+      return details;
     }
     if (status == EVENT_REWRITE_CONTINUE) {
       CHECK(!rewritten_event);
diff --git a/ui/events/win/keyboard_hook_win_base.cc b/ui/events/win/keyboard_hook_win_base.cc
index 1841b06d..dbf5545 100644
--- a/ui/events/win/keyboard_hook_win_base.cc
+++ b/ui/events/win/keyboard_hook_win_base.cc
@@ -15,7 +15,6 @@
 
 KeyboardHookWinBase::~KeyboardHookWinBase() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
   if (!enable_hook_registration_)
     return;
 
diff --git a/ui/file_manager/base/js/volume_manager_types.js b/ui/file_manager/base/js/volume_manager_types.js
index 1ff1cae..571e58d 100644
--- a/ui/file_manager/base/js/volume_manager_types.js
+++ b/ui/file_manager/base/js/volume_manager_types.js
@@ -100,6 +100,9 @@
   // 'Offline'.
   DRIVE_FAKE_ROOT: 'drive_fake_root',
 
+  // 'Add new services' menu item.
+  DEPRECATED_ADD_NEW_SERVICES_MENU: 'deprecated_add_new_services_menu',
+
   // Root for crostini 'Linux files'.
   CROSTINI: 'crostini',
 
@@ -130,27 +133,28 @@
  * @const
  */
 VolumeManagerCommon.RootTypesForUMA = [
-  VolumeManagerCommon.RootType.DOWNLOADS,
-  VolumeManagerCommon.RootType.ARCHIVE,
-  VolumeManagerCommon.RootType.REMOVABLE,
-  VolumeManagerCommon.RootType.DRIVE,
-  VolumeManagerCommon.RootType.TEAM_DRIVES_GRAND_ROOT,
-  VolumeManagerCommon.RootType.TEAM_DRIVE,
-  VolumeManagerCommon.RootType.MTP,
-  VolumeManagerCommon.RootType.PROVIDED,
-  VolumeManagerCommon.RootType.DRIVE_OTHER,
-  VolumeManagerCommon.RootType.DRIVE_OFFLINE,
-  VolumeManagerCommon.RootType.DRIVE_SHARED_WITH_ME,
-  VolumeManagerCommon.RootType.DRIVE_RECENT,
-  VolumeManagerCommon.RootType.MEDIA_VIEW,
-  VolumeManagerCommon.RootType.RECENT,
-  VolumeManagerCommon.RootType.DRIVE_FAKE_ROOT,
-  VolumeManagerCommon.RootType.CROSTINI,
-  VolumeManagerCommon.RootType.ANDROID_FILES,
-  VolumeManagerCommon.RootType.MY_FILES,
-  VolumeManagerCommon.RootType.COMPUTERS_GRAND_ROOT,
-  VolumeManagerCommon.RootType.COMPUTER,
-  VolumeManagerCommon.RootType.EXTERNAL_MEDIA,
+  VolumeManagerCommon.RootType.DOWNLOADS,                         // 0
+  VolumeManagerCommon.RootType.ARCHIVE,                           // 1
+  VolumeManagerCommon.RootType.REMOVABLE,                         // 2
+  VolumeManagerCommon.RootType.DRIVE,                             // 3
+  VolumeManagerCommon.RootType.TEAM_DRIVES_GRAND_ROOT,            // 4
+  VolumeManagerCommon.RootType.TEAM_DRIVE,                        // 5
+  VolumeManagerCommon.RootType.MTP,                               // 6
+  VolumeManagerCommon.RootType.PROVIDED,                          // 7
+  VolumeManagerCommon.RootType.DRIVE_OTHER,                       // 8
+  VolumeManagerCommon.RootType.DRIVE_OFFLINE,                     // 9
+  VolumeManagerCommon.RootType.DRIVE_SHARED_WITH_ME,              // 10
+  VolumeManagerCommon.RootType.DRIVE_RECENT,                      // 11
+  VolumeManagerCommon.RootType.MEDIA_VIEW,                        // 12
+  VolumeManagerCommon.RootType.RECENT,                            // 13
+  VolumeManagerCommon.RootType.DRIVE_FAKE_ROOT,                   // 14
+  VolumeManagerCommon.RootType.DEPRECATED_ADD_NEW_SERVICES_MENU,  // 15
+  VolumeManagerCommon.RootType.CROSTINI,                          // 16
+  VolumeManagerCommon.RootType.ANDROID_FILES,                     // 17
+  VolumeManagerCommon.RootType.MY_FILES,                          // 18
+  VolumeManagerCommon.RootType.COMPUTERS_GRAND_ROOT,              // 19
+  VolumeManagerCommon.RootType.COMPUTER,                          // 20
+  VolumeManagerCommon.RootType.EXTERNAL_MEDIA,                    // 21
 ];
 console.assert(
     Object.keys(VolumeManagerCommon.RootType).length ===
diff --git a/ui/file_manager/base/js/volume_manager_types_unittest.js b/ui/file_manager/base/js/volume_manager_types_unittest.js
index 1e8edc2..05b7de4 100644
--- a/ui/file_manager/base/js/volume_manager_types_unittest.js
+++ b/ui/file_manager/base/js/volume_manager_types_unittest.js
@@ -33,7 +33,9 @@
     // TODO(tapted): Validate this against util.isFakeEntry(..) when
     // files_app_entry_types is moved to file_manager/base.
     if (rootType === VolumeManagerCommon.RootType.RECENT ||
-        rootType === VolumeManagerCommon.RootType.DRIVE_FAKE_ROOT) {
+        rootType === VolumeManagerCommon.RootType.DRIVE_FAKE_ROOT ||
+        rootType ===
+            VolumeManagerCommon.RootType.DEPRECATED_ADD_NEW_SERVICES_MENU) {
       return;
     }
 
diff --git a/ui/file_manager/gallery/css/gallery.css b/ui/file_manager/gallery/css/gallery.css
index 00e604e..41d67ce9 100644
--- a/ui/file_manager/gallery/css/gallery.css
+++ b/ui/file_manager/gallery/css/gallery.css
@@ -934,7 +934,7 @@
   width: 16px;
 }
 
-paper-slider {
+cr-slider {
   width: 172px;
 }
 
diff --git a/ui/file_manager/gallery/gallery.html b/ui/file_manager/gallery/gallery.html
index d0a3c48..9727024 100644
--- a/ui/file_manager/gallery/gallery.html
+++ b/ui/file_manager/gallery/gallery.html
@@ -16,12 +16,12 @@
   <script src="chrome://resources/js/util.js"></script>
 
   <link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html">
+  <link rel="import" href="chrome://resources/cr_elements/cr_slider/cr_slider.html">
   <link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
   <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
   <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
   <link rel="import" href="chrome://resources/polymer/v1_0/paper-progress/paper-progress.html">
   <link rel="import" href="chrome://resources/polymer/v1_0/paper-ripple/paper-ripple.html">
-  <link rel="import" href="chrome://resources/polymer/v1_0/paper-slider/paper-slider.html">
   <link rel="import" href="chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/foreground/elements/files_ripple.html">
   <link rel="import" href="chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/foreground/elements/files_toast.html">
   <link rel="import" href="chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/foreground/elements/files_toggle_ripple.html">
@@ -45,11 +45,11 @@
         --cr-checkbox-size: 14px;
         --cr-checkbox-unchecked-box-color: white;
       }
-      paper-slider {
-        --paper-slider-active-color: white;
-        --paper-slider-container-color: rgba(255, 255, 255, 0.2);
-        --paper-slider-knob-color: white;
-        --paper-slider-secondary-color: transparent;
+      cr-slider {
+        --cr-slider-active-color: white;
+        --cr-slider-container-color: rgba(255, 255, 255, 0.2);
+        --cr-slider-knob-color: white;
+        --cr-slider-secondary-color: transparent;
       }
       paper-progress {
         --paper-progress-container-color: rgba(0, 0, 0, 0.3);
diff --git a/ui/file_manager/gallery/js/image_editor/image_editor_toolbar.js b/ui/file_manager/gallery/js/image_editor/image_editor_toolbar.js
index 60fcdd4..9dc1f6cc 100644
--- a/ui/file_manager/gallery/js/image_editor/image_editor_toolbar.js
+++ b/ui/file_manager/gallery/js/image_editor/image_editor_toolbar.js
@@ -278,14 +278,14 @@
   range.appendChild(label);
 
   var scale = opt_scale || 1;
-  var slider = document.createElement('paper-slider');
+  var slider = document.createElement('cr-slider');
   slider.min = Math.ceil(min * scale);
   slider.max = Math.floor(max * scale);
   slider.value = value * scale;
-  slider.addEventListener('change', function(event) {
+  slider.addEventListener('value-changed', () => {
     if (this.updateCallback_)
       this.updateCallback_(this.getOptions());
-  }.bind(this));
+  });
   range.appendChild(slider);
 
   range.name = name;
@@ -343,7 +343,7 @@
   // Focus the first input on the toolbar.
   if (on) {
     var input = this.container_.querySelector(
-        'button, paper-button, input, paper-slider, cr-input');
+        'button, paper-button, input, cr-slider, cr-input');
     if (input)
       input.focus();
   }
diff --git a/ui/file_manager/integration_tests/gallery/photo_editor.js b/ui/file_manager/integration_tests/gallery/photo_editor.js
index 2e9da5d..81fa46a 100644
--- a/ui/file_manager/integration_tests/gallery/photo_editor.js
+++ b/ui/file_manager/integration_tests/gallery/photo_editor.js
@@ -140,43 +140,50 @@
     var origMetadata = null;
 
     // Click the exposure button.
-    return gallery.waitAndClickElement(appId, buttonQuery).then(function() {
-      // Wait until the edit controls appear.
-      return Promise.all([
-        gallery.waitForElement(appId, '.brightness > paper-slider'),
-        gallery.waitForElement(appId, '.contrast > paper-slider'),
-      ]);
-    }).then(function() {
-      return gallery.callRemoteTestUtil(
-          'changeValue', appId, ['.brightness > paper-slider', 20]);
-    }).then(function() {
-      return gallery.callRemoteTestUtil(
-          'changeValue', appId, ['.contrast > paper-slider', -20]);
-    }).then(function() {
-      return gallery.callRemoteTestUtil('getMetadata', null, [url]);
-    }).then(function(metadata) {
-      origMetadata = metadata;
-
-      // Push the Enter key.
-      return gallery.fakeKeyDown(appId, 'body', 'Enter', false, false, false);
-    }).then(function() {
-      // Wait until the image is updated.
-      return repeatUntil(function() {
-        return gallery.callRemoteTestUtil('getMetadata', null, [url])
+    return gallery.waitAndClickElement(appId, buttonQuery)
+        .then(function() {
+          // Wait until the edit controls appear.
+          return Promise.all([
+            gallery.waitForElement(appId, '.brightness > cr-slider'),
+            gallery.waitForElement(appId, '.contrast > cr-slider'),
+          ]);
+        })
+        .then(function() {
+          return gallery.callRemoteTestUtil(
+              'changeValue', appId, ['.brightness > cr-slider', 20]);
+        })
+        .then(function() {
+          return gallery.callRemoteTestUtil(
+              'changeValue', appId, ['.contrast > cr-slider', -20]);
+        })
+        .then(function() {
+          return gallery.callRemoteTestUtil('getMetadata', null, [url]);
+        })
         .then(function(metadata) {
-          if (origMetadata.modificationTime != metadata.modificationTime) {
-            return true;
-          } else {
-            return pending(
-                '%s is not updated. ' +
-                    'First last modified: %s, Second last modified: %s.',
-                url,
-                origMetadata.modificationTime,
-                metadata.modificationTime);
-          }
+          origMetadata = metadata;
+
+          // Push the Enter key.
+          return gallery.fakeKeyDown(
+              appId, 'body', 'Enter', false, false, false);
+        })
+        .then(function() {
+          // Wait until the image is updated.
+          return repeatUntil(function() {
+            return gallery.callRemoteTestUtil('getMetadata', null, [url])
+                .then(function(metadata) {
+                  if (origMetadata.modificationTime !=
+                      metadata.modificationTime) {
+                    return true;
+                  } else {
+                    return pending(
+                        '%s is not updated. First ' +
+                            'last modified: %s, Second last modified: %s.',
+                        url, origMetadata.modificationTime,
+                        metadata.modificationTime);
+                  }
+                });
+          });
         });
-      });
-    });
   });
 }
 
diff --git a/ui/views/controls/menu/menu_item_view.cc b/ui/views/controls/menu/menu_item_view.cc
index 48b6a2e..ebe01b0 100644
--- a/ui/views/controls/menu/menu_item_view.cc
+++ b/ui/views/controls/menu/menu_item_view.cc
@@ -619,6 +619,10 @@
     View* child = child_at(0);
     gfx::Size size = child->GetPreferredSize();
     child->SetBounds(0, GetTopMargin(), size.width(), size.height());
+    // TODO(crbug/913998): this is a hack. We should change
+    // ExtensionToolbarMenuView so that it does not move itself when laid out,
+    // and accomplish the same thing via insets or similar.
+    child->Layout();
   } else {
     // Child views are laid out right aligned and given the full height. To
     // right align start with the last view and progress to the first.
diff --git a/ui/views/controls/webview/webview.cc b/ui/views/controls/webview/webview.cc
index 3d6a736..639fb34 100644
--- a/ui/views/controls/webview/webview.cc
+++ b/ui/views/controls/webview/webview.cc
@@ -11,6 +11,7 @@
 #include "content/public/browser/browser_accessibility_state.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
@@ -414,10 +415,7 @@
 void WebView::NotifyAccessibilityWebContentsChanged() {
   content::RenderFrameHost* rfh =
       web_contents() ? web_contents()->GetMainFrame() : nullptr;
-  if (rfh)
-    child_ax_tree_id_ = rfh->GetAXTreeID();
-  else
-    child_ax_tree_id_ = ui::AXTreeIDUnknown();
+  child_ax_tree_id_ = rfh ? rfh->GetAXTreeID() : ui::AXTreeIDUnknown();
   NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged, false);
 }
 
diff --git a/ui/webui/resources/cr_elements/cr_slider/cr_slider.html b/ui/webui/resources/cr_elements/cr_slider/cr_slider.html
index 1bf1ad04..9ba11dc 100644
--- a/ui/webui/resources/cr_elements/cr_slider/cr_slider.html
+++ b/ui/webui/resources/cr_elements/cr_slider/cr_slider.html
@@ -15,6 +15,7 @@
         --cr-slider-position-transition: 80ms ease;
         -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
         cursor: default;
+        outline: none;
         user-select: none;
       }
 
@@ -37,7 +38,7 @@
       }
 
       #barContainer {
-        border-top-color: var(--google-blue-600-opacity-24);
+        border-top-color: var(--cr-slider-container-color, var(--google-blue-600-opacity-24));
         height: var(--cr-slider-bar-height);
         margin: 0 16px;
         position: absolute;
@@ -89,7 +90,7 @@
       }
 
       paper-ripple {
-        color: var(--google-blue-600);
+        color: var(--cr-slider-knob-color, var(--google-blue-600));
         height: 32px;
         left: -11px;
         pointer-events: none;
@@ -206,8 +207,7 @@
         </div>
       </div>
       <div id="knobContainer">
-        <div id="knob" tabindex="0" on-transitionend="onKnobTransitionEnd_">
-        </div>
+        <div id="knob" on-transitionend="onKnobTransitionEnd_"></div>
       </div>
       <div id="labelContainer" aria-label="[[label_]]">
         <div id="label">[[label_]]</div>
diff --git a/ui/webui/resources/cr_elements/cr_slider/cr_slider.js b/ui/webui/resources/cr_elements/cr_slider/cr_slider.js
index c08f454c..35214d1 100644
--- a/ui/webui/resources/cr_elements/cr_slider/cr_slider.js
+++ b/ui/webui/resources/cr_elements/cr_slider/cr_slider.js
@@ -265,7 +265,8 @@
 
     /** @private */
     onDisabledChanged_: function() {
-      this.$.knob.setAttribute('tabindex', this.disabled_ ? '-1' : '0');
+      this.setAttribute('tabindex', this.disabled_ ? -1 : 0);
+      this.$.knob.setAttribute('tabindex', this.disabled_ ? -1 : 0);
       this.blur();
     },
 
diff --git a/webrunner/fidl/web/context.fidl b/webrunner/fidl/web/context.fidl
index ee90a86..7de9089e 100644
--- a/webrunner/fidl/web/context.fidl
+++ b/webrunner/fidl/web/context.fidl
@@ -7,8 +7,8 @@
 // Manages browsing state (e.g. LocalStorage, cookies, etc) associated with
 // a set of Frames.
 interface Context {
-   // Creates a new frame under this Context.
-   //
-   // |frame|: An interface request that will be bound to the created Frame.
-   1: CreateFrame(request<Frame> frame);
+  // Creates a new frame under this Context.
+  //
+  // |frame|: An interface request that will be bound to the created Frame.
+  CreateFrame(request<Frame> frame);
 };
diff --git a/webrunner/fidl/web/context_provider.fidl b/webrunner/fidl/web/context_provider.fidl
index 74a5a44..9559c2dc 100644
--- a/webrunner/fidl/web/context_provider.fidl
+++ b/webrunner/fidl/web/context_provider.fidl
@@ -8,12 +8,12 @@
 // Context resources.
 [Discoverable]
 interface ContextProvider {
-   // Creates a new browser Context whose state is wholly independent and
-   // isolated from other Contexts.
-   //
-   // context: An interface request which will receive a bound Context
-   //          service.
-   1: Create(CreateContextParams params, request<Context> context);
+  // Creates a new browser Context whose state is wholly independent and
+  // isolated from other Contexts.
+  //
+  // context: An interface request which will receive a bound Context
+  //          service.
+  Create(CreateContextParams params, request<Context> context);
 };
 
 struct CreateContextParams {
diff --git a/webrunner/fidl/web/frame.fidl b/webrunner/fidl/web/frame.fidl
index 4b615b3c..e1cf627 100644
--- a/webrunner/fidl/web/frame.fidl
+++ b/webrunner/fidl/web/frame.fidl
@@ -27,14 +27,14 @@
   // the view tree.
   //
   // |view_token|: Token for the new view.
-  4: CreateView2(handle<eventpair> view_token,
+  CreateView2(handle<eventpair> view_token,
                  request<fuchsia.sys.ServiceProvider>? incoming_services,
                  fuchsia.sys.ServiceProvider? outgoing_services);
 
   // Deprecated.
   // TODO(crbug.com/899348): Update all code to use CreateView2()
   // and remove CreateView().
-  1: CreateView(request<fuchsia.ui.viewsv1token.ViewOwner> view_owner,
+  CreateView(request<fuchsia.ui.viewsv1token.ViewOwner> view_owner,
                 request<fuchsia.sys.ServiceProvider>? services);
 
   // Returns an interface through which the frame may be navigated to
@@ -42,7 +42,7 @@
   //
   // |view_provider|: An interface request for the Frame's
   // NavigationController.
-  2: GetNavigationController(request<NavigationController> controller);
+  GetNavigationController(request<NavigationController> controller);
 
   // Executes |script| in the frame if the frame's URL has an origin which
   // matches entries in |origins|.
@@ -65,7 +65,7 @@
   // Returns |true| if the script was executed, |false| if the script was
   // rejected due to injection being blocked by the parent Context, or because
   // the script's text encoding was invalid.
-  3: ExecuteJavaScript(
+  ExecuteJavaScript(
      vector<string> origins, fuchsia.mem.Buffer script, ExecuteMode mode) ->
      (bool success);
 
@@ -78,18 +78,18 @@
   // for more details on how the target origin policy is applied.
   //
   // Returns |false| if |message| is invalid or |targetOrigin| is missing.
-  5: PostMessage(WebMessage message, string targetOrigin) -> (bool success);
+  PostMessage(WebMessage message, string targetOrigin) -> (bool success);
 
   // Sets the observer for handling page navigation events.
   //
   // |observer|: The observer to use. Unregisters any existing observers
   //             if null.
-  100: SetNavigationEventObserver(NavigationEventObserver? observer);
+  SetNavigationEventObserver(NavigationEventObserver? observer);
 
   // If set to a value other than NONE, allows web content to log messages
   // to the system logger using console.log(), console.info(), console.warn(),
   // and console.error().
-  101: SetJavaScriptLogLevel(LogLevel level);
+  SetJavaScriptLogLevel(LogLevel level);
 };
 
 struct WebMessage {
@@ -118,13 +118,13 @@
 // is torn down.
 interface MessagePort {
   // Sends a WebMessage to the peer.
-  1: PostMessage(WebMessage message) -> (bool success);
+  PostMessage(WebMessage message) -> (bool success);
 
   // Asynchronously reads the next message from the channel.
   // The client should invoke the callback when it is ready to process
   // another message.
   // Unreceived messages are buffered on the sender's side and bounded
   // by its available resources.
-  2: ReceiveMessage() -> (WebMessage message);
+  ReceiveMessage() -> (WebMessage message);
 };
 
diff --git a/webrunner/fidl/web/navigation_controller.fidl b/webrunner/fidl/web/navigation_controller.fidl
index b781bf0..5c18c2b 100644
--- a/webrunner/fidl/web/navigation_controller.fidl
+++ b/webrunner/fidl/web/navigation_controller.fidl
@@ -12,16 +12,16 @@
   // |url|:    The address to navigate to.
   // |params|: Additional parameters that affect how the resource will be
   //           loaded (e.g. cookies, HTTP headers, etc.)
-  1: LoadUrl(string url, LoadUrlParams? params);
+  LoadUrl(string url, LoadUrlParams? params);
 
-  50: GoBack();
-  51: GoForward();
-  52: Stop();
-  53: Reload(ReloadType type);
+  GoBack();
+  GoForward();
+  Stop();
+  Reload(ReloadType type);
 
   // Returns information for the currently visible content regardless of
   // loading state, or a null entry if no content is being displayed.
-  100: GetVisibleEntry() -> (NavigationEntry? entry);
+  GetVisibleEntry() -> (NavigationEntry? entry);
 };
 
 // Additional parameters for modifying the behavior of LoadUrl().
diff --git a/webrunner/fidl/web/navigation_event_observer.fidl b/webrunner/fidl/web/navigation_event_observer.fidl
index a0a7b70c..a724b629 100644
--- a/webrunner/fidl/web/navigation_event_observer.fidl
+++ b/webrunner/fidl/web/navigation_event_observer.fidl
@@ -20,6 +20,6 @@
   // creation or the last acknowledgement callback, whichever occurred later.
   // |change| will contain all the differences in navigation state since the
   // last acknowledgement.
-  1: OnNavigationStateChanged(NavigationEvent change) -> ();
+  OnNavigationStateChanged(NavigationEvent change) -> ();
 };