diff --git a/DEPS b/DEPS
index 9436e20..dd0cdcf 100644
--- a/DEPS
+++ b/DEPS
@@ -79,11 +79,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '66abdf6658969285fa64eadfaf4de4bdbad09332',
+  'skia_revision': 'b537879c7214efd87840c9a7267ab3b3facda873',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'dc2d3bb9711effb349df58af26c49169aa019121',
+  'v8_revision': '0cf325d677a6d04e2bd04834eaa7dc2a11b72ed8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -91,7 +91,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': 'e8a93c6ed6feda4e0f22bd034cf95dd4aae3618d',
+  'angle_revision': '33140409810f244abfd85231c44c347c6ae02c86',
   # 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.
@@ -103,7 +103,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': '5a7e330ef5e013e5df5fe771d3901ff890aa9731',
+  'pdfium_revision': '3baef5c6daf58cec2df193714b5727802d0bd42e',
   # 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.
@@ -135,7 +135,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': '8f3d6b77acab8e35a062745097cd2c4d1c9a4de6',
+  'catapult_revision': 'b90b97cf8dec1060b14197b68a7c862bab7e4ed5',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -657,7 +657,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '3c1cb0203b6cfc10389e85a350b2ea6ca29d01ce',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '6d72c3258ff5b9a887fbf23f70dd60dddb4dfbf1', # commit position 21742
+    Var('webrtc_git') + '/src.git' + '@' + 'a5aa68b73f1d5407ed83c2772ee2b0edac69ac1b', # commit position 21742
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc
index 9999713..6d5e24f 100644
--- a/android_webview/browser/aw_browser_context.cc
+++ b/android_webview/browser/aw_browser_context.cc
@@ -42,7 +42,7 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "net/proxy_resolution/proxy_config_service_android.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 
 using base::FilePath;
 using content::BrowserThread;
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index 17b10518..6ec2405 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -691,6 +691,20 @@
                                                auth_required_callback);
 }
 
+bool AwContentBrowserClient::HandleExternalProtocol(
+    const GURL& url,
+    content::ResourceRequestInfo::WebContentsGetter web_contents_getter,
+    int child_id,
+    content::NavigationUIData* navigation_data,
+    bool is_main_frame,
+    ui::PageTransition page_transition,
+    bool has_user_gesture) {
+  // The AwURLRequestJobFactory implementation should ensure this method never
+  // gets called.
+  NOTREACHED();
+  return false;
+}
+
 // static
 void AwContentBrowserClient::DisableCreatingTaskScheduler() {
   g_should_create_task_scheduler = false;
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h
index b79c289e..3989eac 100644
--- a/android_webview/browser/aw_content_browser_client.h
+++ b/android_webview/browser/aw_content_browser_client.h
@@ -176,6 +176,14 @@
       bool first_auth_attempt,
       const base::Callback<void(const base::Optional<net::AuthCredentials>&)>&
           auth_required_callback) override;
+  bool HandleExternalProtocol(
+      const GURL& url,
+      content::ResourceRequestInfo::WebContentsGetter web_contents_getter,
+      int child_id,
+      content::NavigationUIData* navigation_data,
+      bool is_main_frame,
+      ui::PageTransition page_transition,
+      bool has_user_gesture) override;
 
   static void DisableCreatingTaskScheduler();
 
diff --git a/android_webview/browser/net/aw_url_request_context_getter.cc b/android_webview/browser/net/aw_url_request_context_getter.cc
index cd4e393..3db1952 100644
--- a/android_webview/browser/net/aw_url_request_context_getter.cc
+++ b/android_webview/browser/net/aw_url_request_context_getter.cc
@@ -51,7 +51,7 @@
 #include "net/log/net_log_capture_mode.h"
 #include "net/log/net_log_util.h"
 #include "net/net_features.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/socket/next_proto.h"
 #include "net/ssl/channel_id_service.h"
 #include "net/ssl/ssl_config.h"
diff --git a/android_webview/browser/net/aw_url_request_context_getter_unittest.cc b/android_webview/browser/net/aw_url_request_context_getter_unittest.cc
index 2f314748..b53857bd 100644
--- a/android_webview/browser/net/aw_url_request_context_getter_unittest.cc
+++ b/android_webview/browser/net/aw_url_request_context_getter_unittest.cc
@@ -16,7 +16,7 @@
 #include "net/base/net_errors.h"
 #include "net/log/net_log.h"
 #include "net/proxy_resolution/proxy_config_service.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/ssl/ssl_config.h"
 #include "net/ssl/ssl_config_service.h"
 #include "net/test/url_request/url_request_failed_job.h"
diff --git a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc
index 72afa21..74c56c9 100644
--- a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc
+++ b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc
@@ -404,15 +404,6 @@
                  user_agent, content_disposition, mime_type, content_length));
 }
 
-bool AwResourceDispatcherHostDelegate::HandleExternalProtocol(
-    const GURL& url,
-    content::ResourceRequestInfo* info) {
-  // The AwURLRequestJobFactory implementation should ensure this method never
-  // gets called.
-  NOTREACHED();
-  return false;
-}
-
 void AwResourceDispatcherHostDelegate::OnResponseStarted(
     net::URLRequest* request,
     content::ResourceContext* resource_context,
diff --git a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h
index abbee78..790c0dd 100644
--- a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h
+++ b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h
@@ -42,8 +42,6 @@
                         bool is_new_request,
                         std::vector<std::unique_ptr<content::ResourceThrottle>>*
                             throttles) override;
-  bool HandleExternalProtocol(const GURL& url,
-                              content::ResourceRequestInfo* info) override;
   void OnResponseStarted(net::URLRequest* request,
                          content::ResourceContext* resource_context,
                          network::ResourceResponse* response) override;
diff --git a/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java b/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java
index 9672e3a3..53c53b1 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java
@@ -149,8 +149,8 @@
 
     private static void tryObtainingDataDirLock() {
         // Many existing apps rely on this even though it's known to be unsafe.
-        // Make it fatal for apps that target P or higher.
-        boolean dieOnFailure = BuildInfo.targetsAtLeastP();
+        // Make it fatal when on P for apps that target P or higher
+        boolean dieOnFailure = BuildInfo.isAtLeastP() && BuildInfo.targetsAtLeastP();
 
         StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
         try {
diff --git a/android_webview/support_library/boundary_interfaces/BUILD.gn b/android_webview/support_library/boundary_interfaces/BUILD.gn
index bc1fcb3a..dda7b79 100644
--- a/android_webview/support_library/boundary_interfaces/BUILD.gn
+++ b/android_webview/support_library/boundary_interfaces/BUILD.gn
@@ -8,12 +8,14 @@
 android_library("boundary_interface_java") {
   java_files = [
     "src/org/chromium/support_lib_boundary/StaticsBoundaryInterface.java",
+    "src/org/chromium/support_lib_boundary/SupportLibraryInfoBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/VisualStateCallbackBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/WebSettingsBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/WebViewProviderBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/WebViewProviderFactoryBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/WebkitToCompatConverterBoundaryInterface.java",
     "src/org/chromium/support_lib_boundary/util/BoundaryInterfaceReflectionUtil.java",
+    "src/org/chromium/support_lib_boundary/util/Features.java",
   ]
 
   proguard_configs = [ "proguard.flags" ]
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/SupportLibraryInfoBoundaryInterface.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/SupportLibraryInfoBoundaryInterface.java
new file mode 100644
index 0000000..11a141f
--- /dev/null
+++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/SupportLibraryInfoBoundaryInterface.java
@@ -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.
+
+package org.chromium.support_lib_boundary;
+
+/**
+ * Contains information about the WebView support library side, e.g. which features are supported on
+ * that side.
+ * This is passed to the WebView APK code on support library initialization.
+ */
+public interface SupportLibraryInfoBoundaryInterface { String[] getSupportedFeatures(); }
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewProviderFactoryBoundaryInterface.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewProviderFactoryBoundaryInterface.java
index e868f7a..094e2cf 100644
--- a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewProviderFactoryBoundaryInterface.java
+++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewProviderFactoryBoundaryInterface.java
@@ -14,4 +14,5 @@
     /* SupportLibraryWebViewChromium */ InvocationHandler createWebView(WebView webview);
     /* SupportLibWebkitToCompatConverter */ InvocationHandler getWebkitToCompatConverter();
     /* StaticsAdapter */ InvocationHandler getStatics();
+    String[] getSupportedFeatures();
 }
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java
new file mode 100644
index 0000000..d74ea55
--- /dev/null
+++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.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.support_lib_boundary.util;
+
+/**
+ * Class containing all the features the support library can support.
+ * This class lives in the boundary interface directory so that the Android Support Library and
+ * Chromium can share its definition.
+ */
+public class Features {
+    // This class just contains constants representing features.
+    private Features() {}
+
+    // WebViewCompat.postVisualStateCallback
+    public static final String VISUAL_STATE_CALLBACK = "VISUAL_STATE_CALLBACK";
+}
diff --git a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibReflectionUtil.java b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibReflectionUtil.java
index c121439..84b9304 100644
--- a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibReflectionUtil.java
+++ b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibReflectionUtil.java
@@ -20,8 +20,10 @@
      * Changing the signature of this method will break existing WebView Support Library versions!
      */
     @UsedByReflection("WebView Support Library")
-    public static InvocationHandler createWebViewProviderFactory() {
-        final SupportLibWebViewChromiumFactory factory = new SupportLibWebViewChromiumFactory();
+    public static InvocationHandler createWebViewProviderFactory(
+            /* SupportLibraryInfo */ InvocationHandler supportLibraryInfo) {
+        final SupportLibWebViewChromiumFactory factory =
+                new SupportLibWebViewChromiumFactory(supportLibraryInfo);
         return BoundaryInterfaceReflectionUtil.createInvocationHandlerFor(factory);
     }
 }
diff --git a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java
index 2f81bbd..ff175fcf 100644
--- a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java
+++ b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java
@@ -15,8 +15,10 @@
 import com.android.webview.chromium.WebkitToSharedGlueConverter;
 
 import org.chromium.support_lib_boundary.StaticsBoundaryInterface;
+import org.chromium.support_lib_boundary.SupportLibraryInfoBoundaryInterface;
 import org.chromium.support_lib_boundary.WebViewProviderFactoryBoundaryInterface;
 import org.chromium.support_lib_boundary.util.BoundaryInterfaceReflectionUtil;
+import org.chromium.support_lib_boundary.util.Features;
 
 import java.lang.reflect.InvocationHandler;
 import java.util.List;
@@ -28,14 +30,23 @@
     // SupportLibWebkitToCompatConverterAdapter
     private final InvocationHandler mCompatConverterAdapter;
     private final WebViewChromiumAwInit mAwInit;
+    private final String[] mSupportLibrarySupportedFeatures;
+    private final String[] mWebViewSupportedFeatures =
+            new String[] {Features.VISUAL_STATE_CALLBACK};
 
     // Initialization guarded by mAwInit.getLock()
     private InvocationHandler mStatics;
 
-    public SupportLibWebViewChromiumFactory() {
+    public SupportLibWebViewChromiumFactory(
+            /* SupportLibraryInfo */ InvocationHandler supportLibraryInfo) {
         mCompatConverterAdapter = BoundaryInterfaceReflectionUtil.createInvocationHandlerFor(
                 new SupportLibWebkitToCompatConverterAdapter());
         mAwInit = WebkitToSharedGlueConverter.getGlobalAwInit();
+        mSupportLibrarySupportedFeatures =
+                BoundaryInterfaceReflectionUtil
+                        .castToSuppLibClass(
+                                SupportLibraryInfoBoundaryInterface.class, supportLibraryInfo)
+                        .getSupportedFeatures();
     }
 
     @Override
@@ -85,4 +96,9 @@
         }
         return mStatics;
     }
+
+    @Override
+    public String[] getSupportedFeatures() {
+        return mWebViewSupportedFeatures;
+    }
 }
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 77732ff3..50a014d 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -75,6 +75,8 @@
     "accessibility/touch_accessibility_enabler.h",
     "accessibility/touch_exploration_controller.cc",
     "accessibility/touch_exploration_controller.h",
+    "accessibility/touch_exploration_manager.cc",
+    "accessibility/touch_exploration_manager.h",
     "animation/animation_change_type.h",
     "app_list/app_list_controller_impl.cc",
     "app_list/app_list_controller_impl.h",
@@ -91,8 +93,6 @@
     "ash_export.h",
     "ash_layout_constants.cc",
     "ash_layout_constants.h",
-    "ash_touch_exploration_manager_chromeos.cc",
-    "ash_touch_exploration_manager_chromeos.h",
     "ash_view_ids.h",
     "autoclick/autoclick_controller.cc",
     "autoclick/autoclick_controller.h",
@@ -1406,10 +1406,10 @@
     "accessibility/accessibility_panel_layout_manager_unittest.cc",
     "accessibility/touch_accessibility_enabler_unittest.cc",
     "accessibility/touch_exploration_controller_unittest.cc",
+    "accessibility/touch_exploration_manager_unittest.cc",
     "app_list/app_list_presenter_delegate_unittest.cc",
     "app_list/model/app_list_item_list_unittest.cc",
     "app_list/model/app_list_model_unittest.cc",
-    "ash_touch_exploration_manager_chromeos_unittest.cc",
     "autoclick/autoclick_unittest.cc",
     "detachable_base/detachable_base_handler_unittest.cc",
     "detachable_base/detachable_base_notification_controller_unittest.cc",
diff --git a/ash/ash_touch_exploration_manager_chromeos.cc b/ash/accessibility/touch_exploration_manager.cc
similarity index 81%
rename from ash/ash_touch_exploration_manager_chromeos.cc
rename to ash/accessibility/touch_exploration_manager.cc
index 9306f6308..d2efb99 100644
--- a/ash/ash_touch_exploration_manager_chromeos.cc
+++ b/ash/accessibility/touch_exploration_manager.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/ash_touch_exploration_manager_chromeos.h"
+#include "ash/accessibility/touch_exploration_manager.h"
 
 #include <memory>
 #include <vector>
@@ -34,7 +34,7 @@
 
 }  // namespace
 
-AshTouchExplorationManager::AshTouchExplorationManager(
+TouchExplorationManager::TouchExplorationManager(
     RootWindowController* root_window_controller)
     : root_window_controller_(root_window_controller),
       audio_handler_(chromeos::CrasAudioHandler::Get()),
@@ -46,7 +46,7 @@
   UpdateTouchExplorationState();
 }
 
-AshTouchExplorationManager::~AshTouchExplorationManager() {
+TouchExplorationManager::~TouchExplorationManager() {
   // TODO(jamescook): Clean up shutdown order so this check isn't needed.
   if (Shell::Get()->accessibility_controller())
     Shell::Get()->accessibility_controller()->RemoveObserver(this);
@@ -55,12 +55,12 @@
   Shell::Get()->RemoveShellObserver(this);
 }
 
-void AshTouchExplorationManager::OnAccessibilityStatusChanged(
+void TouchExplorationManager::OnAccessibilityStatusChanged(
     AccessibilityNotificationVisibility notify) {
   UpdateTouchExplorationState();
 }
 
-void AshTouchExplorationManager::SetOutputLevel(int volume) {
+void TouchExplorationManager::SetOutputLevel(int volume) {
   if (volume > 0) {
     if (audio_handler_->IsOutputMuted()) {
       audio_handler_->SetOutputMute(false);
@@ -72,12 +72,12 @@
     audio_handler_->SetOutputMute(true);
 }
 
-void AshTouchExplorationManager::SilenceSpokenFeedback() {
+void TouchExplorationManager::SilenceSpokenFeedback() {
   if (GetA11yController()->IsSpokenFeedbackEnabled())
     GetA11yController()->SilenceSpokenFeedback();
 }
 
-void AshTouchExplorationManager::PlayVolumeAdjustEarcon() {
+void TouchExplorationManager::PlayVolumeAdjustEarcon() {
   if (!VolumeAdjustSoundEnabled())
     return;
   if (!audio_handler_->IsOutputMuted() &&
@@ -86,24 +86,24 @@
   }
 }
 
-void AshTouchExplorationManager::PlayPassthroughEarcon() {
+void TouchExplorationManager::PlayPassthroughEarcon() {
   GetA11yController()->PlayEarcon(chromeos::SOUND_PASSTHROUGH);
 }
 
-void AshTouchExplorationManager::PlayExitScreenEarcon() {
+void TouchExplorationManager::PlayExitScreenEarcon() {
   GetA11yController()->PlayEarcon(chromeos::SOUND_EXIT_SCREEN);
 }
 
-void AshTouchExplorationManager::PlayEnterScreenEarcon() {
+void TouchExplorationManager::PlayEnterScreenEarcon() {
   GetA11yController()->PlayEarcon(chromeos::SOUND_ENTER_SCREEN);
 }
 
-void AshTouchExplorationManager::HandleAccessibilityGesture(
+void TouchExplorationManager::HandleAccessibilityGesture(
     ax::mojom::Gesture gesture) {
   GetA11yController()->HandleAccessibilityGesture(gesture);
 }
 
-void AshTouchExplorationManager::OnDisplayMetricsChanged(
+void TouchExplorationManager::OnDisplayMetricsChanged(
     const display::Display& display,
     uint32_t changed_metrics) {
   const display::Display this_display =
@@ -113,15 +113,15 @@
     UpdateTouchExplorationState();
 }
 
-void AshTouchExplorationManager::OnTwoFingerTouchStart() {
+void TouchExplorationManager::OnTwoFingerTouchStart() {
   GetA11yController()->OnTwoFingerTouchStart();
 }
 
-void AshTouchExplorationManager::OnTwoFingerTouchStop() {
+void TouchExplorationManager::OnTwoFingerTouchStop() {
   GetA11yController()->OnTwoFingerTouchStop();
 }
 
-void AshTouchExplorationManager::PlaySpokenFeedbackToggleCountdown(
+void TouchExplorationManager::PlaySpokenFeedbackToggleCountdown(
     int tick_count) {
   GetA11yController()->ShouldToggleSpokenFeedbackViaTouch(base::BindOnce(
       [](int tick_count, bool should_toggle) {
@@ -132,11 +132,11 @@
       tick_count));
 }
 
-void AshTouchExplorationManager::PlayTouchTypeEarcon() {
+void TouchExplorationManager::PlayTouchTypeEarcon() {
   GetA11yController()->PlayEarcon(chromeos::SOUND_TOUCH_TYPE);
 }
 
-void AshTouchExplorationManager::ToggleSpokenFeedback() {
+void TouchExplorationManager::ToggleSpokenFeedback() {
   GetA11yController()->ShouldToggleSpokenFeedbackViaTouch(
       base::BindOnce([](bool should_toggle) {
         if (!should_toggle)
@@ -147,14 +147,14 @@
       }));
 }
 
-void AshTouchExplorationManager::OnWindowActivated(
+void TouchExplorationManager::OnWindowActivated(
     ::wm::ActivationChangeObserver::ActivationReason reason,
     aura::Window* gained_active,
     aura::Window* lost_active) {
   UpdateTouchExplorationState();
 }
 
-void AshTouchExplorationManager::SetTouchAccessibilityAnchorPoint(
+void TouchExplorationManager::SetTouchAccessibilityAnchorPoint(
     const gfx::Point& anchor_point) {
   if (touch_exploration_controller_) {
     touch_exploration_controller_->SetTouchAccessibilityAnchorPoint(
@@ -162,17 +162,17 @@
   }
 }
 
-void AshTouchExplorationManager::OnKeyboardVisibleBoundsChanged(
+void TouchExplorationManager::OnKeyboardVisibleBoundsChanged(
     const gfx::Rect& new_bounds) {
   UpdateTouchExplorationState();
 }
 
-void AshTouchExplorationManager::OnKeyboardClosed() {
+void TouchExplorationManager::OnKeyboardClosed() {
   keyboard_observer_.RemoveAll();
   UpdateTouchExplorationState();
 }
 
-void AshTouchExplorationManager::OnVirtualKeyboardStateChanged(
+void TouchExplorationManager::OnVirtualKeyboardStateChanged(
     bool activated,
     aura::Window* root_window) {
   UpdateKeyboardObserverFromStateChanged(
@@ -180,7 +180,7 @@
       &keyboard_observer_);
 }
 
-void AshTouchExplorationManager::UpdateTouchExplorationState() {
+void TouchExplorationManager::UpdateTouchExplorationState() {
   // See crbug.com/603745 for more details.
   const bool pass_through_surface =
       wm::GetActiveWindow() &&
@@ -230,7 +230,7 @@
   }
 }
 
-bool AshTouchExplorationManager::VolumeAdjustSoundEnabled() {
+bool TouchExplorationManager::VolumeAdjustSoundEnabled() {
   return !base::CommandLine::ForCurrentProcess()->HasSwitch(
       chromeos::switches::kDisableVolumeAdjustSound);
 }
diff --git a/ash/ash_touch_exploration_manager_chromeos.h b/ash/accessibility/touch_exploration_manager.h
similarity index 84%
rename from ash/ash_touch_exploration_manager_chromeos.h
rename to ash/accessibility/touch_exploration_manager.h
index fd39c1e..fbc947c 100644
--- a/ash/ash_touch_exploration_manager_chromeos.h
+++ b/ash/accessibility/touch_exploration_manager.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef ASH_TOUCH_EXPLORATION_MANAGER_CHROMEOS_H_
-#define ASH_TOUCH_EXPLORATION_MANAGER_CHROMEOS_H_
+#ifndef ASH_ACCESSIBILITY_TOUCH_EXPLORATION_MANAGER_H_
+#define ASH_ACCESSIBILITY_TOUCH_EXPLORATION_MANAGER_H_
 
 #include <memory>
 
@@ -29,11 +29,14 @@
 namespace ash {
 class RootWindowController;
 
-// Responsible for initializing TouchExplorationController when spoken
-// feedback is on for ChromeOS only. This class implements
-// TouchExplorationControllerDelegate which allows touch gestures to manipulate
-// the system.
-class ASH_EXPORT AshTouchExplorationManager
+// Responsible for initializing TouchExplorationController when spoken feedback
+// is on. Implements TouchExplorationControllerDelegate which allows touch
+// gestures to manipulate the system.
+//
+// TODO(jamescook): Move the TouchExplorationControllerDelegate methods into
+// TouchExplorationController. I suspect the delegate was added to support ash
+// on Windows, which we don't ship anymore.
+class ASH_EXPORT TouchExplorationManager
     : public AccessibilityObserver,
       public TouchExplorationControllerDelegate,
       public TouchAccessibilityEnablerDelegate,
@@ -42,9 +45,9 @@
       public keyboard::KeyboardControllerObserver,
       public ShellObserver {
  public:
-  explicit AshTouchExplorationManager(
+  explicit TouchExplorationManager(
       RootWindowController* root_window_controller);
-  ~AshTouchExplorationManager() override;
+  ~TouchExplorationManager() override;
 
   // AccessibilityObserver overrides:
   void OnAccessibilityStatusChanged(
@@ -100,7 +103,7 @@
                  keyboard::KeyboardControllerObserver>
       keyboard_observer_;
 
-  DISALLOW_COPY_AND_ASSIGN(AshTouchExplorationManager);
+  DISALLOW_COPY_AND_ASSIGN(TouchExplorationManager);
 };
 
 }  // namespace ash
diff --git a/ash/ash_touch_exploration_manager_chromeos_unittest.cc b/ash/accessibility/touch_exploration_manager_unittest.cc
similarity index 83%
rename from ash/ash_touch_exploration_manager_chromeos_unittest.cc
rename to ash/accessibility/touch_exploration_manager_unittest.cc
index 8348411..3263aa73 100644
--- a/ash/ash_touch_exploration_manager_chromeos_unittest.cc
+++ b/ash/accessibility/touch_exploration_manager_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/ash_touch_exploration_manager_chromeos.h"
+#include "ash/accessibility/touch_exploration_manager.h"
 
 #include "ash/accessibility/accessibility_controller.h"
 #include "ash/accessibility/test_accessibility_controller_client.h"
@@ -14,11 +14,11 @@
 
 namespace ash {
 
-using AshTouchExplorationManagerTest = AshTestBase;
+using TouchExplorationManagerTest = AshTestBase;
 
-TEST_F(AshTouchExplorationManagerTest, AdjustSound) {
+TEST_F(TouchExplorationManagerTest, AdjustSound) {
   RootWindowController* controller = Shell::GetPrimaryRootWindowController();
-  AshTouchExplorationManager touch_exploration_manager(controller);
+  TouchExplorationManager touch_exploration_manager(controller);
   chromeos::CrasAudioHandler* audio_handler = chromeos::CrasAudioHandler::Get();
 
   touch_exploration_manager.SetOutputLevel(10);
@@ -38,9 +38,9 @@
   EXPECT_TRUE(audio_handler->IsOutputMuted());
 }
 
-TEST_F(AshTouchExplorationManagerTest, HandleAccessibilityGesture) {
+TEST_F(TouchExplorationManagerTest, HandleAccessibilityGesture) {
   RootWindowController* controller = Shell::GetPrimaryRootWindowController();
-  AshTouchExplorationManager touch_exploration_manager(controller);
+  TouchExplorationManager touch_exploration_manager(controller);
   AccessibilityController* a11y_controller =
       Shell::Get()->accessibility_controller();
   TestAccessibilityControllerClient client;
diff --git a/ash/ash_constants.cc b/ash/ash_constants.cc
index 58d512d..a48f26e 100644
--- a/ash/ash_constants.cc
+++ b/ash/ash_constants.cc
@@ -18,6 +18,8 @@
 
 const float kInactiveFrameButtonIconAlphaRatio = 0.2f;
 
+const float kInactiveFrameButtonIconAlphaRatioTouch = 0.43f;
+
 const SkColor kFocusBorderColor = SkColorSetA(gfx::kGoogleBlue500, 0x99);
 const int kFocusBorderThickness = 2;
 
diff --git a/ash/ash_constants.h b/ash/ash_constants.h
index 1236b0f..c6d1b4ca 100644
--- a/ash/ash_constants.h
+++ b/ash/ash_constants.h
@@ -29,6 +29,9 @@
 // The alpha to draw inactive browser frame icons with.
 ASH_EXPORT extern const float kInactiveFrameButtonIconAlphaRatio;
 
+// Similar to the above but for touch-optimized UI.
+ASH_EXPORT extern const float kInactiveFrameButtonIconAlphaRatioTouch;
+
 // The border color of keyboard focus for launcher items and system tray.
 extern const SkColor kFocusBorderColor;
 extern const int kFocusBorderThickness;
diff --git a/ash/components/fast_ink/fast_ink_view.cc b/ash/components/fast_ink/fast_ink_view.cc
index f9c85c7..ced5301 100644
--- a/ash/components/fast_ink/fast_ink_view.cc
+++ b/ash/components/fast_ink/fast_ink_view.cc
@@ -20,8 +20,8 @@
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
 #include "ui/aura/env.h"
-#include "ui/aura/env_observer.h"
 #include "ui/aura/window.h"
+#include "ui/aura/window_observer.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/layout.h"
 #include "ui/gfx/geometry/dip_util.h"
@@ -118,7 +118,7 @@
 
 class FastInkView::LayerTreeFrameSinkHolder
     : public cc::LayerTreeFrameSinkClient,
-      public aura::EnvObserver {
+      public aura::WindowObserver {
  public:
   LayerTreeFrameSinkHolder(FastInkView* view,
                            std::unique_ptr<cc::LayerTreeFrameSink> frame_sink)
@@ -128,8 +128,8 @@
   ~LayerTreeFrameSinkHolder() override {
     if (frame_sink_)
       frame_sink_->DetachFromClient();
-    if (env_)
-      env_->RemoveObserver(this);
+    if (root_window_)
+      root_window_->RemoveObserver(this);
   }
 
   // Delete frame sink after having reclaimed all exported resources.
@@ -165,15 +165,20 @@
     if (holder->exported_resources_.empty())
       return;
 
-    aura::Env* env = aura::Env::GetInstance();
-    holder->env_ = env;
+    // Delete sink holder immediately if native window is already gone.
+    aura::Window* window = holder->view_->GetWidget()->GetNativeView();
+    if (!window)
+      return;
+
+    aura::Window* root_window = window->GetRootWindow();
+    holder->root_window_ = root_window;
     holder->view_ = nullptr;
 
     // If we have exported resources to reclaim then extend the lifetime of
-    // holder by adding it as an aura env observer. The holder will delete
-    // itself when aura shuts down or when all exported resources have been
-    // reclaimed.
-    env->AddObserver(holder.release());
+    // holder by adding it as a root window observer. The holder will delete
+    // itself when the root window is removed or when all exported resources
+    // have been reclaimed.
+    root_window->AddObserver(holder.release());
   }
 
   void SubmitCompositorFrame(viz::CompositorFrame frame,
@@ -204,7 +209,7 @@
         view_->ReclaimResource(std::move(resource));
     }
 
-    if (env_ && exported_resources_.empty())
+    if (root_window_ && exported_resources_.empty())
       ScheduleDelete();
   }
   void SetTreeActivationCallback(const base::Closure& callback) override {}
@@ -219,7 +224,7 @@
   void DidDiscardCompositorFrame(uint32_t presentation_token) override {}
   void DidLoseLayerTreeFrameSink() override {
     exported_resources_.clear();
-    if (env_)
+    if (root_window_)
       ScheduleDelete();
   }
   void OnDraw(const gfx::Transform& transform,
@@ -230,11 +235,10 @@
       const gfx::Rect& viewport_rect,
       const gfx::Transform& transform) override {}
 
-  // Overridden from aura::EnvObserver:
-  void OnWindowInitialized(aura::Window* window) override {}
-  void OnWillDestroyEnv() override {
-    env_->RemoveObserver(this);
-    env_ = nullptr;
+  // Overridden from aura::WindowObserver:
+  void OnWindowDestroying(aura::Window* window) override {
+    root_window_->RemoveObserver(this);
+    root_window_ = nullptr;
     // Make sure frame sink never outlives aura.
     frame_sink_->DetachFromClient();
     frame_sink_.reset();
@@ -255,7 +259,7 @@
       exported_resources_;
   gfx::Size last_frame_size_in_pixels_;
   float last_frame_device_scale_factor_ = 1.0f;
-  aura::Env* env_ = nullptr;
+  aura::Window* root_window_ = nullptr;
   bool delete_pending_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(LayerTreeFrameSinkHolder);
diff --git a/ash/frame/caption_buttons/frame_caption_button.cc b/ash/frame/caption_buttons/frame_caption_button.cc
index 0f08255..6fc2fab 100644
--- a/ash/frame/caption_buttons/frame_caption_button.cc
+++ b/ash/frame/caption_buttons/frame_caption_button.cc
@@ -5,6 +5,7 @@
 #include "ash/frame/caption_buttons/frame_caption_button.h"
 
 #include "ash/ash_constants.h"
+#include "ui/base/material_design/material_design_controller.h"
 #include "ui/gfx/animation/slide_animation.h"
 #include "ui/gfx/animation/throb_animation.h"
 #include "ui/gfx/canvas.h"
@@ -56,9 +57,19 @@
 
 // static
 SkColor FrameCaptionButton::GetButtonColor(bool use_light_images) {
+  if (ui::MaterialDesignController::IsTouchOptimizedUiEnabled())
+    return use_light_images ? gfx::kGoogleGrey100 : gfx::kGoogleGrey800;
+
   return use_light_images ? SK_ColorWHITE : gfx::kChromeIconGrey;
 }
 
+// static
+float FrameCaptionButton::GetInactiveButtonColorAlphaRatio() {
+  return ui::MaterialDesignController::IsTouchOptimizedUiEnabled()
+             ? kInactiveFrameButtonIconAlphaRatioTouch
+             : kInactiveFrameButtonIconAlphaRatio;
+}
+
 void FrameCaptionButton::SetImage(CaptionButtonIcon icon,
                                   Animate animate,
                                   const gfx::VectorIcon& icon_definition) {
@@ -185,7 +196,7 @@
     return base_alpha;
 
   // Paint icons as active when they are hovered over or pressed.
-  double inactive_alpha = kInactiveFrameButtonIconAlphaRatio;
+  double inactive_alpha = GetInactiveButtonColorAlphaRatio();
 
   if (hover_animation().is_animating()) {
     inactive_alpha =
diff --git a/ash/frame/caption_buttons/frame_caption_button.h b/ash/frame/caption_buttons/frame_caption_button.h
index adb7cac..5c9a606 100644
--- a/ash/frame/caption_buttons/frame_caption_button.h
+++ b/ash/frame/caption_buttons/frame_caption_button.h
@@ -34,6 +34,9 @@
   // Gets the color to use for a frame caption button.
   static SkColor GetButtonColor(bool use_light_images);
 
+  // Gets the alpha ratio for the colors of inactive frame caption buttons.
+  static float GetInactiveButtonColorAlphaRatio();
+
   // Sets the image to use to paint the button. If |animate| is ANIMATE_YES,
   // the button crossfades to the new visuals. If the image matches the one
   // currently used by the button and |animate| is ANIMATE_NO, the crossfade
diff --git a/ash/lock_screen_action/lock_screen_note_display_state_handler_unittest.cc b/ash/lock_screen_action/lock_screen_note_display_state_handler_unittest.cc
index 2e4f28b..48222ba 100644
--- a/ash/lock_screen_action/lock_screen_note_display_state_handler_unittest.cc
+++ b/ash/lock_screen_action/lock_screen_note_display_state_handler_unittest.cc
@@ -24,6 +24,7 @@
 #include "base/test/simple_test_tick_clock.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power_manager/backlight.pb.h"
 #include "services/ui/public/cpp/input_devices/input_device_client_test_api.h"
 #include "ui/events/devices/stylus_state.h"
 
@@ -46,15 +47,16 @@
     power_manager_->set_user_activity_callback(base::RepeatingClosure());
   }
 
-  const std::vector<int> brightness_changes() const {
+  const std::vector<double>& brightness_changes() const {
     return brightness_changes_;
   }
 
   void ClearBrightnessChanges() { brightness_changes_.clear(); }
 
   // chromeos::PowerManagerClient::Observer:
-  void BrightnessChanged(int level, bool user_initiated) override {
-    brightness_changes_.push_back(level);
+  void ScreenBrightnessChanged(
+      const power_manager::BacklightBrightnessChange& change) override {
+    brightness_changes_.push_back(change.percent());
   }
 
   void OnUserActivity() {
@@ -66,7 +68,7 @@
 
  private:
   chromeos::FakePowerManagerClient* power_manager_;
-  std::vector<int> brightness_changes_;
+  std::vector<double> brightness_changes_;
 
   ScopedObserver<chromeos::PowerManagerClient,
                  chromeos::PowerManagerClient::Observer>
@@ -145,7 +147,10 @@
 
   void TurnScreenOffForUserInactivity() {
     power_manager_client_->set_screen_brightness_percent(0);
-    power_manager_client_->SendBrightnessChanged(0, false /*user_initiated*/);
+    power_manager::BacklightBrightnessChange change;
+    change.set_percent(0.0);
+    change.set_cause(power_manager::BacklightBrightnessChange_Cause_OTHER);
+    power_manager_client_->SendScreenBrightnessChanged(change);
     power_manager_observer_->ClearBrightnessChanges();
   }
 
@@ -227,7 +232,7 @@
   base::RunLoop().RunUntilIdle();
 
   EXPECT_TRUE(power_manager_client_->backlights_forced_off());
-  EXPECT_EQ(std::vector<int>({0}),
+  EXPECT_EQ(std::vector<double>({0.0}),
             power_manager_observer_->brightness_changes());
   power_manager_observer_->ClearBrightnessChanges();
 
@@ -239,7 +244,7 @@
   base::RunLoop().RunUntilIdle();
 
   EXPECT_FALSE(power_manager_client_->backlights_forced_off());
-  EXPECT_EQ(std::vector<int>({kVisibleBrightnessPercent}),
+  EXPECT_EQ(std::vector<double>({kVisibleBrightnessPercent}),
             power_manager_observer_->brightness_changes());
 
   ASSERT_FALSE(LaunchTimeoutRunning());
@@ -261,7 +266,7 @@
 
   // Styluls eject is expected to turn the screen on due to user activity.
   EXPECT_FALSE(power_manager_client_->backlights_forced_off());
-  EXPECT_EQ(std::vector<int>({kVisibleBrightnessPercent}),
+  EXPECT_EQ(std::vector<double>({kVisibleBrightnessPercent}),
             power_manager_observer_->brightness_changes());
   power_manager_observer_->ClearBrightnessChanges();
 
@@ -289,7 +294,7 @@
   base::RunLoop().RunUntilIdle();
 
   EXPECT_TRUE(power_manager_client_->backlights_forced_off());
-  EXPECT_EQ(std::vector<int>({0}),
+  EXPECT_EQ(std::vector<double>({0.0}),
             power_manager_observer_->brightness_changes());
   power_manager_observer_->ClearBrightnessChanges();
 
@@ -301,7 +306,7 @@
   base::RunLoop().RunUntilIdle();
 
   EXPECT_FALSE(power_manager_client_->backlights_forced_off());
-  EXPECT_EQ(std::vector<int>({kVisibleBrightnessPercent}),
+  EXPECT_EQ(std::vector<double>({kVisibleBrightnessPercent}),
             power_manager_observer_->brightness_changes());
 
   ASSERT_FALSE(LaunchTimeoutRunning());
@@ -316,7 +321,7 @@
   SimulatePowerButtonPress();
 
   ASSERT_TRUE(power_manager_client_->backlights_forced_off());
-  EXPECT_EQ(std::vector<int>({0}),
+  EXPECT_EQ(std::vector<double>({0.0}),
             power_manager_observer_->brightness_changes());
   power_manager_observer_->ClearBrightnessChanges();
 
@@ -335,7 +340,7 @@
   base::RunLoop().RunUntilIdle();
 
   EXPECT_FALSE(power_manager_client_->backlights_forced_off());
-  EXPECT_EQ(std::vector<int>({kVisibleBrightnessPercent}),
+  EXPECT_EQ(std::vector<double>({kVisibleBrightnessPercent}),
             power_manager_observer_->brightness_changes());
 
   ASSERT_FALSE(LaunchTimeoutRunning());
@@ -352,7 +357,7 @@
       mojom::LockScreenNoteOrigin::kStylusEject));
 
   EXPECT_TRUE(power_manager_client_->backlights_forced_off());
-  EXPECT_EQ(std::vector<int>({0}),
+  EXPECT_EQ(std::vector<double>({0.0}),
             power_manager_observer_->brightness_changes());
   power_manager_observer_->ClearBrightnessChanges();
 
@@ -360,7 +365,7 @@
   base::RunLoop().RunUntilIdle();
 
   EXPECT_FALSE(power_manager_client_->backlights_forced_off());
-  EXPECT_EQ(std::vector<int>({kVisibleBrightnessPercent}),
+  EXPECT_EQ(std::vector<double>({kVisibleBrightnessPercent}),
             power_manager_observer_->brightness_changes());
   power_manager_observer_->ClearBrightnessChanges();
 
@@ -384,7 +389,8 @@
   SimulatePowerButtonPress();
   EXPECT_TRUE(power_manager_client_->backlights_forced_off());
   EXPECT_TRUE(power_manager_observer_->brightness_changes().empty());
-  EXPECT_EQ(1u, power_manager_client_->pending_brightness_changes().size());
+  EXPECT_EQ(1u,
+            power_manager_client_->pending_screen_brightness_changes().size());
 
   ui::InputDeviceClientTestApi devices_test_api;
   devices_test_api.NotifyObserversStylusStateChanged(ui::StylusState::REMOVED);
@@ -396,12 +402,14 @@
   EXPECT_TRUE(tray_action_client_.note_origins().empty());
 
   // Apply screen brightness set by forcing backlights off,
-  EXPECT_EQ(1u, power_manager_client_->pending_brightness_changes().size());
-  ASSERT_TRUE(power_manager_client_->ApplyPendingBrightnessChange());
+  EXPECT_EQ(1u,
+            power_manager_client_->pending_screen_brightness_changes().size());
+  ASSERT_TRUE(power_manager_client_->ApplyPendingScreenBrightnessChange());
 
   EXPECT_TRUE(power_manager_client_->backlights_forced_off());
-  EXPECT_TRUE(power_manager_client_->pending_brightness_changes().empty());
-  EXPECT_EQ(std::vector<int>({0}),
+  EXPECT_TRUE(
+      power_manager_client_->pending_screen_brightness_changes().empty());
+  EXPECT_EQ(std::vector<double>({0.0}),
             power_manager_observer_->brightness_changes());
   power_manager_observer_->ClearBrightnessChanges();
 
@@ -412,8 +420,8 @@
       mojom::TrayActionState::kActive);
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(power_manager_client_->backlights_forced_off());
-  ASSERT_TRUE(power_manager_client_->ApplyPendingBrightnessChange());
-  EXPECT_EQ(std::vector<int>({kVisibleBrightnessPercent}),
+  ASSERT_TRUE(power_manager_client_->ApplyPendingScreenBrightnessChange());
+  EXPECT_EQ(std::vector<double>({kVisibleBrightnessPercent}),
             power_manager_observer_->brightness_changes());
 
   ASSERT_FALSE(LaunchTimeoutRunning());
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc
index 6399637..55957154 100644
--- a/ash/root_window_controller.cc
+++ b/ash/root_window_controller.cc
@@ -11,8 +11,8 @@
 
 #include "ash/accessibility/accessibility_panel_layout_manager.h"
 #include "ash/accessibility/touch_exploration_controller.h"
+#include "ash/accessibility/touch_exploration_manager.h"
 #include "ash/ash_constants.h"
-#include "ash/ash_touch_exploration_manager_chromeos.h"
 #include "ash/focus_cycler.h"
 #include "ash/high_contrast/high_contrast_controller.h"
 #include "ash/host/ash_window_tree_host.h"
@@ -704,12 +704,13 @@
     shell->OnRootWindowAdded(root_window);
   }
 
-  // TODO: AshTouchExplorationManager doesn't work with mus.
+  // TODO: TouchExplorationManager doesn't work with mash.
   // http://crbug.com/679782
   if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kAshDisableTouchExplorationMode) &&
       Shell::GetAshConfig() != Config::MASH) {
-    touch_exploration_manager_.reset(new AshTouchExplorationManager(this));
+    touch_exploration_manager_ =
+        std::make_unique<TouchExplorationManager>(this);
   }
 }
 
diff --git a/ash/root_window_controller.h b/ash/root_window_controller.h
index ca51a83..76452d61 100644
--- a/ash/root_window_controller.h
+++ b/ash/root_window_controller.h
@@ -45,7 +45,6 @@
 
 namespace ash {
 class AlwaysOnTopController;
-class AshTouchExplorationManager;
 class AshWindowTreeHost;
 class LockScreenActionBackgroundController;
 enum class LoginStatus;
@@ -58,6 +57,7 @@
 class SystemModalContainerLayoutManager;
 class SystemTray;
 class SystemWallpaperController;
+class TouchExplorationManager;
 class TouchHudDebug;
 class TouchHudProjection;
 class WallpaperWidgetController;
@@ -312,7 +312,7 @@
 
   // Responsible for initializing TouchExplorationController when spoken
   // feedback is on.
-  std::unique_ptr<AshTouchExplorationManager> touch_exploration_manager_;
+  std::unique_ptr<TouchExplorationManager> touch_exploration_manager_;
 
   // Heads-up displays for touch events. These HUDs are not owned by the root
   // window controller and manage their own lifetimes.
diff --git a/ash/system/brightness/tray_brightness.cc b/ash/system/brightness/tray_brightness.cc
index d70a303..998c92e 100644
--- a/ash/system/brightness/tray_brightness.cc
+++ b/ash/system/brightness/tray_brightness.cc
@@ -20,6 +20,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/power_manager/backlight.pb.h"
 #include "chromeos/dbus/power_manager_client.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/display/display.h"
@@ -239,11 +240,14 @@
   return false;
 }
 
-void TrayBrightness::BrightnessChanged(int level, bool user_initiated) {
+void TrayBrightness::ScreenBrightnessChanged(
+    const power_manager::BacklightBrightnessChange& change) {
   Shell::Get()->metrics()->RecordUserMetricsAction(
       UMA_STATUS_AREA_BRIGHTNESS_CHANGED);
-  double percent = static_cast<double>(level);
-  HandleBrightnessChanged(percent, user_initiated);
+  const bool user_initiated =
+      change.cause() ==
+      power_manager::BacklightBrightnessChange_Cause_USER_REQUEST;
+  HandleBrightnessChanged(change.percent(), user_initiated);
 }
 
 void TrayBrightness::HandleBrightnessChanged(double percent,
diff --git a/ash/system/brightness/tray_brightness.h b/ash/system/brightness/tray_brightness.h
index ee6cd39..4204d27 100644
--- a/ash/system/brightness/tray_brightness.h
+++ b/ash/system/brightness/tray_brightness.h
@@ -44,7 +44,8 @@
   bool ShouldShowShelf() const override;
 
   // Overriden from PowerManagerClient::Observer.
-  void BrightnessChanged(int level, bool user_initiated) override;
+  void ScreenBrightnessChanged(
+      const power_manager::BacklightBrightnessChange& change) override;
 
   void HandleBrightnessChanged(double percent, bool user_initiated);
 
diff --git a/ash/system/keyboard_brightness/tray_keyboard_brightness.cc b/ash/system/keyboard_brightness/tray_keyboard_brightness.cc
index ebf5992..4b3e11dd 100644
--- a/ash/system/keyboard_brightness/tray_keyboard_brightness.cc
+++ b/ash/system/keyboard_brightness/tray_keyboard_brightness.cc
@@ -19,6 +19,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/power_manager/backlight.pb.h"
 #include "chromeos/dbus/power_manager_client.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/display/display.h"
@@ -146,14 +147,15 @@
   return false;
 }
 
-void TrayKeyboardBrightness::KeyboardBrightnessChanged(int level,
-                                                       bool user_initiated) {
-  current_percent_ = static_cast<double>(level);
+void TrayKeyboardBrightness::KeyboardBrightnessChanged(
+    const power_manager::BacklightBrightnessChange& change) {
+  current_percent_ = change.percent();
 
   if (brightness_view_)
     brightness_view_->SetKeyboardBrightnessPercent(current_percent_);
 
-  if (!user_initiated)
+  if (change.cause() !=
+      power_manager::BacklightBrightnessChange_Cause_USER_REQUEST)
     return;
 
   if (brightness_view_ && brightness_view_->visible())
diff --git a/ash/system/keyboard_brightness/tray_keyboard_brightness.h b/ash/system/keyboard_brightness/tray_keyboard_brightness.h
index 31ad86c..cb6fd1a2 100644
--- a/ash/system/keyboard_brightness/tray_keyboard_brightness.h
+++ b/ash/system/keyboard_brightness/tray_keyboard_brightness.h
@@ -34,7 +34,8 @@
   bool ShouldShowShelf() const override;
 
   // Overriden from PowerManagerClient::Observer.
-  void KeyboardBrightnessChanged(int level, bool user_initiated) override;
+  void KeyboardBrightnessChanged(
+      const power_manager::BacklightBrightnessChange& change) override;
 
   tray::KeyboardBrightnessView* brightness_view_ = nullptr;
 
diff --git a/ash/system/power/backlights_forced_off_setter.cc b/ash/system/power/backlights_forced_off_setter.cc
index 6f1ef58e..544a22b 100644
--- a/ash/system/power/backlights_forced_off_setter.cc
+++ b/ash/system/power/backlights_forced_off_setter.cc
@@ -12,6 +12,7 @@
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/power_manager/backlight.pb.h"
 
 namespace ash {
 
@@ -51,10 +52,14 @@
   return scoped_backlights_forced_off;
 }
 
-void BacklightsForcedOffSetter::BrightnessChanged(int level,
-                                                  bool user_initiated) {
+void BacklightsForcedOffSetter::ScreenBrightnessChanged(
+    const power_manager::BacklightBrightnessChange& change) {
+  const bool user_initiated =
+      change.cause() ==
+      power_manager::BacklightBrightnessChange_Cause_USER_REQUEST;
+
   const ScreenState old_state = screen_state_;
-  if (level != 0)
+  if (change.percent() > 0.0)
     screen_state_ = ScreenState::ON;
   else
     screen_state_ = user_initiated ? ScreenState::OFF : ScreenState::OFF_AUTO;
diff --git a/ash/system/power/backlights_forced_off_setter.h b/ash/system/power/backlights_forced_off_setter.h
index 8d7c964..d71fca6 100644
--- a/ash/system/power/backlights_forced_off_setter.h
+++ b/ash/system/power/backlights_forced_off_setter.h
@@ -65,7 +65,8 @@
   std::unique_ptr<ScopedBacklightsForcedOff> ForceBacklightsOff();
 
   // Overridden from chromeos::PowerManagerClient::Observer:
-  void BrightnessChanged(int level, bool user_initiated) override;
+  void ScreenBrightnessChanged(
+      const power_manager::BacklightBrightnessChange& change) override;
   void PowerManagerRestarted() override;
 
   // Resets internal state for tests.
diff --git a/ash/system/power/power_button_controller.cc b/ash/system/power/power_button_controller.cc
index d174b410..9b11e70b 100644
--- a/ash/system/power/power_button_controller.cc
+++ b/ash/system/power/power_button_controller.cc
@@ -4,6 +4,7 @@
 
 #include "ash/system/power/power_button_controller.h"
 
+#include <limits>
 #include <utility>
 
 #include "ash/accelerators/accelerator_controller.h"
@@ -22,6 +23,7 @@
 #include "base/command_line.h"
 #include "base/time/default_tick_clock.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/power_manager/backlight.pb.h"
 #include "ui/display/types/display_snapshot.h"
 #include "ui/views/widget/widget.h"
 
@@ -239,8 +241,10 @@
       internal_display_off && external_display_on;
 }
 
-void PowerButtonController::BrightnessChanged(int level, bool user_initiated) {
-  brightness_is_zero_ = level == 0;
+void PowerButtonController::ScreenBrightnessChanged(
+    const power_manager::BacklightBrightnessChange& change) {
+  brightness_is_zero_ =
+      change.percent() <= std::numeric_limits<double>::epsilon();
 }
 
 void PowerButtonController::PowerButtonEventReceived(
diff --git a/ash/system/power/power_button_controller.h b/ash/system/power/power_button_controller.h
index 590af998..8a684a4 100644
--- a/ash/system/power/power_button_controller.h
+++ b/ash/system/power/power_button_controller.h
@@ -98,7 +98,8 @@
       const display::DisplayConfigurator::DisplayStateList& outputs) override;
 
   // chromeos::PowerManagerClient::Observer:
-  void BrightnessChanged(int level, bool user_initiated) override;
+  void ScreenBrightnessChanged(
+      const power_manager::BacklightBrightnessChange& change) override;
   void PowerButtonEventReceived(bool down,
                                 const base::TimeTicks& timestamp) override;
   void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
diff --git a/ash/system/power/power_button_controller_unittest.cc b/ash/system/power/power_button_controller_unittest.cc
index 417df99..4d3b6e4f 100644
--- a/ash/system/power/power_button_controller_unittest.cc
+++ b/ash/system/power/power_button_controller_unittest.cc
@@ -36,7 +36,13 @@
 namespace {
 
 // A non-zero brightness used for test.
-constexpr int kNonZeroBrightness = 10;
+constexpr double kNonZeroBrightness = 10.;
+
+// Shorthand for some long constants.
+constexpr power_manager::BacklightBrightnessChange_Cause kUserCause =
+    power_manager::BacklightBrightnessChange_Cause_USER_REQUEST;
+constexpr power_manager::BacklightBrightnessChange_Cause kOtherCause =
+    power_manager::BacklightBrightnessChange_Cause_OTHER;
 
 }  // namespace
 
@@ -48,7 +54,8 @@
   void SetUp() override {
     PowerButtonTestBase::SetUp();
     InitPowerButtonControllerMembers(PowerManagerClient::TabletMode::ON);
-    power_manager_client_->SendBrightnessChanged(kNonZeroBrightness, true);
+
+    SendBrightnessChange(kNonZeroBrightness, kUserCause);
     EXPECT_FALSE(power_manager_client_->backlights_forced_off());
 
     // Advance a duration longer than |kIgnorePowerButtonAfterResumeDelay| to
@@ -63,6 +70,15 @@
   }
 
  protected:
+  void SendBrightnessChange(
+      double percent,
+      power_manager::BacklightBrightnessChange_Cause cause) {
+    power_manager::BacklightBrightnessChange change;
+    change.set_percent(percent);
+    change.set_cause(cause);
+    power_manager_client_->SendScreenBrightnessChanged(change);
+  }
+
   bool GetLockedState() {
     // LockScreen is an async mojo call.
     SessionController* const session_controller =
@@ -79,11 +95,11 @@
   // Tapping power button when screen is off will turn the screen on but not
   // showing the menu.
   void TappingPowerButtonWhenScreenIsIdleOff() {
-    power_manager_client_->SendBrightnessChanged(0, true);
+    SendBrightnessChange(0, kUserCause);
     PressPowerButton();
     EXPECT_TRUE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
     EXPECT_FALSE(power_manager_client_->backlights_forced_off());
-    power_manager_client_->SendBrightnessChanged(kNonZeroBrightness, true);
+    SendBrightnessChange(kNonZeroBrightness, kUserCause);
     ReleasePowerButton();
     EXPECT_FALSE(power_manager_client_->backlights_forced_off());
     EXPECT_FALSE(power_button_test_api_->PowerButtonMenuTimerIsRunning());
@@ -298,10 +314,10 @@
        TappingPowerButtonWhenSuspendedWithoutBacklightsForcedOff) {
   power_manager_client_->SendSuspendImminent(
       power_manager::SuspendImminent_Reason_OTHER);
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   // There is a power button pressed here, but PowerButtonEvent is sent later.
   power_manager_client_->SendSuspendDone();
-  power_manager_client_->SendBrightnessChanged(kNonZeroBrightness, true);
+  SendBrightnessChange(kNonZeroBrightness, kUserCause);
 
   // Send the power button event after a short delay and check that backlights
   // are not forced off.
@@ -318,7 +334,7 @@
   PressPowerButton();
   EXPECT_TRUE(power_button_test_api_->ShutdownTimerIsRunning());
   ReleasePowerButton();
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   EXPECT_FALSE(power_button_test_api_->ShutdownTimerIsRunning());
   EXPECT_TRUE(power_manager_client_->backlights_forced_off());
 }
@@ -329,7 +345,7 @@
        TappingPowerButtonWhenSuspendedWithBacklightsForcedOff) {
   PressPowerButton();
   ReleasePowerButton();
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   ASSERT_TRUE(power_manager_client_->backlights_forced_off());
   power_manager_client_->SendSuspendImminent(
       power_manager::SuspendImminent_Reason_OTHER);
@@ -342,7 +358,7 @@
   // are not forced off.
   tick_clock_.Advance(base::TimeDelta::FromMilliseconds(500));
   PressPowerButton();
-  power_manager_client_->SendBrightnessChanged(kNonZeroBrightness, true);
+  SendBrightnessChange(kNonZeroBrightness, kUserCause);
   EXPECT_TRUE(power_button_test_api_->ShutdownTimerIsRunning());
   ReleasePowerButton();
   EXPECT_FALSE(power_button_test_api_->ShutdownTimerIsRunning());
@@ -354,7 +370,7 @@
   PressPowerButton();
   EXPECT_TRUE(power_button_test_api_->ShutdownTimerIsRunning());
   ReleasePowerButton();
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   EXPECT_FALSE(power_button_test_api_->ShutdownTimerIsRunning());
   EXPECT_TRUE(power_manager_client_->backlights_forced_off());
 }
@@ -367,27 +383,27 @@
   // KeyEvent should SetBacklightsForcedOff(false).
   PressPowerButton();
   ReleasePowerButton();
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   ASSERT_TRUE(power_manager_client_->backlights_forced_off());
   PressKey(ui::VKEY_L);
-  power_manager_client_->SendBrightnessChanged(kNonZeroBrightness, true);
+  SendBrightnessChange(kNonZeroBrightness, kUserCause);
   EXPECT_FALSE(power_manager_client_->backlights_forced_off());
 
   // Regular mouse event should SetBacklightsForcedOff(false).
   AdvanceClockToAvoidIgnoring();
   PressPowerButton();
   ReleasePowerButton();
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   ASSERT_TRUE(power_manager_client_->backlights_forced_off());
   GenerateMouseMoveEvent();
-  power_manager_client_->SendBrightnessChanged(kNonZeroBrightness, true);
+  SendBrightnessChange(kNonZeroBrightness, kUserCause);
   EXPECT_FALSE(power_manager_client_->backlights_forced_off());
 
   // Synthesized mouse event should not SetBacklightsForcedOff(false).
   AdvanceClockToAvoidIgnoring();
   PressPowerButton();
   ReleasePowerButton();
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   ASSERT_TRUE(power_manager_client_->backlights_forced_off());
   GetEventGenerator().set_flags(ui::EF_IS_SYNTHESIZED);
   GenerateMouseMoveEvent();
@@ -402,7 +418,7 @@
 
   PressPowerButton();
   ReleasePowerButton();
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   ASSERT_TRUE(power_manager_client_->backlights_forced_off());
   PressKey(ui::VKEY_L);
   EXPECT_TRUE(power_manager_client_->backlights_forced_off());
@@ -443,11 +459,11 @@
   ASSERT_TRUE(GetGlobalTouchscreenEnabled());
   PressPowerButton();
   ReleasePowerButton();
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   EXPECT_FALSE(GetGlobalTouchscreenEnabled());
 
   PressPowerButton();
-  power_manager_client_->SendBrightnessChanged(kNonZeroBrightness, true);
+  SendBrightnessChange(kNonZeroBrightness, kUserCause);
   ReleasePowerButton();
   EXPECT_TRUE(GetGlobalTouchscreenEnabled());
 
@@ -456,22 +472,22 @@
   AdvanceClockToAvoidIgnoring();
   PressPowerButton();
   ReleasePowerButton();
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   ASSERT_TRUE(power_manager_client_->backlights_forced_off());
   ASSERT_FALSE(GetGlobalTouchscreenEnabled());
   PressKey(ui::VKEY_L);
-  power_manager_client_->SendBrightnessChanged(kNonZeroBrightness, true);
+  SendBrightnessChange(kNonZeroBrightness, kUserCause);
   EXPECT_TRUE(GetGlobalTouchscreenEnabled());
 
   // MouseEvent on laptop mode when screen is off.
   AdvanceClockToAvoidIgnoring();
   PressPowerButton();
   ReleasePowerButton();
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   ASSERT_TRUE(power_manager_client_->backlights_forced_off());
   ASSERT_FALSE(GetGlobalTouchscreenEnabled());
   GenerateMouseMoveEvent();
-  power_manager_client_->SendBrightnessChanged(kNonZeroBrightness, true);
+  SendBrightnessChange(kNonZeroBrightness, kUserCause);
   EXPECT_TRUE(GetGlobalTouchscreenEnabled());
 }
 
@@ -481,14 +497,14 @@
   ASSERT_TRUE(GetGlobalTouchscreenEnabled());
 
   // Turn screen off for automated change (e.g. user is inactive).
-  power_manager_client_->SendBrightnessChanged(0, false);
+  SendBrightnessChange(0, kOtherCause);
   EXPECT_FALSE(GetGlobalTouchscreenEnabled());
-  power_manager_client_->SendBrightnessChanged(kNonZeroBrightness, true);
+  SendBrightnessChange(kNonZeroBrightness, kUserCause);
   EXPECT_TRUE(GetGlobalTouchscreenEnabled());
 
   // After decreasing the brightness to zero for a user request, the touchscreen
   // should remain enabled.
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   EXPECT_TRUE(GetGlobalTouchscreenEnabled());
 }
 
@@ -525,14 +541,14 @@
   // Set backlights forced off for starting point.
   PressPowerButton();
   ReleasePowerButton();
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   ASSERT_TRUE(power_manager_client_->backlights_forced_off());
 
   // Test that a pressing-releasing operation after a short duration, backlights
   // forced off is stopped since we don't drop request for power button pressed.
   tick_clock_.Advance(base::TimeDelta::FromMilliseconds(200));
   PressPowerButton();
-  power_manager_client_->SendBrightnessChanged(kNonZeroBrightness, true);
+  SendBrightnessChange(kNonZeroBrightness, kUserCause);
   ReleasePowerButton();
   EXPECT_FALSE(power_manager_client_->backlights_forced_off());
 
@@ -547,7 +563,7 @@
   tick_clock_.Advance(base::TimeDelta::FromMilliseconds(800));
   PressPowerButton();
   ReleasePowerButton();
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   EXPECT_TRUE(power_manager_client_->backlights_forced_off());
 }
 
@@ -636,7 +652,7 @@
 TEST_F(PowerButtonControllerTest, SuspendDoneStopsForcingOff) {
   PressPowerButton();
   ReleasePowerButton();
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   ASSERT_TRUE(power_manager_client_->backlights_forced_off());
 
   // Simulate an edge case that system resumes because of tablet power button
@@ -671,13 +687,13 @@
 TEST_F(PowerButtonControllerTest, IgnoreForcingOffWhenDisplayIsTurningOn) {
   PressPowerButton();
   ReleasePowerButton();
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   ASSERT_TRUE(power_manager_client_->backlights_forced_off());
 
   // Trigger a key event to stop backlights forcing off. Chrome will receive
   // brightness changed signal. But we may still have display off state.
   PressKey(ui::VKEY_L);
-  power_manager_client_->SendBrightnessChanged(kNonZeroBrightness, true);
+  SendBrightnessChange(kNonZeroBrightness, kUserCause);
   EXPECT_FALSE(power_manager_client_->backlights_forced_off());
 
   // Since display could still be off, ignore forcing off.
@@ -692,7 +708,7 @@
   AdvanceClockToAvoidIgnoring();
   PressPowerButton();
   ReleasePowerButton();
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   EXPECT_TRUE(power_manager_client_->backlights_forced_off());
 }
 
@@ -705,12 +721,12 @@
   controller->SetClient(client.CreateInterfacePtrAndBind());
   PressPowerButton();
   ReleasePowerButton();
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   controller->FlushMojoForTest();
   EXPECT_EQ(mojom::AccessibilityAlert::SCREEN_OFF, client.last_a11y_alert());
 
   PressPowerButton();
-  power_manager_client_->SendBrightnessChanged(kNonZeroBrightness, true);
+  SendBrightnessChange(kNonZeroBrightness, kUserCause);
   controller->FlushMojoForTest();
   EXPECT_EQ(mojom::AccessibilityAlert::SCREEN_ON, client.last_a11y_alert());
   ReleasePowerButton();
@@ -778,7 +794,7 @@
 TEST_F(PowerButtonControllerTest, DismissMenuWhenScreenIsIdleOff) {
   OpenPowerButtonMenu();
   // Mock screen idle off.
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
 }
 
@@ -790,13 +806,13 @@
   AdvanceClockToAvoidIgnoring();
   PressPowerButton();
   ReleasePowerButton();
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   EXPECT_TRUE(power_manager_client_->backlights_forced_off());
   EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
 
   // Long press the power button when backlights are off will show the menu.
   PressPowerButton();
-  power_manager_client_->SendBrightnessChanged(kNonZeroBrightness, true);
+  SendBrightnessChange(kNonZeroBrightness, kUserCause);
   EXPECT_TRUE(power_button_test_api_->TriggerPowerButtonMenuTimeout());
   ReleasePowerButton();
   EXPECT_TRUE(power_button_test_api_->IsMenuOpened());
@@ -804,7 +820,7 @@
   AdvanceClockToAvoidIgnoring();
   PressPowerButton();
   ReleasePowerButton();
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   EXPECT_TRUE(power_manager_client_->backlights_forced_off());
   EXPECT_FALSE(power_button_test_api_->IsMenuOpened());
 }
diff --git a/ash/wm/lock_state_controller_unittest.cc b/ash/wm/lock_state_controller_unittest.cc
index a684ebe..6f56342 100644
--- a/ash/wm/lock_state_controller_unittest.cc
+++ b/ash/wm/lock_state_controller_unittest.cc
@@ -32,6 +32,11 @@
 namespace ash {
 namespace {
 
+// Shorthand for some long constants.
+constexpr power_manager::BacklightBrightnessChange_Cause kUserCause =
+    power_manager::BacklightBrightnessChange_Cause_USER_REQUEST;
+constexpr power_manager::BacklightBrightnessChange_Cause kOtherCause =
+    power_manager::BacklightBrightnessChange_Cause_OTHER;
 bool cursor_visible() {
   return Shell::Get()->cursor_manager()->IsCursorVisible();
 }
@@ -91,6 +96,15 @@
     test_animator_->Advance(test_animator_->GetDuration(speed) * factor);
   }
 
+  void SendBrightnessChange(
+      double percent,
+      power_manager::BacklightBrightnessChange_Cause cause) {
+    power_manager::BacklightBrightnessChange change;
+    change.set_percent(percent);
+    change.set_cause(cause);
+    power_manager_client_->SendScreenBrightnessChanged(change);
+  }
+
   void ExpectPreLockAnimationStarted() {
     SCOPED_TRACE("Failure in ExpectPreLockAnimationStarted");
     EXPECT_LT(0u, test_animator_->GetAnimationCount());
@@ -342,14 +356,14 @@
 
   // When the screen brightness is at 0%, we shouldn't do anything in response
   // to power button presses.
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   PressPowerButton();
   EXPECT_FALSE(lock_state_test_api_->is_animating_lock());
   ReleasePowerButton();
 
   // After increasing the brightness to 10%, we should start the timer like
   // usual.
-  power_manager_client_->SendBrightnessChanged(10, true);
+  SendBrightnessChange(10, kUserCause);
   PressPowerButton();
   EXPECT_TRUE(lock_state_test_api_->is_animating_lock());
   ReleasePowerButton();
@@ -378,7 +392,7 @@
 
   // When all of the displays are turned off (e.g. due to user inactivity), the
   // power button should be ignored.
-  power_manager_client_->SendBrightnessChanged(0, true);
+  SendBrightnessChange(0, kUserCause);
   internal_display->set_current_mode(nullptr);
   external_display->set_current_mode(nullptr);
   power_button_controller_->OnDisplayModeChanged(outputs);
@@ -637,13 +651,13 @@
   base::RunLoop().RunUntilIdle();
 
   // Manually turn the screen off and check that the touchscreen is enabled.
-  power_manager_client_->SendBrightnessChanged(0, true /* user_initiated */);
+  SendBrightnessChange(0, kUserCause);
   EXPECT_TRUE(Shell::Get()->touch_devices_controller()->GetTouchscreenEnabled(
       TouchscreenEnabledSource::GLOBAL));
 
   // It should be disabled if the screen is turned off due to user inactivity.
-  power_manager_client_->SendBrightnessChanged(100, true /* user_initiated */);
-  power_manager_client_->SendBrightnessChanged(0, false /* user_initiated */);
+  SendBrightnessChange(100, kUserCause);
+  SendBrightnessChange(0, kOtherCause);
   EXPECT_FALSE(Shell::Get()->touch_devices_controller()->GetTouchscreenEnabled(
       TouchscreenEnabledSource::GLOBAL));
 }
@@ -660,7 +674,7 @@
   base::RunLoop().RunUntilIdle();
 
   // The touchscreen should remain enabled.
-  power_manager_client_->SendBrightnessChanged(0, false /* user_initiated */);
+  SendBrightnessChange(0, kOtherCause);
   EXPECT_TRUE(Shell::Get()->touch_devices_controller()->GetTouchscreenEnabled(
       TouchscreenEnabledSource::GLOBAL));
 }
diff --git a/base/native_library_win.cc b/base/native_library_win.cc
index 7a5c9f62..f782ace 100644
--- a/base/native_library_win.cc
+++ b/base/native_library_win.cc
@@ -165,7 +165,7 @@
 // static
 void* GetFunctionPointerFromNativeLibrary(NativeLibrary library,
                                           StringPiece name) {
-  return GetProcAddress(library, name.data());
+  return reinterpret_cast<void*>(GetProcAddress(library, name.data()));
 }
 
 // static
diff --git a/build/android/gyp/process_resources.py b/build/android/gyp/process_resources.py
index 22036a2b..a038a60 100755
--- a/build/android/gyp/process_resources.py
+++ b/build/android/gyp/process_resources.py
@@ -339,8 +339,6 @@
   # Keep these assignments all on one line to make diffing against regular
   # aapt-generated files easier.
   create_id = ('{{ e.resource_type }}.{{ e.name }} ^= packageIdTransform;')
-  create_id_arr = ('{{ e.resource_type }}.{{ e.name }}[i] ^='
-                   ' packageIdTransform;')
   # Here we diverge from what aapt does. Because we have so many
   # resources, the onResourcesLoaded method was exceeding the 64KB limit that
   # Java imposes. For this reason we split onResourcesLoaded into different
@@ -362,6 +360,13 @@
     }
     {% endfor %}
     {% if shared_resources %}
+    public static void transfromArray(int[] array, int packageIdTransform) {
+        for (int i=0; i < array.length; i++) {
+            if ((array[i] >>> 24) == 0x7f) {
+                array[i] ^= packageIdTransform;
+            }
+        }
+    }
     public static void onResourcesLoaded(int packageId) {
         assert !sResourcesDidLoad;
         sResourcesDidLoad = true;
@@ -370,9 +375,7 @@
         onResourcesLoaded{{ resource_type|title }}(packageIdTransform);
         {% for e in non_final_resources[resource_type] %}
         {% if e.java_type == 'int[]' %}
-        for(int i = 0; i < {{ e.resource_type }}.{{ e.name }}.length; ++i) {
-            """ + create_id_arr + """
-        }
+        transfromArray({{ e.resource_type }}.{{ e.name }}, packageIdTransform);
         {% endif %}
         {% endfor %}
         {% endfor %}
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 9a10137aa..b424763 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -1278,6 +1278,12 @@
       # [1] https://gcc.gnu.org/gcc-6/porting_to.html#this-cannot-be-null
       # [2] https://crbug.com/784492#c13
       cflags += [ "-fno-delete-null-pointer-checks" ]
+
+      # -Wcomment gives too many false positives in the case a
+      # backslash ended comment line is followed by a new line of
+      # comments
+      # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61638
+      cflags += [ "-Wno-comments" ]
     }
   }
 
diff --git a/chrome/android/java/res/layout/new_tab_page_layout.xml b/chrome/android/java/res/layout/new_tab_page_layout.xml
index 21c61dce..31dcd7f7 100644
--- a/chrome/android/java/res/layout/new_tab_page_layout.xml
+++ b/chrome/android/java/res/layout/new_tab_page_layout.xml
@@ -131,4 +131,28 @@
         android:layout_height="0dp"
         android:layout_weight="1"
         android:visibility="gone" />
+
+    <LinearLayout
+        android:id="@+id/shortcuts"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center"
+        android:orientation="horizontal"
+        android:visibility="gone" >
+
+        <Button
+            style="@style/SuggestionCardAction"
+            android:id="@+id/bookmarks_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingEnd="16dp"
+            android:text="@string/menu_bookmarks" />
+
+        <Button
+            style="@style/SuggestionCardAction"
+            android:id="@+id/downloads_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/menu_downloads" />
+    </LinearLayout>
 </org.chromium.chrome.browser.ntp.NewTabPageLayout>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
index 20d00be..808f8997 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -226,9 +226,10 @@
             "NTPArticleSuggestionsExpandableHeader";
     public static final String NTP_CONDENSED_LAYOUT = "NTPCondensedLayout";
     public static final String NTP_CONDENSED_TILE_LAYOUT = "NTPCondensedTileLayout";
-    public static final String NTP_MODERN_LAYOUT = "NTPModernLayout";
     public static final String NTP_FOREIGN_SESSIONS_SUGGESTIONS = "NTPForeignSessionsSuggestions";
     public static final String NTP_LAUNCH_AFTER_INACTIVITY = "NTPLaunchAfterInactivity";
+    public static final String NTP_MODERN_LAYOUT = "NTPModernLayout";
+    public static final String NTP_SHORTCUTS = "NTPShortcuts";
     public static final String NTP_SHOW_GOOGLE_G_IN_OMNIBOX = "NTPShowGoogleGInOmnibox";
     public static final String NTP_SNIPPETS_INCREASED_VISIBILITY = "NTPSnippetsIncreasedVisibility";
     public static final String OFFLINE_PAGES_DESCRIPTIVE_PENDING_STATUS =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index ec9237d..82108897 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -1962,6 +1962,17 @@
         }
     }
 
+    @Override
+    public boolean moveTaskToBack(boolean nonRoot) {
+        try {
+            return super.moveTaskToBack(nonRoot);
+        } catch (NullPointerException e) {
+            // Work around framework bug described in https://crbug.com/817567.
+            finish();
+            return true;
+        }
+    }
+
     /**
      * Launch a URL from an intent.
      *
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java
index ff03367..67d95eb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java
@@ -418,8 +418,9 @@
      * @param time  The current time of the app in ms.
      */
     public void commitOutstandingModelState(long time) {
-        mStacks.get(1).ensureCleaningUpDyingTabs(time);
-        mStacks.get(0).ensureCleaningUpDyingTabs(time);
+        for (int i = 0; i < mStacks.size(); i++) {
+            mStacks.get(i).ensureCleaningUpDyingTabs(time);
+        }
     }
 
     @Override
@@ -568,15 +569,21 @@
     @Override
     public boolean onUpdateAnimation(long time, boolean jumpToEnd) {
         boolean animationsWasDone = super.onUpdateAnimation(time, jumpToEnd);
-        boolean finishedView0 = mStacks.get(0).onUpdateViewAnimation(time, jumpToEnd);
-        boolean finishedView1 = mStacks.get(1).onUpdateViewAnimation(time, jumpToEnd);
-        boolean finishedCompositor0 = mStacks.get(0).onUpdateCompositorAnimations(time, jumpToEnd);
-        boolean finishedCompositor1 = mStacks.get(1).onUpdateCompositorAnimations(time, jumpToEnd);
-        if (animationsWasDone && finishedView0 && finishedView1 && finishedCompositor0
-                && finishedCompositor1) {
+
+        boolean finishedAllViews = true;
+        for (int i = 0; i < mStacks.size(); i++) {
+            finishedAllViews &= mStacks.get(i).onUpdateViewAnimation(time, jumpToEnd);
+        }
+
+        boolean finishedAllCompositors = true;
+        for (int i = 0; i < mStacks.size(); i++) {
+            finishedAllCompositors &= mStacks.get(i).onUpdateCompositorAnimations(time, jumpToEnd);
+        }
+
+        if (animationsWasDone && finishedAllViews && finishedAllCompositors) {
             return true;
         } else {
-            if (!animationsWasDone || !finishedCompositor0 || !finishedCompositor1) {
+            if (!animationsWasDone || !finishedAllCompositors) {
                 requestStackUpdate();
             }
 
@@ -773,18 +780,19 @@
     }
 
     private void requestStackUpdate() {
-        // TODO(jgreenwald): It isn't always necessary to invalidate both
-        // stacks.
-        mStacks.get(0).requestUpdate();
-        mStacks.get(1).requestUpdate();
+        // TODO(jgreenwald): It isn't always necessary to invalidate all stacks.
+        for (int i = 0; i < mStacks.size(); i++) {
+            mStacks.get(i).requestUpdate();
+        }
     }
 
     @Override
     public void notifySizeChanged(float width, float height, int orientation) {
         mCachedLandscapeViewport = null;
         mCachedPortraitViewport = null;
-        mStacks.get(0).notifySizeChanged(width, height, orientation);
-        mStacks.get(1).notifySizeChanged(width, height, orientation);
+        for (Stack stack : mStacks) {
+            stack.notifySizeChanged(width, height, orientation);
+        }
         resetScrollData();
         requestStackUpdate();
     }
@@ -793,8 +801,9 @@
     public void contextChanged(Context context) {
         super.contextChanged(context);
         StackTab.resetDimensionConstants(context);
-        mStacks.get(0).contextChanged(context);
-        mStacks.get(1).contextChanged(context);
+        for (Stack stack : mStacks) {
+            stack.contextChanged(context);
+        }
         requestStackUpdate();
     }
 
@@ -1049,16 +1058,28 @@
         super.updateLayout(time, dt);
         boolean needUpdate = false;
 
+        if (mStackRects.size() > mStacks.size()) {
+            mStackRects.subList(mStacks.size(), mStackRects.size()).clear();
+        }
+        while (mStackRects.size() < mStacks.size()) mStackRects.add(new RectF());
+
         final PortraitViewport viewport = getViewportParameters();
-        mStackRects.get(0).left = viewport.getStack0Left();
-        mStackRects.get(0).right = mStackRects.get(0).left + viewport.getWidth();
-        mStackRects.get(0).top = viewport.getStack0Top();
-        mStackRects.get(0).bottom = mStackRects.get(0).top + viewport.getHeight();
-        mStackRects.get(1).left =
-                mStackRects.get(0).left + viewport.getStack0ToStack1TranslationX();
-        mStackRects.get(1).right = mStackRects.get(1).left + viewport.getWidth();
-        mStackRects.get(1).top = mStackRects.get(0).top + viewport.getStack0ToStack1TranslationY();
-        mStackRects.get(1).bottom = mStackRects.get(1).top + viewport.getHeight();
+
+        if (!mStackRects.isEmpty()) {
+            mStackRects.get(0).left = viewport.getStack0Left();
+            mStackRects.get(0).right = mStackRects.get(0).left + viewport.getWidth();
+            mStackRects.get(0).top = viewport.getStack0Top();
+            mStackRects.get(0).bottom = mStackRects.get(0).top + viewport.getHeight();
+        }
+
+        for (int i = 1; i < mStackRects.size(); i++) {
+            mStackRects.get(i).left =
+                    mStackRects.get(i - 1).left + viewport.getStack0ToStack1TranslationX();
+            mStackRects.get(i).right = mStackRects.get(i).left + viewport.getWidth();
+            mStackRects.get(i).top =
+                    mStackRects.get(i - 1).top + viewport.getStack0ToStack1TranslationY();
+            mStackRects.get(i).bottom = mStackRects.get(i).top + viewport.getHeight();
+        }
 
         mStacks.get(0).setStackFocusInfo(1.0f + mRenderedScrollOffset,
                 mSortingComparator == mOrderComparator ? mTabModelSelector.getModel(false).index()
@@ -1068,13 +1089,16 @@
                                                        : -1);
 
         // Compute position and visibility
-        mStacks.get(0).computeTabPosition(time, mStackRects.get(0));
-        mStacks.get(1).computeTabPosition(time, mStackRects.get(1));
+        for (int i = 0; i < mStacks.size(); i++) {
+            mStacks.get(i).computeTabPosition(time, mStackRects.get(i));
+        }
 
         // Pre-allocate/resize {@link #mLayoutTabs} before it get populated by
         // computeTabPositionAndAppendLayoutTabs.
-        final int tabVisibleCount =
-                mStacks.get(0).getVisibleCount() + mStacks.get(1).getVisibleCount();
+        int tabVisibleCount = 0;
+        for (int i = 0; i < mStacks.size(); i++) {
+            tabVisibleCount += mStacks.get(i).getVisibleCount();
+        }
 
         int layoutTabCount = tabVisibleCount + (mNewTabLayoutTab == null ? 0 : 1);
 
@@ -1085,13 +1109,12 @@
         }
 
         int index = 0;
-        if (getTabStackIndex() == 1) {
-            index = appendVisibleLayoutTabs(time, 0, mLayoutTabs, index);
-            index = appendVisibleLayoutTabs(time, 1, mLayoutTabs, index);
-        } else {
-            index = appendVisibleLayoutTabs(time, 1, mLayoutTabs, index);
-            index = appendVisibleLayoutTabs(time, 0, mLayoutTabs, index);
+        for (int i = 0; i < mStacks.size(); i++) {
+            // Append tabs for the current stack last so they get priority in rendering.
+            if (getTabStackIndex() == i) continue;
+            index = appendVisibleLayoutTabs(time, i, mLayoutTabs, index);
         }
+        index = appendVisibleLayoutTabs(time, getTabStackIndex(), mLayoutTabs, index);
         assert index == tabVisibleCount : "index should be incremented up to tabVisibleCount";
 
         // Update tab snapping
@@ -1191,15 +1214,26 @@
         }
     }
 
+    /**
+     * Updates mSortedPriorityArray, which stores the list of StackTabs to render, sorted by
+     * rendering priority.
+     *
+     * @param comparator The comparator used to sort the StackTabs.
+     * @return True if at least one Stack has a tab, false if there are no tabs.
+     */
     private boolean updateSortedPriorityArray(Comparator<StackTab> comparator) {
-        final int allTabsCount = mStacks.get(0).getCount() + mStacks.get(1).getCount();
+        int allTabsCount = 0;
+        for (int i = 0; i < mStacks.size(); i++) {
+            allTabsCount += mStacks.get(i).getCount();
+        }
         if (allTabsCount == 0) return false;
         if (mSortedPriorityArray == null || mSortedPriorityArray.length != allTabsCount) {
             mSortedPriorityArray = new StackTab[allTabsCount];
         }
         int sortedOffset = 0;
-        sortedOffset = addAllTabs(mStacks.get(0), mSortedPriorityArray, sortedOffset);
-        sortedOffset = addAllTabs(mStacks.get(1), mSortedPriorityArray, sortedOffset);
+        for (int i = 0; i < mStacks.size(); i++) {
+            sortedOffset = addAllTabs(mStacks.get(i), mSortedPriorityArray, sortedOffset);
+        }
         assert sortedOffset == mSortedPriorityArray.length;
         Arrays.sort(mSortedPriorityArray, comparator);
         return true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
index 41a77df..21fe777 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageView.java
@@ -364,6 +364,8 @@
             }
         });
 
+        initializeShortcuts();
+
         mInitialized = true;
 
         TraceEvent.end(TAG + ".initialize()");
@@ -1065,4 +1067,19 @@
         mTab.getWindowAndroid().removeContextMenuCloseListener(mContextMenuManager);
         VrShellDelegate.unregisterVrModeObserver(this);
     }
+
+    private void initializeShortcuts() {
+        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.NTP_SHORTCUTS)) return;
+
+        ViewGroup shortcuts =
+                (ViewGroup) mRecyclerView.getAboveTheFoldView().findViewById(R.id.shortcuts);
+        shortcuts.setVisibility(View.VISIBLE);
+
+        shortcuts.findViewById(R.id.bookmarks_button)
+                .setOnClickListener(view -> mManager.getNavigationDelegate().navigateToBookmarks());
+
+        shortcuts.findViewById(R.id.downloads_button)
+                .setOnClickListener(
+                        view -> mManager.getNavigationDelegate().navigateToDownloadManager());
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java
index fa5a7e6d..539375b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java
@@ -531,9 +531,9 @@
             }
 
             // Categories that support adding exceptions also manage the 'Add site' preference.
+            // This should only be used for settings that have host-pattern based exceptions.
             if (mCategory.showAutoplaySites() || mCategory.showBackgroundSyncSites()
-                    || mCategory.showJavaScriptSites() || mCategory.showSoundSites()
-                    || mCategory.showClipboardSites()) {
+                    || mCategory.showJavaScriptSites() || mCategory.showSoundSites()) {
                 if ((boolean) newValue) {
                     Preference addException = getPreferenceScreen().findPreference(
                             ADD_EXCEPTION_KEY);
@@ -566,10 +566,6 @@
             resource = R.string.website_settings_add_site_description_autoplay;
         } else if (mCategory.showBackgroundSyncSites()) {
             resource = R.string.website_settings_add_site_description_background_sync;
-        } else if (mCategory.showClipboardSites()) {
-            resource = PrefServiceBridge.getInstance().isClipboardEnabled()
-                    ? R.string.website_settings_add_site_description_clipboard_block
-                    : R.string.website_settings_add_site_description_clipboard_allow;
         } else if (mCategory.showJavaScriptSites()) {
             resource = R.string.website_settings_add_site_description_javascript;
         } else if (mCategory.showSoundSites()) {
@@ -643,7 +639,7 @@
         if ((mCategory.showAutoplaySites() && !PrefServiceBridge.getInstance().isAutoplayEnabled())
                 || (mCategory.showJavaScriptSites()
                            && !PrefServiceBridge.getInstance().javaScriptEnabled())
-                || mCategory.showSoundSites() || mCategory.showClipboardSites()
+                || mCategory.showSoundSites()
                 || (mCategory.showBackgroundSyncSites()
                            && !PrefServiceBridge.getInstance().isBackgroundSyncAllowed())) {
             getPreferenceScreen().addPreference(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsConfig.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsConfig.java
index 435f3d4..18cd1dc9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsConfig.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsConfig.java
@@ -38,7 +38,7 @@
         // The scroll to load feature does not work well for users who require accessibility mode.
         if (AccessibilityUtil.isAccessibilityEnabled()) return false;
 
-        return FeatureUtilities.isChromeHomeEnabled()
+        return ChromeFeatureList.isEnabled(ChromeFeatureList.NTP_SHORTCUTS)
                 && ChromeFeatureList.isEnabled(
                            ChromeFeatureList.CONTENT_SUGGESTIONS_SCROLL_TO_LOAD);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
index 460ed05..3cadc46 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -584,11 +584,6 @@
             public void onOverviewModeFinishedHiding() {
                 mToolbar.onTabSwitcherTransitionFinished();
             }
-
-            @Override
-            public void onOverviewModeFinishedShowing() {
-                mToolbar.onTabSwitcherTransitionFinished();
-            }
         };
 
         mSceneChangeObserver = new SceneChangeObserver() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
index f20e424a..b1bbe302 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
@@ -207,7 +207,6 @@
      *
      * @return Whether or not chrome should attach the toolbar to the bottom of the screen.
      */
-    @CalledByNative
     public static boolean isChromeHomeEnabled() {
         return false;
     }
@@ -281,8 +280,6 @@
      */
     @CalledByNative
     public static boolean isChromeModernDesignEnabled() {
-        if (isChromeHomeEnabled()) return true;
-
         if (sIsChromeModernDesignEnabled == null) {
             ChromePreferenceManager prefManager = ChromePreferenceManager.getInstance();
             try (StrictModeContext unused = StrictModeContext.allowDiskReads()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ListMenuButton.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ListMenuButton.java
index bdbaa7d6..4147811 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/ListMenuButton.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ListMenuButton.java
@@ -223,7 +223,8 @@
         mPopupMenu = new AnchoredPopupWindow(getContext(), this,
                 ApiCompatibilityUtils.getDrawable(getResources(), R.drawable.menu_bg), contentView,
                 rectProvider);
-        mPopupMenu.setOverlapAnchor(true);
+        mPopupMenu.setVerticalOverlapAnchor(true);
+        mPopupMenu.setHorizontalOverlapAnchor(true);
         mPopupMenu.setMaxWidth(mMenuWidth);
         mPopupMenu.setFocusable(true);
         mPopupMenu.setLayoutObserver(this);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java
index 1eeebb0..698eca6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java
@@ -36,6 +36,7 @@
 import org.chromium.chrome.browser.toolbar.ActionModeController;
 import org.chromium.chrome.browser.toolbar.ToolbarActionModeCallback;
 import org.chromium.chrome.browser.util.FeatureUtilities;
+import org.chromium.chrome.browser.vr_shell.VrShellDelegate;
 import org.chromium.chrome.browser.widget.NumberRollView;
 import org.chromium.chrome.browser.widget.TintedDrawable;
 import org.chromium.chrome.browser.widget.TintedImageButton;
@@ -56,9 +57,9 @@
  *
  * @param <E> The type of the selectable items this toolbar interacts with.
  */
-public class SelectableListToolbar<E> extends Toolbar implements SelectionObserver<E>,
-        OnClickListener, OnEditorActionListener, DisplayStyleObserver {
-
+public class SelectableListToolbar<E>
+        extends Toolbar implements SelectionObserver<E>, OnClickListener, OnEditorActionListener,
+                                   DisplayStyleObserver, VrShellDelegate.VrModeObserver {
     /**
      * A delegate that handles searching the list of selectable items associated with this toolbar.
      */
@@ -116,6 +117,7 @@
     private SearchDelegate mSearchDelegate;
     private boolean mIsLightTheme = true;
     private boolean mSelectableListHasItems;
+    private boolean mIsVrEnabled = false;
 
     protected NumberRollView mNumberRollView;
     private DrawerLayout mDrawerLayout;
@@ -158,6 +160,7 @@
         if (mSelectionDelegate != null) mSelectionDelegate.removeObserver(this);
         mObservers.clear();
         UiUtils.hideKeyboard(mSearchEditText);
+        VrShellDelegate.unregisterVrModeObserver(this);
     }
 
     /**
@@ -222,6 +225,20 @@
         }
     }
 
+    @Override
+    public void onEnterVr() {
+        // TODO(https://crbug.com/817177): Editing text is not supported in VR, so we disable
+        // searching.
+        mIsVrEnabled = true;
+        if (mHasSearchView) updateSearchMenuItem();
+    }
+
+    @Override
+    public void onExitVr() {
+        mIsVrEnabled = false;
+        if (mHasSearchView) updateSearchMenuItem();
+    }
+
     /**
      * Inflates and initializes the search view.
      * @param searchDelegate The delegate that will handle performing searches.
@@ -274,6 +291,9 @@
                     getResources().getDimensionPixelSize(R.dimen.clear_text_button_end_padding),
                     mClearTextButton.getPaddingBottom());
         }
+
+        VrShellDelegate.registerVrModeObserver(this);
+        if (VrShellDelegate.isInVr()) onEnterVr();
     }
 
     @Override
@@ -450,9 +470,7 @@
     protected void onDataChanged(int numItems) {
         if (mHasSearchView) {
             mSelectableListHasItems = numItems != 0;
-            getMenu()
-                    .findItem(mSearchMenuItemId)
-                    .setVisible(!mIsSelectionEnabled && !mIsSearching && mSelectableListHasItems);
+            updateSearchMenuItem();
         }
     }
 
@@ -577,7 +595,7 @@
         getMenu().setGroupVisible(mSelectedGroupResId, false);
         if (mHasSearchView) {
             mSearchView.setVisibility(View.GONE);
-            getMenu().findItem(mSearchMenuItemId).setVisible(mSelectableListHasItems);
+            updateSearchMenuItem();
         }
 
         setNavigationButton(NAVIGATION_BUTTON_MENU);
@@ -626,6 +644,15 @@
         updateDisplayStyleIfNecessary();
     }
 
+    private void updateSearchMenuItem() {
+        if (!mHasSearchView) return;
+        MenuItem searchMenuItem = getMenu().findItem(mSearchMenuItemId);
+        if (searchMenuItem != null) {
+            searchMenuItem.setVisible(mSelectableListHasItems && !mIsSelectionEnabled
+                    && !mIsSearching && !mIsVrEnabled);
+        }
+    }
+
     protected void switchToNumberRollView(List<E> selectedItems, boolean wasSelectionEnabled) {
         setTitle(null);
         mNumberRollView.setVisibility(View.VISIBLE);
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index b65b8ff..7fbc4e4 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -832,12 +832,6 @@
       <message name="IDS_WEBSITE_SETTINGS_ADD_SITE_DESCRIPTION_BACKGROUND_SYNC" desc="The description for the allow Background Sync for website dialog.">
         Allow Background Sync for a specific site.
       </message>
-      <message name="IDS_WEBSITE_SETTINGS_ADD_SITE_DESCRIPTION_CLIPBOARD_ALLOW" desc="The description for the allow clipboard for website dialog.">
-        Allow clipboard read access for a specific site.
-      </message>
-      <message name="IDS_WEBSITE_SETTINGS_ADD_SITE_DESCRIPTION_CLIPBOARD_BLOCK" desc="The description for the block clipboard for website dialog.">
-        Block clipboard read access for a specific site.
-      </message>
       <message name="IDS_WEBSITE_SETTINGS_ADD_SITE_DESCRIPTION_SOUND_ALLOW" desc="The description for the allow sound for website dialog.">
         Allow sound for a specific site.
       </message>
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/DetachedResourceRequestTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/DetachedResourceRequestTest.java
index 69f4d77..ed828b9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/DetachedResourceRequestTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/DetachedResourceRequestTest.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.customtabs;
 
 import android.content.Context;
+import android.content.Intent;
 import android.net.Uri;
 import android.support.customtabs.CustomTabsService;
 import android.support.customtabs.CustomTabsSessionToken;
@@ -26,25 +27,34 @@
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.browserservices.OriginVerifier;
+import org.chromium.chrome.browser.firstrun.FirstRunStatus;
+import org.chromium.chrome.browser.preferences.PrefServiceBridge;
+import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
+import org.chromium.content.browser.test.util.JavaScriptUtils;
+import org.chromium.net.GURLUtils;
 import org.chromium.net.test.EmbeddedTestServer;
 
 /** Tests for detached resource requests. */
 @RunWith(ChromeJUnit4ClassRunner.class)
 public class DetachedResourceRequestTest {
     @Rule
-    public TestRule processor = new Features.InstrumentationProcessor();
+    public TestRule mProcessor = new Features.InstrumentationProcessor();
+    @Rule
+    public CustomTabActivityTestRule mCustomTabActivityTestRule = new CustomTabActivityTestRule();
 
     private CustomTabsConnection mConnection;
     private Context mContext;
+    private EmbeddedTestServer mServer;
 
     private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "chrome";
     private static final String ORIGIN = "http://cats.google.com";
 
     @Before
     public void setUp() throws Exception {
+        ThreadUtils.runOnUiThreadBlocking(() -> FirstRunStatus.setFirstRunFlowComplete(true));
         PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX);
         LibraryLoader.get(LibraryProcessType.PROCESS_BROWSER).ensureInitialized();
         mConnection = CustomTabsTestUtils.setUpConnection();
@@ -56,6 +66,8 @@
     @After
     public void tearDown() throws Exception {
         CustomTabsTestUtils.cleanupSessions(mConnection);
+        if (mServer != null) mServer.stopAndDestroyServer();
+        mServer = null;
     }
 
     @Test
@@ -99,38 +111,109 @@
     @EnableFeatures(ChromeFeatureList.CCT_PARALLEL_REQUEST)
     public void testCanStartParallelRequest() throws Exception {
         CustomTabsSessionToken session = prepareSession();
-
+        mServer = new EmbeddedTestServer();
         final CallbackHelper cb = new CallbackHelper();
-        EmbeddedTestServer server = new EmbeddedTestServer();
-        try {
-            server.initializeNative(mContext, EmbeddedTestServer.ServerHTTPSSetting.USE_HTTP);
-            server.setConnectionListener(new EmbeddedTestServer.ConnectionListener() {
-                @Override
-                public void readFromSocket(long socketId) {
-                    cb.notifyCalled();
-                }
-            });
-            server.start();
+        mServer.initializeNative(mContext, EmbeddedTestServer.ServerHTTPSSetting.USE_HTTP);
+        mServer.setConnectionListener(new EmbeddedTestServer.ConnectionListener() {
+            @Override
+            public void readFromSocket(long socketId) {
+                cb.notifyCalled();
+            }
+        });
+        mServer.start();
 
-            ThreadUtils.runOnUiThread(() -> {
-                String url = server.getURL("/echotitle");
-                Assert.assertTrue(mConnection.startParallelRequest(session, url, ORIGIN));
-            });
-            cb.waitForCallback(0, 1);
-        } finally {
-            server.stopAndDestroyServer();
-        }
+        String url = mServer.getURL("/echotitle");
+        ThreadUtils.runOnUiThread(
+                () -> Assert.assertTrue(mConnection.startParallelRequest(session, url, ORIGIN)));
+        cb.waitForCallback(0, 1);
+    }
+
+    @Test
+    @SmallTest
+    @EnableFeatures(ChromeFeatureList.CCT_PARALLEL_REQUEST)
+    public void testCanSetCookie() throws Exception {
+        CustomTabsSessionToken session = prepareSession();
+        mServer = EmbeddedTestServer.createAndStartServer(mContext);
+        final String url = mServer.getURL("/set-cookie?acookie");
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> Assert.assertTrue(mConnection.startParallelRequest(session, url, ORIGIN)));
+
+        String echoUrl = mServer.getURL("/echoheader?Cookie");
+        Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(mContext, echoUrl);
+        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
+
+        Tab tab = mCustomTabActivityTestRule.getActivity().getActivityTab();
+        String content = JavaScriptUtils.executeJavaScriptAndWaitForResult(
+                tab.getWebContents(), "document.body.textContent");
+        Assert.assertEquals("\"acookie\"", content);
+    }
+
+    @Test
+    @SmallTest
+    @EnableFeatures(ChromeFeatureList.CCT_PARALLEL_REQUEST)
+    public void testCanBlockThirdPartyCookies() throws Exception {
+        CustomTabsSessionToken session = prepareSession();
+        mServer = EmbeddedTestServer.createAndStartServer(mContext);
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            PrefServiceBridge prefs = PrefServiceBridge.getInstance();
+            Assert.assertFalse(prefs.isBlockThirdPartyCookiesEnabled());
+            prefs.setBlockThirdPartyCookiesEnabled(true);
+        });
+        final String url = mServer.getURL("/set-cookie?acookie");
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> Assert.assertTrue(mConnection.startParallelRequest(session, url, ORIGIN)));
+
+        String echoUrl = mServer.getURL("/echoheader?Cookie");
+        Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(mContext, echoUrl);
+        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
+
+        Tab tab = mCustomTabActivityTestRule.getActivity().getActivityTab();
+        String content = JavaScriptUtils.executeJavaScriptAndWaitForResult(
+                tab.getWebContents(), "document.body.textContent");
+        Assert.assertEquals("\"None\"", content);
+    }
+
+    @Test
+    @SmallTest
+    @EnableFeatures(ChromeFeatureList.CCT_PARALLEL_REQUEST)
+    public void testThirdPartyCookieBlockingAllowsFirstParty() throws Exception {
+        CustomTabsTestUtils.warmUpAndWait();
+        mServer = EmbeddedTestServer.createAndStartServer(mContext);
+        ThreadUtils.runOnUiThreadBlocking(() -> {
+            PrefServiceBridge prefs = PrefServiceBridge.getInstance();
+            Assert.assertFalse(prefs.isBlockThirdPartyCookiesEnabled());
+            prefs.setBlockThirdPartyCookiesEnabled(true);
+        });
+        final String url = mServer.getURL("/set-cookie?acookie");
+        String origin = GURLUtils.getOrigin(url);
+        CustomTabsSessionToken session = prepareSession(origin);
+
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> Assert.assertTrue(mConnection.startParallelRequest(session, url, origin)));
+
+        String echoUrl = mServer.getURL("/echoheader?Cookie");
+        Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(mContext, echoUrl);
+        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
+
+        Tab tab = mCustomTabActivityTestRule.getActivity().getActivityTab();
+        String content = JavaScriptUtils.executeJavaScriptAndWaitForResult(
+                tab.getWebContents(), "document.body.textContent");
+        Assert.assertEquals("\"acookie\"", content);
     }
 
     private CustomTabsSessionToken prepareSession() throws Exception {
+        return prepareSession(ORIGIN);
+    }
+
+    private CustomTabsSessionToken prepareSession(String origin) throws Exception {
         final CustomTabsSessionToken session =
                 CustomTabsSessionToken.createMockSessionTokenForTesting();
         Assert.assertTrue(mConnection.newSession(session));
         CustomTabsTestUtils.warmUpAndWait();
         ThreadUtils.runOnUiThreadBlocking(() -> {
-            OriginVerifier.addVerifiedOriginForPackage(mContext.getPackageName(), Uri.parse(ORIGIN),
+            OriginVerifier.addVerifiedOriginForPackage(mContext.getPackageName(), Uri.parse(origin),
                     CustomTabsService.RELATION_USE_AS_ORIGIN);
-            Assert.assertTrue(mConnection.canDoParallelRequest(session, ORIGIN));
+            Assert.assertTrue(mConnection.canDoParallelRequest(session, origin));
         });
         return session;
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java
index c29aa2d2..cb640ff7 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java
@@ -36,6 +36,8 @@
 import static org.hamcrest.Matchers.not;
 import static org.hamcrest.Matchers.startsWith;
 
+import static org.chromium.chrome.test.util.ViewUtils.waitForView;
+
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.content.Intent;
@@ -44,14 +46,11 @@
 import android.support.annotation.Nullable;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.espresso.Espresso;
-import android.support.test.espresso.PerformException;
-import android.support.test.espresso.UiController;
-import android.support.test.espresso.ViewAction;
 import android.support.test.espresso.intent.Intents;
-import android.support.test.espresso.util.TreeIterables;
 import android.support.test.filters.SmallTest;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.LinearLayout;
 
 import org.hamcrest.Matcher;
@@ -81,7 +80,6 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.concurrent.TimeoutException;
 
 /**
  * Tests for the "Save Passwords" settings screen.
@@ -333,39 +331,6 @@
             Thread.sleep(100);
     }
 
-    /**
-     * Waits until a view matching the given matcher appears. Times out if no view was found until
-     * the UI_UPDATING_TIMEOUT_MS expired.
-     * @param viewMatcher The matcher matching the view that should be waited for.
-     */
-    private void waitForView(Matcher<View> viewMatcher) {
-        Espresso.onView(isRoot()).perform(new ViewAction() {
-            @Override
-            public Matcher<View> getConstraints() {
-                return isRoot();
-            }
-
-            @Override
-            public String getDescription() {
-                return "wait for " + UI_UPDATING_TIMEOUT_MS + "ms to match "
-                        + viewMatcher.toString();
-            }
-
-            @Override
-            public void perform(UiController uiController, View root) {
-                final long start_time = System.currentTimeMillis();
-                do {
-                    for (View view : TreeIterables.breadthFirstViewTraversal(root))
-                        if (viewMatcher.matches(view)) return;
-                    uiController.loopMainThreadForAtLeast(100);
-                } while (System.currentTimeMillis() - start_time < UI_UPDATING_TIMEOUT_MS);
-                throw new PerformException.Builder()
-                        .withActionDescription(this.getDescription())
-                        .withCause(new TimeoutException())
-                        .build();
-            }
-        });
-    }
 
     /**
      * Ensure that resetting of empty passwords list works.
@@ -1590,12 +1555,15 @@
         ReauthenticationManager.setApiOverride(ReauthenticationManager.OVERRIDE_STATE_AVAILABLE);
         ReauthenticationManager.setScreenLockSetUpOverride(
                 ReauthenticationManager.OVERRIDE_STATE_AVAILABLE);
-        PreferencesTest.startPreferences(InstrumentationRegistry.getInstrumentation(),
-                SavePasswordsPreferences.class.getName());
+        final Preferences prefs =
+                PreferencesTest.startPreferences(InstrumentationRegistry.getInstrumentation(),
+                        SavePasswordsPreferences.class.getName());
 
         // Open the search and filter all but "Zeus".
         Espresso.onView(withSearchMenuIdOrText()).perform(click());
-        waitForView(withId(R.id.search_src_text));
+
+        Espresso.onView(isRoot()).check(
+                (root, e) -> waitForView((ViewGroup) root, withId(R.id.search_src_text)));
         Espresso.onView(withId(R.id.search_src_text))
                 .perform(click(), typeText("Zeu"), closeSoftKeyboard());
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
@@ -1632,7 +1600,10 @@
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
 
         // The search bar should still be open and still display the search query.
-        waitForView(allOf(withId(R.id.search_src_text), withText("Zeu")));
+        Espresso.onView(isRoot()).check(
+                (root, e)
+                        -> waitForView((ViewGroup) root,
+                                allOf(withId(R.id.search_src_text), withText("Zeu"))));
         Espresso.onView(withId(R.id.search_src_text)).check(matches(withText("Zeu")));
     }
 
@@ -1673,7 +1644,9 @@
         InstrumentationRegistry.getInstrumentation().removeMonitor(monitor);
         Espresso.onView(withContentDescription(R.string.abc_action_bar_up_description))
                 .perform(click()); // Go back to the search list.
-        waitForView(withId(R.id.search_src_text));
+        Espresso.onView(isRoot()).check(
+                (root, e) -> waitForView((ViewGroup) root, withId(R.id.search_src_text)));
+
         Assert.assertEquals(1, viewed_after_search_delta.getDelta());
 
         preferences.finish();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
index 5fe4d1c..c9b270d 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
@@ -104,7 +104,8 @@
 @Config(manifest = Config.NONE, shadows = {CustomShadowAsyncTask.class})
 @DisableFeatures({ChromeFeatureList.NTP_CONDENSED_LAYOUT, ChromeFeatureList.CHROME_HOME,
         ChromeFeatureList.CONTENT_SUGGESTIONS_SCROLL_TO_LOAD,
-        ChromeFeatureList.NTP_ARTICLE_SUGGESTIONS_EXPANDABLE_HEADER})
+        ChromeFeatureList.NTP_ARTICLE_SUGGESTIONS_EXPANDABLE_HEADER,
+        ChromeFeatureList.NTP_SHORTCUTS})
 public class NewTabPageAdapterTest {
     @Rule
     public DisableHistogramsRule mDisableHistogramsRule = new DisableHistogramsRule();
diff --git a/chrome/app/BUILD.gn b/chrome/app/BUILD.gn
index 2df48fa..442ad24 100644
--- a/chrome/app/BUILD.gn
+++ b/chrome/app/BUILD.gn
@@ -444,7 +444,7 @@
       "//ash/components/quick_launch:manifest",
       "//ash/components/touch_hud:manifest",
       "//ash:manifest",
-      "//components/font_service:manifest",
+      "//components/services/font:manifest",
     ]
   }
 }
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 56e8b3d..e741418ac 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2855,8 +2855,8 @@
       "//ash/components/quick_launch/public/mojom:constants",
       "//ash/public/cpp",
       "//chrome/browser/chromeos",
-      "//components/font_service:lib",
-      "//components/font_service/public/interfaces",
+      "//components/services/font:lib",
+      "//components/services/font/public/interfaces",
       "//services/ui/public/cpp/input_devices",
       "//services/ui/public/cpp/input_devices:input_device_controller",
       "//services/ui/public/interfaces",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 0a34f52..9207a97 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -48,6 +48,7 @@
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
 #include "components/dom_distiller/core/dom_distiller_switches.h"
+#include "components/download/public/common/download_features.h"
 #include "components/error_page/common/error_page_switches.h"
 #include "components/favicon/core/features.h"
 #include "components/feature_engagement/public/feature_constants.h"
@@ -2579,12 +2580,15 @@
     {"ntp-modern-layout", flag_descriptions::kNtpModernLayoutName,
      flag_descriptions::kNtpModernLayoutDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(chrome::android::kNTPModernLayoutFeature)},
+    {"ntp-shortcuts", flag_descriptions::kNtpShortcutsName,
+     flag_descriptions::kNtpShortcutsDescription, kOsAndroid,
+     FEATURE_VALUE_TYPE(chrome::android::kNTPShortcuts)},
     {"enable-site-exploration-ui", flag_descriptions::kSiteExplorationUiName,
      flag_descriptions::kSiteExplorationUiDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(ntp_tiles::kSiteExplorationUiFeature)},
     {"ntp-google-g-in-omnibox", flag_descriptions::kNtpGoogleGInOmniboxName,
      flag_descriptions::kNtpGoogleGInOmniboxDescription, kOsAndroid,
-     FEATURE_VALUE_TYPE(chrome::android::NTPShowGoogleGInOmniboxFeature)},
+     FEATURE_VALUE_TYPE(chrome::android::kNTPShowGoogleGInOmniboxFeature)},
 #endif  // OS_ANDROID
     {"user-activation-v2", flag_descriptions::kUserActivationV2Name,
      flag_descriptions::kUserActivationV2Description, kOsAll,
@@ -3204,18 +3208,6 @@
      FEATURE_VALUE_TYPE(
          omnibox::kUIExperimentHideSteadyStateUrlSchemeAndSubdomains)},
 
-    {"omnibox-ui-hide-suggestion-url-scheme",
-     flag_descriptions::kOmniboxUIHideSuggestionUrlSchemeName,
-     flag_descriptions::kOmniboxUIHideSuggestionUrlSchemeDescription, kOsAll,
-     FEATURE_VALUE_TYPE(omnibox::kUIExperimentHideSuggestionUrlScheme)},
-
-    {"omnibox-ui-hide-suggestion-url-trivial-subdomains",
-     flag_descriptions::kOmniboxUIHideSuggestionUrlTrivialSubdomainsName,
-     flag_descriptions::kOmniboxUIHideSuggestionUrlTrivialSubdomainsDescription,
-     kOsAll,
-     FEATURE_VALUE_TYPE(
-         omnibox::kUIExperimentHideSuggestionUrlTrivialSubdomains)},
-
     {"omnibox-ui-show-suggestion-favicons",
      flag_descriptions::kOmniboxUIShowSuggestionFaviconsName,
      flag_descriptions::kOmniboxUIShowSuggestionFaviconsDescription, kOsDesktop,
@@ -3499,7 +3491,7 @@
 
     {"enable-parallel-downloading", flag_descriptions::kParallelDownloadingName,
      flag_descriptions::kParallelDownloadingDescription, kOsAll,
-     FEATURE_VALUE_TYPE(features::kParallelDownloading)},
+     FEATURE_VALUE_TYPE(download::features::kParallelDownloading)},
 
     {"enable-html-base-username-detector",
      flag_descriptions::kHtmlBasedUsernameDetectorName,
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc
index df27db4..90990ca 100644
--- a/chrome/browser/android/chrome_feature_list.cc
+++ b/chrome/browser/android/chrome_feature_list.cc
@@ -101,9 +101,10 @@
     &kNoCreditCardAbort,
     &kNTPCondensedLayoutFeature,
     &kNTPCondensedTileLayoutFeature,
-    &kNTPModernLayoutFeature,
     &kNTPLaunchAfterInactivity,
-    &NTPShowGoogleGInOmniboxFeature,
+    &kNTPModernLayoutFeature,
+    &kNTPShortcuts,
+    &kNTPShowGoogleGInOmniboxFeature,
     &kOmniboxSpareRenderer,
     &kOmniboxVoiceSearchAlwaysVisible,
     &kPayWithGoogleV1,
@@ -318,7 +319,10 @@
 const base::Feature kNTPLaunchAfterInactivity{
     "NTPLaunchAfterInactivity", base::FEATURE_DISABLED_BY_DEFAULT};
 
-const base::Feature NTPShowGoogleGInOmniboxFeature{
+const base::Feature kNTPShortcuts{"NTPShortcuts",
+                                  base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kNTPShowGoogleGInOmniboxFeature{
     "NTPShowGoogleGInOmnibox", base::FEATURE_DISABLED_BY_DEFAULT};
 
 const base::Feature kOmniboxSpareRenderer{"OmniboxSpareRenderer",
diff --git a/chrome/browser/android/chrome_feature_list.h b/chrome/browser/android/chrome_feature_list.h
index 168b475b..66fdf19a 100644
--- a/chrome/browser/android/chrome_feature_list.h
+++ b/chrome/browser/android/chrome_feature_list.h
@@ -60,9 +60,10 @@
 extern const base::Feature kNoCreditCardAbort;
 extern const base::Feature kNTPCondensedLayoutFeature;
 extern const base::Feature kNTPCondensedTileLayoutFeature;
-extern const base::Feature kNTPModernLayoutFeature;
 extern const base::Feature kNTPLaunchAfterInactivity;
-extern const base::Feature NTPShowGoogleGInOmniboxFeature;
+extern const base::Feature kNTPModernLayoutFeature;
+extern const base::Feature kNTPShortcuts;
+extern const base::Feature kNTPShowGoogleGInOmniboxFeature;
 extern const base::Feature kOmniboxSpareRenderer;
 extern const base::Feature kOmniboxVoiceSearchAlwaysVisible;
 extern const base::Feature kPayWithGoogleV1;
diff --git a/chrome/browser/android/feature_utilities.cc b/chrome/browser/android/feature_utilities.cc
index 6fdddef..c61f20a 100644
--- a/chrome/browser/android/feature_utilities.cc
+++ b/chrome/browser/android/feature_utilities.cc
@@ -30,11 +30,6 @@
   return is_in_multi_window_mode;
 }
 
-bool GetIsChromeHomeEnabled() {
-  JNIEnv* env = base::android::AttachCurrentThread();
-  return Java_FeatureUtilities_isChromeHomeEnabled(env);
-}
-
 bool GetIsChromeModernDesignEnabled() {
   JNIEnv* env = base::android::AttachCurrentThread();
   return Java_FeatureUtilities_isChromeModernDesignEnabled(env);
diff --git a/chrome/browser/android/feature_utilities.h b/chrome/browser/android/feature_utilities.h
index c031410..782c09b 100644
--- a/chrome/browser/android/feature_utilities.h
+++ b/chrome/browser/android/feature_utilities.h
@@ -20,8 +20,6 @@
 
 bool GetIsInMultiWindowModeValue();
 
-bool GetIsChromeHomeEnabled();
-
 bool GetIsChromeModernDesignEnabled();
 
 } // namespace android
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm
index e7dd7e00..0074196 100644
--- a/chrome/browser/app_controller_mac.mm
+++ b/chrome/browser/app_controller_mac.mm
@@ -737,8 +737,14 @@
 
   [self openUrls:urls];
 
+  // In test environments where there is no network connection, the visible NTP
+  // URL may be chrome-search://local-ntp/local-ntp.html instead of
+  // chrome://newtab/. See local_ntp_test_utils::GetFinalNtpUrl for more
+  // details.
+  // This NTP check should be replaced once https://crbug.com/624410 is fixed.
   if (startupIndex != TabStripModel::kNoTab &&
-      startupContent->GetVisibleURL() == chrome::kChromeUINewTabURL) {
+      (startupContent->GetVisibleURL() == chrome::kChromeUINewTabURL ||
+       startupContent->GetVisibleURL() == chrome::kChromeSearchLocalNtpUrl)) {
     browser->tab_strip_model()->CloseWebContentsAt(startupIndex,
         TabStripModel::CLOSE_NONE);
   }
diff --git a/chrome/browser/app_controller_mac_browsertest.mm b/chrome/browser/app_controller_mac_browsertest.mm
index 65852221..02823f79 100644
--- a/chrome/browser/app_controller_mac_browsertest.mm
+++ b/chrome/browser/app_controller_mac_browsertest.mm
@@ -36,6 +36,7 @@
 #include "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.h"
 #include "chrome/browser/ui/cocoa/history_menu_bridge.h"
 #include "chrome/browser/ui/cocoa/test/run_loop_testing.h"
+#include "chrome/browser/ui/search/local_ntp_test_utils.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/user_manager.h"
 #include "chrome/common/chrome_constants.h"
@@ -462,11 +463,17 @@
 // Tests that when a GURL is opened after startup, it replaces the NTP.
 IN_PROC_BROWSER_TEST_F(AppControllerReplaceNTPBrowserTest,
                        ReplaceNTPAfterStartup) {
+  // Depending on network connectivity, the NTP URL can either be
+  // chrome://newtab/ or chrome-search://local-ntp/local-ntp.html. See
+  // local_ntp_test_utils::GetFinalNtpUrl for more details.
+  std::string expected_url =
+      local_ntp_test_utils::GetFinalNtpUrl(browser()->profile()).spec();
+
   // Ensure that there is exactly 1 tab showing, and the tab is the NTP.
-  GURL ntp(chrome::kChromeUINewTabURL);
+  GURL ntp(expected_url);
   EXPECT_EQ(1, browser()->tab_strip_model()->count());
   browser()->tab_strip_model()->GetActiveWebContents()->GetController().LoadURL(
-      GURL(chrome::kChromeUINewTabURL), content::Referrer(),
+      GURL(expected_url), content::Referrer(),
       ui::PageTransition::PAGE_TRANSITION_LINK, std::string());
 
   // Wait for one navigation on the active web contents.
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index f1e7159df..57daee4 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -46,6 +46,7 @@
 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
 #include "chrome/browser/defaults.h"
 #include "chrome/browser/download/download_prefs.h"
+#include "chrome/browser/external_protocol/external_protocol_handler.h"
 #include "chrome/browser/font_family_cache.h"
 #include "chrome/browser/language/chrome_language_detection_tab_helper.h"
 #include "chrome/browser/media/platform_verification_impl.h"
@@ -71,6 +72,7 @@
 #include "chrome/browser/prerender/prerender_manager.h"
 #include "chrome/browser/prerender/prerender_manager_factory.h"
 #include "chrome/browser/prerender/prerender_message_filter.h"
+#include "chrome/browser/prerender/prerender_util.h"
 #include "chrome/browser/printing/printing_message_filter.h"
 #include "chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.h"
 #include "chrome/browser/profiles/profile.h"
@@ -836,6 +838,51 @@
 #endif
 }
 
+void LaunchURL(
+    const GURL& url,
+    const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
+    ui::PageTransition page_transition,
+    bool has_user_gesture) {
+  // If there is no longer a WebContents, the request may have raced with tab
+  // closing. Don't fire the external request. (It may have been a prerender.)
+  content::WebContents* web_contents = web_contents_getter.Run();
+  if (!web_contents)
+    return;
+
+  // Do not launch external requests attached to unswapped prerenders.
+  prerender::PrerenderContents* prerender_contents =
+      prerender::PrerenderContents::FromWebContents(web_contents);
+  if (prerender_contents) {
+    prerender_contents->Destroy(prerender::FINAL_STATUS_UNSUPPORTED_SCHEME);
+    prerender::ReportPrerenderExternalURL();
+    return;
+  }
+
+  bool is_whitelisted = false;
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents->GetBrowserContext());
+  PolicyBlacklistService* service =
+      PolicyBlacklistFactory::GetForProfile(profile);
+  if (service) {
+    const policy::URLBlacklist::URLBlacklistState url_state =
+        service->GetURLBlacklistState(url);
+    is_whitelisted =
+        url_state == policy::URLBlacklist::URLBlacklistState::URL_IN_WHITELIST;
+  }
+
+  // If the URL is in whitelist, we launch it without asking the user and
+  // without any additional security checks. Since the URL is whitelisted,
+  // we assume it can be executed.
+  if (is_whitelisted) {
+    ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(url, web_contents);
+  } else {
+    ExternalProtocolHandler::LaunchUrl(
+        url, web_contents->GetRenderViewHost()->GetProcess()->GetID(),
+        web_contents->GetRenderViewHost()->GetRoutingID(), page_transition,
+        has_user_gesture);
+  }
+}
+
 }  // namespace
 
 ChromeContentBrowserClient::ChromeContentBrowserClient()
@@ -3996,6 +4043,41 @@
                            auth_required_callback);
 }
 
+bool ChromeContentBrowserClient::HandleExternalProtocol(
+    const GURL& url,
+    content::ResourceRequestInfo::WebContentsGetter web_contents_getter,
+    int child_id,
+    content::NavigationUIData* navigation_data,
+    bool is_main_frame,
+    ui::PageTransition page_transition,
+    bool has_user_gesture) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  // External protocols are disabled for guests. An exception is made for the
+  // "mailto" protocol, so that pages that utilize it work properly in a
+  // WebView.
+  ChromeNavigationUIData* chrome_data =
+      static_cast<ChromeNavigationUIData*>(navigation_data);
+  if ((extensions::WebViewRendererState::GetInstance()->IsGuest(child_id) ||
+       (chrome_data &&
+        chrome_data->GetExtensionNavigationUIData()->is_web_view())) &&
+      !url.SchemeIs(url::kMailToScheme)) {
+    return false;
+  }
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
+
+#if defined(OS_ANDROID)
+  // Main frame external protocols are handled by
+  // InterceptNavigationResourceThrottle.
+  if (is_main_frame)
+    return false;
+#endif  // defined(ANDROID)
+
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                          base::BindOnce(&LaunchURL, url, web_contents_getter,
+                                         page_transition, has_user_gesture));
+  return true;
+}
+
 // Static; handles rewriting Web UI URLs.
 bool ChromeContentBrowserClient::HandleWebUI(
     GURL* url,
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index fa4c647c..dd5c867e 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -426,6 +426,14 @@
       bool first_auth_attempt,
       const base::Callback<void(const base::Optional<net::AuthCredentials>&)>&
           auth_required_callback) override;
+  bool HandleExternalProtocol(
+      const GURL& url,
+      content::ResourceRequestInfo::WebContentsGetter web_contents_getter,
+      int child_id,
+      content::NavigationUIData* navigation_data,
+      bool is_main_frame,
+      ui::PageTransition page_transition,
+      bool has_user_gesture) override;
 
  protected:
   static bool HandleWebUI(GURL* url, content::BrowserContext* browser_context);
diff --git a/chrome/browser/chrome_plugin_browsertest.cc b/chrome/browser/chrome_plugin_browsertest.cc
index 5e6c17b..fdf2b7d 100644
--- a/chrome/browser/chrome_plugin_browsertest.cc
+++ b/chrome/browser/chrome_plugin_browsertest.cc
@@ -214,7 +214,7 @@
   EnsureFlashProcessCount(1);
 }
 
-#if defined(OFFICIAL_BUILD)
+#if defined(GOOGLE_CHROME_BUILD)
 // Verify that the official builds have the known set of plugins.
 IN_PROC_BROWSER_TEST_F(ChromePluginTest, InstalledPlugins) {
   const char* expected[] = {
diff --git a/chrome/browser/chrome_site_per_process_browsertest.cc b/chrome/browser/chrome_site_per_process_browsertest.cc
index 37f72267..74646a28 100644
--- a/chrome/browser/chrome_site_per_process_browsertest.cc
+++ b/chrome/browser/chrome_site_per_process_browsertest.cc
@@ -15,7 +15,6 @@
 #include "chrome/browser/chrome_content_browser_client.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/external_protocol/external_protocol_handler.h"
-#include "chrome/browser/loader/chrome_resource_dispatcher_host_delegate.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/renderer_context_menu/render_view_context_menu_browsertest_util.h"
 #include "chrome/browser/ui/browser.h"
@@ -525,8 +524,7 @@
   ui_test_utils::NavigateToURL(browser(), mailto_main_frame_url);
 
   MailtoExternalProtocolHandlerDelegate delegate;
-  ChromeResourceDispatcherHostDelegate::
-      SetExternalProtocolHandlerDelegateForTesting(&delegate);
+  ExternalProtocolHandler::SetDelegateForTesting(&delegate);
 
   GURL mailto_subframe_url(
       embedded_test_server()->GetURL("c.com", "/page_with_mailto.html"));
@@ -540,8 +538,7 @@
   EXPECT_TRUE(delegate.has_triggered_external_protocol());
   EXPECT_EQ(delegate.external_protocol_url(), GURL("mailto:mail@example.org"));
   EXPECT_EQ(active_web_contents, delegate.web_contents());
-  ChromeResourceDispatcherHostDelegate::
-      SetExternalProtocolHandlerDelegateForTesting(nullptr);
+  ExternalProtocolHandler::SetDelegateForTesting(nullptr);
 }
 
 // Verify that a popup can be opened after navigating a remote frame.  This has
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 5d9a50c..508d61f 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -130,6 +130,7 @@
     "//components/viz/host",
     "//services/identity/public/cpp",
     "//services/metrics/public/cpp:ukm_builders",
+    "//services/network:network_service",
     "//services/resource_coordinator/public/cpp:resource_coordinator_cpp",
     "//third_party/fontconfig",
     "//third_party/metrics_proto",
diff --git a/chrome/browser/chromeos/DEPS b/chrome/browser/chromeos/DEPS
index 87350f5..cb59aa29 100644
--- a/chrome/browser/chromeos/DEPS
+++ b/chrome/browser/chromeos/DEPS
@@ -27,6 +27,7 @@
   "+mojo/edk/embedder",
   "+services/device/public",
   "+services/metrics/public",
+  "+services/network",
   "+services/tracing/public",
   "+services/viz/public/interfaces",
   # Chromeos should not use ozone directly, it must go through mojo as ozone
diff --git a/chrome/browser/chromeos/arc/arc_session_manager.cc b/chrome/browser/chromeos/arc/arc_session_manager.cc
index e9531ba..ba2b8c7e 100644
--- a/chrome/browser/chromeos/arc/arc_session_manager.cc
+++ b/chrome/browser/chromeos/arc/arc_session_manager.cc
@@ -730,7 +730,7 @@
     scoped_opt_in_tracker_ = std::make_unique<ScopedOptInFlowTracker>();
   }
 
-  if (!IsArcTermsOfServiceNegotiationNeeded()) {
+  if (!IsArcTermsOfServiceNegotiationNeeded(profile_)) {
     // Moves to next state, Android management check, immediately, as if
     // Terms of Service negotiation is done successfully.
     StartAndroidManagementCheck();
@@ -783,33 +783,6 @@
   StartAndroidManagementCheck();
 }
 
-bool ArcSessionManager::IsArcTermsOfServiceNegotiationNeeded() const {
-  DCHECK(profile_);
-
-  // Skip to show UI asking users to set up ARC OptIn preferences, if all of
-  // them are managed by the admin policy. Note that the ToS agreement is anyway
-  // not shown in the case of the managed ARC.
-  if (IsArcPlayStoreEnabledPreferenceManagedForProfile(profile_) &&
-      AreArcAllOptInPreferencesIgnorableForProfile(profile_)) {
-    VLOG(1) << "All opt-in preferences are under managed. "
-            << "Skip ARC Terms of Service negotiation.";
-    return false;
-  }
-
-  // If it is marked that the Terms of service is accepted already,
-  // just skip the negotiation with user, and start Android management
-  // check directly.
-  // This happens, e.g., when a user accepted the Terms of service on Opt-in
-  // flow, but logged out before ARC sign in procedure was done. Then, logs
-  // in again.
-  if (profile_->GetPrefs()->GetBoolean(prefs::kArcTermsAccepted)) {
-    VLOG(1) << "The user already accepts ARC Terms of Service.";
-    return false;
-  }
-
-  return true;
-}
-
 void ArcSessionManager::StartAndroidManagementCheck() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(state_ == State::NEGOTIATING_TERMS_OF_SERVICE ||
diff --git a/chrome/browser/chromeos/arc/arc_session_manager.h b/chrome/browser/chromeos/arc/arc_session_manager.h
index dfb8d66..c9e561c0 100644
--- a/chrome/browser/chromeos/arc/arc_session_manager.h
+++ b/chrome/browser/chromeos/arc/arc_session_manager.h
@@ -283,11 +283,6 @@
   void MaybeStartTermsOfServiceNegotiation();
   void OnTermsOfServiceNegotiated(bool accepted);
 
-  // Returns true if Terms of Service negotiation is needed. Otherwise false.
-  // TODO(crbug.com/698418): Write unittest for this utility after extracting
-  //   ToS related code from ArcSessionManager into a dedicated class.
-  bool IsArcTermsOfServiceNegotiationNeeded() const;
-
   void ShutdownSession();
   void ResetArcState();
   void OnArcSignInTimeout();
diff --git a/chrome/browser/chromeos/arc/arc_util.cc b/chrome/browser/chromeos/arc/arc_util.cc
index fa0d78d1..d7d4b62ed 100644
--- a/chrome/browser/chromeos/arc/arc_util.cc
+++ b/chrome/browser/chromeos/arc/arc_util.cc
@@ -27,6 +27,7 @@
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
 #include "chromeos/chromeos_switches.h"
 #include "components/arc/arc_prefs.h"
 #include "components/arc/arc_util.h"
@@ -101,14 +102,12 @@
   if (is_compatible) {
     user_manager::known_user::SetIntegerPref(
         account_id, prefs::kArcCompatibleFilesystemChosen,
-        arc::kFileSystemCompatible);
+        kFileSystemCompatible);
 
     // TODO(kinaba): Remove this code for accounts without user prefs.
     // See the comment for |g_known_compatible_users| for the detail.
-    if (GetFileSystemCompatibilityPref(account_id) !=
-        arc::kFileSystemCompatible) {
+    if (GetFileSystemCompatibilityPref(account_id) != kFileSystemCompatible)
       g_known_compatible_users.Get().insert(account_id);
-    }
   }
   callback.Run();
 }
@@ -440,6 +439,73 @@
   return true;
 }
 
+bool IsArcTermsOfServiceNegotiationNeeded(const Profile* profile) {
+  DCHECK(profile);
+
+  // Skip to show UI asking users to set up ARC OptIn preferences, if all of
+  // them are managed by the admin policy. Note that the ToS agreement is anyway
+  // not shown in the case of the managed ARC.
+  if (IsArcPlayStoreEnabledPreferenceManagedForProfile(profile) &&
+      AreArcAllOptInPreferencesIgnorableForProfile(profile)) {
+    VLOG(1) << "All opt-in preferences are under managed. "
+            << "Skip ARC Terms of Service negotiation.";
+    return false;
+  }
+
+  // If it is marked that the Terms of service is accepted already,
+  // just skip the negotiation with user, and start Android management
+  // check directly.
+  // This happens, e.g., when a user accepted the Terms of service on Opt-in
+  // flow, but logged out before ARC sign in procedure was done. Then, logs
+  // in again.
+  if (profile->GetPrefs()->GetBoolean(prefs::kArcTermsAccepted)) {
+    VLOG(1) << "The user already accepts ARC Terms of Service.";
+    return false;
+  }
+
+  return true;
+}
+
+bool IsArcTermsOfServiceOobeNegotiationNeeded() {
+  if (!user_manager::UserManager::Get()->IsUserLoggedIn()) {
+    VLOG(1) << "Skip ARC Terms of Service screen because user is not "
+            << "logged in.";
+    return false;
+  }
+
+  const Profile* profile = ProfileManager::GetActiveUserProfile();
+  if (!IsArcAllowedForProfile(profile)) {
+    VLOG(1) << "Skip ARC Terms of Service screen because ARC is not allowed.";
+    return false;
+  }
+
+  if (profile->GetPrefs()->IsManagedPreference(prefs::kArcEnabled) &&
+      !profile->GetPrefs()->GetBoolean(prefs::kArcEnabled)) {
+    VLOG(1) << "Skip ARC Terms of Service screen because ARC is disabled.";
+    return false;
+  }
+
+  if (!IsPlayStoreAvailable()) {
+    VLOG(1) << "Skip ARC Terms of Service screen because Play Store is not "
+               "available on the device.";
+    return false;
+  }
+
+  if (IsActiveDirectoryUserForProfile(profile)) {
+    VLOG(1) << "Skip ARC Terms of Service screen because it does not apply to "
+               "Active Directory users.";
+    return false;
+  }
+
+  if (!IsArcTermsOfServiceNegotiationNeeded(profile)) {
+    VLOG(1) << "Skip ARC Terms of Service screen because it is already "
+               "accepted or fully controlled by policy.";
+    return false;
+  }
+
+  return true;
+}
+
 void UpdateArcFileSystemCompatibilityPrefIfNeeded(
     const AccountId& account_id,
     const base::FilePath& profile_path,
diff --git a/chrome/browser/chromeos/arc/arc_util.h b/chrome/browser/chromeos/arc/arc_util.h
index 73f2f58..404240af 100644
--- a/chrome/browser/chromeos/arc/arc_util.h
+++ b/chrome/browser/chromeos/arc/arc_util.h
@@ -122,6 +122,14 @@
 // Returns true if ChromeOS OOBE opt-in window is currently showing.
 bool IsArcOobeOptInActive();
 
+// Returns true if Terms of Service negotiation is needed. Otherwise false.
+bool IsArcTermsOfServiceNegotiationNeeded(const Profile* profile);
+
+// Returns true if Terms of Service negotiation is needed in OOBE flow.
+// Otherwise false. Similar to IsArcTermsOfServiceNegotiationNeeded but
+// also checks set of preconditions and uses active user profile.
+bool IsArcTermsOfServiceOobeNegotiationNeeded();
+
 // Checks and updates the preference value whether the underlying filesystem
 // for the profile is compatible with ARC, when necessary. After it's done (or
 // skipped), |callback| is run either synchronously or asynchronously.
diff --git a/chrome/browser/chromeos/arc/arc_util_unittest.cc b/chrome/browser/chromeos/arc/arc_util_unittest.cc
index 74a212e..c53301af 100644
--- a/chrome/browser/chromeos/arc/arc_util_unittest.cc
+++ b/chrome/browser/chromeos/arc/arc_util_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/test/icu_test_util.h"
 #include "base/test/scoped_command_line.h"
 #include "base/values.h"
+#include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/arc/arc_session_manager.h"
 #include "chrome/browser/chromeos/login/supervised/supervised_user_creation_flow.h"
 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
@@ -25,7 +26,9 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/ash/test_wallpaper_controller.h"
 #include "chrome/browser/ui/ash/wallpaper_controller_client.h"
+#include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/testing_profile_manager.h"
 #include "chromeos/chromeos_switches.h"
 #include "components/arc/arc_prefs.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
@@ -37,6 +40,8 @@
 #include "components/user_manager/scoped_user_manager.h"
 #include "components/user_manager/user_manager.h"
 #include "components/user_manager/user_names.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/common/content_switches.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -54,13 +59,53 @@
   connector->OverrideIsManagedForTesting(true);
 }
 
+void DisableDBusForProfileManager() {
+  // Prevent access to DBus. This switch is reset in case set from test SetUp
+  // due massive usage of InitFromArgv.
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  if (!command_line->HasSwitch(switches::kTestType))
+    command_line->AppendSwitch(switches::kTestType);
+}
+
+class FakeUserManagerWithLocalState : public chromeos::FakeChromeUserManager {
+ public:
+  explicit FakeUserManagerWithLocalState(
+      TestingProfileManager* testing_profile_manager)
+      : testing_profile_manager_(testing_profile_manager),
+        test_local_state_(std::make_unique<TestingPrefServiceSimple>()) {
+    RegisterPrefs(test_local_state_->registry());
+  }
+
+  PrefService* GetLocalState() const override {
+    return test_local_state_.get();
+  }
+
+  TestingProfileManager* testing_profile_manager() {
+    return testing_profile_manager_;
+  }
+
+ private:
+  // Unowned pointer.
+  TestingProfileManager* const testing_profile_manager_;
+
+  std::unique_ptr<TestingPrefServiceSimple> test_local_state_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeUserManagerWithLocalState);
+};
+
 class ScopedLogIn {
  public:
   ScopedLogIn(
-      chromeos::FakeChromeUserManager* fake_user_manager,
+      FakeUserManagerWithLocalState* fake_user_manager,
       const AccountId& account_id,
       user_manager::UserType user_type = user_manager::USER_TYPE_REGULAR)
       : fake_user_manager_(fake_user_manager), account_id_(account_id) {
+    // Prevent access to DBus. This switch is reset in case set from test SetUp
+    // due massive usage of InitFromArgv.
+    base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();
+    if (!command_line.HasSwitch(switches::kTestType))
+      command_line.AppendSwitch(switches::kTestType);
+
     switch (user_type) {
       case user_manager::USER_TYPE_REGULAR:  // fallthrough
       case user_manager::USER_TYPE_ACTIVE_DIRECTORY:
@@ -75,9 +120,13 @@
       default:
         NOTREACHED();
     }
+    fake_user_manager_->testing_profile_manager()->SetLoggedIn(true);
   }
 
-  ~ScopedLogIn() { LogOut(); }
+  ~ScopedLogIn() {
+    fake_user_manager_->testing_profile_manager()->SetLoggedIn(false);
+    LogOut();
+  }
 
  private:
   void LogIn() {
@@ -97,7 +146,7 @@
 
   void LogOut() { fake_user_manager_->RemoveUserFromList(account_id_); }
 
-  chromeos::FakeChromeUserManager* fake_user_manager_;
+  FakeUserManagerWithLocalState* fake_user_manager_;
   const AccountId account_id_;
 
   DISALLOW_COPY_AND_ASSIGN(ScopedLogIn);
@@ -119,23 +168,6 @@
   }
 };
 
-class FakeUserManagerWithLocalState : public chromeos::FakeChromeUserManager {
- public:
-  FakeUserManagerWithLocalState()
-      : test_local_state_(std::make_unique<TestingPrefServiceSimple>()) {
-    RegisterPrefs(test_local_state_->registry());
-  }
-
-  PrefService* GetLocalState() const override {
-    return test_local_state_.get();
-  }
-
- private:
-  std::unique_ptr<TestingPrefServiceSimple> test_local_state_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeUserManagerWithLocalState);
-};
-
 bool IsArcAllowedForProfileOnFirstCall(const Profile* profile) {
   ResetArcAllowedCheckForTesting(profile);
   return IsArcAllowedForProfile(profile);
@@ -151,8 +183,14 @@
   void SetUp() override {
     command_line_ = std::make_unique<base::test::ScopedCommandLine>();
 
+    ASSERT_TRUE(data_dir_.CreateUniqueTempDir());
+    profile_manager_ = std::make_unique<TestingProfileManager>(
+        TestingBrowserProcess::GetGlobal());
+    ASSERT_TRUE(profile_manager_->SetUp());
+
     user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>(
-        std::make_unique<FakeUserManagerWithLocalState>());
+        std::make_unique<FakeUserManagerWithLocalState>(
+            profile_manager_.get()));
     // Used by FakeChromeUserManager.
     chromeos::DeviceSettingsService::Initialize();
     chromeos::CrosSettings::Initialize();
@@ -161,21 +199,23 @@
     wallpaper_controller_client_->InitForTesting(
         test_wallpaper_controller_.CreateInterfacePtr());
 
-    profile_ = std::make_unique<TestingProfile>();
-    profile_->set_profile_name(kTestProfileName);
+    profile_ = profile_manager_->CreateTestingProfile(kTestProfileName);
   }
 
   void TearDown() override {
-    profile_.reset();
-    user_manager_enabler_.reset();
+    profile_manager_->DeleteTestingProfile(kTestProfileName);
+    profile_ = nullptr;
     command_line_.reset();
     wallpaper_controller_client_.reset();
+    chromeos::CrosSettings::Shutdown();
+    chromeos::DeviceSettingsService::Shutdown();
+    user_manager_enabler_.reset();
   }
 
-  TestingProfile* profile() { return profile_.get(); }
+  TestingProfile* profile() { return profile_; }
 
-  chromeos::FakeChromeUserManager* GetFakeUserManager() const {
-    return static_cast<chromeos::FakeChromeUserManager*>(
+  FakeUserManagerWithLocalState* GetFakeUserManager() const {
+    return static_cast<FakeUserManagerWithLocalState*>(
         user_manager::UserManager::Get());
   }
 
@@ -191,8 +231,11 @@
   TestWallpaperController test_wallpaper_controller_;
   std::unique_ptr<base::test::ScopedCommandLine> command_line_;
   content::TestBrowserThreadBundle thread_bundle_;
+  base::ScopedTempDir data_dir_;
+  std::unique_ptr<TestingProfileManager> profile_manager_;
   std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_;
-  std::unique_ptr<TestingProfile> profile_;
+  // Owned by |profile_manager_|
+  TestingProfile* profile_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(ChromeArcUtilTest);
 };
@@ -623,6 +666,77 @@
   EXPECT_TRUE(IsActiveDirectoryUserForProfile(profile()));
 }
 
+TEST_F(ChromeArcUtilTest, TermsOfServiceNegotiationNeededForAlreadyAccepted) {
+  base::CommandLine::ForCurrentProcess()->InitFromArgv(
+      {"", "--arc-availability=officially-supported"});
+  DisableDBusForProfileManager();
+  ScopedLogIn login(GetFakeUserManager(),
+                    AccountId::FromUserEmailGaiaId(
+                        profile()->GetProfileUserName(), kTestGaiaId));
+  EXPECT_TRUE(IsArcTermsOfServiceNegotiationNeeded(profile()));
+  EXPECT_TRUE(IsArcTermsOfServiceOobeNegotiationNeeded());
+  profile()->GetPrefs()->SetBoolean(prefs::kArcTermsAccepted, true);
+  EXPECT_FALSE(IsArcTermsOfServiceNegotiationNeeded(profile()));
+  EXPECT_FALSE(IsArcTermsOfServiceOobeNegotiationNeeded());
+}
+
+TEST_F(ChromeArcUtilTest, TermsOfServiceNegotiationNeededForManagedUser) {
+  base::CommandLine::ForCurrentProcess()->InitFromArgv(
+      {"", "--arc-availability=officially-supported"});
+  DisableDBusForProfileManager();
+  ScopedLogIn login(GetFakeUserManager(),
+                    AccountId::FromUserEmailGaiaId(
+                        profile()->GetProfileUserName(), kTestGaiaId));
+  SetProfileIsManagedForTesting(profile());
+  profile()->GetTestingPrefService()->SetManagedPref(
+      prefs::kArcEnabled, std::make_unique<base::Value>(true));
+  EXPECT_TRUE(IsArcTermsOfServiceNegotiationNeeded(profile()));
+  EXPECT_TRUE(IsArcTermsOfServiceOobeNegotiationNeeded());
+  profile()->GetTestingPrefService()->SetManagedPref(
+      prefs::kArcBackupRestoreEnabled, std::make_unique<base::Value>(false));
+  EXPECT_TRUE(IsArcTermsOfServiceNegotiationNeeded(profile()));
+  EXPECT_TRUE(IsArcTermsOfServiceOobeNegotiationNeeded());
+  profile()->GetTestingPrefService()->SetManagedPref(
+      prefs::kArcLocationServiceEnabled, std::make_unique<base::Value>(false));
+  EXPECT_FALSE(IsArcTermsOfServiceNegotiationNeeded(profile()));
+  EXPECT_FALSE(IsArcTermsOfServiceOobeNegotiationNeeded());
+}
+
+TEST_F(ChromeArcUtilTest, TermsOfServiceOobeNegotiationNeededNoLogin) {
+  DisableDBusForProfileManager();
+  EXPECT_FALSE(IsArcTermsOfServiceOobeNegotiationNeeded());
+}
+
+TEST_F(ChromeArcUtilTest,
+       TermsOfServiceOobeNegotiationNeededNoArcAvailability) {
+  DisableDBusForProfileManager();
+  ScopedLogIn login(GetFakeUserManager(),
+                    AccountId::FromUserEmailGaiaId(
+                        profile()->GetProfileUserName(), kTestGaiaId));
+  EXPECT_FALSE(IsArcTermsOfServiceOobeNegotiationNeeded());
+}
+
+TEST_F(ChromeArcUtilTest, TermsOfServiceOobeNegotiationNeededNoPlayStore) {
+  base::CommandLine::ForCurrentProcess()->InitFromArgv(
+      {"", "--arc-availability=officially-supported",
+       "--arc-start-mode=always-start-with-no-play-store"});
+  DisableDBusForProfileManager();
+  ScopedLogIn login(GetFakeUserManager(),
+                    AccountId::FromUserEmailGaiaId(
+                        profile()->GetProfileUserName(), kTestGaiaId));
+  EXPECT_FALSE(IsArcTermsOfServiceOobeNegotiationNeeded());
+}
+
+TEST_F(ChromeArcUtilTest, TermsOfServiceOobeNegotiationNeededAdUser) {
+  base::CommandLine::ForCurrentProcess()->InitFromArgv(
+      {"", "--arc-availability=officially-supported"});
+  DisableDBusForProfileManager();
+  ScopedLogIn login(GetFakeUserManager(),
+                    AccountId::AdFromUserEmailObjGuid(
+                        profile()->GetProfileUserName(), kTestGaiaId));
+  EXPECT_FALSE(IsArcTermsOfServiceOobeNegotiationNeeded());
+}
+
 using ArcMigrationTest = ChromeArcUtilTest;
 
 TEST_F(ArcMigrationTest, IsMigrationAllowedUnmanagedUser) {
diff --git a/chrome/browser/chromeos/customization/customization_document.cc b/chrome/browser/chromeos/customization/customization_document.cc
index f7bde92a..ce55b999 100644
--- a/chrome/browser/chromeos/customization/customization_document.cc
+++ b/chrome/browser/chromeos/customization/customization_document.cc
@@ -34,6 +34,7 @@
 #include "chrome/browser/chromeos/net/delay_network_call.h"
 #include "chrome/browser/extensions/external_loader.h"
 #include "chrome/browser/extensions/external_provider_impl.h"
+#include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/app_list_syncable_service.h"
 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
@@ -44,11 +45,14 @@
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/storage_partition.h"
 #include "extensions/common/extension_urls.h"
 #include "net/base/load_flags.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_status_code.h"
-#include "net/url_request/url_fetcher.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/url_loader_factory.h"
 
 namespace chromeos {
 namespace {
@@ -570,14 +574,41 @@
 }
 
 void ServicesCustomizationDocument::DoStartFileFetch() {
-  url_fetcher_ = net::URLFetcher::Create(url_, net::URLFetcher::GET, this);
-  url_fetcher_->SetRequestContext(g_browser_process->system_request_context());
-  url_fetcher_->AddExtraRequestHeader("Accept: application/json");
-  url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
-                             net::LOAD_DO_NOT_SAVE_COOKIES |
-                             net::LOAD_DISABLE_CACHE |
-                             net::LOAD_DO_NOT_SEND_AUTH_DATA);
-  url_fetcher_->Start();
+  net::NetworkTrafficAnnotationTag traffic_annotation =
+      net::DefineNetworkTrafficAnnotation("chromeos_customization_document", R"(
+          semantics {
+            sender: "Chrome OS Services Customization"
+            description:
+              "Chrome OS downloads the OEM services customization manifest."
+            trigger:
+              "When a public session starts on managed devices and an OEM "
+              "has uploaded a service customization document."
+            data:
+              "URL of the OEM service customization document. "
+              "No user information is sent."
+            destination: WEBSITE
+          }
+          policy {
+            cookies_allowed: NO
+            setting: "Unconditionally enabled on Chrome OS."
+          })");
+  auto resource_request = std::make_unique<network::ResourceRequest>();
+  resource_request->url = url_;
+  resource_request->load_flags =
+      net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES |
+      net::LOAD_DISABLE_CACHE | net::LOAD_DO_NOT_SEND_AUTH_DATA;
+  resource_request->headers.SetHeader("Accept", "application/json");
+  simple_loader_ = network::SimpleURLLoader::Create(std::move(resource_request),
+                                                    traffic_annotation);
+  network::mojom::URLLoaderFactory* loader_factory = url_loader_factory_;
+  if (!loader_factory) {
+    loader_factory = g_browser_process->system_network_context_manager()
+                         ->GetURLLoaderFactory();
+  }
+  simple_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
+      loader_factory,
+      base::BindOnce(&ServicesCustomizationDocument::OnSimpleLoaderComplete,
+                     base::Unretained(this)));
 }
 
 bool ServicesCustomizationDocument::LoadManifestFromString(
@@ -609,26 +640,30 @@
   }
 }
 
-void ServicesCustomizationDocument::OnURLFetchComplete(
-    const net::URLFetcher* source) {
-  std::string mime_type;
-  std::string data;
-  if (source->GetStatus().is_success() &&
-      source->GetResponseCode() == net::HTTP_OK &&
-      source->GetResponseHeaders()->GetMimeType(&mime_type) &&
-      mime_type == "application/json" &&
-      source->GetResponseAsString(&data)) {
-    LoadManifestFromString(data);
-  } else if (source->GetResponseCode() == net::HTTP_NOT_FOUND) {
-    LOG(ERROR) << "Customization manifest is missing on server: "
-               << source->GetURL().spec();
-    OnCustomizationNotFound();
-  } else {
+void ServicesCustomizationDocument::OnSimpleLoaderComplete(
+    std::unique_ptr<std::string> response_body) {
+  int response_code = 0;
+  bool retry = true;
+  if (simple_loader_->ResponseInfo() &&
+      simple_loader_->ResponseInfo()->headers) {
+    response_code = simple_loader_->ResponseInfo()->headers->response_code();
+    std::string mime_type;
+    simple_loader_->ResponseInfo()->headers->GetMimeType(&mime_type);
+    if (mime_type == "application/json" and response_body) {
+      LoadManifestFromString(*response_body);
+      retry = false;
+    } else if (response_code == net::HTTP_NOT_FOUND) {
+      LOG(ERROR) << "Customization manifest is missing on server: "
+                 << url_.spec();
+      OnCustomizationNotFound();
+      retry = false;
+    }
+  }
+  if (retry) {
     if (num_retries_ < kMaxFetchRetries) {
       num_retries_++;
       content::BrowserThread::PostDelayedTask(
-          content::BrowserThread::UI,
-          FROM_HERE,
+          content::BrowserThread::UI, FROM_HERE,
           base::Bind(&ServicesCustomizationDocument::StartFileFetch,
                      weak_ptr_factory_.GetWeakPtr()),
           base::TimeDelta::FromSeconds(kRetriesDelayInSec));
@@ -636,8 +671,8 @@
     }
     // This doesn't stop fetching manifest on next restart.
     LOG(ERROR) << "URL fetch for services customization failed:"
-               << " response code = " << source->GetResponseCode()
-               << " URL = " << source->GetURL().spec();
+               << " response code = " << response_code
+               << " URL = " << url_.spec();
 
     LogManifestLoadResult(HISTOGRAM_LOAD_RESULT_RETRIES_FAIL);
   }
@@ -777,8 +812,8 @@
 std::string ServicesCustomizationDocument::GetOemAppsFolderNameImpl(
     const std::string& locale,
     const base::DictionaryValue& root) const {
-  return GetLocaleSpecificStringImpl(
-      &root, locale, kLocalizedContent, kDefaultAppsFolderName);
+  return GetLocaleSpecificStringImpl(&root, locale, kLocalizedContent,
+                                     kDefaultAppsFolderName);
 }
 
 // static
@@ -851,10 +886,9 @@
 
   std::unique_ptr<bool> exists(new bool(false));
 
-  base::Closure check_file_exists =
-      base::Bind(&CheckWallpaperCacheExists,
-                 GetCustomizedWallpaperDownloadedFileName(),
-                 base::Unretained(exists.get()));
+  base::Closure check_file_exists = base::Bind(
+      &CheckWallpaperCacheExists, GetCustomizedWallpaperDownloadedFileName(),
+      base::Unretained(exists.get()));
   base::Closure on_checked_closure = base::Bind(
       &ServicesCustomizationDocument::OnCheckedWallpaperCacheExists,
       weak_ptr_factory_.GetWeakPtr(), base::Passed(std::move(exists)),
diff --git a/chrome/browser/chromeos/customization/customization_document.h b/chrome/browser/chromeos/customization/customization_document.h
index 3ffbb0e1..a4a9bae 100644
--- a/chrome/browser/chromeos/customization/customization_document.h
+++ b/chrome/browser/chromeos/customization/customization_document.h
@@ -17,7 +17,6 @@
 #include "base/memory/singleton.h"
 #include "base/memory/weak_ptr.h"
 #include "base/values.h"
-#include "net/url_request/url_fetcher_delegate.h"
 #include "url/gurl.h"
 
 class PrefRegistrySimple;
@@ -32,8 +31,14 @@
 class ExternalLoader;
 }
 
-namespace net {
-class URLFetcher;
+namespace network {
+class SimpleURLLoader;
+}
+
+namespace network {
+namespace mojom {
+class URLLoaderFactory;
+}
 }
 
 namespace user_prefs {
@@ -141,8 +146,7 @@
 // outside this class by calling StartFetching() or EnsureCustomizationApplied()
 // methods.
 // User of the file should check IsReady before use it.
-class ServicesCustomizationDocument : public CustomizationDocument,
-                                      private net::URLFetcherDelegate {
+class ServicesCustomizationDocument : public CustomizationDocument {
  public:
   static ServicesCustomizationDocument* GetInstance();
 
@@ -200,6 +204,11 @@
     return wallpaper_downloader_.get();
   }
 
+  void SetURLLoaderFactoryForTesting(
+      network::mojom::URLLoaderFactory* url_loader_factory) {
+    url_loader_factory_ = url_loader_factory;
+  }
+
  private:
   friend struct base::DefaultSingletonTraits<ServicesCustomizationDocument>;
   FRIEND_TEST_ALL_PREFIXES(CustomizationWallpaperDownloaderBrowserTest,
@@ -227,8 +236,7 @@
   // Overriden from CustomizationDocument:
   bool LoadManifestFromString(const std::string& manifest) override;
 
-  // Overriden from net::URLFetcherDelegate:
-  void OnURLFetchComplete(const net::URLFetcher* source) override;
+  void OnSimpleLoaderComplete(std::unique_ptr<std::string> response_body);
 
   // Initiate file fetching. Wait for online status.
   void StartFileFetch();
@@ -293,9 +301,6 @@
   // Services customization manifest URL.
   GURL url_;
 
-  // URLFetcher instance.
-  std::unique_ptr<net::URLFetcher> url_fetcher_;
-
   // How many times we already tried to fetch customization manifest file.
   int num_retries_;
 
@@ -309,6 +314,7 @@
   ExternalLoaders external_loaders_;
 
   std::unique_ptr<CustomizationWallpaperDownloader> wallpaper_downloader_;
+  std::unique_ptr<network::SimpleURLLoader> simple_loader_;
 
   // This is barrier until customization is applied.
   // When number of finished tasks match number of started - customization is
@@ -321,6 +327,9 @@
   // successfully.
   size_t apply_tasks_success_;
 
+  // Only used for unit tests. Not owned.
+  network::mojom::URLLoaderFactory* url_loader_factory_;
+
   // Weak factory for callbacks.
   base::WeakPtrFactory<ServicesCustomizationDocument> weak_ptr_factory_;
 
diff --git a/chrome/browser/chromeos/customization/customization_document_unittest.cc b/chrome/browser/chromeos/customization/customization_document_unittest.cc
index c59d179..85eef2e93 100644
--- a/chrome/browser/chromeos/customization/customization_document_unittest.cc
+++ b/chrome/browser/chromeos/customization/customization_document_unittest.cc
@@ -32,13 +32,11 @@
 #include "extensions/common/manifest.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_status_code.h"
-#include "net/url_request/test_url_fetcher_factory.h"
-#include "net/url_request/url_request_status.h"
+#include "net/http/http_util.h"
+#include "services/network/test/test_url_loader_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-using ::testing::Exactly;
-using ::testing::Invoke;
 using ::testing::Mock;
 using ::testing::_;
 using extensions::ExternalInstallInfoFile;
@@ -159,30 +157,6 @@
   EXPECT_FALSE(customization.IsReady());
 }
 
-class TestURLFetcherCallback {
- public:
-  std::unique_ptr<net::FakeURLFetcher> CreateURLFetcher(
-      const GURL& url,
-      net::URLFetcherDelegate* d,
-      const std::string& response_data,
-      net::HttpStatusCode response_code,
-      net::URLRequestStatus::Status status) {
-    std::unique_ptr<net::FakeURLFetcher> fetcher(
-        new net::FakeURLFetcher(url, d, response_data, response_code, status));
-    OnRequestCreate(url, fetcher.get());
-    return fetcher;
-  }
-  MOCK_METHOD2(OnRequestCreate,
-               void(const GURL&, net::FakeURLFetcher*));
-};
-
-void AddMimeHeader(const GURL& url, net::FakeURLFetcher* fetcher) {
-  scoped_refptr<net::HttpResponseHeaders> download_headers =
-      new net::HttpResponseHeaders("");
-  download_headers->AddHeader("Content-Type: application/json");
-  fetcher->set_response_headers(download_headers);
-}
-
 class MockExternalProviderVisitor
     : public extensions::ExternalProviderInterface::VisitorInterface {
  public:
@@ -203,11 +177,6 @@
 
 class ServicesCustomizationDocumentTest : public testing::Test {
  protected:
-  ServicesCustomizationDocumentTest()
-      : factory_(nullptr,
-                 base::Bind(&TestURLFetcherCallback::CreateURLFetcher,
-                            base::Unretained(&url_callback_))) {}
-
   // testing::Test:
   void SetUp() override {
     ServicesCustomizationDocument::InitializeForTesting();
@@ -258,25 +227,33 @@
                            const std::string& manifest) {
     GURL url(base::StringPrintf(ServicesCustomizationDocument::kManifestUrl,
                                 id.c_str()));
-    factory_.SetFakeResponse(url,
-                             manifest,
-                             net::HTTP_OK,
-                             net::URLRequestStatus::SUCCESS);
-    EXPECT_CALL(url_callback_, OnRequestCreate(url, _))
-      .Times(Exactly(1))
-      .WillRepeatedly(Invoke(AddMimeHeader));
+    network::ResourceResponseHead head;
+    char base_headers_string[] =
+        "HTTP/1.0 200 OK\r\n"
+        "\r\n";
+    head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+        net::HttpUtil::AssembleRawHeaders(base_headers_string,
+                                          sizeof(base_headers_string)));
+    head.headers->AddHeader("Content-Type: application/json");
+    network::URLLoaderCompletionStatus status;
+    status.decoded_body_length = manifest.size();
+    factory_.AddResponse(url, head, manifest, status);
   }
 
   void AddManifestNotFound(const std::string& id) {
     GURL url(base::StringPrintf(ServicesCustomizationDocument::kManifestUrl,
                                 id.c_str()));
-    factory_.SetFakeResponse(url,
-                             std::string(),
-                             net::HTTP_NOT_FOUND,
-                             net::URLRequestStatus::SUCCESS);
-    EXPECT_CALL(url_callback_, OnRequestCreate(url, _))
-      .Times(Exactly(1))
-      .WillRepeatedly(Invoke(AddMimeHeader));
+    network::ResourceResponseHead head;
+    char base_headers_string[] =
+        "HTTP/1.x 404 Not Found\r\n"
+        "\r\n";
+    head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+        net::HttpUtil::AssembleRawHeaders(base_headers_string,
+                                          sizeof(base_headers_string)));
+    head.headers->AddHeader("Content-Type: application/json");
+    network::URLLoaderCompletionStatus status;
+    status.decoded_body_length = 0;
+    factory_.AddResponse(url, head, "", status);
   }
 
   std::unique_ptr<TestingProfile> CreateProfile() {
@@ -291,13 +268,13 @@
     return profile_builder.Build();
   }
 
+  network::TestURLLoaderFactory factory_;
+
  private:
   content::TestBrowserThreadBundle thread_bundle_;
   system::ScopedFakeStatisticsProvider fake_statistics_provider_;
   ScopedCrosSettingsTestHelper scoped_cros_settings_test_helper_;
   TestingPrefServiceSimple local_state_;
-  TestURLFetcherCallback url_callback_;
-  net::FakeURLFetcherFactory factory_;
   NetworkPortalDetectorTestImpl network_portal_detector_;
 };
 
@@ -309,6 +286,7 @@
       ServicesCustomizationDocument::GetInstance();
   EXPECT_FALSE(doc->IsReady());
 
+  doc->SetURLLoaderFactoryForTesting(&factory_);
   doc->StartFetching();
   RunUntilIdle();
   EXPECT_TRUE(doc->IsReady());
@@ -346,6 +324,7 @@
       ServicesCustomizationDocument::GetInstance();
   EXPECT_FALSE(doc->IsReady());
 
+  doc->SetURLLoaderFactoryForTesting(&factory_);
   std::unique_ptr<TestingProfile> profile = CreateProfile();
   extensions::ExternalLoader* loader = doc->CreateExternalLoader(profile.get());
   EXPECT_TRUE(loader);
@@ -382,6 +361,7 @@
       ServicesCustomizationDocument::GetInstance();
   EXPECT_FALSE(doc->IsReady());
 
+  doc->SetURLLoaderFactoryForTesting(&factory_);
   std::unique_ptr<TestingProfile> profile = CreateProfile();
   extensions::ExternalLoader* loader = doc->CreateExternalLoader(profile.get());
   EXPECT_TRUE(loader);
@@ -432,6 +412,7 @@
       ServicesCustomizationDocument::GetInstance();
   EXPECT_FALSE(doc->IsReady());
 
+  doc->SetURLLoaderFactoryForTesting(&factory_);
   std::unique_ptr<TestingProfile> profile = CreateProfile();
   extensions::ExternalLoader* loader = doc->CreateExternalLoader(profile.get());
   EXPECT_TRUE(loader);
diff --git a/chrome/browser/chromeos/extensions/extension_system_event_observer.cc b/chrome/browser/chromeos/extensions/extension_system_event_observer.cc
index e37bdb3..fbab699 100644
--- a/chrome/browser/chromeos/extensions/extension_system_event_observer.cc
+++ b/chrome/browser/chromeos/extensions/extension_system_event_observer.cc
@@ -6,6 +6,7 @@
 
 #include "chrome/browser/extensions/api/system_private/system_private_api.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/power_manager/backlight.pb.h"
 #include "components/session_manager/core/session_manager.h"
 
 namespace chromeos {
@@ -21,9 +22,12 @@
   session_manager::SessionManager::Get()->RemoveObserver(this);
 }
 
-void ExtensionSystemEventObserver::BrightnessChanged(int level,
-                                                     bool user_initiated) {
-  extensions::DispatchBrightnessChangedEvent(level, user_initiated);
+void ExtensionSystemEventObserver::ScreenBrightnessChanged(
+    const power_manager::BacklightBrightnessChange& change) {
+  const bool user_initiated =
+      change.cause() ==
+      power_manager::BacklightBrightnessChange_Cause_USER_REQUEST;
+  extensions::DispatchBrightnessChangedEvent(change.percent(), user_initiated);
 }
 
 void ExtensionSystemEventObserver::SuspendDone(
diff --git a/chrome/browser/chromeos/extensions/extension_system_event_observer.h b/chrome/browser/chromeos/extensions/extension_system_event_observer.h
index 42a7c8b..5a7d5546 100644
--- a/chrome/browser/chromeos/extensions/extension_system_event_observer.h
+++ b/chrome/browser/chromeos/extensions/extension_system_event_observer.h
@@ -22,7 +22,8 @@
   ~ExtensionSystemEventObserver() override;
 
   // PowerManagerClient::Observer overrides:
-  void BrightnessChanged(int level, bool user_initiated) override;
+  void ScreenBrightnessChanged(
+      const power_manager::BacklightBrightnessChange& change) override;
   void SuspendDone(const base::TimeDelta& sleep_duration) override;
 
   // session_manager::SessionManagerObserver override:
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc
index 6a5e6cb..8a79db8c 100644
--- a/chrome/browser/chromeos/login/wizard_controller.cc
+++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -604,7 +604,7 @@
 }
 
 void WizardController::ShowArcTermsOfServiceScreen() {
-  if (ShouldShowArcTerms()) {
+  if (arc::IsArcTermsOfServiceOobeNegotiationNeeded()) {
     VLOG(1) << "Showing ARC Terms of Service screen.";
     UpdateStatusAreaVisibilityForScreen(
         OobeScreen::SCREEN_ARC_TERMS_OF_SERVICE);
@@ -1665,38 +1665,6 @@
       switches::kHostPairingOobe);
 }
 
-bool WizardController::ShouldShowArcTerms() const {
-  if (!user_manager::UserManager::Get()->IsUserLoggedIn()) {
-    VLOG(1) << "Skip ARC Terms of Service screen because user is not "
-            << "logged in.";
-    return false;
-  }
-
-  const Profile* profile = ProfileManager::GetActiveUserProfile();
-  if (!arc::IsArcAllowedForProfile(profile)) {
-    VLOG(1) << "Skip ARC Terms of Service screen because ARC is not allowed.";
-    return false;
-  }
-  if (profile->GetPrefs()->IsManagedPreference(arc::prefs::kArcEnabled) &&
-      !profile->GetPrefs()->GetBoolean(arc::prefs::kArcEnabled)) {
-    VLOG(1) << "Skip ARC Terms of Service screen because ARC is disabled.";
-    return false;
-  }
-
-  if (!arc::IsPlayStoreAvailable()) {
-    VLOG(1) << "Skip ARC Terms of Service screen because Play Store is not "
-               "available on the device.";
-    return false;
-  }
-
-  if (arc::IsActiveDirectoryUserForProfile(profile)) {
-    VLOG(1) << "Skip ARC Terms of Service screen because it does not apply to "
-               "Active Directory users.";
-    return false;
-  }
-  return true;
-}
-
 bool WizardController::ShouldShowVoiceInteractionValueProp() const {
   // If the OOBE flow was initiated from voice interaction shortcut, we will
   // show Arc terms later.
diff --git a/chrome/browser/chromeos/login/wizard_controller.h b/chrome/browser/chromeos/login/wizard_controller.h
index f39b30b2..34facfce 100644
--- a/chrome/browser/chromeos/login/wizard_controller.h
+++ b/chrome/browser/chromeos/login/wizard_controller.h
@@ -299,9 +299,6 @@
   // detected or not.
   bool IsRemoraPairingOobe() const;
 
-  // Returns true if arc terms of service should be shown.
-  bool ShouldShowArcTerms() const;
-
   // Returns true if voice interaction value prop should be shown.
   bool ShouldShowVoiceInteractionValueProp() const;
 
diff --git a/chrome/browser/component_updater/third_party_module_list_component_installer_win.cc b/chrome/browser/component_updater/third_party_module_list_component_installer_win.cc
index 75b255e..0741121 100644
--- a/chrome/browser/component_updater/third_party_module_list_component_installer_win.cc
+++ b/chrome/browser/component_updater/third_party_module_list_component_installer_win.cc
@@ -142,7 +142,9 @@
   if (!database)
     return;
   ThirdPartyConflictsManager* manager =
-      &database->third_party_conflicts_manager();
+      database->third_party_conflicts_manager();
+  if (!manager)
+    return;
   auto installer = base::MakeRefCounted<ComponentInstaller>(
       std::make_unique<ThirdPartyModuleListComponentInstallerPolicy>(manager));
   installer->Register(cus, base::OnceClosure());
diff --git a/chrome/browser/conflicts/module_database_win.cc b/chrome/browser/conflicts/module_database_win.cc
index 1868ec19a..d7c0834 100644
--- a/chrome/browser/conflicts/module_database_win.cc
+++ b/chrome/browser/conflicts/module_database_win.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/files/file_path.h"
 #include "base/location.h"
+#include "base/win/windows_version.h"
 #include "chrome/browser/conflicts/module_database_observer_win.h"
 
 namespace {
@@ -44,14 +45,15 @@
       // base::Unretained().
       module_inspector_(base::Bind(&ModuleDatabase::OnModuleInspected,
                                    base::Unretained(this))),
-#if defined(GOOGLE_CHROME_BUILD)
-      third_party_conflicts_manager_(this),
-#endif
       weak_ptr_factory_(this) {
   AddObserver(&third_party_metrics_);
 
 #if defined(GOOGLE_CHROME_BUILD)
-  AddObserver(&third_party_conflicts_manager_);
+  if (base::win::GetVersion() >= base::win::VERSION_WIN10) {
+    third_party_conflicts_manager_ =
+        std::make_unique<ThirdPartyConflictsManager>(this);
+    AddObserver(third_party_conflicts_manager_.get());
+  }
 #endif
 }
 
diff --git a/chrome/browser/conflicts/module_database_win.h b/chrome/browser/conflicts/module_database_win.h
index d7f836a1..e9583721 100644
--- a/chrome/browser/conflicts/module_database_win.h
+++ b/chrome/browser/conflicts/module_database_win.h
@@ -117,8 +117,9 @@
 #if defined(GOOGLE_CHROME_BUILD)
   // Accessor for the third party conflicts manager. This is exposed so that the
   // manager can be wired up to the ThirdPartyModuleListComponentInstaller.
-  ThirdPartyConflictsManager& third_party_conflicts_manager() {
-    return third_party_conflicts_manager_;
+  // Returns returns null on Windows 8.1 and lower.
+  ThirdPartyConflictsManager* third_party_conflicts_manager() {
+    return third_party_conflicts_manager_.get();
   }
 #endif
 
@@ -193,7 +194,7 @@
   base::ObserverList<ModuleDatabaseObserver> observer_list_;
 
 #if defined(GOOGLE_CHROME_BUILD)
-  ThirdPartyConflictsManager third_party_conflicts_manager_;
+  std::unique_ptr<ThirdPartyConflictsManager> third_party_conflicts_manager_;
 #endif
 
   // Records metrics on third-party modules.
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
index 6184521..bac6c31 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -4321,7 +4321,7 @@
       base::Bind(&OnDangerPromptCreated);
   DownloadsAcceptDangerFunction::OnPromptCreatedForTesting(
       &callback);
-  BrowserActionTestUtil(browser()).Press(0);
+  BrowserActionTestUtil::Create(browser())->Press(0);
   observer->WaitForFinished();
 }
 
diff --git a/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc b/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
index 35432db..0f19212 100644
--- a/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
+++ b/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
@@ -131,7 +131,7 @@
  protected:
   BrowserActionTestUtil* GetBrowserActionsBar() {
     if (!browser_action_test_util_)
-      browser_action_test_util_.reset(new BrowserActionTestUtil(browser()));
+      browser_action_test_util_ = BrowserActionTestUtil::Create(browser());
     return browser_action_test_util_.get();
   }
 
@@ -419,9 +419,9 @@
 
   // The extension's popup's size grows by |growFactor| each click.
   const int growFactor = 500;
-  gfx::Size minSize = BrowserActionTestUtil::GetMinPopupSize();
+  gfx::Size minSize = actions_bar->GetMinPopupSize();
   gfx::Size middleSize = gfx::Size(growFactor, growFactor);
-  gfx::Size maxSize = BrowserActionTestUtil::GetMaxPopupSize();
+  gfx::Size maxSize = actions_bar->GetMaxPopupSize();
 
   // Ensure that two clicks will exceed the maximum allowed size.
   ASSERT_GT(minSize.height() + growFactor * 2, maxSize.height());
@@ -551,8 +551,8 @@
   Browser* incognito_browser =
       new Browser(Browser::CreateParams(incognito_profile, true));
 
-  ASSERT_EQ(0,
-            BrowserActionTestUtil(incognito_browser).NumberOfBrowserActions());
+  ASSERT_EQ(0, BrowserActionTestUtil::Create(incognito_browser)
+                   ->NumberOfBrowserActions());
 
   // Now enable the extension in incognito mode, and test that the browser
   // action shows up.
@@ -564,8 +564,8 @@
       extension->id(), browser()->profile(), true);
   registry_observer.WaitForExtensionLoaded();
 
-  ASSERT_EQ(1,
-            BrowserActionTestUtil(incognito_browser).NumberOfBrowserActions());
+  ASSERT_EQ(1, BrowserActionTestUtil::Create(incognito_browser)
+                   ->NumberOfBrowserActions());
 
   // TODO(mpcomplete): simulate a click and have it do the right thing in
   // incognito.
@@ -587,8 +587,8 @@
   base::RunLoop().RunUntilIdle();  // Wait for profile initialization.
   // Navigate just to have a tab in this window, otherwise wonky things happen.
   OpenURLOffTheRecord(browser()->profile(), GURL("about:blank"));
-  ASSERT_EQ(1,
-            BrowserActionTestUtil(incognito_browser).NumberOfBrowserActions());
+  ASSERT_EQ(1, BrowserActionTestUtil::Create(incognito_browser)
+                   ->NumberOfBrowserActions());
 
   // A click in the regular profile should open a tab in the regular profile.
   ExecuteExtensionAction(browser(), extension);
diff --git a/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc b/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
index f709e6c..c5e7e37 100644
--- a/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
+++ b/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
@@ -127,10 +127,10 @@
   }
 
   void EnsurePopupActive() {
-    BrowserActionTestUtil test_util(browser());
-    EXPECT_TRUE(test_util.HasPopup());
-    EXPECT_TRUE(test_util.WaitForPopup());
-    EXPECT_TRUE(test_util.HasPopup());
+    auto test_util = BrowserActionTestUtil::Create(browser());
+    EXPECT_TRUE(test_util->HasPopup());
+    EXPECT_TRUE(test_util->WaitForPopup());
+    EXPECT_TRUE(test_util->HasPopup());
   }
 
   // Open an extension popup via the chrome.browserAction.openPopup API.
@@ -160,17 +160,17 @@
     content::WindowedNotificationObserver frame_observer(
         content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
         content::NotificationService::AllSources());
-    BrowserActionTestUtil(browser()).Press(0);
+    BrowserActionTestUtil::Create(browser())->Press(0);
     frame_observer.Wait();
     EnsurePopupActive();
   }
 
   // Close the popup window directly.
-  void ClosePopup() { BrowserActionTestUtil(browser()).HidePopup(); }
+  void ClosePopup() { BrowserActionTestUtil::Create(browser())->HidePopup(); }
 
   // Trigger a focus loss to close the popup.
   void ClosePopupViaFocusLoss() {
-    EXPECT_TRUE(BrowserActionTestUtil(browser()).HasPopup());
+    EXPECT_TRUE(BrowserActionTestUtil::Create(browser())->HasPopup());
     content::WindowedNotificationObserver observer(
         extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED,
         content::NotificationService::AllSources());
@@ -189,7 +189,7 @@
 #endif
 
     // The window disappears immediately.
-    EXPECT_FALSE(BrowserActionTestUtil(browser()).HasPopup());
+    EXPECT_FALSE(BrowserActionTestUtil::Create(browser())->HasPopup());
 
     // Wait for the notification to achieve a consistent state and verify that
     // the popup was properly torn down.
@@ -210,13 +210,13 @@
   if (!ShouldRunPopupTest())
     return;
 
-  BrowserActionTestUtil browserActionBar(browser());
+  auto browserActionBar = BrowserActionTestUtil::Create(browser());
   // Setup extension message listener to wait for javascript to finish running.
   ExtensionTestMessageListener listener("ready", true);
   {
     OpenPopupViaAPI(true);
-    EXPECT_TRUE(browserActionBar.HasPopup());
-    browserActionBar.HidePopup();
+    EXPECT_TRUE(browserActionBar->HasPopup());
+    browserActionBar->HidePopup();
   }
 
   EXPECT_TRUE(listener.WaitUntilSatisfied());
@@ -246,10 +246,10 @@
     // Show second popup in new window.
     listener.Reply("show another");
     frame_observer.Wait();
-    EXPECT_TRUE(BrowserActionTestUtil(new_browser).HasPopup());
+    EXPECT_TRUE(BrowserActionTestUtil::Create(new_browser)->HasPopup());
   }
   ASSERT_TRUE(catcher.GetNextResult()) << message_;
-  BrowserActionTestUtil(new_browser).HidePopup();
+  BrowserActionTestUtil::Create(new_browser)->HidePopup();
 }
 
 // Tests opening a popup in an incognito window.
@@ -269,12 +269,13 @@
   // have popups if there is any popup open.
 #if !(defined(OS_LINUX) && !defined(USE_AURA))
   // Starting window does not have a popup.
-  EXPECT_FALSE(BrowserActionTestUtil(browser()).HasPopup());
+  EXPECT_FALSE(BrowserActionTestUtil::Create(browser())->HasPopup());
 #endif
   // Incognito window should have a popup.
-  BrowserActionTestUtil test_util(BrowserList::GetInstance()->GetLastActive());
-  EXPECT_TRUE(test_util.HasPopup());
-  test_util.HidePopup();
+  auto test_util = BrowserActionTestUtil::Create(
+      BrowserList::GetInstance()->GetLastActive());
+  EXPECT_TRUE(test_util->HasPopup());
+  test_util->HidePopup();
 }
 
 // Tests that an extension can open a popup in the last active incognito window
@@ -296,9 +297,9 @@
       OpenURLOffTheRecord(profile(), GURL("chrome://newtab/"));
   listener.WaitUntilSatisfied();
   EXPECT_EQ(std::string("opened"), listener.message());
-  BrowserActionTestUtil test_util(incognito_browser);
-  EXPECT_TRUE(test_util.HasPopup());
-  test_util.HidePopup();
+  auto test_util = BrowserActionTestUtil::Create(incognito_browser);
+  EXPECT_TRUE(test_util->HasPopup());
+  test_util->HidePopup();
 }
 
 #if defined(OS_LINUX)
@@ -394,7 +395,7 @@
   browser()->tab_strip_model()->ActivateTabAt(0, true);
   observer.Wait();
 
-  EXPECT_FALSE(BrowserActionTestUtil(browser()).HasPopup());
+  EXPECT_FALSE(BrowserActionTestUtil::Create(browser())->HasPopup());
 }
 
 IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest,
@@ -404,8 +405,8 @@
 
   // First, we open a popup.
   OpenPopupViaAPI(false);
-  BrowserActionTestUtil browser_action_test_util(browser());
-  EXPECT_TRUE(browser_action_test_util.HasPopup());
+  auto browser_action_test_util = BrowserActionTestUtil::Create(browser());
+  EXPECT_TRUE(browser_action_test_util->HasPopup());
 
   // Then, find the extension that created it.
   content::WebContents* active_web_contents =
@@ -419,7 +420,7 @@
   // Finally, uninstall the extension, which causes the view to be deleted and
   // the popup to go away. This should not crash.
   UninstallExtension(extension->id());
-  EXPECT_FALSE(browser_action_test_util.HasPopup());
+  EXPECT_FALSE(browser_action_test_util->HasPopup());
 }
 
 // BrowserActionTestUtil::InspectPopup() is not implemented for a Cocoa browser.
@@ -444,9 +445,9 @@
   content::WindowedNotificationObserver frame_observer(
       content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
       content::NotificationService::AllSources());
-  BrowserActionTestUtil(browser()).InspectPopup(0);
+  BrowserActionTestUtil::Create(browser())->InspectPopup(0);
   frame_observer.Wait();
-  EXPECT_TRUE(BrowserActionTestUtil(browser()).HasPopup());
+  EXPECT_TRUE(BrowserActionTestUtil::Create(browser())->HasPopup());
 
   // Close the browser window, this should not cause a crash.
   chrome::CloseWindow(browser());
@@ -459,8 +460,8 @@
     return;
 
   OpenPopupViaAPI(false);
-  BrowserActionTestUtil test_util(browser());
-  const gfx::NativeView popup_view = test_util.GetPopupNativeView();
+  auto test_util = BrowserActionTestUtil::Create(browser());
+  const gfx::NativeView popup_view = test_util->GetPopupNativeView();
   EXPECT_NE(static_cast<gfx::NativeView>(nullptr), popup_view);
   const HWND popup_hwnd = views::HWNDForNativeView(popup_view);
   EXPECT_EQ(TRUE, ::IsWindow(popup_hwnd));
diff --git a/chrome/browser/extensions/extension_incognito_apitest.cc b/chrome/browser/extensions/extension_incognito_apitest.cc
index 8841acb2..3a37473 100644
--- a/chrome/browser/extensions/extension_incognito_apitest.cc
+++ b/chrome/browser/extensions/extension_incognito_apitest.cc
@@ -185,7 +185,7 @@
       embedded_test_server()->GetURL("/extensions/test_file.html"));
 
   // Simulate the incognito's browser action being clicked.
-  BrowserActionTestUtil(incognito_browser).Press(0);
+  BrowserActionTestUtil::Create(incognito_browser)->Press(0);
 
   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
 }
diff --git a/chrome/browser/extensions/extension_keybinding_apitest.cc b/chrome/browser/extensions/extension_keybinding_apitest.cc
index eca1c2d..ed00897 100644
--- a/chrome/browser/extensions/extension_keybinding_apitest.cc
+++ b/chrome/browser/extensions/extension_keybinding_apitest.cc
@@ -187,9 +187,9 @@
   // immaterial to this test).
   ASSERT_TRUE(RunExtensionTest("keybinding/conflicting")) << message_;
 
-  BrowserActionTestUtil browser_actions_bar(browser());
+  auto browser_actions_bar = BrowserActionTestUtil::Create(browser());
   // Test that there are two browser actions in the toolbar.
-  ASSERT_EQ(2, browser_actions_bar.NumberOfBrowserActions());
+  ASSERT_EQ(2, browser_actions_bar->NumberOfBrowserActions());
 
   ui_test_utils::NavigateToURL(
       browser(), embedded_test_server()->GetURL("/extensions/test_file.txt"));
diff --git a/chrome/browser/extensions/lazy_background_page_apitest.cc b/chrome/browser/extensions/lazy_background_page_apitest.cc
index 09e0415..9cbbc204 100644
--- a/chrome/browser/extensions/lazy_background_page_apitest.cc
+++ b/chrome/browser/extensions/lazy_background_page_apitest.cc
@@ -152,7 +152,7 @@
   // Observe background page being created and closed after
   // the browser action is clicked.
   LazyBackgroundObserver page_complete;
-  BrowserActionTestUtil(browser()).Press(0);
+  BrowserActionTestUtil::Create(browser())->Press(0);
   page_complete.Wait();
 
   // Background page created a new tab before it closed.
@@ -174,7 +174,7 @@
   // Observe background page being created and closed after
   // the browser action is clicked.
   LazyBackgroundObserver page_complete;
-  BrowserActionTestUtil(browser()).Press(0);
+  BrowserActionTestUtil::Create(browser())->Press(0);
   page_complete.Wait();
 
   // Background page is closed after creating a new tab.
@@ -340,7 +340,7 @@
   {
     ExtensionTestMessageListener nacl_module_loaded("nacl_module_loaded",
                                                     false);
-    BrowserActionTestUtil(browser()).Press(0);
+    BrowserActionTestUtil::Create(browser())->Press(0);
     nacl_module_loaded.WaitUntilSatisfied();
     content::RunAllTasksUntilIdle();
     EXPECT_TRUE(IsBackgroundPageAlive(last_loaded_extension_id()));
@@ -350,7 +350,7 @@
   // down.
   {
     LazyBackgroundObserver page_complete;
-    BrowserActionTestUtil(browser()).Press(0);
+    BrowserActionTestUtil::Create(browser())->Press(0);
     page_complete.WaitUntilClosed();
   }
 
@@ -456,7 +456,7 @@
     ExtensionTestMessageListener listener_incognito("waiting_incognito", false);
 
     LazyBackgroundObserver page_complete(browser()->profile());
-    BrowserActionTestUtil(browser()).Press(0);
+    BrowserActionTestUtil::Create(browser())->Press(0);
     page_complete.Wait();
 
     // Only the original event page received the message.
@@ -532,9 +532,9 @@
   EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id()));
 
   // The browser action has a new title.
-  BrowserActionTestUtil browser_action(browser());
-  ASSERT_EQ(1, browser_action.NumberOfBrowserActions());
-  EXPECT_EQ("Success", browser_action.GetTooltip(0));
+  auto browser_action = BrowserActionTestUtil::Create(browser());
+  ASSERT_EQ(1, browser_action->NumberOfBrowserActions());
+  EXPECT_EQ("Success", browser_action->GetTooltip(0));
 }
 
 // Tests that both a regular page and an event page will receive events when
diff --git a/chrome/browser/extensions/process_manager_browsertest.cc b/chrome/browser/extensions/process_manager_browsertest.cc
index 323795a..fe77d73 100644
--- a/chrome/browser/extensions/process_manager_browsertest.cc
+++ b/chrome/browser/extensions/process_manager_browsertest.cc
@@ -391,14 +391,14 @@
   EXPECT_FALSE(pm->IsBackgroundHostClosing(popup->id()));
 
   // Simulate clicking on the action to open a popup.
-  BrowserActionTestUtil test_util(browser());
+  auto test_util = BrowserActionTestUtil::Create(browser());
   content::WindowedNotificationObserver frame_observer(
       content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
       content::NotificationService::AllSources());
   // Open popup in the first extension.
-  test_util.Press(0);
+  test_util->Press(0);
   frame_observer.Wait();
-  ASSERT_TRUE(test_util.HasPopup());
+  ASSERT_TRUE(test_util->HasPopup());
 
   // We now have a view, but still no background hosts.
   EXPECT_EQ(0u, pm->background_hosts().size());
@@ -730,20 +730,11 @@
   }
 }
 
-// Time-outs on Win, fails on Mac and Linux (http://crbug.com/806684).
-#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
-#define MAYBE_NestedURLNavigationsToExtensionBlocked \
-  DISABLED_NestedURLNavigationsToExtensionBlocked
-#else
-#define MAYBE_NestedURLNavigationsToExtensionBlocked \
-  NestedURLNavigationsToExtensionBlocked
-#endif
-
 // Test that navigations to blob: and filesystem: URLs with extension origins
 // are disallowed when initiated from non-extension processes.  See
 // https://crbug.com/645028 and https://crbug.com/644426.
 IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest,
-                       MAYBE_NestedURLNavigationsToExtensionBlocked) {
+                       NestedURLNavigationsToExtensionBlocked) {
   // Disabling web security is necessary to test the browser enforcement;
   // without it, the loads in this test would be blocked by
   // SecurityOrigin::canDisplay() as invalid local resource loads.
@@ -853,6 +844,10 @@
     EXPECT_EQ(1u, pm->GetAllFrames().size());
   }
 
+  // Close the popup.  It won't be needed anymore, and bringing the original
+  // page back into foreground makes the remainder of this test a bit faster.
+  popup->Close();
+
   // Navigate second subframe to each nested URL from the main frame (i.e.,
   // from non-extension process).  These should be canceled.
   for (size_t i = 0; i < arraysize(nested_urls); i++) {
@@ -869,15 +864,58 @@
     EXPECT_TRUE(
         content::NavigateIframeToURL(tab, "frame2", GURL(url::kAboutBlankURL)));
   }
+}
 
-  // Check that the URLs still can be downloaded via an HTML anchor tag with
-  // the download attribute (i.e., <a download>) (which starts out as a
-  // top-level navigation).
+// Check that browser-side restrictions on extension blob/filesystem URLs allow
+// navigations that will result in downloads.  See https://crbug.com/714373.
+IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest,
+                       NestedURLDownloadsToExtensionAllowed) {
+  // Disabling web security is necessary to test the browser enforcement;
+  // without it, the loads in this test would be blocked by
+  // SecurityOrigin::CanDisplay() as invalid local resource loads.
+  PrefService* prefs = browser()->profile()->GetPrefs();
+  prefs->SetBoolean(prefs::kWebKitWebSecurityEnabled, false);
+
+  // Create a simple extension without a background page.
+  const Extension* extension = CreateExtension("Extension", false);
+  embedded_test_server()->ServeFilesFromDirectory(extension->path());
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  // Navigate main tab to a web page an iframe.  There should be no extension
+  // frames yet.
+  NavigateToURL(embedded_test_server()->GetURL("/blank_iframe.html"));
+  ProcessManager* pm = ProcessManager::Get(profile());
+  EXPECT_EQ(0u, pm->GetAllFrames().size());
+  EXPECT_EQ(0u, pm->GetRenderFrameHostsForExtension(extension->id()).size());
+
+  content::WebContents* tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  // Navigate iframe to an extension URL.
+  const GURL extension_url(extension->url().Resolve("empty.html"));
+  EXPECT_TRUE(content::NavigateIframeToURL(tab, "frame0", extension_url));
+  EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension->id()).size());
+  EXPECT_EQ(1u, pm->GetAllFrames().size());
+
+  content::RenderFrameHost* main_frame = tab->GetMainFrame();
+  content::RenderFrameHost* extension_frame = ChildFrameAt(main_frame, 0);
+
+  // Create valid blob and filesystem URLs in the extension's origin.
+  url::Origin extension_origin(extension_frame->GetLastCommittedOrigin());
+  GURL blob_url(CreateBlobURL(extension_frame, "foo"));
+  EXPECT_EQ(extension_origin, url::Origin::Create(blob_url));
+  GURL filesystem_url(CreateFileSystemURL(extension_frame, "foo"));
+  EXPECT_EQ(extension_origin, url::Origin::Create(filesystem_url));
+  GURL nested_urls[] = {blob_url, filesystem_url};
+
+  // Check that extension blob/filesystem URLs still can be downloaded via an
+  // HTML anchor tag with the download attribute (i.e., <a download>) (which
+  // starts out as a top-level navigation).
   PermissionRequestManager* permission_request_manager =
-      PermissionRequestManager::FromWebContents(popup);
+      PermissionRequestManager::FromWebContents(tab);
   permission_request_manager->set_auto_response_for_test(
       PermissionRequestManager::ACCEPT_ALL);
-  for (size_t i = 0; i < arraysize(nested_urls); i++) {
+  for (const GURL& nested_url : nested_urls) {
     content::DownloadTestObserverTerminal observer(
         content::BrowserContext::GetDownloadManager(profile()), 1,
         content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
@@ -886,18 +924,18 @@
            anchor.href = '%s';
            anchor.download = '';
            anchor.click();)",
-        nested_urls[i].spec().c_str());
-    EXPECT_TRUE(ExecuteScript(popup, script));
+        nested_url.spec().c_str());
+    EXPECT_TRUE(ExecuteScript(tab, script));
     observer.WaitForFinished();
     EXPECT_EQ(
         1u, observer.NumDownloadsSeenInState(download::DownloadItem::COMPLETE));
 
     // This is a top-level navigation that should have resulted in a download.
-    // Ensure that the popup stayed at its original location.
-    EXPECT_NE(nested_urls[i], popup->GetLastCommittedURL());
+    // Ensure that the tab stayed at its original location.
+    EXPECT_NE(nested_url, tab->GetLastCommittedURL());
     EXPECT_FALSE(extension_origin.IsSameOriginWith(
-        popup->GetMainFrame()->GetLastCommittedOrigin()));
-    EXPECT_NE("foo", GetTextContent(popup->GetMainFrame()));
+        main_frame->GetLastCommittedOrigin()));
+    EXPECT_NE("foo", GetTextContent(main_frame));
 
     EXPECT_EQ(1u, pm->GetRenderFrameHostsForExtension(extension->id()).size());
     EXPECT_EQ(1u, pm->GetAllFrames().size());
diff --git a/chrome/browser/external_protocol/external_protocol_handler.cc b/chrome/browser/external_protocol/external_protocol_handler.cc
index 9faf99f..9bd2997 100644
--- a/chrome/browser/external_protocol/external_protocol_handler.cc
+++ b/chrome/browser/external_protocol/external_protocol_handler.cc
@@ -30,6 +30,8 @@
 // each user gesture. This variable should only be accessed from the UI thread.
 bool g_accept_requests = true;
 
+ExternalProtocolHandler::Delegate* g_delegate = nullptr;
+
 constexpr const char* kDeniedSchemes[] = {
     "afp", "data", "disk", "disks",
     // ShellExecuting file:///C:/WINDOWS/system32/notepad.exe will simply
@@ -144,6 +146,11 @@
     "BrowserDialogs.ExternalProtocol.HandleState";
 
 // static
+void ExternalProtocolHandler::SetDelegateForTesting(Delegate* delegate) {
+  g_delegate = delegate;
+}
+
+// static
 ExternalProtocolHandler::BlockState ExternalProtocolHandler::GetBlockState(
     const std::string& scheme,
     Profile* profile) {
@@ -209,13 +216,11 @@
 }
 
 // static
-void ExternalProtocolHandler::LaunchUrlWithDelegate(
-    const GURL& url,
-    int render_process_host_id,
-    int render_view_routing_id,
-    ui::PageTransition page_transition,
-    bool has_user_gesture,
-    Delegate* delegate) {
+void ExternalProtocolHandler::LaunchUrl(const GURL& url,
+                                        int render_process_host_id,
+                                        int render_view_routing_id,
+                                        ui::PageTransition page_transition,
+                                        bool has_user_gesture) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   // Escape the input scheme to be sure that the command does not
@@ -233,10 +238,10 @@
   if (web_contents)  // Maybe NULL during testing.
     profile = Profile::FromBrowserContext(web_contents->GetBrowserContext());
   BlockState block_state =
-      GetBlockStateWithDelegate(escaped_url.scheme(), delegate, profile);
+      GetBlockStateWithDelegate(escaped_url.scheme(), g_delegate, profile);
   if (block_state == BLOCK) {
-    if (delegate)
-      delegate->BlockRequest();
+    if (g_delegate)
+      g_delegate->BlockRequest();
     return;
   }
 
@@ -247,12 +252,12 @@
   shell_integration::DefaultWebClientWorkerCallback callback = base::Bind(
       &OnDefaultProtocolClientWorkerFinished, escaped_url,
       render_process_host_id, render_view_routing_id, block_state == UNKNOWN,
-      page_transition, has_user_gesture, delegate);
+      page_transition, has_user_gesture, g_delegate);
 
   // Start the check process running. This will send tasks to a worker task
   // runner and when the answer is known will send the result back to
   // OnDefaultProtocolClientWorkerFinished().
-  CreateShellWorker(callback, escaped_url.scheme(), delegate)
+  CreateShellWorker(callback, escaped_url.scheme(), g_delegate)
       ->StartCheckIsDefault();
 }
 
diff --git a/chrome/browser/external_protocol/external_protocol_handler.h b/chrome/browser/external_protocol/external_protocol_handler.h
index f4628c3..727dba7 100644
--- a/chrome/browser/external_protocol/external_protocol_handler.h
+++ b/chrome/browser/external_protocol/external_protocol_handler.h
@@ -61,6 +61,10 @@
   // UMA histogram metric names.
   static const char kHandleStateMetric[];
 
+  // Called on the UI thread. Allows switching out the
+  // ExternalProtocolHandler::Delegate for testing code.
+  static void SetDelegateForTesting(Delegate* delegate);
+
   // Returns whether we should block a given scheme.
   static BlockState GetBlockState(const std::string& scheme, Profile* profile);
 
@@ -76,13 +80,11 @@
   // LaunchUrlWithoutSecurityCheck is called on the io thread and the
   // application is launched.
   // Must run on the UI thread.
-  // Allowing use of a delegate to facilitate unit testing.
-  static void LaunchUrlWithDelegate(const GURL& url,
-                                    int render_process_host_id,
-                                    int render_view_routing_id,
-                                    ui::PageTransition page_transition,
-                                    bool has_user_gesture,
-                                    Delegate* delegate);
+  static void LaunchUrl(const GURL& url,
+                        int render_process_host_id,
+                        int render_view_routing_id,
+                        ui::PageTransition page_transition,
+                        bool has_user_gesture);
 
   // Starts a url using the external protocol handler with the help
   // of shellexecute. Should only be called if the protocol is whitelisted
diff --git a/chrome/browser/external_protocol/external_protocol_handler_unittest.cc b/chrome/browser/external_protocol/external_protocol_handler_unittest.cc
index f2a2f8d..5bc9965d 100644
--- a/chrome/browser/external_protocol/external_protocol_handler_unittest.cc
+++ b/chrome/browser/external_protocol/external_protocol_handler_unittest.cc
@@ -146,12 +146,13 @@
     EXPECT_FALSE(delegate_.has_prompted());
     EXPECT_FALSE(delegate_.has_launched());
     EXPECT_FALSE(delegate_.has_blocked());
-
+    ExternalProtocolHandler::SetDelegateForTesting(&delegate_);
     delegate_.set_block_state(block_state);
     delegate_.set_os_state(os_state);
-    ExternalProtocolHandler::LaunchUrlWithDelegate(
-        url, 0, 0, ui::PAGE_TRANSITION_LINK, true, &delegate_);
+    ExternalProtocolHandler::LaunchUrl(url, 0, 0, ui::PAGE_TRANSITION_LINK,
+                                       true);
     content::RunAllTasksUntilIdle();
+    ExternalProtocolHandler::SetDelegateForTesting(nullptr);
 
     EXPECT_EQ(expected_action == Action::PROMPT, delegate_.has_prompted());
     EXPECT_EQ(expected_action == Action::LAUNCH, delegate_.has_launched());
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 8cb64cf5..81e265c4 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1035,17 +1035,6 @@
     "In the Omnibox, hide the scheme and trivial subdomains from steady state "
     "displayed URLs. Hidden portions are restored during editing.";
 
-const char kOmniboxUIHideSuggestionUrlSchemeName[] =
-    "Omnibox UI Hide Suggestion URL Scheme";
-const char kOmniboxUIHideSuggestionUrlSchemeDescription[] =
-    "Elides the schemes of suggested URLs in the Omnibox dropdown.";
-
-const char kOmniboxUIHideSuggestionUrlTrivialSubdomainsName[] =
-    "Omnibox UI Hide Suggestion URL Trivial Subdomains";
-const char kOmniboxUIHideSuggestionUrlTrivialSubdomainsDescription[] =
-    "Elides trivially informative subdomains from suggested URLs in the "
-    "Omnibox dropdown (e.g. www. and m.).";
-
 const char kOmniboxUIMaxAutocompleteMatchesName[] =
     "Omnibox UI Max Autocomplete Matches";
 
@@ -2109,6 +2098,10 @@
 const char kNtpModernLayoutDescription[] =
     "Show a modern layout on the New Tab Page.";
 
+const char kNtpShortcutsName[] = "NTP Shortcuts";
+const char kNtpShortcutsDescription[] =
+    "Show shortcuts for bookmarks and downloads on the New Tab Page.";
+
 const char kSiteExplorationUiName[] = "Site Exploration UI";
 const char kSiteExplorationUiDescription[] =
     "Show site suggestions in the Exploration UI";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 64c57a5..0d746b6 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -646,12 +646,6 @@
 extern const char kOmniboxUIHideSteadyStateUrlSchemeAndSubdomainsName[];
 extern const char kOmniboxUIHideSteadyStateUrlSchemeAndSubdomainsDescription[];
 
-extern const char kOmniboxUIHideSuggestionUrlSchemeName[];
-extern const char kOmniboxUIHideSuggestionUrlSchemeDescription[];
-
-extern const char kOmniboxUIHideSuggestionUrlTrivialSubdomainsName[];
-extern const char kOmniboxUIHideSuggestionUrlTrivialSubdomainsDescription[];
-
 extern const char kOmniboxUIMaxAutocompleteMatchesName[];
 extern const char kOmniboxUIMaxAutocompleteMatchesDescription[];
 
@@ -1283,6 +1277,9 @@
 extern const char kNtpModernLayoutName[];
 extern const char kNtpModernLayoutDescription[];
 
+extern const char kNtpShortcutsName[];
+extern const char kNtpShortcutsDescription[];
+
 extern const char kSiteExplorationUiName[];
 extern const char kSiteExplorationUiDescription[];
 
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc
index e056fc9..b63bbb2 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -88,7 +88,7 @@
 #include "net/nqe/network_quality_estimator_params.h"
 #include "net/proxy_resolution/pac_file_fetcher_impl.h"
 #include "net/proxy_resolution/proxy_config_service.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/quic/chromium/quic_utils_chromium.h"
 #include "net/socket/ssl_client_socket.h"
 #include "net/url_request/url_fetcher.h"
diff --git a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc
index c81c6ea..0ad5af2 100644
--- a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc
+++ b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc
@@ -142,8 +142,6 @@
 
 namespace {
 
-ExternalProtocolHandler::Delegate* g_external_protocol_handler_delegate = NULL;
-
 void NotifyDownloadInitiatedOnUI(
     const content::ResourceRequestInfo::WebContentsGetter& wc_getter) {
   content::WebContents* web_contents = wc_getter.Run();
@@ -186,51 +184,6 @@
     prerender_manager->AddProfileNetworkBytesIfEnabled(bytes);
 }
 
-void LaunchURL(
-    const GURL& url,
-    const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
-    ui::PageTransition page_transition,
-    bool has_user_gesture) {
-  // If there is no longer a WebContents, the request may have raced with tab
-  // closing. Don't fire the external request. (It may have been a prerender.)
-  content::WebContents* web_contents = web_contents_getter.Run();
-  if (!web_contents)
-    return;
-
-  // Do not launch external requests attached to unswapped prerenders.
-  prerender::PrerenderContents* prerender_contents =
-      prerender::PrerenderContents::FromWebContents(web_contents);
-  if (prerender_contents) {
-    prerender_contents->Destroy(prerender::FINAL_STATUS_UNSUPPORTED_SCHEME);
-    prerender::ReportPrerenderExternalURL();
-    return;
-  }
-
-  bool is_whitelisted = false;
-  Profile* profile =
-      Profile::FromBrowserContext(web_contents->GetBrowserContext());
-  PolicyBlacklistService* service =
-      PolicyBlacklistFactory::GetForProfile(profile);
-  if (service) {
-    const policy::URLBlacklist::URLBlacklistState url_state =
-        service->GetURLBlacklistState(url);
-    is_whitelisted =
-        url_state == policy::URLBlacklist::URLBlacklistState::URL_IN_WHITELIST;
-  }
-
-  // If the URL is in whitelist, we launch it without asking the user and
-  // without any additional security checks. Since the URL is whitelisted,
-  // we assume it can be executed.
-  if (is_whitelisted) {
-    ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(url, web_contents);
-  } else {
-    ExternalProtocolHandler::LaunchUrlWithDelegate(
-        url, web_contents->GetRenderViewHost()->GetProcess()->GetID(),
-        web_contents->GetRenderViewHost()->GetRoutingID(), page_transition,
-        has_user_gesture, g_external_protocol_handler_delegate);
-  }
-}
-
 #if BUILDFLAG(ENABLE_NACL)
 void AppendComponentUpdaterThrottles(
     net::URLRequest* request,
@@ -568,39 +521,6 @@
 #endif
 }
 
-bool ChromeResourceDispatcherHostDelegate::HandleExternalProtocol(
-    const GURL& url,
-    content::ResourceRequestInfo* info) {
-
-#if BUILDFLAG(ENABLE_EXTENSIONS)
-  // External protocols are disabled for guests. An exception is made for the
-  // "mailto" protocol, so that pages that utilize it work properly in a
-  // WebView.
-  int child_id = info->GetChildID();
-  ChromeNavigationUIData* navigation_data =
-      static_cast<ChromeNavigationUIData*>(info->GetNavigationUIData());
-  if ((extensions::WebViewRendererState::GetInstance()->IsGuest(child_id) ||
-      (navigation_data &&
-       navigation_data->GetExtensionNavigationUIData()->is_web_view())) &&
-      !url.SchemeIs(url::kMailToScheme)) {
-    return false;
-  }
-#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
-
-#if defined(OS_ANDROID)
-  // Main frame external protocols are handled by
-  // InterceptNavigationResourceThrottle.
-  if (info->IsMainFrame())
-    return false;
-#endif  // defined(ANDROID)
-
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::BindOnce(&LaunchURL, url, info->GetWebContentsGetterForRequest(),
-                     info->GetPageTransition(), info->HasUserGesture()));
-  return true;
-}
-
 void ChromeResourceDispatcherHostDelegate::AppendStandardResourceThrottles(
     net::URLRequest* request,
     content::ResourceContext* resource_context,
@@ -923,13 +843,6 @@
   return previews_state;
 }
 
-// static
-void ChromeResourceDispatcherHostDelegate::
-    SetExternalProtocolHandlerDelegateForTesting(
-    ExternalProtocolHandler::Delegate* delegate) {
-  g_external_protocol_handler_delegate = delegate;
-}
-
 content::NavigationData*
 ChromeResourceDispatcherHostDelegate::GetNavigationData(
     net::URLRequest* request) const {
diff --git a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.h b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.h
index 7fc0506..a2767b5 100644
--- a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.h
+++ b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.h
@@ -66,8 +66,6 @@
                         bool is_new_request,
                         std::vector<std::unique_ptr<content::ResourceThrottle>>*
                             throttles) override;
-  bool HandleExternalProtocol(const GURL& url,
-                              content::ResourceRequestInfo* info) override;
   bool ShouldInterceptResourceAsStream(net::URLRequest* request,
                                        const std::string& mime_type,
                                        GURL* origin,
@@ -91,11 +89,6 @@
   content::NavigationData* GetNavigationData(
       net::URLRequest* request) const override;
 
-  // Called on the UI thread. Allows switching out the
-  // ExternalProtocolHandler::Delegate for testing code.
-  static void SetExternalProtocolHandlerDelegateForTesting(
-      ExternalProtocolHandler::Delegate* delegate);
-
  protected:
   // Virtual for testing.
   virtual void AppendStandardResourceThrottles(
diff --git a/chrome/browser/mash_service_registry.cc b/chrome/browser/mash_service_registry.cc
index 61f9cc1a..ff8a425 100644
--- a/chrome/browser/mash_service_registry.cc
+++ b/chrome/browser/mash_service_registry.cc
@@ -8,7 +8,7 @@
 #include "ash/public/interfaces/constants.mojom.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
-#include "components/font_service/public/interfaces/constants.mojom.h"
+#include "components/services/font/public/interfaces/constants.mojom.h"
 #include "services/ui/public/interfaces/constants.mojom.h"
 
 using content::ContentBrowserClient;
diff --git a/chrome/browser/memory_details.cc b/chrome/browser/memory_details.cc
index a2648df..34bc5ae 100644
--- a/chrome/browser/memory_details.cc
+++ b/chrome/browser/memory_details.cc
@@ -32,6 +32,8 @@
 #include "content/public/common/bindings_policy.h"
 #include "content/public/common/content_constants.h"
 #include "extensions/buildflags/buildflags.h"
+#include "services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h"
+#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
 #include "ui/base/l10n/l10n_util.h"
 
 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
@@ -96,7 +98,7 @@
       num_open_fds(-1),
       open_fds_soft_limit(-1),
       renderer_type(RENDERER_UNKNOWN),
-      phys_footprint(0) {}
+      private_memory_footprint_kb(0) {}
 
 ProcessMemoryInformation::ProcessMemoryInformation(
     const ProcessMemoryInformation& other) = default;
@@ -105,7 +107,7 @@
 
 bool ProcessMemoryInformation::operator<(
     const ProcessMemoryInformation& rhs) const {
-  return working_set.priv < rhs.working_set.priv;
+  return private_memory_footprint_kb < rhs.private_memory_footprint_kb;
 }
 
 ProcessData::ProcessData() {}
@@ -175,13 +177,8 @@
       }
       log += "]";
     }
-    log += StringPrintf(" %d MB private, %d MB shared",
-                        static_cast<int>(iter1->working_set.priv) / 1024,
-                        static_cast<int>(iter1->working_set.shared) / 1024);
-#if defined(OS_CHROMEOS)
-    log += StringPrintf(", %d MB swapped",
-                        static_cast<int>(iter1->working_set.swapped) / 1024);
-#endif
+    log += StringPrintf(
+        " %d MB", static_cast<int>(iter1->private_memory_footprint_kb) / 1024);
     if (iter1->num_open_fds != -1 || iter1->open_fds_soft_limit != -1) {
       log += StringPrintf(", %d FDs open of %d", iter1->num_open_fds,
                           iter1->open_fds_soft_limit);
@@ -359,5 +356,31 @@
   vector.erase(std::remove_if(vector.begin(), vector.end(), is_unknown),
                vector.end());
 
+  // Grab a memory dump for all processes.
+  // Using AdaptCallbackForRepeating allows for an easier transition to
+  // OnceCallbacks for https://crbug.com/714018.
+  memory_instrumentation::MemoryInstrumentation::GetInstance()
+      ->RequestGlobalDump(std::vector<std::string>(),
+                          base::AdaptCallbackForRepeating(base::BindOnce(
+                              &MemoryDetails::DidReceiveMemoryDump, this)));
+}
+
+void MemoryDetails::DidReceiveMemoryDump(
+    bool success,
+    std::unique_ptr<memory_instrumentation::GlobalMemoryDump> global_dump) {
+  ProcessData* const chrome_browser = ChromeBrowser();
+  if (success) {
+    for (const memory_instrumentation::GlobalMemoryDump::ProcessDump& dump :
+         global_dump->process_dumps()) {
+      base::ProcessId dump_pid = dump.pid();
+      for (ProcessMemoryInformation& pmi : chrome_browser->processes) {
+        if (pmi.pid == dump_pid) {
+          pmi.private_memory_footprint_kb = dump.os_dump().private_footprint_kb;
+          break;
+        }
+      }
+    }
+  }
+
   OnDetailsAvailable();
 }
diff --git a/chrome/browser/memory_details.h b/chrome/browser/memory_details.h
index 5f6b259..00c7de2 100644
--- a/chrome/browser/memory_details.h
+++ b/chrome/browser/memory_details.h
@@ -19,6 +19,10 @@
 #include "chrome/browser/site_details.h"
 #include "content/public/common/process_type.h"
 
+namespace memory_instrumentation {
+class GlobalMemoryDump;
+}  // namespace memory_instrumentation
+
 // We collect data about each browser process.  A browser may
 // have multiple processes (of course!).  Even IE has multiple
 // processes these days.
@@ -49,10 +53,6 @@
 
   // The process id.
   base::ProcessId pid;
-  // The working set information.
-  base::WorkingSetKBytes working_set;
-  // The committed bytes.
-  base::CommittedKBytes committed;
   // The process version
   base::string16 version;
   // The process product name.
@@ -69,9 +69,8 @@
   RendererProcessType renderer_type;
   // A collection of titles used, i.e. for a tab it'll show all the page titles.
   std::vector<base::string16> titles;
-  // The physical footprint is a macOS concept that tracks anonymous,
-  // non-discardable memory.
-  size_t phys_footprint;
+  // Consistent memory metric for all platforms.
+  size_t private_memory_footprint_kb;
 };
 
 typedef std::vector<ProcessMemoryInformation> ProcessMemoryInformationList;
@@ -170,6 +169,10 @@
   // renderer processes is only available there.
   void CollectChildInfoOnUIThread();
 
+  void DidReceiveMemoryDump(
+      bool success,
+      std::unique_ptr<memory_instrumentation::GlobalMemoryDump> dump);
+
   std::vector<ProcessData> process_data_;
 
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/memory_details_android.cc b/chrome/browser/memory_details_android.cc
index d8954be8..a19301de 100644
--- a/chrome/browser/memory_details_android.cc
+++ b/chrome/browser/memory_details_android.cc
@@ -63,7 +63,6 @@
 
     std::unique_ptr<base::ProcessMetrics> metrics(
         base::ProcessMetrics::CreateProcessMetrics(*i));
-    metrics->GetWorkingSetKBytes(&pmi.working_set);
 
     // TODO(ssid): Reading "/proc/fd" only works for current process. For child
     // processes, the values need to be computed by the process itself.
diff --git a/chrome/browser/memory_details_linux.cc b/chrome/browser/memory_details_linux.cc
index 38a7ce9..2cc9a8c 100644
--- a/chrome/browser/memory_details_linux.cc
+++ b/chrome/browser/memory_details_linux.cc
@@ -70,7 +70,6 @@
 
     std::unique_ptr<base::ProcessMetrics> metrics(
         base::ProcessMetrics::CreateProcessMetrics(pid));
-    metrics->GetWorkingSetKBytes(&pmi.working_set);
     pmi.num_open_fds = metrics->GetOpenFdCount();
     pmi.open_fds_soft_limit = metrics->GetOpenFdSoftLimit();
 
diff --git a/chrome/browser/memory_details_mac.cc b/chrome/browser/memory_details_mac.cc
index 312cb98..fd6b991 100644
--- a/chrome/browser/memory_details_mac.cc
+++ b/chrome/browser/memory_details_mac.cc
@@ -58,13 +58,6 @@
     }
   }
 
-  std::unique_ptr<base::ProcessMetrics> metrics =
-      base::ProcessMetrics::CreateProcessMetrics(
-          pid, content::BrowserChildProcessHost::GetPortProvider());
-  metrics->GetCommittedAndWorkingSetKBytes(&info.committed, &info.working_set);
-  base::ProcessMetrics::TaskVMInfo vm_info = metrics->GetTaskVMInfo();
-  info.phys_footprint = vm_info.phys_footprint;
-
   processes->push_back(info);
 }
 
diff --git a/chrome/browser/memory_details_win.cc b/chrome/browser/memory_details_win.cc
index 1d4288db..11515e7 100644
--- a/chrome/browser/memory_details_win.cc
+++ b/chrome/browser/memory_details_win.cc
@@ -78,11 +78,6 @@
                             ? content::PROCESS_TYPE_BROWSER
                             : content::PROCESS_TYPE_UNKNOWN;
 
-    std::unique_ptr<base::ProcessMetrics> metrics =
-        base::ProcessMetrics::CreateProcessMetrics(process_handle.Get());
-    metrics->GetCommittedKBytes(&info.committed);
-    metrics->GetWorkingSetKBytes(&info.working_set);
-
     // Get Version Information.
     info.version = base::ASCIIToUTF16(version_info::GetVersionNumber());
     // Check if this is one of the child processes whose data we collected
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc
index 77927b77..1866155c 100644
--- a/chrome/browser/metrics/chrome_metrics_service_client.cc
+++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -712,7 +712,7 @@
                  weak_ptr_factory_.GetWeakPtr());
 
   scoped_refptr<MetricsMemoryDetails> details(
-      new MetricsMemoryDetails(callback, &memory_growth_tracker_));
+      new MetricsMemoryDetails(callback));
   details->StartFetch();
 
   scoped_refptr<ProcessMemoryMetricsEmitter> emitter(
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.h b/chrome/browser/metrics/chrome_metrics_service_client.h
index d31ba84..517966d 100644
--- a/chrome/browser/metrics/chrome_metrics_service_client.h
+++ b/chrome/browser/metrics/chrome_metrics_service_client.h
@@ -204,10 +204,6 @@
   PluginMetricsProvider* plugin_metrics_provider_;
 #endif
 
-  // The MemoryGrowthTracker instance that tracks memory usage growth in
-  // MemoryDetails.
-  MemoryGrowthTracker memory_growth_tracker_;
-
   // Callback to determine whether or not a cellular network is currently being
   // used.
   base::Callback<void(bool*)> cellular_callback_;
diff --git a/chrome/browser/metrics/metrics_memory_details.cc b/chrome/browser/metrics/metrics_memory_details.cc
index 5b6bc1d..a67b3ff 100644
--- a/chrome/browser/metrics/metrics_memory_details.cc
+++ b/chrome/browser/metrics/metrics_memory_details.cc
@@ -21,47 +21,9 @@
 #include "ppapi/features/features.h"
 #include "third_party/leveldatabase/leveldb_chrome.h"
 
-MemoryGrowthTracker::MemoryGrowthTracker() {
-}
-
-MemoryGrowthTracker::~MemoryGrowthTracker() {
-}
-
-bool MemoryGrowthTracker::UpdateSample(base::ProcessId pid,
-                                       int sample,
-                                       int* diff) {
-  // |sample| is memory usage in kB.
-  const base::TimeTicks current_time = base::TimeTicks::Now();
-  std::map<base::ProcessId, int>::iterator found_size = memory_sizes_.find(pid);
-  if (found_size != memory_sizes_.end()) {
-    const int last_size = found_size->second;
-    std::map<base::ProcessId, base::TimeTicks>::iterator found_time =
-        times_.find(pid);
-    const base::TimeTicks last_time = found_time->second;
-    if (last_time < (current_time - base::TimeDelta::FromMinutes(30))) {
-      // Note that it is undefined how division of a negative integer gets
-      // rounded. |*diff| may have a difference of 1 from the correct number
-      // if |sample| < |last_size|. We ignore it as 1 is small enough.
-      *diff =
-          ((sample - last_size) * 30 / (current_time - last_time).InMinutes());
-      found_size->second = sample;
-      found_time->second = current_time;
-      return true;
-    }
-    // Skip if a last record is found less than 30 minutes ago.
-  } else {
-    // Not reporting if it's the first record for |pid|.
-    times_[pid] = current_time;
-    memory_sizes_[pid] = sample;
-  }
-  return false;
-}
-
 MetricsMemoryDetails::MetricsMemoryDetails(
-    const base::Closure& callback,
-    MemoryGrowthTracker* memory_growth_tracker)
+    const base::Closure& callback)
     : callback_(callback),
-      memory_growth_tracker_(memory_growth_tracker),
       generate_histograms_(true) {}
 
 MetricsMemoryDetails::~MetricsMemoryDetails() {
@@ -70,7 +32,6 @@
 void MetricsMemoryDetails::OnDetailsAvailable() {
   if (generate_histograms_)
     UpdateHistograms();
-  AnalyzeMemoryGrowth();
   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback_);
 }
 
@@ -80,22 +41,12 @@
   const ProcessData& browser = *ChromeBrowser();
   int chrome_count = 0;
   int extension_count = 0;
-  int pepper_plugin_count = 0;
-  int pepper_plugin_broker_count = 0;
   int renderer_count = 0;
-  int other_count = 0;
-  int worker_count = 0;
-  int process_limit = content::RenderProcessHost::GetMaxRendererProcessCount();
   for (size_t index = 0; index < browser.processes.size(); index++) {
-    size_t committed = browser.processes[index].committed.priv +
-                       browser.processes[index].committed.mapped +
-                       browser.processes[index].committed.image;
     int num_open_fds = browser.processes[index].num_open_fds;
     int open_fds_soft_limit = browser.processes[index].open_fds_soft_limit;
     switch (browser.processes[index].process_type) {
       case content::PROCESS_TYPE_BROWSER:
-        UMA_HISTOGRAM_MEMORY_LARGE_MB("Memory.Browser.Committed",
-                                      committed / 1024);
         if (num_open_fds != -1 && open_fds_soft_limit != -1) {
           UMA_HISTOGRAM_COUNTS_10000("Memory.Browser.OpenFDs", num_open_fds);
           UMA_HISTOGRAM_COUNTS_10000("Memory.Browser.OpenFDsSoftLimit",
@@ -129,9 +80,6 @@
             continue;
           case ProcessMemoryInformation::RENDERER_NORMAL:
           default:
-            // TODO(erikkay): Should we bother splitting out the other subtypes?
-            UMA_HISTOGRAM_MEMORY_LARGE_MB("Memory.Renderer.Committed",
-                                          committed / 1024);
             if (num_open_fds != -1) {
               UMA_HISTOGRAM_COUNTS_10000("Memory.Renderer.OpenFDs",
                                          num_open_fds);
@@ -143,19 +91,16 @@
       case content::PROCESS_TYPE_UTILITY:
         if (num_open_fds != -1)
           UMA_HISTOGRAM_COUNTS_10000("Memory.Utility.OpenFDs", num_open_fds);
-        other_count++;
         continue;
       case content::PROCESS_TYPE_ZYGOTE:
         if (num_open_fds != -1)
           UMA_HISTOGRAM_COUNTS_10000("Memory.Zygote.OpenFDs", num_open_fds);
-        other_count++;
         continue;
       case content::PROCESS_TYPE_SANDBOX_HELPER:
         if (num_open_fds != -1) {
           UMA_HISTOGRAM_COUNTS_10000("Memory.SandboxHelper.OpenFDs",
                                      num_open_fds);
         }
-        other_count++;
         continue;
       case content::PROCESS_TYPE_GPU:
         if (num_open_fds != -1 && open_fds_soft_limit != -1) {
@@ -163,7 +108,6 @@
           UMA_HISTOGRAM_COUNTS_10000("Memory.Gpu.OpenFDsSoftLimit",
                                      open_fds_soft_limit);
         }
-        other_count++;
         continue;
 #if BUILDFLAG(ENABLE_PLUGINS)
       case content::PROCESS_TYPE_PPAPI_PLUGIN: {
@@ -171,7 +115,6 @@
           UMA_HISTOGRAM_COUNTS_10000("Memory.PepperPlugin.OpenFDs",
                                      num_open_fds);
         }
-        pepper_plugin_count++;
         continue;
       }
       case content::PROCESS_TYPE_PPAPI_BROKER:
@@ -179,7 +122,6 @@
           UMA_HISTOGRAM_COUNTS_10000("Memory.PepperPluginBroker.OpenFDs",
                                      num_open_fds);
         }
-        pepper_plugin_broker_count++;
         continue;
 #endif
       case PROCESS_TYPE_NACL_LOADER:
@@ -187,14 +129,12 @@
           UMA_HISTOGRAM_COUNTS_10000("Memory.NativeClient.OpenFDs",
                                      num_open_fds);
         }
-        other_count++;
         continue;
       case PROCESS_TYPE_NACL_BROKER:
         if (num_open_fds != -1) {
           UMA_HISTOGRAM_COUNTS_10000("Memory.NativeClientBroker.OpenFDs",
                                      num_open_fds);
         }
-        other_count++;
         continue;
       default:
         NOTREACHED();
@@ -209,21 +149,6 @@
     UMA_HISTOGRAM_MEMORY_MB("Memory.Graphics", meminfo.gem_size / 1024 / 1024);
 #endif
 
-  UMA_HISTOGRAM_COUNTS_100("Memory.ProcessLimit", process_limit);
-  UMA_HISTOGRAM_COUNTS_100("Memory.ProcessCount",
-                           static_cast<int>(browser.processes.size()));
-  UMA_HISTOGRAM_COUNTS_100("Memory.ChromeProcessCount", chrome_count);
-  UMA_HISTOGRAM_COUNTS_100("Memory.ExtensionProcessCount", extension_count);
-  UMA_HISTOGRAM_COUNTS_100("Memory.OtherProcessCount", other_count);
-  UMA_HISTOGRAM_COUNTS_100("Memory.PepperPluginProcessCount",
-                           pepper_plugin_count);
-  UMA_HISTOGRAM_COUNTS_100("Memory.PepperPluginBrokerProcessCount",
-                           pepper_plugin_broker_count);
-  UMA_HISTOGRAM_COUNTS_100("Memory.RendererProcessCount", renderer_count);
-  UMA_HISTOGRAM_COUNTS_100("Memory.WorkerProcessCount", worker_count);
-  // TODO(viettrungluu): Do we want separate counts for the other
-  // (platform-specific) process types?
-
   // Predict the number of processes needed when isolating all sites and when
   // isolating only HTTPS sites.
   int all_renderer_count = renderer_count + chrome_count + extension_count;
@@ -232,121 +157,5 @@
   SiteDetails::UpdateHistograms(browser.site_data, all_renderer_count,
                                 non_renderer_count);
 
-#if defined(OS_CHROMEOS)
-  UpdateSwapHistograms();
-#endif
   leveldb_chrome::UpdateHistograms();
 }
-
-#if defined(OS_CHROMEOS)
-void MetricsMemoryDetails::UpdateSwapHistograms() {
-  UMA_HISTOGRAM_BOOLEAN("Memory.Swap.HaveSwapped", swap_info().num_writes > 0);
-  if (swap_info().num_writes == 0)
-    return;
-
-  // Only record swap info when any swaps have happened, to give us more
-  // detail in the histograms.
-  const ProcessData& browser = *ChromeBrowser();
-  size_t aggregate_memory = 0;
-  for (size_t index = 0; index < browser.processes.size(); index++) {
-    int sample = static_cast<int>(browser.processes[index].working_set.swapped);
-    aggregate_memory += sample;
-    switch (browser.processes[index].process_type) {
-      case content::PROCESS_TYPE_BROWSER:
-        UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Browser", sample);
-        continue;
-      case content::PROCESS_TYPE_RENDERER: {
-        ProcessMemoryInformation::RendererProcessType renderer_type =
-            browser.processes[index].renderer_type;
-        switch (renderer_type) {
-          case ProcessMemoryInformation::RENDERER_EXTENSION:
-            UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Extension", sample);
-            continue;
-          case ProcessMemoryInformation::RENDERER_CHROME:
-            UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Chrome", sample);
-            continue;
-          case ProcessMemoryInformation::RENDERER_UNKNOWN:
-            NOTREACHED() << "Unknown renderer process type.";
-            continue;
-          case ProcessMemoryInformation::RENDERER_NORMAL:
-          default:
-            UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Renderer", sample);
-            continue;
-        }
-      }
-      case content::PROCESS_TYPE_UTILITY:
-        UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Utility", sample);
-        continue;
-      case content::PROCESS_TYPE_ZYGOTE:
-        UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Zygote", sample);
-        continue;
-      case content::PROCESS_TYPE_SANDBOX_HELPER:
-        UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.SandboxHelper", sample);
-        continue;
-      case content::PROCESS_TYPE_GPU:
-        UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.Gpu", sample);
-        continue;
-      case content::PROCESS_TYPE_PPAPI_PLUGIN:
-        UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.PepperPlugin", sample);
-        continue;
-      case content::PROCESS_TYPE_PPAPI_BROKER:
-        UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.PepperPluginBroker", sample);
-        continue;
-      case PROCESS_TYPE_NACL_LOADER:
-        UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.NativeClient", sample);
-        continue;
-      case PROCESS_TYPE_NACL_BROKER:
-        UMA_HISTOGRAM_MEMORY_KB("Memory.Swap.NativeClientBroker", sample);
-        continue;
-      default:
-        NOTREACHED();
-        continue;
-    }
-  }
-
-  // TODO(rkaplow): Remove once we've verified Memory.Swap.Total2 is ok.
-  int total_sample_old = static_cast<int>(aggregate_memory / 1000);
-  UMA_HISTOGRAM_MEMORY_MB("Memory.Swap.Total", total_sample_old);
-  int total_sample = static_cast<int>(aggregate_memory / 1024);
-  UMA_HISTOGRAM_MEMORY_LARGE_MB("Memory.Swap.Total2", total_sample);
-
-  UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.CompressedDataSize",
-                              swap_info().compr_data_size / (1024 * 1024), 1,
-                              4096, 50);
-  UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.OriginalDataSize",
-                              swap_info().orig_data_size / (1024 * 1024), 1,
-                              4096, 50);
-  UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.MemUsedTotal",
-                              swap_info().mem_used_total / (1024 * 1024), 1,
-                              4096, 50);
-  UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.NumReads", swap_info().num_reads, 1,
-                              100000000, 100);
-  UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.Swap.NumWrites", swap_info().num_writes,
-                              1, 100000000, 100);
-
-  if (swap_info().orig_data_size > 0 && swap_info().compr_data_size > 0) {
-    UMA_HISTOGRAM_CUSTOM_COUNTS(
-        "Memory.Swap.CompressionRatio",
-        swap_info().orig_data_size / swap_info().compr_data_size, 1, 20, 20);
-  }
-}
-#endif  // defined(OS_CHROMEOS)
-
-void MetricsMemoryDetails::AnalyzeMemoryGrowth() {
-  for (const auto& process_entry : ChromeBrowser()->processes) {
-    int sample = static_cast<int>(process_entry.working_set.priv);
-    int diff;
-
-    // UpdateSample changes state of |memory_growth_tracker_| and it should be
-    // called even if |generate_histograms_| is false.
-    if (memory_growth_tracker_ &&
-        memory_growth_tracker_->UpdateSample(process_entry.pid, sample,
-                                             &diff) &&
-        generate_histograms_) {
-      if (diff < 0)
-        UMA_HISTOGRAM_MEMORY_KB("Memory.RendererShrinkIn30Min", -diff);
-      else
-        UMA_HISTOGRAM_MEMORY_KB("Memory.RendererGrowthIn30Min", diff);
-    }
-  }
-}
diff --git a/chrome/browser/metrics/metrics_memory_details.h b/chrome/browser/metrics/metrics_memory_details.h
index f833afb..b938d685 100644
--- a/chrome/browser/metrics/metrics_memory_details.h
+++ b/chrome/browser/metrics/metrics_memory_details.h
@@ -12,39 +12,12 @@
 #include "build/build_config.h"
 #include "chrome/browser/memory_details.h"
 
-// MemoryGrowthTracker tracks latest metrics about record time and memory usage
-// at that time per process.
-class MemoryGrowthTracker {
- public:
-  MemoryGrowthTracker();
-  virtual ~MemoryGrowthTracker();
-
-  // If 30 minutes have passed since last UMA record, UpdateSample() computes
-  // a difference between current memory usage |sample| of process |pid| and
-  // stored memory usage at the time of last UMA record. Then, it updates the
-  // stored memory usage to |sample|, stores the difference in |diff| and
-  // returns true.
-  // If no memory usage of |pid| has not been recorded so far or 30 minutes
-  // have not passed since last record, it just returns false.
-  // |sample| is memory usage in kB.
-  virtual bool UpdateSample(base::ProcessId pid, int sample, int* diff);
-
- private:
-  // Latest metrics about record time and memory usage at that time per process.
-  // The second values of |memory_sizes_| are in kB.
-  std::map<base::ProcessId, base::TimeTicks> times_;
-  std::map<base::ProcessId, int> memory_sizes_;
-
-  DISALLOW_COPY_AND_ASSIGN(MemoryGrowthTracker);
-};
-
 // Handles asynchronous fetching of memory details and logging histograms about
 // memory use of various processes.
 // Will run the provided callback when finished.
 class MetricsMemoryDetails : public MemoryDetails {
  public:
-  MetricsMemoryDetails(const base::Closure& callback,
-                       MemoryGrowthTracker* memory_growth_tracker);
+  explicit MetricsMemoryDetails(const base::Closure& callback);
 
   void set_generate_histograms(bool generate_histograms) {
     generate_histograms_ = generate_histograms;
@@ -60,21 +33,8 @@
   // Updates the global histograms for tracking memory usage.
   void UpdateHistograms();
 
-#if defined(OS_CHROMEOS)
-  void UpdateSwapHistograms();
-#endif
-
-  // Notifies |memory_growth_tracker_| about the memory usage.
-  // Update histograms on memory growth or shrink in renderer processes.
-  void AnalyzeMemoryGrowth();
-
   base::Closure callback_;
 
-  // A pointer to MemoryGrowthTracker which is contained in a longer-lived
-  // owner of MetricsMemoryDetails, for example, ChromeMetricsServiceClient.
-  // If it is null, nothing is tracked.
-  MemoryGrowthTracker* memory_growth_tracker_;
-
   // A flag indicating if histogram data should be generated. True on default.
   // If false, then only MemoryGrowthTracker gets notified about memory usage.
   bool generate_histograms_;
diff --git a/chrome/browser/metrics/metrics_memory_details_browsertest.cc b/chrome/browser/metrics/metrics_memory_details_browsertest.cc
deleted file mode 100644
index 46db7b01..0000000
--- a/chrome/browser/metrics/metrics_memory_details_browsertest.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/metrics/metrics_memory_details.h"
-
-#include "base/bind_helpers.h"
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/test/histogram_tester.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "content/public/test/test_utils.h"
-
-namespace {
-
-class TestMemoryDetails : public MetricsMemoryDetails {
- public:
-  TestMemoryDetails() : MetricsMemoryDetails(base::DoNothing(), nullptr) {}
-
-  void StartFetchAndWait() {
-    StartFetch();
-    content::RunMessageLoop();
-  }
-
- private:
-  ~TestMemoryDetails() override {}
-
-  void OnDetailsAvailable() override {
-    MetricsMemoryDetails::OnDetailsAvailable();
-    // Exit the loop initiated by StartFetchAndWait().
-    base::RunLoop::QuitCurrentWhenIdleDeprecated();
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(TestMemoryDetails);
-};
-
-}  // namespace
-
-class MetricsMemoryDetailsBrowserTest : public InProcessBrowserTest {
- public:
-  MetricsMemoryDetailsBrowserTest() {}
-  ~MetricsMemoryDetailsBrowserTest() override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MetricsMemoryDetailsBrowserTest);
-};
-
-IN_PROC_BROWSER_TEST_F(MetricsMemoryDetailsBrowserTest, TestMemoryDetails) {
-  base::HistogramTester histogram_tester;
-
-  scoped_refptr<TestMemoryDetails> details(new TestMemoryDetails);
-  details->StartFetchAndWait();
-
-  histogram_tester.ExpectTotalCount("Memory.Browser.Committed", 1);
-  std::unique_ptr<base::HistogramSamples> committed_samples(
-      histogram_tester.GetHistogramSamplesSinceCreation(
-          "Memory.Browser.Committed"));
-  ASSERT_TRUE(committed_samples);
-#if !defined(OS_LINUX)
-  // Committed memory isn't calculated on Linux.
-  EXPECT_NE(0, committed_samples->sum());
-#endif
-}
diff --git a/chrome/browser/net/predictor.cc b/chrome/browser/net/predictor.cc
index a5be71e..cd006b0 100644
--- a/chrome/browser/net/predictor.cc
+++ b/chrome/browser/net/predictor.cc
@@ -49,7 +49,7 @@
 #include "net/http/transport_security_state.h"
 #include "net/log/net_log_with_source.h"
 #include "net/proxy_resolution/proxy_info.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/ssl/ssl_config_service.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
diff --git a/chrome/browser/net/predictor_unittest.cc b/chrome/browser/net/predictor_unittest.cc
index 3bfca9c..b25bfee 100644
--- a/chrome/browser/net/predictor_unittest.cc
+++ b/chrome/browser/net/predictor_unittest.cc
@@ -28,7 +28,7 @@
 #include "net/base/net_errors.h"
 #include "net/http/transport_security_state.h"
 #include "net/proxy_resolution/proxy_config_service_fixed.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
diff --git a/chrome/browser/net/proxy_service_factory.cc b/chrome/browser/net/proxy_service_factory.cc
index 59d78ba..d0efbce 100644
--- a/chrome/browser/net/proxy_service_factory.cc
+++ b/chrome/browser/net/proxy_service_factory.cc
@@ -8,7 +8,7 @@
 #include "components/proxy_config/pref_proxy_config_tracker_impl.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/proxy_resolution/proxy_config_service.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 
 #if defined(OS_CHROMEOS)
 #include "chromeos/network/proxy/proxy_config_service_impl.h"
diff --git a/chrome/browser/notifications/notification_platform_bridge_win.cc b/chrome/browser/notifications/notification_platform_bridge_win.cc
index 7f663001..c2a8bef 100644
--- a/chrome/browser/notifications/notification_platform_bridge_win.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_win.cc
@@ -14,6 +14,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/command_line.h"
 #include "base/compiler_specific.h"
 #include "base/feature_list.h"
 #include "base/hash.h"
@@ -38,6 +39,7 @@
 #include "chrome/browser/notifications/notification_template_builder.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/chrome_features.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/install_static/install_util.h"
 #include "chrome/installer/util/install_util.h"
 #include "chrome/installer/util/shell_util.h"
@@ -87,6 +89,7 @@
     const std::string& profile_id,
     bool incognito,
     const base::Optional<int>& action_index,
+    const base::Optional<base::string16>& reply,
     const base::Optional<bool>& by_user) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!g_browser_process)
@@ -96,7 +99,7 @@
       profile_id, incognito,
       base::Bind(&NotificationDisplayServiceImpl::ProfileLoadedCallback,
                  operation, notification_type, origin, notification_id,
-                 action_index, /*reply=*/base::nullopt, by_user));
+                 action_index, reply, by_user));
 }
 
 }  // namespace
@@ -497,7 +500,8 @@
         base::BindOnce(&ForwardNotificationOperationOnUiThread, operation,
                        launch_id.notification_type(), launch_id.origin_url(),
                        launch_id.notification_id(), launch_id.profile_id(),
-                       launch_id.incognito(), action_index, by_user));
+                       launch_id.incognito(), action_index,
+                       /*reply=*/base::nullopt, by_user));
   }
 
   base::Optional<int> ParseActionIndex(
@@ -732,14 +736,22 @@
 }
 
 // static
-bool NotificationPlatformBridgeWin::HandleActivation(
-    const std::string& launch_id_str) {
+bool NotificationPlatformBridgeWin::HandleActivation() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  std::string launch_id_str =
+      command_line->GetSwitchValueASCII(switches::kNotificationLaunchId);
   NotificationLaunchId launch_id(launch_id_str);
   if (!launch_id.is_valid())
     return false;
 
+  base::Optional<base::string16> reply;
+  base::string16 inline_reply =
+      command_line->GetSwitchValueNative(switches::kNotificationInlineReply);
+  if (!inline_reply.empty())
+    reply = inline_reply;
+
   NotificationCommon::Operation operation = launch_id.is_for_context_menu()
                                                 ? NotificationCommon::SETTINGS
                                                 : NotificationCommon::CLICK;
@@ -747,7 +759,7 @@
   ForwardNotificationOperationOnUiThread(
       operation, launch_id.notification_type(), launch_id.origin_url(),
       launch_id.notification_id(), launch_id.profile_id(),
-      launch_id.incognito(), launch_id.button_index(), /*by_user=*/true);
+      launch_id.incognito(), launch_id.button_index(), reply, /*by_user=*/true);
 
   return true;
 }
diff --git a/chrome/browser/notifications/notification_platform_bridge_win.h b/chrome/browser/notifications/notification_platform_bridge_win.h
index a585a5e..9c3a5f9 100644
--- a/chrome/browser/notifications/notification_platform_bridge_win.h
+++ b/chrome/browser/notifications/notification_platform_bridge_win.h
@@ -38,9 +38,9 @@
       const GetDisplayedNotificationsCallback& callback) const override;
   void SetReadyCallback(NotificationBridgeReadyCallback callback) override;
 
-  // Handles notification activation given |launch_id_str| via the
-  // notification_helper process. Returns false if |launch_id_str| is invalid.
-  static bool HandleActivation(const std::string& launch_id_str);
+  // Handles notification activation from the notification_helper process.
+  // Returns false if the launch id, passed via the command line, is invalid.
+  static bool HandleActivation();
 
   // Extracts the profile ID from |launch_id_str|.
   static std::string GetProfileIdFromLaunchId(const std::string& launch_id_str);
diff --git a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
index e4039b0..82f1e97a 100644
--- a/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
+++ b/chrome/browser/ntp_snippets/content_suggestions_service_factory.cc
@@ -68,7 +68,6 @@
 
 #if defined(OS_ANDROID)
 #include "chrome/browser/android/chrome_feature_list.h"
-#include "chrome/browser/android/feature_utilities.h"
 #include "chrome/browser/android/ntp/ntp_snippets_launcher.h"
 #include "chrome/browser/download/download_core_service.h"
 #include "chrome/browser/download/download_core_service_factory.h"
@@ -126,8 +125,8 @@
 using syncer::SyncService;
 
 #if defined(OS_ANDROID)
-using chrome::android::GetIsChromeHomeEnabled;
 using content::DownloadManager;
+using ntp_snippets::AreNtpShortcutsEnabled;
 using ntp_snippets::BreakingNewsGCMAppHandler;
 using ntp_snippets::GetPushUpdatesSubscriptionEndpoint;
 using ntp_snippets::GetPushUpdatesUnsubscriptionEndpoint;
@@ -507,7 +506,7 @@
   std::unique_ptr<CategoryRanker> category_ranker =
       ntp_snippets::BuildSelectedCategoryRanker(
           pref_service, base::DefaultClock::GetInstance(),
-          GetIsChromeHomeEnabled());
+          AreNtpShortcutsEnabled());
 
   auto* service = new ContentSuggestionsService(
       State::ENABLED, identity_manager, history_service, large_icon_service,
diff --git a/chrome/browser/ntp_snippets/dependent_features.cc b/chrome/browser/ntp_snippets/dependent_features.cc
index cecd105..130bca8 100644
--- a/chrome/browser/ntp_snippets/dependent_features.cc
+++ b/chrome/browser/ntp_snippets/dependent_features.cc
@@ -18,15 +18,6 @@
 
 namespace {
 
-// All platforms proxy for chrome::android::GetIsChromeHomeEnabled.
-bool GetIsChromeHomeEnabled() {
-#if defined(OS_ANDROID)
-  return chrome::android::GetIsChromeHomeEnabled();
-#else
-  return false;
-#endif  // OS_ANDROID
-}
-
 bool IsPhysicalWebEnabled() {
 #if defined(OS_ANDROID)
   return base::FeatureList::IsEnabled(chrome::android::kPhysicalWebFeature);
@@ -37,14 +28,23 @@
 
 }  // namespace
 
+// All platforms proxy for whether NTP shortcuts are enabled.
+bool AreNtpShortcutsEnabled() {
+#if defined(OS_ANDROID)
+  return base::FeatureList::IsEnabled(chrome::android::kNTPShortcuts);
+#else
+  return false;
+#endif  // OS_ANDROID
+}
+
 bool AreAssetDownloadsEnabled() {
-  return !GetIsChromeHomeEnabled() &&
+  return !AreNtpShortcutsEnabled() &&
          base::FeatureList::IsEnabled(
              features::kAssetDownloadSuggestionsFeature);
 }
 
 bool AreOfflinePageDownloadsEnabled() {
-  return !GetIsChromeHomeEnabled() &&
+  return !AreNtpShortcutsEnabled() &&
          base::FeatureList::IsEnabled(
              features::kOfflinePageDownloadSuggestionsFeature);
 }
@@ -53,13 +53,13 @@
 }
 
 bool IsBookmarkProviderEnabled() {
-  return !GetIsChromeHomeEnabled() &&
+  return !AreNtpShortcutsEnabled() &&
          base::FeatureList::IsEnabled(
              ntp_snippets::kBookmarkSuggestionsFeature);
 }
 
 bool IsRecentTabProviderEnabled() {
-  return !GetIsChromeHomeEnabled() &&
+  return !AreNtpShortcutsEnabled() &&
          base::FeatureList::IsEnabled(
              ntp_snippets::kRecentOfflineTabSuggestionsFeature) &&
          base::FeatureList::IsEnabled(
@@ -67,14 +67,14 @@
 }
 
 bool IsPhysicalWebPageProviderEnabled() {
-  return !GetIsChromeHomeEnabled() &&
+  return !AreNtpShortcutsEnabled() &&
          base::FeatureList::IsEnabled(
              ntp_snippets::kPhysicalWebPageSuggestionsFeature) &&
          IsPhysicalWebEnabled();
 }
 
 bool IsForeignSessionsProviderEnabled() {
-  return !GetIsChromeHomeEnabled() &&
+  return !AreNtpShortcutsEnabled() &&
          base::FeatureList::IsEnabled(
              ntp_snippets::kForeignSessionsSuggestionsFeature);
 }
diff --git a/chrome/browser/ntp_snippets/dependent_features.h b/chrome/browser/ntp_snippets/dependent_features.h
index 665de65f..801621e5 100644
--- a/chrome/browser/ntp_snippets/dependent_features.h
+++ b/chrome/browser/ntp_snippets/dependent_features.h
@@ -9,6 +9,8 @@
 
 namespace ntp_snippets {
 
+bool AreNtpShortcutsEnabled();
+
 bool AreAssetDownloadsEnabled();
 bool AreOfflinePageDownloadsEnabled();
 bool IsDownloadsProviderEnabled();
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index bef2eac7..0610049 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -55,6 +55,7 @@
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/common/content_features.h"
 #include "content/public/common/context_menu_params.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
@@ -887,6 +888,42 @@
   EXPECT_EQ(base::ASCIIToUTF16("test.pdf"), GetActiveWebContents()->GetTitle());
 }
 
+IN_PROC_BROWSER_TEST_F(PDFExtensionTest, MultipleDomains) {
+  for (const auto& url :
+       {embedded_test_server()->GetURL("a.com", "/pdf/test.pdf"),
+        embedded_test_server()->GetURL("b.com", "/pdf/test.pdf"),
+        embedded_test_server()->GetURL("c.com", "/pdf/test.pdf"),
+        embedded_test_server()->GetURL("d.com", "/pdf/test.pdf")}) {
+    ASSERT_TRUE(LoadPdf(url));
+  }
+  EXPECT_EQ(1, CountPDFProcesses());
+}
+
+class PDFIsolatedExtensionTest : public PDFExtensionTest {
+ public:
+  PDFIsolatedExtensionTest() {}
+  ~PDFIsolatedExtensionTest() override {}
+
+  void SetUp() override {
+    features_.InitAndEnableFeature(features::kPdfIsolation);
+    PDFExtensionTest::SetUp();
+  }
+
+ private:
+  base::test::ScopedFeatureList features_;
+};
+
+IN_PROC_BROWSER_TEST_F(PDFIsolatedExtensionTest, MultipleDomains) {
+  for (const auto& url :
+       {embedded_test_server()->GetURL("a.com", "/pdf/test.pdf"),
+        embedded_test_server()->GetURL("b.com", "/pdf/test.pdf"),
+        embedded_test_server()->GetURL("c.com", "/pdf/test.pdf"),
+        embedded_test_server()->GetURL("d.com", "/pdf/test.pdf")}) {
+    ASSERT_TRUE(LoadPdf(url));
+  }
+  EXPECT_EQ(4, CountPDFProcesses());
+}
+
 class PDFExtensionLinkClickTest : public PDFExtensionTest {
  public:
   PDFExtensionLinkClickTest() : guest_contents_(nullptr) {}
diff --git a/chrome/browser/prerender/prerender_test_utils.cc b/chrome/browser/prerender/prerender_test_utils.cc
index e69f0fe9..a6ea2e2 100644
--- a/chrome/browser/prerender/prerender_test_utils.cc
+++ b/chrome/browser/prerender/prerender_test_utils.cc
@@ -15,7 +15,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/loader/chrome_resource_dispatcher_host_delegate.h"
 #include "chrome/browser/prerender/prerender_manager.h"
 #include "chrome/browser/prerender/prerender_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
@@ -712,9 +711,8 @@
                  base::Unretained(this)));
   if (autostart_test_server_)
     CHECK(embedded_test_server()->Start());
-  ChromeResourceDispatcherHostDelegate::
-      SetExternalProtocolHandlerDelegateForTesting(
-          external_protocol_handler_delegate_.get());
+  ExternalProtocolHandler::SetDelegateForTesting(
+      external_protocol_handler_delegate_.get());
 
   // Check that PrerenderManager exists, which is necessary to make sure
   // NoStatePrefetch can be enabled and perceived FCP metrics can be recorded.
diff --git a/chrome/browser/resources/chromeos/select_to_speak/paragraph_utils.js b/chrome/browser/resources/chromeos/select_to_speak/paragraph_utils.js
index bfecfdf..a94ef2b 100644
--- a/chrome/browser/resources/chromeos/select_to_speak/paragraph_utils.js
+++ b/chrome/browser/resources/chromeos/select_to_speak/paragraph_utils.js
@@ -161,7 +161,15 @@
         newNode = new NodeGroupItem(node, result.text.length, false);
       }
       if (newNode) {
-        result.text += newNode.node.name + ' ';
+        if (newNode.node.role == RoleType.TEXT_FIELD &&
+            newNode.node.children.length == 0 && newNode.node.value) {
+          // A text field with no children should use its value instead of
+          // the name element, this is the contents of the text field.
+          // This occurs in native UI such as the omnibox.
+          result.text += newNode.node.value + ' ';
+        } else {
+          result.text += newNode.node.name + ' ';
+        }
         result.nodes.push(newNode);
       }
     }
diff --git a/chrome/browser/resources/chromeos/select_to_speak/paragraph_utils_unittest.gtestjs b/chrome/browser/resources/chromeos/select_to_speak/paragraph_utils_unittest.gtestjs
index 943c0978..fefbc6f 100644
--- a/chrome/browser/resources/chromeos/select_to_speak/paragraph_utils_unittest.gtestjs
+++ b/chrome/browser/resources/chromeos/select_to_speak/paragraph_utils_unittest.gtestjs
@@ -150,4 +150,19 @@
   assertEquals(6, result.nodes[1].startChar);
   assertEquals(linkText, result.nodes[1].node);
   assertEquals(paragraph1, result.blockParent);
+});
+
+TEST_F('SelectToSpeakParagraphUnitTest', 'BuildNodeGroupNativeTextBox',
+    function() {
+  let root = {role: 'desktop'};
+  let parent = {role: 'pane', parent: root, root: root};
+  let searchBar = {role: 'textField', name: 'Address and search bar',
+      value: 'http://www.google.com', children: []};
+  let result = buildNodeGroup([searchBar], 0);
+  assertEquals('http://www.google.com ', result.text);
+
+  // If there is no value, it should use the name.
+  searchBar.value = '';
+  result = buildNodeGroup([searchBar], 0);
+  assertEquals('Address and search bar ', result.text);
 });
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/select_to_speak/test_support.js b/chrome/browser/resources/chromeos/select_to_speak/test_support.js
index c0f6d87..a0b83c4 100644
--- a/chrome/browser/resources/chromeos/select_to_speak/test_support.js
+++ b/chrome/browser/resources/chromeos/select_to_speak/test_support.js
@@ -22,7 +22,8 @@
   ROOT_WEB_AREA: 'rootWebArea',
   STATIC_TEXT: 'staticText',
   INLINE_TEXT_BOX: 'inlineTextBox',
-  PARAGRAPH: 'paragraph'
+  PARAGRAPH: 'paragraph',
+  TEXT_FIELD: 'textField',
 };
 
 chrome.automation.StateType = {
diff --git a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.js b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.js
index d213ede1..33cb93e 100644
--- a/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.js
+++ b/chrome/browser/resources/settings/passwords_and_forms_page/passwords_section.js
@@ -554,6 +554,8 @@
   /** @private */
   onPasswordsExportDialogClosed_: function() {
     this.showPasswordsExportDialog_ = false;
+    cr.ui.focusWithoutInk(assert(this.activeDialogAnchor_));
+    this.activeDialogAnchor_ = null;
   },
 
   /**
diff --git a/chrome/browser/search/suggestions/suggestions_service_factory.cc b/chrome/browser/search/suggestions/suggestions_service_factory.cc
index 8b24c82..72b3c80b 100644
--- a/chrome/browser/search/suggestions/suggestions_service_factory.cc
+++ b/chrome/browser/search/suggestions/suggestions_service_factory.cc
@@ -90,7 +90,7 @@
   return new SuggestionsServiceImpl(
       identity_manager, sync_service, profile->GetRequestContext(),
       std::move(suggestions_store), std::move(thumbnail_manager),
-      std::move(blacklist_store), std::make_unique<base::DefaultTickClock>());
+      std::move(blacklist_store), base::DefaultTickClock::GetInstance());
 }
 
 void SuggestionsServiceFactory::RegisterProfilePrefs(
diff --git a/chrome/browser/site_details_browsertest.cc b/chrome/browser/site_details_browsertest.cc
index db2659ea..aad93052 100644
--- a/chrome/browser/site_details_browsertest.cc
+++ b/chrome/browser/site_details_browsertest.cc
@@ -54,7 +54,7 @@
 
 class TestMemoryDetails : public MetricsMemoryDetails {
  public:
-  TestMemoryDetails() : MetricsMemoryDetails(base::DoNothing(), nullptr) {}
+  TestMemoryDetails() : MetricsMemoryDetails(base::DoNothing()) {}
 
   void StartFetchAndWait() {
     uma_.reset(new base::HistogramTester());
diff --git a/chrome/browser/subresource_filter/subresource_filter_browsertest.cc b/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
index 15772b61..c658e2f 100644
--- a/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
@@ -22,6 +22,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/metrics/subprocess_metrics_provider.h"
 #include "chrome/browser/page_load_metrics/observers/subresource_filter_metrics_observer.h"
@@ -69,6 +70,10 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
+namespace subresource_filter {
+
+using subresource_filter::testing::TestRulesetPair;
+
 namespace {
 
 namespace proto = url_pattern_index::proto;
@@ -132,13 +137,47 @@
   return url.ReplaceComponents(replacements);
 }
 
+void OpenAndPublishRuleset(ContentRulesetService* content_ruleset_service,
+                           const base::FilePath& path) {
+  base::File index_file;
+  base::RunLoop open_loop;
+  auto open_callback = base::BindRepeating(
+      [](base::OnceClosure quit_closure, base::File* out, base::File result) {
+        *out = std::move(result);
+        std::move(quit_closure).Run();
+      },
+      open_loop.QuitClosure(), &index_file);
+  content_ruleset_service->TryOpenAndSetRulesetFile(path,
+                                                    std::move(open_callback));
+  open_loop.Run();
+  ASSERT_TRUE(index_file.IsValid());
+  content_ruleset_service->PublishNewRulesetVersion(std::move(index_file));
+}
+
+RulesetVerificationStatus GetRulesetVerification() {
+  ContentRulesetService* service =
+      g_browser_process->subresource_filter_ruleset_service();
+  VerifiedRulesetDealer::Handle* dealer_handle = service->ruleset_dealer();
+
+  auto callback_method = [](base::OnceClosure quit_closure,
+                            RulesetVerificationStatus* status,
+                            VerifiedRulesetDealer* verified_dealer) {
+    *status = verified_dealer->status();
+    std::move(quit_closure).Run();
+  };
+
+  RulesetVerificationStatus status;
+  base::RunLoop run_loop;
+  auto callback =
+      base::BindRepeating(callback_method, run_loop.QuitClosure(), &status);
+
+  dealer_handle->GetDealerAsync(callback);
+  run_loop.Run();
+  return status;
+}
+
 }  // namespace
 
-namespace subresource_filter {
-
-using subresource_filter::testing::TestRulesetCreator;
-using subresource_filter::testing::TestRulesetPair;
-
 // Tests -----------------------------------------------------------------------
 
 IN_PROC_BROWSER_TEST_F(SubresourceFilterListInsertingBrowserTest,
@@ -654,8 +693,7 @@
   ContentRulesetService* service =
       g_browser_process->subresource_filter_ruleset_service();
   ASSERT_TRUE(service->ruleset_dealer());
-  service->PublishNewRulesetVersion(
-      testing::TestRuleset::Open(test_ruleset_pair.indexed));
+  OpenAndPublishRuleset(service, test_ruleset_pair.indexed.path);
 
   auto ruleset_handle =
       std::make_unique<VerifiedRuleset::Handle>(service->ruleset_dealer());
@@ -667,6 +705,27 @@
                                         receiver.GetCallback());
   receiver.WaitForActivationDecision();
   receiver.ExpectReceivedOnce(ActivationState(ActivationLevel::DISABLED));
+  RulesetVerificationStatus dealer_status = GetRulesetVerification();
+  EXPECT_EQ(RulesetVerificationStatus::CORRUPT, dealer_status);
+}
+
+IN_PROC_BROWSER_TEST_F(SubresourceFilterBrowserTest, LazyRulesetValidation) {
+  // The ruleset shouldn't be validated until it's used.
+  SetRulesetToDisallowURLsWithPathSuffix("included_script.js");
+  RulesetVerificationStatus dealer_status = GetRulesetVerification();
+  EXPECT_EQ(RulesetVerificationStatus::NOT_VERIFIED, dealer_status);
+}
+
+IN_PROC_BROWSER_TEST_F(SubresourceFilterBrowserTest,
+                       AdsTaggingImmediateRulesetValidation) {
+  // When Ads Tagging is enabled, the ruleset should be validated as soon as
+  // it's published.
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(subresource_filter::kAdTagging);
+
+  SetRulesetToDisallowURLsWithPathSuffix("included_script.js");
+  RulesetVerificationStatus dealer_status = GetRulesetVerification();
+  EXPECT_EQ(RulesetVerificationStatus::INTACT, dealer_status);
 }
 
 IN_PROC_BROWSER_TEST_F(SubresourceFilterBrowserTest, PageLoadMetrics) {
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 55bb0ab..b5352b83 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -3901,16 +3901,16 @@
       "views/payments/test_chrome_payment_request_delegate.h",
       "views/toolbar/browser_action_test_util_views_mac.mm",
     ]
+    if (is_mac) {
+      sources += [ "cocoa/extensions/browser_action_test_util_views_cocoa.mm" ]
+    }
     if (!is_mac || mac_views_browser) {
       sources += [
         "views/find_bar_host_unittest_util_views.cc",
         "views/toolbar/browser_action_test_util_views.cc",
       ]
     } else {
-      sources += [
-        "cocoa/extensions/browser_action_test_util_views_cocoa.mm",
-        "cocoa/find_bar/find_bar_host_unittest_util_cocoa.mm",
-      ]
+      sources += [ "cocoa/find_bar/find_bar_host_unittest_util_cocoa.mm" ]
     }
     if (use_aura) {
       sources += [ "views/toolbar/browser_action_test_util_views_aura.cc" ]
diff --git a/chrome/browser/ui/cocoa/extensions/browser_action_test_util_views_cocoa.mm b/chrome/browser/ui/cocoa/extensions/browser_action_test_util_views_cocoa.mm
index d86f903..bb2101a 100644
--- a/chrome/browser/ui/cocoa/extensions/browser_action_test_util_views_cocoa.mm
+++ b/chrome/browser/ui/cocoa/extensions/browser_action_test_util_views_cocoa.mm
@@ -12,6 +12,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/path_service.h"
 #include "base/strings/sys_string_conversions.h"
+#include "build/buildflag.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/cocoa/browser_dialogs_views_mac.h"
 #import "chrome/browser/ui/cocoa/browser_window_cocoa.h"
@@ -27,8 +28,11 @@
 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
 #include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
+#include "chrome/browser/ui/views/toolbar/browser_action_test_util_views.h"
+#include "chrome/browser/ui/views_mode_controller.h"
 #include "chrome/common/chrome_constants.h"
 #include "ui/base/theme_provider.h"
+#include "ui/base/ui_features.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/native_widget_types.h"
@@ -185,12 +189,51 @@
 
 }  // namespace
 
-BrowserActionTestUtil::BrowserActionTestUtil(Browser* browser)
-    : BrowserActionTestUtil(browser, true) {
-}
+class BrowserActionTestUtilCocoa : public BrowserActionTestUtil {
+ public:
+  explicit BrowserActionTestUtilCocoa(Browser* browser);
+  BrowserActionTestUtilCocoa(Browser* browser, bool is_real_window);
 
-BrowserActionTestUtil::BrowserActionTestUtil(Browser* browser,
-                                             bool is_real_window)
+  ~BrowserActionTestUtilCocoa() override;
+
+  // BrowserActionTestUtil:
+  int NumberOfBrowserActions() override;
+  int VisibleBrowserActions() override;
+  void InspectPopup(int index) override;
+  bool HasIcon(int index) override;
+  gfx::Image GetIcon(int index) override;
+  void Press(int index) override;
+  std::string GetExtensionId(int index) override;
+  std::string GetTooltip(int index) override;
+  gfx::NativeView GetPopupNativeView() override;
+  bool HasPopup() override;
+  gfx::Size GetPopupSize() override;
+  bool HidePopup() override;
+  bool ActionButtonWantsToRun(size_t index) override;
+  void SetWidth(int width) override;
+  ToolbarActionsBar* GetToolbarActionsBar() override;
+  std::unique_ptr<BrowserActionTestUtil> CreateOverflowBar() override;
+  gfx::Size GetMinPopupSize() override;
+  gfx::Size GetMaxPopupSize() override;
+
+ private:
+  friend class BrowserActionTestUtil;
+
+  BrowserActionTestUtilCocoa(Browser* browser,
+                             BrowserActionTestUtilCocoa* main_bar);
+
+  Browser* const browser_;  // weak
+
+  // Our test helper, which constructs and owns the views if we don't have a
+  // real browser window, or if this is an overflow version.
+  std::unique_ptr<TestToolbarActionsBarHelper> test_helper_;
+};
+
+BrowserActionTestUtilCocoa::BrowserActionTestUtilCocoa(Browser* browser)
+    : BrowserActionTestUtilCocoa(browser, true) {}
+
+BrowserActionTestUtilCocoa::BrowserActionTestUtilCocoa(Browser* browser,
+                                                       bool is_real_window)
     : browser_(browser) {
   if (!is_real_window)
     test_helper_.reset(new TestToolbarActionsBarHelperCocoa(browser, nullptr));
@@ -199,25 +242,25 @@
   GetExtensionPopupTestManager()->DisableAnimations();
 }
 
-BrowserActionTestUtil::~BrowserActionTestUtil() {}
+BrowserActionTestUtilCocoa::~BrowserActionTestUtilCocoa() {}
 
-int BrowserActionTestUtil::NumberOfBrowserActions() {
+int BrowserActionTestUtilCocoa::NumberOfBrowserActions() {
   return [GetController(browser_, test_helper_.get()) buttonCount];
 }
 
-int BrowserActionTestUtil::VisibleBrowserActions() {
+int BrowserActionTestUtilCocoa::VisibleBrowserActions() {
   return [GetController(browser_, test_helper_.get()) visibleButtonCount];
 }
 
-void BrowserActionTestUtil::InspectPopup(int index) {
+void BrowserActionTestUtilCocoa::InspectPopup(int index) {
   NOTREACHED();
 }
 
-bool BrowserActionTestUtil::HasIcon(int index) {
+bool BrowserActionTestUtilCocoa::HasIcon(int index) {
   return [GetButton(browser_, test_helper_.get(), index) image] != nil;
 }
 
-gfx::Image BrowserActionTestUtil::GetIcon(int index) {
+gfx::Image BrowserActionTestUtilCocoa::GetIcon(int index) {
   NSImage* ns_image = [GetButton(browser_, test_helper_.get(), index) image];
   // gfx::Image takes ownership of the |ns_image| reference. We have to increase
   // the ref count so |ns_image| stays around when the image object is
@@ -226,45 +269,45 @@
   return gfx::Image(ns_image);
 }
 
-void BrowserActionTestUtil::Press(int index) {
+void BrowserActionTestUtilCocoa::Press(int index) {
   NSButton* button = GetButton(browser_, test_helper_.get(), index);
   [button performClick:nil];
 }
 
-std::string BrowserActionTestUtil::GetExtensionId(int index) {
+std::string BrowserActionTestUtilCocoa::GetExtensionId(int index) {
   return
       [GetButton(browser_, test_helper_.get(), index) viewController]->GetId();
 }
 
-std::string BrowserActionTestUtil::GetTooltip(int index) {
+std::string BrowserActionTestUtilCocoa::GetTooltip(int index) {
   NSString* tooltip = [GetButton(browser_, test_helper_.get(), index) toolTip];
   return base::SysNSStringToUTF8(tooltip);
 }
 
-gfx::NativeView BrowserActionTestUtil::GetPopupNativeView() {
+gfx::NativeView BrowserActionTestUtilCocoa::GetPopupNativeView() {
   ToolbarActionViewController* popup_owner =
       GetToolbarActionsBar()->popup_owner();
   return popup_owner ? popup_owner->GetPopupNativeView() : nil;
 }
 
-bool BrowserActionTestUtil::HasPopup() {
+bool BrowserActionTestUtilCocoa::HasPopup() {
   return GetPopupNativeView() != nil;
 }
 
-gfx::Size BrowserActionTestUtil::GetPopupSize() {
+gfx::Size BrowserActionTestUtilCocoa::GetPopupSize() {
   return GetExtensionPopupTestManager()->GetPopupSize(this);
 }
 
-bool BrowserActionTestUtil::HidePopup() {
+bool BrowserActionTestUtilCocoa::HidePopup() {
   GetExtensionPopupTestManager()->HidePopup(this);
   return !HasPopup();
 }
 
-bool BrowserActionTestUtil::ActionButtonWantsToRun(size_t index) {
+bool BrowserActionTestUtilCocoa::ActionButtonWantsToRun(size_t index) {
   return [GetButton(browser_, test_helper_.get(), index) wantsToRunForTesting];
 }
 
-void BrowserActionTestUtil::SetWidth(int width) {
+void BrowserActionTestUtilCocoa::SetWidth(int width) {
   BrowserActionsContainerView* containerView =
       [GetController(browser_, test_helper_.get()) containerView];
   NSRect frame = [containerView frame];
@@ -272,30 +315,41 @@
   [containerView setFrame:frame];
 }
 
-ToolbarActionsBar* BrowserActionTestUtil::GetToolbarActionsBar() {
+ToolbarActionsBar* BrowserActionTestUtilCocoa::GetToolbarActionsBar() {
   return [GetController(browser_, test_helper_.get()) toolbarActionsBar];
 }
 
 std::unique_ptr<BrowserActionTestUtil>
-BrowserActionTestUtil::CreateOverflowBar() {
+BrowserActionTestUtilCocoa::CreateOverflowBar() {
   CHECK(!GetToolbarActionsBar()->in_overflow_mode())
       << "Only a main bar can create an overflow bar!";
-  return base::WrapUnique(new BrowserActionTestUtil(browser_, this));
+  return base::WrapUnique(new BrowserActionTestUtilCocoa(browser_, this));
 }
 
-// static
-gfx::Size BrowserActionTestUtil::GetMinPopupSize() {
+gfx::Size BrowserActionTestUtilCocoa::GetMinPopupSize() {
   return GetExtensionPopupTestManager()->GetMinPopupSize();
 }
 
-// static
-gfx::Size BrowserActionTestUtil::GetMaxPopupSize() {
+gfx::Size BrowserActionTestUtilCocoa::GetMaxPopupSize() {
   return GetExtensionPopupTestManager()->GetMaxPopupSize();
 }
 
-BrowserActionTestUtil::BrowserActionTestUtil(Browser* browser,
-                                             BrowserActionTestUtil* main_bar)
+BrowserActionTestUtilCocoa::BrowserActionTestUtilCocoa(
+    Browser* browser,
+    BrowserActionTestUtilCocoa* main_bar)
     : browser_(browser),
       test_helper_(new TestToolbarActionsBarHelperCocoa(
-          browser_, GetController(browser_, main_bar->test_helper_.get()))) {
+          browser_,
+          GetController(browser_, main_bar->test_helper_.get()))) {}
+
+// static
+std::unique_ptr<BrowserActionTestUtil> BrowserActionTestUtil::Create(
+    Browser* browser,
+    bool is_real_window) {
+#if BUILDFLAG(MAC_VIEWS_BROWSER)
+  if (!views_mode_controller::IsViewsBrowserCocoa())
+    return std::make_unique<BrowserActionTestUtilViews>(browser,
+                                                        is_real_window);
+#endif
+  return std::make_unique<BrowserActionTestUtilCocoa>(browser, is_real_window);
 }
diff --git a/chrome/browser/ui/extensions/browser_action_test_util.h b/chrome/browser/ui/extensions/browser_action_test_util.h
index 8543991..00c051c 100644
--- a/chrome/browser/ui/extensions/browser_action_test_util.h
+++ b/chrome/browser/ui/extensions/browser_action_test_util.h
@@ -30,90 +30,84 @@
 
 class BrowserActionTestUtil {
  public:
-  // Constructs a BrowserActionTestUtil that uses the |browser|'s default
-  // browser action container.
-  explicit BrowserActionTestUtil(Browser* browser);
-
   // Constructs a BrowserActionTestUtil which, if |is_real_window| is false,
   // will create its own browser actions container. This is useful in unit
   // tests, when the |browser|'s window doesn't create platform-specific views.
-  BrowserActionTestUtil(Browser* browser, bool is_real_window);
+  static std::unique_ptr<BrowserActionTestUtil> Create(
+      Browser* browser,
+      bool is_real_window = true);
 
-  ~BrowserActionTestUtil();
+  virtual ~BrowserActionTestUtil() {}
 
   // Returns the number of browser action buttons in the window toolbar.
-  int NumberOfBrowserActions();
+  virtual int NumberOfBrowserActions() = 0;
 
   // Returns the number of browser action currently visible.
-  int VisibleBrowserActions();
+  virtual int VisibleBrowserActions() = 0;
 
   // Inspects the extension popup for the action at the given index.
-  void InspectPopup(int index);
+  virtual void InspectPopup(int index) = 0;
 
   // Returns whether the browser action at |index| has a non-null icon. Note
   // that the icon is loaded asynchronously, in which case you can wait for it
   // to load by calling WaitForBrowserActionUpdated.
-  bool HasIcon(int index);
+  virtual bool HasIcon(int index) = 0;
 
   // Returns icon for the browser action at |index|.
-  gfx::Image GetIcon(int index);
+  virtual gfx::Image GetIcon(int index) = 0;
 
   // Simulates a user click on the browser action button at |index|.
-  void Press(int index);
+  virtual void Press(int index) = 0;
 
   // Returns the extension id of the extension at |index|.
-  std::string GetExtensionId(int index);
+  virtual std::string GetExtensionId(int index) = 0;
 
   // Returns the current tooltip for the browser action button.
-  std::string GetTooltip(int index);
+  virtual std::string GetTooltip(int index) = 0;
 
-  gfx::NativeView GetPopupNativeView();
+  virtual gfx::NativeView GetPopupNativeView() = 0;
 
   // Spins a RunLoop until the NativeWindow hosting |GetPopupNativeView()| is
-  // reported as active by the OS. Returns true if successful.
+  // reported as active by the OS. Returns true if successful. This method is
+  // strange: it's not overridden by subclasses, and instead the implementation
+  // is selected at compile-time depending on the windowing system in use.
   bool WaitForPopup();
 
   // Returns whether a browser action popup is being shown currently.
-  bool HasPopup();
+  virtual bool HasPopup() = 0;
 
   // Returns the size of the current browser action popup.
-  gfx::Size GetPopupSize();
+  virtual gfx::Size GetPopupSize() = 0;
 
   // Hides the given popup and returns whether the hide was successful.
-  bool HidePopup();
+  virtual bool HidePopup() = 0;
 
   // Tests that the button at the given |index| is displaying that it wants
   // to run.
-  bool ActionButtonWantsToRun(size_t index);
+  virtual bool ActionButtonWantsToRun(size_t index) = 0;
 
   // Sets the current width of the browser actions container without resizing
   // the underlying controller. This is to simulate e.g. when the browser window
   // is too small for the preferred width.
-  void SetWidth(int width);
+  virtual void SetWidth(int width) = 0;
 
   // Returns the ToolbarActionsBar.
-  ToolbarActionsBar* GetToolbarActionsBar();
+  virtual ToolbarActionsBar* GetToolbarActionsBar() = 0;
 
   // Creates and returns a BrowserActionTestUtil with an "overflow" container,
   // with this object's container as the main bar.
-  std::unique_ptr<BrowserActionTestUtil> CreateOverflowBar();
+  virtual std::unique_ptr<BrowserActionTestUtil> CreateOverflowBar() = 0;
 
   // Returns the minimum allowed size of an extension popup.
-  static gfx::Size GetMinPopupSize();
+  virtual gfx::Size GetMinPopupSize() = 0;
 
   // Returns the maximum allowed size of an extension popup.
-  static gfx::Size GetMaxPopupSize();
+  virtual gfx::Size GetMaxPopupSize() = 0;
+
+ protected:
+  BrowserActionTestUtil() {}
 
  private:
-  // A private constructor to create an overflow version.
-  BrowserActionTestUtil(Browser* browser, BrowserActionTestUtil* main_bar);
-
-  Browser* const browser_;  // weak
-
-  // Our test helper, which constructs and owns the views if we don't have a
-  // real browser window, or if this is an overflow version.
-  std::unique_ptr<TestToolbarActionsBarHelper> test_helper_;
-
   DISALLOW_COPY_AND_ASSIGN(BrowserActionTestUtil);
 };
 
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
index f37f47d4..a0de46b 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -335,9 +335,7 @@
   // Launch() call is from notification_helper.exe to process toast activation.
   // Delegate to the notification system; do not open a browser window here.
   if (command_line_.HasSwitch(switches::kNotificationLaunchId)) {
-    if (NotificationPlatformBridgeWin::HandleActivation(
-            command_line_.GetSwitchValueASCII(
-                switches::kNotificationLaunchId))) {
+    if (NotificationPlatformBridgeWin::HandleActivation()) {
       RecordLaunchModeHistogram(LM_WIN_PLATFORM_NOTIFICATION);
       return true;
     }
diff --git a/chrome/browser/ui/toolbar/browser_actions_bar_browsertest.cc b/chrome/browser/ui/toolbar/browser_actions_bar_browsertest.cc
index 9bcab312..f7de23e 100644
--- a/chrome/browser/ui/toolbar/browser_actions_bar_browsertest.cc
+++ b/chrome/browser/ui/toolbar/browser_actions_bar_browsertest.cc
@@ -74,7 +74,7 @@
 
 void BrowserActionsBarBrowserTest::SetUpOnMainThread() {
   ExtensionBrowserTest::SetUpOnMainThread();
-  browser_actions_bar_.reset(new BrowserActionTestUtil(browser()));
+  browser_actions_bar_ = BrowserActionTestUtil::Create(browser());
   toolbar_model_ = ToolbarActionsModel::Get(profile());
 }
 
diff --git a/chrome/browser/ui/toolbar/component_toolbar_actions_browsertest.cc b/chrome/browser/ui/toolbar/component_toolbar_actions_browsertest.cc
index 6208d63..ed8f2fb 100644
--- a/chrome/browser/ui/toolbar/component_toolbar_actions_browsertest.cc
+++ b/chrome/browser/ui/toolbar/component_toolbar_actions_browsertest.cc
@@ -39,26 +39,26 @@
 // and can receive click events properly.
 IN_PROC_BROWSER_TEST_F(ComponentToolbarActionsBrowserTest,
                        ComponentToolbarActionsShowUpAndRespondToClicks) {
-  BrowserActionTestUtil browser_actions_bar(browser());
+  auto browser_actions_bar = BrowserActionTestUtil::Create(browser());
   toolbar_model_->AddComponentAction(
       MockComponentToolbarActionsFactory::kActionIdForTesting);
 
   // There should be only one component action view.
-  ASSERT_EQ(1, browser_actions_bar.NumberOfBrowserActions());
+  ASSERT_EQ(1, browser_actions_bar->NumberOfBrowserActions());
 
   // Even though the method says "ExtensionId", this actually refers to any id
   // for the action.
   EXPECT_EQ(MockComponentToolbarActionsFactory::kActionIdForTesting,
-            browser_actions_bar.GetExtensionId(0));
+            browser_actions_bar->GetExtensionId(0));
 
   const std::vector<ToolbarActionViewController*>& actions =
-      browser_actions_bar.GetToolbarActionsBar()->GetActions();
+      browser_actions_bar->GetToolbarActionsBar()->GetActions();
   TestToolbarActionViewController* mock_component_action =
       static_cast<TestToolbarActionViewController* const>(actions[0]);
   ASSERT_TRUE(mock_component_action);
 
   // Test that clicking on the component action works.
   EXPECT_EQ(0, mock_component_action->execute_action_count());
-  browser_actions_bar.Press(0);
+  browser_actions_bar->Press(0);
   EXPECT_EQ(1, mock_component_action->execute_action_count());
 }
diff --git a/chrome/browser/ui/toolbar/media_router_action_unittest.cc b/chrome/browser/ui/toolbar/media_router_action_unittest.cc
index dbf7985..3d553809 100644
--- a/chrome/browser/ui/toolbar/media_router_action_unittest.cc
+++ b/chrome/browser/ui/toolbar/media_router_action_unittest.cc
@@ -112,8 +112,7 @@
 
     // browser() will only be valid once BrowserWithTestWindowTest::SetUp()
     // has run.
-    browser_action_test_util_.reset(
-        new BrowserActionTestUtil(browser(), false));
+    browser_action_test_util_ = BrowserActionTestUtil::Create(browser(), false);
     action_.reset(
         new TestMediaRouterAction(
             browser(),
diff --git a/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc b/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc
index d35424b4..c26c764 100644
--- a/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc
+++ b/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc
@@ -49,8 +49,7 @@
 
     signin_manager_ =
         SigninManagerFactory::GetInstance()->GetForProfile(profile());
-    browser_action_test_util_ =
-        std::make_unique<BrowserActionTestUtil>(browser(), false);
+    browser_action_test_util_ = BrowserActionTestUtil::Create(browser(), false);
     action_ = std::make_unique<MediaRouterAction>(
         browser(), browser_action_test_util_->GetToolbarActionsBar());
 
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc b/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc
index f854f09f..d9c5742 100644
--- a/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc
+++ b/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc
@@ -167,7 +167,7 @@
   material_design_state_.reset(
       new ui::test::MaterialDesignControllerTestAPI(GetParam()));
   ToolbarActionsBar::disable_animations_for_testing_ = true;
-  browser_action_test_util_.reset(new BrowserActionTestUtil(browser(), false));
+  browser_action_test_util_ = BrowserActionTestUtil::Create(browser(), false);
 
   overflow_browser_action_test_util_ =
       browser_action_test_util_->CreateOverflowBar();
diff --git a/chrome/browser/ui/views/arc_app_dialog_view.cc b/chrome/browser/ui/views/arc_app_dialog_view.cc
index 5587a93..c6d36af 100644
--- a/chrome/browser/ui/views/arc_app_dialog_view.cc
+++ b/chrome/browser/ui/views/arc_app_dialog_view.cc
@@ -219,16 +219,6 @@
 void ArcAppDialogView::Show() {
   initial_setup_ = false;
 
-  // The parent window was killed before the icon was loaded.
-  // TODO(lgcheng@) : Remove this since the dialog is not parented to applist
-  // anymore.
-  if (controller_ && !AppListService::Get()->IsAppListVisible()) {
-    g_current_arc_app_dialog_view = nullptr;
-    Cancel();
-    DialogDelegateView::DeleteDelegate();
-    return;
-  }
-
   if (controller_)
     controller_->OnShowChildDialog();
 
diff --git a/chrome/browser/ui/views/arc_app_dialog_view_browsertest.cc b/chrome/browser/ui/views/arc_app_dialog_view_browsertest.cc
index 9ac732f..98d6b4fe 100644
--- a/chrome/browser/ui/views/arc_app_dialog_view_browsertest.cc
+++ b/chrome/browser/ui/views/arc_app_dialog_view_browsertest.cc
@@ -11,10 +11,7 @@
 #include "chrome/browser/chromeos/arc/arc_session_manager.h"
 #include "chrome/browser/chromeos/arc/arc_util.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
-#include "chrome/browser/ui/app_list/app_list_service.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
-#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
 #include "chrome/browser/ui/app_list/arc/arc_usb_host_permission_manager.h"
 #include "chrome/browser/ui/browser.h"
@@ -44,11 +41,6 @@
 
   void SetUpOnMainThread() override {
     profile_ = browser()->profile();
-    arc_app_list_pref_ = ArcAppListPrefs::Get(profile_);
-    if (!arc_app_list_pref_) {
-      ArcAppListPrefsFactory::GetInstance()->RecreateServiceInstanceForTesting(
-          profile_);
-    }
 
     arc::SetArcPlayStoreEnabledForProfile(profile_, true);
 
@@ -410,112 +402,59 @@
 // share same package.
 IN_PROC_BROWSER_TEST_F(ArcAppUninstallDialogViewBrowserTest,
                        UserConfirmsUninstall) {
-  std::vector<std::string> app_ids = arc_app_list_pref()->GetAppIds();
-  EXPECT_EQ(app_ids.size(), 2u);
+  EXPECT_EQ(2u, arc_app_list_pref()->GetAppIds().size());
   std::string package_name = "fake.package.0";
   std::string app_activity = "fake.app.0.activity";
   std::string app_id =
       arc_app_list_pref()->GetAppId(package_name, app_activity);
 
-  AppListService* service = AppListService::Get();
-  ASSERT_TRUE(service);
-  AppListControllerDelegate* controller(service->GetControllerDelegate());
-  ASSERT_TRUE(controller);
-
-  // The dialog is only shown when AppList is visible, so we show AppList
-  // first.
-  service->ShowForProfile(browser()->profile());
-  ShowArcAppUninstallDialog(browser()->profile(), controller, app_id);
+  ShowArcAppUninstallDialog(browser()->profile(), nullptr /*controller*/,
+                            app_id);
   content::RunAllPendingInMessageLoop();
 
-  // When we show the dialog, AppList loses focus and gets dismissed.
-  EXPECT_FALSE(service->IsAppListVisible());
-
   // Cancelling the dialog won't uninstall any app.
   EXPECT_TRUE(CloseAppDialogViewAndConfirmForTest(false));
   content::RunAllPendingInMessageLoop();
-  app_ids = arc_app_list_pref()->GetAppIds();
-  EXPECT_EQ(app_ids.size(), 2u);
+  EXPECT_EQ(2u, arc_app_list_pref()->GetAppIds().size());
 
-  // The app list is not showing, so the dialog won't show.
-  ShowArcAppUninstallDialog(browser()->profile(), controller, app_id);
-  content::RunAllPendingInMessageLoop();
-  EXPECT_FALSE(IsArcAppDialogViewAliveForTest());
-
-  // Acceptting the dialog won't work since it was not shown.
-  EXPECT_FALSE(CloseAppDialogViewAndConfirmForTest(true));
-  content::RunAllPendingInMessageLoop();
-  app_ids = arc_app_list_pref()->GetAppIds();
-  EXPECT_EQ(app_ids.size(), 2u);
-  controller->DismissView();
-
-  // Show the app list, and then the dialog.
-  service->ShowForProfile(browser()->profile());
-  ShowArcAppUninstallDialog(browser()->profile(), controller, app_id);
+  ShowArcAppUninstallDialog(browser()->profile(), nullptr /*controller*/,
+                            app_id);
   content::RunAllPendingInMessageLoop();
   EXPECT_TRUE(IsArcAppDialogViewAliveForTest());
 
-  // Acceptting the dialog should work now.
+  // Accepting the dialog should work now.
   EXPECT_TRUE(CloseAppDialogViewAndConfirmForTest(true));
   content::RunAllPendingInMessageLoop();
-  app_ids = arc_app_list_pref()->GetAppIds();
-  EXPECT_EQ(app_ids.size(), 0u);
-  controller->DismissView();
+  EXPECT_EQ(0u, arc_app_list_pref()->GetAppIds().size());
 }
 
 // User confirms/cancels ARC app shortcut removal. Note that the app is not
 // uninstalled when the shortcut is removed.
 IN_PROC_BROWSER_TEST_F(ArcAppUninstallDialogViewBrowserTest,
                        UserConfirmsUninstallShortcut) {
-  std::vector<std::string> app_ids = arc_app_list_pref()->GetAppIds();
-  EXPECT_EQ(app_ids.size(), 2u);
+  EXPECT_EQ(2u, arc_app_list_pref()->GetAppIds().size());
   std::string package_name = "fake.package.0";
   std::string intent_uri = "Fake Shortcut uri 0";
   std::string app_id = arc_app_list_pref()->GetAppId(package_name, intent_uri);
 
-  AppListService* service = AppListService::Get();
-  ASSERT_TRUE(service);
-  AppListControllerDelegate* controller(service->GetControllerDelegate());
-  ASSERT_TRUE(controller);
-
-  // The dialog is only shown when AppList is visible, so we show AppList
-  // first.
-  service->ShowForProfile(browser()->profile());
-  ShowArcAppUninstallDialog(browser()->profile(), controller, app_id);
+  ShowArcAppUninstallDialog(browser()->profile(), nullptr /*controller*/,
+                            app_id);
   content::RunAllPendingInMessageLoop();
 
-  // When we show the dialog, AppList loses focus and gets dismissed.
-  EXPECT_FALSE(service->IsAppListVisible());
-
   // Cancelling the dialog won't uninstall any app.
   EXPECT_TRUE(CloseAppDialogViewAndConfirmForTest(false));
   content::RunAllPendingInMessageLoop();
-  app_ids = arc_app_list_pref()->GetAppIds();
-  EXPECT_EQ(app_ids.size(), 2u);
+  EXPECT_EQ(2u, arc_app_list_pref()->GetAppIds().size());
 
-  // The app list is not showing, so the dialog won't show.
-  ShowArcAppUninstallDialog(browser()->profile(), controller, app_id);
-  content::RunAllPendingInMessageLoop();
-  EXPECT_FALSE(IsArcAppDialogViewAliveForTest());
-
-  // Acceptting the dialog won't work since it was not shown.
-  EXPECT_FALSE(CloseAppDialogViewAndConfirmForTest(true));
-  content::RunAllPendingInMessageLoop();
-  app_ids = arc_app_list_pref()->GetAppIds();
-  EXPECT_EQ(app_ids.size(), 2u);
-
-  // Show the app list, and then the dialog.
-  service->ShowForProfile(browser()->profile());
-  ShowArcAppUninstallDialog(browser()->profile(), controller, app_id);
+  ShowArcAppUninstallDialog(browser()->profile(), nullptr /*controller*/,
+                            app_id);
   content::RunAllPendingInMessageLoop();
   EXPECT_TRUE(IsArcAppDialogViewAliveForTest());
 
-  // Acceptting the dialog should work now.
+  // Accepting the dialog should uninstall the shortcut only.
   EXPECT_TRUE(CloseAppDialogViewAndConfirmForTest(true));
   content::RunAllPendingInMessageLoop();
-  app_ids = arc_app_list_pref()->GetAppIds();
-  EXPECT_EQ(app_ids.size(), 1u);
-  controller->DismissView();
+  EXPECT_EQ(1u, arc_app_list_pref()->GetAppIds().size());
 }
 
 }  // namespace arc
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
index df37909..0a3308b 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
@@ -58,6 +58,11 @@
   }
 }
 
+// static
+int BrowserNonClientFrameView::GetAvatarIconPadding() {
+  return ui::MaterialDesignController::IsTouchOptimizedUiEnabled() ? 8 : 4;
+}
+
 void BrowserNonClientFrameView::OnBrowserViewInitViewsComplete() {
   UpdateMinimumSize();
 }
@@ -90,6 +95,12 @@
 
 void BrowserNonClientFrameView::UpdateMinimumSize() {}
 
+int BrowserNonClientFrameView::GetTabStripLeftInset() const {
+  return profile_indicator_icon()
+             ? 2 * GetAvatarIconPadding() + GetIncognitoAvatarIcon().width()
+             : 4;
+}
+
 void BrowserNonClientFrameView::ChildPreferredSizeChanged(views::View* child) {
   if (child == GetProfileSwitcherView()) {
     // Perform a re-layout if the avatar button has changed, since that can
@@ -200,9 +211,12 @@
   gfx::Image icon;
   if (is_incognito) {
     icon = gfx::Image(GetIncognitoAvatarIcon());
+    profile_indicator_icon_->set_stroke_color(SK_ColorTRANSPARENT);
   } else {
 #if defined(OS_CHROMEOS)
     AvatarMenu::GetImageForMenuButton(profile->GetPath(), &icon);
+    // Draw a stroke around the profile icon only for the avatar.
+    profile_indicator_icon_->set_stroke_color(GetToolbarTopSeparatorColor());
 #else
     NOTREACHED();
 #endif
@@ -219,12 +233,12 @@
 #endif
   gfx::ImageSkia incognito_icon = GetIncognitoAvatarIcon();
   int avatar_bottom = GetTopInset(false) + browser_view()->GetTabStripHeight() -
-                      kAvatarIconPadding;
+                      GetAvatarIconPadding();
   int avatar_y = avatar_bottom - incognito_icon.height();
   int avatar_height = incognito_icon.height();
+  gfx::Rect avatar_bounds(GetAvatarIconPadding(), avatar_y,
+                          incognito_icon.width(), avatar_height);
 
-  gfx::Rect avatar_bounds(kAvatarIconPadding, avatar_y, incognito_icon.width(),
-                          avatar_height);
   profile_indicator_icon()->SetBoundsRect(avatar_bounds);
   profile_indicator_icon()->SetVisible(true);
 }
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
index 63f0a60..a43a838 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
@@ -18,12 +18,12 @@
 class BrowserNonClientFrameView : public views::NonClientFrameView,
                                   public ProfileAttributesStorage::Observer {
  public:
-  // The padding on the left, right, and bottom of the avatar icon.
-  static constexpr int kAvatarIconPadding = 4;
-
   BrowserNonClientFrameView(BrowserFrame* frame, BrowserView* browser_view);
   ~BrowserNonClientFrameView() override;
 
+  // Returns the padding on the left, right, and bottom of the avatar icon.
+  static int GetAvatarIconPadding();
+
   BrowserView* browser_view() const { return browser_view_; }
   BrowserFrame* frame() const { return frame_; }
 
@@ -77,6 +77,12 @@
   // Provided for mus to update the minimum window size property.
   virtual void UpdateMinimumSize();
 
+  // Distance between the leading edge of the NonClientFrameView and the tab
+  // strip.
+  // TODO: Consider refactoring and unifying tabstrip bounds calculations.
+  // https://crbug.com/820485.
+  virtual int GetTabStripLeftInset() const;
+
   // Overriden from views::View.
   void ChildPreferredSizeChanged(views::View* child) override;
   void VisibilityChanged(views::View* starting_from, bool is_visible) override;
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
index f1972d1..8d270c0 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -352,7 +352,7 @@
   frame_header_->SetHeaderHeightForPainting(painted_height);
 
   if (profile_indicator_icon())
-    LayoutProfileIndicatorIcon();
+    LayoutIncognitoButton();
   BrowserNonClientFrameView::Layout();
   const bool immersive =
       browser_view()->immersive_mode_controller()->IsEnabled();
@@ -499,14 +499,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 // BrowserNonClientFrameViewAsh, private:
 
-int BrowserNonClientFrameViewAsh::GetTabStripLeftInset() const {
-  const int avatar_right =
-      profile_indicator_icon()
-          ? (kAvatarIconPadding + GetIncognitoAvatarIcon().width())
-          : 0;
-  return avatar_right + kAvatarIconPadding;
-}
-
 int BrowserNonClientFrameViewAsh::GetTabStripRightInset() const {
   return kTabstripRightSpacing +
       caption_button_container_->GetPreferredSize().width();
@@ -519,21 +511,6 @@
          browser->is_app();
 }
 
-void BrowserNonClientFrameViewAsh::LayoutProfileIndicatorIcon() {
-  DCHECK(profile_indicator_icon());
-
-  const gfx::ImageSkia incognito_icon = GetIncognitoAvatarIcon();
-  const int avatar_bottom = GetTopInset(false) +
-                            browser_view()->GetTabStripHeight() -
-                            kAvatarIconPadding;
-  int avatar_y = avatar_bottom - incognito_icon.height();
-
-  const int avatar_height = avatar_bottom - avatar_y;
-  profile_indicator_icon()->SetBounds(kAvatarIconPadding, avatar_y,
-                                      incognito_icon.width(), avatar_height);
-  profile_indicator_icon()->SetVisible(true);
-}
-
 bool BrowserNonClientFrameViewAsh::ShouldPaint() const {
   // We need to paint when the top-of-window views are revealed in immersive
   // fullscreen.
@@ -595,10 +572,11 @@
     // Add the container for extra hosted app buttons (e.g app menu button).
     SkColor button_color = ash::FrameCaptionButton::GetButtonColor(
         default_frame_header->ShouldUseLightImages());
+    const float inactive_alpha_ratio =
+        ash::FrameCaptionButton::GetInactiveButtonColorAlphaRatio();
     hosted_app_button_container_ = new HostedAppButtonContainer(
         browser_view(), button_color,
-        SkColorSetA(button_color,
-                    255 * ash::kInactiveFrameButtonIconAlphaRatio));
+        SkColorSetA(button_color, 255 * inactive_alpha_ratio));
     caption_button_container_->AddChildViewAt(hosted_app_button_container_, 0);
   } else if (!browser->is_app()) {
     // For non app (i.e. WebUI) windows (e.g. Settings) use MD frame color.
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
index de2fde8..4282a506 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
@@ -108,9 +108,6 @@
 
   friend class BrowserFrameHeaderAsh;
 
-  // Distance between the left edge of the NonClientFrameView and the tab strip.
-  int GetTabStripLeftInset() const;
-
   // Distance between the right edge of the NonClientFrameView and the tab
   // strip.
   int GetTabStripRightInset() const;
@@ -120,8 +117,6 @@
   // scheme than browser windows.
   bool UsePackagedAppHeaderStyle() const;
 
-  void LayoutProfileIndicatorIcon();
-
   // Returns true if there is anything to paint. Some fullscreen windows do not
   // need their frames painted.
   bool ShouldPaint() const;
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
index efb61635..efccea6 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -61,6 +61,7 @@
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 #include "ui/events/base_event_utils.h"
 #include "ui/events/event.h"
+#include "ui/gfx/color_palette.h"
 #include "ui/views/widget/widget.h"
 
 namespace {
@@ -558,7 +559,13 @@
       static_cast<ash::DefaultFrameHeader*>(frame_view->frame_header_.get());
   EXPECT_EQ(SK_ColorBLUE, frame_header->GetActiveFrameColor());
   EXPECT_EQ(SK_ColorBLUE, frame_header->GetInactiveFrameColor());
-  EXPECT_EQ(SK_ColorWHITE, button_container->active_icon_color_);
+  // TODO(afakhry): Figure out the right way to test this (i.e. are we testing
+  // that the caption colors are light since the frame color is dark? Or are we
+  // testing that the colors are contrasting?). Do this while working on themes
+  // in https://crbug.com/820495.
+  const SkColor expected_active_icon_color =
+      GetParam() ? gfx::kGoogleGrey100 : SK_ColorWHITE;
+  EXPECT_EQ(expected_active_icon_color, button_container->active_icon_color_);
 
   // Show a content setting icon.
   auto& content_setting_views =
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h
index 5d5994d..27576a8 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h
@@ -21,6 +21,7 @@
   int GetTopInset(bool restored) const override;
   int GetThemeBackgroundXInset() const override;
   void UpdateThrobber(bool running) override;
+  int GetTabStripLeftInset() const override;
 
   // views::NonClientFrameView:
   gfx::Rect GetBoundsForClientView() const override;
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm
index 3562bf8..795e00c 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm
@@ -42,7 +42,7 @@
   DCHECK(tabstrip);
   gfx::Rect bounds = gfx::Rect(0, kTabstripTopInset, width(),
                                tabstrip->GetPreferredSize().height());
-  bounds.Inset(kTabstripLeftInset, 0, GetTabStripRightInset(), 0);
+  bounds.Inset(GetTabStripLeftInset(), 0, GetTabStripRightInset(), 0);
   return bounds;
 }
 
@@ -56,7 +56,8 @@
   if (profile_switcher_view) {
     inset += profile_switcher_view->GetPreferredSize().width();
   } else if (profile_indicator_icon()) {
-    inset += profile_indicator_icon()->bounds().width() + kAvatarIconPadding;
+    inset +=
+        profile_indicator_icon()->bounds().width() + GetAvatarIconPadding();
   }
   return inset;
 }
@@ -68,6 +69,10 @@
 void BrowserNonClientFrameViewMac::UpdateThrobber(bool running) {
 }
 
+int BrowserNonClientFrameViewMac::GetTabStripLeftInset() const {
+  return kTabstripLeftInset;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // BrowserNonClientFrameViewMac, views::NonClientFrameView implementation:
 
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc
index f686243..6812476 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.cc
@@ -225,6 +225,11 @@
   }
 }
 
+int BrowserNonClientFrameViewMus::GetTabStripLeftInset() const {
+  return BrowserNonClientFrameView::GetTabStripLeftInset() +
+         frame_values().normal_insets.left();
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // views::NonClientFrameView:
 
@@ -380,15 +385,6 @@
   tab_strip_ = nullptr;
 }
 
-int BrowserNonClientFrameViewMus::GetTabStripLeftInset() const {
-  const int avatar_right =
-      profile_indicator_icon()
-          ? (kAvatarIconPadding + GetIncognitoAvatarIcon().width())
-          : 0;
-  return avatar_right + kAvatarIconPadding +
-         frame_values().normal_insets.left();
-}
-
 int BrowserNonClientFrameViewMus::GetTabStripRightInset() const {
   const int frame_right_insets = frame_values().normal_insets.right() +
                                  frame_values().max_title_bar_button_width;
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.h
index f45458f..c9534f0 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mus.h
@@ -38,6 +38,7 @@
   void UpdateThrobber(bool running) override;
   void UpdateClientArea() override;
   void UpdateMinimumSize() override;
+  int GetTabStripLeftInset() const override;
 
   // views::NonClientFrameView:
   gfx::Rect GetBoundsForClientView() const override;
@@ -70,9 +71,6 @@
   void TabStripMaxXChanged(TabStrip* tab_strip) override;
   void TabStripDeleted(TabStrip* tab_strip) override;
 
-  // Distance between the left edge of the NonClientFrameView and the tab strip.
-  int GetTabStripLeftInset() const;
-
   // Distance between the right edge of the NonClientFrameView and the tab
   // strip.
   int GetTabStripRightInset() const;
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 1cc7f25..6ed0f79 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -84,6 +84,7 @@
 #include "chrome/browser/ui/views/omnibox/omnibox_view_views.h"
 #include "chrome/browser/ui/views/profiles/profile_indicator_icon.h"
 #include "chrome/browser/ui/views/status_bubble_views.h"
+#include "chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.h"
 #include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h"
 #include "chrome/browser/ui/views/tabs/tab.h"
 #include "chrome/browser/ui/views/tabs/tab_strip.h"
@@ -747,6 +748,9 @@
   bool change_tab_contents =
       contents_web_view_->web_contents() != new_contents;
 
+  bool will_restore_focus = !browser_->tab_strip_model()->closing_all() &&
+                            GetWidget()->IsActive() && GetWidget()->IsVisible();
+
   // Update various elements that are interested in knowing the current
   // WebContents.
 
@@ -754,12 +758,13 @@
   // we don't want any WebContents to be attached, so that we
   // avoid an unnecessary resize and re-layout of a WebContents.
   if (change_tab_contents) {
-    if (GetWidget() &&
-        (contents_web_view_->HasFocus() || devtools_web_view_->HasFocus())) {
+    if (will_restore_focus) {
       // Manually clear focus before setting focus behavior so that the focus
       // is not temporarily advanced to an arbitrary place in the UI via
       // SetFocusBehavior(FocusBehavior::NEVER), confusing screen readers.
       // The saved focus for new_contents is restored after it is attached.
+      // In addition, this ensures that the next RestoreFocus() will be
+      // read out to screen readers, even if focus doesn't actually change.
       GetWidget()->GetFocusManager()->ClearFocus();
     }
     contents_web_view_->SetWebContents(nullptr);
@@ -785,6 +790,20 @@
   UpdateDevToolsForContents(new_contents, !change_tab_contents);
 
   if (change_tab_contents) {
+    // When the location bar or other UI focus will be restored, first focus the
+    // root view so that screen readers announce the current page title. The
+    // kFocusContext event will delay the subsequent focus event so that screen
+    // readers register them as distinct events.
+    if (will_restore_focus) {
+      ChromeWebContentsViewFocusHelper* focus_helper =
+          ChromeWebContentsViewFocusHelper::FromWebContents(new_contents);
+      if (focus_helper &&
+          focus_helper->GetStoredFocus() != contents_web_view_) {
+        GetWidget()->GetRootView()->NotifyAccessibilityEvent(
+            ax::mojom::Event::kFocusContext, true);
+      }
+    }
+
     web_contents_close_handler_->ActiveTabChanged();
     contents_web_view_->SetWebContents(new_contents);
     SadTabHelper* sad_tab_helper = SadTabHelper::FromWebContents(new_contents);
@@ -796,8 +815,7 @@
     UpdateDevToolsForContents(new_contents, true);
   }
 
-  if (!browser_->tab_strip_model()->closing_all() && GetWidget()->IsActive() &&
-      GetWidget()->IsVisible()) {
+  if (will_restore_focus) {
     // We only restore focus if our window is visible, to avoid invoking blur
     // handlers when we are eventually shown.
     new_contents->RestoreFocus();
diff --git a/chrome/browser/ui/views/frame/browser_view_browsertest.cc b/chrome/browser/ui/views/frame/browser_view_browsertest.cc
index 1253eb7..f5bf99c 100644
--- a/chrome/browser/ui/views/frame/browser_view_browsertest.cc
+++ b/chrome/browser/ui/views/frame/browser_view_browsertest.cc
@@ -16,6 +16,7 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "chrome/test/views/scoped_macviews_browser_mode.h"
 #include "components/bookmarks/common/bookmark_pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/invalidate_type.h"
@@ -57,6 +58,8 @@
   DevToolsWindow* devtools_;
 
  private:
+  test::ScopedMacViewsBrowserMode views_mode_{true};
+
   DISALLOW_COPY_AND_ASSIGN(BrowserViewTest);
 };
 
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
index 9711016..607c39f 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -139,7 +139,7 @@
 
 gfx::Rect GlassBrowserFrameView::GetBoundsForTabStrip(
     views::View* tabstrip) const {
-  const int x = incognito_bounds_.right() + kAvatarIconPadding;
+  const int x = GetTabStripLeftInset();
   int end_x = width() - ClientBorderThickness(false);
   if (!CaptionButtonsOnLeadingEdge()) {
     end_x = std::min(MinimizeButtonX(), end_x) -
@@ -218,6 +218,10 @@
   return min_size;
 }
 
+int GlassBrowserFrameView::GetTabStripLeftInset() const {
+  return incognito_bounds_.right() + GetAvatarIconPadding();
+}
+
 void GlassBrowserFrameView::OnBrowserViewInitViewsComplete() {
   if (browser_view()->tabstrip()) {
     DCHECK(!tab_strip_observer_.IsObserving(browser_view()->tabstrip()));
@@ -754,9 +758,9 @@
                                   : 0);
   }
   const int bottom = GetTopInset(false) + browser_view()->GetTabStripHeight() -
-                     kAvatarIconPadding;
+                     GetAvatarIconPadding();
   incognito_bounds_.SetRect(
-      x + (profile_indicator_icon() ? kAvatarIconPadding : 0),
+      x + (profile_indicator_icon() ? GetAvatarIconPadding() : 0),
       bottom - size.height(), profile_indicator_icon() ? size.width() : 0,
       size.height());
   if (profile_indicator_icon())
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.h b/chrome/browser/ui/views/frame/glass_browser_frame_view.h
index e90776f..a745037 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view.h
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.h
@@ -36,6 +36,7 @@
   int GetThemeBackgroundXInset() const override;
   void UpdateThrobber(bool running) override;
   gfx::Size GetMinimumSize() const override;
+  int GetTabStripLeftInset() const override;
   void OnBrowserViewInitViewsComplete() override;
 
   // views::NonClientFrameView:
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
index af731ef..9a058f51 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
@@ -173,6 +173,10 @@
   return layout_->GetMinimumSize(width());
 }
 
+int OpaqueBrowserFrameView::GetTabStripLeftInset() const {
+  return layout_->GetTabStripLeftInset();
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // OpaqueBrowserFrameView, views::NonClientFrameView implementation:
 
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
index 29ceddf7..e9a9f3c2 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.h
@@ -55,6 +55,7 @@
   int GetThemeBackgroundXInset() const override;
   void UpdateThrobber(bool running) override;
   gfx::Size GetMinimumSize() const override;
+  int GetTabStripLeftInset() const override;
 
   // views::NonClientFrameView:
   gfx::Rect GetBoundsForClientView() const override;
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
index 0879180d..1fcb8a5 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
@@ -104,7 +104,7 @@
 gfx::Rect OpaqueBrowserFrameViewLayout::GetBoundsForTabStrip(
     const gfx::Size& tabstrip_preferred_size,
     int available_width) const {
-  int x = leading_button_start_ + OpaqueBrowserFrameView::kAvatarIconPadding;
+  const int x = GetTabStripLeftInset();
   available_width -= x + NewTabCaptionSpacing() + trailing_button_start_;
   return gfx::Rect(x, GetTabStripInsetsTop(false), std::max(0, available_width),
                    tabstrip_preferred_size.height());
@@ -132,6 +132,10 @@
   return min_size;
 }
 
+int OpaqueBrowserFrameViewLayout::GetTabStripLeftInset() const {
+  return leading_button_start_ + OpaqueBrowserFrameView::GetAvatarIconPadding();
+}
+
 gfx::Rect OpaqueBrowserFrameViewLayout::GetWindowBoundsForClientBounds(
     const gfx::Rect& client_bounds) const {
   int top_height = NonClientTopHeight(false);
@@ -428,7 +432,7 @@
   trailing_button_start_ = std::max(trailing_button_start_, min_button_width);
 
   if (incognito_icon_) {
-    constexpr int pad = OpaqueBrowserFrameView::kAvatarIconPadding;
+    const int pad = OpaqueBrowserFrameView::GetAvatarIconPadding();
     const gfx::Size size(delegate_->GetIncognitoAvatarIcon().size());
     const int incognito_width = pad + size.width();
     int x;
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h
index accb03c..2636bf17 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h
@@ -55,6 +55,9 @@
 
   gfx::Size GetMinimumSize(int available_width) const;
 
+  // Distance between the left edge of the NonClientFrameView and the tab strip.
+  int GetTabStripLeftInset() const;
+
   // Returns the bounds of the window required to display the content area at
   // the specified bounds.
   gfx::Rect GetWindowBoundsForClientBounds(
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
index a043f4a..8fbeeb8 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
@@ -241,7 +241,7 @@
                      : -GetLayoutSize(NEW_TAB_BUTTON, delegate_->IsIncognito())
                             .width());
     }
-    int tabstrip_x = OpaqueBrowserFrameView::kAvatarIconPadding;
+    int tabstrip_x = OpaqueBrowserFrameView::GetAvatarIconPadding();
     if (show_caption_buttons && caption_buttons_on_left) {
       int right_of_close =
           maximized ? kMaximizedExtraCloseWidth : OBFVL::kFrameBorderThickness;
diff --git a/chrome/browser/ui/views/frame/test_with_browser_view.cc b/chrome/browser/ui/views/frame/test_with_browser_view.cc
index c1ab6f5a..f028f99 100644
--- a/chrome/browser/ui/views/frame/test_with_browser_view.cc
+++ b/chrome/browser/ui/views/frame/test_with_browser_view.cc
@@ -31,11 +31,6 @@
 #include "chrome/browser/chromeos/input_method/mock_input_method_manager_impl.h"
 #endif
 
-#if defined(OS_MACOSX)
-#include "chrome/common/chrome_features.h"
-#include "ui/base/ui_base_features.h"
-#endif
-
 namespace {
 
 std::unique_ptr<KeyedService> CreateTemplateURLService(
@@ -78,9 +73,6 @@
   chromeos::input_method::InitializeForTesting(
       new chromeos::input_method::MockInputMethodManagerImpl);
 #endif
-#if defined(OS_MACOSX)
-  feature_list_.InitAndEnableFeature(features::kViewsBrowserWindows);
-#endif
   BrowserWithTestWindowTest::SetUp();
   browser_view_ = static_cast<BrowserView*>(browser()->window());
 }
diff --git a/chrome/browser/ui/views/frame/test_with_browser_view.h b/chrome/browser/ui/views/frame/test_with_browser_view.h
index 3b6a50b8..e3e4fb8 100644
--- a/chrome/browser/ui/views/frame/test_with_browser_view.h
+++ b/chrome/browser/ui/views/frame/test_with_browser_view.h
@@ -8,9 +8,8 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "base/test/scoped_feature_list.h"
-#include "build/build_config.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
+#include "chrome/test/views/scoped_macviews_browser_mode.h"
 
 class BrowserView;
 
@@ -33,7 +32,7 @@
 
  private:
   BrowserView* browser_view_;  // Not owned.
-  base::test::ScopedFeatureList feature_list_;
+  test::ScopedMacViewsBrowserMode views_mode_{true};
 
   DISALLOW_COPY_AND_ASSIGN(TestWithBrowserView);
 };
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc b/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc
index dd89803..94299450 100644
--- a/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc
+++ b/chrome/browser/ui/views/profiles/profile_chooser_view_browsertest.cc
@@ -521,9 +521,15 @@
   ShowAndVerifyUi();
 }
 
+// Crashes on Win only.  http://crbug.com/820390
+#if defined(OS_WIN)
+#define MAYBE_InvokeUi_SupervisedUser DISABLED_InvokeUi_SupervisedUser
+#else
+#define MAYBE_InvokeUi_SupervisedUser InvokeUi_SupervisedUser
+#endif
 // Shows the |ProfileChooserView| when a supervised user is the active profile.
 IN_PROC_BROWSER_TEST_F(ProfileChooserViewExtensionsTest,
-                       InvokeUi_SupervisedUser) {
+                       MAYBE_InvokeUi_SupervisedUser) {
   ShowAndVerifyUi();
 }
 
diff --git a/chrome/browser/ui/views/profiles/profile_indicator_icon.cc b/chrome/browser/ui/views/profiles/profile_indicator_icon.cc
index 70c9b1d..e3c1182 100644
--- a/chrome/browser/ui/views/profiles/profile_indicator_icon.cc
+++ b/chrome/browser/ui/views/profiles/profile_indicator_icon.cc
@@ -7,7 +7,7 @@
 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
 #include "ui/gfx/canvas.h"
 
-ProfileIndicatorIcon::ProfileIndicatorIcon() : old_height_(0) {
+ProfileIndicatorIcon::ProfileIndicatorIcon() {
   // In RTL mode, the incognito icon should be looking the opposite direction.
   EnableCanvasFlippingForRTLUI(true);
 }
@@ -45,6 +45,22 @@
   canvas->DrawImageInt(modified_icon_, 0, 0, modified_icon_.width(),
                        modified_icon_.height(), dst_x, dst_y, dst_width,
                        dst_height, false);
+
+  if (stroke_color_ == SK_ColorTRANSPARENT)
+    return;
+
+  // Draw a 1px circular stroke (regardless of DSF) around the avatar icon.
+  const gfx::PointF center((dst_x + dst_width) / 2.0f,
+                           (dst_y + dst_height) / 2.0f);
+  cc::PaintFlags paint_flags;
+  paint_flags.setAntiAlias(true);
+  paint_flags.setStyle(cc::PaintFlags::kStroke_Style);
+  paint_flags.setColor(stroke_color_);
+  paint_flags.setStrokeWidth(1.0f / canvas->image_scale());
+  // Reduce the radius by 0.5f such that the circle overlaps with the edge of
+  // the image.
+  const float radius = (dst_width + dst_height) / 4.0f;
+  canvas->DrawCircle(center, radius - 0.5f, paint_flags);
 }
 
 void ProfileIndicatorIcon::SetIcon(const gfx::Image& icon) {
diff --git a/chrome/browser/ui/views/profiles/profile_indicator_icon.h b/chrome/browser/ui/views/profiles/profile_indicator_icon.h
index d38116f9..dbdbe75 100644
--- a/chrome/browser/ui/views/profiles/profile_indicator_icon.h
+++ b/chrome/browser/ui/views/profiles/profile_indicator_icon.h
@@ -27,17 +27,22 @@
   ProfileIndicatorIcon();
   ~ProfileIndicatorIcon() override;
 
-  // views::MenuButton:
+  // views::View:
   void OnPaint(gfx::Canvas* canvas) override;
 
   // Sets the image for the avatar button. Rectangular images, as opposed
   // to Chrome avatar icons, will be resized and modified for the title bar.
   void SetIcon(const gfx::Image& icon);
 
+  // Sets the color to use for drawing a circular stroke around the icon image.
+  // Use SK_ColorTRANSPARENT not to draw any stroke.
+  void set_stroke_color(SkColor color) { stroke_color_ = color; }
+
  private:
   gfx::Image base_icon_;
   gfx::ImageSkia modified_icon_;
-  int old_height_;
+  int old_height_ = 0;
+  SkColor stroke_color_ = SK_ColorTRANSPARENT;
   DISALLOW_COPY_AND_ASSIGN(ProfileIndicatorIcon);
 };
 
diff --git a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.cc b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.cc
index 3ee3094..9dc22d12 100644
--- a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.cc
+++ b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.cc
@@ -19,13 +19,11 @@
 #include "content/public/browser/web_contents.h"
 #include "ui/views/widget/widget.h"
 
-
 ChromeWebContentsViewDelegateViews::ChromeWebContentsViewDelegateViews(
     content::WebContents* web_contents)
-    : ContextMenuDelegate(web_contents),
-      focus_helper_(
-          std::make_unique<ChromeWebContentsViewFocusHelper>(web_contents)),
-      web_contents_(web_contents) {}
+    : ContextMenuDelegate(web_contents), web_contents_(web_contents) {
+  ChromeWebContentsViewFocusHelper::CreateForWebContents(web_contents);
+}
 
 ChromeWebContentsViewDelegateViews::~ChromeWebContentsViewDelegateViews() =
     default;
@@ -43,24 +41,32 @@
   return bookmark_handler_.get();
 }
 
+ChromeWebContentsViewFocusHelper*
+ChromeWebContentsViewDelegateViews::GetFocusHelper() const {
+  ChromeWebContentsViewFocusHelper* helper =
+      ChromeWebContentsViewFocusHelper::FromWebContents(web_contents_);
+  DCHECK(helper);
+  return helper;
+}
+
 bool ChromeWebContentsViewDelegateViews::Focus() {
-  return focus_helper_->Focus();
+  return GetFocusHelper()->Focus();
 }
 
 bool ChromeWebContentsViewDelegateViews::TakeFocus(bool reverse) {
-  return focus_helper_->TakeFocus(reverse);
+  return GetFocusHelper()->TakeFocus(reverse);
 }
 
 void ChromeWebContentsViewDelegateViews::StoreFocus() {
-  focus_helper_->StoreFocus();
+  GetFocusHelper()->StoreFocus();
 }
 
 bool ChromeWebContentsViewDelegateViews::RestoreFocus() {
-  return focus_helper_->RestoreFocus();
+  return GetFocusHelper()->RestoreFocus();
 }
 
 void ChromeWebContentsViewDelegateViews::ResetStoredFocus() {
-  focus_helper_->ResetStoredFocus();
+  GetFocusHelper()->ResetStoredFocus();
 }
 
 std::unique_ptr<RenderViewContextMenuBase>
diff --git a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.h b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.h
index 684850c..196b84b 100644
--- a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.h
+++ b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views.h
@@ -12,8 +12,8 @@
 #include "components/renderer_context_menu/context_menu_delegate.h"
 #include "content/public/browser/web_contents_view_delegate.h"
 
-class ChromeWebContentsViewFocusHelper;
 class RenderViewContextMenuBase;
+class ChromeWebContentsViewFocusHelper;
 
 namespace content {
 class WebContents;
@@ -49,9 +49,6 @@
   void ShowMenu(std::unique_ptr<RenderViewContextMenuBase> menu) override;
 
  private:
-  // Used to handle focus management.
-  std::unique_ptr<ChromeWebContentsViewFocusHelper> focus_helper_;
-
   // The context menu is reset every time we show it, but we keep a pointer to
   // between uses so that it won't go out of scope before we're done with it.
   std::unique_ptr<RenderViewContextMenuBase> context_menu_;
@@ -61,6 +58,8 @@
 
   content::WebContents* web_contents_;
 
+  ChromeWebContentsViewFocusHelper* GetFocusHelper() const;
+
   DISALLOW_COPY_AND_ASSIGN(ChromeWebContentsViewDelegateViews);
 };
 
diff --git a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_mac.h b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_mac.h
index c6d75a22..2a91757 100644
--- a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_mac.h
+++ b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_mac.h
@@ -25,8 +25,9 @@
   bool TakeFocus(bool reverse) override;
 
  private:
-  // Used to handle focus management.
-  std::unique_ptr<ChromeWebContentsViewFocusHelper> focus_helper_;
+  content::WebContents* web_contents_;
+
+  ChromeWebContentsViewFocusHelper* GetFocusHelper() const;
 
   DISALLOW_COPY_AND_ASSIGN(ChromeWebContentsViewDelegateViewsMac);
 };
diff --git a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_mac.mm b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_mac.mm
index b8b3e22..07d8134 100644
--- a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_mac.mm
+++ b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_mac.mm
@@ -14,31 +14,40 @@
 ChromeWebContentsViewDelegateViewsMac::ChromeWebContentsViewDelegateViewsMac(
     content::WebContents* web_contents)
     : ChromeWebContentsViewDelegateMac(web_contents),
-      focus_helper_(
-          std::make_unique<ChromeWebContentsViewFocusHelper>(web_contents)) {}
+      web_contents_(web_contents) {
+  ChromeWebContentsViewFocusHelper::CreateForWebContents(web_contents);
+}
 
 ChromeWebContentsViewDelegateViewsMac::
     ~ChromeWebContentsViewDelegateViewsMac() {
 }
 
+ChromeWebContentsViewFocusHelper*
+ChromeWebContentsViewDelegateViewsMac::GetFocusHelper() const {
+  ChromeWebContentsViewFocusHelper* helper =
+      ChromeWebContentsViewFocusHelper::FromWebContents(web_contents_);
+  DCHECK(helper);
+  return helper;
+}
+
 void ChromeWebContentsViewDelegateViewsMac::StoreFocus() {
-  focus_helper_->StoreFocus();
+  GetFocusHelper()->StoreFocus();
 }
 
 bool ChromeWebContentsViewDelegateViewsMac::RestoreFocus() {
-  return focus_helper_->RestoreFocus();
+  return GetFocusHelper()->RestoreFocus();
 }
 
 void ChromeWebContentsViewDelegateViewsMac::ResetStoredFocus() {
-  focus_helper_->ResetStoredFocus();
+  GetFocusHelper()->ResetStoredFocus();
 }
 
 bool ChromeWebContentsViewDelegateViewsMac::Focus() {
-  return focus_helper_->Focus();
+  return GetFocusHelper()->Focus();
 }
 
 bool ChromeWebContentsViewDelegateViewsMac::TakeFocus(bool reverse) {
-  return focus_helper_->TakeFocus(reverse);
+  return GetFocusHelper()->TakeFocus(reverse);
 }
 
 #if BUILDFLAG(MAC_VIEWS_BROWSER)
diff --git a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.cc b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.cc
index ece83aa..9b4689d 100644
--- a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.cc
+++ b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.cc
@@ -12,12 +12,22 @@
 #include "ui/views/focus/focus_manager.h"
 #include "ui/views/widget/widget.h"
 
+DEFINE_WEB_CONTENTS_USER_DATA_KEY(ChromeWebContentsViewFocusHelper);
+
+// static
+void ChromeWebContentsViewFocusHelper::CreateForWebContents(
+    content::WebContents* web_contents) {
+  if (!ChromeWebContentsViewFocusHelper::FromWebContents(web_contents)) {
+    web_contents->SetUserData(
+        ChromeWebContentsViewFocusHelper::UserDataKey(),
+        base::WrapUnique(new ChromeWebContentsViewFocusHelper(web_contents)));
+  }
+}
+
 ChromeWebContentsViewFocusHelper::ChromeWebContentsViewFocusHelper(
     content::WebContents* web_contents)
     : web_contents_(web_contents) {}
 
-ChromeWebContentsViewFocusHelper::~ChromeWebContentsViewFocusHelper() {}
-
 bool ChromeWebContentsViewFocusHelper::Focus() {
   SadTabHelper* sad_tab_helper = SadTabHelper::FromWebContents(web_contents_);
   if (sad_tab_helper) {
@@ -52,12 +62,10 @@
 }
 
 bool ChromeWebContentsViewFocusHelper::RestoreFocus() {
-  views::View* last_focused_view = last_focused_view_tracker_.view();
+  views::View* view_to_focus = GetStoredFocus();
   last_focused_view_tracker_.Clear();
-  if (last_focused_view &&
-      last_focused_view->IsFocusable() &&
-      GetFocusManager()->ContainsView(last_focused_view)) {
-    last_focused_view->RequestFocus();
+  if (view_to_focus) {
+    view_to_focus->RequestFocus();
     return true;
   }
   return false;
@@ -67,6 +75,15 @@
   last_focused_view_tracker_.Clear();
 }
 
+views::View* ChromeWebContentsViewFocusHelper::GetStoredFocus() {
+  views::View* last_focused_view = last_focused_view_tracker_.view();
+  if (last_focused_view && last_focused_view->IsFocusable() &&
+      GetFocusManager()->ContainsView(last_focused_view)) {
+    return last_focused_view;
+  }
+  return nullptr;
+}
+
 gfx::NativeView ChromeWebContentsViewFocusHelper::GetActiveNativeView() {
   return web_contents_->GetFullscreenRenderWidgetHostView() ?
       web_contents_->GetFullscreenRenderWidgetHostView()->GetNativeView() :
diff --git a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.h b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.h
index 1d05c7e3..684494b5 100644
--- a/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.h
+++ b/chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_TAB_CONTENTS_CHROME_WEB_CONTENTS_VIEW_FOCUS_HELPER_H_
 #define CHROME_BROWSER_UI_VIEWS_TAB_CONTENTS_CHROME_WEB_CONTENTS_VIEW_FOCUS_HELPER_H_
 
+#include "base/supports_user_data.h"
+#include "content/public/browser/web_contents_user_data.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/views/view_tracker.h"
 
@@ -15,21 +17,29 @@
 namespace views {
 class FocusManager;
 class Widget;
+class View;
 }
 
 // A chrome specific helper class that handles focus management.
-class ChromeWebContentsViewFocusHelper {
+class ChromeWebContentsViewFocusHelper
+    : public content::WebContentsUserData<ChromeWebContentsViewFocusHelper> {
  public:
-  explicit ChromeWebContentsViewFocusHelper(content::WebContents* web_contents);
-  ~ChromeWebContentsViewFocusHelper();
+  // Creates a ChromeWebContentsViewFocusHelper for the given
+  // WebContents. If a ChromeWebContentsViewFocusHelper is already
+  // associated with the WebContents, this method is a no-op.
+  static void CreateForWebContents(content::WebContents* web_contents);
 
   void StoreFocus();
   bool RestoreFocus();
   void ResetStoredFocus();
   bool Focus();
   bool TakeFocus(bool reverse);
+  // Returns the View that will be focused if RestoreFocus() is called.
+  views::View* GetStoredFocus();
 
  private:
+  explicit ChromeWebContentsViewFocusHelper(content::WebContents* web_contents);
+  friend class content::WebContentsUserData<ChromeWebContentsViewFocusHelper>;
   gfx::NativeView GetActiveNativeView();
   views::Widget* GetTopLevelWidget();
   views::FocusManager* GetFocusManager();
diff --git a/chrome/browser/ui/views/toolbar/browser_action_test_util_views.cc b/chrome/browser/ui/views/toolbar/browser_action_test_util_views.cc
index 9a308fc..e3edd35 100644
--- a/chrome/browser/ui/views/toolbar/browser_action_test_util_views.cc
+++ b/chrome/browser/ui/views/toolbar/browser_action_test_util_views.cc
@@ -9,12 +9,14 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/extensions/extension_action_view_controller.h"
 #include "chrome/browser/ui/views/extensions/extension_popup.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/toolbar/app_menu_button.h"
+#include "chrome/browser/ui/views/toolbar/browser_action_test_util_views.h"
 #include "chrome/browser/ui/views/toolbar/browser_actions_container.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_action_view.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
@@ -81,64 +83,62 @@
 
 }  // namespace
 
-BrowserActionTestUtil::BrowserActionTestUtil(Browser* browser)
-    : BrowserActionTestUtil(browser, true) {
-}
+BrowserActionTestUtilViews::BrowserActionTestUtilViews(Browser* browser)
+    : BrowserActionTestUtilViews(browser, true) {}
 
-BrowserActionTestUtil::BrowserActionTestUtil(Browser* browser,
-                                             bool is_real_window)
+BrowserActionTestUtilViews::BrowserActionTestUtilViews(Browser* browser,
+                                                       bool is_real_window)
     : browser_(browser) {
   if (!is_real_window)
     test_helper_.reset(new TestToolbarActionsBarHelperViews(browser, nullptr));
 }
 
-BrowserActionTestUtil::~BrowserActionTestUtil() {
-}
+BrowserActionTestUtilViews::~BrowserActionTestUtilViews() {}
 
-int BrowserActionTestUtil::NumberOfBrowserActions() {
+int BrowserActionTestUtilViews::NumberOfBrowserActions() {
   return GetContainer(browser_, test_helper_.get())->num_toolbar_actions();
 }
 
-int BrowserActionTestUtil::VisibleBrowserActions() {
+int BrowserActionTestUtilViews::VisibleBrowserActions() {
   return GetContainer(browser_, test_helper_.get())->VisibleBrowserActions();
 }
 
-void BrowserActionTestUtil::InspectPopup(int index) {
+void BrowserActionTestUtilViews::InspectPopup(int index) {
   ToolbarActionView* view =
       GetContainer(browser_, test_helper_.get())->GetToolbarActionViewAt(index);
   static_cast<ExtensionActionViewController*>(view->view_controller())->
       InspectPopup();
 }
 
-bool BrowserActionTestUtil::HasIcon(int index) {
+bool BrowserActionTestUtilViews::HasIcon(int index) {
   return !GetContainer(browser_, test_helper_.get())
               ->GetToolbarActionViewAt(index)
               ->GetImage(views::Button::STATE_NORMAL)
               .isNull();
 }
 
-gfx::Image BrowserActionTestUtil::GetIcon(int index) {
+gfx::Image BrowserActionTestUtilViews::GetIcon(int index) {
   gfx::ImageSkia icon = GetContainer(browser_, test_helper_.get())
                             ->GetToolbarActionViewAt(index)
                             ->GetIconForTest();
   return gfx::Image(icon);
 }
 
-void BrowserActionTestUtil::Press(int index) {
+void BrowserActionTestUtilViews::Press(int index) {
   GetContainer(browser_, test_helper_.get())
       ->GetToolbarActionViewAt(index)
       ->view_controller()
       ->ExecuteAction(true);
 }
 
-std::string BrowserActionTestUtil::GetExtensionId(int index) {
+std::string BrowserActionTestUtilViews::GetExtensionId(int index) {
   return GetContainer(browser_, test_helper_.get())
       ->GetToolbarActionViewAt(index)
       ->view_controller()
       ->GetId();
 }
 
-std::string BrowserActionTestUtil::GetTooltip(int index) {
+std::string BrowserActionTestUtilViews::GetTooltip(int index) {
   base::string16 text;
   GetContainer(browser_, test_helper_.get())
       ->GetToolbarActionViewAt(index)
@@ -146,64 +146,71 @@
   return base::UTF16ToUTF8(text);
 }
 
-gfx::NativeView BrowserActionTestUtil::GetPopupNativeView() {
+gfx::NativeView BrowserActionTestUtilViews::GetPopupNativeView() {
   ToolbarActionViewController* popup_owner =
       GetToolbarActionsBar()->popup_owner();
   return popup_owner ? popup_owner->GetPopupNativeView() : nullptr;
 }
 
-bool BrowserActionTestUtil::HasPopup() {
+bool BrowserActionTestUtilViews::HasPopup() {
   return GetPopupNativeView() != nullptr;
 }
 
-gfx::Size BrowserActionTestUtil::GetPopupSize() {
+gfx::Size BrowserActionTestUtilViews::GetPopupSize() {
   gfx::NativeView popup = GetPopupNativeView();
   views::Widget* widget = views::Widget::GetWidgetForNativeView(popup);
   return widget->GetWindowBoundsInScreen().size();
 }
 
-bool BrowserActionTestUtil::HidePopup() {
+bool BrowserActionTestUtilViews::HidePopup() {
   GetToolbarActionsBar()->HideActivePopup();
   return !HasPopup();
 }
 
-bool BrowserActionTestUtil::ActionButtonWantsToRun(size_t index) {
+bool BrowserActionTestUtilViews::ActionButtonWantsToRun(size_t index) {
   return GetContainer(browser_, test_helper_.get())
       ->GetToolbarActionViewAt(index)
       ->wants_to_run_for_testing();
 }
 
-void BrowserActionTestUtil::SetWidth(int width) {
+void BrowserActionTestUtilViews::SetWidth(int width) {
   BrowserActionsContainer* container =
       GetContainer(browser_, test_helper_.get());
   container->SetSize(gfx::Size(width, container->height()));
 }
 
-ToolbarActionsBar* BrowserActionTestUtil::GetToolbarActionsBar() {
+ToolbarActionsBar* BrowserActionTestUtilViews::GetToolbarActionsBar() {
   return GetContainer(browser_, test_helper_.get())->toolbar_actions_bar();
 }
 
 std::unique_ptr<BrowserActionTestUtil>
-BrowserActionTestUtil::CreateOverflowBar() {
+BrowserActionTestUtilViews::CreateOverflowBar() {
   CHECK(!GetToolbarActionsBar()->in_overflow_mode())
       << "Only a main bar can create an overflow bar!";
-  return base::WrapUnique(new BrowserActionTestUtil(browser_, this));
+  return base::WrapUnique(new BrowserActionTestUtilViews(browser_, this));
 }
 
-// static
-gfx::Size BrowserActionTestUtil::GetMinPopupSize() {
+gfx::Size BrowserActionTestUtilViews::GetMinPopupSize() {
   return gfx::Size(ExtensionPopup::kMinWidth, ExtensionPopup::kMinHeight);
 }
 
-// static
-gfx::Size BrowserActionTestUtil::GetMaxPopupSize() {
+gfx::Size BrowserActionTestUtilViews::GetMaxPopupSize() {
   return gfx::Size(ExtensionPopup::kMaxWidth, ExtensionPopup::kMaxHeight);
 }
 
-BrowserActionTestUtil::BrowserActionTestUtil(Browser* browser,
-                                             BrowserActionTestUtil* main_bar)
+BrowserActionTestUtilViews::BrowserActionTestUtilViews(
+    Browser* browser,
+    BrowserActionTestUtilViews* main_bar)
     : browser_(browser),
       test_helper_(new TestToolbarActionsBarHelperViews(
           browser_,
-          GetContainer(browser_, main_bar->test_helper_.get()))) {
+          GetContainer(browser_, main_bar->test_helper_.get()))) {}
+
+#if !defined(OS_MACOSX)
+// static
+std::unique_ptr<BrowserActionTestUtil> BrowserActionTestUtil::Create(
+    Browser* browser,
+    bool is_real_window) {
+  return std::make_unique<BrowserActionTestUtilViews>(browser, is_real_window);
 }
+#endif
diff --git a/chrome/browser/ui/views/toolbar/browser_action_test_util_views.h b/chrome/browser/ui/views/toolbar/browser_action_test_util_views.h
new file mode 100644
index 0000000..0a67b46
--- /dev/null
+++ b/chrome/browser/ui/views/toolbar/browser_action_test_util_views.h
@@ -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.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_TOOLBAR_BROWSER_ACTION_TEST_UTIL_VIEWS_H_
+#define CHROME_BROWSER_UI_VIEWS_TOOLBAR_BROWSER_ACTION_TEST_UTIL_VIEWS_H_
+
+#include "chrome/browser/ui/extensions/browser_action_test_util.h"
+
+class BrowserActionTestUtilViews : public BrowserActionTestUtil {
+ public:
+  explicit BrowserActionTestUtilViews(Browser* browser);
+  BrowserActionTestUtilViews(Browser* browser, bool is_real_window);
+  ~BrowserActionTestUtilViews() override;
+
+  // BrowserActionTestUtil:
+  int NumberOfBrowserActions() override;
+  int VisibleBrowserActions() override;
+  void InspectPopup(int index) override;
+  bool HasIcon(int index) override;
+  gfx::Image GetIcon(int index) override;
+  void Press(int index) override;
+  std::string GetExtensionId(int index) override;
+  std::string GetTooltip(int index) override;
+  gfx::NativeView GetPopupNativeView() override;
+  bool HasPopup() override;
+  gfx::Size GetPopupSize() override;
+  bool HidePopup() override;
+  bool ActionButtonWantsToRun(size_t index) override;
+  void SetWidth(int width) override;
+  ToolbarActionsBar* GetToolbarActionsBar() override;
+  std::unique_ptr<BrowserActionTestUtil> CreateOverflowBar() override;
+  gfx::Size GetMinPopupSize() override;
+  gfx::Size GetMaxPopupSize() override;
+
+ private:
+  friend class BrowserActionTestUtil;
+
+  Browser* const browser_;  // weak
+
+  // Our test helper, which constructs and owns the views if we don't have a
+  // real browser window, or if this is an overflow version.
+  std::unique_ptr<TestToolbarActionsBarHelper> test_helper_;
+
+  BrowserActionTestUtilViews(Browser* browser,
+                             BrowserActionTestUtilViews* main_bar);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_TOOLBAR_BROWSER_ACTION_TEST_UTIL_VIEWS_H_
diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
index 302df0f..aa1c9cb 100644
--- a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
+++ b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
@@ -72,7 +72,7 @@
 #include "net/log/net_log_capture_mode.h"
 #include "net/log/net_log_entry.h"
 #include "net/log/net_log_util.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
 
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
index d3cd93d8..9bce25e 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -891,7 +891,7 @@
   // Getting the number formatting based on the locale and writing to
   // dictionary.
   base::string16 number_format = base::FormatDouble(123456.78, 2);
-  settings->SetString(kDecimalDelimeter, number_format.substr(6, 1));
+  settings->SetString(kDecimalDelimeter, number_format.substr(7, 1));
   settings->SetString(kThousandsDelimeter, number_format.substr(3, 1));
   settings->SetInteger(kUnitType, system);
 }
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc
index 382461c3..bc72b510 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/base64.h"
 #include "base/containers/flat_set.h"
+#include "base/i18n/rtl.h"
 #include "base/json/json_writer.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/strings/string16.h"
@@ -339,6 +340,10 @@
   }
 
   void Initialize() {
+    // Set locale since the delimeters we check in VerifyInitialSettings()
+    // depend on it.
+    base::i18n::SetICUDefaultLocale("en");
+
     // Sending this message will enable javascript, so it must always be called
     // before any other messages are sent.
     base::Value args(base::Value::Type::LIST);
@@ -376,7 +381,8 @@
   // print_preview.NativeInitialSettings type in
   // chrome/browser/resources/print_preview/native_layer.js. Checks that
   // |default_printer_name| is the printer name returned and that
-  // |initiator_title| is the initiator title returned. Assumes
+  // |initiator_title| is the initiator title returned and validates that
+  // delimeters are correct for "en" locale (set in Initialize()). Assumes
   // "test-callback-id-0" was used as the callback id.
   void ValidateInitialSettings(const content::TestWebUI::CallData& data,
                                const std::string& default_printer_name,
@@ -387,10 +393,16 @@
                                         base::Value::Type::BOOLEAN));
     ASSERT_TRUE(settings->FindKeyOfType("isInAppKioskMode",
                                         base::Value::Type::BOOLEAN));
-    ASSERT_TRUE(settings->FindKeyOfType("thousandsDelimeter",
-                                        base::Value::Type::STRING));
-    ASSERT_TRUE(
-        settings->FindKeyOfType("decimalDelimeter", base::Value::Type::STRING));
+
+    const base::Value* thousandsDelimeter = settings->FindKeyOfType(
+        "thousandsDelimeter", base::Value::Type::STRING);
+    ASSERT_TRUE(thousandsDelimeter);
+    EXPECT_EQ(",", thousandsDelimeter->GetString());
+    const base::Value* decimalDelimeter =
+        settings->FindKeyOfType("decimalDelimeter", base::Value::Type::STRING);
+    ASSERT_TRUE(decimalDelimeter);
+    EXPECT_EQ(".", decimalDelimeter->GetString());
+
     ASSERT_TRUE(
         settings->FindKeyOfType("unitType", base::Value::Type::INTEGER));
     ASSERT_TRUE(settings->FindKeyOfType("previewModifiable",
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index af0b83c..7e44b11 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -921,6 +921,10 @@
 // This flag is only relevant for Windows currently.
 const char kNoNetworkProfileWarning[]       = "no-network-profile-warning";
 
+// Used in combination with kNotificationLaunchId to specify the inline reply
+// entered in the toast in the Windows Action Center.
+const char kNotificationInlineReply[] = "notification-inline-reply";
+
 // Used for launching Chrome when a toast displayed in the Windows Action Center
 // has been activated. Should contain the launch ID encoded by Chrome.
 const char kNotificationLaunchId[] = "notification-launch-id";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index a6f30008..ef7d80bf 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -286,6 +286,7 @@
 extern const char kEnableProfileShortcutManager[];
 extern const char kHideIcons[];
 extern const char kNoNetworkProfileWarning[];
+extern const char kNotificationInlineReply[];
 extern const char kNotificationLaunchId[];
 extern const char kPrefetchArgumentBrowserBackground[];
 extern const char kPrefetchArgumentWatcher[];
diff --git a/chrome/common/extensions/api/automation.idl b/chrome/common/extensions/api/automation.idl
index 97fd6e9c..93531c0 100644
--- a/chrome/common/extensions/api/automation.idl
+++ b/chrome/common/extensions/api/automation.idl
@@ -24,6 +24,7 @@
     documentSelectionChanged,
     expandedChanged,
     focus,
+    focusContext,
     imageFrameUpdated,
     hide,
     hitTestResult,
diff --git a/chrome/installer/zucchini/equivalence_map.cc b/chrome/installer/zucchini/equivalence_map.cc
index 2a044e2..92d9989 100644
--- a/chrome/installer/zucchini/equivalence_map.cc
+++ b/chrome/installer/zucchini/equivalence_map.cc
@@ -294,9 +294,8 @@
       // Shrink all equivalences that overlap with |current|. These are all
       // worse than |current| since no reaper is found.
       for (auto reduced = current + 1; reduced != next; ++reduced) {
-        offset_t delta =
-            std::min(reduced->length, current->src_end() - reduced->src_offset);
-        reduced->length -= delta;
+        offset_t delta = current->src_end() - reduced->src_offset;
+        reduced->length -= std::min(reduced->length, delta);
         reduced->src_offset += delta;
         reduced->dst_offset += delta;
         DCHECK_EQ(reduced->src_offset, current->src_end());
@@ -458,9 +457,8 @@
     } else {
       // Shrinks all overlapping candidates following and worse than |current|.
       for (auto reduced = current + 1; reduced != next; ++reduced) {
-        offset_t delta = std::min(
-            reduced->eq.length, current->eq.dst_end() - reduced->eq.dst_offset);
-        reduced->eq.length -= delta;
+        offset_t delta = current->eq.dst_end() - reduced->eq.dst_offset;
+        reduced->eq.length -= std::min(reduced->eq.length, delta);
         reduced->eq.src_offset += delta;
         reduced->eq.dst_offset += delta;
         reduced->similarity = GetEquivalenceSimilarity(
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 3874615c..301d6a6 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -1372,6 +1372,12 @@
   return module_name == "Native Client";
 }
 
+bool ChromeContentRendererClient::IsOriginIsolatedPepperPlugin(
+    const base::FilePath& plugin_path) {
+  return plugin_path ==
+         base::FilePath::FromUTF8Unsafe(ChromeContentClient::kPDFPluginPath);
+}
+
 #if BUILDFLAG(ENABLE_PLUGINS) && BUILDFLAG(ENABLE_EXTENSIONS)
 bool ChromeContentRendererClient::IsExtensionOrSharedModuleWhitelisted(
     const GURL& url,
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h
index d3bdf1b..1b30fe68 100644
--- a/chrome/renderer/chrome_content_renderer_client.h
+++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -169,6 +169,7 @@
       const content::RenderFrame* render_frame,
       blink::mojom::PageVisibilityState* override_state) override;
   bool IsExternalPepperPlugin(const std::string& module_name) override;
+  bool IsOriginIsolatedPepperPlugin(const base::FilePath& plugin_path) override;
   std::unique_ptr<blink::WebSocketHandshakeThrottle>
   CreateWebSocketHandshakeThrottle() override;
   std::unique_ptr<blink::WebSpeechSynthesizer> OverrideSpeechSynthesizer(
diff --git a/chrome/renderer/extensions/automation_ax_tree_wrapper.cc b/chrome/renderer/extensions/automation_ax_tree_wrapper.cc
index 9fc7eba..2137e4ad 100644
--- a/chrome/renderer/extensions/automation_ax_tree_wrapper.cc
+++ b/chrome/renderer/extensions/automation_ax_tree_wrapper.cc
@@ -36,6 +36,7 @@
     case ax::mojom::Event::kExpandedChanged:
       return api::automation::EVENT_TYPE_EXPANDEDCHANGED;
     case ax::mojom::Event::kFocus:
+    case ax::mojom::Event::kFocusContext:
       return api::automation::EVENT_TYPE_FOCUS;
     case ax::mojom::Event::kHide:
       return api::automation::EVENT_TYPE_HIDE;
@@ -317,6 +318,7 @@
     case api::automation::EVENT_TYPE_NONE:
     case api::automation::EVENT_TYPE_AUTOCORRECTIONOCCURED:
     case api::automation::EVENT_TYPE_CLICKED:
+    case api::automation::EVENT_TYPE_FOCUSCONTEXT:
     case api::automation::EVENT_TYPE_HITTESTRESULT:
     case api::automation::EVENT_TYPE_HOVER:
     case api::automation::EVENT_TYPE_MEDIASTARTEDPLAYING:
diff --git a/chrome/service/net/service_url_request_context_getter.cc b/chrome/service/net/service_url_request_context_getter.cc
index c11444a..5b3ecd7f 100644
--- a/chrome/service/net/service_url_request_context_getter.cc
+++ b/chrome/service/net/service_url_request_context_getter.cc
@@ -15,7 +15,7 @@
 #include "chrome/service/service_process.h"
 #include "components/version_info/version_info.h"
 #include "net/proxy_resolution/proxy_config_service.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/url_request/url_request_context_builder.h"
 
 #if defined(OS_POSIX) && !defined(OS_MACOSX)
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index bf656793..143d085 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -251,6 +251,8 @@
     sources += [
       "views/chrome_views_test_base.cc",
       "views/chrome_views_test_base.h",
+      "views/scoped_macviews_browser_mode.cc",
+      "views/scoped_macviews_browser_mode.h",
     ]
   }
 
@@ -583,7 +585,6 @@
       "../browser/media_galleries/fileapi/media_file_validator_browsertest.cc",
       "../browser/media_galleries/media_galleries_dialog_controller_mock.cc",
       "../browser/media_galleries/media_galleries_dialog_controller_mock.h",
-      "../browser/metrics/metrics_memory_details_browsertest.cc",
       "../browser/metrics/metrics_reporting_state_browsertest.cc",
       "../browser/metrics/metrics_service_browsertest.cc",
       "../browser/metrics/oom/out_of_memory_reporter_browsertest.cc",
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn
index 4bccc466..34ed4d6 100644
--- a/chrome/test/android/BUILD.gn
+++ b/chrome/test/android/BUILD.gn
@@ -54,6 +54,7 @@
     "javatests/src/org/chromium/chrome/test/util/ChromeSigninUtils.java",
     "javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java",
     "javatests/src/org/chromium/chrome/test/util/DisableInTabbedMode.java",
+    "javatests/src/org/chromium/chrome/test/util/ViewUtils.java",
     "javatests/src/org/chromium/chrome/test/util/FullscreenTestUtils.java",
     "javatests/src/org/chromium/chrome/test/util/InfoBarTestAnimationListener.java",
     "javatests/src/org/chromium/chrome/test/util/InfoBarUtil.java",
@@ -96,6 +97,7 @@
     "//third_party/android_tools:android_support_design_java",
     "//third_party/android_tools:android_support_v7_appcompat_java",
     "//third_party/android_tools:android_support_v7_recyclerview_java",
+    "//third_party/hamcrest:hamcrest_core_java",
     "//third_party/jsr-305:jsr_305_javalib",
     "//third_party/junit",
     "//third_party/ub-uiautomator:ub_uiautomator_java",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ViewUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ViewUtils.java
new file mode 100644
index 0000000..9e8cbd21
--- /dev/null
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ViewUtils.java
@@ -0,0 +1,116 @@
+// 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.test.util;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.support.annotation.IntDef;
+import android.view.View;
+import android.view.ViewGroup;
+
+import org.hamcrest.Matcher;
+
+import org.chromium.content.browser.test.util.Criteria;
+import org.chromium.content.browser.test.util.CriteriaHelper;
+
+import java.lang.annotation.Retention;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Collection of utilities helping to clarify expectations on views in tests.
+ */
+public class ViewUtils {
+    @Retention(SOURCE)
+    @IntDef(flag = true, value = {VIEW_VISIBLE, VIEW_INVISIBLE, VIEW_GONE, VIEW_NULL})
+    public @interface ExpectedViewState {}
+    public static final int VIEW_VISIBLE = 1;
+    public static final int VIEW_INVISIBLE = 1 << 1;
+    public static final int VIEW_GONE = 1 << 2;
+    public static final int VIEW_NULL = 1 << 3;
+
+    private static class ExpectedViewCriteria extends Criteria {
+        private final Matcher<View> mViewMatcher;
+        private final @ExpectedViewState int mViewState;
+        private final ViewGroup mRootView;
+
+        ExpectedViewCriteria(
+                Matcher<View> viewMatcher, @ExpectedViewState int viewState, ViewGroup rootView) {
+            mViewMatcher = viewMatcher;
+            mViewState = viewState;
+            mRootView = rootView;
+        }
+
+        @Override
+        public boolean isSatisfied() {
+            List<View> matchedViews = new ArrayList<>();
+            findMatchingChildren(mRootView, matchedViews);
+            if (matchedViews.size() > 1) {
+                updateFailureReason("Multiple views matched: " + mViewMatcher.toString());
+                return false;
+            }
+            return matchedViews.size() == 0 ? hasViewExpectedState(null)
+                                            : hasViewExpectedState(matchedViews.get(0));
+        }
+
+        private void findMatchingChildren(ViewGroup root, List<View> matchedViews) {
+            for (int i = 0; i < root.getChildCount(); i++) {
+                View view = root.getChildAt(i);
+                if (mViewMatcher.matches(view)) matchedViews.add(view);
+                if (view instanceof ViewGroup) {
+                    findMatchingChildren((ViewGroup) view, matchedViews);
+                }
+            };
+        }
+
+        private boolean hasViewExpectedState(View view) {
+            if (view == null) {
+                updateFailureReason("No matching view was found!");
+                return (mViewState & VIEW_NULL) != 0;
+            }
+            switch (view.getVisibility()) {
+                case View.VISIBLE:
+                    updateFailureReason("Found view is unexpectedly visible!");
+                    return (mViewState & VIEW_VISIBLE) != 0;
+                case View.INVISIBLE:
+                    updateFailureReason("Found view is unexpectedly invisible!");
+                    return (mViewState & VIEW_INVISIBLE) != 0;
+                case View.GONE:
+                    updateFailureReason("Found view is unexpectedly gone!");
+                    return (mViewState & VIEW_GONE) != 0;
+            }
+            assert false; // Not Reached.
+            return false;
+        }
+    }
+
+    private ViewUtils() {}
+
+    /**
+     * Waits until a view matching the given matches any of the given {@link ExpectedViewState}s.
+     * Fails if the matcher applies to multiple views. Times out if no view was found while waiting
+     * up to
+     * {@link CriteriaHelper#DEFAULT_MAX_TIME_TO_POLL} milliseconds.
+     * @param root The view group to search in.
+     * @param viewMatcher The matcher matching the view that should be waited for.
+     * @param viewState State that the matching view should be in. If multiple states are passed,
+     *                  the waiting will stop if at least one applies.
+     */
+    public static void waitForView(
+            ViewGroup root, Matcher<View> viewMatcher, @ExpectedViewState int viewState) {
+        CriteriaHelper.pollUiThread(new ExpectedViewCriteria(viewMatcher, viewState, root));
+    }
+
+    /**
+     * Waits until a visible view matching the given matcher appears. Fails if the matcher applies
+     * to multiple views.  Times out if no view was found while waiting up to
+     * {@link CriteriaHelper#DEFAULT_MAX_TIME_TO_POLL} milliseconds.
+     * @param root The view group to search in.
+     * @param viewMatcher The matcher matching the view that should be waited for.
+     */
+    public static void waitForView(ViewGroup root, Matcher<View> viewMatcher) {
+        waitForView(root, viewMatcher, VIEW_VISIBLE);
+    }
+}
diff --git a/chrome/test/views/scoped_macviews_browser_mode.cc b/chrome/test/views/scoped_macviews_browser_mode.cc
new file mode 100644
index 0000000..3a5808f
--- /dev/null
+++ b/chrome/test/views/scoped_macviews_browser_mode.cc
@@ -0,0 +1,24 @@
+// 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/test/views/scoped_macviews_browser_mode.h"
+
+#include "build/build_config.h"
+#include "build/buildflag.h"
+#include "ui/base/ui_base_features.h"
+
+namespace test {
+
+ScopedMacViewsBrowserMode::ScopedMacViewsBrowserMode(bool is_views) {
+#if defined(OS_MACOSX) && BUILDFLAG(MAC_VIEWS_BROWSER)
+  if (is_views)
+    feature_list_.InitAndEnableFeature(features::kViewsBrowserWindows);
+  else
+    feature_list_.InitAndDisableFeature(features::kViewsBrowserWindows);
+#endif
+}
+
+ScopedMacViewsBrowserMode::~ScopedMacViewsBrowserMode() {}
+
+}  // namespace test
diff --git a/chrome/test/views/scoped_macviews_browser_mode.h b/chrome/test/views/scoped_macviews_browser_mode.h
new file mode 100644
index 0000000..6f1ad76
--- /dev/null
+++ b/chrome/test/views/scoped_macviews_browser_mode.h
@@ -0,0 +1,37 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_TEST_VIEWS_SCOPED_MACVIEWS_BROWSER_MODE_H_
+#define CHROME_TEST_VIEWS_SCOPED_MACVIEWS_BROWSER_MODE_H_
+
+#include "base/macros.h"
+#include "base/test/scoped_feature_list.h"
+
+namespace test {
+
+// TODO(ellyjones): Delete this class once Mac Chrome always uses a Views
+// browser window.
+//
+// This is a transitional class, designed for forcing a test case to run with a
+// specific type of browser window on the Mac. This class is available on all
+// platforms so that every use of it doesn't have to be wrapped in preprocessor
+// conditionals, but is a no-op on non-Mac platforms.
+//
+// Tests that care about using a specific type of browser window, or that only
+// work with one type of browser window, can include a member variable of type
+// ScopedMacViewsBrowserMode to enforce that.
+class ScopedMacViewsBrowserMode {
+ public:
+  explicit ScopedMacViewsBrowserMode(bool is_views);
+  virtual ~ScopedMacViewsBrowserMode();
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedMacViewsBrowserMode);
+};
+
+}  // namespace test
+
+#endif  // CHROME_TEST_VIEWS_SCOPED_MACVIEWS_BROWSER_MODE_H_
diff --git a/chrome/utility/BUILD.gn b/chrome/utility/BUILD.gn
index 730bb82..2481d41 100644
--- a/chrome/utility/BUILD.gn
+++ b/chrome/utility/BUILD.gn
@@ -154,8 +154,8 @@
       "//ash/components/quick_launch/public/mojom",
       "//ash/components/touch_hud:lib",
       "//chrome/services/file_util:lib",
-      "//components/font_service:lib",
-      "//components/font_service/public/interfaces",
+      "//components/services/font:lib",
+      "//components/services/font/public/interfaces",
       "//services/ui:lib",
       "//services/ui/public/interfaces",
     ]
diff --git a/chrome/utility/DEPS b/chrome/utility/DEPS
index 78243c3a0..37bfc09 100644
--- a/chrome/utility/DEPS
+++ b/chrome/utility/DEPS
@@ -18,7 +18,7 @@
   "+chrome/services/wifi_util_win/wifi_util_win_service.h",
   "+chrome/services/wifi_util_win/public/mojom",
   "+components/crash/core/common/crash_keys.h",
-  "+components/font_service/font_service_app.h",
+  "+components/services/font/font_service_app.h",
   "+components/patch_service",
   "+components/payments/content/utility",
   "+components/printing/service/public/cpp",
@@ -51,8 +51,8 @@
     "+ash/components/touch_hud/touch_hud_application.h",
     "+ash/public/interfaces",
     "+ash/window_manager_service.h",
-    "+components/font_service/font_service_app.h",
-    "+components/font_service/public/interfaces",
+    "+components/services/font/font_service_app.h",
+    "+components/services/font/public/interfaces",
     "+services/ui/common/image_cursors_set.h",
     "+services/ui/public",
     "+services/ui/service.h",
diff --git a/chrome/utility/mash_service_factory.cc b/chrome/utility/mash_service_factory.cc
index 96a3cd7..a9b76ea 100644
--- a/chrome/utility/mash_service_factory.cc
+++ b/chrome/utility/mash_service_factory.cc
@@ -14,8 +14,8 @@
 #include "ash/window_manager_service.h"
 #include "base/bind.h"
 #include "build/build_config.h"
-#include "components/font_service/font_service_app.h"
-#include "components/font_service/public/interfaces/constants.mojom.h"
+#include "components/services/font/font_service_app.h"
+#include "components/services/font/public/interfaces/constants.mojom.h"
 #include "services/ui/common/image_cursors_set.h"
 #include "services/ui/public/interfaces/constants.mojom.h"
 #include "services/ui/service.h"
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsActivity.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsActivity.java
index eb7bd6e..2831fcd 100644
--- a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsActivity.java
+++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsActivity.java
@@ -7,6 +7,7 @@
 import android.app.Activity;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.media.AudioManager;
 import android.net.Uri;
 import android.os.Bundle;
 import android.view.KeyEvent;
@@ -40,6 +41,8 @@
 
     // Tracks whether this Activity is between onCreate() and onDestroy().
     private final Controller<Unit> mCreatedState = new Controller<>();
+    // Tracks whether this Activity is between onResume() and onPause().
+    private final Controller<Unit> mResumedState = new Controller<>();
     // Tracks the most recent Intent for the Activity.
     private final Controller<Intent> mGotIntentState = new Controller<>();
     // Set this to cause the Activity to finish.
@@ -111,9 +114,11 @@
         super.onCreate(savedInstanceState);
         mCreatedState.set(Unit.unit());
         mGotIntentState.set(getIntent());
+        CastAudioManager.getAudioManager(this).requestAudioFocusWhen(
+                mResumedState, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
     }
 
-    protected void handleIntent(Intent intent) {
+    private void handleIntent(Intent intent) {
         final Bundle bundle = intent.getExtras();
         if (bundle == null) {
             Log.i(TAG, "Intent without bundle received!");
@@ -159,7 +164,7 @@
     protected void onPause() {
         if (DEBUG) Log.d(TAG, "onPause");
         super.onPause();
-
+        mResumedState.reset();
         if (mSurfaceHelper != null) {
             mSurfaceHelper.onPause();
         }
@@ -169,6 +174,7 @@
     protected void onResume() {
         if (DEBUG) Log.d(TAG, "onResume");
         super.onResume();
+        mResumedState.set(Unit.unit());
         if (mSurfaceHelper != null) {
             mSurfaceHelper.onResume();
         }
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsSurfaceHelper.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsSurfaceHelper.java
index 7878791..c5dfa0b7 100644
--- a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsSurfaceHelper.java
+++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsSurfaceHelper.java
@@ -81,8 +81,6 @@
                 CastSwitches.CAST_APP_BACKGROUND_COLOR, Color.BLACK));
         mHandler = new Handler();
         mAudioManager = CastAudioManager.getAudioManager(getActivity());
-        mAudioManager.requestAudioFocusWhen(
-                mResumedState, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
 
         // Receive broadcasts indicating the screen turned off while we have active WebContents.
         mHasWebContentsState.watch(() -> {
diff --git a/chromecast/browser/android/junit/src/org/chromium/chromecast/shell/CastWebContentsActivityTest.java b/chromecast/browser/android/junit/src/org/chromium/chromecast/shell/CastWebContentsActivityTest.java
index 865a571d..fd850eb 100644
--- a/chromecast/browser/android/junit/src/org/chromium/chromecast/shell/CastWebContentsActivityTest.java
+++ b/chromecast/browser/android/junit/src/org/chromium/chromecast/shell/CastWebContentsActivityTest.java
@@ -5,6 +5,7 @@
 package org.chromium.chromecast.shell;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNull;
 
 import android.content.Intent;
@@ -18,6 +19,7 @@
 import org.robolectric.android.controller.ActivityController;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowActivity;
+import org.robolectric.shadows.ShadowAudioManager;
 
 import org.chromium.testing.local.LocalRobolectricTestRunner;
 
@@ -59,4 +61,35 @@
         Intent intent = mShadowActivity.getNextStartedActivity();
         assertNull(intent);
     }
+
+    @Test
+    public void testDoesNotRequestAudioFocusBeforeResume() {
+        ShadowAudioManager shadowAudioManager = Shadows.shadowOf(
+                CastAudioManager.getAudioManager(RuntimeEnvironment.application).getInternal());
+        ShadowAudioManager.AudioFocusRequest originalRequest =
+                shadowAudioManager.getLastAudioFocusRequest();
+        mActivityLifecycle.create().start();
+        assertEquals(shadowAudioManager.getLastAudioFocusRequest(), originalRequest);
+    }
+
+    @Test
+    public void testRequestsAudioFocusOnResume() {
+        ShadowAudioManager shadowAudioManager = Shadows.shadowOf(
+                CastAudioManager.getAudioManager(RuntimeEnvironment.application).getInternal());
+        ShadowAudioManager.AudioFocusRequest originalRequest =
+                shadowAudioManager.getLastAudioFocusRequest();
+        mActivityLifecycle.create().start().resume();
+        assertNotEquals(shadowAudioManager.getLastAudioFocusRequest(), originalRequest);
+    }
+
+    @Test
+    public void testAbandonsAudioFocusOnPause() {
+        ShadowAudioManager shadowAudioManager = Shadows.shadowOf(
+                CastAudioManager.getAudioManager(RuntimeEnvironment.application).getInternal());
+        mActivityLifecycle.create().start().resume().pause();
+        ShadowAudioManager.AudioFocusRequest originalRequest =
+                shadowAudioManager.getLastAudioFocusRequest();
+        assertEquals(
+                shadowAudioManager.getLastAbandonedAudioFocusListener(), originalRequest.listener);
+    }
 }
diff --git a/chromecast/browser/url_request_context_factory.cc b/chromecast/browser/url_request_context_factory.cc
index dd4dfb69..c06b453 100644
--- a/chromecast/browser/url_request_context_factory.cc
+++ b/chromecast/browser/url_request_context_factory.cc
@@ -36,7 +36,7 @@
 #include "net/http/http_network_layer.h"
 #include "net/http/http_server_properties_impl.h"
 #include "net/http/http_stream_factory.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/ssl/channel_id_service.h"
 #include "net/ssl/default_channel_id_store.h"
 #include "net/ssl/ssl_config_service_defaults.h"
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn
index a56ada7a..f4c072e4 100644
--- a/chromeos/BUILD.gn
+++ b/chromeos/BUILD.gn
@@ -767,6 +767,7 @@
 
 proto_library("power_manager_proto") {
   sources = [
+    "//third_party/cros_system_api/dbus/power_manager/backlight.proto",
     "//third_party/cros_system_api/dbus/power_manager/idle.proto",
     "//third_party/cros_system_api/dbus/power_manager/input_event.proto",
     "//third_party/cros_system_api/dbus/power_manager/peripheral_battery_status.proto",
diff --git a/chromeos/dbus/fake_power_manager_client.cc b/chromeos/dbus/fake_power_manager_client.cc
index 7ec72fc..0c1b3cd 100644
--- a/chromeos/dbus/fake_power_manager_client.cc
+++ b/chromeos/dbus/fake_power_manager_client.cc
@@ -61,9 +61,13 @@
   screen_brightness_percent_ = percent;
   requested_screen_brightness_percent_ = percent;
 
+  power_manager::BacklightBrightnessChange change;
+  change.set_percent(percent);
+  change.set_cause(power_manager::BacklightBrightnessChange_Cause_USER_REQUEST);
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(&FakePowerManagerClient::SendBrightnessChanged,
-                                weak_ptr_factory_.GetWeakPtr(), percent, true));
+      FROM_HERE,
+      base::BindOnce(&FakePowerManagerClient::SendScreenBrightnessChanged,
+                     weak_ptr_factory_.GetWeakPtr(), change));
 }
 
 void FakePowerManagerClient::GetScreenBrightnessPercent(
@@ -145,17 +149,21 @@
   backlights_forced_off_ = forced_off;
   ++num_set_backlights_forced_off_calls_;
 
-  double target_brightness =
-      forced_off ? 0 : requested_screen_brightness_percent_;
+  power_manager::BacklightBrightnessChange change;
+  change.set_percent(forced_off ? 0 : requested_screen_brightness_percent_);
+  change.set_cause(
+      forced_off ? power_manager::BacklightBrightnessChange_Cause_FORCED_OFF
+                 : power_manager::
+                       BacklightBrightnessChange_Cause_NO_LONGER_FORCED_OFF);
+
   if (enqueue_brightness_changes_on_backlights_forced_off_) {
-    pending_brightness_changes_.push(target_brightness);
+    pending_screen_brightness_changes_.push(change);
   } else {
-    screen_brightness_percent_ = target_brightness;
+    screen_brightness_percent_ = change.percent();
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
-        base::BindOnce(&FakePowerManagerClient::SendBrightnessChanged,
-                       weak_ptr_factory_.GetWeakPtr(), target_brightness,
-                       false));
+        base::BindOnce(&FakePowerManagerClient::SendScreenBrightnessChanged,
+                       weak_ptr_factory_.GetWeakPtr(), change));
   }
 }
 
@@ -217,17 +225,16 @@
     observer.DarkSuspendImminent();
 }
 
-void FakePowerManagerClient::SendBrightnessChanged(int level,
-                                                   bool user_initiated) {
+void FakePowerManagerClient::SendScreenBrightnessChanged(
+    const power_manager::BacklightBrightnessChange& change) {
   for (auto& observer : observers_)
-    observer.BrightnessChanged(level, user_initiated);
+    observer.ScreenBrightnessChanged(change);
 }
 
 void FakePowerManagerClient::SendKeyboardBrightnessChanged(
-    int level,
-    bool user_initiated) {
+    const power_manager::BacklightBrightnessChange& change) {
   for (auto& observer : observers_)
-    observer.KeyboardBrightnessChanged(level, user_initiated);
+    observer.KeyboardBrightnessChanged(change);
 }
 
 void FakePowerManagerClient::SendScreenIdleStateChanged(
@@ -286,16 +293,16 @@
   power_policy_quit_closure_ = std::move(quit_closure);
 }
 
-bool FakePowerManagerClient::ApplyPendingBrightnessChange() {
-  if (pending_brightness_changes_.empty())
+bool FakePowerManagerClient::ApplyPendingScreenBrightnessChange() {
+  if (pending_screen_brightness_changes_.empty())
     return false;
-  double brightness = pending_brightness_changes_.front();
-  pending_brightness_changes_.pop();
 
-  DCHECK(brightness == 0 || brightness == requested_screen_brightness_percent_);
+  power_manager::BacklightBrightnessChange change =
+      pending_screen_brightness_changes_.front();
+  pending_screen_brightness_changes_.pop();
 
-  screen_brightness_percent_ = brightness;
-  SendBrightnessChanged(brightness, false);
+  screen_brightness_percent_ = change.percent();
+  SendScreenBrightnessChanged(change);
   return true;
 }
 
diff --git a/chromeos/dbus/fake_power_manager_client.h b/chromeos/dbus/fake_power_manager_client.h
index 888f773b..8ca190c 100644
--- a/chromeos/dbus/fake_power_manager_client.h
+++ b/chromeos/dbus/fake_power_manager_client.h
@@ -16,6 +16,7 @@
 #include "base/observer_list.h"
 #include "base/optional.h"
 #include "chromeos/chromeos_export.h"
+#include "chromeos/dbus/power_manager/backlight.pb.h"
 #include "chromeos/dbus/power_manager/policy.pb.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
 #include "chromeos/dbus/power_manager/suspend.pb.h"
@@ -53,8 +54,9 @@
   void set_enqueue_brightness_changes_on_backlights_forced_off(bool enqueue) {
     enqueue_brightness_changes_on_backlights_forced_off_ = enqueue;
   }
-  const std::queue<double>& pending_brightness_changes() const {
-    return pending_brightness_changes_;
+  const std::queue<power_manager::BacklightBrightnessChange>&
+  pending_screen_brightness_changes() const {
+    return pending_screen_brightness_changes_;
   }
   void set_user_activity_callback(base::RepeatingClosure callback) {
     user_activity_callback_ = std::move(callback);
@@ -104,13 +106,12 @@
   void SendSuspendDone(base::TimeDelta sleep_duration = base::TimeDelta());
   void SendDarkSuspendImminent();
 
-  // Emulates the power manager announcing that the system is changing
-  // display brightness to |level|.
-  void SendBrightnessChanged(int level, bool user_initiated);
-
-  // Emulates the power manager announcing that the system is changing
-  // keyboard brightness to |level|.
-  void SendKeyboardBrightnessChanged(int level, bool user_initiated);
+  // Emulates the power manager announcing that the system is changing the
+  // screen or keyboard brightness.
+  void SendScreenBrightnessChanged(
+      const power_manager::BacklightBrightnessChange& proto);
+  void SendKeyboardBrightnessChanged(
+      const power_manager::BacklightBrightnessChange& proto);
 
   // Notifies observers about the screen idle state changing.
   void SendScreenIdleStateChanged(const power_manager::ScreenIdleState& proto);
@@ -137,10 +138,10 @@
   void SetPowerPolicyQuitClosure(base::OnceClosure quit_closure);
 
   // Updates screen brightness to the first pending value in
-  // |pending_brightness_changes_|.
+  // |pending_screen_brightness_changes_|.
   // Returns whether the screen brightness change was applied - this will
   // return false if there are no pending brightness changes.
-  bool ApplyPendingBrightnessChange();
+  bool ApplyPendingScreenBrightnessChange();
 
   // Sets the screen brightness percent to be returned.
   // The nullopt |percent| means an error. In case of success,
@@ -198,13 +199,14 @@
   // brightness and send a brightness change event (provided undimmed
   // brightness percent is set).
   // If set, brightness changes will be enqueued to
-  // pending_brightness_changes_, and will have to be applied explicitly by
-  // calling ApplyPendingBrightnessChange().
+  // |pending_screen_brightness_changes_|, and will have to be applied
+  // explicitly by calling ApplyPendingScreenBrightnessChange().
   bool enqueue_brightness_changes_on_backlights_forced_off_ = false;
 
-  // Pending brightness changes caused by SetBacklightsForcedOff().
-  // ApplyPendingBrightnessChange() applies the first pending change.
-  std::queue<double> pending_brightness_changes_;
+  // Pending screen brightness changes caused by SetBacklightsForcedOff().
+  // ApplyPendingScreenBrightnessChange() applies the first pending change.
+  std::queue<power_manager::BacklightBrightnessChange>
+      pending_screen_brightness_changes_;
 
   // Delays returned by GetInactivityDelays().
   power_manager::PowerManagementPolicy::Delays inactivity_delays_;
diff --git a/chromeos/dbus/power_manager_client.cc b/chromeos/dbus/power_manager_client.cc
index f686c87..8c72d06 100644
--- a/chromeos/dbus/power_manager_client.cc
+++ b/chromeos/dbus/power_manager_client.cc
@@ -25,6 +25,7 @@
 #include "base/timer/timer.h"
 #include "chromeos/chromeos_switches.h"
 #include "chromeos/dbus/fake_power_manager_client.h"
+#include "chromeos/dbus/power_manager/backlight.pb.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
 #include "chromeos/dbus/power_manager/input_event.pb.h"
 #include "chromeos/dbus/power_manager/peripheral_battery_status.pb.h"
@@ -360,19 +361,21 @@
     // brightness level in Chrome as it'll make things less reliable.
     power_manager_proxy_->ConnectToSignal(
         power_manager::kPowerManagerInterface,
-        power_manager::kBrightnessChangedSignal,
-        base::Bind(&PowerManagerClientImpl::BrightnessChangedReceived,
-                   weak_ptr_factory_.GetWeakPtr()),
-        base::Bind(&PowerManagerClientImpl::SignalConnected,
-                   weak_ptr_factory_.GetWeakPtr()));
+        power_manager::kScreenBrightnessChangedSignal,
+        base::BindRepeating(
+            &PowerManagerClientImpl::ScreenBrightnessChangedReceived,
+            weak_ptr_factory_.GetWeakPtr()),
+        base::BindOnce(&PowerManagerClientImpl::SignalConnected,
+                       weak_ptr_factory_.GetWeakPtr()));
 
     power_manager_proxy_->ConnectToSignal(
         power_manager::kPowerManagerInterface,
         power_manager::kKeyboardBrightnessChangedSignal,
-        base::Bind(&PowerManagerClientImpl::KeyboardBrightnessChangedReceived,
-                   weak_ptr_factory_.GetWeakPtr()),
-        base::Bind(&PowerManagerClientImpl::SignalConnected,
-                   weak_ptr_factory_.GetWeakPtr()));
+        base::BindRepeating(
+            &PowerManagerClientImpl::KeyboardBrightnessChangedReceived,
+            weak_ptr_factory_.GetWeakPtr()),
+        base::BindOnce(&PowerManagerClientImpl::SignalConnected,
+                       weak_ptr_factory_.GetWeakPtr()));
 
     power_manager_proxy_->ConnectToSignal(
         power_manager::kPowerManagerInterface,
@@ -503,36 +506,34 @@
     }
   }
 
-  void BrightnessChangedReceived(dbus::Signal* signal) {
+  void ScreenBrightnessChangedReceived(dbus::Signal* signal) {
     dbus::MessageReader reader(signal);
-    int32_t brightness_level = 0;
-    bool user_initiated = 0;
-    if (!(reader.PopInt32(&brightness_level) &&
-          reader.PopBool(&user_initiated))) {
-      POWER_LOG(ERROR) << "Brightness changed signal had incorrect parameters: "
-                       << signal->ToString();
+    power_manager::BacklightBrightnessChange proto;
+    if (!reader.PopArrayOfBytesAsProto(&proto)) {
+      POWER_LOG(ERROR) << "Unable to decode protocol buffer from "
+                       << power_manager::kScreenBrightnessChangedSignal
+                       << " signal";
       return;
     }
-    POWER_LOG(DEBUG) << "Brightness changed to " << brightness_level
-                     << ": user initiated " << user_initiated;
+    POWER_LOG(DEBUG) << "Screen brightness changed to " << proto.percent()
+                     << ": cause " << proto.cause();
     for (auto& observer : observers_)
-      observer.BrightnessChanged(brightness_level, user_initiated);
+      observer.ScreenBrightnessChanged(proto);
   }
 
   void KeyboardBrightnessChangedReceived(dbus::Signal* signal) {
     dbus::MessageReader reader(signal);
-    int32_t brightness_level = 0;
-    bool user_initiated = 0;
-    if (!(reader.PopInt32(&brightness_level) &&
-          reader.PopBool(&user_initiated))) {
-      POWER_LOG(ERROR) << "Keyboard brightness changed signal had incorrect "
-                       << "parameters: " << signal->ToString();
+    power_manager::BacklightBrightnessChange proto;
+    if (!reader.PopArrayOfBytesAsProto(&proto)) {
+      POWER_LOG(ERROR) << "Unable to decode protocol buffer from "
+                       << power_manager::kKeyboardBrightnessChangedSignal
+                       << " signal";
       return;
     }
-    POWER_LOG(DEBUG) << "Keyboard brightness changed to " << brightness_level
-                     << ": user initiated " << user_initiated;
+    POWER_LOG(DEBUG) << "Keyboard brightness changed to " << proto.percent()
+                     << ": cause " << proto.cause();
     for (auto& observer : observers_)
-      observer.KeyboardBrightnessChanged(brightness_level, user_initiated);
+      observer.KeyboardBrightnessChanged(proto);
   }
 
   void ScreenIdleStateChangedReceived(dbus::Signal* signal) {
diff --git a/chromeos/dbus/power_manager_client.h b/chromeos/dbus/power_manager_client.h
index bf4e2d1..fcd5e88 100644
--- a/chromeos/dbus/power_manager_client.h
+++ b/chromeos/dbus/power_manager_client.h
@@ -21,6 +21,7 @@
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
 namespace power_manager {
+class BacklightBrightnessChange;
 class PowerSupplyProperties;
 class ScreenIdleState;
 }
@@ -56,14 +57,12 @@
     virtual void PowerManagerRestarted() {}
 
     // Called when the screen brightness is changed.
-    // |level| is of the range [0, 100].
-    // |user_initiated| is true if the action is initiated by the user.
-    virtual void BrightnessChanged(int level, bool user_initiated) {}
+    virtual void ScreenBrightnessChanged(
+        const power_manager::BacklightBrightnessChange& change) {}
 
     // Called when the keyboard brightness is changed.
-    // |level| is of the range [0, 100].
-    // |user_initiated| is true if the action is initiated by the user.
-    virtual void KeyboardBrightnessChanged(int level, bool user_initiated) {}
+    virtual void KeyboardBrightnessChanged(
+        const power_manager::BacklightBrightnessChange& change) {}
 
     // Called when screen-related inactivity timeouts are triggered or reset.
     virtual void ScreenIdleStateChanged(
diff --git a/chromeos/dbus/services/proxy_resolution_service_provider.cc b/chromeos/dbus/services/proxy_resolution_service_provider.cc
index a756042d..c21eacf 100644
--- a/chromeos/dbus/services/proxy_resolution_service_provider.cc
+++ b/chromeos/dbus/services/proxy_resolution_service_provider.cc
@@ -16,7 +16,7 @@
 #include "net/base/net_errors.h"
 #include "net/log/net_log_with_source.h"
 #include "net/proxy_resolution/proxy_info.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
diff --git a/components/arc/power/arc_power_bridge.cc b/components/arc/power/arc_power_bridge.cc
index d110d313..be74d85 100644
--- a/components/arc/power/arc_power_bridge.cc
+++ b/components/arc/power/arc_power_bridge.cc
@@ -12,6 +12,7 @@
 #include "base/logging.h"
 #include "base/memory/singleton.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/power_manager/backlight.pb.h"
 #include "chromeos/dbus/power_policy_controller.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_browser_context_keyed_service_factory_base.h"
@@ -190,18 +191,18 @@
   power_instance->Resume();
 }
 
-void ArcPowerBridge::BrightnessChanged(int level, bool user_initiated) {
-  double percent = static_cast<double>(level);
+void ArcPowerBridge::ScreenBrightnessChanged(
+    const power_manager::BacklightBrightnessChange& change) {
   const base::TimeTicks now = base::TimeTicks::Now();
   if (last_brightness_changed_time_.is_null() ||
       (now - last_brightness_changed_time_) >= kNotifyBrightnessDelay) {
-    UpdateAndroidScreenBrightness(percent);
+    UpdateAndroidScreenBrightness(change.percent());
     notify_brightness_timer_.Stop();
   } else {
     notify_brightness_timer_.Start(
         FROM_HERE, kNotifyBrightnessDelay,
         base::Bind(&ArcPowerBridge::UpdateAndroidScreenBrightness,
-                   weak_ptr_factory_.GetWeakPtr(), percent));
+                   weak_ptr_factory_.GetWeakPtr(), change.percent()));
   }
   last_brightness_changed_time_ = now;
 }
diff --git a/components/arc/power/arc_power_bridge.h b/components/arc/power/arc_power_bridge.h
index e21306f..bacd4acf 100644
--- a/components/arc/power/arc_power_bridge.h
+++ b/components/arc/power/arc_power_bridge.h
@@ -64,7 +64,8 @@
   // chromeos::PowerManagerClient::Observer overrides.
   void SuspendImminent(power_manager::SuspendImminent::Reason reason) override;
   void SuspendDone(const base::TimeDelta& sleep_duration) override;
-  void BrightnessChanged(int level, bool user_initiated) override;
+  void ScreenBrightnessChanged(
+      const power_manager::BacklightBrightnessChange& change) override;
 
   // DisplayConfigurator::Observer overrides.
   void OnPowerStateChanged(chromeos::DisplayPowerState power_state) override;
diff --git a/components/arc/power/arc_power_bridge_unittest.cc b/components/arc/power/arc_power_bridge_unittest.cc
index 60b65b1..2eb125b 100644
--- a/components/arc/power/arc_power_bridge_unittest.cc
+++ b/components/arc/power/arc_power_bridge_unittest.cc
@@ -150,7 +150,10 @@
   // Check that Chrome OS brightness changes are passed to Android.
   const double kUpdatedBrightness = 45.0;
   power_manager_client_->set_screen_brightness_percent(kUpdatedBrightness);
-  power_manager_client_->SendBrightnessChanged(kUpdatedBrightness, true);
+  power_manager::BacklightBrightnessChange change;
+  change.set_percent(kUpdatedBrightness);
+  change.set_cause(power_manager::BacklightBrightnessChange_Cause_USER_REQUEST);
+  power_manager_client_->SendScreenBrightnessChanged(change);
   EXPECT_DOUBLE_EQ(kUpdatedBrightness, power_instance_->screen_brightness());
 
   // Requests from Android should update the Chrome OS brightness.
@@ -162,7 +165,8 @@
   // To prevent battles between Chrome OS and Android, the updated brightness
   // shouldn't be passed to Android immediately, but it should be passed after
   // the timer fires.
-  power_manager_client_->SendBrightnessChanged(kAndroidBrightness, true);
+  change.set_percent(kAndroidBrightness);
+  power_manager_client_->SendScreenBrightnessChanged(change);
   EXPECT_DOUBLE_EQ(kUpdatedBrightness, power_instance_->screen_brightness());
   ASSERT_TRUE(power_bridge_->TriggerNotifyBrightnessTimerForTesting());
   EXPECT_DOUBLE_EQ(kAndroidBrightness, power_instance_->screen_brightness());
diff --git a/components/cronet/android/cronet_library_loader.cc b/components/cronet/android/cronet_library_loader.cc
index 86b259d..9dd89b08 100644
--- a/components/cronet/android/cronet_library_loader.cc
+++ b/components/cronet/android/cronet_library_loader.cc
@@ -29,7 +29,7 @@
 #include "net/android/network_change_notifier_factory_android.h"
 #include "net/base/network_change_notifier.h"
 #include "net/proxy_resolution/proxy_config_service_android.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "url/url_features.h"
 #include "url/url_util.h"
 
diff --git a/components/cronet/android/cronet_url_request_context_adapter.cc b/components/cronet/android/cronet_url_request_context_adapter.cc
index 77085e74..731d9677 100644
--- a/components/cronet/android/cronet_url_request_context_adapter.cc
+++ b/components/cronet/android/cronet_url_request_context_adapter.cc
@@ -54,7 +54,7 @@
 #include "net/log/net_log_util.h"
 #include "net/nqe/network_quality_estimator_params.h"
 #include "net/proxy_resolution/proxy_config_service_android.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/quic/core/quic_versions.h"
 #include "net/ssl/channel_id_service.h"
 #include "net/url_request/url_request_context.h"
diff --git a/components/cronet/cronet_global_state_stubs.cc b/components/cronet/cronet_global_state_stubs.cc
index 4643f03..7980e77 100644
--- a/components/cronet/cronet_global_state_stubs.cc
+++ b/components/cronet/cronet_global_state_stubs.cc
@@ -8,7 +8,7 @@
 #include "base/task_scheduler/post_task.h"
 #include "base/task_scheduler/task_scheduler.h"
 #include "net/proxy_resolution/proxy_config_service.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "url/url_util.h"
 
 // This file provides minimal "stub" implementations of the Cronet global-state
diff --git a/components/cronet/cronet_url_request_context.cc b/components/cronet/cronet_url_request_context.cc
index 7889cb1..42e9684 100644
--- a/components/cronet/cronet_url_request_context.cc
+++ b/components/cronet/cronet_url_request_context.cc
@@ -48,7 +48,7 @@
 #include "net/log/file_net_log_observer.h"
 #include "net/log/net_log_util.h"
 #include "net/nqe/network_quality_estimator_params.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/quic/core/quic_versions.h"
 #include "net/ssl/channel_id_service.h"
 #include "net/url_request/url_request_context.h"
diff --git a/components/cronet/ios/cronet_environment.mm b/components/cronet/ios/cronet_environment.mm
index fec8e1c..39bb4404 100644
--- a/components/cronet/ios/cronet_environment.mm
+++ b/components/cronet/ios/cronet_environment.mm
@@ -42,7 +42,7 @@
 #include "net/log/net_log.h"
 #include "net/log/net_log_capture_mode.h"
 #include "net/log/net_log_util.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/quic/core/quic_versions.h"
 #include "net/socket/ssl_client_socket.h"
 #include "net/ssl/channel_id_service.h"
diff --git a/components/cronet/ios/cronet_global_state_ios.mm b/components/cronet/ios/cronet_global_state_ios.mm
index 267fe5b..92a7139 100644
--- a/components/cronet/ios/cronet_global_state_ios.mm
+++ b/components/cronet/ios/cronet_global_state_ios.mm
@@ -13,7 +13,7 @@
 #include "ios/web/public/global_state/ios_global_state_configuration.h"
 #include "ios/web/public/user_agent.h"
 #include "net/proxy_resolution/proxy_config_service.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "url/url_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.cc
index 0a51d7e8..ac307e5 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.cc
@@ -23,8 +23,8 @@
 #include "net/proxy_resolution/proxy_config.h"
 #include "net/proxy_resolution/proxy_info.h"
 #include "net/proxy_resolution/proxy_list.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/proxy_resolution/proxy_retry_info.h"
-#include "net/proxy_resolution/proxy_service.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_status.h"
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc
index 2f8e414..a8b8be9 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc
@@ -36,7 +36,7 @@
 #include "net/http/http_response_headers.h"
 #include "net/http/http_transaction_test_util.h"
 #include "net/http/http_util.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/socket/socket_test_util.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_response.h"
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc
index 313c824..39c311ae 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc
@@ -16,7 +16,7 @@
 #include "net/base/proxy_server.h"
 #include "net/http/http_response_headers.h"
 #include "net/http/http_status_code.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context.h"
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
index 6c8ca425..7342956 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
@@ -27,7 +27,7 @@
 #include "net/log/net_log.h"
 #include "net/log/net_log_with_source.h"
 #include "net/proxy_resolution/proxy_info.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc
index dc71586..6a9b397 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc
@@ -19,7 +19,7 @@
 #include "net/base/proxy_server.h"
 #include "net/log/net_log_source_type.h"
 #include "net/log/net_log_with_source.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/socket/socket_test_util.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/url_request.h"
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
index c26d6dd..19b6230 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
@@ -33,7 +33,7 @@
 #include "net/nqe/effective_connection_type.h"
 #include "net/nqe/network_quality_estimator.h"
 #include "net/proxy_resolution/proxy_info.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_status.h"
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
index 672db949..011e104 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
@@ -59,8 +59,8 @@
 #include "net/nqe/network_quality_estimator_test_util.h"
 #include "net/proxy_resolution/proxy_config.h"
 #include "net/proxy_resolution/proxy_info.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/proxy_resolution/proxy_retry_info.h"
-#include "net/proxy_resolution/proxy_service.h"
 #include "net/socket/socket_test_util.h"
 #include "net/test/cert_test_util.h"
 #include "net/test/gtest_util.h"
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h
index 29865459..c895cf4 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h
@@ -13,7 +13,7 @@
 #include "base/time/time.h"
 #include "net/http/http_request_headers.h"
 #include "net/http/http_response_headers.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 
 class GURL;
 
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers_unittest.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers_unittest.cc
index 28d104f..2fac76306 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_headers_unittest.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_headers_unittest.cc
@@ -19,7 +19,7 @@
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers_test_utils.h"
 #include "net/http/http_response_headers.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
diff --git a/components/download/public/common/BUILD.gn b/components/download/public/common/BUILD.gn
index a082a38..07d258c 100644
--- a/components/download/public/common/BUILD.gn
+++ b/components/download/public/common/BUILD.gn
@@ -21,6 +21,8 @@
     "download_danger_type.h",
     "download_destination_observer.cc",
     "download_destination_observer.h",
+    "download_features.cc",
+    "download_features.h",
     "download_interrupt_reason_values.h",
     "download_interrupt_reasons.h",
     "download_interrupt_reasons_utils.h",
diff --git a/components/download/public/common/download_features.cc b/components/download/public/common/download_features.cc
new file mode 100644
index 0000000..2a04e258
--- /dev/null
+++ b/components/download/public/common/download_features.cc
@@ -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.
+
+#include "components/download/public/common/download_features.h"
+
+#include "build/build_config.h"
+
+namespace download {
+namespace features {
+
+const base::Feature kParallelDownloading {
+  "ParallelDownloading",
+#if defined(OS_ANDROID)
+      base::FEATURE_ENABLED_BY_DEFAULT
+#else
+      base::FEATURE_DISABLED_BY_DEFAULT
+#endif
+};
+
+}  // namespace features
+}  // namespace download
diff --git a/components/download/public/common/download_features.h b/components/download/public/common/download_features.h
new file mode 100644
index 0000000..e6b6c134
--- /dev/null
+++ b/components/download/public/common/download_features.h
@@ -0,0 +1,20 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_FEATURES_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_FEATURES_H_
+
+#include "base/feature_list.h"
+#include "components/download/public/common/download_export.h"
+
+namespace download {
+namespace features {
+
+// Whether a download can be handled by parallel jobs.
+COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature kParallelDownloading;
+
+}  // namespace features
+}  // namespace download
+
+#endif  // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_FEATURES_H_
diff --git a/components/feed/features.gni b/components/feed/features.gni
index 73f73c7..808c6147 100644
--- a/components/feed/features.gni
+++ b/components/feed/features.gni
@@ -3,5 +3,7 @@
 # found in the LICENSE file.
 
 declare_args() {
-  enable_feed_in_chrome = is_android
+  # TODO(agrieve): Re-enable for is_android once multidex issue is resolved:
+  #     https://crbug.com/820361
+  enable_feed_in_chrome = false
 }
diff --git a/components/omnibox/browser/autocomplete_match.cc b/components/omnibox/browser/autocomplete_match.cc
index e2c17664..8228612 100644
--- a/components/omnibox/browser/autocomplete_match.cc
+++ b/components/omnibox/browser/autocomplete_match.cc
@@ -574,14 +574,11 @@
   auto format_types = url_formatter::kFormatUrlOmitDefaults;
   if (preserve_scheme) {
     format_types &= ~url_formatter::kFormatUrlOmitHTTP;
-  } else if (base::FeatureList::IsEnabled(
-                 omnibox::kUIExperimentHideSuggestionUrlScheme)) {
+  } else {
     format_types |= url_formatter::kFormatUrlOmitHTTPS;
   }
 
-  if (!preserve_subdomain &&
-      base::FeatureList::IsEnabled(
-          omnibox::kUIExperimentHideSuggestionUrlTrivialSubdomains)) {
+  if (!preserve_subdomain) {
     format_types |= url_formatter::kFormatUrlOmitTrivialSubdomains;
   }
 
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc
index e06e18f..955baf0 100644
--- a/components/omnibox/browser/omnibox_field_trial.cc
+++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -107,17 +107,6 @@
     "OmniboxUIExperimentHideSteadyStateUrlSchemeAndSubdomains",
     base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Feature used for hiding the suggestion URL scheme as a UI experiment.
-const base::Feature kUIExperimentHideSuggestionUrlScheme{
-    "OmniboxUIExperimentHideSuggestionUrlScheme",
-    base::FEATURE_ENABLED_BY_DEFAULT};
-
-// Feature used for hiding the suggestion URL subdomain as a UI experiment.
-// This only hides some trivially informative subdomains such as "www" or "m".
-const base::Feature kUIExperimentHideSuggestionUrlTrivialSubdomains{
-    "OmniboxUIExperimentHideSuggestionUrlTrivialSubdomains",
-    base::FEATURE_ENABLED_BY_DEFAULT};
-
 // Feature used for the omnibox narrow suggestions dropdown UI experiment.
 const base::Feature kUIExperimentNarrowDropdown{
     "OmniboxUIExperimentNarrowDropdown", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/omnibox/browser/omnibox_field_trial.h b/components/omnibox/browser/omnibox_field_trial.h
index 90504c5..fecd3fc 100644
--- a/components/omnibox/browser/omnibox_field_trial.h
+++ b/components/omnibox/browser/omnibox_field_trial.h
@@ -37,8 +37,6 @@
 extern const base::Feature kDisplayTitleForCurrentUrl;
 extern const base::Feature kUIExperimentElideSuggestionUrlAfterHost;
 extern const base::Feature kUIExperimentHideSteadyStateUrlSchemeAndSubdomains;
-extern const base::Feature kUIExperimentHideSuggestionUrlScheme;
-extern const base::Feature kUIExperimentHideSuggestionUrlTrivialSubdomains;
 extern const base::Feature kUIExperimentMaxAutocompleteMatches;
 extern const base::Feature kUIExperimentNarrowDropdown;
 extern const base::Feature kUIExperimentShowSuggestionFavicons;
diff --git a/components/proxy_config/ios/proxy_service_factory.cc b/components/proxy_config/ios/proxy_service_factory.cc
index ad272d9..f8d1f1d 100644
--- a/components/proxy_config/ios/proxy_service_factory.cc
+++ b/components/proxy_config/ios/proxy_service_factory.cc
@@ -11,7 +11,7 @@
 #include "components/proxy_config/pref_proxy_config_tracker_impl.h"
 #include "ios/web/public/web_thread.h"
 #include "net/proxy_resolution/proxy_config_service.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 
 // static
 std::unique_ptr<net::ProxyConfigService>
diff --git a/components/search_provider_logos/logo_service_impl.cc b/components/search_provider_logos/logo_service_impl.cc
index e6449b8..3c7ec3f 100644
--- a/components/search_provider_logos/logo_service_impl.cc
+++ b/components/search_provider_logos/logo_service_impl.cc
@@ -284,8 +284,8 @@
   logo_cache_for_test_ = std::move(cache);
 }
 
-void LogoServiceImpl::SetClockForTests(std::unique_ptr<base::Clock> clock) {
-  clock_for_test_ = std::move(clock);
+void LogoServiceImpl::SetClockForTests(base::Clock* clock) {
+  clock_for_test_ = clock;
 }
 
 void LogoServiceImpl::InitializeLogoTrackerIfNecessary() {
@@ -298,15 +298,15 @@
     logo_cache = std::make_unique<LogoCache>(cache_directory_);
   }
 
-  std::unique_ptr<base::Clock> clock = std::move(clock_for_test_);
+  base::Clock* clock = clock_for_test_;
   if (!clock) {
-    clock = std::make_unique<base::DefaultClock>();
+    clock = base::DefaultClock::GetInstance();
   }
 
   logo_tracker_ = std::make_unique<LogoTracker>(
       request_context_getter_,
       std::make_unique<LogoDelegateImpl>(std::move(image_decoder_)),
-      std::move(logo_cache), std::move(clock));
+      std::move(logo_cache), clock);
 }
 
 void LogoServiceImpl::SigninStatusChanged() {
diff --git a/components/search_provider_logos/logo_service_impl.h b/components/search_provider_logos/logo_service_impl.h
index db69bff..6dbf079 100644
--- a/components/search_provider_logos/logo_service_impl.h
+++ b/components/search_provider_logos/logo_service_impl.h
@@ -56,7 +56,7 @@
   void SetLogoCacheForTests(std::unique_ptr<LogoCache> cache);
 
   // Overrides the clock used to check the time.
-  void SetClockForTests(std::unique_ptr<base::Clock> clock);
+  void SetClockForTests(base::Clock* clock);
 
  private:
   class SigninObserver;
@@ -79,8 +79,10 @@
 
   std::unique_ptr<SigninObserver> signin_observer_;
 
+  // For testing.
+  base::Clock* clock_for_test_ = nullptr;
+
   // For testing. logo_tracker_ takes ownership if/when it is initialized.
-  std::unique_ptr<base::Clock> clock_for_test_;
   std::unique_ptr<LogoCache> logo_cache_for_test_;
 
   // Lazily initialized on first call to GetLogo().
diff --git a/components/search_provider_logos/logo_service_impl_unittest.cc b/components/search_provider_logos/logo_service_impl_unittest.cc
index 017b3eb43..8a6040e 100644
--- a/components/search_provider_logos/logo_service_impl_unittest.cc
+++ b/components/search_provider_logos/logo_service_impl_unittest.cc
@@ -321,7 +321,6 @@
  protected:
   LogoServiceImplTest()
       : template_url_service_(nullptr, 0),
-        test_clock_(new base::SimpleTestClock()),
         logo_cache_(new NiceMock<MockLogoCache>()),
         fake_url_fetcher_factory_(
             nullptr,
@@ -335,7 +334,7 @@
                     GURL("https://example.com/logo.json"),
                     /*make_default=*/true);
 
-    test_clock_->SetNow(base::Time::FromJsTime(INT64_C(1388686828000)));
+    test_clock_.SetNow(base::Time::FromJsTime(INT64_C(1388686828000)));
     logo_service_ = std::make_unique<LogoServiceImpl>(
         base::FilePath(), signin_helper_.cookie_service(),
         &template_url_service_, std::make_unique<FakeImageDecoder>(),
@@ -343,7 +342,7 @@
             base::ThreadTaskRunnerHandle::Get()),
         base::BindRepeating(&LogoServiceImplTest::use_gray_background,
                             base::Unretained(this)));
-    logo_service_->SetClockForTests(base::WrapUnique(test_clock_));
+    logo_service_->SetClockForTests(&test_clock_);
     logo_service_->SetLogoCacheForTests(base::WrapUnique(logo_cache_));
   }
 
@@ -357,7 +356,7 @@
   }
 
   // Returns the response that the server would send for the given logo.
-  std::string ServerResponse(const Logo& logo) const;
+  std::string ServerResponse(const Logo& logo);
 
   // Sets the response to be returned when the LogoTracker fetches the logo.
   void SetServerResponse(const std::string& response,
@@ -398,7 +397,7 @@
 
   base::test::ScopedTaskEnvironment task_environment_;
   TemplateURLService template_url_service_;
-  base::SimpleTestClock* test_clock_;
+  base::SimpleTestClock test_clock_;
   NiceMock<MockLogoCache>* logo_cache_;
   net::FakeURLFetcherFactory fake_url_fetcher_factory_;
   std::unique_ptr<LogoServiceImpl> logo_service_;
@@ -420,10 +419,10 @@
                                                response_code, status);
 }
 
-std::string LogoServiceImplTest::ServerResponse(const Logo& logo) const {
+std::string LogoServiceImplTest::ServerResponse(const Logo& logo) {
   base::TimeDelta time_to_live;
   if (!logo.metadata.expiration_time.is_null())
-    time_to_live = logo.metadata.expiration_time - test_clock_->Now();
+    time_to_live = logo.metadata.expiration_time - test_clock_.Now();
   return MakeServerResponse(logo, time_to_live);
 }
 
@@ -493,7 +492,7 @@
 
 TEST_F(LogoServiceImplTest, CTARequestedBackgroundCanUpdate) {
   std::string response =
-      ServerResponse(GetSampleLogo(DoodleURL(), test_clock_->Now()));
+      ServerResponse(GetSampleLogo(DoodleURL(), test_clock_.Now()));
   GURL query_with_gray_background = AppendFingerprintParamToDoodleURL(
       AppendPreliminaryParamsToDoodleURL(true, DoodleURL()), std::string());
   GURL query_without_gray_background = AppendFingerprintParamToDoodleURL(
@@ -533,7 +532,7 @@
 TEST_F(LogoServiceImplTest, DownloadAndCacheLogo) {
   StrictMock<MockLogoCallback> cached;
   StrictMock<MockLogoCallback> fresh;
-  Logo logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  Logo logo = GetSampleLogo(DoodleURL(), test_clock_.Now());
   SetServerResponse(ServerResponse(logo));
   logo_cache_->ExpectSetCachedLogo(&logo);
   EXPECT_CALL(cached, Run(LogoCallbackReason::DETERMINED, Eq(base::nullopt)));
@@ -544,7 +543,7 @@
 TEST_F(LogoServiceImplTest, DownloadAndCacheEncodedLogo) {
   StrictMock<MockEncodedLogoCallback> cached;
   StrictMock<MockEncodedLogoCallback> fresh;
-  Logo logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  Logo logo = GetSampleLogo(DoodleURL(), test_clock_.Now());
   EncodedLogo encoded_logo = EncodeLogo(logo);
   SetServerResponse(ServerResponse(logo));
   logo_cache_->ExpectSetCachedLogo(&logo);
@@ -631,7 +630,7 @@
 }
 
 TEST_F(LogoServiceImplTest, ReturnCachedLogo) {
-  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_.Now());
   logo_cache_->EncodeAndSetCachedLogo(cached_logo);
   SetServerResponseWhenFingerprint(cached_logo.metadata.fingerprint, "",
                                    net::URLRequestStatus::FAILED, net::HTTP_OK);
@@ -649,7 +648,7 @@
 }
 
 TEST_F(LogoServiceImplTest, ValidateCachedLogo) {
-  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_.Now());
   logo_cache_->EncodeAndSetCachedLogo(cached_logo);
 
   // During revalidation, the image data and mime_type are absent.
@@ -657,7 +656,7 @@
   fresh_logo.image.reset();
   fresh_logo.metadata.mime_type.clear();
   fresh_logo.metadata.expiration_time =
-      test_clock_->Now() + base::TimeDelta::FromDays(8);
+      test_clock_.Now() + base::TimeDelta::FromDays(8);
   SetServerResponseWhenFingerprint(fresh_logo.metadata.fingerprint,
                                    ServerResponse(fresh_logo));
 
@@ -694,7 +693,7 @@
 }
 
 TEST_F(LogoServiceImplTest, UpdateCachedLogoMetadata) {
-  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_.Now());
   logo_cache_->EncodeAndSetCachedLogo(cached_logo);
 
   Logo fresh_logo = cached_logo;
@@ -704,7 +703,7 @@
   fresh_logo.metadata.alt_text = "new alt text";
   fresh_logo.metadata.animated_url = GURL("https://new.animated.url");
   fresh_logo.metadata.expiration_time =
-      test_clock_->Now() + base::TimeDelta::FromDays(8);
+      test_clock_.Now() + base::TimeDelta::FromDays(8);
   SetServerResponseWhenFingerprint(fresh_logo.metadata.fingerprint,
                                    ServerResponse(fresh_logo));
 
@@ -732,10 +731,10 @@
 }
 
 TEST_F(LogoServiceImplTest, UpdateCachedLogo) {
-  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_.Now());
   logo_cache_->EncodeAndSetCachedLogo(cached_logo);
 
-  Logo fresh_logo = GetSampleLogo2(DoodleURL(), test_clock_->Now());
+  Logo fresh_logo = GetSampleLogo2(DoodleURL(), test_clock_.Now());
   SetServerResponseWhenFingerprint(cached_logo.metadata.fingerprint,
                                    ServerResponse(fresh_logo));
 
@@ -751,7 +750,7 @@
 }
 
 TEST_F(LogoServiceImplTest, InvalidateCachedLogo) {
-  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_.Now());
   logo_cache_->EncodeAndSetCachedLogo(cached_logo);
 
   // This response means there's no current logo.
@@ -773,7 +772,7 @@
 TEST_F(LogoServiceImplTest, DeleteCachedLogoFromOldUrl) {
   SetServerResponse("", net::URLRequestStatus::FAILED, net::HTTP_OK);
   Logo cached_logo =
-      GetSampleLogo(GURL("https://oldsearchprovider.com"), test_clock_->Now());
+      GetSampleLogo(GURL("https://oldsearchprovider.com"), test_clock_.Now());
   logo_cache_->EncodeAndSetCachedLogo(cached_logo);
 
   EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(0);
@@ -790,9 +789,9 @@
 }
 
 TEST_F(LogoServiceImplTest, LogoWithTTLCannotBeShownAfterExpiration) {
-  Logo logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  Logo logo = GetSampleLogo(DoodleURL(), test_clock_.Now());
   base::TimeDelta time_to_live = base::TimeDelta::FromDays(3);
-  logo.metadata.expiration_time = test_clock_->Now() + time_to_live;
+  logo.metadata.expiration_time = test_clock_.Now() + time_to_live;
   SetServerResponse(ServerResponse(logo));
   LogoCallbacks callbacks;
   callbacks.on_fresh_decoded_logo_available = base::Bind(
@@ -802,12 +801,11 @@
   const LogoMetadata* cached_metadata = logo_cache_->GetCachedLogoMetadata();
   ASSERT_TRUE(cached_metadata);
   EXPECT_FALSE(cached_metadata->can_show_after_expiration);
-  EXPECT_EQ(test_clock_->Now() + time_to_live,
-            cached_metadata->expiration_time);
+  EXPECT_EQ(test_clock_.Now() + time_to_live, cached_metadata->expiration_time);
 }
 
 TEST_F(LogoServiceImplTest, LogoWithoutTTLCanBeShownAfterExpiration) {
-  Logo logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  Logo logo = GetSampleLogo(DoodleURL(), test_clock_.Now());
   base::TimeDelta time_to_live = base::TimeDelta();
   SetServerResponse(MakeServerResponse(logo, time_to_live));
   LogoCallbacks callbacks;
@@ -818,15 +816,15 @@
   const LogoMetadata* cached_metadata = logo_cache_->GetCachedLogoMetadata();
   ASSERT_TRUE(cached_metadata);
   EXPECT_TRUE(cached_metadata->can_show_after_expiration);
-  EXPECT_EQ(test_clock_->Now() + base::TimeDelta::FromDays(30),
+  EXPECT_EQ(test_clock_.Now() + base::TimeDelta::FromDays(30),
             cached_metadata->expiration_time);
 }
 
 TEST_F(LogoServiceImplTest, UseSoftExpiredCachedLogo) {
   SetServerResponse("", net::URLRequestStatus::FAILED, net::HTTP_OK);
-  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_.Now());
   cached_logo.metadata.expiration_time =
-      test_clock_->Now() - base::TimeDelta::FromSeconds(1);
+      test_clock_.Now() - base::TimeDelta::FromSeconds(1);
   cached_logo.metadata.can_show_after_expiration = true;
   logo_cache_->EncodeAndSetCachedLogo(cached_logo);
 
@@ -843,13 +841,13 @@
 }
 
 TEST_F(LogoServiceImplTest, RerequestSoftExpiredCachedLogo) {
-  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_.Now());
   cached_logo.metadata.expiration_time =
-      test_clock_->Now() - base::TimeDelta::FromDays(5);
+      test_clock_.Now() - base::TimeDelta::FromDays(5);
   cached_logo.metadata.can_show_after_expiration = true;
   logo_cache_->EncodeAndSetCachedLogo(cached_logo);
 
-  Logo fresh_logo = GetSampleLogo2(DoodleURL(), test_clock_->Now());
+  Logo fresh_logo = GetSampleLogo2(DoodleURL(), test_clock_.Now());
   SetServerResponse(ServerResponse(fresh_logo));
 
   logo_cache_->ExpectSetCachedLogo(&fresh_logo);
@@ -866,9 +864,9 @@
 
 TEST_F(LogoServiceImplTest, DeleteAncientCachedLogo) {
   SetServerResponse("", net::URLRequestStatus::FAILED, net::HTTP_OK);
-  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_.Now());
   cached_logo.metadata.expiration_time =
-      test_clock_->Now() - base::TimeDelta::FromDays(200);
+      test_clock_.Now() - base::TimeDelta::FromDays(200);
   cached_logo.metadata.can_show_after_expiration = true;
   logo_cache_->EncodeAndSetCachedLogo(cached_logo);
 
@@ -887,9 +885,9 @@
 
 TEST_F(LogoServiceImplTest, DeleteExpiredCachedLogo) {
   SetServerResponse("", net::URLRequestStatus::FAILED, net::HTTP_OK);
-  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_.Now());
   cached_logo.metadata.expiration_time =
-      test_clock_->Now() - base::TimeDelta::FromSeconds(1);
+      test_clock_.Now() - base::TimeDelta::FromSeconds(1);
   cached_logo.metadata.can_show_after_expiration = false;
   logo_cache_->EncodeAndSetCachedLogo(cached_logo);
 
@@ -909,7 +907,7 @@
 TEST_F(LogoServiceImplTest, ClearLogoOnSignOut) {
   // Sign in and setup a logo response.
   signin_helper_.SignIn();
-  Logo logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  Logo logo = GetSampleLogo(DoodleURL(), test_clock_.Now());
   SetServerResponse(ServerResponse(logo));
 
   // Request the logo so it gets fetched and cached.
@@ -947,11 +945,11 @@
 }
 
 TEST_F(LogoServiceImplTest, SupportOverlappingLogoRequests) {
-  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  Logo cached_logo = GetSampleLogo(DoodleURL(), test_clock_.Now());
   logo_cache_->EncodeAndSetCachedLogo(cached_logo);
   ON_CALL(*logo_cache_, SetCachedLogo(_)).WillByDefault(Return());
 
-  Logo fresh_logo = GetSampleLogo2(DoodleURL(), test_clock_->Now());
+  Logo fresh_logo = GetSampleLogo2(DoodleURL(), test_clock_.Now());
   std::string response = ServerResponse(fresh_logo);
   SetServerResponse(response);
   SetServerResponseWhenFingerprint(cached_logo.metadata.fingerprint, response);
@@ -996,7 +994,7 @@
                   GURL("https://chromium.org/logo.json"),
                   /*make_default=*/true);
 
-  Logo logo = GetSampleLogo(DoodleURL(), test_clock_->Now());
+  Logo logo = GetSampleLogo(DoodleURL(), test_clock_.Now());
   SetServerResponse(ServerResponse(logo));
 
   StrictMock<MockLogoCallback> second_cached;
diff --git a/components/search_provider_logos/logo_tracker.cc b/components/search_provider_logos/logo_tracker.cc
index 3e11082..1324ddf 100644
--- a/components/search_provider_logos/logo_tracker.cc
+++ b/components/search_provider_logos/logo_tracker.cc
@@ -85,7 +85,7 @@
     scoped_refptr<net::URLRequestContextGetter> request_context_getter,
     std::unique_ptr<LogoDelegate> delegate,
     std::unique_ptr<LogoCache> logo_cache,
-    std::unique_ptr<base::Clock> clock)
+    base::Clock* clock)
     : is_idle_(true),
       is_cached_logo_valid_(false),
       logo_delegate_(std::move(delegate)),
@@ -94,7 +94,7 @@
            base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
       logo_cache_(logo_cache.release(),
                   base::OnTaskRunnerDeleter(cache_task_runner_)),
-      clock_(std::move(clock)),
+      clock_(clock),
       request_context_getter_(request_context_getter),
       weak_ptr_factory_(this) {}
 
diff --git a/components/search_provider_logos/logo_tracker.h b/components/search_provider_logos/logo_tracker.h
index 23692db..8c3191be 100644
--- a/components/search_provider_logos/logo_tracker.h
+++ b/components/search_provider_logos/logo_tracker.h
@@ -90,7 +90,7 @@
       scoped_refptr<net::URLRequestContextGetter> request_context_getter,
       std::unique_ptr<LogoDelegate> delegate,
       std::unique_ptr<LogoCache> logo_cache,
-      std::unique_ptr<base::Clock> clock);
+      base::Clock* clock);
 
   ~LogoTracker() override;
 
@@ -227,7 +227,7 @@
   std::unique_ptr<LogoCache, base::OnTaskRunnerDeleter> logo_cache_;
 
   // Clock used to determine current time. Can be overridden in tests.
-  std::unique_ptr<base::Clock> clock_;
+  base::Clock* clock_;
 
   // The URLRequestContextGetter used for network requests.
   scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
diff --git a/components/services/OWNERS b/components/services/OWNERS
new file mode 100644
index 0000000..e4ca4ab0
--- /dev/null
+++ b/components/services/OWNERS
@@ -0,0 +1 @@
+file://services/OWNERS
diff --git a/components/services/README.md b/components/services/README.md
new file mode 100644
index 0000000..e6e0239
--- /dev/null
+++ b/components/services/README.md
@@ -0,0 +1,5 @@
+This directory holds [services](/services) that are:
+(a) Not considered part of Chrome's foundation (i.e., //services), but
+(b) Still used by multiple embedders
+
+If in doubt about where your service belongs, contact services-dev@chromium.org.
diff --git a/components/font_service/BUILD.gn b/components/services/font/BUILD.gn
similarity index 93%
rename from components/font_service/BUILD.gn
rename to components/services/font/BUILD.gn
index 250b3ab..8ee50e0a 100644
--- a/components/font_service/BUILD.gn
+++ b/components/services/font/BUILD.gn
@@ -13,7 +13,7 @@
 
   deps = [
     "//base",
-    "//components/font_service/public/interfaces",
+    "//components/services/font/public/interfaces",
     "//mojo/common:common_base",
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/system",
diff --git a/components/font_service/DEPS b/components/services/font/DEPS
similarity index 100%
rename from components/font_service/DEPS
rename to components/services/font/DEPS
diff --git a/components/font_service/OWNERS b/components/services/font/OWNERS
similarity index 100%
rename from components/font_service/OWNERS
rename to components/services/font/OWNERS
diff --git a/components/font_service/font_service_app.cc b/components/services/font/font_service_app.cc
similarity index 96%
rename from components/font_service/font_service_app.cc
rename to components/services/font/font_service_app.cc
index 6feb156..63ecd06 100644
--- a/components/font_service/font_service_app.cc
+++ b/components/services/font/font_service_app.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/font_service/font_service_app.h"
+#include "components/services/font/font_service_app.h"
 
 #include <utility>
 
@@ -65,8 +65,7 @@
       SkFontConfigInterface::GetSingletonDirectInterface();
   const bool r = fc->matchFamilyName(
       family_name.data(),
-      SkFontStyle(requested_style->weight,
-                  requested_style->width,
+      SkFontStyle(requested_style->weight, requested_style->width,
                   static_cast<SkFontStyle::Slant>(requested_style->slant)),
       &result_identity, &result_family, &result_style);
 
diff --git a/components/font_service/font_service_app.h b/components/services/font/font_service_app.h
similarity index 86%
rename from components/font_service/font_service_app.h
rename to components/services/font/font_service_app.h
index d48cb1b..ce0fa7c3 100644
--- a/components/font_service/font_service_app.h
+++ b/components/services/font/font_service_app.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FONT_SERVICE_FONT_SERVICE_APP_H_
-#define COMPONENTS_FONT_SERVICE_FONT_SERVICE_APP_H_
+#ifndef COMPONENTS_SERVICES_FONT_FONT_SERVICE_APP_H_
+#define COMPONENTS_SERVICES_FONT_FONT_SERVICE_APP_H_
 
 #include <stdint.h>
 #include <vector>
 
 #include "base/macros.h"
-#include "components/font_service/public/interfaces/font_service.mojom.h"
+#include "components/services/font/public/interfaces/font_service.mojom.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "services/service_manager/public/cpp/service.h"
@@ -52,4 +52,4 @@
 
 }  // namespace font_service
 
-#endif  // COMPONENTS_FONT_SERVICE_FONT_SERVICE_APP_H_
+#endif  // COMPONENTS_SERVICES_FONT_FONT_SERVICE_APP_H_
diff --git a/components/font_service/main.cc b/components/services/font/main.cc
similarity index 89%
rename from components/font_service/main.cc
rename to components/services/font/main.cc
index 4fd55f0..6995dab 100644
--- a/components/font_service/main.cc
+++ b/components/services/font/main.cc
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/font_service/font_service_app.h"
 #include "services/service_manager/public/c/main.h"
+#include "components/services/font/font_service_app.h"
 #include "services/service_manager/public/cpp/service_runner.h"
 
 MojoResult ServiceMain(MojoHandle service_request_handle) {
diff --git a/components/font_service/manifest.json b/components/services/font/manifest.json
similarity index 100%
rename from components/font_service/manifest.json
rename to components/services/font/manifest.json
diff --git a/components/font_service/public/cpp/BUILD.gn b/components/services/font/public/cpp/BUILD.gn
similarity index 100%
rename from components/font_service/public/cpp/BUILD.gn
rename to components/services/font/public/cpp/BUILD.gn
diff --git a/components/font_service/public/cpp/font_loader.cc b/components/services/font/public/cpp/font_loader.cc
similarity index 83%
rename from components/font_service/public/cpp/font_loader.cc
rename to components/services/font/public/cpp/font_loader.cc
index 877adb4..618c22f 100644
--- a/components/font_service/public/cpp/font_loader.cc
+++ b/components/services/font/public/cpp/font_loader.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/font_service/public/cpp/font_loader.h"
+#include "components/services/font/public/cpp/font_loader.h"
 
 #include <utility>
 
 #include "base/bind.h"
 #include "base/trace_event/trace_event.h"
-#include "components/font_service/public/cpp/font_service_thread.h"
+#include "components/services/font/public/cpp/font_service_thread.h"
 #include "services/service_manager/public/cpp/connector.h"
 
 namespace font_service {
@@ -38,9 +38,8 @@
 }
 
 SkStreamAsset* FontLoader::openStream(const FontIdentity& identity) {
-  TRACE_EVENT2("font_loader", "FontLoader::openStream",
-               "identity", identity.fID,
-               "name", identity.fString.c_str());
+  TRACE_EVENT2("font_loader", "FontLoader::openStream", "identity",
+               identity.fID, "name", identity.fString.c_str());
   {
     base::AutoLock lock(lock_);
     auto mapped_font_files_it = mapped_font_files_.find(identity.fID);
@@ -59,8 +58,9 @@
   {
     base::AutoLock lock(lock_);
     auto mapped_font_files_it =
-        mapped_font_files_.insert(std::make_pair(mapped_font_file->font_id(),
-                                                 mapped_font_file.get()))
+        mapped_font_files_
+            .insert(std::make_pair(mapped_font_file->font_id(),
+                                   mapped_font_file.get()))
             .first;
     return mapped_font_files_it->second->CreateMemoryStream();
   }
diff --git a/components/font_service/public/cpp/font_loader.h b/components/services/font/public/cpp/font_loader.h
similarity index 87%
rename from components/font_service/public/cpp/font_loader.h
rename to components/services/font/public/cpp/font_loader.h
index d2affa9..7f9d7d2 100644
--- a/components/font_service/public/cpp/font_loader.h
+++ b/components/services/font/public/cpp/font_loader.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FONT_SERVICE_PUBLIC_CPP_FONT_LOADER_H_
-#define COMPONENTS_FONT_SERVICE_PUBLIC_CPP_FONT_LOADER_H_
+#ifndef COMPONENTS_SERVICES_FONT_PUBLIC_CPP_FONT_LOADER_H_
+#define COMPONENTS_SERVICES_FONT_PUBLIC_CPP_FONT_LOADER_H_
 
 #include <stdint.h>
 
@@ -11,8 +11,8 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/synchronization/lock.h"
-#include "components/font_service/public/cpp/mapped_font_file.h"
-#include "components/font_service/public/interfaces/font_service.mojom.h"
+#include "components/services/font/public/cpp/mapped_font_file.h"
+#include "components/services/font/public/interfaces/font_service.mojom.h"
 #include "third_party/skia/include/core/SkStream.h"
 #include "third_party/skia/include/core/SkTypeface.h"
 #include "third_party/skia/include/ports/SkFontConfigInterface.h"
@@ -70,4 +70,4 @@
 
 }  // namespace font_service
 
-#endif  // COMPONENTS_FONT_SERVICE_PUBLIC_CPP_FONT_LOADER_H_
+#endif  // COMPONENTS_SERVICES_FONT_PUBLIC_CPP_FONT_LOADER_H_
diff --git a/components/font_service/public/cpp/font_service_thread.cc b/components/services/font/public/cpp/font_service_thread.cc
similarity index 96%
rename from components/font_service/public/cpp/font_service_thread.cc
rename to components/services/font/public/cpp/font_service_thread.cc
index 4c14737..d1ecf77 100644
--- a/components/font_service/public/cpp/font_service_thread.cc
+++ b/components/services/font/public/cpp/font_service_thread.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/font_service/public/cpp/font_service_thread.h"
+#include "components/services/font/public/cpp/font_service_thread.h"
 
 #include <utility>
 
 #include "base/bind.h"
 #include "base/files/file.h"
 #include "base/synchronization/waitable_event.h"
-#include "components/font_service/public/cpp/mapped_font_file.h"
+#include "components/services/font/public/cpp/mapped_font_file.h"
 
 namespace font_service {
 namespace internal {
@@ -132,8 +132,7 @@
     // behaviour of the current Linux IPC version.
 
     *out_family_name = family_name.data();
-    *out_style = SkFontStyle(style->weight,
-                             style->width,
+    *out_style = SkFontStyle(style->weight, style->width,
                              static_cast<SkFontStyle::Slant>(style->slant));
   }
 
diff --git a/components/font_service/public/cpp/font_service_thread.h b/components/services/font/public/cpp/font_service_thread.h
similarity index 93%
rename from components/font_service/public/cpp/font_service_thread.h
rename to components/services/font/public/cpp/font_service_thread.h
index 6cfc862..2069a29 100644
--- a/components/font_service/public/cpp/font_service_thread.h
+++ b/components/services/font/public/cpp/font_service_thread.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FONT_SERVICE_PUBLIC_CPP_FONT_SERVICE_THREAD_H_
-#define COMPONENTS_FONT_SERVICE_PUBLIC_CPP_FONT_SERVICE_THREAD_H_
+#ifndef COMPONENTS_SERVICES_FONT_PUBLIC_CPP_FONT_SERVICE_THREAD_H_
+#define COMPONENTS_SERVICES_FONT_PUBLIC_CPP_FONT_SERVICE_THREAD_H_
 
 #include <stdint.h>
 
@@ -13,7 +13,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread.h"
-#include "components/font_service/public/interfaces/font_service.mojom.h"
+#include "components/services/font/public/interfaces/font_service.mojom.h"
 #include "third_party/skia/include/core/SkStream.h"
 #include "third_party/skia/include/core/SkTypeface.h"
 #include "third_party/skia/include/ports/SkFontConfigInterface.h"
@@ -114,4 +114,4 @@
 }  // namespace internal
 }  // namespace font_service
 
-#endif  // COMPONENTS_FONT_SERVICE_PUBLIC_CPP_FONT_SERVICE_THREAD_H_
+#endif  // COMPONENTS_SERVICES_FONT_PUBLIC_CPP_FONT_SERVICE_THREAD_H_
diff --git a/components/font_service/public/cpp/mapped_font_file.cc b/components/services/font/public/cpp/mapped_font_file.cc
similarity index 91%
rename from components/font_service/public/cpp/mapped_font_file.cc
rename to components/services/font/public/cpp/mapped_font_file.cc
index f7bf173..98ab1fb 100644
--- a/components/font_service/public/cpp/mapped_font_file.cc
+++ b/components/services/font/public/cpp/mapped_font_file.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/font_service/public/cpp/mapped_font_file.h"
+#include "components/services/font/public/cpp/mapped_font_file.h"
 
 #include <utility>
 
@@ -28,7 +28,7 @@
   DCHECK(mapped_font_file_.IsValid());
   sk_sp<SkData> data =
       SkData::MakeWithProc(mapped_font_file_.data(), mapped_font_file_.length(),
-                          &MappedFontFile::ReleaseProc, this);
+                           &MappedFontFile::ReleaseProc, this);
   if (!data)
     return nullptr;
   AddRef();
diff --git a/components/font_service/public/cpp/mapped_font_file.h b/components/services/font/public/cpp/mapped_font_file.h
similarity index 87%
rename from components/font_service/public/cpp/mapped_font_file.h
rename to components/services/font/public/cpp/mapped_font_file.h
index d4fbdc4..48d169a 100644
--- a/components/font_service/public/cpp/mapped_font_file.h
+++ b/components/services/font/public/cpp/mapped_font_file.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_FONT_SERVICE_PUBLIC_CPP_MAPPED_FONT_FILE_H_
-#define COMPONENTS_FONT_SERVICE_PUBLIC_CPP_MAPPED_FONT_FILE_H_
+#ifndef COMPONENTS_SERVICES_FONT_PUBLIC_CPP_MAPPED_FONT_FILE_H_
+#define COMPONENTS_SERVICES_FONT_PUBLIC_CPP_MAPPED_FONT_FILE_H_
 
 #include <stdint.h>
 
@@ -53,4 +53,4 @@
 }  // namespace internal
 }  // namespace font_service
 
-#endif  // COMPONENTS_FONT_SERVICE_PUBLIC_CPP_MAPPED_FONT_FILE_H_
+#endif  // COMPONENTS_SERVICES_FONT_PUBLIC_CPP_MAPPED_FONT_FILE_H_
diff --git a/components/font_service/public/interfaces/BUILD.gn b/components/services/font/public/interfaces/BUILD.gn
similarity index 100%
rename from components/font_service/public/interfaces/BUILD.gn
rename to components/services/font/public/interfaces/BUILD.gn
diff --git a/components/font_service/public/interfaces/OWNERS b/components/services/font/public/interfaces/OWNERS
similarity index 100%
rename from components/font_service/public/interfaces/OWNERS
rename to components/services/font/public/interfaces/OWNERS
diff --git a/components/font_service/public/interfaces/constants.mojom b/components/services/font/public/interfaces/constants.mojom
similarity index 100%
rename from components/font_service/public/interfaces/constants.mojom
rename to components/services/font/public/interfaces/constants.mojom
diff --git a/components/font_service/public/interfaces/font_service.mojom b/components/services/font/public/interfaces/font_service.mojom
similarity index 100%
rename from components/font_service/public/interfaces/font_service.mojom
rename to components/services/font/public/interfaces/font_service.mojom
diff --git a/components/subresource_filter/content/browser/content_ruleset_service.cc b/components/subresource_filter/content/browser/content_ruleset_service.cc
index dcd08ec..d1c0115 100644
--- a/components/subresource_filter/content/browser/content_ruleset_service.cc
+++ b/components/subresource_filter/content/browser/content_ruleset_service.cc
@@ -6,12 +6,14 @@
 
 #include <utility>
 
+#include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/sequenced_task_runner.h"
 #include "base/task_scheduler/post_task.h"
 #include "components/subresource_filter/content/common/subresource_filter_messages.h"
 #include "components/subresource_filter/core/browser/ruleset_service.h"
+#include "components/subresource_filter/core/browser/subresource_filter_features.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_source.h"
@@ -85,6 +87,14 @@
   DCHECK(ruleset_data.IsValid());
   CloseFileOnFileThread(&ruleset_data_);
 
+  // If Ad Tagging is running, then every request does a lookup and it's
+  // important that we verify the ruleset early on.
+  if (base::FeatureList::IsEnabled(kAdTagging)) {
+    // Even though the handle will immediately be destroyed, it will still
+    // validate the ruleset on its task runner.
+    VerifiedRuleset::Handle ruleset_handle(ruleset_dealer_.get());
+  }
+
   ruleset_data_ = std::move(ruleset_data);
   for (auto it = content::RenderProcessHost::AllHostsIterator(); !it.IsAtEnd();
        it.Advance()) {
diff --git a/components/suggestions/suggestions_service_impl.cc b/components/suggestions/suggestions_service_impl.cc
index 155071f1..e7cfc8d 100644
--- a/components/suggestions/suggestions_service_impl.cc
+++ b/components/suggestions/suggestions_service_impl.cc
@@ -123,7 +123,7 @@
     std::unique_ptr<SuggestionsStore> suggestions_store,
     std::unique_ptr<ImageManager> thumbnail_manager,
     std::unique_ptr<BlacklistStore> blacklist_store,
-    std::unique_ptr<base::TickClock> tick_clock)
+    base::TickClock* tick_clock)
     : identity_manager_(identity_manager),
       sync_service_(sync_service),
       sync_service_observer_(this),
@@ -132,9 +132,9 @@
       suggestions_store_(std::move(suggestions_store)),
       thumbnail_manager_(std::move(thumbnail_manager)),
       blacklist_store_(std::move(blacklist_store)),
-      tick_clock_(std::move(tick_clock)),
-      blacklist_upload_backoff_(&kBlacklistBackoffPolicy, tick_clock_.get()),
-      blacklist_upload_timer_(tick_clock_.get()),
+      tick_clock_(tick_clock),
+      blacklist_upload_backoff_(&kBlacklistBackoffPolicy, tick_clock_),
+      blacklist_upload_timer_(tick_clock_),
       weak_ptr_factory_(this) {
   // |sync_service_| is null if switches::kDisableSync is set (tests use that).
   if (sync_service_) {
diff --git a/components/suggestions/suggestions_service_impl.h b/components/suggestions/suggestions_service_impl.h
index b6ec178..cc20f12f 100644
--- a/components/suggestions/suggestions_service_impl.h
+++ b/components/suggestions/suggestions_service_impl.h
@@ -63,7 +63,7 @@
                          std::unique_ptr<SuggestionsStore> suggestions_store,
                          std::unique_ptr<ImageManager> thumbnail_manager,
                          std::unique_ptr<BlacklistStore> blacklist_store,
-                         std::unique_ptr<base::TickClock> tick_clock);
+                         base::TickClock* tick_clock);
   ~SuggestionsServiceImpl() override;
 
   // SuggestionsService implementation.
@@ -195,7 +195,7 @@
   // The local cache for temporary blacklist, until uploaded to the server.
   std::unique_ptr<BlacklistStore> blacklist_store_;
 
-  std::unique_ptr<base::TickClock> tick_clock_;
+  base::TickClock* tick_clock_;
 
   // Backoff for scheduling blacklist upload tasks.
   net::BackoffEntry blacklist_upload_backoff_;
diff --git a/components/suggestions/suggestions_service_impl_unittest.cc b/components/suggestions/suggestions_service_impl_unittest.cc
index 07bc68d..8e88e9f 100644
--- a/components/suggestions/suggestions_service_impl_unittest.cc
+++ b/components/suggestions/suggestions_service_impl_unittest.cc
@@ -171,7 +171,7 @@
         request_context_.get(), base::WrapUnique(test_suggestions_store_),
         base::WrapUnique(mock_thumbnail_manager_),
         base::WrapUnique(mock_blacklist_store_),
-        task_runner_->DeprecatedGetMockTickClock());
+        task_runner_->GetMockTickClock());
   }
 
   GURL GetCurrentlyQueriedUrl() {
diff --git a/components/suggestions/suggestions_store.cc b/components/suggestions/suggestions_store.cc
index 002dedd..4332ce3 100644
--- a/components/suggestions/suggestions_store.cc
+++ b/components/suggestions/suggestions_store.cc
@@ -20,7 +20,7 @@
 namespace suggestions {
 
 SuggestionsStore::SuggestionsStore(PrefService* profile_prefs)
-    : pref_service_(profile_prefs), clock_(new base::DefaultClock()) {
+    : pref_service_(profile_prefs), clock_(base::DefaultClock::GetInstance()) {
   DCHECK(profile_prefs);
 }
 
@@ -29,9 +29,8 @@
 
 SuggestionsStore::~SuggestionsStore() {}
 
-void SuggestionsStore::SetClockForTesting(
-    std::unique_ptr<base::Clock> test_clock) {
-  this->clock_ = std::move(test_clock);
+void SuggestionsStore::SetClockForTesting(base::Clock* test_clock) {
+  this->clock_ = test_clock;
 }
 
 bool SuggestionsStore::LoadSuggestions(SuggestionsProfile* suggestions) {
diff --git a/components/suggestions/suggestions_store.h b/components/suggestions/suggestions_store.h
index 8d726e5..35f1095c 100644
--- a/components/suggestions/suggestions_store.h
+++ b/components/suggestions/suggestions_store.h
@@ -42,7 +42,7 @@
   // Register SuggestionsStore related prefs in the Profile prefs.
   static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
 
-  void SetClockForTesting(std::unique_ptr<base::Clock> clock);
+  void SetClockForTesting(base::Clock* clock);
 
  protected:
   // Test seam. For simplicity of mock creation.
@@ -51,8 +51,8 @@
  private:
   // The pref service used to persist the suggestions data.
   PrefService* pref_service_;
-  // Can be set for testing.
-  std::unique_ptr<base::Clock> clock_;
+  // Can be overridden for testing.
+  base::Clock* clock_;
 
   DISALLOW_COPY_AND_ASSIGN(SuggestionsStore);
 
diff --git a/components/suggestions/suggestions_store_unittest.cc b/components/suggestions/suggestions_store_unittest.cc
index b39ad74..602d463 100644
--- a/components/suggestions/suggestions_store_unittest.cc
+++ b/components/suggestions/suggestions_store_unittest.cc
@@ -89,16 +89,14 @@
     SuggestionsStore::RegisterProfilePrefs(pref_service_->registry());
     suggestions_store_.reset(new SuggestionsStore(pref_service_.get()));
 
-    base::SimpleTestClock* test_clock(new base::SimpleTestClock());
-    current_time = base::Time::FromInternalValue(13063394337546738);
-    test_clock->SetNow(current_time);
-    suggestions_store_->SetClockForTesting(base::WrapUnique(test_clock));
+    test_clock_.SetNow(base::Time::FromInternalValue(13063394337546738));
+    suggestions_store_->SetClockForTesting(&test_clock_);
   }
 
  protected:
   std::unique_ptr<sync_preferences::TestingPrefServiceSyncable> pref_service_;
   std::unique_ptr<SuggestionsStore> suggestions_store_;
-  base::Time current_time;
+  base::SimpleTestClock test_clock_;
 
   DISALLOW_COPY_AND_ASSIGN(SuggestionsStoreTest);
 };
@@ -106,7 +104,7 @@
 // Tests LoadSuggestions function to filter expired suggestions.
 TEST_F(SuggestionsStoreTest, LoadAllExpired) {
   SuggestionsProfile suggestions =
-      CreateTestSuggestionsProfileWithExpiry(current_time, 5, 0);
+      CreateTestSuggestionsProfileWithExpiry(test_clock_.Now(), 5, 0);
   SuggestionsProfile filtered_suggestions;
 
   // Store and load. Expired suggestions should not be loaded.
@@ -118,7 +116,7 @@
 // Tests LoadSuggestions function to filter expired suggestions.
 TEST_F(SuggestionsStoreTest, LoadValidAndExpired) {
   SuggestionsProfile suggestions =
-      CreateTestSuggestionsProfileWithExpiry(current_time, 5, 3);
+      CreateTestSuggestionsProfileWithExpiry(test_clock_.Now(), 5, 3);
   SuggestionsProfile filtered_suggestions;
 
   // Store and load. Expired suggestions should not be loaded.
@@ -130,7 +128,7 @@
 // Tests LoadSuggestions function to filter expired suggestions.
 TEST_F(SuggestionsStoreTest, CheckStoreAfterLoadExpired) {
   SuggestionsProfile suggestions =
-      CreateTestSuggestionsProfileWithExpiry(current_time, 5, 3);
+      CreateTestSuggestionsProfileWithExpiry(test_clock_.Now(), 5, 3);
   SuggestionsProfile filtered_suggestions;
 
   // Store and load. Expired suggestions should not be loaded.
diff --git a/components/unzip_service/public/cpp/BUILD.gn b/components/unzip_service/public/cpp/BUILD.gn
index 83bc8ae..a11aebd 100644
--- a/components/unzip_service/public/cpp/BUILD.gn
+++ b/components/unzip_service/public/cpp/BUILD.gn
@@ -16,3 +16,18 @@
     "//services/service_manager/public/cpp",
   ]
 }
+
+static_library("test_support") {
+  testonly = true
+  sources = [
+    "test_unzip_service.cc",
+    "test_unzip_service.h",
+  ]
+
+  deps = [
+    ":cpp",
+    "//base",
+    "//components/unzip_service:lib",
+    "//services/service_manager/public/cpp/test:test_support",
+  ]
+}
diff --git a/components/unzip_service/public/cpp/test_unzip_service.cc b/components/unzip_service/public/cpp/test_unzip_service.cc
new file mode 100644
index 0000000..141fb41
--- /dev/null
+++ b/components/unzip_service/public/cpp/test_unzip_service.cc
@@ -0,0 +1,41 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/unzip_service/public/cpp/test_unzip_service.h"
+
+namespace unzip {
+
+CrashyUnzipService::CrashyUnzipService() = default;
+
+CrashyUnzipService::~CrashyUnzipService() = default;
+
+// service_manager::Service implmentation:
+void CrashyUnzipService::OnStart() {}
+
+void CrashyUnzipService::OnBindInterface(
+    const service_manager::BindSourceInfo& source_info,
+    const std::string& interface_name,
+    mojo::ScopedMessagePipeHandle interface_pipe) {
+  DCHECK(interface_name == mojom::Unzipper::Name_);
+  DCHECK(!unzipper_binding_);
+  unzipper_binding_ = std::make_unique<mojo::Binding<mojom::Unzipper>>(
+      this, mojom::UnzipperRequest(std::move(interface_pipe)));
+}
+
+// unzip::mojom::Unzipper:
+void CrashyUnzipService::Unzip(base::File zip_file,
+                               filesystem::mojom::DirectoryPtr output_dir,
+                               UnzipCallback callback) {
+  unzipper_binding_.reset();
+}
+
+void CrashyUnzipService::UnzipWithFilter(
+    base::File zip_file,
+    filesystem::mojom::DirectoryPtr output_dir,
+    mojom::UnzipFilterPtr filter,
+    UnzipWithFilterCallback callback) {
+  unzipper_binding_.reset();
+}
+
+}  // namespace unzip
diff --git a/components/unzip_service/public/cpp/test_unzip_service.h b/components/unzip_service/public/cpp/test_unzip_service.h
new file mode 100644
index 0000000..52d07c9
--- /dev/null
+++ b/components/unzip_service/public/cpp/test_unzip_service.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 COMPONENTS_UNZIP_SERVICE_PUBLIC_CPP_TEST_UNZIP_SERVICE_H_
+#define COMPONENTS_UNZIP_SERVICE_PUBLIC_CPP_TEST_UNZIP_SERVICE_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "components/unzip_service/public/interfaces/unzipper.mojom.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "services/service_manager/public/cpp/service.h"
+
+namespace unzip {
+
+// An implementation of the UnzipService that closes the connection when
+// a call is made on the Unzipper interface.
+// Can be used with a TestConnectorFactory to simulate crashes in the service
+// while processing a call.
+class CrashyUnzipService : public service_manager::Service,
+                           public mojom::Unzipper {
+ public:
+  CrashyUnzipService();
+  ~CrashyUnzipService() override;
+
+  // service_manager::Service:
+  void OnStart() override;
+  void OnBindInterface(const service_manager::BindSourceInfo& source_info,
+                       const std::string& interface_name,
+                       mojo::ScopedMessagePipeHandle interface_pipe) override;
+
+  // unzip::mojom::Unzipper:
+  void Unzip(base::File zip_file,
+             filesystem::mojom::DirectoryPtr output_dir,
+             UnzipCallback callback) override;
+  void UnzipWithFilter(base::File zip_file,
+                       filesystem::mojom::DirectoryPtr output_dir,
+                       mojom::UnzipFilterPtr filter,
+                       UnzipWithFilterCallback callback) override;
+
+ private:
+  std::unique_ptr<mojo::Binding<mojom::Unzipper>> unzipper_binding_;
+
+  DISALLOW_COPY_AND_ASSIGN(CrashyUnzipService);
+};
+
+}  // namespace unzip
+
+#endif  // COMPONENTS_UNZIP_SERVICE_PUBLIC_CPP_TEST_UNZIP_SERVICE_H_
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index 1e817f8..834df5e 100644
--- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -49,6 +49,7 @@
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/download_test_observer.h"
+#include "content/public/test/slow_download_http_response.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "content/shell/browser/shell.h"
 #include "content/shell/browser/shell_browser_context.h"
@@ -58,9 +59,7 @@
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/cert_test_util.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
-#include "net/test/test_data_directory.h"
-#include "net/test/url_request/url_request_mock_http_job.h"
-#include "net/test/url_request/url_request_slow_download_job.h"
+#include "services/network/public/cpp/features.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -2507,7 +2506,7 @@
 class DownloadCreateObserver : DownloadManager::Observer {
  public:
   explicit DownloadCreateObserver(DownloadManager* manager)
-      : manager_(manager), item_(nullptr) {
+      : manager_(manager), item_(nullptr), received_item_response_(false) {
     manager_->AddObserver(this);
   }
 
@@ -2525,16 +2524,26 @@
 
   void OnDownloadCreated(DownloadManager* manager,
                          download::DownloadItem* download) override {
+    received_item_response_ = true;
+
     if (!item_)
       item_ = download;
 
-    if (!completion_closure_.is_null())
-      base::ResetAndReturn(&completion_closure_).Run();
+    if (completion_closure_)
+      std::move(completion_closure_).Run();
+  }
+
+  void OnDownloadDropped(DownloadManager* manager) override {
+    received_item_response_ = true;
+
+    item_ = nullptr;
+    if (completion_closure_)
+      std::move(completion_closure_).Run();
   }
 
   download::DownloadItem* WaitForFinished() {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
-    if (!item_) {
+    if (!received_item_response_) {
       base::RunLoop run_loop;
       completion_closure_ = run_loop.QuitClosure();
       run_loop.Run();
@@ -2545,6 +2554,7 @@
  private:
   DownloadManager* manager_;
   download::DownloadItem* item_;
+  bool received_item_response_;
   base::Closure completion_closure_;
 };
 
@@ -2568,14 +2578,8 @@
     manager->SetDelegate(test_delegate_.get());
     test_delegate_->SetDownloadManager(manager);
 
-    BrowserThread::PostTask(
-        BrowserThread::IO, FROM_HERE,
-        base::BindOnce(&net::URLRequestSlowDownloadJob::AddUrlHandler));
-    base::FilePath mock_base(GetTestFilePath("download", ""));
-
-    BrowserThread::PostTask(
-        BrowserThread::IO, FROM_HERE,
-        base::BindOnce(&net::URLRequestMockHTTPJob::AddUrlHandlers, mock_base));
+    embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
+        &content::SlowDownloadHttpResponse::HandleSlowDownloadRequest));
     ASSERT_TRUE(embedded_test_server()->Start());
   }
 
@@ -2621,13 +2625,7 @@
   }
 
   bool EnsureNoPendingDownloads() {
-    bool result = true;
-    BrowserThread::PostTask(
-        BrowserThread::IO, FROM_HERE,
-        base::BindOnce(&EnsureNoPendingDownloadJobsOnIO, &result));
-    base::RunLoop().Run();
-    return result &&
-           (CountingDownloadFile::GetNumberActiveFilesFromFileThread() == 0);
+    return CountingDownloadFile::GetNumberActiveFilesFromFileThread() == 0;
   }
 
   // Checks that |path| is has |file_size| bytes, and matches the |value|
@@ -2671,14 +2669,6 @@
   }
 
  private:
-  static void EnsureNoPendingDownloadJobsOnIO(bool* result) {
-    if (net::URLRequestSlowDownloadJob::NumberOutstandingRequests())
-      *result = false;
-    BrowserThread::PostTask(
-        BrowserThread::UI, FROM_HERE,
-        base::MessageLoop::current()->QuitWhenIdleClosure());
-  }
-
   // Location of the downloads directory for these tests
   base::ScopedTempDir downloads_directory_;
   std::unique_ptr<TestShellDownloadManagerDelegate> test_delegate_;
@@ -2697,8 +2687,7 @@
   // Create a download, wait until it's started, and confirm
   // we're in the expected state.
   download::DownloadItem* download = StartDownloadAndReturnItem(
-      shell(),
-      GURL(net::URLRequestMockHTTPJob::GetMockUrl("download-test.lib")));
+      shell(), embedded_test_server()->GetURL("/download/download-test.lib"));
   ASSERT_EQ(download::DownloadItem::IN_PROGRESS, download->GetState());
 
   WaitForCompletion(download);
@@ -2716,7 +2705,8 @@
   // Create a download, wait until it's started, and confirm
   // we're in the expected state.
   download::DownloadItem* download = StartDownloadAndReturnItem(
-      shell(), GURL(net::URLRequestSlowDownloadJob::kUnknownSizeUrl));
+      shell(), embedded_test_server()->GetURL(
+                   content::SlowDownloadHttpResponse::kUnknownSizeUrl));
   ASSERT_EQ(download::DownloadItem::IN_PROGRESS, download->GetState());
 
   // Cancel the download and wait for download system quiesce.
@@ -2738,9 +2728,10 @@
   SetDownloadBehavior("deny");
   // Create a download, wait and confirm it was cancelled.
   download::DownloadItem* download = StartDownloadAndReturnItem(
-      shell(),
-      GURL(net::URLRequestMockHTTPJob::GetMockUrl("download-test.lib")));
-  EnsureNoPendingDownloads();
+      shell(), embedded_test_server()->GetURL("/download/download-test.lib"));
+  DownloadTestFlushObserver flush_observer(DownloadManagerForShell(shell()));
+  flush_observer.WaitForFlush();
+  EXPECT_TRUE(EnsureNoPendingDownloads());
   ASSERT_EQ(download::DownloadItem::CANCELLED, download->GetState());
 }
 
@@ -2755,7 +2746,8 @@
   // Create a download, wait until it's started, and confirm
   // we're in the expected state.
   download::DownloadItem* download = StartDownloadAndReturnItem(
-      shell(), GURL(net::URLRequestSlowDownloadJob::kUnknownSizeUrl));
+      shell(), embedded_test_server()->GetURL(
+                   content::SlowDownloadHttpResponse::kUnknownSizeUrl));
   ASSERT_EQ(download::DownloadItem::IN_PROGRESS, download->GetState());
 
   // Cancel the download and wait for download system quiesce.
@@ -2779,10 +2771,17 @@
   SetDownloadBehavior("default");
   // Create a download, wait and confirm it was cancelled.
   download::DownloadItem* download = StartDownloadAndReturnItem(
-      shell(),
-      GURL(net::URLRequestMockHTTPJob::GetMockUrl("download-test.lib")));
-  EnsureNoPendingDownloads();
-  ASSERT_EQ(download::DownloadItem::CANCELLED, download->GetState());
+      shell(), embedded_test_server()->GetURL("/download/download-test.lib"));
+  DownloadTestFlushObserver flush_observer(DownloadManagerForShell(shell()));
+  flush_observer.WaitForFlush();
+  EXPECT_TRUE(EnsureNoPendingDownloads());
+  if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+    // The download manager will intercept the download navigation and drop it
+    // since we have set the delegate to null.
+    EXPECT_EQ(nullptr, download);
+  } else {
+    EXPECT_EQ(download::DownloadItem::CANCELLED, download->GetState());
+  }
 }
 
 // Check that download logic is reset when creating a new target.
@@ -2799,7 +2798,7 @@
   // Create a download, wait and confirm it wasn't cancelled.
   download::DownloadItem* download = StartDownloadAndReturnItem(
       new_window,
-      GURL(net::URLRequestMockHTTPJob::GetMockUrl("download-test.lib")));
+      embedded_test_server()->GetURL("/download/download-test.lib"));
   WaitForCompletion(download);
   ASSERT_EQ(download::DownloadItem::COMPLETE, download->GetState());
 }
@@ -2816,13 +2815,14 @@
   // Create a download, wait until it's started, and confirm
   // we're in the expected state.
   download::DownloadItem* download1 = StartDownloadAndReturnItem(
-      shell(), GURL(net::URLRequestSlowDownloadJob::kUnknownSizeUrl));
+      shell(), embedded_test_server()->GetURL(
+                   content::SlowDownloadHttpResponse::kUnknownSizeUrl));
   ASSERT_EQ(download::DownloadItem::IN_PROGRESS, download1->GetState());
 
   NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
   SetDownloadBehavior("allow", "download2");
   // Start the second download and wait until it's done.
-  GURL url(net::URLRequestMockHTTPJob::GetMockUrl("download-test.lib"));
+  GURL url(embedded_test_server()->GetURL("/download/download-test.lib"));
   download::DownloadItem* download2 = StartDownloadAndReturnItem(shell(), url);
   WaitForCompletion(download2);
 
@@ -2832,7 +2832,8 @@
   // Allow the first request to finish.
   std::unique_ptr<DownloadTestObserver> observer2(CreateWaiter(shell(), 1));
   NavigateToURL(shell(),
-                GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl));
+                embedded_test_server()->GetURL(
+                    content::SlowDownloadHttpResponse::kFinishDownloadUrl));
   observer2->WaitForFinished();  // Wait for the third request.
   EXPECT_EQ(
       1u, observer2->NumDownloadsSeenInState(download::DownloadItem::COMPLETE));
@@ -2846,8 +2847,8 @@
   // source file.
   base::FilePath file1(download1->GetTargetFilePath());
   ASSERT_EQ(file1.DirName().MaybeAsASCII(), "download1");
-  size_t file_size1 = net::URLRequestSlowDownloadJob::kFirstDownloadSize +
-                      net::URLRequestSlowDownloadJob::kSecondDownloadSize;
+  size_t file_size1 = content::SlowDownloadHttpResponse::kFirstDownloadSize +
+                      content::SlowDownloadHttpResponse::kSecondDownloadSize;
   std::string expected_contents(file_size1, '*');
   ASSERT_TRUE(VerifyFile(file1, expected_contents, file_size1));
 
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc
index 4935952..2474afd 100644
--- a/content/browser/download/download_browsertest.cc
+++ b/content/browser/download/download_browsertest.cc
@@ -32,6 +32,7 @@
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "components/download/public/common/download_danger_type.h"
+#include "components/download/public/common/download_features.h"
 #include "components/download/public/common/download_task_runner.h"
 #include "content/browser/download/download_file_factory.h"
 #include "content/browser/download/download_file_impl.h"
@@ -42,7 +43,6 @@
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/download_request_utils.h"
 #include "content/public/browser/resource_throttle.h"
-#include "content/public/common/content_features.h"
 #include "content/public/common/content_paths.h"
 #include "content/public/common/webplugininfo.h"
 #include "content/public/test/browser_test_utils.h"
@@ -915,7 +915,7 @@
         {content::kParallelRequestDelayFinchKey, "0"},
         {content::kParallelRequestRemainingTimeFinchKey, "0"}};
     scoped_feature_list_.InitAndEnableFeatureWithParameters(
-        features::kParallelDownloading, params);
+        download::features::kParallelDownloading, params);
   }
 
   ~ParallelDownloadTest() override {}
@@ -971,7 +971,8 @@
       const download::DownloadItem::ReceivedSlices& received_slices,
       int64_t total_length,
       size_t expected_request_count) {
-    EXPECT_TRUE(base::FeatureList::IsEnabled(features::kParallelDownloading));
+    EXPECT_TRUE(
+        base::FeatureList::IsEnabled(download::features::kParallelDownloading));
     GURL url = TestDownloadHttpResponse::GetNextURLForDownload();
     GURL server_url = embedded_test_server()->GetURL(url.host(), url.path());
     TestDownloadHttpResponse::Parameters parameters;
@@ -1007,7 +1008,8 @@
 
   // Verifies parallel download completion.
   void RunCompletionTest(TestDownloadHttpResponse::Parameters& parameters) {
-    EXPECT_TRUE(base::FeatureList::IsEnabled(features::kParallelDownloading));
+    EXPECT_TRUE(
+        base::FeatureList::IsEnabled(download::features::kParallelDownloading));
 
     GURL url = TestDownloadHttpResponse::GetNextURLForDownload();
     GURL server_url = embedded_test_server()->GetURL(url.host(), url.path());
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index 33efd7d..5fcb455 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -885,8 +885,11 @@
     net::CertStatus cert_status,
     int frame_tree_node_id) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  if (!delegate_)
+  if (!delegate_) {
+    for (auto& observer : observers_)
+      observer.OnDownloadDropped(this);
     return;
+  }
 
   const GURL& url = resource_request->url;
   const std::string& method = resource_request->method;
@@ -1133,8 +1136,11 @@
     net::CertStatus cert_status,
     network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
     bool is_download_allowed) {
-  if (!is_download_allowed)
+  if (!is_download_allowed) {
+    for (auto& observer : observers_)
+      observer.OnDownloadDropped(this);
     return;
+  }
 
   int render_process_id = -1;
   int render_frame_id = -1;
diff --git a/content/browser/download/parallel_download_utils.cc b/content/browser/download/parallel_download_utils.cc
index 1204be29..f3f508ae 100644
--- a/content/browser/download/parallel_download_utils.cc
+++ b/content/browser/download/parallel_download_utils.cc
@@ -7,8 +7,8 @@
 #include "base/metrics/field_trial_params.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/time/time.h"
+#include "components/download/public/common/download_features.h"
 #include "components/download/public/common/download_save_info.h"
-#include "content/public/common/content_features.h"
 
 namespace content {
 
@@ -157,7 +157,7 @@
 
 int64_t GetMinSliceSizeConfig() {
   std::string finch_value = base::GetFieldTrialParamValueByFeature(
-      features::kParallelDownloading, kMinSliceSizeFinchKey);
+      download::features::kParallelDownloading, kMinSliceSizeFinchKey);
   int64_t result;
   return base::StringToInt64(finch_value, &result)
              ? result
@@ -166,7 +166,7 @@
 
 int GetParallelRequestCountConfig() {
   std::string finch_value = base::GetFieldTrialParamValueByFeature(
-      features::kParallelDownloading, kParallelRequestCountFinchKey);
+      download::features::kParallelDownloading, kParallelRequestCountFinchKey);
   int result;
   return base::StringToInt(finch_value, &result) ? result
                                                  : kParallelRequestCount;
@@ -174,7 +174,7 @@
 
 base::TimeDelta GetParallelRequestDelayConfig() {
   std::string finch_value = base::GetFieldTrialParamValueByFeature(
-      features::kParallelDownloading, kParallelRequestDelayFinchKey);
+      download::features::kParallelDownloading, kParallelRequestDelayFinchKey);
   int64_t time_ms = 0;
   return base::StringToInt64(finch_value, &time_ms)
              ? base::TimeDelta::FromMilliseconds(time_ms)
@@ -183,7 +183,8 @@
 
 base::TimeDelta GetParallelRequestRemainingTimeConfig() {
   std::string finch_value = base::GetFieldTrialParamValueByFeature(
-      features::kParallelDownloading, kParallelRequestRemainingTimeFinchKey);
+      download::features::kParallelDownloading,
+      kParallelRequestRemainingTimeFinchKey);
   int time_in_seconds = 0;
   return base::StringToInt(finch_value, &time_in_seconds)
              ? base::TimeDelta::FromSeconds(time_in_seconds)
@@ -214,11 +215,12 @@
 
 bool IsParallelDownloadEnabled() {
   bool feature_enabled =
-      base::FeatureList::IsEnabled(features::kParallelDownloading);
+      base::FeatureList::IsEnabled(download::features::kParallelDownloading);
   // Disabled when |kEnableParallelDownloadFinchKey| Finch config is set to
   // false.
   bool enabled_parameter = GetFieldTrialParamByFeatureAsBool(
-      features::kParallelDownloading, kEnableParallelDownloadFinchKey, true);
+      download::features::kParallelDownloading, kEnableParallelDownloadFinchKey,
+      true);
   return feature_enabled && enabled_parameter;
 }
 
diff --git a/content/browser/download/parallel_download_utils_unittest.cc b/content/browser/download/parallel_download_utils_unittest.cc
index de977873..53ac459d 100644
--- a/content/browser/download/parallel_download_utils_unittest.cc
+++ b/content/browser/download/parallel_download_utils_unittest.cc
@@ -9,11 +9,11 @@
 
 #include "base/strings/string_number_conversions.h"
 #include "base/test/scoped_feature_list.h"
+#include "components/download/public/common/download_features.h"
 #include "components/download/public/common/download_save_info.h"
 #include "content/browser/byte_stream.h"
 #include "content/browser/download/byte_stream_input_stream.h"
 #include "content/public/browser/download_manager.h"
-#include "content/public/common/content_features.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -203,7 +203,7 @@
       {content::kParallelRequestDelayFinchKey, "2000"},
       {content::kParallelRequestRemainingTimeFinchKey, "3"}};
   feature_list.InitAndEnableFeatureWithParameters(
-      features::kParallelDownloading, params);
+      download::features::kParallelDownloading, params);
   EXPECT_TRUE(IsParallelDownloadEnabled());
   EXPECT_EQ(GetMinSliceSizeConfig(), 1234);
   EXPECT_EQ(GetParallelRequestCountConfig(), 6);
@@ -216,7 +216,7 @@
 // feature.
 TEST_F(ParallelDownloadUtilsTest, FinchConfigDisabled) {
   base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndDisableFeature(features::kParallelDownloading);
+  feature_list.InitAndDisableFeature(download::features::kParallelDownloading);
   EXPECT_FALSE(IsParallelDownloadEnabled());
 }
 
@@ -229,7 +229,7 @@
         {content::kMinSliceSizeFinchKey, "4321"},
         {content::kEnableParallelDownloadFinchKey, "false"}};
     feature_list.InitAndEnableFeatureWithParameters(
-        features::kParallelDownloading, params);
+        download::features::kParallelDownloading, params);
     // Use |enable_parallel_download| to disable parallel download in enabled
     // experiment group.
     EXPECT_FALSE(IsParallelDownloadEnabled());
@@ -241,7 +241,7 @@
         {content::kMinSliceSizeFinchKey, "4321"},
         {content::kEnableParallelDownloadFinchKey, "true"}};
     feature_list.InitAndEnableFeatureWithParameters(
-        features::kParallelDownloading, params);
+        download::features::kParallelDownloading, params);
     // Disable only if |enable_parallel_download| sets to false.
     EXPECT_TRUE(IsParallelDownloadEnabled());
     EXPECT_EQ(GetMinSliceSizeConfig(), 4321);
@@ -251,7 +251,7 @@
     std::map<std::string, std::string> params = {
         {content::kMinSliceSizeFinchKey, "4321"}};
     feature_list.InitAndEnableFeatureWithParameters(
-        features::kParallelDownloading, params);
+        download::features::kParallelDownloading, params);
     // Empty |enable_parallel_download| in an enabled experiment group will have
     // no impact.
     EXPECT_TRUE(IsParallelDownloadEnabled());
diff --git a/content/browser/find_request_manager_browsertest.cc b/content/browser/find_request_manager_browsertest.cc
index 5e89155..75d16cd 100644
--- a/content/browser/find_request_manager_browsertest.cc
+++ b/content/browser/find_request_manager_browsertest.cc
@@ -230,12 +230,8 @@
 // Basic test that a search result is actually brought into view.
 IN_PROC_BROWSER_TEST_P(FindRequestManagerTest, ScrollAndZoomIntoView) {
   LoadAndWait("/find_in_page_desktop.html");
-  if (GetParam()) {
-    // TODO(bokan): The OOPIF version of this test is currently broken due to
-    // bug https://crbug.com/810291.
-    // MakeChildFrameCrossProcess();
-    return;
-  }
+  if (GetParam())
+    MakeChildFrameCrossProcess();
 
   FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                             ->GetFrameTree()
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 39057c5..450ff21f 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -2044,7 +2044,6 @@
 void RenderFrameHostImpl::OnRunJavaScriptDialog(
     const base::string16& message,
     const base::string16& default_prompt,
-    const GURL& frame_url,
     JavaScriptDialogType dialog_type,
     IPC::Message* reply_msg) {
   if (dialog_type == JavaScriptDialogType::JAVASCRIPT_DIALOG_TYPE_ALERT)
@@ -2071,7 +2070,6 @@
 }
 
 void RenderFrameHostImpl::OnRunBeforeUnloadConfirm(
-    const GURL& frame_url,
     bool is_reload,
     IPC::Message* reply_msg) {
   TRACE_EVENT1("navigation", "RenderFrameHostImpl::OnRunBeforeUnloadConfirm",
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 95fa30f..b62576bc 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -790,12 +790,9 @@
   void OnVisualStateResponse(uint64_t id);
   void OnRunJavaScriptDialog(const base::string16& message,
                              const base::string16& default_prompt,
-                             const GURL& frame_url,
                              JavaScriptDialogType dialog_type,
                              IPC::Message* reply_msg);
-  void OnRunBeforeUnloadConfirm(const GURL& frame_url,
-                                bool is_reload,
-                                IPC::Message* reply_msg);
+  void OnRunBeforeUnloadConfirm(bool is_reload, IPC::Message* reply_msg);
   void OnRunFileChooser(const FileChooserParams& params);
   void OnTextSurroundingSelectionResponse(const base::string16& content,
                                           uint32_t start_offset,
diff --git a/content/browser/loader/mojo_async_resource_handler_unittest.cc b/content/browser/loader/mojo_async_resource_handler_unittest.cc
index 7e49dc5..6927e1f7 100644
--- a/content/browser/loader/mojo_async_resource_handler_unittest.cc
+++ b/content/browser/loader/mojo_async_resource_handler_unittest.cc
@@ -132,13 +132,6 @@
     ADD_FAILURE() << "DownloadStarting should not be called.";
   }
 
-  bool HandleExternalProtocol(
-      const GURL& url,
-      ResourceRequestInfo* resource_request_info) override {
-    ADD_FAILURE() << "HandleExternalProtocol should not be called.";
-    return false;
-  }
-
   bool ShouldInterceptResourceAsStream(net::URLRequest* request,
                                        const std::string& mime_type,
                                        GURL* origin,
diff --git a/content/browser/loader/navigation_url_loader_network_service.cc b/content/browser/loader/navigation_url_loader_network_service.cc
index a3322f6b..126eda7f 100644
--- a/content/browser/loader/navigation_url_loader_network_service.cc
+++ b/content/browser/loader/navigation_url_loader_network_service.cc
@@ -255,6 +255,14 @@
   return new_request;
 }
 
+// Called for requests that we don't have a URLLoaderFactory for.
+void UnknownSchemeCallback(bool handled_externally,
+                           network::mojom::URLLoaderRequest request,
+                           network::mojom::URLLoaderClientPtr client) {
+  client->OnComplete(network::URLLoaderCompletionStatus(
+      handled_externally ? net::ERR_ABORTED : net::ERR_UNKNOWN_URL_SCHEME));
+}
+
 }  // namespace
 
 // Kept around during the lifetime of the navigation request, and is
@@ -277,6 +285,7 @@
       base::Optional<std::string> suggested_filename,
       network::mojom::URLLoaderFactoryRequest proxied_factory_request,
       network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info,
+      std::set<std::string> known_schemes,
       const base::WeakPtr<NavigationURLLoaderNetworkService>& owner)
       : handlers_(std::move(initial_handlers)),
         resource_request_(std::move(resource_request)),
@@ -289,6 +298,7 @@
         response_loader_binding_(this),
         proxied_factory_request_(std::move(proxied_factory_request)),
         proxied_factory_info_(std::move(proxied_factory_info)),
+        known_schemes_(std::move(known_schemes)),
         weak_factory_(this) {}
 
   ~URLLoaderRequestController() override {
@@ -575,18 +585,31 @@
           default_url_loader_factory_getter_->GetBlobFactory());
     } else if (!IsURLHandledByNetworkService(resource_request_->url) &&
                !resource_request_->url.SchemeIs(url::kDataScheme)) {
-      network::mojom::URLLoaderFactoryPtr& non_network_factory =
-          non_network_url_loader_factories_[resource_request_->url.scheme()];
-      if (!non_network_factory.is_bound()) {
-        BrowserThread::PostTask(
-            BrowserThread::UI, FROM_HERE,
-            base::BindOnce(&NavigationURLLoaderNetworkService ::
-                               BindNonNetworkURLLoaderFactoryRequest,
-                           owner_, frame_tree_node_id_, resource_request_->url,
-                           mojo::MakeRequest(&non_network_factory)));
+      if (known_schemes_.find(resource_request_->url.scheme()) ==
+          known_schemes_.end()) {
+        bool handled = GetContentClient()->browser()->HandleExternalProtocol(
+            resource_request_->url, web_contents_getter_,
+            ChildProcessHost::kInvalidUniqueID, navigation_ui_data_.get(),
+            resource_request_->resource_type == RESOURCE_TYPE_MAIN_FRAME,
+            static_cast<ui::PageTransition>(resource_request_->transition_type),
+            resource_request_->has_user_gesture);
+        factory = base::MakeRefCounted<SingleRequestURLLoaderFactory>(
+            base::BindOnce(UnknownSchemeCallback, handled));
+      } else {
+        network::mojom::URLLoaderFactoryPtr& non_network_factory =
+            non_network_url_loader_factories_[resource_request_->url.scheme()];
+        if (!non_network_factory.is_bound()) {
+          BrowserThread::PostTask(
+              BrowserThread::UI, FROM_HERE,
+              base::BindOnce(&NavigationURLLoaderNetworkService ::
+                                 BindNonNetworkURLLoaderFactoryRequest,
+                             owner_, frame_tree_node_id_,
+                             resource_request_->url,
+                             mojo::MakeRequest(&non_network_factory)));
+        }
+        factory = base::MakeRefCounted<WeakWrapperSharedURLLoaderFactory>(
+            non_network_factory.get());
       }
-      factory = base::MakeRefCounted<WeakWrapperSharedURLLoaderFactory>(
-          non_network_factory.get());
     } else {
       default_loader_used_ = true;
 
@@ -927,6 +950,10 @@
   network::mojom::URLLoaderFactoryRequest proxied_factory_request_;
   network::mojom::URLLoaderFactoryPtrInfo proxied_factory_info_;
 
+  // The schemes that this loader can use. For anything else we'll try external
+  // protocol handlers.
+  std::set<std::string> known_schemes_;
+
   base::WeakPtrFactory<URLLoaderRequestController> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController);
@@ -976,7 +1003,7 @@
         request_info->begin_params->initiator_origin,
         request_info->common_params.suggested_filename,
         /* proxied_url_loader_factory_request */ nullptr,
-        /* proxied_url_loader_factory_info */ nullptr,
+        /* proxied_url_loader_factory_info */ nullptr, std::set<std::string>(),
         weak_factory_.GetWeakPtr());
 
     BrowserThread::PostTask(
@@ -1029,6 +1056,16 @@
   }
 
   auto* partition = static_cast<StoragePartitionImpl*>(storage_partition);
+  non_network_url_loader_factories_[url::kFileScheme] =
+      std::make_unique<FileURLLoaderFactory>(
+          partition->browser_context()->GetPath(),
+          base::CreateSequencedTaskRunnerWithTraits(
+              {base::MayBlock(), base::TaskPriority::BACKGROUND,
+               base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
+  std::set<std::string> known_schemes;
+  for (auto& iter : non_network_url_loader_factories_)
+    known_schemes.insert(iter.first);
+
   DCHECK(!request_controller_);
   request_controller_ = std::make_unique<URLLoaderRequestController>(
       std::move(initial_handlers), std::move(new_request), resource_context,
@@ -1036,7 +1073,7 @@
       request_info->begin_params->initiator_origin,
       request_info->common_params.suggested_filename,
       std::move(proxied_factory_request), std::move(proxied_factory_info),
-      weak_factory_.GetWeakPtr());
+      std::move(known_schemes), weak_factory_.GetWeakPtr());
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
       base::BindOnce(
@@ -1047,13 +1084,6 @@
           std::move(request_info), std::move(navigation_ui_data),
           std::move(factory_for_webui), frame_tree_node_id,
           ServiceManagerConnection::GetForProcess()->GetConnector()->Clone()));
-
-  non_network_url_loader_factories_[url::kFileScheme] =
-      std::make_unique<FileURLLoaderFactory>(
-          partition->browser_context()->GetPath(),
-          base::CreateSequencedTaskRunnerWithTraits(
-              {base::MayBlock(), base::TaskPriority::BACKGROUND,
-               base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
 }
 
 NavigationURLLoaderNetworkService::~NavigationURLLoaderNetworkService() {
diff --git a/content/browser/loader/navigation_url_loader_unittest.cc b/content/browser/loader/navigation_url_loader_unittest.cc
index e23ef68..4bd10b3 100644
--- a/content/browser/loader/navigation_url_loader_unittest.cc
+++ b/content/browser/loader/navigation_url_loader_unittest.cc
@@ -161,7 +161,7 @@
 
   // Wait for the request to fail as expected.
   delegate.WaitForRequestFailed();
-  EXPECT_EQ(net::ERR_UNKNOWN_URL_SCHEME, delegate.net_error());
+  EXPECT_EQ(net::ERR_ABORTED, delegate.net_error());
   EXPECT_FALSE(delegate.ssl_info().is_valid());
   EXPECT_EQ(1, delegate.on_request_handled_counter());
 }
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc
index 2749cfe..802cc1b 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -586,9 +586,6 @@
 
 bool ResourceDispatcherHostImpl::HandleExternalProtocol(ResourceLoader* loader,
                                                         const GURL& url) {
-  if (!delegate_)
-    return false;
-
   ResourceRequestInfoImpl* info = loader->GetRequestInfo();
 
   if (!IsResourceTypeFrame(info->GetResourceType()))
@@ -599,7 +596,10 @@
   if (!url.is_valid() || job_factory->IsHandledProtocol(url.scheme()))
     return false;
 
-  return delegate_->HandleExternalProtocol(url, info);
+  return GetContentClient()->browser()->HandleExternalProtocol(
+      url, info->GetWebContentsGetterForRequest(), info->GetChildID(),
+      info->GetNavigationUIData(), info->IsMainFrame(),
+      info->GetPageTransition(), info->HasUserGesture());
 }
 
 void ResourceDispatcherHostImpl::DidStartRequest(ResourceLoader* loader) {
@@ -2354,27 +2354,45 @@
 }
 
 std::unique_ptr<ResourceDispatcherHostImpl::LoadInfoList>
-ResourceDispatcherHostImpl::GetLoadInfoForAllRoutes() {
-  std::unique_ptr<LoadInfoList> infos(new LoadInfoList);
-
+ResourceDispatcherHostImpl::GetInterestingPerFrameLoadInfos() {
+  auto infos = std::make_unique<LoadInfoList>();
+  std::map<GlobalFrameRoutingId, LoadInfo> frame_infos;
   for (const auto& loader : pending_loaders_) {
     net::URLRequest* request = loader.second->request();
     net::UploadProgress upload_progress = request->GetUploadProgress();
 
     LoadInfo load_info;
-    load_info.web_contents_getter =
-        loader.second->GetRequestInfo()->GetWebContentsGetterForRequest();
     load_info.host = request->url().host();
     load_info.load_state = request->GetLoadState();
     load_info.upload_size = upload_progress.size();
     load_info.upload_position = upload_progress.position();
-    infos->push_back(load_info);
+
+    ResourceRequestInfoImpl* request_info = loader.second->GetRequestInfo();
+    load_info.web_contents_getter =
+        request_info->GetWebContentsGetterForRequest();
+
+    // Navigation requests have frame_tree_node_ids, and may not have frame
+    // routing ids. Just include them unconditionally.
+    if (request_info->frame_tree_node_id() != -1) {
+      infos->push_back(load_info);
+    } else {
+      GlobalFrameRoutingId id(request_info->GetChildID(),
+                              request_info->GetRenderFrameID());
+      auto existing = frame_infos.find(id);
+      if (existing == frame_infos.end() ||
+          LoadInfoIsMoreInteresting(load_info, existing->second)) {
+        frame_infos[id] = std::move(load_info);
+      }
+    }
   }
+
+  for (auto it : frame_infos)
+    infos->push_back(std::move(it.second));
   return infos;
 }
 
 void ResourceDispatcherHostImpl::UpdateLoadInfo() {
-  std::unique_ptr<LoadInfoList> infos(GetLoadInfoForAllRoutes());
+  std::unique_ptr<LoadInfoList> infos(GetInterestingPerFrameLoadInfos());
 
   // Stop the timer if there are no more pending requests. Future new requests
   // will restart it as necessary.
diff --git a/content/browser/loader/resource_dispatcher_host_impl.h b/content/browser/loader/resource_dispatcher_host_impl.h
index 1b299ac..aa4a7df0 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/content/browser/loader/resource_dispatcher_host_impl.h
@@ -359,6 +359,7 @@
   FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest, LoadInfoSamePriority);
   FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest, LoadInfoUploadProgress);
   FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest, LoadInfoTwoRenderViews);
+  FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest, UpdateLoadState);
 
   struct OustandingRequestsStats {
     int memory_cost;
@@ -521,8 +522,14 @@
   static std::unique_ptr<LoadInfoMap> PickMoreInterestingLoadInfos(
       std::unique_ptr<LoadInfoList> infos);
 
-  // Gets all the LoadInfos for each pending request.
-  std::unique_ptr<LoadInfoList> GetLoadInfoForAllRoutes();
+  // Gets the most interesting LoadInfos for each GlobalFrameRoutingIds.
+  // Includes the LoadInfo for all navigation requests, which may not have valid
+  // frame ids.
+  //
+  // We aggregate per-frame on the IO thread, and per-WebContents on the UI
+  // thread. The IO thread aggregation is used to avoid copying state for every
+  // request across threads.
+  std::unique_ptr<LoadInfoList> GetInterestingPerFrameLoadInfos();
 
   // Checks all pending requests and updates the load info if necessary.
   void UpdateLoadInfo();
diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc
index 3f10ec022..5ca6c14 100644
--- a/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -2145,15 +2145,47 @@
   EXPECT_EQ(0, host_.pending_requests());
 }
 
+namespace {
+
+class ExternalProtocolBrowserClient : public TestContentBrowserClient {
+ public:
+  ExternalProtocolBrowserClient() {}
+
+  bool HandleExternalProtocol(
+      const GURL& url,
+      ResourceRequestInfo::WebContentsGetter web_contents_getter,
+      int child_id,
+      NavigationUIData* navigation_data,
+      bool is_main_frame,
+      ui::PageTransition page_transition,
+      bool has_user_gesture) override {
+    return false;
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ExternalProtocolBrowserClient);
+};
+
+}  // namespace
+
+// Verifies that if the embedder says that it didn't handle an unkonown protocol
+// the request is cancelled and net::ERR_ABORTED is returned. Otherwise it is
+// not aborted and net/ layer cancels it with net::ERR_UNKNOWN_URL_SCHEME.
 TEST_F(ResourceDispatcherHostTest, UnknownURLScheme) {
   EXPECT_EQ(0, host_.pending_requests());
 
   HandleScheme("http");
 
-  const GURL invalid_sheme_url = GURL("foo://bar");
-  const int expected_error_code = net::ERR_UNKNOWN_URL_SCHEME;
+  ExternalProtocolBrowserClient test_client;
+  ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
 
-  CompleteFailingMainResourceRequest(invalid_sheme_url, expected_error_code);
+  const GURL invalid_scheme_url = GURL("foo://bar");
+  int expected_error_code = net::ERR_UNKNOWN_URL_SCHEME;
+  CompleteFailingMainResourceRequest(invalid_scheme_url, expected_error_code);
+  SetBrowserClientForTesting(old_client);
+
+  expected_error_code = net::ERR_ABORTED;
+  CompleteFailingMainResourceRequest(invalid_scheme_url, expected_error_code);
 }
 
 // Request a very large detachable resource and cancel part way. Some of the
diff --git a/content/browser/loader/resource_requester_info.cc b/content/browser/loader/resource_requester_info.cc
index 874bd21a..60d6688d 100644
--- a/content/browser/loader/resource_requester_info.cc
+++ b/content/browser/loader/resource_requester_info.cc
@@ -12,6 +12,7 @@
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/public/browser/resource_context.h"
 #include "content/public/common/browser_side_navigation_policy.h"
+#include "content/public/common/child_process_host.h"
 #include "content/public/common/content_features.h"
 #include "services/network/public/cpp/features.h"
 #include "storage/browser/fileapi/file_system_context.h"
@@ -86,10 +87,10 @@
 ResourceRequesterInfo::CreateForBrowserSideNavigation(
     scoped_refptr<ServiceWorkerContextWrapper> service_worker_context) {
   return scoped_refptr<ResourceRequesterInfo>(new ResourceRequesterInfo(
-      RequesterType::BROWSER_SIDE_NAVIGATION, -1,
-      nullptr /* appcache_service */, nullptr /* blob_storage_context */,
-      nullptr /* file_system_context */, service_worker_context.get(),
-      GetContextsCallback()));
+      RequesterType::BROWSER_SIDE_NAVIGATION,
+      ChildProcessHost::kInvalidUniqueID, nullptr /* appcache_service */,
+      nullptr /* blob_storage_context */, nullptr /* file_system_context */,
+      service_worker_context.get(), GetContextsCallback()));
 }
 
 scoped_refptr<ResourceRequesterInfo>
@@ -123,8 +124,9 @@
   }
 
   return scoped_refptr<ResourceRequesterInfo>(new ResourceRequesterInfo(
-      RequesterType::NAVIGATION_PRELOAD, -1, nullptr /* appcache_service */,
-      nullptr /* blob_storage_context */, nullptr /* file_system_context */,
+      RequesterType::NAVIGATION_PRELOAD, ChildProcessHost::kInvalidUniqueID,
+      nullptr /* appcache_service */, nullptr /* blob_storage_context */,
+      nullptr /* file_system_context */,
       original_request_info->service_worker_context(), get_contexts_callback));
 }
 
@@ -134,10 +136,10 @@
   DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService));
   DCHECK(base::FeatureList::IsEnabled(features::kSignedHTTPExchange));
   return scoped_refptr<ResourceRequesterInfo>(new ResourceRequesterInfo(
-      RequesterType::CERTIFICATE_FETCHER_FOR_SIGNED_EXCHANGE, -1,
-      nullptr /* appcache_service */, nullptr /* blob_storage_context */,
-      nullptr /* file_system_context */, nullptr /* service_worker_context */,
-      get_contexts_callback));
+      RequesterType::CERTIFICATE_FETCHER_FOR_SIGNED_EXCHANGE,
+      ChildProcessHost::kInvalidUniqueID, nullptr /* appcache_service */,
+      nullptr /* blob_storage_context */, nullptr /* file_system_context */,
+      nullptr /* service_worker_context */, get_contexts_callback));
 }
 
 }  // namespace content
diff --git a/content/browser/media/capture/desktop_capture_device.cc b/content/browser/media/capture/desktop_capture_device.cc
index 9d2deac..50f3cb7 100644
--- a/content/browser/media/capture/desktop_capture_device.cc
+++ b/content/browser/media/capture/desktop_capture_device.cc
@@ -117,7 +117,7 @@
 
   void SetMockTimeForTesting(
       scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-      std::unique_ptr<base::TickClock> tick_clock);
+      base::TickClock* tick_clock);
 
  private:
   // webrtc::DesktopCapturer::Callback interface.
@@ -166,7 +166,7 @@
   // be returned to the caller directly then this is NULL.
   std::unique_ptr<webrtc::DesktopFrame> output_frame_;
 
-  std::unique_ptr<base::TickClock> tick_clock_;
+  base::TickClock* tick_clock_ = nullptr;
 
   // Timer used to capture the frame.
   std::unique_ptr<base::OneShotTimer> capture_timer_;
@@ -204,7 +204,6 @@
     DesktopMediaID::Type type)
     : task_runner_(task_runner),
       desktop_capturer_(std::move(capturer)),
-      tick_clock_(nullptr),
       capture_timer_(new base::OneShotTimer()),
       max_cpu_consumption_percentage_(GetMaximumCpuConsumptionPercentage()),
       capture_in_progress_(false),
@@ -268,9 +267,9 @@
 
 void DesktopCaptureDevice::Core::SetMockTimeForTesting(
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-    std::unique_ptr<base::TickClock> tick_clock) {
-  tick_clock_ = std::move(tick_clock);
-  capture_timer_.reset(new base::OneShotTimer(tick_clock_.get()));
+    base::TickClock* tick_clock) {
+  tick_clock_ = tick_clock;
+  capture_timer_.reset(new base::OneShotTimer(tick_clock_));
   capture_timer_->SetTaskRunner(task_runner);
 }
 
@@ -577,8 +576,8 @@
 
 void DesktopCaptureDevice::SetMockTimeForTesting(
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-    std::unique_ptr<base::TickClock> tick_clock) {
-  core_->SetMockTimeForTesting(task_runner, std::move(tick_clock));
+    base::TickClock* tick_clock) {
+  core_->SetMockTimeForTesting(task_runner, tick_clock);
 }
 
 }  // namespace content
diff --git a/content/browser/media/capture/desktop_capture_device.h b/content/browser/media/capture/desktop_capture_device.h
index 5263d45..2c1b9e8 100644
--- a/content/browser/media/capture/desktop_capture_device.h
+++ b/content/browser/media/capture/desktop_capture_device.h
@@ -63,7 +63,7 @@
   // other testing entities inheriting the common runner and tick interfaces.
   void SetMockTimeForTesting(
       scoped_refptr<base::SingleThreadTaskRunner> task_runner,
-      std::unique_ptr<base::TickClock> tick_clock);
+      base::TickClock* tick_clock);
 
   base::Thread thread_;
   std::unique_ptr<Core> core_;
diff --git a/content/browser/media/capture/desktop_capture_device_unittest.cc b/content/browser/media/capture/desktop_capture_device_unittest.cc
index c1a86a9..3ca88ac 100644
--- a/content/browser/media/capture/desktop_capture_device_unittest.cc
+++ b/content/browser/media/capture/desktop_capture_device_unittest.cc
@@ -602,7 +602,7 @@
               base::TestMockTimeTaskRunner::Type::kStandalone);
 
           capture_device_->SetMockTimeForTesting(
-              task_runner, task_runner->DeprecatedGetMockTickClock());
+              task_runner, task_runner->GetMockTickClock());
         }));
 
     EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _))
diff --git a/content/browser/renderer_host/pepper/pepper_network_proxy_host.h b/content/browser/renderer_host/pepper/pepper_network_proxy_host.h
index 780af3e..a3b9424ae 100644
--- a/content/browser/renderer_host/pepper/pepper_network_proxy_host.h
+++ b/content/browser/renderer_host/pepper/pepper_network_proxy_host.h
@@ -15,7 +15,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "content/common/content_export.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "ppapi/host/host_message_context.h"
 #include "ppapi/host/resource_host.h"
 
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index f4f6c45..2573d92 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -2372,7 +2372,10 @@
   const gfx::Rect caret_rect = ConvertRectToScreen(gfx::Rect(
       region->focus.edge_top_rounded().x(),
       region->focus.edge_top_rounded().y(), 1, region->focus.GetHeight()));
-  legacy_render_widget_host_HWND_->MoveCaretTo(caret_rect);
+  gfx::Rect dip_caret_rect = display::win::ScreenWin::DIPToScreenRect(
+      legacy_render_widget_host_HWND_->hwnd(), caret_rect);
+  dip_caret_rect.set_width(1);  // Collapse any selection.
+  legacy_render_widget_host_HWND_->MoveCaretTo(dip_caret_rect);
 #endif  // defined(OS_WIN)
 }
 
diff --git a/content/browser/resolve_proxy_msg_helper.h b/content/browser/resolve_proxy_msg_helper.h
index 8a59d13..8eacab90 100644
--- a/content/browser/resolve_proxy_msg_helper.h
+++ b/content/browser/resolve_proxy_msg_helper.h
@@ -12,7 +12,7 @@
 #include "content/common/content_export.h"
 #include "content/public/browser/browser_message_filter.h"
 #include "net/base/completion_callback.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "url/gurl.h"
 
 namespace net {
diff --git a/content/browser/resolve_proxy_msg_helper_unittest.cc b/content/browser/resolve_proxy_msg_helper_unittest.cc
index ec1d86b..f9e7e142 100644
--- a/content/browser/resolve_proxy_msg_helper_unittest.cc
+++ b/content/browser/resolve_proxy_msg_helper_unittest.cc
@@ -13,7 +13,7 @@
 #include "net/base/net_errors.h"
 #include "net/proxy_resolution/mock_proxy_resolver.h"
 #include "net/proxy_resolution/proxy_config_service.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace content {
diff --git a/content/browser/service_worker/service_worker_handle.h b/content/browser/service_worker/service_worker_handle.h
index abf0971..b5037d8 100644
--- a/content/browser/service_worker/service_worker_handle.h
+++ b/content/browser/service_worker/service_worker_handle.h
@@ -10,12 +10,20 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "build/build_config.h"
 #include "content/browser/service_worker/service_worker_version.h"
 #include "content/common/content_export.h"
 #include "content/common/service_worker/service_worker_types.h"
 #include "mojo/public/cpp/bindings/associated_binding_set.h"
 #include "third_party/WebKit/public/mojom/service_worker/service_worker_object.mojom.h"
 
+#if defined(OS_WIN)
+// Since PostMessage is a Win32 macro, ensure that it has the same
+// value every time this header is parsed. This avoids strange
+// compilation and linking errors.
+#include "base/win/windows_types.h"
+#endif
+
 namespace url {
 class Origin;
 }  // namespace url
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index 1451c36..6f4c8f2 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -12,6 +12,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "components/url_formatter/url_formatter.h"
 #include "content/browser/frame_host/frame_tree.h"
 #include "content/browser/frame_host/navigation_entry_impl.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
@@ -41,6 +42,7 @@
 #include "content/shell/browser/shell.h"
 #include "content/test/content_browser_test_utils_internal.h"
 #include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/controllable_http_response.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "url/gurl.h"
@@ -75,6 +77,8 @@
   }
 
   void SetUpOnMainThread() override {
+    host_resolver()->AddRuleWithLatency("slow.com", "127.0.0.1",
+                                        1000 * 60 * 60 /* ms */);
     // Setup the server to allow serving separate sites, so we can perform
     // cross-process navigation.
     host_resolver()->AddRule("*", "127.0.0.1");
@@ -1687,4 +1691,113 @@
             target_url_waiter.WaitForUpdatedTargetURL());
 }
 
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, UpdateLoadState) {
+  // Controlled responses for image requests made in the test. They will
+  // alternate being the "most interesting" for the purposes of notifying the
+  // WebContents.
+  auto a_response =
+      std::make_unique<net::test_server::ControllableHttpResponse>(
+          embedded_test_server(), "/a_img");
+  auto slow_response =
+      std::make_unique<net::test_server::ControllableHttpResponse>(
+          embedded_test_server(), "/slow_img");
+  auto c_response =
+      std::make_unique<net::test_server::ControllableHttpResponse>(
+          embedded_test_server(), "/c_img");
+  ASSERT_TRUE(embedded_test_server()->Start());
+
+  // This is a hack to ensure that the resource scheduler has at least one
+  // loading client for the duration of the test. Could alternatively delay some
+  // subresources on the main target page, but it would require care to ensure
+  // *all* other resources are completed before the test properly gets started.
+  Shell* popup = CreateBrowser();
+  const GURL kPopupUrl(embedded_test_server()->GetURL("/title1.html"));
+  TestNavigationManager popup_delayer(popup->web_contents(), kPopupUrl);
+  popup->LoadURL(kPopupUrl);
+  EXPECT_TRUE(popup_delayer.WaitForResponse());
+
+  EXPECT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL(
+                   "a.com", "/cross_site_iframe_factory.html?a(b(c))")));
+  WebContentsImpl* web_contents =
+      static_cast<WebContentsImpl*>(shell()->web_contents());
+  FrameTreeNode* a_frame = web_contents->GetFrameTree()->root();
+  FrameTreeNode* slow_frame = a_frame->child_at(0);
+  FrameTreeNode* c_frame = slow_frame->child_at(0);
+
+  // Start loading the respective resources in each frame.
+  auto load_resource = [](FrameTreeNode* frame, const std::string url) {
+    std::string partial_script = R"(
+      var img = new Image();
+      img.src = '%s';
+      document.body.appendChild(img);
+    )";
+    std::string script =
+        base::StringPrintf(partial_script.c_str(), url.c_str());
+    EXPECT_TRUE(ExecuteScript(frame, script));
+  };
+
+  // Blocks until the img element in |frame| finishes.
+  auto wait_for_img_finished = [](FrameTreeNode* frame) {
+    bool finished = false;
+    std::string script = R"(
+      var img = document.getElementsByTagName('img')[0];
+      if (img.complete)
+        window.domAutomationController.send(true);
+      else
+        img.onload = img.onerror = window.domAutomationController.send(true);
+    )";
+    EXPECT_TRUE(ExecuteScriptAndExtractBool(frame, script.c_str(), &finished));
+  };
+
+  // Requests a load state notification from the RDHI and waits until the update
+  // is posted back on the UI thread. Due to PostTaskAndReply, relies on
+  // UpdateLoadInfo synchronously posting a task to the WebContents.
+  auto update_load_state_and_wait = []() {
+    base::RunLoop run_loop;
+    BrowserThread::PostTaskAndReply(
+        BrowserThread::IO, FROM_HERE,
+        base::BindOnce(&ResourceDispatcherHostImpl::UpdateLoadInfo,
+                       base::Unretained(ResourceDispatcherHostImpl::Get())),
+        run_loop.QuitClosure());
+    run_loop.Run();
+  };
+
+  // There should be no outgoing requests, so the load state should be empty.
+  update_load_state_and_wait();
+  EXPECT_TRUE(web_contents->GetLoadStateHost().empty());
+  EXPECT_EQ(url_formatter::IDNToUnicode(kPopupUrl.host()),
+            popup->web_contents()->GetLoadStateHost());
+
+  load_resource(a_frame, "/a_img");
+  a_response->WaitForRequest();
+  update_load_state_and_wait();
+  EXPECT_EQ(url_formatter::IDNToUnicode("a.com"),
+            web_contents->GetLoadStateHost());
+
+  // slow_img should never get past DNS resolution for the remainder of the
+  // test. Ensure that a_img is further along (and therefore more interesting).
+  load_resource(slow_frame, "http://slow.com/slow_img");
+  update_load_state_and_wait();
+  EXPECT_EQ(url_formatter::IDNToUnicode("a.com"),
+            web_contents->GetLoadStateHost());
+
+  // Finish a_img and start c_img, ensure it passes slow_img.
+  a_response->Done();
+  load_resource(c_frame, "/c_img");
+  wait_for_img_finished(a_frame);
+  c_response->WaitForRequest();
+  update_load_state_and_wait();
+  EXPECT_EQ(url_formatter::IDNToUnicode("c.com"),
+            web_contents->GetLoadStateHost());
+
+  // Finish c_img and ensure slow_img (the last outgoing request) is the most
+  // interesting.
+  c_response->Done();
+  wait_for_img_finished(c_frame);
+  update_load_state_and_wait();
+  EXPECT_EQ(url_formatter::IDNToUnicode("slow.com"),
+            web_contents->GetLoadStateHost());
+}
+
 }  // namespace content
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index 2799f2aa..44e71c6 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -1532,22 +1532,21 @@
                     base::ListValue  /* result */)
 
 // A request to run a JavaScript dialog.
-IPC_SYNC_MESSAGE_ROUTED4_2(FrameHostMsg_RunJavaScriptDialog,
+IPC_SYNC_MESSAGE_ROUTED3_2(FrameHostMsg_RunJavaScriptDialog,
                            base::string16 /* in - alert message */,
                            base::string16 /* in - default prompt */,
-                           GURL /* in - originating page URL */,
                            content::JavaScriptDialogType /* in - type */,
                            bool /* out - success */,
                            base::string16 /* out - user_input field */)
 
 // Displays a dialog to confirm that the user wants to navigate away from the
 // page. Replies true if yes, and false otherwise. The reply string is ignored,
-// but is included so that we can use OnJavaScriptMessageBoxClosed.
-IPC_SYNC_MESSAGE_ROUTED2_2(FrameHostMsg_RunBeforeUnloadConfirm,
-                           GURL,           /* in - originating frame URL */
-                           bool            /* in - is a reload */,
-                           bool            /* out - success */,
-                           base::string16  /* out - This is ignored.*/)
+// but is included so that we can use
+// RenderFrameHostImpl::SendJavaScriptDialogReply.
+IPC_SYNC_MESSAGE_ROUTED1_2(FrameHostMsg_RunBeforeUnloadConfirm,
+                           bool /* in - is a reload */,
+                           bool /* out - success */,
+                           base::string16 /* out - This is ignored.*/)
 
 // Notify browser the theme color has been changed.
 IPC_MESSAGE_ROUTED1(FrameHostMsg_DidChangeThemeColor,
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index c8e612e..391c342 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -688,4 +688,15 @@
   return nullptr;
 }
 
+bool ContentBrowserClient::HandleExternalProtocol(
+    const GURL& url,
+    ResourceRequestInfo::WebContentsGetter web_contents_getter,
+    int child_id,
+    NavigationUIData* navigation_data,
+    bool is_main_frame,
+    ui::PageTransition page_transition,
+    bool has_user_gesture) {
+  return true;
+}
+
 }  // namespace content
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index 6646852..6d96829 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -1112,6 +1112,22 @@
       bool first_auth_attempt,
       const base::Callback<void(const base::Optional<net::AuthCredentials>&)>&
           auth_required_callback);
+
+  // Launches the url for the given tab. Returns true if an attempt to handle
+  // the url was made, e.g. by launching an app. Note that this does not
+  // guarantee that the app successfully handled it.
+  // If this is a navigation request, then |child_id| will be
+  // ChildProcessHost::kInvalidUniqueID and |navigation_ui_data| will valid.
+  // Otherwise child_id will be the process id and |navigation_ui_data| will be
+  // nullptr.
+  virtual bool HandleExternalProtocol(
+      const GURL& url,
+      ResourceRequestInfo::WebContentsGetter web_contents_getter,
+      int child_id,
+      NavigationUIData* navigation_data,
+      bool is_main_frame,
+      ui::PageTransition page_transition,
+      bool has_user_gesture);
 };
 
 }  // namespace content
diff --git a/content/public/browser/download_manager.h b/content/public/browser/download_manager.h
index 0e3f4f4..11dccbcd 100644
--- a/content/public/browser/download_manager.h
+++ b/content/public/browser/download_manager.h
@@ -91,6 +91,12 @@
     virtual void OnDownloadCreated(DownloadManager* manager,
                                    download::DownloadItem* item) {}
 
+    // Called when the download manager intercepted a download navigation but
+    // didn't create the download item. Possible reasons:
+    // 1. |delegate| is null.
+    // 2. |delegate| doesn't allow the download.
+    virtual void OnDownloadDropped(DownloadManager* manager) {}
+
     // Called when the download manager has finished loading the data.
     virtual void OnManagerInitialized() {}
 
diff --git a/content/public/browser/resource_dispatcher_host_delegate.cc b/content/public/browser/resource_dispatcher_host_delegate.cc
index 4addf92..838ec2e1 100644
--- a/content/public/browser/resource_dispatcher_host_delegate.cc
+++ b/content/public/browser/resource_dispatcher_host_delegate.cc
@@ -35,12 +35,6 @@
     bool is_new_request,
     std::vector<std::unique_ptr<ResourceThrottle>>* throttles) {}
 
-bool ResourceDispatcherHostDelegate::HandleExternalProtocol(
-    const GURL& url,
-    ResourceRequestInfo* info) {
-  return true;
-}
-
 bool ResourceDispatcherHostDelegate::ShouldInterceptResourceAsStream(
     net::URLRequest* request,
     const std::string& mime_type,
diff --git a/content/public/browser/resource_dispatcher_host_delegate.h b/content/public/browser/resource_dispatcher_host_delegate.h
index 2d904ad..8a11639 100644
--- a/content/public/browser/resource_dispatcher_host_delegate.h
+++ b/content/public/browser/resource_dispatcher_host_delegate.h
@@ -65,12 +65,6 @@
       bool is_new_request,
       std::vector<std::unique_ptr<ResourceThrottle>>* throttles);
 
-  // Launches the url for the given tab. Returns true if an attempt to handle
-  // the url was made, e.g. by launching an app. Note that this does not
-  // guarantee that the app successfully handled it.
-  virtual bool HandleExternalProtocol(const GURL& url,
-                                      ResourceRequestInfo* info);
-
   // Returns true and sets |origin| if a Stream should be created for the
   // resource. If true is returned, a new Stream will be created and
   // OnStreamCreated() will be called with a StreamHandle instance for the
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index a1b368c..fcfaebc 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -238,16 +238,6 @@
 const base::Feature kOriginTrials{"OriginTrials",
                                   base::FEATURE_ENABLED_BY_DEFAULT};
 
-// Whether a download can be handled by parallel jobs.
-const base::Feature kParallelDownloading {
-  "ParallelDownloading",
-#if defined(OS_ANDROID)
-      base::FEATURE_ENABLED_BY_DEFAULT
-#else
-      base::FEATURE_DISABLED_BY_DEFAULT
-#endif
-};
-
 // Whether document level event listeners should default 'passive' to true.
 const base::Feature kPassiveDocumentEventListeners{
     "PassiveDocumentEventListeners", base::FEATURE_ENABLED_BY_DEFAULT};
@@ -257,6 +247,10 @@
 const base::Feature kPassiveEventListenersDueToFling{
     "PassiveEventListenersDueToFling", base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Whether PDF files should be rendered in diffent processes based on origin.
+const base::Feature kPdfIsolation = {"PdfIsolation",
+                                     base::FEATURE_DISABLED_BY_DEFAULT};
+
 // If Pepper 3D Image Chromium is allowed, this feature controls whether it is
 // enabled.
 const base::Feature kPepper3DImageChromium {
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 4915ec9..a36d645 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -64,9 +64,9 @@
 CONTENT_EXPORT extern const base::Feature kNotificationsWithMojo;
 CONTENT_EXPORT extern const base::Feature kOriginManifest;
 CONTENT_EXPORT extern const base::Feature kOriginTrials;
-CONTENT_EXPORT extern const base::Feature kParallelDownloading;
 CONTENT_EXPORT extern const base::Feature kPassiveDocumentEventListeners;
 CONTENT_EXPORT extern const base::Feature kPassiveEventListenersDueToFling;
+CONTENT_EXPORT extern const base::Feature kPdfIsolation;
 CONTENT_EXPORT extern const base::Feature kPepper3DImageChromium;
 CONTENT_EXPORT extern const base::Feature kPurgeAndSuspend;
 CONTENT_EXPORT extern const base::Feature kPWAFullCodeCache;
diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc
index 4569941..4566c56 100644
--- a/content/public/renderer/content_renderer_client.cc
+++ b/content/public/renderer/content_renderer_client.cc
@@ -173,6 +173,11 @@
   return false;
 }
 
+bool ContentRendererClient::IsOriginIsolatedPepperPlugin(
+    const base::FilePath& plugin_path) {
+  return false;
+}
+
 bool ContentRendererClient::AllowPepperMediaStreamAPI(const GURL& url) {
   return false;
 }
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h
index c5da6a40..f663393a 100644
--- a/content/public/renderer/content_renderer_client.h
+++ b/content/public/renderer/content_renderer_client.h
@@ -13,6 +13,7 @@
 #include <vector>
 
 #include "base/callback_forward.h"
+#include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "base/strings/string16.h"
 #include "base/task_scheduler/task_scheduler.h"
@@ -261,6 +262,12 @@
   // startup steps).
   virtual bool IsExternalPepperPlugin(const std::string& module_name);
 
+  // Returns true if the given Pepper plugin should process content from
+  // different origins in different PPAPI processes. This is generally a
+  // worthwhile precaution when the plugin provides an active scripting
+  // language.
+  virtual bool IsOriginIsolatedPepperPlugin(const base::FilePath& plugin_path);
+
   // Returns true if the page at |url| can use Pepper MediaStream APIs.
   virtual bool AllowPepperMediaStreamAPI(const GURL& url);
 
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc
index b2e5854c..28b8bdd 100644
--- a/content/renderer/browser_plugin/browser_plugin.cc
+++ b/content/renderer/browser_plugin/browser_plugin.cc
@@ -389,7 +389,7 @@
 }
 
 float BrowserPlugin::GetDeviceScaleFactor() const {
-  return embedding_render_widget_->GetOriginalDeviceScaleFactor();
+  return embedding_render_widget_->GetOriginalScreenInfo().device_scale_factor;
 }
 
 void BrowserPlugin::UpdateInternalInstanceId() {
@@ -461,7 +461,8 @@
   embedding_render_widget_ =
       RenderFrameImpl::FromWebFrame(container_->GetDocument().GetFrame())
           ->GetRenderWidget();
-  pending_resize_params_.screen_info = embedding_render_widget_->screen_info();
+  pending_resize_params_.screen_info =
+      embedding_render_widget_->GetOriginalScreenInfo();
   embedding_render_widget_->RegisterBrowserPlugin(this);
 
   return true;
@@ -540,7 +541,8 @@
   }
 
   pending_resize_params_.frame_rect = frame_rect;
-  pending_resize_params_.screen_info = embedding_render_widget_->screen_info();
+  pending_resize_params_.screen_info =
+      embedding_render_widget_->GetOriginalScreenInfo();
   if (guest_crashed_) {
     // Update the sad page to match the current ScreenInfo.
     compositing_helper_->ChildFrameGone(frame_rect.size(),
diff --git a/content/renderer/input/render_widget_input_handler.cc b/content/renderer/input/render_widget_input_handler.cc
index 1e9a563..ab2968bb 100644
--- a/content/renderer/input/render_widget_input_handler.cc
+++ b/content/renderer/input/render_widget_input_handler.cc
@@ -209,7 +209,7 @@
   gfx::PointF point_in_pixel(point);
   if (IsUseZoomForDSFEnabled()) {
     point_in_pixel = gfx::ConvertPointToPixel(
-        widget_->GetOriginalDeviceScaleFactor(), point_in_pixel);
+        widget_->GetOriginalScreenInfo().device_scale_factor, point_in_pixel);
   }
   blink::WebNode result_node = widget_->GetWebWidget()
                                    ->HitTestResultAt(blink::WebPoint(
diff --git a/content/renderer/mus/renderer_window_tree_client.cc b/content/renderer/mus/renderer_window_tree_client.cc
index bffe1f3..1907fde 100644
--- a/content/renderer/mus/renderer_window_tree_client.cc
+++ b/content/renderer/mus/renderer_window_tree_client.cc
@@ -170,6 +170,16 @@
       CreateMusEmbeddedFrame(render_frame_proxy, token));
 }
 
+void RendererWindowTreeClient::OnEmbedFromToken(
+    const base::UnguessableToken& token,
+    ui::mojom::WindowDataPtr root,
+    int64_t display_id,
+    const base::Optional<viz::LocalSurfaceId>& local_surface_id) {
+  // Renderers don't use ScheduleEmbedForExistingClient(), so this path should
+  // never be hit.
+  NOTREACHED();
+}
+
 void RendererWindowTreeClient::DestroyFrame(uint32_t frame_routing_id) {
   pending_frames_.erase(frame_routing_id);
 }
diff --git a/content/renderer/mus/renderer_window_tree_client.h b/content/renderer/mus/renderer_window_tree_client.h
index d61ad5b..b85fd04a 100644
--- a/content/renderer/mus/renderer_window_tree_client.h
+++ b/content/renderer/mus/renderer_window_tree_client.h
@@ -117,6 +117,11 @@
       ui::Id focused_window_id,
       bool drawn,
       const base::Optional<viz::LocalSurfaceId>& local_surface_id) override;
+  void OnEmbedFromToken(
+      const base::UnguessableToken& token,
+      ui::mojom::WindowDataPtr root,
+      int64_t display_id,
+      const base::Optional<viz::LocalSurfaceId>& local_surface_id) override;
   void OnEmbeddedAppDisconnected(ui::Id window_id) override;
   void OnUnembed(ui::Id window_id) override;
   void OnCaptureChanged(ui::Id new_capture_window_id,
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index d4dbc776..f87af36 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -1202,9 +1202,12 @@
   CHECK(parent_routing_id != MSG_ROUTING_NONE || !web_frame->Parent());
 
   if (widget_params.routing_id != MSG_ROUTING_NONE) {
+    // TODO(fsamuel): It's not clear if we should be passing in the
+    // web ScreenInfo or the original ScreenInfo here.
     render_frame->render_widget_ = RenderWidget::CreateForFrame(
         widget_params.routing_id, widget_params.hidden,
-        render_frame->render_view_->screen_info(), compositor_deps, web_frame);
+        render_frame->render_view_->GetWebScreenInfo(), compositor_deps,
+        web_frame);
   }
 
   if (has_committed_real_load)
@@ -1585,10 +1588,12 @@
       base::Bind(&RenderViewImpl::ShowCreatedFullscreenWidget,
                  render_view()->GetWeakPtr());
 
+  // TODO(fsamuel): It's not clear if we should be passing in the
+  // web ScreenInfo or the original ScreenInfo here.
   RenderWidgetFullscreenPepper* widget = RenderWidgetFullscreenPepper::Create(
       fullscreen_widget_routing_id, show_callback,
       GetRenderWidget()->compositor_deps(), plugin, active_url,
-      GetRenderWidget()->screen_info(), std::move(widget_channel_request));
+      GetRenderWidget()->GetWebScreenInfo(), std::move(widget_channel_request));
   // TODO(nick): The show() handshake seems like unnecessary complexity here,
   // since there's no real delay between CreateFullscreenWidget and
   // ShowCreatedFullscreenWidget. Would it be simpler to have the
@@ -2576,7 +2581,6 @@
 bool RenderFrameImpl::RunJavaScriptDialog(JavaScriptDialogType type,
                                           const base::string16& message,
                                           const base::string16& default_value,
-                                          const GURL& frame_url,
                                           base::string16* result) {
   // Don't allow further dialogs if we are waiting to swap out, since the
   // ScopedPageLoadDeferrer in our stack prevents it.
@@ -2598,7 +2602,7 @@
     result = &result_temp;
 
   Send(new FrameHostMsg_RunJavaScriptDialog(routing_id_, message, default_value,
-                                            frame_url, type, &success, result));
+                                            type, &success, result));
   return success;
 }
 
@@ -2850,8 +2854,11 @@
         this, delegate->GetWeakPtr());
   }
 
-  // TODO(tsepez): extract origin to lock from WebPluginParams url.
   base::Optional<url::Origin> origin_lock;
+  if (base::FeatureList::IsEnabled(features::kPdfIsolation) &&
+      GetContentClient()->renderer()->IsOriginIsolatedPepperPlugin(info.path)) {
+    origin_lock = url::Origin::Create(GURL(params.url));
+  }
 
   bool pepper_plugin_was_registered = false;
   scoped_refptr<PluginModule> pepper_module(PluginModule::Create(
@@ -4668,13 +4675,12 @@
 
 void RenderFrameImpl::RunModalAlertDialog(const blink::WebString& message) {
   RunJavaScriptDialog(JAVASCRIPT_DIALOG_TYPE_ALERT, message.Utf16(),
-                      base::string16(), frame_->GetDocument().Url(), nullptr);
+                      base::string16(), nullptr);
 }
 
 bool RenderFrameImpl::RunModalConfirmDialog(const blink::WebString& message) {
   return RunJavaScriptDialog(JAVASCRIPT_DIALOG_TYPE_CONFIRM, message.Utf16(),
-                             base::string16(), frame_->GetDocument().Url(),
-                             nullptr);
+                             base::string16(), nullptr);
 }
 
 bool RenderFrameImpl::RunModalPromptDialog(
@@ -4683,8 +4689,7 @@
     blink::WebString* actual_value) {
   base::string16 result;
   bool ok = RunJavaScriptDialog(JAVASCRIPT_DIALOG_TYPE_PROMPT, message.Utf16(),
-                                default_value.Utf16(),
-                                frame_->GetDocument().Url(), &result);
+                                default_value.Utf16(), &result);
   if (ok)
     *actual_value = WebString::FromUTF16(result);
   return ok;
@@ -4700,9 +4705,8 @@
   // This is an ignored return value, but is included so we can accept the same
   // response as RunJavaScriptDialog.
   base::string16 ignored_result;
-  Send(new FrameHostMsg_RunBeforeUnloadConfirm(
-      routing_id_, frame_->GetDocument().Url(), is_reload, &success,
-      &ignored_result));
+  Send(new FrameHostMsg_RunBeforeUnloadConfirm(routing_id_, is_reload, &success,
+                                               &ignored_result));
   return success;
 }
 
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 8ae31282..109bdfd 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -1145,7 +1145,6 @@
   bool RunJavaScriptDialog(JavaScriptDialogType type,
                            const base::string16& message,
                            const base::string16& default_value,
-                           const GURL& frame_url,
                            base::string16* result);
 
   // Loads the appropriate error page for the specified failure into the frame.
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc
index bd66172..647a6be 100644
--- a/content/renderer/render_frame_proxy.cc
+++ b/content/renderer/render_frame_proxy.cc
@@ -237,7 +237,7 @@
 
   compositing_helper_ = std::make_unique<ChildFrameCompositingHelper>(this);
 
-  pending_resize_params_.screen_info = render_widget_->screen_info();
+  pending_resize_params_.screen_info = render_widget_->GetOriginalScreenInfo();
 
 #if defined(USE_AURA)
   if (features::IsMusEnabled()) {
@@ -716,7 +716,7 @@
   pending_resize_params_.screen_space_rect = gfx::Rect(screen_space_rect);
   pending_resize_params_.local_frame_size =
       gfx::Size(local_frame_rect.width, local_frame_rect.height);
-  pending_resize_params_.screen_info = render_widget_->screen_info();
+  pending_resize_params_.screen_info = render_widget_->GetOriginalScreenInfo();
   if (crashed_) {
     // Update the sad page to match the current size.
     compositing_helper_->ChildFrameGone(local_frame_size(),
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 9d8d925..d5a2b7e 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -449,8 +449,8 @@
     params.needs_resize_ack = false;
     params.content_source_id = view()->GetContentSourceId();
     view()->OnResize(params);
-    ASSERT_EQ(dsf, view()->GetWebDeviceScaleFactor());
-    ASSERT_EQ(dsf, view()->GetOriginalDeviceScaleFactor());
+    ASSERT_EQ(dsf, view()->GetWebScreenInfo().device_scale_factor);
+    ASSERT_EQ(dsf, view()->GetOriginalScreenInfo().device_scale_factor);
   }
 
   void TestEmulatedSizeDprDsf(int width, int height, float dpr,
@@ -802,6 +802,61 @@
   CloseRenderView(new_view);
 }
 
+// This test verifies that when device emulation is enabled, RenderFrameProxy
+// continues to receive the original ScreenInfo and not the emualted
+// ScreenInfo.
+TEST_F(RenderViewImplScaleFactorTest, DeviceEmulationWithOOPIF) {
+  DoSetUp();
+
+  // This test should only run with --site-per-process.
+  if (!AreAllSitesIsolatedForTesting())
+    return;
+
+  const float device_scale = 2.0f;
+  float compositor_dsf = IsUseZoomForDSFEnabled() ? 1.f : device_scale;
+  SetDeviceScaleFactor(device_scale);
+
+  LoadHTML(
+      "<body style='min-height:1000px;'>"
+      "  <iframe src='data:text/html,frame 1'></iframe>"
+      "</body>");
+
+  WebFrame* web_frame = frame()->GetWebFrame();
+  ASSERT_TRUE(web_frame->FirstChild()->IsWebLocalFrame());
+  TestRenderFrame* child_frame = static_cast<TestRenderFrame*>(
+      RenderFrame::FromWebFrame(web_frame->FirstChild()->ToWebLocalFrame()));
+  ASSERT_TRUE(child_frame);
+
+  child_frame->SwapOut(kProxyRoutingId + 1, true,
+                       ReconstructReplicationStateForTesting(child_frame));
+  EXPECT_TRUE(web_frame->FirstChild()->IsWebRemoteFrame());
+  RenderFrameProxy* child_proxy = RenderFrameProxy::FromWebFrame(
+      web_frame->FirstChild()->ToWebRemoteFrame());
+  ASSERT_TRUE(child_proxy);
+
+  // Verify that the system device scale factor has propagated into the
+  // RenderFrameProxy.
+  EXPECT_EQ(device_scale,
+            view()->GetWidget()->GetWebScreenInfo().device_scale_factor);
+  EXPECT_EQ(device_scale,
+            view()->GetWidget()->GetOriginalScreenInfo().device_scale_factor);
+  EXPECT_EQ(device_scale, child_proxy->screen_info().device_scale_factor);
+
+  TestEmulatedSizeDprDsf(640, 480, 3.f, compositor_dsf);
+
+  // Verify that the RenderFrameProxy device scale factor is still the same.
+  EXPECT_EQ(3.f, view()->GetWidget()->GetWebScreenInfo().device_scale_factor);
+  EXPECT_EQ(device_scale,
+            view()->GetWidget()->GetOriginalScreenInfo().device_scale_factor);
+  EXPECT_EQ(device_scale, child_proxy->screen_info().device_scale_factor);
+
+  view()->OnDisableDeviceEmulation();
+
+  blink::WebDeviceEmulationParams params;
+  view()->OnEnableDeviceEmulation(params);
+  // Don't disable here to test that emulation is being shutdown properly.
+}
+
 // Verify that security origins are replicated properly to RenderFrameProxies
 // when swapping out.
 TEST_F(RenderViewImplTest, OriginReplicationForSwapOut) {
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 6f1a1042..02d0c37 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -580,9 +580,10 @@
     main_render_frame_ = RenderFrameImpl::CreateMainFrame(
         this, params->main_frame_routing_id,
         std::move(main_frame_interface_provider),
-        params->main_frame_widget_routing_id, params->hidden, screen_info(),
-        compositor_deps_, opener_frame, params->devtools_main_frame_token,
-        params->replicated_frame_state, params->has_committed_real_load);
+        params->main_frame_widget_routing_id, params->hidden,
+        GetWebScreenInfo(), compositor_deps_, opener_frame,
+        params->devtools_main_frame_token, params->replicated_frame_state,
+        params->has_committed_real_load);
   }
 
   // TODO(dcheng): Shouldn't these be mutually exclusive at this point? See
@@ -1824,7 +1825,7 @@
 }
 
 float RenderViewImpl::GetDeviceScaleFactor() const {
-  return GetWebDeviceScaleFactor();
+  return GetWebScreenInfo().device_scale_factor;
 }
 
 float RenderViewImpl::GetZoomLevel() const {
@@ -1914,8 +1915,10 @@
 
   if (IsUseZoomForDSFEnabled()) {
     webview()->EnableAutoResizeMode(
-        gfx::ScaleToCeiledSize(min_size, GetWebDeviceScaleFactor()),
-        gfx::ScaleToCeiledSize(max_size, GetWebDeviceScaleFactor()));
+        gfx::ScaleToCeiledSize(min_size,
+                               GetWebScreenInfo().device_scale_factor),
+        gfx::ScaleToCeiledSize(max_size,
+                               GetWebScreenInfo().device_scale_factor));
   } else {
     webview()->EnableAutoResizeMode(min_size, max_size);
   }
@@ -1964,8 +1967,10 @@
 
   if (IsUseZoomForDSFEnabled()) {
     webview()->EnableAutoResizeMode(
-        gfx::ScaleToCeiledSize(min_size, GetWebDeviceScaleFactor()),
-        gfx::ScaleToCeiledSize(max_size, GetWebDeviceScaleFactor()));
+        gfx::ScaleToCeiledSize(min_size,
+                               GetWebScreenInfo().device_scale_factor),
+        gfx::ScaleToCeiledSize(max_size,
+                               GetWebScreenInfo().device_scale_factor));
   } else {
     webview()->EnableAutoResizeMode(min_size, max_size);
   }
@@ -2295,7 +2300,8 @@
 
   // The touch_rect, target_rects and zoom_rect are in the outer viewport
   // reference frame.
-  float to_pix = IsUseZoomForDSFEnabled() ? 1 : GetWebDeviceScaleFactor();
+  float to_pix =
+      IsUseZoomForDSFEnabled() ? 1 : GetWebScreenInfo().device_scale_factor;
   gfx::Rect zoom_rect;
   float new_total_scale =
       DisambiguationPopupHelper::ComputeZoomAreaAndScaleFactor(
@@ -2338,7 +2344,7 @@
         // device scale will be applied in WebKit
         // --> zoom_rect doesn't include device scale,
         //     but WebKit will still draw on zoom_rect *
-        //     GetWebDeviceScaleFactor()
+        //     GetWebScreenInfo().device_scale_factor
         canvas.scale(new_total_scale / to_pix, new_total_scale / to_pix);
         canvas.translate(-zoom_rect.x() * to_pix, -zoom_rect.y() * to_pix);
 
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 6f222635..0199552 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -443,6 +443,8 @@
                            ScreenMetricsEmulationWithOriginalDSF1);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplScaleFactorTest,
                            ScreenMetricsEmulationWithOriginalDSF2);
+  FRIEND_TEST_ALL_PREFIXES(RenderViewImplScaleFactorTest,
+                           DeviceEmulationWithOOPIF);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
                            DecideNavigationPolicyHandlesAllTopLevel);
 #if defined(OS_MACOSX)
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index a985c6e9..b87c3a9 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -768,8 +768,8 @@
   ResizeParams params;
   params.screen_info = screen_info_;
   params.new_size = new_window_rect.size();
-  params.compositor_viewport_pixel_size =
-      gfx::ScaleToCeiledSize(new_window_rect.size(), GetWebDeviceScaleFactor());
+  params.compositor_viewport_pixel_size = gfx::ScaleToCeiledSize(
+      new_window_rect.size(), GetWebScreenInfo().device_scale_factor);
   params.visible_viewport_size = new_window_rect.size();
   params.is_fullscreen_granted = is_fullscreen_granted_;
   params.display_mode = display_mode_;
@@ -1356,8 +1356,10 @@
 }
 
 gfx::Size RenderWidget::GetSizeForWebWidget() const {
-  if (IsUseZoomForDSFEnabled())
-    return gfx::ScaleToCeiledSize(size_, GetOriginalDeviceScaleFactor());
+  if (IsUseZoomForDSFEnabled()) {
+    return gfx::ScaleToCeiledSize(size_,
+                                  GetOriginalScreenInfo().device_scale_factor);
+  }
 
   return size_;
 }
@@ -1432,9 +1434,9 @@
 
   WebSize visual_viewport_size;
   if (IsUseZoomForDSFEnabled()) {
-    visual_viewport_size = gfx::ScaleToCeiledSize(
-        params.visible_viewport_size,
-        GetOriginalDeviceScaleFactor());
+    visual_viewport_size =
+        gfx::ScaleToCeiledSize(params.visible_viewport_size,
+                               GetOriginalScreenInfo().device_scale_factor);
   } else {
     visual_viewport_size = visible_viewport_size_;
   }
@@ -1716,13 +1718,14 @@
   blink::WebView* webview = current_frame ? current_frame->View() : nullptr;
   if (webview) {
     if (IsUseZoomForDSFEnabled())
-      webview->SetZoomFactorForDeviceScaleFactor(GetWebDeviceScaleFactor());
+      webview->SetZoomFactorForDeviceScaleFactor(
+          GetWebScreenInfo().device_scale_factor);
     else
-      webview->SetDeviceScaleFactor(GetWebDeviceScaleFactor());
+      webview->SetDeviceScaleFactor(GetWebScreenInfo().device_scale_factor);
 
     webview->GetSettings()->SetPreferCompositingToLCDTextEnabled(
         PreferCompositingToLCDText(compositor_deps_,
-                                   GetWebDeviceScaleFactor()));
+                                   GetWebScreenInfo().device_scale_factor));
   }
 }
 
@@ -1934,12 +1937,12 @@
     viz::LocalSurfaceId new_local_surface_id,
     const gfx::Size& new_compositor_viewport_pixel_size,
     const ScreenInfo& new_screen_info) {
-  bool screen_info_changed = screen_info_ != new_screen_info;
   bool orientation_changed =
       screen_info_.orientation_angle != new_screen_info.orientation_angle ||
       screen_info_.orientation_type != new_screen_info.orientation_type;
   bool web_device_scale_factor_changed =
       screen_info_.device_scale_factor != new_screen_info.device_scale_factor;
+  ScreenInfo previous_original_screen_info = GetOriginalScreenInfo();
 
   local_surface_id_ = new_local_surface_id;
   compositor_viewport_pixel_size_ = new_compositor_viewport_pixel_size;
@@ -1948,21 +1951,21 @@
   if (compositor_) {
     // Note carefully that the DSF specified in |new_screen_info| is not the
     // DSF used by the compositor during device emulation!
-    compositor_->SetViewportSizeAndScale(compositor_viewport_pixel_size_,
-                                         GetOriginalDeviceScaleFactor(),
-                                         local_surface_id_);
+    compositor_->SetViewportSizeAndScale(
+        compositor_viewport_pixel_size_,
+        GetOriginalScreenInfo().device_scale_factor, local_surface_id_);
   }
 
   if (orientation_changed)
     OnOrientationChange();
 
-  if (screen_info_changed) {
+  if (previous_original_screen_info != GetOriginalScreenInfo()) {
     for (auto& observer : render_frame_proxies_)
-      observer.OnScreenInfoChanged(screen_info_);
+      observer.OnScreenInfoChanged(GetOriginalScreenInfo());
 
     // Notify all embedded BrowserPlugins of the updated ScreenInfo.
     for (auto& observer : browser_plugins_)
-      observer.ScreenInfoChanged(screen_info_);
+      observer.ScreenInfoChanged(GetOriginalScreenInfo());
   }
 
   if (web_device_scale_factor_changed)
@@ -2170,7 +2173,7 @@
 
 void RenderWidget::ConvertViewportToWindow(blink::WebRect* rect) {
   if (IsUseZoomForDSFEnabled()) {
-    float reverse = 1 / GetOriginalDeviceScaleFactor();
+    float reverse = 1 / GetOriginalScreenInfo().device_scale_factor;
     // TODO(oshima): We may need to allow pixel precision here as the the
     // anchor element can be placed at half pixel.
     gfx::Rect window_rect =
@@ -2184,10 +2187,10 @@
 
 void RenderWidget::ConvertWindowToViewport(blink::WebFloatRect* rect) {
   if (IsUseZoomForDSFEnabled()) {
-    rect->x *= GetOriginalDeviceScaleFactor();
-    rect->y *= GetOriginalDeviceScaleFactor();
-    rect->width *= GetOriginalDeviceScaleFactor();
-    rect->height *= GetOriginalDeviceScaleFactor();
+    rect->x *= GetOriginalScreenInfo().device_scale_factor;
+    rect->y *= GetOriginalScreenInfo().device_scale_factor;
+    rect->width *= GetOriginalScreenInfo().device_scale_factor;
+    rect->height *= GetOriginalScreenInfo().device_scale_factor;
   }
 }
 
@@ -2382,7 +2385,7 @@
     // calculation of |new_compositor_viewport_pixel_size| does not appear to
     // take into account device emulation.
     gfx::Size new_compositor_viewport_pixel_size =
-        gfx::ScaleToCeiledSize(size_, GetWebDeviceScaleFactor());
+        gfx::ScaleToCeiledSize(size_, GetWebScreenInfo().device_scale_factor);
     UpdateSurfaceAndScreenInfo(viz::LocalSurfaceId(),
                                new_compositor_viewport_pixel_size,
                                screen_info_);
@@ -2514,12 +2517,14 @@
                         !tapped_node.IsContentEditable() &&
                         !tapped_node.IsInsideFocusableElementOrARIAWidget();
   if (should_trigger) {
-    float x_px = IsUseZoomForDSFEnabled()
-                     ? tapped_position.x
-                     : tapped_position.x * GetWebDeviceScaleFactor();
-    float y_px = IsUseZoomForDSFEnabled()
-                     ? tapped_position.y
-                     : tapped_position.y * GetWebDeviceScaleFactor();
+    float x_px =
+        IsUseZoomForDSFEnabled()
+            ? tapped_position.x
+            : tapped_position.x * GetWebScreenInfo().device_scale_factor;
+    float y_px =
+        IsUseZoomForDSFEnabled()
+            ? tapped_position.y
+            : tapped_position.y * GetWebScreenInfo().device_scale_factor;
     Send(new ViewHostMsg_ShowUnhandledTapUIIfNeeded(routing_id_, x_px, y_px));
   }
 }
@@ -2644,15 +2649,14 @@
                MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE);
 }
 
-float RenderWidget::GetWebDeviceScaleFactor() const {
-  return screen_info_.device_scale_factor;
+const ScreenInfo& RenderWidget::GetWebScreenInfo() const {
+  return screen_info_;
 }
 
-float RenderWidget::GetOriginalDeviceScaleFactor() const {
+const ScreenInfo& RenderWidget::GetOriginalScreenInfo() const {
   return screen_metrics_emulator_
              ? screen_metrics_emulator_->original_screen_info()
-                   .device_scale_factor
-             : screen_info_.device_scale_factor;
+             : screen_info_;
 }
 
 gfx::PointF RenderWidget::ConvertWindowPointToViewport(
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index 0660e31..7314970 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -212,9 +212,6 @@
 
   RenderWidgetOwnerDelegate* owner_delegate() const { return owner_delegate_; }
 
-  // ScreenInfo exposed so it can be passed to subframe RenderWidgets.
-  ScreenInfo screen_info() const { return screen_info_; }
-
   // Sets whether this RenderWidget has been swapped out to be displayed by
   // a RenderWidget in a different process.  If so, no new IPC messages will be
   // sent (only ACKs) and the process is free to exit when there are no other
@@ -411,12 +408,12 @@
     return mouse_lock_dispatcher_.get();
   }
 
-  // Returns the device scale factor exposed to Blink. In device emulation, this
-  // may not match the compositor device scale factor.
-  float GetWebDeviceScaleFactor() const;
+  // Returns the ScreenInfo exposed to Blink. In device emulation, this
+  // may not match the compositor ScreenInfo.
+  const ScreenInfo& GetWebScreenInfo() const;
 
-  // When emulated, this returns original (non-emulated) device scale factor.
-  float GetOriginalDeviceScaleFactor() const;
+  // When emulated, this returns the original (non-emulated) ScreenInfo.
+  const ScreenInfo& GetOriginalScreenInfo() const;
 
   // Helper to convert |point| using ConvertWindowToViewport().
   gfx::PointF ConvertWindowPointToViewport(const gfx::PointF& point);
diff --git a/content/renderer/service_worker/embedded_worker_instance_client_impl.cc b/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
index 69c1df6..c82d9a49 100644
--- a/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
+++ b/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
@@ -12,6 +12,7 @@
 #include "content/child/thread_safe_sender.h"
 #include "content/common/service_worker/service_worker_utils.h"
 #include "content/public/common/content_client.h"
+#include "content/renderer/render_thread_impl.h"
 #include "content/renderer/service_worker/service_worker_context_client.h"
 #include "content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h"
 #include "third_party/WebKit/public/platform/WebContentSettingsClient.h"
@@ -66,7 +67,9 @@
       std::move(params->controller_request),
       std::move(params->service_worker_host), std::move(params->instance_host),
       std::move(params->provider_info), std::move(temporal_self_),
-      ChildThreadImpl::current()->thread_safe_sender(), io_thread_runner_);
+      ChildThreadImpl::current()->thread_safe_sender(),
+      RenderThreadImpl::current()->GetRendererScheduler()->DefaultTaskRunner(),
+      io_thread_runner_);
   client->set_blink_initialized_time(blink_initialized_time_);
   client->set_start_worker_received_time(base::TimeTicks::Now());
   wrapper_ = StartWorkerContext(std::move(params), std::move(client),
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
index f2d9aa4..566b36b 100644
--- a/content/renderer/service_worker/service_worker_context_client.cc
+++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -764,13 +764,14 @@
     mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
     std::unique_ptr<EmbeddedWorkerInstanceClientImpl> embedded_worker_client,
     scoped_refptr<ThreadSafeSender> sender,
+    scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner)
     : embedded_worker_id_(embedded_worker_id),
       service_worker_version_id_(service_worker_version_id),
       service_worker_scope_(service_worker_scope),
       script_url_(script_url),
       sender_(sender),
-      main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+      main_thread_task_runner_(std::move(main_thread_task_runner)),
       io_thread_task_runner_(io_thread_task_runner),
       proxy_(nullptr),
       pending_dispatcher_request_(std::move(dispatcher_request)),
diff --git a/content/renderer/service_worker/service_worker_context_client.h b/content/renderer/service_worker/service_worker_context_client.h
index 86e0bd0..31beebba 100644
--- a/content/renderer/service_worker/service_worker_context_client.h
+++ b/content/renderer/service_worker/service_worker_context_client.h
@@ -99,6 +99,7 @@
       mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info,
       std::unique_ptr<EmbeddedWorkerInstanceClientImpl> embedded_worker_client,
       scoped_refptr<ThreadSafeSender> sender,
+      scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner);
   ~ServiceWorkerContextClient() override;
 
diff --git a/content/renderer/service_worker/service_worker_context_client_unittest.cc b/content/renderer/service_worker/service_worker_context_client_unittest.cc
index bd0b49f..3a9bbd8d 100644
--- a/content/renderer/service_worker/service_worker_context_client_unittest.cc
+++ b/content/renderer/service_worker/service_worker_context_client_unittest.cc
@@ -36,6 +36,7 @@
 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerClientsInfo.h"
 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerError.h"
 #include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerRequest.h"
+#include "third_party/WebKit/public/platform/scheduler/test/renderer_scheduler_test_support.h"
 #include "third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextProxy.h"
 
 namespace content {
@@ -266,7 +267,9 @@
         embedded_worker_host_ptr.PassInterface(),
         CreateProviderInfo(&out_pipes->registration_host_request,
                            &out_pipes->registration),
-        nullptr /* embedded_worker_client */, sender_, io_task_runner());
+        nullptr /* embedded_worker_client */, sender_,
+        blink::scheduler::GetSingleThreadTaskRunnerForTesting(),
+        io_task_runner());
   }
 
   scoped_refptr<base::TestMockTimeTaskRunner> task_runner() const {
diff --git a/content/shell/browser/layout_test/layout_test_url_request_context_getter.cc b/content/shell/browser/layout_test/layout_test_url_request_context_getter.cc
index 693adbf..c4524d4b 100644
--- a/content/shell/browser/layout_test/layout_test_url_request_context_getter.cc
+++ b/content/shell/browser/layout_test/layout_test_url_request_context_getter.cc
@@ -13,7 +13,7 @@
 #include "content/shell/browser/shell_network_delegate.h"
 #include "content/shell/common/layout_test/layout_test_switches.h"
 #include "net/cert/cert_verifier.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "services/network/ignore_errors_cert_verifier.h"
 
 namespace content {
diff --git a/content/shell/browser/shell_url_request_context_getter.cc b/content/shell/browser/shell_url_request_context_getter.cc
index baa6a70..dcb1541 100644
--- a/content/shell/browser/shell_url_request_context_getter.cc
+++ b/content/shell/browser/shell_url_request_context_getter.cc
@@ -34,7 +34,7 @@
 #include "net/http/http_network_session.h"
 #include "net/net_features.h"
 #include "net/proxy_resolution/proxy_config_service.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/ssl/channel_id_service.h"
 #include "net/ssl/default_channel_id_store.h"
 #include "net/url_request/url_request_context.h"
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 80d181b3..1708eeb0 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -870,6 +870,7 @@
     "//components/discardable_memory/service",
     "//components/network_session_configurator/common",
     "//components/payments/mojom",
+    "//components/url_formatter:url_formatter",
     "//components/viz/test:test_support",
     "//content:resources",
     "//content/app:both_for_content_tests",
diff --git a/content/test/proxy_service_mojo_unittest.cc b/content/test/proxy_service_mojo_unittest.cc
index 137cea2..a8da0469 100644
--- a/content/test/proxy_service_mojo_unittest.cc
+++ b/content/test/proxy_service_mojo_unittest.cc
@@ -24,7 +24,7 @@
 #include "net/proxy_resolution/dhcp_pac_file_fetcher.h"
 #include "net/proxy_resolution/mock_pac_file_fetcher.h"
 #include "net/proxy_resolution/proxy_config_service_fixed.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/test/event_waiter.h"
 #include "net/test/gtest_util.h"
 #include "services/network/proxy_service_mojo.h"
diff --git a/device/BUILD.gn b/device/BUILD.gn
index e74dfc2..68420c599 100644
--- a/device/BUILD.gn
+++ b/device/BUILD.gn
@@ -68,6 +68,7 @@
     "fido/ctap_response_unittest.cc",
     "fido/fake_u2f_discovery_unittest.cc",
     "fido/fido_hid_message_unittest.cc",
+    "fido/test_callback_receiver_unittest.cc",
     "fido/u2f_apdu_unittest.cc",
     "fido/u2f_ble_connection_unittest.cc",
     "fido/u2f_ble_device_unittest.cc",
diff --git a/device/fido/BUILD.gn b/device/fido/BUILD.gn
index 464db35..45b8b72 100644
--- a/device/fido/BUILD.gn
+++ b/device/fido/BUILD.gn
@@ -217,6 +217,7 @@
   sources = [
     "fake_u2f_discovery.cc",
     "fake_u2f_discovery.h",
+    "test_callback_receiver.h",
   ]
   deps = [
     "//base",
diff --git a/device/fido/test_callback_receiver.h b/device/fido/test_callback_receiver.h
new file mode 100644
index 0000000..1a93bc5
--- /dev/null
+++ b/device/fido/test_callback_receiver.h
@@ -0,0 +1,121 @@
+// 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 DEVICE_FIDO_TEST_CALLBACK_RECEIVER_H_
+#define DEVICE_FIDO_TEST_CALLBACK_RECEIVER_H_
+
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/optional.h"
+#include "base/run_loop.h"
+
+namespace device {
+namespace test {
+
+// Serves as a testing callback target on which callbacks with an arbitrary
+// signature `void(CallbackArgs...)` can be invoked on.
+//
+// Example usage:
+//   base::test::ScopedTaskEnvironment task_environment;
+//   TestCallbackReceiver<int> callback_receiver;
+//
+//   // Manufacture the base::OnceCallback whose invovcation will be received
+//   // by this instance.
+//   auto callback = callback_receiver.callback();
+//
+//   // Pass |callback| into testing code that will invoke it.
+//   DoStuffAndInvokeCallbackWithResult(std::move(callback));
+//
+//   // Spin the message loop until the callback is invoked, and read result.
+//   callback_receiver.WaitForCallback();
+//   DoStuffWithResult(std::get<0>(*callback_receiver.result());
+//
+template <class... CallbackArgs>
+class TestCallbackReceiver {
+ public:
+  using TupleOfNonReferenceArgs =
+      std::tuple<typename std::decay_t<CallbackArgs>...>;
+
+  TestCallbackReceiver() = default;
+  ~TestCallbackReceiver() = default;
+
+  // Whether the |callback| was already called.
+  bool was_called() const { return was_called_; }
+
+  // The result, which is non-null exactly if the callback was already invoked
+  // and the result has not yet been taken with TakeResult().
+  const base::Optional<TupleOfNonReferenceArgs>& result() const {
+    return result_;
+  }
+
+  // Constructs a base::OnceCallback that can be passed into code under test and
+  // be waited, but must not be invoked after |this| instance goes out of scope.
+  //
+  // This method can only be called once during the lifetime of an instance.
+  // Construct multiple TestCallbackReceiver instances for multiple callbacks.
+  base::OnceCallback<void(CallbackArgs...)> callback() {
+    return base::BindOnce(&TestCallbackReceiver::ReceiverMethod,
+                          base::Unretained(this));
+  }
+
+  // Takes a tuple containing the arguments the callback was called with.
+  TupleOfNonReferenceArgs TakeResult() {
+    auto value = std::move(result_).value();
+    result_.reset();
+    return value;
+  }
+
+  // Returns immediately if the |callback()| was already called, otherwise pumps
+  // the current MessageLoop until it is called.
+  void WaitForCallback() {
+    if (was_called_)
+      return;
+    wait_for_callback_loop_.Run();
+  }
+
+ private:
+  void ReceiverMethod(CallbackArgs... args) {
+    result_.emplace(std::move(args)...);
+    was_called_ = true;
+    wait_for_callback_loop_.Quit();
+  }
+
+  bool was_called_ = false;
+  base::RunLoop wait_for_callback_loop_;
+  base::Optional<TupleOfNonReferenceArgs> result_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestCallbackReceiver);
+};
+
+template <class Status>
+class StatusCallbackReceiver : public TestCallbackReceiver<Status> {
+ public:
+  const Status& status() const {
+    return std::get<0>(*TestCallbackReceiver<Status>::result());
+  }
+};
+
+template <class Status, class Value>
+class StatusAndValueCallbackReceiver
+    : public TestCallbackReceiver<Status, Value> {
+ public:
+  const Status& status() const {
+    return std::get<0>(*TestCallbackReceiver<Status, Value>::result());
+  }
+
+  const Value& value() const {
+    return std::get<1>(*TestCallbackReceiver<Status, Value>::result());
+  }
+};
+
+}  // namespace test
+}  // namespace device
+
+#endif  // DEVICE_FIDO_TEST_CALLBACK_RECEIVER_H_
diff --git a/device/fido/test_callback_receiver_unittest.cc b/device/fido/test_callback_receiver_unittest.cc
new file mode 100644
index 0000000..dc31f78f
--- /dev/null
+++ b/device/fido/test_callback_receiver_unittest.cc
@@ -0,0 +1,140 @@
+// 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 "device/fido/test_callback_receiver.h"
+
+#include "base/test/bind_test_util.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace device {
+namespace test {
+
+TEST(TestCallbackReceiver, BasicClosure) {
+  base::test::ScopedTaskEnvironment task_environment;
+  TestCallbackReceiver<> closure_receiver;
+
+  auto closure = closure_receiver.callback();
+
+  EXPECT_FALSE(closure_receiver.was_called());
+  EXPECT_FALSE(closure_receiver.result().has_value());
+  EXPECT_TRUE(closure);
+  std::move(closure).Run();
+
+  EXPECT_TRUE(closure_receiver.was_called());
+  EXPECT_TRUE(closure_receiver.result().has_value());
+  EXPECT_EQ(std::tuple<>(), closure_receiver.TakeResult());
+  EXPECT_TRUE(closure_receiver.was_called());
+  EXPECT_FALSE(closure_receiver.result().has_value());
+}
+
+TEST(TestCallbackReceiver, BasicCopyableArgument) {
+  base::test::ScopedTaskEnvironment task_environment;
+  TestCallbackReceiver<int> callback_receiver;
+
+  auto callback = callback_receiver.callback();
+
+  EXPECT_FALSE(callback_receiver.was_called());
+  EXPECT_FALSE(callback_receiver.result().has_value());
+  EXPECT_TRUE(callback);
+  std::move(callback).Run(42);
+
+  EXPECT_TRUE(callback_receiver.was_called());
+  EXPECT_TRUE(callback_receiver.result().has_value());
+  EXPECT_EQ(std::make_tuple<int>(42), callback_receiver.TakeResult());
+  EXPECT_TRUE(callback_receiver.was_called());
+  EXPECT_FALSE(callback_receiver.result().has_value());
+}
+
+TEST(TestCallbackReceiver, MoveOnlyArgumentIsMoved) {
+  base::test::ScopedTaskEnvironment task_environment;
+  TestCallbackReceiver<std::unique_ptr<int>> callback_receiver;
+
+  auto callback = callback_receiver.callback();
+  std::move(callback).Run(std::make_unique<int>(42));
+
+  auto result = callback_receiver.TakeResult();
+  static_assert(std::tuple_size<decltype(result)>::value == 1u,
+                "The returned tuple should be one-dimensional");
+  ASSERT_TRUE(std::get<0>(result));
+  EXPECT_EQ(42, *std::get<0>(result));
+}
+
+TEST(TestCallbackReceiver, ReferenceArgumentIsCopied) {
+  base::test::ScopedTaskEnvironment task_environment;
+  TestCallbackReceiver<int&> callback_receiver;
+
+  int passed_in_value = 42;
+  auto callback = callback_receiver.callback();
+
+  EXPECT_FALSE(callback_receiver.result().has_value());
+
+  std::move(callback).Run(passed_in_value);
+
+  EXPECT_TRUE(callback_receiver.result().has_value());
+
+  const int& received_value = std::get<0>(*callback_receiver.result());
+  EXPECT_EQ(passed_in_value, received_value);
+
+  passed_in_value = 43;
+  EXPECT_NE(passed_in_value, received_value);
+
+  callback_receiver.TakeResult();
+  EXPECT_FALSE(callback_receiver.result().has_value());
+}
+
+TEST(TestCallbackReceiver, StatusAndValue) {
+  enum class TestStatus { NOT_OK, OK };
+
+  base::test::ScopedTaskEnvironment task_environment;
+  StatusAndValueCallbackReceiver<TestStatus, std::unique_ptr<int>>
+      callback_receiver;
+
+  auto callback = callback_receiver.callback();
+
+  EXPECT_FALSE(callback_receiver.was_called());
+  EXPECT_TRUE(callback);
+  std::move(callback).Run(TestStatus::OK, std::make_unique<int>(1337));
+
+  EXPECT_TRUE(callback_receiver.was_called());
+  EXPECT_EQ(TestStatus::OK, callback_receiver.status());
+  EXPECT_EQ(1337, *callback_receiver.value());
+}
+
+TEST(TestCallbackReceiver, WaitForCallback) {
+  base::test::ScopedTaskEnvironment task_environment;
+  TestCallbackReceiver<> closure_receiver;
+  auto closure = closure_receiver.callback();
+
+  EXPECT_FALSE(closure_receiver.was_called());
+  EXPECT_TRUE(closure);
+
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::BindLambdaForTesting([&closure]() { std::move(closure).Run(); }));
+
+  EXPECT_FALSE(closure_receiver.was_called());
+  closure_receiver.WaitForCallback();
+  EXPECT_TRUE(closure_receiver.was_called());
+}
+
+TEST(TestCallbackReceiver, WaitForCallbackAfterCallback) {
+  base::test::ScopedTaskEnvironment task_environment;
+  TestCallbackReceiver<> closure_receiver;
+
+  auto closure = closure_receiver.callback();
+
+  EXPECT_FALSE(closure_receiver.was_called());
+  EXPECT_TRUE(closure);
+
+  std::move(closure).Run();
+
+  EXPECT_TRUE(closure_receiver.was_called());
+  closure_receiver.WaitForCallback();
+  EXPECT_TRUE(closure_receiver.was_called());
+}
+
+}  // namespace test
+}  // namespace device
diff --git a/device/fido/u2f_ble_device_unittest.cc b/device/fido/u2f_ble_device_unittest.cc
index ce6b063c..94a62c9 100644
--- a/device/fido/u2f_ble_device_unittest.cc
+++ b/device/fido/u2f_ble_device_unittest.cc
@@ -5,43 +5,22 @@
 #include "device/fido/u2f_ble_device.h"
 
 #include "base/optional.h"
-#include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
 #include "device/bluetooth/test/bluetooth_test.h"
 #include "device/fido/mock_u2f_ble_connection.h"
+#include "device/fido/test_callback_receiver.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace device {
+namespace {
 
 using ::testing::_;
 using ::testing::Invoke;
 using ::testing::Test;
-
-namespace {
-
-class TestMessageCallback {
- public:
-  void OnMessage(U2fReturnCode code, const std::vector<uint8_t>& data) {
-    result_ = std::make_pair(code, data);
-    run_loop_->Quit();
-  }
-
-  const std::pair<U2fReturnCode, std::vector<uint8_t>>& WaitForResult() {
-    run_loop_->Run();
-    run_loop_.emplace();
-    return result_;
-  }
-
-  U2fDevice::MessageCallback GetCallback() {
-    return base::BindRepeating(&TestMessageCallback::OnMessage,
-                               base::Unretained(this));
-  }
-
- private:
-  std::pair<U2fReturnCode, std::vector<uint8_t>> result_;
-  base::Optional<base::RunLoop> run_loop_{base::in_place};
-};
+using TestMessageCallbackReceiver =
+    test::StatusAndValueCallbackReceiver<U2fReturnCode,
+                                         const std::vector<uint8_t>&>;
 
 }  // namespace
 
@@ -94,11 +73,12 @@
       .WillOnce(Invoke(
           [this](const auto& data, auto* cb) { std::move(*cb).Run(false); }));
 
-  TestMessageCallback callback;
-  device()->SendPing({'T', 'E', 'S', 'T'}, callback.GetCallback());
+  TestMessageCallbackReceiver callback_receiver;
+  device()->SendPing({'T', 'E', 'S', 'T'}, callback_receiver.callback());
 
-  EXPECT_EQ(std::make_pair(U2fReturnCode::FAILURE, std::vector<uint8_t>()),
-            callback.WaitForResult());
+  callback_receiver.WaitForCallback();
+  EXPECT_EQ(U2fReturnCode::FAILURE, callback_receiver.status());
+  EXPECT_EQ(std::vector<uint8_t>(), callback_receiver.value());
 }
 
 TEST_F(U2fBleDeviceTest, SendPingTest_Failure_Timeout) {
@@ -109,11 +89,12 @@
         scoped_task_environment_.FastForwardBy(U2fDevice::kDeviceTimeout);
       }));
 
-  TestMessageCallback callback;
-  device()->SendPing({'T', 'E', 'S', 'T'}, callback.GetCallback());
+  TestMessageCallbackReceiver callback_receiver;
+  device()->SendPing({'T', 'E', 'S', 'T'}, callback_receiver.callback());
 
-  EXPECT_EQ(std::make_pair(U2fReturnCode::FAILURE, std::vector<uint8_t>()),
-            callback.WaitForResult());
+  callback_receiver.WaitForCallback();
+  EXPECT_EQ(U2fReturnCode::FAILURE, callback_receiver.status());
+  EXPECT_EQ(std::vector<uint8_t>(), callback_receiver.value());
 }
 
 TEST_F(U2fBleDeviceTest, SendPingTest) {
@@ -129,10 +110,12 @@
         std::move(*cb).Run(true);
       }));
 
-  TestMessageCallback callback;
-  device()->SendPing(ping_data, callback.GetCallback());
-  EXPECT_EQ(std::make_pair(U2fReturnCode::SUCCESS, ping_data),
-            callback.WaitForResult());
+  TestMessageCallbackReceiver callback_receiver;
+  device()->SendPing(ping_data, callback_receiver.callback());
+
+  callback_receiver.WaitForCallback();
+  EXPECT_EQ(U2fReturnCode::SUCCESS, callback_receiver.status());
+  EXPECT_EQ(ping_data, callback_receiver.value());
 }
 
 TEST_F(U2fBleDeviceTest, StaticGetIdTest) {
@@ -141,9 +124,9 @@
 }
 
 TEST_F(U2fBleDeviceTest, TryWinkTest) {
-  base::RunLoop run_loop;
-  device()->TryWink(run_loop.QuitClosure());
-  run_loop.Run();
+  test::TestCallbackReceiver<> closure_receiver;
+  device()->TryWink(closure_receiver.callback());
+  closure_receiver.WaitForCallback();
 }
 
 TEST_F(U2fBleDeviceTest, GetIdTest) {
diff --git a/device/fido/u2f_hid_device_unittest.cc b/device/fido/u2f_hid_device_unittest.cc
index 7230b00..10d11eb 100644
--- a/device/fido/u2f_hid_device_unittest.cc
+++ b/device/fido/u2f_hid_device_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <list>
+#include <tuple>
 
 #include "base/bind.h"
 #include "base/containers/span.h"
@@ -12,6 +12,7 @@
 #include "base/test/scoped_mock_time_message_loop_task_runner.h"
 #include "base/test/scoped_task_environment.h"
 #include "device/fido/fake_hid_impl_for_testing.h"
+#include "device/fido/test_callback_receiver.h"
 #include "device/fido/u2f_apdu_command.h"
 #include "device/fido/u2f_apdu_response.h"
 #include "device/fido/u2f_command_type.h"
@@ -32,12 +33,6 @@
 
 namespace {
 
-void ResponseCallback(std::unique_ptr<device::U2fApduResponse>* output,
-                      bool success,
-                      std::unique_ptr<device::U2fApduResponse> response) {
-  *output = std::move(response);
-}
-
 std::string HexEncode(base::span<const uint8_t> in) {
   return base::HexEncode(in.data(), in.size());
 }
@@ -97,107 +92,40 @@
   return hid_device;
 }
 
-}  // namespace
-
-class U2fDeviceEnumerate {
+class U2fDeviceEnumerateCallbackReceiver
+    : public test::TestCallbackReceiver<std::vector<mojom::HidDeviceInfoPtr>> {
  public:
-  explicit U2fDeviceEnumerate(device::mojom::HidManager* hid_manager)
-      : closure_(),
-        callback_(base::BindOnce(&U2fDeviceEnumerate::ReceivedCallback,
-                                 base::Unretained(this))),
-        hid_manager_(hid_manager),
-        run_loop_() {}
-  ~U2fDeviceEnumerate() = default;
+  U2fDeviceEnumerateCallbackReceiver(device::mojom::HidManager* hid_manager)
+      : hid_manager_(hid_manager) {}
+  ~U2fDeviceEnumerateCallbackReceiver() = default;
 
-  void ReceivedCallback(std::vector<device::mojom::HidDeviceInfoPtr> devices) {
-    std::list<std::unique_ptr<U2fHidDevice>> u2f_devices;
-    filter_.SetUsagePage(0xf1d0);
-    for (auto& device_info : devices) {
-      if (filter_.Matches(*device_info))
-        u2f_devices.push_front(std::make_unique<U2fHidDevice>(
+  std::vector<std::unique_ptr<U2fHidDevice>> TakeReturnedDevicesFiltered() {
+    std::vector<std::unique_ptr<U2fHidDevice>> filtered_results;
+    std::vector<mojom::HidDeviceInfoPtr> results;
+    std::tie(results) = TakeResult();
+    for (auto& device_info : results) {
+      HidDeviceFilter filter;
+      filter.SetUsagePage(0xf1d0);
+      if (filter.Matches(*device_info)) {
+        filtered_results.push_back(std::make_unique<U2fHidDevice>(
             std::move(device_info), hid_manager_));
+      }
     }
-    devices_ = std::move(u2f_devices);
-    closure_.Run();
-  }
-
-  std::list<std::unique_ptr<U2fHidDevice>>& WaitForCallback() {
-    closure_ = run_loop_.QuitClosure();
-    run_loop_.Run();
-    return devices_;
-  }
-
-  device::mojom::HidManager::GetDevicesCallback callback() {
-    return std::move(callback_);
+    return filtered_results;
   }
 
  private:
-  HidDeviceFilter filter_;
-  std::list<std::unique_ptr<U2fHidDevice>> devices_;
-  base::Closure closure_;
-  device::mojom::HidManager::GetDevicesCallback callback_;
   device::mojom::HidManager* hid_manager_;
-  base::RunLoop run_loop_;
+
+  DISALLOW_COPY_AND_ASSIGN(U2fDeviceEnumerateCallbackReceiver);
 };
 
-class TestVersionCallback {
- public:
-  TestVersionCallback()
-      : closure_(),
-        callback_(base::BindOnce(&TestVersionCallback::ReceivedCallback,
-                                 base::Unretained(this))),
-        run_loop_() {}
-  ~TestVersionCallback() = default;
+using TestVersionCallbackReceiver =
+    test::StatusAndValueCallbackReceiver<bool, U2fDevice::ProtocolVersion>;
+using TestDeviceCallbackReceiver = ::device::test::
+    StatusAndValueCallbackReceiver<bool, std::unique_ptr<U2fApduResponse>>;
 
-  void ReceivedCallback(bool success, U2fDevice::ProtocolVersion version) {
-    version_ = version;
-    std::move(closure_).Run();
-  }
-
-  U2fDevice::ProtocolVersion WaitForCallback() {
-    closure_ = run_loop_.QuitClosure();
-    run_loop_.Run();
-    return version_;
-  }
-
-  U2fDevice::VersionCallback callback() { return std::move(callback_); }
-
- private:
-  U2fDevice::ProtocolVersion version_;
-  base::OnceClosure closure_;
-  U2fDevice::VersionCallback callback_;
-  base::RunLoop run_loop_;
-};
-
-class TestDeviceCallback {
- public:
-  TestDeviceCallback()
-      : closure_(),
-        callback_(base::Bind(&TestDeviceCallback::ReceivedCallback,
-                             base::Unretained(this))),
-        run_loop_() {}
-  ~TestDeviceCallback() = default;
-
-  void ReceivedCallback(bool success,
-                        std::unique_ptr<U2fApduResponse> response) {
-    response_ = std::move(response);
-    closure_.Run();
-  }
-
-  std::unique_ptr<U2fApduResponse> WaitForCallback() {
-    closure_ = run_loop_.QuitClosure();
-    run_loop_.Run();
-    return std::move(response_);
-  }
-
-  const U2fDevice::DeviceCallback& callback() { return callback_; }
-
- private:
-  std::unique_ptr<U2fApduResponse> response_;
-  base::Closure closure_;
-  U2fDevice::DeviceCallback callback_;
-  base::RunLoop run_loop_;
-};
+}  // namespace
 
 class U2fHidDeviceTest : public ::testing::Test {
  public:
@@ -220,16 +148,15 @@
   if (!U2fHidDevice::IsTestEnabled())
     return;
 
-  U2fDeviceEnumerate callback(hid_manager_.get());
-  hid_manager_->GetDevices(callback.callback());
-  std::list<std::unique_ptr<U2fHidDevice>>& u2f_devices =
-      callback.WaitForCallback();
+  U2fDeviceEnumerateCallbackReceiver receiver(hid_manager_.get());
+  hid_manager_->GetDevices(receiver.callback());
+  receiver.WaitForCallback();
 
-  for (auto& device : u2f_devices) {
-    TestVersionCallback vc;
+  for (auto& device : receiver.TakeReturnedDevicesFiltered()) {
+    TestVersionCallbackReceiver vc;
     device->Version(vc.callback());
-    U2fDevice::ProtocolVersion version = vc.WaitForCallback();
-    EXPECT_EQ(version, U2fDevice::ProtocolVersion::U2F_V2);
+    vc.WaitForCallback();
+    EXPECT_EQ(U2fDevice::ProtocolVersion::U2F_V2, vc.value());
   }
 }
 
@@ -237,114 +164,109 @@
   if (!U2fHidDevice::IsTestEnabled())
     return;
 
-  U2fDeviceEnumerate callback(hid_manager_.get());
-  hid_manager_->GetDevices(callback.callback());
-  std::list<std::unique_ptr<U2fHidDevice>>& u2f_devices =
-      callback.WaitForCallback();
+  U2fDeviceEnumerateCallbackReceiver receiver(hid_manager_.get());
+  hid_manager_->GetDevices(receiver.callback());
+  receiver.WaitForCallback();
 
-  for (auto& device : u2f_devices) {
-    TestVersionCallback vc;
-    TestVersionCallback vc2;
+  for (auto& device : receiver.TakeReturnedDevicesFiltered()) {
+    TestVersionCallbackReceiver vc;
+    TestVersionCallbackReceiver vc2;
     // Call version twice to check message queueing
     device->Version(vc.callback());
     device->Version(vc2.callback());
-    U2fDevice::ProtocolVersion version = vc.WaitForCallback();
-    EXPECT_EQ(version, U2fDevice::ProtocolVersion::U2F_V2);
-    version = vc2.WaitForCallback();
-    EXPECT_EQ(version, U2fDevice::ProtocolVersion::U2F_V2);
+    vc.WaitForCallback();
+    EXPECT_EQ(U2fDevice::ProtocolVersion::U2F_V2, vc.value());
+    vc2.WaitForCallback();
+    EXPECT_EQ(U2fDevice::ProtocolVersion::U2F_V2, vc2.value());
   }
 }
 
 TEST_F(U2fHidDeviceTest, TestConnectionFailure) {
   // Setup and enumerate mock device
-  U2fDeviceEnumerate callback(hid_manager_.get());
+  U2fDeviceEnumerateCallbackReceiver receiver(hid_manager_.get());
   auto hid_device = TestHidDevice();
   fake_hid_manager_->AddDevice(std::move(hid_device));
-  hid_manager_->GetDevices(callback.callback());
+  hid_manager_->GetDevices(receiver.callback());
+  receiver.WaitForCallback();
 
-  std::list<std::unique_ptr<U2fHidDevice>>& u2f_devices =
-      callback.WaitForCallback();
+  std::vector<std::unique_ptr<U2fHidDevice>> u2f_devices =
+      receiver.TakeReturnedDevicesFiltered();
 
   ASSERT_EQ(static_cast<size_t>(1), u2f_devices.size());
   auto& device = u2f_devices.front();
+
   // Put device in IDLE state
-  TestDeviceCallback cb0;
   device->state_ = U2fHidDevice::State::IDLE;
 
   // Manually delete connection
   device->connection_ = nullptr;
+
   // Add pending transactions manually and ensure they are processed
-  std::unique_ptr<U2fApduResponse> response1(
-      U2fApduResponse::CreateFromMessage(std::vector<uint8_t>({0x0, 0x0})));
+  TestDeviceCallbackReceiver receiver_1;
   device->pending_transactions_.emplace(
       U2fApduCommand::CreateVersion()->GetEncodedCommand(),
-      base::BindOnce(&ResponseCallback, &response1));
-  std::unique_ptr<U2fApduResponse> response2(
-      U2fApduResponse::CreateFromMessage(std::vector<uint8_t>({0x0, 0x0})));
+      receiver_1.callback());
+  TestDeviceCallbackReceiver receiver_2;
   device->pending_transactions_.emplace(
       U2fApduCommand::CreateVersion()->GetEncodedCommand(),
-      base::BindOnce(&ResponseCallback, &response2));
-  std::unique_ptr<U2fApduResponse> response3(
-      U2fApduResponse::CreateFromMessage(std::vector<uint8_t>({0x0, 0x0})));
+      receiver_2.callback());
+  TestDeviceCallbackReceiver receiver_3;
   device->DeviceTransact(U2fApduCommand::CreateVersion()->GetEncodedCommand(),
-                         base::BindOnce(&ResponseCallback, &response3));
+                         receiver_3.callback());
   EXPECT_EQ(U2fHidDevice::State::DEVICE_ERROR, device->state_);
-  EXPECT_EQ(nullptr, response1);
-  EXPECT_EQ(nullptr, response2);
-  EXPECT_EQ(nullptr, response3);
+  EXPECT_EQ(nullptr, receiver_1.value());
+  EXPECT_EQ(nullptr, receiver_2.value());
+  EXPECT_EQ(nullptr, receiver_3.value());
 }
 
 TEST_F(U2fHidDeviceTest, TestDeviceError) {
   // Setup and enumerate mock device
-  U2fDeviceEnumerate callback(hid_manager_.get());
-
+  U2fDeviceEnumerateCallbackReceiver receiver(hid_manager_.get());
   auto hid_device = TestHidDevice();
-
   fake_hid_manager_->AddDevice(std::move(hid_device));
-  hid_manager_->GetDevices(callback.callback());
+  hid_manager_->GetDevices(receiver.callback());
+  receiver.WaitForCallback();
 
-  std::list<std::unique_ptr<U2fHidDevice>>& u2f_devices =
-      callback.WaitForCallback();
+  std::vector<std::unique_ptr<U2fHidDevice>> u2f_devices =
+      receiver.TakeReturnedDevicesFiltered();
 
   ASSERT_EQ(static_cast<size_t>(1), u2f_devices.size());
   auto& device = u2f_devices.front();
+
   // Mock connection where writes always fail
   FakeHidConnection::mock_connection_error_ = true;
   device->state_ = U2fHidDevice::State::IDLE;
-  std::unique_ptr<U2fApduResponse> response0(
+  TestDeviceCallbackReceiver receiver_0;
+  std::unique_ptr<U2fApduResponse> response_0(
       U2fApduResponse::CreateFromMessage(std::vector<uint8_t>({0x0, 0x0})));
   device->DeviceTransact(U2fApduCommand::CreateVersion()->GetEncodedCommand(),
-                         base::BindOnce(&ResponseCallback, &response0));
-  EXPECT_EQ(nullptr, response0);
+                         receiver_0.callback());
+  EXPECT_EQ(nullptr, receiver_0.value());
   EXPECT_EQ(U2fHidDevice::State::DEVICE_ERROR, device->state_);
 
   // Add pending transactions manually and ensure they are processed
-  std::unique_ptr<U2fApduResponse> response1(
-      U2fApduResponse::CreateFromMessage(std::vector<uint8_t>({0x0, 0x0})));
+  TestDeviceCallbackReceiver receiver_1;
   device->pending_transactions_.emplace(
       U2fApduCommand::CreateVersion()->GetEncodedCommand(),
-      base::BindOnce(&ResponseCallback, &response1));
-  std::unique_ptr<U2fApduResponse> response2(
-      U2fApduResponse::CreateFromMessage(std::vector<uint8_t>({0x0, 0x0})));
+      receiver_1.callback());
+  TestDeviceCallbackReceiver receiver_2;
   device->pending_transactions_.emplace(
       U2fApduCommand::CreateVersion()->GetEncodedCommand(),
-      base::BindOnce(&ResponseCallback, &response2));
-  std::unique_ptr<U2fApduResponse> response3(
-      U2fApduResponse::CreateFromMessage(std::vector<uint8_t>({0x0, 0x0})));
+      receiver_2.callback());
+  TestDeviceCallbackReceiver receiver_3;
   device->DeviceTransact(U2fApduCommand::CreateVersion()->GetEncodedCommand(),
-                         base::BindOnce(&ResponseCallback, &response3));
+                         receiver_3.callback());
   FakeHidConnection::mock_connection_error_ = false;
 
   EXPECT_EQ(U2fHidDevice::State::DEVICE_ERROR, device->state_);
-  EXPECT_EQ(nullptr, response1);
-  EXPECT_EQ(nullptr, response2);
-  EXPECT_EQ(nullptr, response3);
+  EXPECT_EQ(nullptr, receiver_1.value());
+  EXPECT_EQ(nullptr, receiver_2.value());
+  EXPECT_EQ(nullptr, receiver_3.value());
 }
 
 TEST_F(U2fHidDeviceTest, TestLegacyVersion) {
   const std::vector<uint8_t> kChannelId = {0x01, 0x02, 0x03, 0x04};
 
-  U2fDeviceEnumerate callback(hid_manager_.get());
   auto hid_device = TestHidDevice();
 
   // Replace device HID connection with custom client connection bound to mock
@@ -402,15 +324,19 @@
   fake_hid_manager_->AddDeviceAndSetConnection(std::move(hid_device),
                                                std::move(connection_client));
 
-  hid_manager_->GetDevices(callback.callback());
-  std::list<std::unique_ptr<U2fHidDevice>>& u2f_devices =
-      callback.WaitForCallback();
+  U2fDeviceEnumerateCallbackReceiver receiver(hid_manager_.get());
+  hid_manager_->GetDevices(receiver.callback());
+  receiver.WaitForCallback();
+
+  std::vector<std::unique_ptr<U2fHidDevice>> u2f_devices =
+      receiver.TakeReturnedDevicesFiltered();
 
   ASSERT_EQ(1u, u2f_devices.size());
   auto& device = u2f_devices.front();
-  TestVersionCallback vc;
+  TestVersionCallbackReceiver vc;
   device->Version(vc.callback());
-  EXPECT_EQ(vc.WaitForCallback(), U2fDevice::ProtocolVersion::U2F_V2);
+  vc.WaitForCallback();
+  EXPECT_EQ(U2fDevice::ProtocolVersion::U2F_V2, vc.value());
 }
 
 TEST_F(U2fHidDeviceTest, TestRetryChannelAllocation) {
@@ -419,7 +345,6 @@
 
   const std::vector<uint8_t> kChannelId = {0x01, 0x02, 0x03, 0x04};
 
-  U2fDeviceEnumerate callback(hid_manager_.get());
   auto hid_device = TestHidDevice();
 
   // Replace device HID connection with custom client connection bound to mock
@@ -474,15 +399,19 @@
   fake_hid_manager_->AddDeviceAndSetConnection(std::move(hid_device),
                                                std::move(connection_client));
 
-  hid_manager_->GetDevices(callback.callback());
-  std::list<std::unique_ptr<U2fHidDevice>>& u2f_devices =
-      callback.WaitForCallback();
+  U2fDeviceEnumerateCallbackReceiver receiver(hid_manager_.get());
+  hid_manager_->GetDevices(receiver.callback());
+  receiver.WaitForCallback();
+
+  std::vector<std::unique_ptr<U2fHidDevice>> u2f_devices =
+      receiver.TakeReturnedDevicesFiltered();
 
   ASSERT_EQ(1u, u2f_devices.size());
   auto& device = u2f_devices.front();
-  TestVersionCallback vc;
+  TestVersionCallbackReceiver vc;
   device->Version(vc.callback());
-  EXPECT_EQ(vc.WaitForCallback(), U2fDevice::ProtocolVersion::U2F_V2);
+  vc.WaitForCallback();
+  EXPECT_EQ(U2fDevice::ProtocolVersion::U2F_V2, vc.value());
 }
 
 }  // namespace device
diff --git a/device/fido/u2f_register_unittest.cc b/device/fido/u2f_register_unittest.cc
index 29f1fab..3e4614a96 100644
--- a/device/fido/u2f_register_unittest.cc
+++ b/device/fido/u2f_register_unittest.cc
@@ -18,6 +18,7 @@
 #include "device/fido/fido_attestation_statement.h"
 #include "device/fido/mock_u2f_device.h"
 #include "device/fido/register_response_data.h"
+#include "device/fido/test_callback_receiver.h"
 #include "device/fido/u2f_parsing_utils.h"
 #include "device/fido/u2f_response_test_data.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -285,34 +286,9 @@
   return test_authenticator_object;
 }
 
-class TestRegisterCallback {
- public:
-  TestRegisterCallback()
-      : callback_(base::BindOnce(&TestRegisterCallback::ReceivedCallback,
-                                 base::Unretained(this))) {}
-  ~TestRegisterCallback() = default;
-
-  void ReceivedCallback(U2fReturnCode status_code,
-                        base::Optional<RegisterResponseData> response_data) {
-    response_ = std::make_pair(status_code, std::move(response_data));
-    run_loop_.Quit();
-  }
-
-  const std::pair<U2fReturnCode, base::Optional<RegisterResponseData>>&
-  WaitForCallback() {
-    run_loop_.Run();
-    return response_;
-  }
-
-  U2fRegister::RegisterResponseCallback callback() {
-    return std::move(callback_);
-  }
-
- private:
-  std::pair<U2fReturnCode, base::Optional<RegisterResponseData>> response_;
-  U2fRegister::RegisterResponseCallback callback_;
-  base::RunLoop run_loop_;
-};
+using TestRegisterCallback = ::device::test::StatusAndValueCallbackReceiver<
+    U2fReturnCode,
+    base::Optional<RegisterResponseData>>;
 
 }  // namespace
 
@@ -337,18 +313,20 @@
         base::flat_set<U2fTransportProtocol>(
             {U2fTransportProtocol::kUsbHumanInterfaceDevice}),
         registered_keys, std::vector<uint8_t>(32), std::vector<uint8_t>(32),
-        kNoIndividualAttestation, register_callback_.callback());
+        kNoIndividualAttestation, register_callback_receiver_.callback());
   }
 
   test::FakeU2fDiscovery* discovery() const { return discovery_; }
-  TestRegisterCallback& register_callback() { return register_callback_; }
+  TestRegisterCallback& register_callback_receiver() {
+    return register_callback_receiver_;
+  }
 
  protected:
   base::test::ScopedTaskEnvironment scoped_task_environment_;
 
   test::ScopedFakeU2fDiscoveryFactory scoped_fake_discovery_factory_;
   test::FakeU2fDiscovery* discovery_;
-  TestRegisterCallback register_callback_;
+  TestRegisterCallback register_callback_receiver_;
 };
 
 TEST_F(U2fRegisterTest, TestCreateU2fRegisterCommand) {
@@ -382,7 +360,7 @@
       std::vector<uint8_t>(std::begin(kChallengeDigest),
                            std::end(kChallengeDigest)),
       std::vector<uint8_t>(std::begin(kAppIdDigest), std::end(kAppIdDigest)),
-      kNoIndividualAttestation, register_callback().callback());
+      kNoIndividualAttestation, register_callback_receiver().callback());
 
   const auto register_command_without_individual_attestation =
       register_request.GetU2fRegisterApduCommand(kNoIndividualAttestation);
@@ -413,9 +391,10 @@
       .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device));
 
-  const auto& response = register_callback().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, std::get<0>(response));
-  EXPECT_EQ(GetTestCredentialRawIdBytes(), std::get<1>(response)->raw_id());
+  register_callback_receiver().WaitForCallback();
+  EXPECT_EQ(U2fReturnCode::SUCCESS, register_callback_receiver().status());
+  EXPECT_EQ(GetTestCredentialRawIdBytes(),
+            register_callback_receiver().value()->raw_id());
 }
 
 TEST_F(U2fRegisterTest, TestDelayedSuccess) {
@@ -434,9 +413,10 @@
       .WillRepeatedly(::testing::Invoke(MockU2fDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device));
 
-  const auto& response = register_callback().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, std::get<0>(response));
-  EXPECT_EQ(GetTestCredentialRawIdBytes(), std::get<1>(response)->raw_id());
+  register_callback_receiver().WaitForCallback();
+  EXPECT_EQ(U2fReturnCode::SUCCESS, register_callback_receiver().status());
+  EXPECT_EQ(GetTestCredentialRawIdBytes(),
+            register_callback_receiver().value()->raw_id());
 }
 
 TEST_F(U2fRegisterTest, TestMultipleDevices) {
@@ -463,10 +443,10 @@
   discovery()->AddDevice(std::move(device1));
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
-  const auto& response = register_callback().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, std::get<0>(response));
+  register_callback_receiver().WaitForCallback();
+  EXPECT_EQ(U2fReturnCode::SUCCESS, register_callback_receiver().status());
   EXPECT_EQ(GetTestCredentialRawIdBytes(),
-            std::get<1>(response).value().raw_id());
+            register_callback_receiver().value()->raw_id());
 }
 
 // Tests a scenario where a single device is connected and registration call
@@ -501,9 +481,10 @@
       .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device));
 
-  const auto& response = register_callback().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, std::get<0>(response));
-  EXPECT_EQ(GetTestCredentialRawIdBytes(), std::get<1>(response)->raw_id());
+  register_callback_receiver().WaitForCallback();
+  EXPECT_EQ(U2fReturnCode::SUCCESS, register_callback_receiver().status());
+  EXPECT_EQ(GetTestCredentialRawIdBytes(),
+            register_callback_receiver().value()->raw_id());
 }
 
 // Tests a scenario where two devices are connected and registration call is
@@ -552,9 +533,10 @@
   discovery()->AddDevice(std::move(device1));
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
-  const auto& response = register_callback().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, std::get<0>(response));
-  EXPECT_EQ(GetTestCredentialRawIdBytes(), std::get<1>(response)->raw_id());
+  register_callback_receiver().WaitForCallback();
+  EXPECT_EQ(U2fReturnCode::SUCCESS, register_callback_receiver().status());
+  EXPECT_EQ(GetTestCredentialRawIdBytes(),
+            register_callback_receiver().value()->raw_id());
 }
 
 // Tests a scenario where single device is connected and registration is called
@@ -591,9 +573,10 @@
       .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device));
 
-  const auto& response = register_callback().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::CONDITIONS_NOT_SATISFIED, std::get<0>(response));
-  EXPECT_EQ(base::nullopt, std::get<1>(response));
+  register_callback_receiver().WaitForCallback();
+  EXPECT_EQ(U2fReturnCode::CONDITIONS_NOT_SATISFIED,
+            register_callback_receiver().status());
+  EXPECT_EQ(base::nullopt, register_callback_receiver().value());
 }
 
 // Tests a scenario where one (device1) of the two devices connected has created
@@ -642,9 +625,10 @@
   discovery()->AddDevice(std::move(device1));
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
-  const auto& response = register_callback().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::CONDITIONS_NOT_SATISFIED, std::get<0>(response));
-  EXPECT_EQ(base::nullopt, std::get<1>(response));
+  register_callback_receiver().WaitForCallback();
+  EXPECT_EQ(U2fReturnCode::CONDITIONS_NOT_SATISFIED,
+            register_callback_receiver().status());
+  EXPECT_EQ(base::nullopt, register_callback_receiver().value());
 }
 
 // These test the parsing of the U2F raw bytes of the registration response.
@@ -780,9 +764,9 @@
         .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
     discovery()->AddDevice(std::move(device));
 
-    const auto& response = cb.WaitForCallback();
-    EXPECT_EQ(U2fReturnCode::SUCCESS, std::get<0>(response));
-    EXPECT_EQ(GetTestCredentialRawIdBytes(), std::get<1>(response)->raw_id());
+    cb.WaitForCallback();
+    EXPECT_EQ(U2fReturnCode::SUCCESS, cb.status());
+    EXPECT_EQ(GetTestCredentialRawIdBytes(), cb.value()->raw_id());
   }
 }
 
diff --git a/device/fido/u2f_sign_unittest.cc b/device/fido/u2f_sign_unittest.cc
index f212e2b..d0522d3 100644
--- a/device/fido/u2f_sign_unittest.cc
+++ b/device/fido/u2f_sign_unittest.cc
@@ -12,6 +12,7 @@
 #include "device/fido/fake_u2f_discovery.h"
 #include "device/fido/mock_u2f_device.h"
 #include "device/fido/sign_response_data.h"
+#include "device/fido/test_callback_receiver.h"
 #include "device/fido/u2f_response_test_data.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -99,36 +100,9 @@
                               test_data::kTestU2fSignResponse + length);
 }
 
-class TestSignCallback {
- public:
-  TestSignCallback()
-      : callback_(base::Bind(&TestSignCallback::ReceivedCallback,
-                             base::Unretained(this))) {}
-  ~TestSignCallback() = default;
-
-  void ReceivedCallback(U2fReturnCode status_code,
-                        base::Optional<SignResponseData> response_data) {
-    response_ = std::make_pair(status_code, std::move(response_data));
-    run_loop_.Quit();
-  }
-
-  void WaitForCallback() {
-    run_loop_.Run();
-  }
-
-  U2fReturnCode GetReturnCode() { return std::get<0>(response_); }
-
-  const base::Optional<SignResponseData>& GetResponseData() {
-    return std::get<1>(response_);
-  }
-
-  U2fSign::SignResponseCallback callback() { return std::move(callback_); }
-
- private:
-  std::pair<U2fReturnCode, base::Optional<SignResponseData>> response_;
-  U2fSign::SignResponseCallback callback_;
-  base::RunLoop run_loop_;
-};
+using TestSignCallback = ::device::test::StatusAndValueCallbackReceiver<
+    U2fReturnCode,
+    base::Optional<SignResponseData>>;
 
 }  // namespace
 
@@ -154,17 +128,17 @@
         base::flat_set<U2fTransportProtocol>(
             {U2fTransportProtocol::kUsbHumanInterfaceDevice}),
         registered_keys, std::vector<uint8_t>(32), std::vector<uint8_t>(32),
-        base::nullopt, sign_callback_.callback());
+        base::nullopt, sign_callback_receiver_.callback());
   }
 
   test::FakeU2fDiscovery* discovery() const { return discovery_; }
-  TestSignCallback& sign_callback() { return sign_callback_; }
+  TestSignCallback& sign_callback_receiver() { return sign_callback_receiver_; }
 
  protected:
   base::test::ScopedTaskEnvironment scoped_task_environment_;
   test::ScopedFakeU2fDiscoveryFactory scoped_fake_discovery_factory_;
   test::FakeU2fDiscovery* discovery_;
-  TestSignCallback sign_callback_;
+  TestSignCallback sign_callback_receiver_;
 };
 
 TEST_F(U2fSignTest, TestCreateSignApduCommand) {
@@ -219,7 +193,7 @@
                    std::vector<uint8_t>(std::begin(kChallengeDigest),
                                         std::end(kChallengeDigest)),
                    std::vector<uint8_t>(std::begin(kAppId), std::end(kAppId)),
-                   base::nullopt, sign_callback().callback());
+                   base::nullopt, sign_callback_receiver().callback());
 
   const auto encoded_sign = u2f_sign.GetU2fSignApduCommand(key_handle);
   ASSERT_TRUE(encoded_sign);
@@ -247,15 +221,15 @@
       .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device));
 
-  sign_callback().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, sign_callback().GetReturnCode());
+  sign_callback_receiver().WaitForCallback();
+  EXPECT_EQ(U2fReturnCode::SUCCESS, sign_callback_receiver().status());
 
   // Correct key was sent so a sign response is expected.
   EXPECT_EQ(GetTestAssertionSignature(),
-            sign_callback().GetResponseData()->signature());
+            sign_callback_receiver().value()->signature());
 
   // Verify that we get the key handle used for signing.
-  EXPECT_EQ(signing_key_handle, sign_callback().GetResponseData()->raw_id());
+  EXPECT_EQ(signing_key_handle, sign_callback_receiver().value()->raw_id());
 }
 
 TEST_F(U2fSignTest, TestDelayedSuccess) {
@@ -275,15 +249,15 @@
       .WillRepeatedly(::testing::Invoke(MockU2fDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device));
 
-  sign_callback().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, sign_callback().GetReturnCode());
+  sign_callback_receiver().WaitForCallback();
+  EXPECT_EQ(U2fReturnCode::SUCCESS, sign_callback_receiver().status());
 
   // Correct key was sent so a sign response is expected
   EXPECT_EQ(GetTestAssertionSignature(),
-            sign_callback().GetResponseData()->signature());
+            sign_callback_receiver().value()->signature());
 
   // Verify that we get the key handle used for signing
-  EXPECT_EQ(signing_key_handle, sign_callback().GetResponseData()->raw_id());
+  EXPECT_EQ(signing_key_handle, sign_callback_receiver().value()->raw_id());
 }
 
 TEST_F(U2fSignTest, TestMultipleHandles) {
@@ -309,15 +283,15 @@
       .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device));
 
-  sign_callback().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, sign_callback().GetReturnCode());
+  sign_callback_receiver().WaitForCallback();
+  EXPECT_EQ(U2fReturnCode::SUCCESS, sign_callback_receiver().status());
 
   // Correct key was sent so a sign response is expected.
   EXPECT_EQ(GetTestAssertionSignature(),
-            sign_callback().GetResponseData()->signature());
+            sign_callback_receiver().value()->signature());
 
   // Verify that we get the key handle used for signing.
-  EXPECT_EQ(correct_key_handle, sign_callback().GetResponseData()->raw_id());
+  EXPECT_EQ(correct_key_handle, sign_callback_receiver().value()->raw_id());
 }
 
 TEST_F(U2fSignTest, TestMultipleDevices) {
@@ -347,15 +321,15 @@
   discovery()->AddDevice(std::move(device1));
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
-  sign_callback().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, sign_callback().GetReturnCode());
+  sign_callback_receiver().WaitForCallback();
+  EXPECT_EQ(U2fReturnCode::SUCCESS, sign_callback_receiver().status());
 
   // Correct key was sent so a sign response is expected.
   EXPECT_EQ(GetTestAssertionSignature(),
-            sign_callback().GetResponseData()->signature());
+            sign_callback_receiver().value()->signature());
 
   // Verify that we get the key handle used for signing.
-  EXPECT_EQ(correct_key_handle, sign_callback().GetResponseData()->raw_id());
+  EXPECT_EQ(correct_key_handle, sign_callback_receiver().value()->raw_id());
 }
 
 TEST_F(U2fSignTest, TestFakeEnroll) {
@@ -388,11 +362,11 @@
   discovery()->AddDevice(std::move(device1));
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
-  sign_callback().WaitForCallback();
+  sign_callback_receiver().WaitForCallback();
   // Device that responded had no correct keys.
   EXPECT_EQ(U2fReturnCode::CONDITIONS_NOT_SATISFIED,
-            sign_callback().GetReturnCode());
-  EXPECT_FALSE(sign_callback().GetResponseData());
+            sign_callback_receiver().status());
+  EXPECT_FALSE(sign_callback_receiver().value());
 }
 
 TEST_F(U2fSignTest, TestAuthenticatorDataForSign) {
@@ -471,9 +445,9 @@
       .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device));
 
-  sign_callback().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::FAILURE, sign_callback().GetReturnCode());
-  EXPECT_FALSE(sign_callback().GetResponseData());
+  sign_callback_receiver().WaitForCallback();
+  EXPECT_EQ(U2fReturnCode::FAILURE, sign_callback_receiver().status());
+  EXPECT_FALSE(sign_callback_receiver().value());
 }
 
 MATCHER_P(WithApplicationParameter, expected, "") {
@@ -503,7 +477,7 @@
           {U2fTransportProtocol::kUsbHumanInterfaceDevice}),
       std::vector<std::vector<uint8_t>>({signing_key_handle}),
       std::vector<uint8_t>(32), primary_app_param, alt_app_param,
-      sign_callback_.callback());
+      sign_callback_receiver_.callback());
 
   request->Start();
   discovery()->WaitForCallToStartAndSimulateSuccess();
@@ -522,12 +496,12 @@
       .WillOnce(::testing::Invoke(MockU2fDevice::WinkDoNothing));
   discovery()->AddDevice(std::move(device));
 
-  sign_callback().WaitForCallback();
-  EXPECT_EQ(U2fReturnCode::SUCCESS, sign_callback().GetReturnCode());
+  sign_callback_receiver().WaitForCallback();
+  EXPECT_EQ(U2fReturnCode::SUCCESS, sign_callback_receiver().status());
 
   EXPECT_EQ(GetTestAssertionSignature(),
-            sign_callback().GetResponseData()->signature());
-  EXPECT_EQ(signing_key_handle, sign_callback().GetResponseData()->raw_id());
+            sign_callback_receiver().value()->signature());
+  EXPECT_EQ(signing_key_handle, sign_callback_receiver().value()->raw_id());
 }
 
 }  // namespace device
diff --git a/device/test/usb_test_gadget_impl.cc b/device/test/usb_test_gadget_impl.cc
index f1b8656..50d2fbc 100644
--- a/device/test/usb_test_gadget_impl.cc
+++ b/device/test/usb_test_gadget_impl.cc
@@ -33,7 +33,7 @@
 #include "device/usb/usb_device_handle.h"
 #include "device/usb/usb_service.h"
 #include "net/base/escape.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/url_fetcher.h"
 #include "net/url_request/url_fetcher_delegate.h"
diff --git a/docs/callback.md b/docs/callback.md
index 309f51167..aeff1085 100644
--- a/docs/callback.md
+++ b/docs/callback.md
@@ -546,6 +546,12 @@
 base::Bind(&Foo, "test");
 base::Bind(&Bar, "test");  // This fails because ptr is not const.
 ```
+ - In case of partial binding of parameters a possibility of having unbound
+   parameters before bound parameters. Example:
+```cpp
+void Foo(int x, bool y);
+base::Bind(&Foo, _1, false); // _1 is a placeholder.
+```
 
 If you are thinking of forward declaring `base::Callback` in your own header
 file, please include "base/callback_forward.h" instead.
diff --git a/extensions/BUILD.gn b/extensions/BUILD.gn
index 3d37afb2..a071e57 100644
--- a/extensions/BUILD.gn
+++ b/extensions/BUILD.gn
@@ -250,7 +250,6 @@
   ]
 
   data_deps = [
-    "//testing/buildbot/filters:extensions_browsertests_filters",
     "//third_party/mesa:osmesa",
   ]
 }
diff --git a/extensions/browser/extension_registrar.h b/extensions/browser/extension_registrar.h
index 7e17bb2..58cfba3 100644
--- a/extensions/browser/extension_registrar.h
+++ b/extensions/browser/extension_registrar.h
@@ -111,8 +111,8 @@
   // retains a reference to it, so it can be enabled later.
   void DisableExtension(const ExtensionId& extension_id, int disable_reasons);
 
-  // Reloads the specified extension by disabling it if it is enabled and
-  // requesting the Delegate load it again.
+  // Attempts to reload the specified extension by disabling it if it is enabled
+  // and requesting the Delegate load it again.
   // NOTE: Reloading an extension can invalidate |extension_id| and Extension
   // pointers for the given extension. Consider making a copy of |extension_id|
   // first and retrieving a new Extension pointer afterwards.
diff --git a/extensions/browser/extension_registrar_unittest.cc b/extensions/browser/extension_registrar_unittest.cc
index 5f187f2..440a95b 100644
--- a/extensions/browser/extension_registrar_unittest.cc
+++ b/extensions/browser/extension_registrar_unittest.cc
@@ -323,6 +323,26 @@
                   ->GetDisableReasons(extension()->id()));
   }
 
+  // Directs ExtensionRegistrar to reload the terminated extension and verifies
+  // the delegate is invoked correctly.
+  void ReloadTerminatedExtension() {
+    SCOPED_TRACE("ReloadTerminatedExtension");
+    EXPECT_CALL(delegate_,
+                LoadExtensionForReload(extension()->id(), extension()->path(),
+                                       LoadErrorBehavior::kNoisy));
+    registrar()->ReloadExtension(extension()->id(), LoadErrorBehavior::kNoisy);
+    VerifyMock();
+
+    // The extension should remain in the terminated set until the reload
+    // completes successfully.
+    ExpectInSet(ExtensionRegistry::TERMINATED);
+    // Unlike when reloading an enabled extension, the extension hasn't been
+    // disabled and shouldn't have the DISABLE_RELOAD disable reason.
+    EXPECT_EQ(disable_reason::DISABLE_NONE,
+              ExtensionPrefs::Get(browser_context())
+                  ->GetDisableReasons(extension()->id()));
+  }
+
   // Verifies that the extension is in the given set in the ExtensionRegistry
   // and not in other sets.
   void ExpectInSet(ExtensionRegistry::IncludeFlag set_id) {
@@ -442,12 +462,14 @@
 TEST_F(ExtensionRegistrarTest, AddBlacklisted) {
   AddBlacklistedExtension();
 
-  // A blacklisted extension cannot be enabled/disabled.
+  // A blacklisted extension cannot be enabled/disabled/reloaded.
   registrar()->EnableExtension(extension()->id());
   ExpectInSet(ExtensionRegistry::BLACKLISTED);
   registrar()->DisableExtension(extension()->id(),
                                 disable_reason::DISABLE_USER_ACTION);
   ExpectInSet(ExtensionRegistry::BLACKLISTED);
+  registrar()->ReloadExtension(extension()->id(), LoadErrorBehavior::kQuiet);
+  ExpectInSet(ExtensionRegistry::BLACKLISTED);
 
   RemoveBlacklistedExtension();
 }
@@ -489,7 +511,7 @@
   RemoveDisabledExtension();
 }
 
-TEST_F(ExtensionRegistrarTest, ReloadTerminatedExtension) {
+TEST_F(ExtensionRegistrarTest, EnableTerminatedExtension) {
   AddEnabledExtension();
   TerminateExtension();
 
@@ -515,6 +537,23 @@
   // Simulate the delegate failing to load the extension and removing it
   // instead.
   RemoveDisabledExtension();
+
+  // Attempting to reload it silently fails.
+  registrar()->ReloadExtension(extension()->id(), LoadErrorBehavior::kQuiet);
+  ExpectInSet(ExtensionRegistry::NONE);
+}
+
+TEST_F(ExtensionRegistrarTest, ReloadTerminatedExtension) {
+  AddEnabledExtension();
+  TerminateExtension();
+
+  // Reload the terminated extension.
+  ReloadTerminatedExtension();
+
+  // Complete the reload by adding the extension. Expect the extension to be
+  // enabled once re-added to the registrar, since ExtensionPrefs shouldn't say
+  // it's disabled.
+  AddEnabledExtension();
 }
 
 }  // namespace extensions
diff --git a/extensions/browser/guest_view/web_view/web_view_apitest.cc b/extensions/browser/guest_view/web_view/web_view_apitest.cc
index 16abea6a..5db2be62 100644
--- a/extensions/browser/guest_view/web_view/web_view_apitest.cc
+++ b/extensions/browser/guest_view/web_view/web_view_apitest.cc
@@ -626,10 +626,6 @@
   RunTest("testNavigateAfterResize", "web_view/apitest");
 }
 
-IN_PROC_BROWSER_TEST_F(WebViewAPITest, TestNavigationToExternalProtocol) {
-  RunTest("testNavigationToExternalProtocol", "web_view/apitest");
-}
-
 IN_PROC_BROWSER_TEST_F(WebViewAPITest,
                        TestContentInitiatedNavigationToDataUrlBlocked) {
   RunTest("testContentInitiatedNavigationToDataUrlBlocked", "web_view/apitest");
diff --git a/extensions/shell/browser/shell_extension_loader.cc b/extensions/shell/browser/shell_extension_loader.cc
index 9d2997b..6b4c562 100644
--- a/extensions/shell/browser/shell_extension_loader.cc
+++ b/extensions/shell/browser/shell_extension_loader.cc
@@ -4,10 +4,17 @@
 
 #include "extensions/shell/browser/shell_extension_loader.h"
 
+#include "apps/launcher.h"
+#include "base/auto_reset.h"
+#include "base/bind.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
+#include "base/sequenced_task_runner.h"
+#include "base/task_runner_util.h"
+#include "extensions/browser/extension_file_task_runner.h"
 #include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/extension_registry.h"
 #include "extensions/common/file_util.h"
 
 namespace extensions {
@@ -53,7 +60,9 @@
 ShellExtensionLoader::ShellExtensionLoader(
     content::BrowserContext* browser_context)
     : browser_context_(browser_context),
-      extension_registrar_(browser_context, this) {}
+      extension_registrar_(browser_context, this),
+      keep_alive_requester_(browser_context),
+      weak_factory_(this) {}
 
 ShellExtensionLoader::~ShellExtensionLoader() = default;
 
@@ -66,6 +75,47 @@
   return extension.get();
 }
 
+void ShellExtensionLoader::ReloadExtension(ExtensionId extension_id) {
+  const Extension* extension = ExtensionRegistry::Get(browser_context_)
+                                   ->GetInstalledExtension(extension_id);
+  // We shouldn't be trying to reload extensions that haven't been added.
+  DCHECK(extension);
+
+  // This should always start false since it's only set here, or in
+  // LoadExtensionForReload() as a result of the call below.
+  DCHECK_EQ(false, did_schedule_reload_);
+  base::AutoReset<bool> reset_did_schedule_reload(&did_schedule_reload_, false);
+
+  // Set up a keep-alive while the extension reloads. Do this before starting
+  // the reload so that the first step, disabling the extension, doesn't release
+  // the last remaining keep-alive and shut down the application.
+  keep_alive_requester_.StartTrackingReload(extension);
+  extension_registrar_.ReloadExtension(extension_id, LoadErrorBehavior::kQuiet);
+  if (did_schedule_reload_)
+    return;
+
+  // ExtensionRegistrar didn't invoke us to schedule the reload, so the reload
+  // wasn't actually started. Clear the keep-alive so we don't wait forever.
+  keep_alive_requester_.StopTrackingReload(extension_id);
+}
+
+void ShellExtensionLoader::FinishExtensionReload(
+    const ExtensionId old_extension_id,
+    scoped_refptr<const Extension> extension) {
+  if (extension) {
+    extension_registrar_.AddExtension(extension);
+    // If the extension is a platform app, adding it above caused
+    // ShellKeepAliveRequester to create a new keep-alive to wait for the app to
+    // open its first window.
+    // Launch the app now.
+    if (extension->is_platform_app())
+      apps::LaunchPlatformApp(browser_context_, extension.get(), SOURCE_RELOAD);
+  }
+
+  // Whether or not the reload succeeded, we should stop waiting for it.
+  keep_alive_requester_.StopTrackingReload(old_extension_id);
+}
+
 void ShellExtensionLoader::PreAddExtension(const Extension* extension,
                                            const Extension* old_extension) {
   if (old_extension)
@@ -97,7 +147,14 @@
     const ExtensionId& extension_id,
     const base::FilePath& path,
     LoadErrorBehavior load_error_behavior) {
-  // TODO(michaelpg): Support reload.
+  CHECK(!path.empty());
+
+  base::PostTaskAndReplyWithResult(
+      GetExtensionFileTaskRunner().get(), FROM_HERE,
+      base::BindOnce(&LoadUnpacked, path),
+      base::BindOnce(&ShellExtensionLoader::FinishExtensionReload,
+                     weak_factory_.GetWeakPtr(), extension_id));
+  did_schedule_reload_ = true;
 }
 
 bool ShellExtensionLoader::CanEnableExtension(const Extension* extension) {
diff --git a/extensions/shell/browser/shell_extension_loader.h b/extensions/shell/browser/shell_extension_loader.h
index 9b88f9a..992ff0c7 100644
--- a/extensions/shell/browser/shell_extension_loader.h
+++ b/extensions/shell/browser/shell_extension_loader.h
@@ -13,6 +13,7 @@
 #include "base/memory/weak_ptr.h"
 #include "extensions/browser/extension_registrar.h"
 #include "extensions/common/extension_id.h"
+#include "extensions/shell/browser/shell_keep_alive_requester.h"
 
 namespace base {
 class FilePath;
@@ -26,7 +27,7 @@
 
 class Extension;
 
-// Handles extension loading using ExtensionRegistrar.
+// Handles extension loading and reloading using ExtensionRegistrar.
 class ShellExtensionLoader : public ExtensionRegistrar::Delegate {
  public:
   explicit ShellExtensionLoader(content::BrowserContext* browser_context);
@@ -36,7 +37,19 @@
   // extension on success, or nullptr otherwise.
   const Extension* LoadExtension(const base::FilePath& extension_dir);
 
+  // Starts reloading the extension. A keep-alive is maintained until the
+  // reload succeeds/fails. If the extension is an app, it will be launched upon
+  // reloading.
+  // This may invalidate references to the old Extension object, so it takes the
+  // ID by value.
+  void ReloadExtension(ExtensionId extension_id);
+
  private:
+  // If the extension loaded successfully, enables it. If it's an app, launches
+  // it. If the load failed, updates ShellKeepAliveRequester.
+  void FinishExtensionReload(const ExtensionId old_extension_id,
+                             scoped_refptr<const Extension> extension);
+
   // ExtensionRegistrar::Delegate:
   void PreAddExtension(const Extension* extension,
                        const Extension* old_extension) override;
@@ -56,6 +69,16 @@
   // Registers and unregisters extensions.
   ExtensionRegistrar extension_registrar_;
 
+  // Holds keep-alives for relaunching apps.
+  ShellKeepAliveRequester keep_alive_requester_;
+
+  // Indicates that we posted the (asynchronous) task to start reloading.
+  // Used by ReloadExtension() to check whether ExtensionRegistrar calls
+  // LoadExtensionForReload().
+  bool did_schedule_reload_ = false;
+
+  base::WeakPtrFactory<ShellExtensionLoader> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(ShellExtensionLoader);
 };
 
diff --git a/extensions/shell/browser/shell_extension_loader_unittest.cc b/extensions/shell/browser/shell_extension_loader_unittest.cc
index 4f986d61..a28a6eb 100644
--- a/extensions/shell/browser/shell_extension_loader_unittest.cc
+++ b/extensions/shell/browser/shell_extension_loader_unittest.cc
@@ -7,24 +7,42 @@
 #include <memory>
 #include <string>
 
+#include "apps/app_lifetime_monitor_factory.h"
 #include "base/macros.h"
 #include "base/path_service.h"
 #include "components/crx_file/id_util.h"
+#include "components/keep_alive_registry/keep_alive_registry.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/user_prefs/user_prefs.h"
 #include "content/public/browser/browser_context.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_utils.h"
 #include "extensions/browser/disable_reason.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extensions_test.h"
+#include "extensions/browser/mock_extension_system.h"
 #include "extensions/browser/null_app_sorting.h"
 #include "extensions/browser/runtime_data.h"
+#include "extensions/browser/test_event_router.h"
 #include "extensions/browser/test_extensions_browser_client.h"
+#include "extensions/common/api/app_runtime.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_id.h"
 #include "extensions/common/extension_paths.h"
+#include "extensions/test/test_extension_dir.h"
+
+#if defined(USE_AURA)
+#include "extensions/browser/app_window/app_window.h"
+#include "extensions/shell/browser/shell_app_window_client.h"
+#include "extensions/shell/browser/shell_native_app_window_aura.h"
+#include "extensions/shell/test/shell_test_extensions_browser_client.h"
+#include "extensions/shell/test/shell_test_helper_aura.h"
+#endif
 
 namespace extensions {
 
+namespace OnLaunched = api::app_runtime::OnLaunched;
+
 namespace {
 
 class TestExtensionSystem : public MockExtensionSystem {
@@ -44,6 +62,25 @@
   DISALLOW_COPY_AND_ASSIGN(TestExtensionSystem);
 };
 
+#if defined(USE_AURA)
+// An AppWindowClient for use without a DesktopController.
+class TestAppWindowClient : public ShellAppWindowClient {
+ public:
+  TestAppWindowClient() = default;
+  ~TestAppWindowClient() override = default;
+
+  // ShellAppWindowClient:
+  NativeAppWindow* CreateNativeAppWindow(
+      AppWindow* window,
+      AppWindow::CreateParams* params) override {
+    return new ShellNativeAppWindowAura(window, *params);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestAppWindowClient);
+};
+#endif
+
 }  // namespace
 
 class ShellExtensionLoaderTest : public ExtensionsTest {
@@ -53,8 +90,18 @@
   ~ShellExtensionLoaderTest() override = default;
 
   void SetUp() override {
+    // Register factory so it's created with the BrowserContext.
+    apps::AppLifetimeMonitorFactory::GetInstance();
+
     ExtensionsTest::SetUp();
     extensions_browser_client()->set_extension_system_factory(&factory_);
+    user_prefs::UserPrefs::Set(browser_context(), &testing_pref_service_);
+    event_router_ = CreateAndUseTestEventRouter(browser_context());
+  }
+
+  void TearDown() override {
+    EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
+    ExtensionsTest::TearDown();
   }
 
   // Returns the path to a test directory.
@@ -75,32 +122,26 @@
         ExtensionRegistry::EVERYTHING & ~ExtensionRegistry::ENABLED));
   }
 
-  // Verifies the extension is correctly created but disabled.
-  void ExpectDisabled(const Extension* extension) {
-    ASSERT_TRUE(extension);
-    EXPECT_EQ(Manifest::COMMAND_LINE, extension->location());
+  // Verifies the extension with the given ID is disabled.
+  void ExpectDisabled(const ExtensionId& extension_id) {
     ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
-    EXPECT_TRUE(registry->disabled_extensions().Contains(extension->id()));
+    EXPECT_TRUE(registry->disabled_extensions().Contains(extension_id));
     EXPECT_FALSE(registry->GetExtensionById(
-        extension->id(),
+        extension_id,
         ExtensionRegistry::EVERYTHING & ~ExtensionRegistry::DISABLED));
   }
 
+  TestEventRouter* event_router() { return event_router_; }
+
  private:
   MockExtensionSystemFactory<TestExtensionSystem> factory_;
+  TestingPrefServiceSimple testing_pref_service_;
+
+  TestEventRouter* event_router_ = nullptr;  // Created in SetUp().
 
   DISALLOW_COPY_AND_ASSIGN(ShellExtensionLoaderTest);
 };
 
-// Tests loading an extension.
-TEST_F(ShellExtensionLoaderTest, Extension) {
-  ShellExtensionLoader loader(browser_context());
-
-  const Extension* extension =
-      loader.LoadExtension(GetExtensionPath("extension"));
-  ExpectEnabled(extension);
-}
-
 // Tests with a non-existent directory.
 TEST_F(ShellExtensionLoaderTest, NotFound) {
   ShellExtensionLoader loader(browser_context());
@@ -108,6 +149,35 @@
   const Extension* extension =
       loader.LoadExtension(GetExtensionPath("nonexistent"));
   ASSERT_FALSE(extension);
+  EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
+}
+
+// Tests loading and reloading an extension.
+TEST_F(ShellExtensionLoaderTest, Extension) {
+  ShellExtensionLoader loader(browser_context());
+
+  const Extension* extension =
+      loader.LoadExtension(GetExtensionPath("extension"));
+  ExpectEnabled(extension);
+
+  // Extensions shouldn't receive the onLaunched event.
+  EXPECT_EQ(0, event_router()->GetEventCount(OnLaunched::kEventName));
+
+  // No keep-alives are used for non-app extensions.
+  const ExtensionId extension_id = extension->id();
+  loader.ReloadExtension(extension->id());
+  ExpectDisabled(extension_id);
+  EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
+
+  // Wait for load.
+  content::RunAllTasksUntilIdle();
+  extension = ExtensionRegistry::Get(browser_context())
+                  ->GetInstalledExtension(extension_id);
+  ExpectEnabled(extension);
+  EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
+
+  // Not an app.
+  EXPECT_EQ(0, event_router()->GetEventCount(OnLaunched::kEventName));
 }
 
 // Tests that the extension is added as enabled even if is disabled in
@@ -138,7 +208,157 @@
 
   ShellExtensionLoader loader(browser_context());
   const Extension* extension = loader.LoadExtension(extension_path);
-  ExpectDisabled(extension);
+  ExpectDisabled(extension->id());
 }
 
+#if defined(USE_AURA)
+class ShellExtensionLoaderTestAura : public ShellExtensionLoaderTest {
+ protected:
+  ShellExtensionLoaderTestAura() = default;
+  ~ShellExtensionLoaderTestAura() override = default;
+
+  void SetUp() override {
+    aura_helper_ = std::make_unique<ShellTestHelperAura>();
+    aura_helper_->SetUp();
+
+    std::unique_ptr<TestExtensionsBrowserClient>
+        test_extensions_browser_client =
+            std::make_unique<ShellTestExtensionsBrowserClient>();
+    SetExtensionsBrowserClient(std::move(test_extensions_browser_client));
+    AppWindowClient::Set(&app_window_client_);
+
+    ShellExtensionLoaderTest::SetUp();
+  }
+
+  void TearDown() override {
+    ShellExtensionLoaderTest::TearDown();
+    AppWindowClient::Set(nullptr);
+    aura_helper_->TearDown();
+  }
+
+  // Returns an initialized app window for the extension.
+  // The app window deletes itself when its native window is closed.
+  AppWindow* CreateAppWindow(const Extension* extension) {
+    AppWindow* app_window =
+        app_window_client_.CreateAppWindow(browser_context(), extension);
+    aura_helper_->InitAppWindow(app_window);
+    return app_window;
+  }
+
+ private:
+  std::unique_ptr<ShellTestHelperAura> aura_helper_;
+  TestAppWindowClient app_window_client_;
+
+  DISALLOW_COPY_AND_ASSIGN(ShellExtensionLoaderTestAura);
+};
+
+// Tests loading and launching a platform app.
+TEST_F(ShellExtensionLoaderTestAura, AppLaunch) {
+  ShellExtensionLoader loader(browser_context());
+
+  const Extension* extension =
+      loader.LoadExtension(GetExtensionPath("platform_app"));
+  ExpectEnabled(extension);
+
+  // A keep-alive is waiting for the app to launch its first window.
+  // (Not strictly necessary in AppShell, because DesktopWindowControllerAura
+  // doesn't consider quitting until an already-open window is closed, but
+  // ShellExtensionLoader and ShellKeepAliveRequester don't make that
+  // assumption.)
+  EXPECT_TRUE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
+
+  {
+    // When AppShell launches the app window, the keep-alive is removed.
+    AppWindow* app_window = CreateAppWindow(extension);
+    EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
+    app_window->GetBaseWindow()->Close();  // Deletes |app_window|.
+  }
+}
+
+// Tests loading, launching and reloading a platform app.
+TEST_F(ShellExtensionLoaderTestAura, AppLaunchAndReload) {
+  ShellExtensionLoader loader(browser_context());
+
+  const Extension* extension =
+      loader.LoadExtension(GetExtensionPath("platform_app"));
+  const ExtensionId extension_id = extension->id();
+  ExpectEnabled(extension);
+  EXPECT_TRUE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
+
+  CreateAppWindow(extension);
+  EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
+
+  // Reload the app.
+  loader.ReloadExtension(extension->id());
+  ExpectDisabled(extension_id);
+  EXPECT_TRUE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
+
+  // Complete the reload. ShellExtensionLoader sends the onLaunched event.
+  content::RunAllTasksUntilIdle();
+  extension = ExtensionRegistry::Get(browser_context())
+                  ->GetInstalledExtension(extension_id);
+  ExpectEnabled(extension);
+  EXPECT_EQ(1, event_router()->GetEventCount(OnLaunched::kEventName));
+  EXPECT_TRUE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
+
+  {
+    // The keep-alive is destroyed when an app window is launched.
+    AppWindow* app_window = CreateAppWindow(extension);
+    EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
+
+    app_window->GetBaseWindow()->Close();
+  }
+}
+
+// Tests failing to reload an app.
+TEST_F(ShellExtensionLoaderTestAura, ReloadFailure) {
+  ShellExtensionLoader loader(browser_context());
+  ExtensionId extension_id;
+
+  // Create an extension in a temporary directory so we can delete it before
+  // trying to reload it.
+  {
+    TestExtensionDir extension_dir;
+    extension_dir.WriteManifest(
+        R"({
+             "name": "Test Platform App",
+             "version": "1",
+             "manifest_version": 2,
+              "app": {
+                "background": {
+                  "scripts": ["background.js"]
+                }
+              }
+           })");
+    extension_dir.WriteFile(FILE_PATH_LITERAL("background.js"), "");
+
+    const Extension* extension =
+        loader.LoadExtension(extension_dir.UnpackedPath());
+    ASSERT_TRUE(extension);
+    extension_id = extension->id();
+    ExpectEnabled(extension);
+    EXPECT_TRUE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
+
+    // Launch an app window.
+    CreateAppWindow(extension);
+    EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
+
+    // Reload the app.
+    loader.ReloadExtension(extension->id());
+    EXPECT_TRUE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
+  }
+
+  // Wait for load (which will fail because the directory is missing).
+  content::RunAllTasksUntilIdle();
+
+  ExpectDisabled(extension_id);
+  EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
+
+  // We can't reload an extension that is already disabled for reloading, so
+  // trying to reload this extension shouldn't result in a dangling keep-alive.
+  loader.ReloadExtension(extension_id);
+  EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
+}
+#endif
+
 }  // namespace extensions
diff --git a/extensions/shell/browser/shell_extension_system_factory.cc b/extensions/shell/browser/shell_extension_system_factory.cc
index 2093c5f..00623e5 100644
--- a/extensions/shell/browser/shell_extension_system_factory.cc
+++ b/extensions/shell/browser/shell_extension_system_factory.cc
@@ -4,6 +4,7 @@
 
 #include "extensions/shell/browser/shell_extension_system_factory.h"
 
+#include "apps/app_lifetime_monitor_factory.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "extensions/browser/extension_prefs_factory.h"
 #include "extensions/browser/extension_registry_factory.h"
@@ -29,6 +30,7 @@
                               BrowserContextDependencyManager::GetInstance()) {
   DependsOn(ExtensionPrefsFactory::GetInstance());
   DependsOn(ExtensionRegistryFactory::GetInstance());
+  DependsOn(apps::AppLifetimeMonitorFactory::GetInstance());
 }
 
 ShellExtensionSystemFactory::~ShellExtensionSystemFactory() {
diff --git a/extensions/shell/browser/shell_keep_alive_requester.cc b/extensions/shell/browser/shell_keep_alive_requester.cc
index 25f72c1..5af5f25 100644
--- a/extensions/shell/browser/shell_keep_alive_requester.cc
+++ b/extensions/shell/browser/shell_keep_alive_requester.cc
@@ -47,11 +47,9 @@
     return;
 
   // Add a keep-alive to wait for the app to launch its first app window, as
-  // otherwise the Aura desktop controller will exit.
-  // This assumes that all platform apps will be launched when loaded, which is
-  // true in AppShell. (The launched app may decline to create a window, in
-  // which case this keep-alive will be erased once the app's background page
-  // eventually stops.
+  // otherwise the Aura desktop controller may exit. The assumption is that all
+  // apps will create a visible window. If the app doesn't, this keep-alive will
+  // still be erased once the app's background page eventually stops.
   app_launching_keep_alives_[extension->id()] =
       std::make_unique<ScopedKeepAlive>(KeepAliveOrigin::APP_CONTROLLER,
                                         KeepAliveRestartOption::ENABLED);
diff --git a/extensions/shell/test/shell_test_base_aura.cc b/extensions/shell/test/shell_test_base_aura.cc
index 3db1c13..0be0ddc8 100644
--- a/extensions/shell/test/shell_test_base_aura.cc
+++ b/extensions/shell/test/shell_test_base_aura.cc
@@ -4,15 +4,9 @@
 
 #include "extensions/shell/test/shell_test_base_aura.h"
 
-#include "base/memory/ptr_util.h"
-#include "content/public/browser/web_contents.h"
 #include "content/public/test/test_browser_thread_bundle.h"
-#include "extensions/browser/app_window/app_window.h"
-#include "extensions/browser/app_window/test_app_window_contents.h"
-#include "extensions/shell/browser/shell_app_delegate.h"
 #include "extensions/shell/test/shell_test_extensions_browser_client.h"
 #include "extensions/shell/test/shell_test_helper_aura.h"
-#include "url/gurl.h"
 
 namespace extensions {
 
@@ -37,25 +31,7 @@
 
 void ShellTestBaseAura::InitAppWindow(AppWindow* app_window,
                                       const gfx::Rect& bounds) {
-  // Create a TestAppWindowContents for the ShellAppDelegate to initialize the
-  // ShellExtensionWebContentsObserver with.
-  std::unique_ptr<content::WebContents> web_contents(
-      content::WebContents::Create(
-          content::WebContents::CreateParams(browser_context())));
-  std::unique_ptr<TestAppWindowContents> app_window_contents =
-      std::make_unique<TestAppWindowContents>(std::move(web_contents));
-
-  // Initialize the web contents and AppWindow.
-  app_window->app_delegate()->InitWebContents(
-      app_window_contents->GetWebContents());
-
-  content::RenderFrameHost* main_frame =
-      app_window_contents->GetWebContents()->GetMainFrame();
-  DCHECK(main_frame);
-
-  AppWindow::CreateParams params;
-  params.content_spec.bounds = bounds;
-  app_window->Init(GURL(), app_window_contents.release(), main_frame, params);
+  helper_->InitAppWindow(app_window, bounds);
 }
 
 }  // namespace extensions
diff --git a/extensions/shell/test/shell_test_helper_aura.cc b/extensions/shell/test/shell_test_helper_aura.cc
index 358caa62..9ad8708f 100644
--- a/extensions/shell/test/shell_test_helper_aura.cc
+++ b/extensions/shell/test/shell_test_helper_aura.cc
@@ -4,9 +4,16 @@
 
 #include "extensions/shell/test/shell_test_helper_aura.h"
 
+#include <memory>
+
+#include "content/public/browser/web_contents.h"
+#include "extensions/browser/app_window/app_window.h"
+#include "extensions/browser/app_window/test_app_window_contents.h"
+#include "extensions/shell/browser/shell_app_delegate.h"
 #include "ui/aura/test/aura_test_helper.h"
 #include "ui/compositor/compositor.h"
 #include "ui/compositor/test/context_factories_for_test.h"
+#include "url/gurl.h"
 
 namespace extensions {
 
@@ -33,4 +40,27 @@
   ui::TerminateContextFactoryForTests();
 }
 
+void ShellTestHelperAura::InitAppWindow(AppWindow* app_window,
+                                        const gfx::Rect& bounds) {
+  // Create a TestAppWindowContents for the ShellAppDelegate to initialize the
+  // ShellExtensionWebContentsObserver with.
+  std::unique_ptr<content::WebContents> web_contents(
+      content::WebContents::Create(
+          content::WebContents::CreateParams(app_window->browser_context())));
+  auto app_window_contents =
+      std::make_unique<TestAppWindowContents>(std::move(web_contents));
+
+  // Initialize the web contents and AppWindow.
+  app_window->app_delegate()->InitWebContents(
+      app_window_contents->GetWebContents());
+
+  content::RenderFrameHost* main_frame =
+      app_window_contents->GetWebContents()->GetMainFrame();
+  DCHECK(main_frame);
+
+  AppWindow::CreateParams params;
+  params.content_spec.bounds = bounds;
+  app_window->Init(GURL(), app_window_contents.release(), main_frame, params);
+}
+
 }  // namespace extensions
diff --git a/extensions/shell/test/shell_test_helper_aura.h b/extensions/shell/test/shell_test_helper_aura.h
index cc03bf1..1ef311a 100644
--- a/extensions/shell/test/shell_test_helper_aura.h
+++ b/extensions/shell/test/shell_test_helper_aura.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "ui/gfx/geometry/rect.h"
 
 namespace aura {
 namespace test {
@@ -17,6 +18,8 @@
 
 namespace extensions {
 
+class AppWindow;
+
 // A helper class that does common Aura initialization required for the shell.
 class ShellTestHelperAura {
  public:
@@ -29,6 +32,9 @@
   // Cleans up.
   void TearDown();
 
+  // Initializes |app_window| for testing.
+  void InitAppWindow(AppWindow* app_window, const gfx::Rect& bounds = {});
+
  private:
   std::unique_ptr<aura::test::AuraTestHelper> helper_;
 
diff --git a/extensions/test/data/web_view/apitest/main.js b/extensions/test/data/web_view/apitest/main.js
index 7c4c7ec..8f9547ac 100644
--- a/extensions/test/data/web_view/apitest/main.js
+++ b/extensions/test/data/web_view/apitest/main.js
@@ -1150,21 +1150,6 @@
   document.body.appendChild(webview);
 }
 
-function testNavigationToExternalProtocol() {
-  var webview = document.createElement('webview');
-  webview.addEventListener('loadstop', function(e) {
-    webview.addEventListener('loadabort', function(e) {
-      embedder.test.assertEq('ERR_UNKNOWN_URL_SCHEME', e.reason);
-      embedder.test.succeed();
-    });
-    webview.executeScript({
-      code: 'window.location.href = "tel:+12223334444";'
-    }, function(results) {});
-  });
-  webview.setAttribute('src', 'data:text/html,navigate to external protocol');
-  document.body.appendChild(webview);
-}
-
 // This test ensures if the guest isn't there and we resize the guest (from JS),
 // it remembers the size correctly.
 function testNavigateAfterResize() {
@@ -1824,7 +1809,6 @@
   'testLoadProgressEvent': testLoadProgressEvent,
   'testLoadStartLoadRedirect': testLoadStartLoadRedirect,
   'testNavigateAfterResize': testNavigateAfterResize,
-  'testNavigationToExternalProtocol': testNavigationToExternalProtocol,
   'testNavOnConsecutiveSrcAttributeChanges':
       testNavOnConsecutiveSrcAttributeChanges,
   'testNavOnSrcAttributeChange': testNavOnSrcAttributeChange,
diff --git a/google_apis/gcm/engine/connection_factory_impl.h b/google_apis/gcm/engine/connection_factory_impl.h
index 4fa1456a..13885460 100644
--- a/google_apis/gcm/engine/connection_factory_impl.h
+++ b/google_apis/gcm/engine/connection_factory_impl.h
@@ -19,7 +19,7 @@
 #include "net/base/network_change_notifier.h"
 #include "net/log/net_log_with_source.h"
 #include "net/proxy_resolution/proxy_info.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/socket/client_socket_handle.h"
 #include "url/gurl.h"
 
diff --git a/headless/lib/browser/headless_url_request_context_getter.cc b/headless/lib/browser/headless_url_request_context_getter.cc
index f45a1f0..046f4e0 100644
--- a/headless/lib/browser/headless_url_request_context_getter.cc
+++ b/headless/lib/browser/headless_url_request_context_getter.cc
@@ -25,7 +25,7 @@
 #include "net/http/http_auth_scheme.h"
 #include "net/http/http_transaction_factory.h"
 #include "net/http/http_util.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/ssl/channel_id_service.h"
 #include "net/ssl/default_channel_id_store.h"
 #include "net/url_request/url_request_context.h"
diff --git a/headless/public/headless_browser_context.h b/headless/public/headless_browser_context.h
index acd3a67e..125f16e 100644
--- a/headless/public/headless_browser_context.h
+++ b/headless/public/headless_browser_context.h
@@ -17,7 +17,7 @@
 #include "headless/lib/browser/headless_network_conditions.h"
 #include "headless/public/headless_export.h"
 #include "headless/public/headless_web_contents.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/url_request/url_request_job_factory.h"
 
 namespace base {
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg
index c7c27b3..4a10929 100644
--- a/infra/config/global/cr-buildbucket.cfg
+++ b/infra/config/global/cr-buildbucket.cfg
@@ -275,6 +275,7 @@
 
 builder_mixins {
   name: "findit"
+  mixins: "goma-j150"
   # This category is meant for Findit to trigger tryjobs on.
   category: "Chromium Variable"
   recipe {
@@ -282,6 +283,15 @@
   }
 }
 
+# GPU bots run very long tests sometimes on a single tester. The regular
+# timeout isn't enough on some testers during the migration when they run both
+# the buildbot and LUCI tests. Double the timeout for them.
+# TODO(cwallez@chromium.org): remove this when the migration is complete
+builder_mixins {
+  name: "gpu-slow-bot"
+  execution_timeout_secs: 21600  # 2 x 3h for a double workload
+}
+
 buckets {
   name: "luci.chromium.ci"
   acl_sets: "ci"
@@ -340,6 +350,27 @@
       dimensions: "cores:8"
     }
 
+    # Fuchsia bots.
+    builders {
+      name: "Fuchsia ARM64"
+      mixins: "linux-ci"
+    }
+
+    builders {
+      name: "Fuchsia ARM64 Cast Audio"
+      mixins: "linux-ci"
+    }
+
+    builders {
+      name: "Fuchsia x64"
+      mixins: "linux-ci"
+    }
+
+    builders {
+      name: "Fuchsia x64 Cast Audio"
+      mixins: "linux-ci"
+    }
+
     # Linux bots.
     builders {
       name: "linux-blink-heap-incremental-marking"
@@ -445,6 +476,7 @@
     builders {
       name: "Linux FYI Release (AMD R7 240)"
       mixins: "linux-gpu-fyi-ci"
+      mixins: "gpu-slow-bot"
     }
 
     builders {
@@ -505,6 +537,7 @@
     builders {
       name: "Mac Pro FYI Release (AMD)"
       mixins: "mac-gpu-fyi-ci"
+      mixins: "gpu-slow-bot"
     }
     builders {
       name: "Mac FYI Retina Release (NVIDIA)"
@@ -533,6 +566,7 @@
     builders {
       name: "Mac FYI Experimental Retina Release (NVIDIA)"
       mixins: "mac-gpu-fyi-ci"
+      mixins: "gpu-slow-bot"
     }
     builders {
       name: "Mac FYI GPU ASAN Release"
@@ -584,37 +618,37 @@
     builders {
       name: "GPU FYI Win Builder"
       mixins: "win-gpu-fyi-ci"
-      dimensions: "cores:32"
+      dimensions: "cores:8"
     }
     builders {
       name: "GPU FYI Win Builder (dbg)"
       mixins: "win-gpu-fyi-ci"
-      dimensions: "cores:32"
+      dimensions: "cores:8"
     }
     builders {
       name: "GPU FYI Win Clang Builder (dbg)"
       mixins: "win-gpu-fyi-ci"
-      dimensions: "cores:32"
+      dimensions: "cores:8"
     }
     builders {
       name: "GPU FYI Win dEQP Builder"
       mixins: "win-gpu-fyi-ci"
-      dimensions: "cores:32"
+      dimensions: "cores:8"
     }
     builders {
       name: "GPU FYI Win x64 Builder"
       mixins: "win-gpu-fyi-ci"
-      dimensions: "cores:32"
+      dimensions: "cores:8"
     }
     builders {
       name: "GPU FYI Win x64 Builder (dbg)"
       mixins: "win-gpu-fyi-ci"
-      dimensions: "cores:32"
+      dimensions: "cores:8"
     }
     builders {
       name: "GPU FYI Win x64 dEQP Builder"
       mixins: "win-gpu-fyi-ci"
-      dimensions: "cores:32"
+      dimensions: "cores:8"
     }
     builders {
       name: "Win10 FYI Debug (NVIDIA)"
diff --git a/infra/config/global/luci-milo.cfg b/infra/config/global/luci-milo.cfg
index 1b8a4b0..80995c6 100644
--- a/infra/config/global/luci-milo.cfg
+++ b/infra/config/global/luci-milo.cfg
@@ -453,21 +453,25 @@
   }
   builders: {
     name: "buildbot/chromium.linux/Fuchsia ARM64 Cast Audio"
+    name: "buildbucket/luci.chromium.ci/Fuchsia ARM64 Cast Audio"
     category: "chromium.linux|fuchsia|Cast"
     short_name: "a64"
   }
   builders: {
     name: "buildbot/chromium.linux/Fuchsia x64 Cast Audio"
+    name: "buildbucket/luci.chromium.ci/Fuchsia x64 Cast Audio"
     category: "chromium.linux|fuchsia|Cast"
     short_name: "x64"
   }
   builders: {
     name: "buildbot/chromium.linux/Fuchsia ARM64"
+    name: "buildbucket/luci.chromium.ci/Fuchsia ARM64"
     category: "chromium.linux|fuchsia"
     short_name: "a64"
   }
   builders: {
     name: "buildbot/chromium.linux/Fuchsia x64"
+    name: "buildbucket/luci.chromium.ci/Fuchsia x64"
     category: "chromium.linux|fuchsia"
     short_name: "x64"
   }
@@ -1512,6 +1516,50 @@
   }
 
   builders: {
+    name: "buildbucket/luci.chromium.ci/Fuchsia ARM64"
+    category: "fuchsia|arm64"
+    short_name: "ci"
+  }
+  builders: {
+    name: "buildbot/chromium.linux/Fuchsia ARM64"
+    category: "fuchsia|arm64"
+    short_name: "bb"
+  }
+
+  builders: {
+    name: "buildbucket/luci.chromium.ci/Fuchsia ARM64 Cast Audio"
+    category: "fuchsia|arm64|cast"
+    short_name: "ci"
+  }
+  builders: {
+    name: "buildbot/chromium.linux/Fuchsia ARM64 Cast Audio"
+    category: "fuchsia|arm64|cast"
+    short_name: "bb"
+  }
+
+  builders: {
+    name: "buildbucket/luci.chromium.ci/Fuchsia x64"
+    category: "fuchsia|x64"
+    short_name: "ci"
+  }
+  builders: {
+    name: "buildbot/chromium.linux/Fuchsia x64"
+    category: "fuchsia|x64"
+    short_name: "bb"
+  }
+
+  builders: {
+    name: "buildbucket/luci.chromium.ci/Fuchsia x64 Cast Audio"
+    category: "fuchsia|x64|cast"
+    short_name: "ci"
+  }
+  builders: {
+    name: "buildbot/chromium.linux/Fuchsia x64 Cast Audio"
+    category: "fuchsia|x64|cast"
+    short_name: "bb"
+  }
+
+  builders: {
     name: "buildbucket/luci.chromium.ci/Mac Builder (dbg)"
     category: "mac|debug|builder"
     short_name: "ci"
@@ -1872,6 +1920,208 @@
     category: "GPU FYI|Mac|Intel|dEQP"
     short_name: "🦖"
   }
+
+  # GPU FYI Window bots, prefixed with GPU FYI|Windows
+  builders: {
+    name: "buildbucket/luci.chromium.ci/GPU FYI Win Builder"
+    category: "GPU FYI|Windows|Builder|Release|x86"
+    short_name: "🏗️"
+  }
+  builders: {
+    name: "buildbot/chromium.gpu.fyi/GPU FYI Win Builder"
+    category: "GPU FYI|Windows|Builder|Release|x86"
+    short_name: "🚧"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/GPU FYI Win x64 Builder"
+    category: "GPU FYI|Windows|Builder|Release|x64"
+    short_name: "🏗️"
+  }
+  builders: {
+    name: "buildbot/chromium.gpu.fyi/GPU FYI Win x64 Builder"
+    category: "GPU FYI|Windows|Builder|Release|x64"
+    short_name: "🚧"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/GPU FYI Win dEQP Builder"
+    category: "GPU FYI|Windows|Builder|dEQP|x86"
+    short_name: "🏗️"
+  }
+  builders: {
+    name: "buildbot/chromium.gpu.fyi/GPU FYI Win dEQP Builder"
+    category: "GPU FYI|Windows|Builder|dEQP|x86"
+    short_name: "🚧"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/GPU FYI Win x64 dEQP Builder"
+    category: "GPU FYI|Windows|Builder|dEQP|x64"
+    short_name: "🏗️"
+  }
+  builders: {
+    name: "buildbot/chromium.gpu.fyi/GPU FYI Win x64 dEQP Builder"
+    category: "GPU FYI|Windows|Builder|dEQP|x64"
+    short_name: "🚧"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/GPU FYI Win Builder (dbg)"
+    category: "GPU FYI|Windows|Builder|Debug|x86"
+    short_name: "🏗️"
+  }
+  builders: {
+    name: "buildbot/chromium.gpu.fyi/GPU FYI Win Builder (dbg)"
+    category: "GPU FYI|Windows|Builder|Debug|x86"
+    short_name: "🚧"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/GPU FYI Win x64 Builder (dbg)"
+    category: "GPU FYI|Windows|Builder|Debug|x64"
+    short_name: "🏗️"
+  }
+  builders: {
+    name: "buildbot/chromium.gpu.fyi/GPU FYI Win x64 Builder (dbg)"
+    category: "GPU FYI|Windows|Builder|Debug|x64"
+    short_name: "🚧"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/GPU FYI Win Clang Builder (dbg)"
+    category: "GPU FYI|Windows|Builder|Clang|Debug|x86"
+    short_name: "🛠️"
+  }
+  builders: {
+    name: "buildbot/chromium.gpu.fyi/GPU FYI Win Clang Builder (dbg)"
+    category: "GPU FYI|Windows|Builder|Clang|Debug|x86"
+    short_name: "🚧"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/Win10 FYI Debug (NVIDIA)"
+    category: "GPU FYI|Windows|10|Nvidia|Debug|x86"
+    short_name: "🏠"
+  }
+  builders: {
+    name: "buildbot/chromium.gpu.fyi/Win10 FYI Debug (NVIDIA)"
+    category: "GPU FYI|Windows|10|Nvidia|Debug|x86"
+    short_name: "🏚️"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/Win10 FYI Release (Intel HD 630)"
+    category: "GPU FYI|Windows|10|Intel|Release|x86"
+    short_name: "🏠"
+  }
+  builders: {
+    name: "buildbot/chromium.gpu.fyi/Win10 FYI Release (Intel HD 630)"
+    category: "GPU FYI|Windows|10|Intel|Release|x86"
+    short_name: "🏚️"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/Win10 FYI Release (NVIDIA)"
+    category: "GPU FYI|Windows|10|Nvidia|Release|x86"
+    short_name: "🏠"
+  }
+  builders: {
+    name: "buildbot/chromium.gpu.fyi/Win10 FYI Release (NVIDIA)"
+    category: "GPU FYI|Windows|10|Nvidia|Release|x86"
+    short_name: "🏚️"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/Win7 FYI Debug (AMD)"
+    category: "GPU FYI|Windows|7|AMD|Debug|x86"
+    short_name: "🐞"
+  }
+  builders: {
+    name: "buildbot/chromium.gpu.fyi/Win7 FYI Debug (AMD)"
+    category: "GPU FYI|Windows|7|AMD|Debug|x86"
+    short_name: "🐛"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/Win7 FYI dEQP Release (AMD)"
+    category: "GPU FYI|Windows|7|AMD|dEQP|x86"
+    short_name: "⛅"
+  }
+  builders: {
+    name: "buildbot/chromium.gpu.fyi/Win7 FYI dEQP Release (AMD)"
+    category: "GPU FYI|Windows|7|AMD|dEQP|x86"
+    short_name: "🔥"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/Win7 FYI Release (AMD)"
+    category: "GPU FYI|Windows|7|AMD|Release|x86"
+    short_name: "🐈"
+  }
+  builders: {
+    name: "buildbot/chromium.gpu.fyi/Win7 FYI Release (AMD)"
+    category: "GPU FYI|Windows|7|AMD|Release|x86"
+    short_name: "🧵"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/Win7 FYI Debug (NVIDIA)"
+    category: "GPU FYI|Windows|7|Nvidia|Debug|x86"
+    short_name: "🐈"
+  }
+  builders: {
+    name: "buildbot/chromium.gpu.fyi/Win7 FYI Debug (NVIDIA)"
+    category: "GPU FYI|Windows|7|Nvidia|Debug|x86"
+    short_name: "🧵"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/Win10 FYI Exp Release (NVIDIA)"
+    category: "GPU FYI|Windows|10|Nvidia|Exp|x86"
+    short_name: "⚗️"
+  }
+  builders: {
+    name: "buildbot/chromium.gpu.fyi/Win10 FYI Exp Release (NVIDIA)"
+    category: "GPU FYI|Windows|10|Nvidia|Exp|x86"
+    short_name: "🎆"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/Win7 FYI Release (NVIDIA)"
+    category: "GPU FYI|Windows|7|Nvidia|Release|x86"
+    short_name: "🐮"
+  }
+  builders: {
+    name: "buildbot/chromium.gpu.fyi/Win7 FYI Release (NVIDIA)"
+    category: "GPU FYI|Windows|7|Nvidia|Release|x86"
+    short_name: "🥩"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/Win10 FYI dEQP Release (NVIDIA)"
+    category: "GPU FYI|Windows|10|Nvidia|dEQP|x86"
+    short_name: "🌞"
+  }
+  builders: {
+    name: "buildbot/chromium.gpu.fyi/Win10 FYI dEQP Release (NVIDIA)"
+    category: "GPU FYI|Windows|10|Nvidia|dEQP|x86"
+    short_name: "🔥"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/Win7 FYI x64 Debug (NVIDIA)"
+    category: "GPU FYI|Windows|7|Nvidia|Debug|x64"
+    short_name: "🤖"
+  }
+  builders: {
+    name: "buildbot/chromium.gpu.fyi/Win7 FYI x64 Debug (NVIDIA)"
+    category: "GPU FYI|Windows|7|Nvidia|Debug|x64"
+    short_name: "🐵"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/Win7 FYI x64 Release (NVIDIA)"
+    category: "GPU FYI|Windows|7|Nvidia|Release|x64"
+    short_name: "🤖"
+  }
+  builders: {
+    name: "buildbot/chromium.gpu.fyi/Win7 FYI x64 Release (NVIDIA)"
+    category: "GPU FYI|Windows|7|Nvidia|Release|x64"
+    short_name: "🐵"
+  }
+  builders: {
+    name: "buildbucket/luci.chromium.ci/Win7 FYI x64 dEQP Release (NVIDIA)"
+    category: "GPU FYI|Windows|7|Nvidia|dEQP|x64"
+    short_name: "🌻"
+  }
+  builders: {
+    name: "buildbot/chromium.gpu.fyi/Win7 FYI x64 dEQP Release (NVIDIA)"
+    category: "GPU FYI|Windows|7|Nvidia|dEQP|x64"
+    short_name: "🔥"
+  }
 }
 
 # Everything below was generated from buildermap.json.
@@ -2932,101 +3182,121 @@
 
   builders: {
     name: "buildbot/chromium.gpu.fyi/GPU FYI Win Builder"
+    name: "buildbucket/luci.chromium.ci/GPU FYI Win Builder"
     category: "Windows|Builder"
     short_name: "x86"
   }
   builders: {
     name: "buildbot/chromium.gpu.fyi/GPU FYI Win x64 Builder"
+    name: "buildbucket/luci.chromium.ci/GPU FYI Win x64 Builder"
     category: "Windows|Builder"
     short_name: "x64"
   }
   builders: {
     name: "buildbot/chromium.gpu.fyi/GPU FYI Win dEQP Builder"
+    name: "buildbucket/luci.chromium.ci/GPU FYI Win dEQP Builder"
     category: "Windows|Builder|dEQP"
     short_name: "x86"
   }
   builders: {
     name: "buildbot/chromium.gpu.fyi/GPU FYI Win x64 dEQP Builder"
+    name: "buildbucket/luci.chromium.ci/GPU FYI Win x64 dEQP Builder"
     category: "Windows|Builder|dEQP"
     short_name: "x64"
   }
   builders: {
     name: "buildbot/chromium.gpu.fyi/GPU FYI Win Builder (dbg)"
+    name: "buildbucket/luci.chromium.ci/GPU FYI Win Builder (dbg)"
     category: "Windows|Builder|Debug"
     short_name: "x86"
   }
   builders: {
     name: "buildbot/chromium.gpu.fyi/GPU FYI Win x64 Builder (dbg)"
+    name: "buildbucket/luci.chromium.ci/GPU FYI Win x64 Builder (dbg)"
     category: "Windows|Builder|Debug"
     short_name: "x64"
   }
   builders: {
     name: "buildbot/chromium.gpu.fyi/GPU FYI Win Clang Builder (dbg)"
+    name: "buildbucket/luci.chromium.ci/GPU FYI Win Clang Builder (dbg)"
     category: "Windows|Builder|Debug"
     short_name: "clg"
   }
   builders: {
     name: "buildbot/chromium.gpu.fyi/Win10 FYI Debug (NVIDIA)"
+    name: "buildbucket/luci.chromium.ci/Win10 FYI Debug (NVIDIA)"
     category: "Windows|10"
     short_name: "nvi"
   }
   builders: {
     name: "buildbot/chromium.gpu.fyi/Win10 FYI Release (Intel HD 630)"
+    name: "buildbucket/luci.chromium.ci/Win10 FYI Release (Intel HD 630)"
     category: "Windows|10|Release"
     short_name: "int"
   }
   builders: {
     name: "buildbot/chromium.gpu.fyi/Win10 FYI Release (NVIDIA)"
+    name: "buildbucket/luci.chromium.ci/Win10 FYI Release (NVIDIA)"
     category: "Windows|10|Release"
     short_name: "nvi"
   }
   builders: {
     name: "buildbot/chromium.gpu.fyi/Win7 FYI Debug (AMD)"
+    name: "buildbucket/luci.chromium.ci/Win7 FYI Debug (AMD)"
     category: "Windows|7|AMD"
     short_name: "dbg"
   }
   builders: {
     name: "buildbot/chromium.gpu.fyi/Win7 FYI dEQP Release (AMD)"
+    name: "buildbucket/luci.chromium.ci/Win7 FYI dEQP Release (AMD)"
     category: "Windows|7|AMD"
     short_name: "dqp"
   }
   builders: {
     name: "buildbot/chromium.gpu.fyi/Win7 FYI Release (AMD)"
+    name: "buildbucket/luci.chromium.ci/Win7 FYI Release (AMD)"
     category: "Windows|7|AMD"
     short_name: "rel"
   }
   builders: {
     name: "buildbot/chromium.gpu.fyi/Win7 FYI Debug (NVIDIA)"
+    name: "buildbucket/luci.chromium.ci/Win7 FYI Debug (NVIDIA)"
     category: "Windows|7|Nvidia"
     short_name: "dbg"
   }
   builders: {
     name: "buildbot/chromium.gpu.fyi/Win10 FYI Exp Release (NVIDIA)"
+    name: "buildbucket/luci.chromium.ci/Win10 FYI Exp Release (NVIDIA)"
     category: "Windows|10|Nvidia"
     short_name: "exp"
   }
   builders: {
     name: "buildbot/chromium.gpu.fyi/Win7 FYI Release (NVIDIA)"
+    name: "buildbucket/luci.chromium.ci/Win7 FYI Release (NVIDIA)"
     category: "Windows|7|Nvidia"
     short_name: "rel"
   }
   builders: {
     name: "buildbot/chromium.gpu.fyi/Win10 FYI dEQP Release (NVIDIA)"
+    name: "buildbucket/luci.chromium.ci/Win10 FYI dEQP Release (NVIDIA)"
     category: "Windows|10|Nvidia"
     short_name: "dqp"
   }
   builders: {
     name: "buildbot/chromium.gpu.fyi/Win7 FYI x64 Debug (NVIDIA)"
+    name: "buildbucket/luci.chromium.ci/Win7 FYI x64 Debug (NVIDIA)"
     category: "Windows|7|Nvidia|x64"
     short_name: "dbg"
   }
   builders: {
     name: "buildbot/chromium.gpu.fyi/Win7 FYI x64 Release (NVIDIA)"
+    name: "buildbucket/luci.chromium.ci/Win7 FYI x64 Release (NVIDIA)"
     category: "Windows|7|Nvidia|x64"
     short_name: "rel"
   }
   builders: {
     name: "buildbot/chromium.gpu.fyi/Win7 FYI x64 dEQP Release (NVIDIA)"
+    name: "buildbucket/luci.chromium.ci/Win7 FYI x64 dEQP Release (NVIDIA)"
     category: "Windows|7|Nvidia|x64"
     short_name: "dqp"
   }
diff --git a/infra/config/global/luci-scheduler.cfg b/infra/config/global/luci-scheduler.cfg
index dd726f7..8eef5b5b 100644
--- a/infra/config/global/luci-scheduler.cfg
+++ b/infra/config/global/luci-scheduler.cfg
@@ -58,6 +58,10 @@
 
   # Linux. Sorted alphabetically.
   triggers: "Cast Linux"
+  triggers: "Fuchsia ARM64"
+  triggers: "Fuchsia ARM64 Cast Audio"
+  triggers: "Fuchsia x64"
+  triggers: "Fuchsia x64 Cast Audio"
   triggers: "GPU FYI Linux Builder"
   triggers: "GPU FYI Linux Builder (dbg)"
   triggers: "GPU FYI Linux dEQP Builder"
@@ -218,6 +222,46 @@
 }
 
 job {
+  id: "Fuchsia ARM64"
+  acl_sets: "default"
+  buildbucket: {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "Fuchsia ARM64"
+  }
+}
+
+job {
+  id: "Fuchsia ARM64 Cast Audio"
+  acl_sets: "default"
+  buildbucket: {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "Fuchsia ARM64 Cast Audio"
+  }
+}
+
+job {
+  id: "Fuchsia x64"
+  acl_sets: "default"
+  buildbucket: {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "Fuchsia x64"
+  }
+}
+
+job {
+  id: "Fuchsia x64 Cast Audio"
+  acl_sets: "default"
+  buildbucket: {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "Fuchsia x64 Cast Audio"
+  }
+}
+
+job {
   id: "GPU FYI Linux Builder"
   acl_sets: "default"
   buildbucket: {
diff --git a/ios/chrome/browser/about_flags.mm b/ios/chrome/browser/about_flags.mm
index a1526f4e..8e4af4e 100644
--- a/ios/chrome/browser/about_flags.mm
+++ b/ios/chrome/browser/about_flags.mm
@@ -182,17 +182,6 @@
      flag_descriptions::kOmniboxUIElideSuggestionUrlAfterHostDescription,
      flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(omnibox::kUIExperimentElideSuggestionUrlAfterHost)},
-    {"omnibox-ui-hide-suggestion-url-scheme",
-     flag_descriptions::kOmniboxUIHideSuggestionUrlSchemeName,
-     flag_descriptions::kOmniboxUIHideSuggestionUrlSchemeDescription,
-     flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(omnibox::kUIExperimentHideSuggestionUrlScheme)},
-    {"omnibox-ui-hide-suggestion-url-trivial-subdomains",
-     flag_descriptions::kOmniboxUIHideSuggestionUrlTrivialSubdomainsName,
-     flag_descriptions::kOmniboxUIHideSuggestionUrlTrivialSubdomainsDescription,
-     flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(
-         omnibox::kUIExperimentHideSuggestionUrlTrivialSubdomains)},
 #if defined(__IPHONE_11_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0)
     {"drag_and_drop", flag_descriptions::kDragAndDropName,
      flag_descriptions::kDragAndDropDescription, flags_ui::kOsIos,
diff --git a/ios/chrome/browser/browser_state/BUILD.gn b/ios/chrome/browser/browser_state/BUILD.gn
index 0a714c9..de91492 100644
--- a/ios/chrome/browser/browser_state/BUILD.gn
+++ b/ios/chrome/browser/browser_state/BUILD.gn
@@ -10,13 +10,17 @@
     "chrome_browser_state.mm",
     "chrome_browser_state_manager.h",
   ]
+
+  public_deps = [
+    "//ios/web",
+    "//net",
+  ]
+
   deps = [
     "//base",
     "//components/prefs",
     "//components/sync_preferences",
     "//ios/chrome/browser/net:net_types",
-    "//ios/web",
-    "//net",
   ]
 
   configs += [ "//build/config/compiler:enable_arc" ]
@@ -138,6 +142,7 @@
     "test_chrome_browser_state_manager_unittest.cc",
   ]
   deps = [
+    ":browser_state",
     ":test_support",
     "//base",
     "//ios/web/public/test",
@@ -156,8 +161,12 @@
     "test_chrome_browser_state_manager.cc",
     "test_chrome_browser_state_manager.h",
   ]
-  deps = [
+
+  public_deps = [
     ":browser_state",
+  ]
+
+  deps = [
     ":browser_state_impl",
     "//base",
     "//components/bookmarks/browser",
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm
index 9494d4b..72ddbc02 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm
@@ -55,9 +55,9 @@
 #include "net/http/http_util.h"
 #include "net/http/transport_security_persister.h"
 #include "net/nqe/network_quality_estimator.h"
-#include "net/proxy_resolution/proxy_config_service_fixed.h"
 #include "net/proxy_resolution/pac_file_fetcher_impl.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_config_service_fixed.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/ssl/channel_id_service.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "net/url_request/data_protocol_handler.h"
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/ios_chrome_flag_descriptions.cc
index 5a8ce2d..fed0f60 100644
--- a/ios/chrome/browser/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/ios_chrome_flag_descriptions.cc
@@ -88,17 +88,6 @@
     "Elides the path, query, and ref of suggested URLs in the omnibox "
     "dropdown.";
 
-const char kOmniboxUIHideSuggestionUrlSchemeName[] =
-    "Hide scheme in omnibox suggestions";
-const char kOmniboxUIHideSuggestionUrlSchemeDescription[] =
-    "Elides the schemes of suggested URLs in the omnibox dropdown.";
-
-const char kOmniboxUIHideSuggestionUrlTrivialSubdomainsName[] =
-    "Hide trivial subdomains in omnibox suggestions";
-const char kOmniboxUIHideSuggestionUrlTrivialSubdomainsDescription[] =
-    "Elides trivially informative subdomains (www, m) from suggested URLs in "
-    "the omnibox dropdown.";
-
 const char kPasswordExportName[] = "Password Export";
 const char kPasswordExportDescription[] =
     "Enables password exporting functionality in password settings.";
diff --git a/ios/chrome/browser/ios_chrome_flag_descriptions.h b/ios/chrome/browser/ios_chrome_flag_descriptions.h
index 60d8a7a..188c93f4 100644
--- a/ios/chrome/browser/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/ios_chrome_flag_descriptions.h
@@ -76,16 +76,6 @@
 extern const char kOmniboxUIElideSuggestionUrlAfterHostName[];
 extern const char kOmniboxUIElideSuggestionUrlAfterHostDescription[];
 
-// Title and description for the flag to enable hiding the URL scheme in
-// omnibox URL suggestions.
-extern const char kOmniboxUIHideSuggestionUrlSchemeName[];
-extern const char kOmniboxUIHideSuggestionUrlSchemeDescription[];
-
-// Title and description for the flag to enable hiding trivial subdomains
-// (www, m) in omnibox URL suggestions.
-extern const char kOmniboxUIHideSuggestionUrlTrivialSubdomainsName[];
-extern const char kOmniboxUIHideSuggestionUrlTrivialSubdomainsDescription[];
-
 // Title and description for the flag to enable the ability to export passwords
 // from the password settings.
 extern const char kPasswordExportName[];
diff --git a/ios/chrome/browser/suggestions/suggestions_service_factory.mm b/ios/chrome/browser/suggestions/suggestions_service_factory.mm
index 0cb06af..6ad50ef 100644
--- a/ios/chrome/browser/suggestions/suggestions_service_factory.mm
+++ b/ios/chrome/browser/suggestions/suggestions_service_factory.mm
@@ -96,7 +96,7 @@
   return std::make_unique<SuggestionsServiceImpl>(
       identity_manager, sync_service, browser_state->GetRequestContext(),
       std::move(suggestions_store), std::move(thumbnail_manager),
-      std::move(blacklist_store), std::make_unique<base::DefaultTickClock>());
+      std::move(blacklist_store), base::DefaultTickClock::GetInstance());
 }
 
 void SuggestionsServiceFactory::RegisterBrowserStatePrefs(
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index 5169c38..8252920 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -2229,7 +2229,7 @@
   _tabHistoryCoordinator.tabModel = _model;
   _tabHistoryCoordinator.presentationProvider = self;
   _tabHistoryCoordinator.tabHistoryUIUpdater =
-      [self.primaryToolbarCoordinator tabHistoryUIUpdater];
+      [self.toolbarInterface tabHistoryUIUpdater];
 
   _sadTabCoordinator = [[SadTabLegacyCoordinator alloc] init];
   _sadTabCoordinator.baseViewController = self;
diff --git a/ios/chrome/browser/ui/history_popup/requirements/tab_history_ui_updater.h b/ios/chrome/browser/ui/history_popup/requirements/tab_history_ui_updater.h
index e565a4c..6c28eb6 100644
--- a/ios/chrome/browser/ui/history_popup/requirements/tab_history_ui_updater.h
+++ b/ios/chrome/browser/ui/history_popup/requirements/tab_history_ui_updater.h
@@ -8,7 +8,6 @@
 #import "ios/chrome/browser/ui/history_popup/requirements/tab_history_constants.h"
 
 @protocol TabHistoryUIUpdater
-@optional
 // Tells the receiver to update its UI now that TabHistory popup will be
 // presented.
 - (void)updateUIForTabHistoryPresentationFrom:(ToolbarButtonType)button;
diff --git a/ios/chrome/browser/ui/history_popup/tab_history_legacy_coordinator.mm b/ios/chrome/browser/ui/history_popup/tab_history_legacy_coordinator.mm
index 2e86908..4371cf7 100644
--- a/ios/chrome/browser/ui/history_popup/tab_history_legacy_coordinator.mm
+++ b/ios/chrome/browser/ui/history_popup/tab_history_legacy_coordinator.mm
@@ -17,6 +17,7 @@
 #import "ios/chrome/browser/ui/history_popup/tab_history_popup_controller.h"
 #include "ios/chrome/browser/ui/rtl_geometry.h"
 #import "ios/chrome/browser/ui/toolbar/public/toolbar_controller_base_feature.h"
+#include "ios/chrome/browser/ui/ui_util.h"
 #import "ios/chrome/browser/ui/util/named_guide.h"
 #include "ios/web/public/navigation_item.h"
 #import "ios/web/public/navigation_manager.h"
@@ -70,6 +71,12 @@
   CGPoint origin = CGPointZero;
   origin = [self popupOriginForNamedGuide:kBackButtonGuide];
 
+  if (IsUIRefreshPhase1Enabled() && origin.y > 200) {
+    // TODO(crbug.com/804772): Remove this workaround once the new navigation
+    // menu popup can be presented from the bottom back/forward arrows.
+    origin.y -= 100;
+  }
+
   [self.tabHistoryUIUpdater
       updateUIForTabHistoryPresentationFrom:ToolbarButtonTypeBack];
   [self presentTabHistoryPopupWithItems:backwardItems origin:origin];
diff --git a/ios/chrome/browser/ui/ntp/incognito_view_controller.mm b/ios/chrome/browser/ui/ntp/incognito_view_controller.mm
index d34cd5d0..b24dea1 100644
--- a/ios/chrome/browser/ui/ntp/incognito_view_controller.mm
+++ b/ios/chrome/browser/ui/ntp/incognito_view_controller.mm
@@ -45,7 +45,7 @@
     _loader = loader;
     if (!IsIPadIdiom()) {
       _toolbarDelegate = toolbarDelegate;
-      [_toolbarDelegate setToolbarBackgroundAlpha:0];
+      [_toolbarDelegate setToolbarBackgroundToIncognitoNTPColorWithAlpha:1];
     }
   }
   return self;
@@ -69,7 +69,7 @@
 }
 
 - (void)dealloc {
-  [_toolbarDelegate setToolbarBackgroundAlpha:1];
+  [_toolbarDelegate setToolbarBackgroundToIncognitoNTPColorWithAlpha:0];
   [_incognitoView setDelegate:nil];
 }
 
@@ -79,12 +79,13 @@
 }
 
 - (void)wasShown {
-  CGFloat alpha = [self toolbarAlphaForScrollView:self.incognitoView];
-  [self.toolbarDelegate setToolbarBackgroundAlpha:alpha];
+  CGFloat alpha =
+      [self incognitoBackgroundAlphaForScrollView:self.incognitoView];
+  [self.toolbarDelegate setToolbarBackgroundToIncognitoNTPColorWithAlpha:alpha];
 }
 
 - (void)wasHidden {
-  [self.toolbarDelegate setToolbarBackgroundAlpha:1];
+  [self.toolbarDelegate setToolbarBackgroundToIncognitoNTPColorWithAlpha:0];
 }
 
 - (void)dismissModals {
@@ -104,17 +105,18 @@
 #pragma mark - UIScrollViewDelegate methods
 
 - (void)scrollViewDidScroll:(UIScrollView*)scrollView {
-  CGFloat alpha = [self toolbarAlphaForScrollView:self.incognitoView];
-  [self.toolbarDelegate setToolbarBackgroundAlpha:alpha];
+  CGFloat alpha =
+      [self incognitoBackgroundAlphaForScrollView:self.incognitoView];
+  [self.toolbarDelegate setToolbarBackgroundToIncognitoNTPColorWithAlpha:alpha];
 }
 
 #pragma mark - Private
 
-// Calculate the background alpha for the toolbar based on how much |scrollView|
-// has scrolled up.
-- (CGFloat)toolbarAlphaForScrollView:(UIScrollView*)scrollView {
-  CGFloat alpha = scrollView.contentOffset.y / kDistanceToFadeToolbar;
-  return MAX(MIN(alpha, 1), 0);
+// Calculate the alpha for the toolbar background color of the NTP's color.
+- (CGFloat)incognitoBackgroundAlphaForScrollView:(UIScrollView*)scrollView {
+  CGFloat alpha = (kDistanceToFadeToolbar - scrollView.contentOffset.y) /
+                  kDistanceToFadeToolbar;
+  return MAX(alpha, 0);
 }
 
 @end
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_controller_delegate.h b/ios/chrome/browser/ui/ntp/new_tab_page_controller_delegate.h
index cbb6a14..5a24684 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_controller_delegate.h
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_controller_delegate.h
@@ -7,8 +7,9 @@
 
 // Delete for NTP and it's subclasses to communicate with the toolbar.
 @protocol NewTabPageControllerDelegate
-// Sets the alpha for the toolbar's background views.
-- (void)setToolbarBackgroundAlpha:(CGFloat)alpha;
+// Sets the background color of the toolbar to the color of the incognito NTP,
+// with an |alpha|.
+- (void)setToolbarBackgroundToIncognitoNTPColorWithAlpha:(CGFloat)alpha;
 // Sets the toolbar location bar alpha and vertical offset based on |progress|.
 - (void)setScrollProgressForTabletOmnibox:(CGFloat)progress;
 @end
diff --git a/ios/chrome/browser/ui/tab_grid/BUILD.gn b/ios/chrome/browser/ui/tab_grid/BUILD.gn
index f6801046..cf1daa40 100644
--- a/ios/chrome/browser/ui/tab_grid/BUILD.gn
+++ b/ios/chrome/browser/ui/tab_grid/BUILD.gn
@@ -21,6 +21,7 @@
     "//base",
     "//components/favicon/ios",
     "//ios/chrome/browser",
+    "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/snapshots",
     "//ios/chrome/browser/tabs",
     "//ios/chrome/browser/ui/commands",
@@ -88,9 +89,12 @@
     ":tab_grid_ui",
     "//base",
     "//base/test:test_support",
+    "//ios/chrome/browser",
+    "//ios/chrome/browser/browser_state:test_support",
     "//ios/chrome/browser/tabs",
     "//ios/chrome/browser/ui/tab_switcher",
     "//ios/chrome/browser/web",
+    "//ios/chrome/browser/web:test_support",
     "//ios/chrome/browser/web_state_list",
     "//ios/chrome/browser/web_state_list:test_support",
     "//ios/chrome/test:block_cleanup_test",
diff --git a/ios/chrome/browser/ui/tab_grid/grid_commands.h b/ios/chrome/browser/ui/tab_grid/grid_commands.h
index 1bf3655..02db60f5 100644
--- a/ios/chrome/browser/ui/tab_grid/grid_commands.h
+++ b/ios/chrome/browser/ui/tab_grid/grid_commands.h
@@ -7,12 +7,16 @@
 
 // Commands issued to a model backing a grid UI.
 @protocol GridCommands
-// Tells the receiver to insert a new item at |index|. A negative |index| tells
-// the receiver to insert a new item at the end of the list.
-- (void)insertNewItemAtIndex:(NSInteger)index;
-// Tells the receiver to select the item at |index|.
+// Tells the receiver to insert a new item at the end of the list.
+- (void)addNewItem;
+// Tells the receiver to insert a new item at |index|. It is an error to call
+// this method with an |index| greater than the number of items in the model.
+- (void)insertNewItemAtIndex:(NSUInteger)index;
+// Tells the receiver to select the item at |index|. It is an error to call this
+// method with an |index| greater than the largest index in the model.
 - (void)selectItemAtIndex:(NSUInteger)index;
-// Tells the receiver to close the item at |index|.
+// Tells the receiver to close the item at |index|. It is an error to call this
+// method with an |index| greater than the largest index in the model.
 - (void)closeItemAtIndex:(NSUInteger)index;
 // Tells the receiver to close all items.
 - (void)closeAllItems;
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm
index a115d55..415ac5c 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm
@@ -9,13 +9,16 @@
 #include "base/scoped_observer.h"
 #include "base/strings/sys_string_conversions.h"
 #include "components/favicon/ios/web_favicon_driver.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/chrome/browser/chrome_url_constants.h"
 #import "ios/chrome/browser/snapshots/snapshot_tab_helper.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/ui/tab_grid/grid_consumer.h"
 #import "ios/chrome/browser/ui/tab_grid/grid_item.h"
 #import "ios/chrome/browser/web/tab_id_tab_helper.h"
-#import "ios/chrome/browser/web_state_list/web_state_list.h"
+#include "ios/chrome/browser/web_state_list/web_state_list.h"
 #import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h"
+#include "ios/chrome/browser/web_state_list/web_state_opener.h"
 #include "ios/web/public/web_state/web_state.h"
 #import "ios/web/public/web_state/web_state_observer_bridge.h"
 #include "ui/gfx/image/image.h"
@@ -158,8 +161,21 @@
 
 #pragma mark - GridCommands
 
-- (void)insertNewItemAtIndex:(NSInteger)index {
-  // TODO(crbug.com/804503) : Add alerts for unimplemented controls.
+- (void)addNewItem {
+  [self insertNewItemAtIndex:self.webStateList->count()];
+}
+
+- (void)insertNewItemAtIndex:(NSUInteger)index {
+  web::WebState::CreateParams params(self.tabModel.browserState);
+  std::unique_ptr<web::WebState> webState = web::WebState::Create(params);
+  self.webStateList->InsertWebState(
+      base::checked_cast<int>(index), std::move(webState),
+      (WebStateList::INSERT_FORCE_INDEX | WebStateList::INSERT_ACTIVATE),
+      WebStateOpener());
+  web::WebState::OpenURLParams openParams(
+      GURL(kChromeUINewTabURL), web::Referrer(),
+      WindowOpenDisposition::CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false);
+  self.webStateList->GetWebStateAt(index)->OpenURL(openParams);
 }
 
 - (void)selectItemAtIndex:(NSUInteger)index {
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator_unittest.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator_unittest.mm
index fa10d18b..219614e 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator_unittest.mm
@@ -8,7 +8,8 @@
 #include <memory>
 
 #include "base/mac/foundation_util.h"
-#include "base/test/scoped_task_environment.h"
+#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
+#include "ios/chrome/browser/chrome_url_constants.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/ui/tab_grid/grid_commands.h"
 #import "ios/chrome/browser/ui/tab_grid/grid_consumer.h"
@@ -18,6 +19,8 @@
 #include "ios/chrome/browser/web_state_list/web_state_list.h"
 #import "ios/chrome/browser/web_state_list/web_state_opener.h"
 #import "ios/web/public/test/fakes/test_web_state.h"
+#import "ios/web/public/test/fakes/test_web_state_delegate.h"
+#include "ios/web/public/test/test_web_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #import "testing/gtest_mac.h"
 #include "testing/platform_test.h"
@@ -28,23 +31,51 @@
 #error "This file requires ARC support."
 #endif
 
+// Fake WebStateList delegate that attaches the tab ID tab helper.
+class TabIdFakeWebStateListDelegate : public FakeWebStateListDelegate {
+ public:
+  explicit TabIdFakeWebStateListDelegate(web::WebStateDelegate* delegate)
+      : delegate_(delegate) {}
+  ~TabIdFakeWebStateListDelegate() override {}
+
+  // WebStateListDelegate implementation.
+  void WillAddWebState(web::WebState* web_state) override {
+    TabIdTabHelper::CreateForWebState(web_state);
+    web_state->SetDelegate(delegate_);
+  }
+  void WebStateDetached(web::WebState* web_state) override {
+    web_state->SetDelegate(nil);
+  }
+
+ private:
+  web::WebStateDelegate* delegate_;
+};
+
 class TabGridMediatorTest : public PlatformTest {
  public:
   TabGridMediatorTest() {
-    web_state_list_ = std::make_unique<WebStateList>(&web_state_list_delegate_);
+    browser_state_ = TestChromeBrowserState::Builder().Build();
+    web_state_list_delegate_ =
+        std::make_unique<TabIdFakeWebStateListDelegate>(&delegate_);
+    web_state_list_ =
+        std::make_unique<WebStateList>(web_state_list_delegate_.get());
     tab_model_ = OCMClassMock([TabModel class]);
     OCMStub([tab_model_ webStateList]).andReturn(web_state_list_.get());
+    OCMStub([tab_model_ browserState]).andReturn(browser_state_.get());
+    original_identifiers_ = [[NSMutableSet alloc] init];
 
     // Insert some web states.
     for (int i = 0; i < 3; i++) {
       auto web_state = std::make_unique<web::TestWebState>();
       TabIdTabHelper::CreateForWebState(web_state.get());
+      NSString* identifier =
+          TabIdTabHelper::FromWebState(web_state.get())->tab_id();
+      [original_identifiers_ addObject:identifier];
       web_state_list_->InsertWebState(i, std::move(web_state),
                                       WebStateList::INSERT_FORCE_INDEX,
                                       WebStateOpener());
     }
     web_state_list_->ActivateWebStateAt(1);
-
     consumer_ = OCMProtocolMock(@protocol(GridConsumer));
     mediator_ = [[TabGridMediator alloc] initWithConsumer:consumer_];
     mediator_.tabModel = tab_model_;
@@ -52,12 +83,15 @@
   ~TabGridMediatorTest() override {}
 
  protected:
-  base::test::ScopedTaskEnvironment task_environment_;
+  web::TestWebThreadBundle thread_bundle_;
+  std::unique_ptr<ios::ChromeBrowserState> browser_state_;
+  web::TestWebStateDelegate delegate_;
+  std::unique_ptr<TabIdFakeWebStateListDelegate> web_state_list_delegate_;
   std::unique_ptr<WebStateList> web_state_list_;
-  FakeWebStateListDelegate web_state_list_delegate_;
   id tab_model_;
   id consumer_;
   TabGridMediator* mediator_;
+  NSMutableSet* original_identifiers_;
 };
 
 // Tests that the consumer is populated after the tab model is set on the
@@ -146,17 +180,55 @@
   EXPECT_EQ(2, web_state_list_->active_index());
 }
 
-// Tests that the webStateList count is decremented when |-closeItemAtIndex:| is
-// called.
+// Tests that the |web_state_list_| count is decremented when
+// |-closeItemAtIndex:| is called.
 TEST_F(TabGridMediatorTest, CloseItemCommand) {
   // Previously there were 3 items.
   [mediator_ closeItemAtIndex:1];
   EXPECT_EQ(2, web_state_list_->count());
 }
 
-// Tests that the webStateList is empty when |-closeAllItems| is called.
+// Tests that the |web_state_list_| is empty when |-closeAllItems| is called.
 TEST_F(TabGridMediatorTest, CloseAllItemsCommand) {
   // Previously there were 3 items.
   [mediator_ closeAllItems];
   EXPECT_EQ(0, web_state_list_->count());
 }
+
+// Tests that when |-addNewItem| is called, the |web_state_list_| count is
+// incremented, the |active_index| is the newly added index, the new web state
+// has no opener, and the URL is the new tab page.
+TEST_F(TabGridMediatorTest, AddNewItemAtEndCommand) {
+  // Previously there were 3 items and the selected index was 1.
+  [mediator_ addNewItem];
+  EXPECT_EQ(4, web_state_list_->count());
+  EXPECT_EQ(3, web_state_list_->active_index());
+  web::WebState* web_state = web_state_list_->GetWebStateAt(3);
+  ASSERT_TRUE(web_state);
+  EXPECT_EQ(web_state->GetBrowserState(), browser_state_.get());
+  EXPECT_FALSE(web_state->HasOpener());
+  web::TestOpenURLRequest* request = delegate_.last_open_url_request();
+  ASSERT_TRUE(request);
+  EXPECT_EQ(kChromeUINewTabURL, request->params.url.spec());
+  NSString* identifier = TabIdTabHelper::FromWebState(web_state)->tab_id();
+  EXPECT_FALSE([original_identifiers_ containsObject:identifier]);
+}
+
+// Tests that when |-insertNewItemAtIndex:| is called, the |web_state_list_|
+// count is incremented, the |active_index| is the newly added index, the new
+// web state has no opener, and the URL is the new tab page.
+TEST_F(TabGridMediatorTest, InsertNewItemCommand) {
+  // Previously there were 3 items and the selected index was 1.
+  [mediator_ insertNewItemAtIndex:0];
+  EXPECT_EQ(4, web_state_list_->count());
+  EXPECT_EQ(0, web_state_list_->active_index());
+  web::WebState* web_state = web_state_list_->GetWebStateAt(0);
+  ASSERT_TRUE(web_state);
+  EXPECT_EQ(web_state->GetBrowserState(), browser_state_.get());
+  EXPECT_FALSE(web_state->HasOpener());
+  web::TestOpenURLRequest* request = delegate_.last_open_url_request();
+  ASSERT_TRUE(request);
+  EXPECT_EQ(kChromeUINewTabURL, request->params.url.spec());
+  NSString* identifier = TabIdTabHelper::FromWebState(web_state)->tab_id();
+  EXPECT_FALSE([original_identifiers_ containsObject:identifier]);
+}
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
index 493cb69..6c8bfe3 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -20,20 +20,6 @@
 NSString* const kTabGridDoneButtonAccessibilityID =
     @"TabGridDoneButtonAccessibilityID";
 
-namespace {
-// Temporary alert used while building this feature.
-UIAlertController* NotImplementedAlert() {
-  UIAlertController* alert =
-      [UIAlertController alertControllerWithTitle:@"Not implemented"
-                                          message:nil
-                                   preferredStyle:UIAlertControllerStyleAlert];
-  [alert addAction:[UIAlertAction actionWithTitle:@"OK"
-                                            style:UIAlertActionStyleCancel
-                                          handler:nil]];
-  return alert;
-}
-}  // namespace
-
 @interface TabGridViewController ()<GridViewControllerDelegate,
                                     UIScrollViewAccessibilityDelegate>
 // Child view controllers.
@@ -567,9 +553,19 @@
 }
 
 - (void)newTabButtonTapped:(id)sender {
-  [self presentViewController:NotImplementedAlert()
-                     animated:YES
-                   completion:nil];
+  switch (self.currentPage) {
+    case TabGridPageIncognitoTabs:
+      [self.incognitoTabsDelegate addNewItem];
+      [self.tabPresentationDelegate showActiveTab];
+      break;
+    case TabGridPageRegularTabs:
+      [self.regularTabsDelegate addNewItem];
+      [self.tabPresentationDelegate showActiveTab];
+      break;
+    case TabGridPageRemoteTabs:
+      // No-op. It is invalid to call insert new tab on remote tabs.
+      break;
+  }
 }
 
 @end
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/BUILD.gn b/ios/chrome/browser/ui/toolbar/adaptive/BUILD.gn
index 12bffc37..55676554 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/BUILD.gn
+++ b/ios/chrome/browser/ui/toolbar/adaptive/BUILD.gn
@@ -11,6 +11,7 @@
     "primary_toolbar_coordinator.mm",
     "secondary_toolbar_coordinator.h",
     "secondary_toolbar_coordinator.mm",
+    "toolbar_coordinatee.h",
     "toolbar_coordinator_adaptor.h",
     "toolbar_coordinator_adaptor.mm",
   ]
@@ -26,6 +27,7 @@
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
     "//ios/chrome/browser/ui/fullscreen",
+    "//ios/chrome/browser/ui/history_popup/requirements",
     "//ios/chrome/browser/ui/location_bar",
     "//ios/chrome/browser/ui/ntp",
     "//ios/chrome/browser/ui/ntp:util",
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_coordinator.h b/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_coordinator.h
index a51a295..a1f4faf43 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_coordinator.h
+++ b/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_coordinator.h
@@ -7,9 +7,8 @@
 
 #import <UIKit/UIKit.h>
 
-#import "ios/chrome/browser/ui/commands/toolbar_commands.h"
 #import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
-#import "ios/chrome/browser/ui/ntp/new_tab_page_controller_delegate.h"
+#import "ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinatee.h"
 #import "ios/chrome/browser/ui/toolbar/public/side_swipe_toolbar_snapshot_providing.h"
 
 @class AdaptiveToolbarViewController;
@@ -21,9 +20,7 @@
 // Coordinator for the adaptive toolbar. This Coordinator is the super class of
 // the specific coordinator (primary or secondary).
 @interface AdaptiveToolbarCoordinator
-    : ChromeCoordinator<NewTabPageControllerDelegate,
-                        SideSwipeToolbarSnapshotProviding,
-                        ToolbarCommands>
+    : ChromeCoordinator<SideSwipeToolbarSnapshotProviding, ToolbarCoordinatee>
 
 // Initializes this Coordinator with its |browserState|.
 - (instancetype)initWithBrowserState:(ios::ChromeBrowserState*)browserState
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_coordinator.mm b/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_coordinator.mm
index 6ed260d..2d88ea9 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_coordinator.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_coordinator.mm
@@ -85,9 +85,9 @@
   return toolbarSnapshot;
 }
 
-#pragma mark - ToolbarCoordinating
+#pragma mark - NewTabPageControllerDelegate
 
-- (void)setToolbarBackgroundAlpha:(CGFloat)alpha {
+- (void)setToolbarBackgroundToIncognitoNTPColorWithAlpha:(CGFloat)alpha {
   // TODO(crbug.com/803379): Implement that.
 }
 
@@ -101,6 +101,12 @@
   [self.viewController.toolsMenuButton triggerAnimation];
 }
 
+#pragma mark - ToolbarCoordinatee
+
+- (id<TabHistoryUIUpdater>)tabHistoryUIUpdater {
+  return self.viewController;
+}
+
 #pragma mark - Protected
 
 - (ToolbarButtonFactory*)buttonFactoryWithType:(ToolbarType)type {
@@ -120,9 +126,7 @@
   BOOL isNTP = IsVisibleUrlNewTabPage(webState);
 
   [self.mediator updateConsumerForWebState:webState];
-  if (webState != self.webStateList->GetActiveWebState() || isNTP) {
-    [self.viewController updateForSideSwipeSnapshotOnNTP:isNTP];
-  }
+  [self.viewController updateForSideSwipeSnapshotOnNTP:isNTP];
 }
 
 - (void)resetToolbarAfterSideSwipeSnapshot {
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view.h b/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view.h
index e772597..bc12c8a 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view.h
+++ b/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view.h
@@ -22,6 +22,9 @@
 // Progress bar displayed below the toolbar.
 @property(nonatomic, strong, readonly) MDCProgressView* progressBar;
 
+// The blur visual effect view.
+@property(nonatomic, strong, readonly) UIVisualEffectView* blur;
+
 // Button to navigate back.
 @property(nonatomic, strong, readonly) ToolbarButton* backButton;
 // Buttons to navigate forward.
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller.h b/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller.h
index d922985e..5f7b116 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller.h
+++ b/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller.h
@@ -7,6 +7,7 @@
 
 #import <UIKit/UIKit.h>
 
+#import "ios/chrome/browser/ui/history_popup/requirements/tab_history_ui_updater.h"
 #import "ios/chrome/browser/ui/ntp/new_tab_page_controller_delegate.h"
 #import "ios/chrome/browser/ui/toolbar/buttons/toolbar_type.h"
 #import "ios/chrome/browser/ui/toolbar/clean/toolbar_consumer.h"
@@ -24,7 +25,9 @@
 // dismissed on such events. For example, the tools menu is closed upon
 // rotation.
 @interface AdaptiveToolbarViewController
-    : UIViewController<ToolbarConsumer, NewTabPageControllerDelegate>
+    : UIViewController<TabHistoryUIUpdater,
+                       ToolbarConsumer,
+                       NewTabPageControllerDelegate>
 
 // Button factory.
 @property(nonatomic, strong) ToolbarButtonFactory* buttonFactory;
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller.mm b/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller.mm
index bae75e8..e0600a4d 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller.mm
@@ -6,9 +6,11 @@
 
 #import "base/logging.h"
 #include "base/metrics/user_metrics.h"
+#import "ios/chrome/browser/ui/commands/browser_commands.h"
 #import "ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view.h"
 #import "ios/chrome/browser/ui/toolbar/buttons/toolbar_button.h"
 #import "ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.h"
+#import "ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.h"
 #import "ios/chrome/browser/ui/toolbar/buttons/toolbar_constants.h"
 #import "ios/chrome/browser/ui/toolbar/buttons/toolbar_tab_grid_button.h"
 #import "ios/chrome/browser/ui/toolbar/buttons/toolbar_tools_menu_button.h"
@@ -40,11 +42,16 @@
 
 - (void)updateForSideSwipeSnapshotOnNTP:(BOOL)onNTP {
   self.view.progressBar.hidden = YES;
+  self.view.blur.hidden = YES;
+  self.view.backgroundColor =
+      self.buttonFactory.toolbarConfiguration.backgroundColor;
   // TODO(crbug.com/804850): Have the correct background color for incognito
   // NTP.
 }
 
 - (void)resetAfterSideSwipeSnapshot {
+  self.view.blur.hidden = NO;
+  self.view.backgroundColor = [UIColor clearColor];
 }
 
 #pragma mark - UIViewController
@@ -57,6 +64,15 @@
 - (void)viewDidLoad {
   [super viewDidLoad];
   [self addStandardActionsForAllButtons];
+
+  // Adds the layout guide to the buttons.
+  self.view.toolsMenuButton.guideName = kTabSwitcherGuide;
+  self.view.forwardButton.guideName = kForwardButtonGuide;
+  self.view.backButton.guideName = kBackButtonGuide;
+
+  // Add navigation popup menu triggers.
+  [self addLongPressGestureToView:self.view.backButton];
+  [self addLongPressGestureToView:self.view.forwardButton];
 }
 
 - (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection {
@@ -128,7 +144,7 @@
 
 #pragma mark - NewTabPageControllerDelegate
 
-- (void)setToolbarBackgroundAlpha:(CGFloat)alpha {
+- (void)setToolbarBackgroundToIncognitoNTPColorWithAlpha:(CGFloat)alpha {
   // TODO(crbug.com/803379): Implement that.
 }
 
@@ -151,6 +167,21 @@
        }];
 }
 
+#pragma mark - TabHistoryUIUpdater
+
+- (void)updateUIForTabHistoryPresentationFrom:(ToolbarButtonType)buttonType {
+  if (buttonType == ToolbarButtonTypeBack) {
+    self.view.backButton.selected = YES;
+  } else {
+    self.view.forwardButton.selected = YES;
+  }
+}
+
+- (void)updateUIForTabHistoryWasDismissed {
+  self.view.backButton.selected = NO;
+  self.view.forwardButton.selected = NO;
+}
+
 #pragma mark - Private
 
 // Updates all buttons visibility to match any recent WebState or SizeClass
@@ -204,4 +235,25 @@
   }
 }
 
+// Adds a LongPressGesture to the |view|, with target on -|handleLongPress:|.
+- (void)addLongPressGestureToView:(UIView*)view {
+  UILongPressGestureRecognizer* navigationHistoryLongPress =
+      [[UILongPressGestureRecognizer alloc]
+          initWithTarget:self
+                  action:@selector(handleLongPress:)];
+  [view addGestureRecognizer:navigationHistoryLongPress];
+}
+
+// Handles the long press on the views.
+- (void)handleLongPress:(UILongPressGestureRecognizer*)gesture {
+  if (gesture.state != UIGestureRecognizerStateBegan)
+    return;
+
+  if (gesture.view == self.view.backButton) {
+    [self.dispatcher showTabHistoryPopupForBackwardHistory];
+  } else if (gesture.view == self.view.forwardButton) {
+    [self.dispatcher showTabHistoryPopupForForwardHistory];
+  }
+}
+
 @end
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_coordinator.mm b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_coordinator.mm
index 81cb85b..2afc092 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_coordinator.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_coordinator.mm
@@ -86,10 +86,6 @@
   return self.locationBarCoordinator;
 }
 
-- (id<TabHistoryUIUpdater>)tabHistoryUIUpdater {
-  return self.viewController;
-}
-
 - (id<ActivityServicePositioner>)activityServicePositioner {
   return self.viewController;
 }
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.h b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.h
index 6f8d9e9..6cb5672 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.h
+++ b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.h
@@ -30,9 +30,6 @@
 // Container for the location bar.
 @property(nonatomic, strong, readonly) UIView* locationBarContainer;
 
-// The blur visual effect view.
-@property(nonatomic, strong, readwrite) UIVisualEffectView* blur;
-
 // The height of the container for the location bar.
 @property(nonatomic, strong, readonly) NSLayoutConstraint* locationBarHeight;
 
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.mm b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.mm
index 0510cedd..b6a9aa7 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view.mm
@@ -22,10 +22,12 @@
 // Factory used to create the buttons.
 @property(nonatomic, strong) ToolbarButtonFactory* buttonFactory;
 
-// Content view in which the view that might have vibrancy effect should be
-// added.
+// ContentView of the vibrancy effect if there is one, self otherwise.
 @property(nonatomic, strong) UIView* contentView;
 
+// The blur visual effect view, redefined as readwrite.
+@property(nonatomic, strong, readwrite) UIVisualEffectView* blur;
+
 // Container for the location bar, redefined as readwrite.
 @property(nonatomic, strong, readwrite) UIView* locationBarContainer;
 // The height of the container for the location bar, redefined as readwrite.
@@ -149,6 +151,7 @@
   self.blur = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
   self.blur.contentView.backgroundColor =
       self.buttonFactory.toolbarConfiguration.blurEffectBackgroundColor;
+  [self addSubview:self.blur];
 
   self.contentView = self;
 
@@ -157,12 +160,11 @@
     UIVisualEffectView* vibrancyView =
         [[UIVisualEffectView alloc] initWithEffect:vibrancy];
     self.contentView = vibrancyView.contentView;
-    [self.blur.contentView addSubview:vibrancyView];
+    [self addSubview:vibrancyView];
     vibrancyView.translatesAutoresizingMaskIntoConstraints = NO;
-    AddSameConstraints(self.blur, vibrancyView);
+    AddSameConstraints(self, vibrancyView);
   }
 
-  [self addSubview:self.blur];
 
   self.blur.translatesAutoresizingMaskIntoConstraints = NO;
   AddSameConstraints(self.blur, self);
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.h b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.h
index a4cbdc0..97a6351 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.h
+++ b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.h
@@ -7,7 +7,6 @@
 
 #import "ios/chrome/browser/ui/activity_services/requirements/activity_service_positioner.h"
 #import "ios/chrome/browser/ui/fullscreen/fullscreen_ui_element.h"
-#import "ios/chrome/browser/ui/history_popup/requirements/tab_history_ui_updater.h"
 #import "ios/chrome/browser/ui/orchestrator/toolbar_animatee.h"
 #import "ios/chrome/browser/ui/toolbar/adaptive/adaptive_toolbar_view_controller.h"
 
@@ -18,7 +17,6 @@
 @interface PrimaryToolbarViewController
     : AdaptiveToolbarViewController<ActivityServicePositioner,
                                     FullscreenUIElement,
-                                    TabHistoryUIUpdater,
                                     ToolbarAnimatee>
 
 @property(nonatomic, weak) id<PrimaryToolbarViewControllerDelegate> delegate;
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.mm b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.mm
index 35e99ee..f2e15a5a 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_view_controller.mm
@@ -91,19 +91,6 @@
   [self.view setUp];
 }
 
-- (void)viewDidLoad {
-  [super viewDidLoad];
-
-  // Adds the layout guide to the buttons.
-  self.view.toolsMenuButton.guideName = kTabSwitcherGuide;
-  self.view.forwardButton.guideName = kForwardButtonGuide;
-  self.view.backButton.guideName = kBackButtonGuide;
-
-  // Add navigation popup menu triggers.
-  [self addLongPressGestureToView:self.view.backButton];
-  [self addLongPressGestureToView:self.view.forwardButton];
-}
-
 - (void)didMoveToParentViewController:(UIViewController*)parent {
   [super didMoveToParentViewController:parent];
   UIView* omniboxView = self.view.locationBarContainer;
@@ -140,21 +127,6 @@
   return self.view.shareButton;
 }
 
-#pragma mark - TabHistoryUIUpdater
-
-- (void)updateUIForTabHistoryPresentationFrom:(ToolbarButtonType)buttonType {
-  if (buttonType == ToolbarButtonTypeBack) {
-    self.view.backButton.selected = YES;
-  } else {
-    self.view.forwardButton.selected = YES;
-  }
-}
-
-- (void)updateUIForTabHistoryWasDismissed {
-  self.view.backButton.selected = NO;
-  self.view.forwardButton.selected = NO;
-}
-
 #pragma mark - FullscreenUIElement
 
 - (void)updateForFullscreenProgress:(CGFloat)progress {
@@ -249,25 +221,4 @@
   [NSLayoutConstraint deactivateConstraints:self.view.expandedConstraints];
 }
 
-// Adds a LongPressGesture to the |view|, with target on -|handleLongPress:|.
-- (void)addLongPressGestureToView:(UIView*)view {
-  UILongPressGestureRecognizer* navigationHistoryLongPress =
-      [[UILongPressGestureRecognizer alloc]
-          initWithTarget:self
-                  action:@selector(handleLongPress:)];
-  [view addGestureRecognizer:navigationHistoryLongPress];
-}
-
-// Handles the long press on the views.
-- (void)handleLongPress:(UILongPressGestureRecognizer*)gesture {
-  if (gesture.state != UIGestureRecognizerStateBegan)
-    return;
-
-  if (gesture.view == self.view.backButton) {
-    [self.dispatcher showTabHistoryPopupForBackwardHistory];
-  } else if (gesture.view == self.view.forwardButton) {
-    [self.dispatcher showTabHistoryPopupForForwardHistory];
-  }
-}
-
 @end
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view.mm b/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view.mm
index 2926bc0..260a995 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view.mm
@@ -23,6 +23,9 @@
 // Redefined as readwrite
 @property(nonatomic, strong, readwrite) NSArray<ToolbarButton*>* allButtons;
 
+// The blur visual effect view, redefined as readwrite.
+@property(nonatomic, strong, readwrite) UIVisualEffectView* blur;
+
 // The stack view containing the buttons.
 @property(nonatomic, strong) UIStackView* stackView;
 
@@ -49,6 +52,7 @@
 @synthesize toolsMenuButton = _toolsMenuButton;
 @synthesize omniboxButton = _omniboxButton;
 @synthesize tabGridButton = _tabGridButton;
+@synthesize blur = _blur;
 
 #pragma mark - Public
 
@@ -80,14 +84,13 @@
   self.translatesAutoresizingMaskIntoConstraints = NO;
 
   UIBlurEffect* blurEffect = self.buttonFactory.toolbarConfiguration.blurEffect;
-  UIVisualEffectView* blur =
-      [[UIVisualEffectView alloc] initWithEffect:blurEffect];
-  blur.contentView.backgroundColor =
+  self.blur = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
+  self.blur.contentView.backgroundColor =
       self.buttonFactory.toolbarConfiguration.blurEffectBackgroundColor;
 
-  [self addSubview:blur];
-  blur.translatesAutoresizingMaskIntoConstraints = NO;
-  AddSameConstraints(blur, self);
+  [self addSubview:self.blur];
+  self.blur.translatesAutoresizingMaskIntoConstraints = NO;
+  AddSameConstraints(self.blur, self);
 
   UIView* contentView = self;
   if (UIVisualEffect* vibrancy = [self.buttonFactory.toolbarConfiguration
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view_controller.mm b/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view_controller.mm
index 1b600ab..5c8ef778 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view_controller.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive/secondary_toolbar_view_controller.mm
@@ -28,11 +28,6 @@
       [[SecondaryToolbarView alloc] initWithButtonFactory:self.buttonFactory];
 }
 
-- (void)viewDidLoad {
-  [super viewDidLoad];
-  self.view.toolsMenuButton.guideName = kTabSwitcherGuide;
-}
-
 - (void)didMoveToParentViewController:(UIViewController*)parent {
   [super didMoveToParentViewController:parent];
   [NamedGuide guideWithName:kSecondaryToolbar view:self.view].constrainedView =
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinatee.h b/ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinatee.h
new file mode 100644
index 0000000..b77ab93
--- /dev/null
+++ b/ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinatee.h
@@ -0,0 +1,20 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_TOOLBAR_ADAPTIVE_TOOLBAR_COORDINATEE_H_
+#define IOS_CHROME_BROWSER_UI_TOOLBAR_ADAPTIVE_TOOLBAR_COORDINATEE_H_
+
+#import "ios/chrome/browser/ui/commands/toolbar_commands.h"
+#import "ios/chrome/browser/ui/ntp/new_tab_page_controller_delegate.h"
+
+@protocol TabHistoryUIUpdater;
+
+// Defines a class being coordinated by a ToolbarCoordinating.
+@protocol ToolbarCoordinatee<NewTabPageControllerDelegate, ToolbarCommands>
+
+- (id<TabHistoryUIUpdater>)tabHistoryUIUpdater;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_TOOLBAR_ADAPTIVE_TOOLBAR_COORDINATEE_H_
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinator_adaptor.h b/ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinator_adaptor.h
index d26dcb9d..f1e3c8e 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinator_adaptor.h
+++ b/ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinator_adaptor.h
@@ -9,7 +9,7 @@
 #import "ios/chrome/browser/ui/tools_menu/public/tools_menu_presentation_state_provider.h"
 
 @class CommandDispatcher;
-@protocol ToolbarCommands;
+@protocol ToolbarCoordinatee;
 @protocol ToolsMenuConfigurationProvider;
 
 // This object is an interface between multiple toolbars and the objects which
@@ -25,8 +25,7 @@
 
 // Adds a |toolbarCoordinator| to the set of coordinators this object is
 // interfacing with.
-- (void)addToolbarCoordinator:
-    (id<NewTabPageControllerDelegate, ToolbarCommands>)toolbarCoordinator;
+- (void)addToolbarCoordinator:(id<ToolbarCoordinatee>)toolbarCoordinator;
 
 @end
 
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinator_adaptor.mm b/ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinator_adaptor.mm
index 09641e78..7778c377 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinator_adaptor.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinator_adaptor.mm
@@ -6,15 +6,18 @@
 
 #import "ios/chrome/browser/ui/commands/command_dispatcher.h"
 #import "ios/chrome/browser/ui/commands/toolbar_commands.h"
+#import "ios/chrome/browser/ui/history_popup/requirements/tab_history_ui_updater.h"
+#import "ios/chrome/browser/ui/toolbar/adaptive/toolbar_coordinatee.h"
 #import "ios/chrome/browser/ui/tools_menu/tools_menu_coordinator.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
-@interface ToolbarCoordinatorAdaptor ()<ToolbarCommands>
+@interface ToolbarCoordinatorAdaptor ()<TabHistoryUIUpdater, ToolbarCommands>
 @property(nonatomic, strong)
-    NSMutableArray<id<ToolbarCoordinating, ToolbarCommands>>* coordinators;
+    NSMutableArray<id<NewTabPageControllerDelegate, ToolbarCommands>>*
+        coordinators;
 // Coordinator for the toolsMenu.
 @property(nonatomic, strong) ToolsMenuCoordinator* toolsMenuCoordinator;
 @end
@@ -44,20 +47,20 @@
 }
 
 - (void)addToolbarCoordinator:
-    (id<ToolbarCoordinating, ToolbarCommands>)toolbarCoordinator {
+    (id<NewTabPageControllerDelegate, ToolbarCommands>)toolbarCoordinator {
   [self.coordinators addObject:toolbarCoordinator];
 }
 
 #pragma mark - NewTabPageControllerDelegate
 
-- (void)setToolbarBackgroundAlpha:(CGFloat)alpha {
-  for (id<ToolbarCoordinating> coordinator in self.coordinators) {
-    [coordinator setToolbarBackgroundAlpha:alpha];
+- (void)setToolbarBackgroundToIncognitoNTPColorWithAlpha:(CGFloat)alpha {
+  for (id<NewTabPageControllerDelegate> coordinator in self.coordinators) {
+    [coordinator setToolbarBackgroundToIncognitoNTPColorWithAlpha:alpha];
   }
 }
 
 - (void)setScrollProgressForTabletOmnibox:(CGFloat)progress {
-  for (id<ToolbarCoordinating> coordinator in self.coordinators) {
+  for (id<NewTabPageControllerDelegate> coordinator in self.coordinators) {
     [coordinator setScrollProgressForTabletOmnibox:progress];
   }
 }
@@ -82,4 +85,23 @@
   [self.toolsMenuCoordinator updateConfiguration];
 }
 
+- (id<TabHistoryUIUpdater>)tabHistoryUIUpdater {
+  return self;
+}
+
+#pragma mark - TabHistoryUIUpdater
+
+- (void)updateUIForTabHistoryPresentationFrom:(ToolbarButtonType)button {
+  for (id<ToolbarCoordinatee> coordinator in self.coordinators) {
+    [coordinator.tabHistoryUIUpdater
+        updateUIForTabHistoryPresentationFrom:button];
+  }
+}
+
+- (void)updateUIForTabHistoryWasDismissed {
+  for (id<ToolbarCoordinatee> coordinator in self.coordinators) {
+    [coordinator.tabHistoryUIUpdater updateUIForTabHistoryWasDismissed];
+  }
+}
+
 @end
diff --git a/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.h b/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.h
index d5967d0..41eb942 100644
--- a/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.h
+++ b/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.h
@@ -30,7 +30,6 @@
 @property(nonatomic, readonly) UIColor* NTPBackgroundColor;
 
 // Background color of the toolbar.
-// TODO(crbug.com/800266): Remove this property.
 @property(nonatomic, readonly) UIColor* backgroundColor;
 
 // Background color of the omnibox.
diff --git a/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.mm b/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.mm
index 3ecf9077..043786ad 100644
--- a/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.mm
+++ b/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.mm
@@ -57,8 +57,13 @@
 
 - (UIColor*)backgroundColor {
   if (IsUIRefreshPhase1Enabled()) {
-    NOTREACHED();
-    return nil;
+    switch (self.style) {
+      case NORMAL:
+        return
+            [UIColor colorWithWhite:kBlurBackgroundGrayscaleComponent alpha:1];
+      case INCOGNITO:
+        return UIColorFromRGB(kIncognitoToolbarBackgroundColor);
+    }
   } else {
     switch (self.style) {
       case NORMAL:
diff --git a/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.mm b/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.mm
index a43f8a58..e9ca68c 100644
--- a/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.mm
+++ b/ios/chrome/browser/ui/toolbar/clean/toolbar_coordinator.mm
@@ -214,7 +214,7 @@
   if (!self.started)
     return;
 
-  [self setToolbarBackgroundAlpha:1];
+  [self setToolbarBackgroundToIncognitoNTPColorWithAlpha:0];
   self.started = NO;
   self.delegate = nil;
   [self.mediator disconnect];
@@ -309,9 +309,8 @@
 
 #pragma mark - NewTabPageControllerDelegate
 
-- (void)setToolbarBackgroundAlpha:(CGFloat)alpha {
-  [self.toolbarViewController
-      setBackgroundToIncognitoNTPColorWithAlpha:1 - alpha];
+- (void)setToolbarBackgroundToIncognitoNTPColorWithAlpha:(CGFloat)alpha {
+  [self.toolbarViewController setBackgroundToIncognitoNTPColorWithAlpha:alpha];
 }
 
 - (void)setScrollProgressForTabletOmnibox:(CGFloat)progress {
diff --git a/ios/chrome/browser/ui/toolbar/clean/toolbar_view.mm b/ios/chrome/browser/ui/toolbar/clean/toolbar_view.mm
index 38a4a1a0..a4739cf 100644
--- a/ios/chrome/browser/ui/toolbar/clean/toolbar_view.mm
+++ b/ios/chrome/browser/ui/toolbar/clean/toolbar_view.mm
@@ -215,6 +215,7 @@
         self.buttonFactory.toolbarConfiguration.NTPBackgroundColor;
     [self insertSubview:_backgroundView atIndex:0];
     AddSameConstraints(self, _backgroundView);
+    _backgroundView.alpha = 0;
   }
   return _backgroundView;
 }
diff --git a/ios/chrome/browser/ui/toolbar/public/primary_toolbar_coordinator.h b/ios/chrome/browser/ui/toolbar/public/primary_toolbar_coordinator.h
index 88a8bfb..be3afdf 100644
--- a/ios/chrome/browser/ui/toolbar/public/primary_toolbar_coordinator.h
+++ b/ios/chrome/browser/ui/toolbar/public/primary_toolbar_coordinator.h
@@ -12,7 +12,6 @@
 
 @protocol ActivityServicePositioner;
 @protocol QRScannerResultLoading;
-@protocol TabHistoryUIUpdater;
 @protocol VoiceSearchControllerDelegate;
 
 // Protocol defining a primary toolbar, in a paradigm where the toolbar can be
@@ -27,7 +26,6 @@
 // internal ViewController.
 - (id<VoiceSearchControllerDelegate>)voiceSearchDelegate;
 - (id<QRScannerResultLoading>)QRScannerResultLoader;
-- (id<TabHistoryUIUpdater>)tabHistoryUIUpdater;
 - (id<ActivityServicePositioner>)activityServicePositioner;
 - (id<OmniboxFocuser>)omniboxFocuser;
 
diff --git a/ios/chrome/browser/ui/toolbar/public/toolbar_coordinating.h b/ios/chrome/browser/ui/toolbar/public/toolbar_coordinating.h
index 671ea16d..dbcfcd2 100644
--- a/ios/chrome/browser/ui/toolbar/public/toolbar_coordinating.h
+++ b/ios/chrome/browser/ui/toolbar/public/toolbar_coordinating.h
@@ -9,11 +9,16 @@
 
 #import "ios/chrome/browser/ui/ntp/new_tab_page_controller_delegate.h"
 
+@protocol TabHistoryUIUpdater;
+
+// Defines a class coordinating the interactions with the toolbar.
 @protocol ToolbarCoordinating<NewTabPageControllerDelegate>
 
 // Updates the tools menu, changing its content to reflect the current page.
 - (void)updateToolsMenu;
 
+- (id<TabHistoryUIUpdater>)tabHistoryUIUpdater;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TOOLBAR_PUBLIC_TOOLBAR_COORDINATING_H_
diff --git a/ios/components/io_thread/ios_io_thread.mm b/ios/components/io_thread/ios_io_thread.mm
index 99c9fb9..609d047 100644
--- a/ios/components/io_thread/ios_io_thread.mm
+++ b/ios/components/io_thread/ios_io_thread.mm
@@ -52,9 +52,9 @@
 #include "net/http/http_network_layer.h"
 #include "net/http/http_server_properties_impl.h"
 #include "net/log/net_log_event_type.h"
-#include "net/proxy_resolution/proxy_config_service.h"
 #include "net/proxy_resolution/pac_file_fetcher_impl.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_config_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/socket/tcp_client_socket.h"
 #include "net/spdy/chromium/spdy_session.h"
 #include "net/ssl/channel_id_service.h"
diff --git a/ios/web/DEPS b/ios/web/DEPS
index 981113d..d7b14c05 100644
--- a/ios/web/DEPS
+++ b/ios/web/DEPS
@@ -5,8 +5,8 @@
   "+ios/web",
   "+mojo/public",
   "+net",
-  "+services/network/public/mojom/url_loader_factory.mojom.h",
-  "+services/network/url_loader.h",
+  "+services/network/network_context.h",
+  "+services/network/public/mojom",
   "+ui",
 
   # Needed to embed the ServiceManager in //ios/web.
diff --git a/ios/web/browser_state.mm b/ios/web/browser_state.mm
index d646688..7bddcb9 100644
--- a/ios/web/browser_state.mm
+++ b/ios/web/browser_state.mm
@@ -19,9 +19,10 @@
 #include "ios/web/public/web_client.h"
 #include "ios/web/public/web_thread.h"
 #include "ios/web/webui/url_data_manager_ios_backend.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
 #include "net/url_request/url_request_context_getter.h"
-#include "services/network/public/mojom/url_loader_factory.mojom.h"
-#include "services/network/url_loader.h"
+#include "net/url_request/url_request_context_getter_observer.h"
+#include "services/network/network_context.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/mojom/service.mojom.h"
 
@@ -106,50 +107,55 @@
 
 }  // namespace
 
-class BrowserState::URLLoaderFactory : public network::mojom::URLLoaderFactory {
+// Class that owns a NetworkContext wrapping the BrowserState's
+// URLRequestContext.  This allows using the URLLoaderFactory and
+// NetworkContext APIs while still issuing requests with a URLRequestContext
+// created by a BrowserState subclass.
+//
+// Created on the UI thread by the BrowserState on first use, so the
+// BrowserState can own the NetworkContextOwner.  A task is then posted to the
+// IO thread to create the NetworkContext itself, which has to live on the IO
+// thread, since that's where the URLRequestContext lives.  Destroyed on the IO
+// thread during shutdown, to ensure the NetworkContext is destroyed on the
+// right thread.
+class BrowserState::NetworkContextOwner
+    : public net::URLRequestContextGetterObserver {
  public:
-  explicit URLLoaderFactory(net::URLRequestContextGetter* request_context)
-      : request_context_(request_context) {}
-
-  void CreateLoaderAndStart(network::mojom::URLLoaderRequest request,
-                            int32_t routing_id,
-                            int32_t request_id,
-                            uint32_t options,
-                            const network::ResourceRequest& resource_request,
-                            network::mojom::URLLoaderClientPtr client,
-                            const net::MutableNetworkTrafficAnnotationTag&
-                                traffic_annotation) override {
-    WebThread::PostTask(
-        web::WebThread::IO, FROM_HERE,
-        base::BindOnce(URLLoaderFactory::CreateLoaderAndStartOnIO,
-                       request_context_, std::move(request), routing_id,
-                       request_id, options, resource_request,
-                       client.PassInterface(), traffic_annotation));
+  explicit NetworkContextOwner(net::URLRequestContextGetter* request_context)
+      : request_context_(request_context) {
+    DCHECK_CURRENTLY_ON(WebThread::UI);
   }
 
-  void Clone(network::mojom::URLLoaderFactoryRequest request) override {
-    NOTREACHED() << "Clone shouldn't be called on iOS";
+  ~NetworkContextOwner() override {
+    DCHECK_CURRENTLY_ON(WebThread::IO);
+    if (request_context_)
+      request_context_->RemoveObserver(this);
+  }
+
+  void InitializeOnIOThread(
+      network::mojom::NetworkContextRequest network_context_request) {
+    DCHECK_CURRENTLY_ON(WebThread::IO);
+    DCHECK(!network_context_);
+
+    network_context_ = std::make_unique<network::NetworkContext>(
+        nullptr, std::move(network_context_request), request_context_);
+    request_context_->AddObserver(this);
+  }
+
+  // net::URLRequestContextGetterObserver implementation:
+  void OnContextShuttingDown() override {
+    DCHECK_CURRENTLY_ON(WebThread::IO);
+
+    // Cancels any pending requests owned by the NetworkContext.
+    network_context_.reset();
+
+    request_context_->RemoveObserver(this);
+    request_context_ = nullptr;
   }
 
  private:
-  static void CreateLoaderAndStartOnIO(
-      scoped_refptr<net::URLRequestContextGetter> request_getter,
-      network::mojom::URLLoaderRequest request,
-      int32_t routing_id,
-      int32_t request_id,
-      uint32_t options,
-      const network::ResourceRequest& resource_request,
-      network::mojom::URLLoaderClientPtrInfo client_info,
-      const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
-    // Object deletes itself when the pipe or the URLRequestContext goes away.
-    network::mojom::URLLoaderClientPtr client(std::move(client_info));
-    new network::URLLoader(
-        request_getter, nullptr, std::move(request), options, resource_request,
-        false, std::move(client),
-        static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation), 0,
-        nullptr, nullptr);
-  }
   scoped_refptr<net::URLRequestContextGetter> request_context_;
+  std::unique_ptr<network::NetworkContext> network_context_;
 };
 
 // static
@@ -182,6 +188,11 @@
       << "Attempting to destroy a BrowserState that never called "
       << "Initialize()";
 
+  if (network_context_) {
+    web::WebThread::DeleteSoon(web::WebThread::IO, FROM_HERE,
+                               network_context_owner_.release());
+  }
+
   RemoveBrowserStateFromUserIdMap(this);
 
   // Delete the URLDataManagerIOSBackend instance on the IO thread if it has
@@ -199,8 +210,20 @@
 
 network::mojom::URLLoaderFactory* BrowserState::GetURLLoaderFactory() {
   if (!url_loader_factory_) {
-    url_loader_factory_ =
-        std::make_unique<URLLoaderFactory>(GetRequestContext());
+    DCHECK(!network_context_);
+    DCHECK(!network_context_owner_);
+
+    network_context_owner_ =
+        std::make_unique<NetworkContextOwner>(GetRequestContext());
+    WebThread::PostTask(
+        web::WebThread::IO, FROM_HERE,
+        base::BindOnce(&NetworkContextOwner::InitializeOnIOThread,
+                       // This is safe, since the NetworkContextOwner will be
+                       // deleted on the IO thread.
+                       base::Unretained(network_context_owner_.get()),
+                       mojo::MakeRequest(&network_context_)));
+    network_context_->CreateURLLoaderFactory(
+        mojo::MakeRequest(&url_loader_factory_), 0 /* process_id */);
   }
 
   return url_loader_factory_.get();
diff --git a/ios/web/public/BUILD.gn b/ios/web/public/BUILD.gn
index 029ff046..fd75ade 100644
--- a/ios/web/public/BUILD.gn
+++ b/ios/web/public/BUILD.gn
@@ -8,6 +8,8 @@
   public_deps = [
     ":user_agent",
     "//net",
+    "//services/network/public/cpp",
+    "//services/network/public/mojom",
   ]
 
   deps = [
diff --git a/ios/web/public/DEPS b/ios/web/public/DEPS
index 057fdd9..eb1339a 100644
--- a/ios/web/public/DEPS
+++ b/ios/web/public/DEPS
@@ -2,6 +2,7 @@
   # web interfaces cannot depend on private web code.
   "-ios/web",
   "+ios/web/public",
+  "+services/network/public/mojom",
   "+services/service_manager/embedder/runner",
 ]
 
diff --git a/ios/web/public/browser_state.h b/ios/web/public/browser_state.h
index 705c183..1fae818 100644
--- a/ios/web/public/browser_state.h
+++ b/ios/web/public/browser_state.h
@@ -8,6 +8,8 @@
 #include <memory>
 
 #include "base/supports_user_data.h"
+#include "services/network/public/mojom/network_service.mojom.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
 #include "services/service_manager/embedder/embedded_service_info.h"
 
 namespace base {
@@ -98,7 +100,7 @@
                          const base::FilePath& path);
 
  private:
-  class URLLoaderFactory;
+  class NetworkContextOwner;
   friend class URLDataManagerIOS;
   friend class URLRequestChromeJob;
 
@@ -108,7 +110,12 @@
   // Not intended for usage outside of //web.
   URLDataManagerIOSBackend* GetURLDataManagerIOSBackendOnIOThread();
 
-  std::unique_ptr<URLLoaderFactory> url_loader_factory_;
+  network::mojom::URLLoaderFactoryPtr url_loader_factory_;
+  network::mojom::NetworkContextPtr network_context_;
+
+  // Owns the network::NetworkContext that backs |url_loader_factory_|. Created
+  // on the UI thread, destroyed on the IO thread.
+  std::unique_ptr<NetworkContextOwner> network_context_owner_;
 
   // The URLDataManagerIOSBackend instance associated with this BrowserState.
   // Created and destroyed on the IO thread, and should be accessed only from
diff --git a/ios/web/shell/shell_url_request_context_getter.mm b/ios/web/shell/shell_url_request_context_getter.mm
index d8cdd89..745a005 100644
--- a/ios/web/shell/shell_url_request_context_getter.mm
+++ b/ios/web/shell/shell_url_request_context_getter.mm
@@ -30,7 +30,7 @@
 #include "net/http/transport_security_state.h"
 #include "net/log/net_log.h"
 #include "net/proxy_resolution/proxy_config_service_ios.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/ssl/channel_id_service.h"
 #include "net/ssl/default_channel_id_store.h"
 #include "net/ssl/ssl_config_service_defaults.h"
diff --git a/ios/web/web_state/ui/wk_web_view_configuration_provider.h b/ios/web/web_state/ui/wk_web_view_configuration_provider.h
index 810d4659..664acc9 100644
--- a/ios/web/web_state/ui/wk_web_view_configuration_provider.h
+++ b/ios/web/web_state/ui/wk_web_view_configuration_provider.h
@@ -28,9 +28,10 @@
   static web::WKWebViewConfigurationProvider& FromBrowserState(
       web::BrowserState* browser_state);
 
-  // Returns an autoreleased copy of WKWebViewConfiguration associated with
-  // browser state. Lazily creates the config. Configuration's |preferences|
-  // will have scriptCanOpenWindowsAutomatically property set to YES.
+  // Returns an autoreleased shallow copy of WKWebViewConfiguration associated
+  // with browser state. Lazily creates the config. Configuration's
+  // |preferences| will have scriptCanOpenWindowsAutomatically property set to
+  // YES.
   // Must be used instead of [[WKWebViewConfiguration alloc] init].
   // Callers must not retain the returned object.
   WKWebViewConfiguration* GetWebViewConfiguration();
diff --git a/ios/web/web_state/ui/wk_web_view_configuration_provider.mm b/ios/web/web_state/ui/wk_web_view_configuration_provider.mm
index 67b5071..18a5f1e 100644
--- a/ios/web/web_state/ui/wk_web_view_configuration_provider.mm
+++ b/ios/web/web_state/ui/wk_web_view_configuration_provider.mm
@@ -101,7 +101,8 @@
     [[configuration_ userContentController]
         addUserScript:InternalGetDocumentEndScriptForAllFrames(browser_state_)];
   }
-  // Prevent callers from changing the internals of configuration.
+  // This is a shallow copy to prevent callers from changing the internals of
+  // configuration.
   return [configuration_ copy];
 }
 
diff --git a/ios/web_view/internal/web_view_url_request_context_getter.mm b/ios/web_view/internal/web_view_url_request_context_getter.mm
index a1b2f06c..b9c6999 100644
--- a/ios/web_view/internal/web_view_url_request_context_getter.mm
+++ b/ios/web_view/internal/web_view_url_request_context_getter.mm
@@ -29,7 +29,7 @@
 #include "net/http/transport_security_state.h"
 #include "net/log/net_log.h"
 #include "net/proxy_resolution/proxy_config_service_ios.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/ssl/channel_id_service.h"
 #include "net/ssl/default_channel_id_store.h"
 #include "net/ssl/ssl_config_service_defaults.h"
diff --git a/mash/BUILD.gn b/mash/BUILD.gn
index a3969619..6784a46 100644
--- a/mash/BUILD.gn
+++ b/mash/BUILD.gn
@@ -64,7 +64,7 @@
   }
 
   if (is_linux && !is_android) {
-    standalone_services += [ "//components/font_service:manifest" ]
+    standalone_services += [ "//components/services/font:manifest" ]
   }
 
   if (enable_nacl) {
diff --git a/media/audio/android/audio_track_output_stream.cc b/media/audio/android/audio_track_output_stream.cc
index 07f5cd5..c3773ae 100644
--- a/media/audio/android/audio_track_output_stream.cc
+++ b/media/audio/android/audio_track_output_stream.cc
@@ -33,7 +33,7 @@
                                                const AudioParameters& params)
     : params_(params),
       audio_manager_(manager),
-      tick_clock_(new base::DefaultTickClock()) {
+      tick_clock_(base::DefaultTickClock::GetInstance()) {
   if (!params_.IsBitstreamFormat()) {
     audio_bus_ = AudioBus::Create(params_);
   }
diff --git a/media/audio/android/audio_track_output_stream.h b/media/audio/android/audio_track_output_stream.h
index 1b01a687..926f7d1 100644
--- a/media/audio/android/audio_track_output_stream.h
+++ b/media/audio/android/audio_track_output_stream.h
@@ -54,7 +54,7 @@
   // Extra buffer for PCM format.
   std::unique_ptr<AudioBus> audio_bus_;
 
-  std::unique_ptr<base::TickClock> tick_clock_;
+  base::TickClock* tick_clock_;
 
   // Java AudioTrackOutputStream instance.
   base::android::ScopedJavaGlobalRef<jobject> j_audio_output_stream_;
diff --git a/media/audio/win/audio_device_listener_win.cc b/media/audio/win/audio_device_listener_win.cc
index 5d8316e5..e39eb06 100644
--- a/media/audio/win/audio_device_listener_win.cc
+++ b/media/audio/win/audio_device_listener_win.cc
@@ -32,7 +32,8 @@
 }
 
 AudioDeviceListenerWin::AudioDeviceListenerWin(const base::Closure& listener_cb)
-    : listener_cb_(listener_cb), tick_clock_(new base::DefaultTickClock()) {
+    : listener_cb_(listener_cb),
+      tick_clock_(base::DefaultTickClock::GetInstance()) {
   // CreateDeviceEnumerator can fail on some installations of Windows such
   // as "Windows Server 2008 R2" where the desktop experience isn't available.
   Microsoft::WRL::ComPtr<IMMDeviceEnumerator> device_enumerator(
diff --git a/media/audio/win/audio_device_listener_win.h b/media/audio/win/audio_device_listener_win.h
index 8a864c87..e82162e 100644
--- a/media/audio/win/audio_device_listener_win.h
+++ b/media/audio/win/audio_device_listener_win.h
@@ -65,7 +65,7 @@
   // AudioDeviceListenerWin must be constructed and destructed on one thread.
   base::ThreadChecker thread_checker_;
 
-  std::unique_ptr<base::TickClock> tick_clock_;
+  base::TickClock* tick_clock_;
 
   DISALLOW_COPY_AND_ASSIGN(AudioDeviceListenerWin);
 };
diff --git a/media/audio/win/audio_device_listener_win_unittest.cc b/media/audio/win/audio_device_listener_win_unittest.cc
index 690bcd1a..e4749264b 100644
--- a/media/audio/win/audio_device_listener_win_unittest.cc
+++ b/media/audio/win/audio_device_listener_win_unittest.cc
@@ -39,13 +39,12 @@
     output_device_listener_.reset(new AudioDeviceListenerWin(base::Bind(
         &AudioDeviceListenerWinTest::OnDeviceChange, base::Unretained(this))));
 
-    tick_clock_ = new base::SimpleTestTickClock();
-    tick_clock_->Advance(base::TimeDelta::FromSeconds(12345));
-    output_device_listener_->tick_clock_.reset(tick_clock_);
+    tick_clock_.Advance(base::TimeDelta::FromSeconds(12345));
+    output_device_listener_->tick_clock_ = &tick_clock_;
   }
 
   void AdvanceLastDeviceChangeTime() {
-    tick_clock_->Advance(base::TimeDelta::FromMilliseconds(
+    tick_clock_.Advance(base::TimeDelta::FromMilliseconds(
         AudioDeviceListenerWin::kDeviceChangeLimitMs + 1));
   }
 
@@ -68,7 +67,7 @@
  private:
   ScopedCOMInitializer com_init_;
   std::unique_ptr<AudioDeviceListenerWin> output_device_listener_;
-  base::SimpleTestTickClock* tick_clock_;
+  base::SimpleTestTickClock tick_clock_;
 
   DISALLOW_COPY_AND_ASSIGN(AudioDeviceListenerWinTest);
 };
diff --git a/media/base/android/media_service_throttler.cc b/media/base/android/media_service_throttler.cc
index 911c05f..74817eb 100644
--- a/media/base/android/media_service_throttler.cc
+++ b/media/base/android/media_service_throttler.cc
@@ -84,7 +84,7 @@
 MediaServiceThrottler::~MediaServiceThrottler() {}
 
 MediaServiceThrottler::MediaServiceThrottler()
-    : clock_(new base::DefaultTickClock()),
+    : clock_(base::DefaultTickClock::GetInstance()),
       current_crashes_(0),
       crash_listener_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
   // base::Unretained is safe because the MediaServiceThrottler is supposed to
@@ -95,7 +95,7 @@
 }
 
 void MediaServiceThrottler::SetTickClockForTesting(base::TickClock* clock) {
-  clock_.reset(clock);
+  clock_ = clock;
 }
 
 base::TimeDelta MediaServiceThrottler::GetBaseThrottlingRateForTesting() {
diff --git a/media/base/android/media_service_throttler.h b/media/base/android/media_service_throttler.h
index a6866bc..ed42b8e 100644
--- a/media/base/android/media_service_throttler.h
+++ b/media/base/android/media_service_throttler.h
@@ -79,7 +79,7 @@
   // based on |current_crashes_|.
   base::TimeDelta GetThrottlingDelayFromServerCrashes();
 
-  std::unique_ptr<base::TickClock> clock_;
+  base::TickClock* clock_;
 
   // Effective number of media server crashes.
   // NOTE: This is of type double because we decay the number of crashes at a
diff --git a/media/base/android/media_service_throttler_unittest.cc b/media/base/android/media_service_throttler_unittest.cc
index d091776..e86e7739 100644
--- a/media/base/android/media_service_throttler_unittest.cc
+++ b/media/base/android/media_service_throttler_unittest.cc
@@ -18,12 +18,12 @@
 
 class MediaServiceThrottlerTest : public testing::Test {
  public:
-  MediaServiceThrottlerTest() : clock_(new base::SimpleTestTickClock()) {
+  MediaServiceThrottlerTest() {
     throttler_ = MediaServiceThrottler::GetInstance();
-    clock_->SetNowTicks(base::TimeTicks());
-    throttler_->SetTickClockForTesting(clock_);
+    clock_.SetNowTicks(base::TimeTicks());
+    throttler_->SetTickClockForTesting(&clock_);
     test_task_runner_ =
-        base::MakeRefCounted<FakeSingleThreadTaskRunner>(clock_);
+        base::MakeRefCounted<FakeSingleThreadTaskRunner>(&clock_);
     throttler_->ResetInternalStateForTesting();
     throttler_->SetCrashListenerTaskRunnerForTesting(test_task_runner_);
     base_delay_ = throttler_->GetBaseThrottlingRateForTesting();
@@ -50,10 +50,10 @@
              throttler_->GetDelayForClientCreation());
   }
 
-  base::TimeTicks TestNow() { return clock_->NowTicks(); }
+  base::TimeTicks TestNow() { return clock_.NowTicks(); }
 
   MediaServiceThrottler* throttler_;
-  base::SimpleTestTickClock* clock_;
+  base::SimpleTestTickClock clock_;
 
   base::TimeDelta base_delay_;
 
@@ -114,7 +114,7 @@
   // Schedule some clients below the burst threshold.
   SimulateClientCreations(7);
 
-  clock_->Advance(base_delay_ * 5);
+  clock_.Advance(base_delay_ * 5);
 
   // Make sure the passage of allows for more clients to be scheduled, since
   // 7 + 8 > kMaxBurstClients.
@@ -129,7 +129,7 @@
   SimulateClientCreations(3 * kMaxBurstClients);
 
   // Advance the time so there are still 2 * kMaxBurstClients pending clients.
-  clock_->Advance(base_delay_ * kMaxBurstClients);
+  clock_.Advance(base_delay_ * kMaxBurstClients);
 
   // Make sure delay we do not burst schedule new clients.
   EXPECT_NE(base::TimeDelta(), throttler_->GetDelayForClientCreation());
@@ -142,7 +142,7 @@
   SimulateClientCreations(base::TimeDelta::FromMinutes(2) / base_delay_);
 
   // Advance the time so the scheduler perceived a full minute of inactivity.
-  clock_->Advance(base::TimeDelta::FromSeconds(61));
+  clock_.Advance(base::TimeDelta::FromSeconds(61));
 
   // Make sure new clients are burst scheduled.
   EXPECT_EQ(base::TimeDelta(), throttler_->GetDelayForClientCreation());
@@ -170,7 +170,7 @@
   SimulateClientCreations(kMaxBurstClients);
 
   SimulateCrashes(1);
-  clock_->Advance(base::TimeDelta::FromMilliseconds(1));
+  clock_.Advance(base::TimeDelta::FromMilliseconds(1));
 
   // Because we use the floor function when calculating crashes, a small time
   // advance should nullify a single crash.
@@ -183,7 +183,7 @@
   SimulateClientCreations(kMaxBurstClients);
 
   SimulateCrashes(2);
-  clock_->Advance(base::TimeDelta::FromMilliseconds(1));
+  clock_.Advance(base::TimeDelta::FromMilliseconds(1));
 
   // The delay after crashes should be greater than the base delay.
   EXPECT_LT(base_delay_, GetCurrentDelayBetweenClients());
@@ -236,7 +236,7 @@
 
   // The effective server crash count should be reset because it has been over
   // a minute since the last crash.
-  clock_->Advance(base::TimeDelta::FromSeconds(61));
+  clock_.Advance(base::TimeDelta::FromSeconds(61));
 
   SimulateClientCreations(kMaxBurstClients);
 
@@ -248,9 +248,9 @@
   SimulateCrashes(9);
 
   // The effective server crash count should not be reset.
-  clock_->Advance(base::TimeDelta::FromSeconds(59));
+  clock_.Advance(base::TimeDelta::FromSeconds(59));
   SimulateCrashes(1);
-  clock_->Advance(base::TimeDelta::FromSeconds(2));
+  clock_.Advance(base::TimeDelta::FromSeconds(2));
 
   SimulateClientCreations(kMaxBurstClients);
 
@@ -266,7 +266,7 @@
   SimulateClientCreations(base::TimeDelta::FromMinutes(3) / base_delay_);
 
   // The MediaServerCrashListener should be alive, with 1s second to spare.
-  clock_->Advance(base::TimeDelta::FromSeconds(59));
+  clock_.Advance(base::TimeDelta::FromSeconds(59));
   test_task_runner_->RunTasks();
   EXPECT_TRUE(throttler_->IsCrashListenerAliveForTesting());
 
@@ -275,12 +275,12 @@
   throttler_->GetDelayForClientCreation();
 
   // The MediaServerCrashListener should be alive, with 58s second to spare.
-  clock_->Advance(base::TimeDelta::FromSeconds(2));
+  clock_.Advance(base::TimeDelta::FromSeconds(2));
   test_task_runner_->RunTasks();
   EXPECT_TRUE(throttler_->IsCrashListenerAliveForTesting());
 
   // The MediaServerCrashListener should be dead.
-  clock_->Advance(base::TimeDelta::FromSeconds(59));
+  clock_.Advance(base::TimeDelta::FromSeconds(59));
   test_task_runner_->RunTasks();
   EXPECT_FALSE(throttler_->IsCrashListenerAliveForTesting());
 }
@@ -295,7 +295,7 @@
   SimulateClientCreations(base::TimeDelta::FromMinutes(3) / base_delay_);
 
   // The MediaServerCrashListener should be alive, with 1s second to spare.
-  clock_->Advance(base::TimeDelta::FromSeconds(59));
+  clock_.Advance(base::TimeDelta::FromSeconds(59));
   test_task_runner_->RunTasks();
   EXPECT_TRUE(throttler_->IsCrashListenerAliveForTesting());
 
@@ -303,7 +303,7 @@
   SimulateCrashes(1);
 
   // The MediaServerCrashListener should be dead.
-  clock_->Advance(base::TimeDelta::FromSeconds(2));
+  clock_.Advance(base::TimeDelta::FromSeconds(2));
   test_task_runner_->RunTasks();
   EXPECT_FALSE(throttler_->IsCrashListenerAliveForTesting());
 }
diff --git a/media/filters/jpeg_parser.h b/media/filters/jpeg_parser.h
index 3cc01e5c..9f77db1 100644
--- a/media/filters/jpeg_parser.h
+++ b/media/filters/jpeg_parser.h
@@ -44,7 +44,8 @@
   JPEG_SOS = 0xDA,    // start of scan
   JPEG_DQT = 0xDB,    // define quantization table
   JPEG_DRI = 0xDD,    // define restart internal
-  JPEG_APP0 = 0xE0,   // start of application segment
+  JPEG_APP0 = 0xE0,   // start of application segment (APP0)
+  JPEG_APP1 = 0xE1,   // start of application segment (APP1)
   JPEG_MARKER_PREFIX = 0xFF,  // jpeg marker prefix
 };
 
diff --git a/media/gpu/android/android_video_surface_chooser_impl.cc b/media/gpu/android/android_video_surface_chooser_impl.cc
index 2ff375a..120f5c7 100644
--- a/media/gpu/android/android_video_surface_chooser_impl.cc
+++ b/media/gpu/android/android_video_surface_chooser_impl.cc
@@ -22,10 +22,8 @@
       tick_clock_(tick_clock),
       weak_factory_(this) {
   // Use a DefaultTickClock if one wasn't provided.
-  if (!tick_clock_) {
-    optional_tick_clock_ = std::make_unique<base::DefaultTickClock>();
-    tick_clock_ = optional_tick_clock_.get();
-  }
+  if (!tick_clock_)
+    tick_clock_ = base::DefaultTickClock::GetInstance();
 }
 
 AndroidVideoSurfaceChooserImpl::~AndroidVideoSurfaceChooserImpl() {}
diff --git a/media/gpu/android/android_video_surface_chooser_impl.h b/media/gpu/android/android_video_surface_chooser_impl.h
index fedc2dfb..1f19a37b 100644
--- a/media/gpu/android/android_video_surface_chooser_impl.h
+++ b/media/gpu/android/android_video_surface_chooser_impl.h
@@ -86,9 +86,6 @@
   // Not owned by us.
   base::TickClock* tick_clock_;
 
-  // Owned copy of |tick_clock_|, or nullptr if one was provided to us.
-  std::unique_ptr<base::TickClock> optional_tick_clock_;
-
   // Time at which we most recently got a failed overlay request.
   base::TimeTicks most_recent_overlay_failure_;
 
diff --git a/media/gpu/android/avda_codec_allocator.cc b/media/gpu/android/avda_codec_allocator.cc
index 4af7a39..a5f728c 100644
--- a/media/gpu/android/avda_codec_allocator.cc
+++ b/media/gpu/android/avda_codec_allocator.cc
@@ -455,7 +455,7 @@
       factory_cb_(std::move(factory_cb)),
       weak_this_factory_(this) {
   // We leak the clock we create, but that's okay because we're a singleton.
-  auto* clock = tick_clock ? tick_clock : new base::DefaultTickClock();
+  auto* clock = tick_clock ? tick_clock : base::DefaultTickClock::GetInstance();
 
   // Create threads with names and indices that match up with TaskType.
   threads_.push_back(new ThreadAndHangDetector("AVDAAutoThread", clock));
diff --git a/media/gpu/android/promotion_hint_aggregator_impl.cc b/media/gpu/android/promotion_hint_aggregator_impl.cc
index d36a5aa..c2dc6d3 100644
--- a/media/gpu/android/promotion_hint_aggregator_impl.cc
+++ b/media/gpu/android/promotion_hint_aggregator_impl.cc
@@ -30,11 +30,8 @@
 PromotionHintAggregatorImpl::PromotionHintAggregatorImpl(
     base::TickClock* tick_clock)
     : weak_ptr_factory_(this) {
-  if (!tick_clock) {
-    clock_we_own_ = std::make_unique<base::DefaultTickClock>();
-    tick_clock = clock_we_own_.get();
-  }
-
+  if (!tick_clock)
+    tick_clock = base::DefaultTickClock::GetInstance();
   tick_clock_ = tick_clock;
 }
 
diff --git a/media/gpu/android/promotion_hint_aggregator_impl.h b/media/gpu/android/promotion_hint_aggregator_impl.h
index 94ba04f..ac2e000 100644
--- a/media/gpu/android/promotion_hint_aggregator_impl.h
+++ b/media/gpu/android/promotion_hint_aggregator_impl.h
@@ -32,9 +32,6 @@
   // Clock, which we might not own, that we'll use.
   base::TickClock* tick_clock_;
 
-  // Will be non-null if we allocate our own clock.  Use |tick_clock| instead.
-  std::unique_ptr<base::TickClock> clock_we_own_;
-
   // When did we receive the most recent "not promotable" frame?
   base::TimeTicks most_recent_unpromotable_;
 
diff --git a/media/gpu/android/surface_chooser_helper.cc b/media/gpu/android/surface_chooser_helper.cc
index 50211a9a..c186475 100644
--- a/media/gpu/android/surface_chooser_helper.cc
+++ b/media/gpu/android/surface_chooser_helper.cc
@@ -34,15 +34,15 @@
     bool is_overlay_required,
     bool promote_aggressively,
     std::unique_ptr<PromotionHintAggregator> promotion_hint_aggregator,
-    std::unique_ptr<base::TickClock> tick_clock)
+    base::TickClock* tick_clock)
     : surface_chooser_(std::move(surface_chooser)),
       is_overlay_required_(is_overlay_required),
       promotion_hint_aggregator_(
           promotion_hint_aggregator
               ? std::move(promotion_hint_aggregator)
               : std::make_unique<PromotionHintAggregatorImpl>()),
-      tick_clock_(tick_clock ? std::move(tick_clock)
-                             : std::make_unique<base::DefaultTickClock>()) {
+      tick_clock_(tick_clock ? tick_clock
+                             : base::DefaultTickClock::GetInstance()) {
   surface_chooser_state_.is_required = is_overlay_required_;
   surface_chooser_state_.promote_aggressively = promote_aggressively;
 }
diff --git a/media/gpu/android/surface_chooser_helper.h b/media/gpu/android/surface_chooser_helper.h
index 148df6e7..b755750 100644
--- a/media/gpu/android/surface_chooser_helper.h
+++ b/media/gpu/android/surface_chooser_helper.h
@@ -34,7 +34,7 @@
       bool promote_aggressively,
       std::unique_ptr<PromotionHintAggregator> promotion_hint_aggregator =
           nullptr,
-      std::unique_ptr<base::TickClock> tick_clock = nullptr);
+      base::TickClock* tick_clock = nullptr);
   ~SurfaceChooserHelper();
 
   enum class SecureSurfaceMode {
@@ -105,7 +105,7 @@
   // Time since we last updated the chooser state.
   base::TimeTicks most_recent_chooser_retry_;
 
-  std::unique_ptr<base::TickClock> tick_clock_;
+  base::TickClock* tick_clock_;
 
   // Number of promotion hints that we need to receive before clearing the
   // "delay overlay promotion" flag in |surface_chooser_state_|.  We do this so
diff --git a/media/gpu/android/surface_chooser_helper_unittest.cc b/media/gpu/android/surface_chooser_helper_unittest.cc
index e88e86c..e1d7c92 100644
--- a/media/gpu/android/surface_chooser_helper_unittest.cc
+++ b/media/gpu/android/surface_chooser_helper_unittest.cc
@@ -35,10 +35,7 @@
 
   void ReplaceHelper(bool is_overlay_required, bool promote_aggressively) {
     // Advance the clock so that time 0 isn't recent.
-    std::unique_ptr<base::SimpleTestTickClock> tick_clock =
-        std::make_unique<base::SimpleTestTickClock>();
-    tick_clock_ = tick_clock.get();
-    tick_clock_->Advance(TimeDelta::FromSeconds(10000));
+    tick_clock_.Advance(TimeDelta::FromSeconds(10000));
 
     std::unique_ptr<MockAndroidVideoSurfaceChooser> chooser =
         std::make_unique<MockAndroidVideoSurfaceChooser>();
@@ -48,7 +45,7 @@
     aggregator_ = aggregator.get();
     helper_ = std::make_unique<SurfaceChooserHelper>(
         std::move(chooser), is_overlay_required, promote_aggressively,
-        std::move(aggregator), std::move(tick_clock));
+        std::move(aggregator), &tick_clock_);
   }
 
   // Convenience function.
@@ -57,7 +54,7 @@
     helper_->UpdateChooserState(base::Optional<AndroidOverlayFactoryCB>());
   }
 
-  base::SimpleTestTickClock* tick_clock_ = nullptr;
+  base::SimpleTestTickClock tick_clock_;
 
   MockPromotionHintAggregator* aggregator_ = nullptr;
 
@@ -217,7 +214,7 @@
   helper_->NotifyPromotionHintAndUpdateChooser(hint, false);
 
   // Advancing the time and using an overlay should not send a hint.
-  tick_clock_->Advance(base::TimeDelta::FromSeconds(10));
+  tick_clock_.Advance(base::TimeDelta::FromSeconds(10));
   EXPECT_CALL(*chooser_, MockUpdateState()).Times(0);
   helper_->NotifyPromotionHintAndUpdateChooser(hint, true);
 
diff --git a/media/gpu/jpeg_encode_accelerator_unittest.cc b/media/gpu/jpeg_encode_accelerator_unittest.cc
index 04b86ade..b58ee8a7 100644
--- a/media/gpu/jpeg_encode_accelerator_unittest.cc
+++ b/media/gpu/jpeg_encode_accelerator_unittest.cc
@@ -254,9 +254,8 @@
   void StartEncode(int32_t bitstream_buffer_id);
 
   // JpegEncodeAccelerator::Client implementation.
-  void VideoFrameReady(int video_frame_id,
-                       size_t encoded_picture_size) override;
-  void NotifyError(int video_frame_id,
+  void VideoFrameReady(int32_t buffer_id, size_t encoded_picture_size) override;
+  void NotifyError(int32_t buffer_id,
                    JpegEncodeAccelerator::Status status) override;
 
  private:
@@ -283,10 +282,8 @@
   // JpegClient doesn't own |test_image_files_|.
   const std::vector<TestImageFile*>& test_image_files_;
 
-  // A map that stores HW encoding start timestamp for each video frame id.
-  std::map<int, base::TimeTicks> video_frame_id_to_start_time_;
-
-  std::map<int, TestImageFile*> video_frame_id_to_image_;
+  // A map that stores HW encoding start timestamp for each output buffer id.
+  std::map<int, base::TimeTicks> buffer_id_to_start_time_;
 
   std::unique_ptr<JpegEncodeAccelerator> encoder_;
   ClientState state_;
@@ -311,7 +308,6 @@
 JpegClient::JpegClient(const std::vector<TestImageFile*>& test_image_files,
                        ClientStateNotification<ClientState>* note)
     : test_image_files_(test_image_files),
-      video_frame_id_to_image_(),
       state_(ClientState::CREATED),
       note_(note) {}
 
@@ -344,12 +340,12 @@
   encoder_.reset();
 }
 
-void JpegClient::VideoFrameReady(int video_frame_id, size_t hw_encoded_size) {
+void JpegClient::VideoFrameReady(int32_t buffer_id, size_t hw_encoded_size) {
   base::TimeTicks hw_encode_end = base::TimeTicks::Now();
   base::TimeDelta elapsed_hw =
-      hw_encode_end - video_frame_id_to_start_time_[video_frame_id];
+      hw_encode_end - buffer_id_to_start_time_[buffer_id];
 
-  TestImageFile* test_image = video_frame_id_to_image_[video_frame_id];
+  TestImageFile* test_image = test_image_files_[buffer_id];
   size_t sw_encoded_size = 0;
   base::TimeDelta elapsed_sw;
   LOG_ASSERT(GetSoftwareEncodeResult(test_image->visible_size.width(),
@@ -457,10 +453,10 @@
   return total_difference / yuv_size;
 }
 
-void JpegClient::NotifyError(int video_frame_id,
+void JpegClient::NotifyError(int32_t buffer_id,
                              JpegEncodeAccelerator::Status status) {
-  LOG(ERROR) << "Notifying of error " << status << " for video frame id "
-             << video_frame_id;
+  LOG(ERROR) << "Notifying of error " << status << " for output buffer id "
+             << buffer_id;
   SetState(ClientState::ERROR);
   encoded_buffer_.reset(nullptr);
 }
@@ -537,10 +533,9 @@
 
   LOG_ASSERT(input_frame_.get());
 
-  video_frame_id_to_image_[input_frame_->unique_id()] = image_file;
-  video_frame_id_to_start_time_[input_frame_->unique_id()] =
-      base::TimeTicks::Now();
-  encoder_->Encode(input_frame_, kJpegDefaultQuality, *encoded_buffer_);
+  buffer_id_to_start_time_[bitstream_buffer_id] = base::TimeTicks::Now();
+  encoder_->Encode(input_frame_, kJpegDefaultQuality, nullptr,
+                   *encoded_buffer_);
 }
 
 class JpegEncodeAcceleratorTest : public ::testing::Test {
diff --git a/media/gpu/vaapi/vaapi_jpeg_encode_accelerator.cc b/media/gpu/vaapi/vaapi_jpeg_encode_accelerator.cc
index 220620d..430331f 100644
--- a/media/gpu/vaapi/vaapi_jpeg_encode_accelerator.cc
+++ b/media/gpu/vaapi/vaapi_jpeg_encode_accelerator.cc
@@ -27,6 +27,11 @@
 
 namespace {
 
+// JPEG format uses 2 bytes to denote the size of a segment, and the size
+// includes the 2 bytes used for specifying it. Therefore, maximum data size
+// allowed is: 65535 - 2 = 65533.
+const size_t kMaxExifSizeAllowed = 65533;
+
 // UMA results that the VaapiJpegEncodeAccelerator class reports.
 // These values are persisted to logs, and should therefore never be renumbered
 // nor reused.
@@ -43,11 +48,15 @@
 }  // namespace
 
 VaapiJpegEncodeAccelerator::EncodeRequest::EncodeRequest(
+    int32_t buffer_id,
     scoped_refptr<media::VideoFrame> video_frame,
-    std::unique_ptr<SharedMemoryRegion> shm,
+    std::unique_ptr<SharedMemoryRegion> exif_shm,
+    std::unique_ptr<SharedMemoryRegion> output_shm,
     int quality)
-    : video_frame(std::move(video_frame)),
-      shm(std::move(shm)),
+    : buffer_id(buffer_id),
+      video_frame(std::move(video_frame)),
+      exif_shm(std::move(exif_shm)),
+      output_shm(std::move(output_shm)),
       quality(quality) {}
 
 VaapiJpegEncodeAccelerator::EncodeRequest::~EncodeRequest() {}
@@ -55,8 +64,8 @@
 class VaapiJpegEncodeAccelerator::Encoder {
  public:
   Encoder(scoped_refptr<VaapiWrapper> vaapi_wrapper,
-          base::RepeatingCallback<void(int, size_t)> video_frame_ready_cb,
-          base::RepeatingCallback<void(int, Status)> notify_error_cb);
+          base::RepeatingCallback<void(int32_t, size_t)> video_frame_ready_cb,
+          base::RepeatingCallback<void(int32_t, Status)> notify_error_cb);
   ~Encoder();
 
   // Processes one encode |request|.
@@ -73,8 +82,8 @@
   std::unique_ptr<VaapiJpegEncoder> jpeg_encoder_;
   scoped_refptr<VaapiWrapper> vaapi_wrapper_;
 
-  base::RepeatingCallback<void(int, size_t)> video_frame_ready_cb_;
-  base::RepeatingCallback<void(int, Status)> notify_error_cb_;
+  base::RepeatingCallback<void(int32_t, size_t)> video_frame_ready_cb_;
+  base::RepeatingCallback<void(int32_t, Status)> notify_error_cb_;
 
   SEQUENCE_CHECKER(sequence_checker_);
 
@@ -83,8 +92,8 @@
 
 VaapiJpegEncodeAccelerator::Encoder::Encoder(
     scoped_refptr<VaapiWrapper> vaapi_wrapper,
-    base::RepeatingCallback<void(int, size_t)> video_frame_ready_cb,
-    base::RepeatingCallback<void(int, Status)> notify_error_cb)
+    base::RepeatingCallback<void(int32_t, size_t)> video_frame_ready_cb,
+    base::RepeatingCallback<void(int32_t, Status)> notify_error_cb)
     : cached_output_buffer_size_(0),
       jpeg_encoder_(new VaapiJpegEncoder(vaapi_wrapper)),
       vaapi_wrapper_(std::move(vaapi_wrapper)),
@@ -103,13 +112,13 @@
   TRACE_EVENT0("jpeg", "EncodeTask");
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  const int video_frame_id = request->video_frame->unique_id();
+  const int buffer_id = request->buffer_id;
   gfx::Size input_size = request->video_frame->coded_size();
   std::vector<VASurfaceID> va_surfaces;
   if (!vaapi_wrapper_->CreateSurfaces(VA_RT_FORMAT_YUV420, input_size, 1,
                                       &va_surfaces)) {
     VLOGF(1) << "Failed to create VA surface";
-    notify_error_cb_.Run(video_frame_id, PLATFORM_FAILURE);
+    notify_error_cb_.Run(buffer_id, PLATFORM_FAILURE);
     return;
   }
   VASurfaceID va_surface_id = va_surfaces[0];
@@ -117,7 +126,7 @@
   if (!vaapi_wrapper_->UploadVideoFrameToSurface(request->video_frame,
                                                  va_surface_id)) {
     VLOGF(1) << "Failed to upload video frame to VA surface";
-    notify_error_cb_.Run(video_frame_id, PLATFORM_FAILURE);
+    notify_error_cb_.Run(buffer_id, PLATFORM_FAILURE);
     return;
   }
 
@@ -132,17 +141,24 @@
     if (!vaapi_wrapper_->CreateCodedBuffer(max_coded_buffer_size,
                                            &output_buffer_id)) {
       VLOGF(1) << "Failed to create VA buffer for encoding output";
-      notify_error_cb_.Run(video_frame_id, PLATFORM_FAILURE);
+      notify_error_cb_.Run(buffer_id, PLATFORM_FAILURE);
       return;
     }
     cached_output_buffer_size_ = max_coded_buffer_size;
     cached_output_buffer_id_ = output_buffer_id;
   }
 
-  if (!jpeg_encoder_->Encode(input_size, request->quality, va_surface_id,
+  uint8_t* exif_buffer = nullptr;
+  size_t exif_buffer_size = 0;
+  if (request->exif_shm) {
+    exif_buffer = static_cast<uint8_t*>(request->exif_shm->memory());
+    exif_buffer_size = request->exif_shm->size();
+  }
+  if (!jpeg_encoder_->Encode(input_size, exif_buffer, exif_buffer_size,
+                             request->quality, va_surface_id,
                              cached_output_buffer_id_)) {
     VLOGF(1) << "Encode JPEG failed";
-    notify_error_cb_.Run(video_frame_id, PLATFORM_FAILURE);
+    notify_error_cb_.Run(buffer_id, PLATFORM_FAILURE);
     return;
   }
 
@@ -151,13 +167,13 @@
   size_t encoded_size = 0;
   if (!vaapi_wrapper_->DownloadFromCodedBuffer(
           cached_output_buffer_id_, va_surface_id,
-          static_cast<uint8_t*>(request->shm->memory()), request->shm->size(),
-          &encoded_size)) {
+          static_cast<uint8_t*>(request->output_shm->memory()),
+          request->output_shm->size(), &encoded_size)) {
     VLOGF(1) << "Failed to retrieve output image from VA coded buffer";
-    notify_error_cb_.Run(video_frame_id, PLATFORM_FAILURE);
+    notify_error_cb_.Run(buffer_id, PLATFORM_FAILURE);
   }
 
-  video_frame_ready_cb_.Run(request->video_frame->unique_id(), encoded_size);
+  video_frame_ready_cb_.Run(buffer_id, encoded_size);
 }
 
 VaapiJpegEncodeAccelerator::VaapiJpegEncodeAccelerator(
@@ -177,22 +193,21 @@
   encoder_task_runner_->DeleteSoon(FROM_HERE, std::move(encoder_));
 }
 
-void VaapiJpegEncodeAccelerator::NotifyError(int video_frame_id,
-                                             Status status) {
+void VaapiJpegEncodeAccelerator::NotifyError(int32_t buffer_id, Status status) {
   DCHECK(task_runner_->BelongsToCurrentThread());
-  VLOGF(1) << "video_frame_id=" << video_frame_id << ", status=" << status;
+  VLOGF(1) << "output_buffer_id=" << buffer_id << ", status=" << status;
   DCHECK(client_);
-  client_->NotifyError(video_frame_id, status);
+  client_->NotifyError(buffer_id, status);
 }
 
-void VaapiJpegEncodeAccelerator::VideoFrameReady(int video_frame_id,
+void VaapiJpegEncodeAccelerator::VideoFrameReady(int32_t buffer_id,
                                                  size_t encoded_picture_size) {
-  DVLOGF(4) << "video_frame_id=" << video_frame_id
+  DVLOGF(4) << "output_buffer_id=" << buffer_id
             << ", size=" << encoded_picture_size;
   DCHECK(task_runner_->BelongsToCurrentThread());
   ReportToUMA(VAJEAEncoderResult::VAAPI_SUCCESS);
 
-  client_->VideoFrameReady(video_frame_id, encoded_picture_size);
+  client_->VideoFrameReady(buffer_id, encoded_picture_size);
 }
 
 JpegEncodeAccelerator::Status VaapiJpegEncodeAccelerator::Initialize(
@@ -240,35 +255,58 @@
 void VaapiJpegEncodeAccelerator::Encode(
     scoped_refptr<media::VideoFrame> video_frame,
     int quality,
-    const BitstreamBuffer& bitstream_buffer) {
+    const BitstreamBuffer* exif_buffer,
+    const BitstreamBuffer& output_buffer) {
   DVLOGF(4);
   DCHECK(io_task_runner_->BelongsToCurrentThread());
 
-  int video_frame_id = video_frame->unique_id();
-  TRACE_EVENT1("jpeg", "Encode", "input_id", video_frame_id);
+  int32_t buffer_id = output_buffer.id();
+  TRACE_EVENT1("jpeg", "Encode", "output_buffer_id", buffer_id);
 
   // TODO(shenghao): support other YUV formats.
   if (video_frame->format() != VideoPixelFormat::PIXEL_FORMAT_I420) {
     VLOGF(1) << "Unsupported input format: " << video_frame->format();
     task_runner_->PostTask(
-        FROM_HERE, base::Bind(&VaapiJpegEncodeAccelerator::NotifyError,
-                              weak_this_, video_frame_id, INVALID_ARGUMENT));
+        FROM_HERE, base::BindOnce(&VaapiJpegEncodeAccelerator::NotifyError,
+                                  weak_this_, buffer_id, INVALID_ARGUMENT));
     return;
   }
 
-  // SharedMemoryRegion will take ownership of the |bitstream_buffer.handle()|.
-  auto shm = std::make_unique<SharedMemoryRegion>(bitstream_buffer, false);
-  if (!shm->Map()) {
+  std::unique_ptr<SharedMemoryRegion> exif_shm;
+  if (exif_buffer) {
+    // |exif_shm| will take ownership of the |exif_buffer->handle()|.
+    exif_shm = std::make_unique<SharedMemoryRegion>(*exif_buffer, true);
+    if (!exif_shm->Map()) {
+      VLOGF(1) << "Failed to map exif buffer";
+      task_runner_->PostTask(
+          FROM_HERE, base::BindOnce(&VaapiJpegEncodeAccelerator::NotifyError,
+                                    weak_this_, buffer_id, PLATFORM_FAILURE));
+      return;
+    }
+    if (exif_shm->size() > kMaxExifSizeAllowed) {
+      VLOGF(1) << "Exif buffer too big: " << exif_shm->size();
+      task_runner_->PostTask(
+          FROM_HERE, base::BindOnce(&VaapiJpegEncodeAccelerator::NotifyError,
+                                    weak_this_, buffer_id, INVALID_ARGUMENT));
+      return;
+    }
+  }
+
+  // |output_shm| will take ownership of the |output_buffer.handle()|.
+  auto output_shm = std::make_unique<SharedMemoryRegion>(output_buffer, false);
+  if (!output_shm->Map()) {
     VLOGF(1) << "Failed to map output buffer";
     task_runner_->PostTask(
         FROM_HERE,
         base::Bind(&VaapiJpegEncodeAccelerator::NotifyError, weak_this_,
-                   video_frame_id, INACCESSIBLE_OUTPUT_BUFFER));
+                   buffer_id, INACCESSIBLE_OUTPUT_BUFFER));
     return;
   }
 
-  auto request = std::make_unique<EncodeRequest>(std::move(video_frame),
-                                                 std::move(shm), quality);
+  auto request = std::make_unique<EncodeRequest>(
+      buffer_id, std::move(video_frame), std::move(exif_shm),
+      std::move(output_shm), quality);
+
   encoder_task_runner_->PostTask(
       FROM_HERE,
       base::Bind(&VaapiJpegEncodeAccelerator::Encoder::EncodeTask,
diff --git a/media/gpu/vaapi/vaapi_jpeg_encode_accelerator.h b/media/gpu/vaapi/vaapi_jpeg_encode_accelerator.h
index 4610bbf..c883b31 100644
--- a/media/gpu/vaapi/vaapi_jpeg_encode_accelerator.h
+++ b/media/gpu/vaapi/vaapi_jpeg_encode_accelerator.h
@@ -41,19 +41,24 @@
   // Currently only I420 format is supported for |video_frame|.
   void Encode(scoped_refptr<media::VideoFrame> video_frame,
               int quality,
-              const BitstreamBuffer& bitstream_buffer) override;
+              const BitstreamBuffer* exif_buffer,
+              const BitstreamBuffer& output_buffer) override;
 
  private:
   // An input video frame and the corresponding output buffer awaiting
   // consumption, provided by the client.
   struct EncodeRequest {
-    EncodeRequest(scoped_refptr<media::VideoFrame> video_frame,
-                  std::unique_ptr<SharedMemoryRegion> shm,
+    EncodeRequest(int32_t buffer_id,
+                  scoped_refptr<media::VideoFrame> video_frame,
+                  std::unique_ptr<SharedMemoryRegion> exif_shm,
+                  std::unique_ptr<SharedMemoryRegion> output_shm,
                   int quality);
     ~EncodeRequest();
 
+    int32_t buffer_id;
     scoped_refptr<media::VideoFrame> video_frame;
-    std::unique_ptr<SharedMemoryRegion> shm;
+    std::unique_ptr<SharedMemoryRegion> exif_shm;
+    std::unique_ptr<SharedMemoryRegion> output_shm;
     int quality;
 
     DISALLOW_COPY_AND_ASSIGN(EncodeRequest);
@@ -65,9 +70,9 @@
 
   // Notifies the client that an error has occurred and encoding cannot
   // continue.
-  void NotifyError(int video_frame_id, Status status);
+  void NotifyError(int32_t buffer_id, Status status);
 
-  void VideoFrameReady(int video_frame_id, size_t encoded_picture_size);
+  void VideoFrameReady(int32_t buffer_id, size_t encoded_picture_size);
 
   // ChildThread's task runner.
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
diff --git a/media/gpu/vaapi/vaapi_jpeg_encoder.cc b/media/gpu/vaapi/vaapi_jpeg_encoder.cc
index f6fe83f..538b873 100644
--- a/media/gpu/vaapi/vaapi_jpeg_encoder.cc
+++ b/media/gpu/vaapi/vaapi_jpeg_encoder.cc
@@ -32,10 +32,11 @@
 const size_t kNumAcRunSizeBits = 16;
 const size_t kNumDcCodeWordsHuffVal = 12;
 const size_t kNumAcCodeWordsHuffVal = 162;
-const size_t kJpegHeaderSize = 83 + (kDctSize2 * 2) + (kNumDcRunSizeBits * 2) +
-                               (kNumDcCodeWordsHuffVal * 2) +
-                               (kNumAcRunSizeBits * 2) +
-                               (kNumAcCodeWordsHuffVal * 2);
+const size_t kJpegDefaultHeaderSize =
+    67 + (kDctSize2 * 2) + (kNumDcRunSizeBits * 2) +
+    (kNumDcCodeWordsHuffVal * 2) + (kNumAcRunSizeBits * 2) +
+    (kNumAcCodeWordsHuffVal * 2);
+const size_t kJFIFApp0Size = 16;
 
 const uint8_t kZigZag8x8[64] = {
     0,  1,  8,  16, 9,  2,  3,  10, 17, 24, 32, 25, 18, 11, 4,  5,
@@ -62,8 +63,6 @@
     },
 };
 
-using JPEGHeader = uint8_t[kJpegHeaderSize];
-
 void FillPictureParameters(const gfx::Size& input_size,
                            int quality,
                            VABufferID output_buffer_id,
@@ -172,8 +171,10 @@
 }
 
 size_t FillJpegHeader(const gfx::Size& input_size,
+                      const uint8_t* exif_buffer,
+                      size_t exif_buffer_size,
                       int quality,
-                      JPEGHeader& header) {
+                      uint8_t* header) {
   unsigned int width = input_size.width();
   unsigned int height = input_size.height();
 
@@ -184,29 +185,40 @@
   memcpy(header, kSOI, sizeof(kSOI));
   idx += sizeof(kSOI);
 
-  // Application Segment - JFIF standard 1.01.
-  // TODO(shenghao): Use Exif (JPEG_APP1) instead.
-  static const uint8_t kAppSegment[] = {
-      0xFF, JPEG_APP0, 0x00,
-      0x10,  // Segment length:16 (2-byte).
-      0x4A,  // J
-      0x46,  // F
-      0x49,  // I
-      0x46,  // F
-      0x00,  // 0
-      0x01,  // Major version.
-      0x01,  // Minor version.
-      0x01,  // Density units 0:no units, 1:pixels per inch,
-             // 2: pixels per cm.
-      0x00,
-      0x48,  // X density (2-byte).
-      0x00,
-      0x48,  // Y density (2-byte).
-      0x00,  // Thumbnail width.
-      0x00   // Thumbnail height.
-  };
-  memcpy(header + idx, kAppSegment, sizeof(kAppSegment));
-  idx += sizeof(kAppSegment);
+  if (exif_buffer_size > 0) {
+    // Application Segment for Exif data.
+    uint16_t exif_segment_size = static_cast<uint16_t>(exif_buffer_size + 2);
+    const uint8_t kAppSegment[] = {
+        0xFF, JPEG_APP1, static_cast<uint8_t>(exif_segment_size / 256),
+        static_cast<uint8_t>(exif_segment_size % 256)};
+    memcpy(header + idx, kAppSegment, sizeof(kAppSegment));
+    idx += sizeof(kAppSegment);
+    memcpy(header + idx, exif_buffer, exif_buffer_size);
+    idx += exif_buffer_size;
+  } else {
+    // Application Segment - JFIF standard 1.01.
+    static const uint8_t kAppSegment[] = {
+        0xFF, JPEG_APP0, 0x00,
+        0x10,  // Segment length:16 (2-byte).
+        0x4A,  // J
+        0x46,  // F
+        0x49,  // I
+        0x46,  // F
+        0x00,  // 0
+        0x01,  // Major version.
+        0x01,  // Minor version.
+        0x01,  // Density units 0:no units, 1:pixels per inch,
+               // 2: pixels per cm.
+        0x00,
+        0x48,  // X density (2-byte).
+        0x00,
+        0x48,  // Y density (2-byte).
+        0x00,  // Thumbnail width.
+        0x00   // Thumbnail height.
+    };
+    memcpy(header + idx, kAppSegment, sizeof(kAppSegment));
+    idx += sizeof(kAppSegment);
+  }
 
   if (quality <= 0) {
     quality = 1;
@@ -349,10 +361,12 @@
 VaapiJpegEncoder::~VaapiJpegEncoder() {}
 
 size_t VaapiJpegEncoder::GetMaxCodedBufferSize(const gfx::Size& size) {
-  return size.GetArea() * 3 / 2 + kJpegHeaderSize;
+  return size.GetArea() * 3 / 2 + kJpegDefaultHeaderSize;
 }
 
 bool VaapiJpegEncoder::Encode(const gfx::Size& input_size,
+                              const uint8_t* exif_buffer,
+                              size_t exif_buffer_size,
                               int quality,
                               VASurfaceID surface_id,
                               VABufferID output_buffer_id) {
@@ -402,8 +416,13 @@
     return false;
   }
 
-  JPEGHeader header_data;
-  size_t length_in_bits = FillJpegHeader(input_size, quality, header_data);
+  std::vector<uint8_t> jpeg_header;
+  size_t jpeg_header_size = exif_buffer_size > 0
+                                ? kJpegDefaultHeaderSize + exif_buffer_size
+                                : kJpegDefaultHeaderSize + kJFIFApp0Size;
+  jpeg_header.resize(jpeg_header_size);
+  size_t length_in_bits = FillJpegHeader(
+      input_size, exif_buffer, exif_buffer_size, quality, jpeg_header.data());
 
   VAEncPackedHeaderParameterBuffer header_param;
   memset(&header_param, 0, sizeof(header_param));
@@ -416,7 +435,8 @@
   }
 
   if (!vaapi_wrapper_->SubmitBuffer(VAEncPackedHeaderDataBufferType,
-                                    (length_in_bits + 7) / 8, header_data)) {
+                                    (length_in_bits + 7) / 8,
+                                    jpeg_header.data())) {
     return false;
   }
 
diff --git a/media/gpu/vaapi/vaapi_jpeg_encoder.h b/media/gpu/vaapi/vaapi_jpeg_encoder.h
index bf3294f72..f3851695 100644
--- a/media/gpu/vaapi/vaapi_jpeg_encoder.h
+++ b/media/gpu/vaapi/vaapi_jpeg_encoder.h
@@ -32,6 +32,9 @@
 
   // Encode a JPEG picture. It will fill VA-API parameters and call
   // corresponding VA-API methods according to |input_size|.
+  // |exif_buffer| contains the EXIF data that will be inserted to the JPEG
+  // image.
+  // |exif_buffer_size| is the size of |exif_buffer|.
   // |quality| is the JPEG image quality
   // |surface_id| is the VA surface that contains input image.
   // |output_buffer_id| is the ID of VA buffer that encoded image will be
@@ -39,6 +42,8 @@
   // GetMaxCodedBufferSize().
   // Return false on failure.
   bool Encode(const gfx::Size& input_size,
+              const uint8_t* exif_buffer,
+              size_t exif_buffer_size,
               int quality,
               VASurfaceID surface_id,
               VABufferID output_buffer_id);
diff --git a/media/video/jpeg_encode_accelerator.h b/media/video/jpeg_encode_accelerator.h
index 7d7afda..313509c 100644
--- a/media/video/jpeg_encode_accelerator.h
+++ b/media/video/jpeg_encode_accelerator.h
@@ -48,11 +48,10 @@
    public:
     // Callback called after each successful Encode().
     // Parameters:
-    //  |video_frame_id| is |VideoFrame.unique_id()| of the input VideoFrame in
-    //  corresponding Encode() call.
+    //  |buffer_id| is |output_buffer.id()| of the corresponding Encode() call.
     //  |encoded_picture_size| is the actual size of encoded JPEG image in
     //  the BitstreamBuffer provided through encode().
-    virtual void VideoFrameReady(int video_frame_id,
+    virtual void VideoFrameReady(int32_t buffer_id,
                                  size_t encoded_picture_size) = 0;
 
     // Callback to notify errors. Client is responsible for destroying JEA when
@@ -60,10 +59,10 @@
     // is informed about the buffer that failed to encode and may continue
     // using the same instance of JEA.
     // Parameters:
-    //  |video_frame_id| is |video_frame_id.unique_id()| of the input VideoFrame
+    //  |buffer_id| is |output_buffer.id()| of the corresponding Encode() call
     //  that resulted in the error.
     //  |status| would be one of the values of Status except ENCODE_OK.
-    virtual void NotifyError(int video_frame_id, Status status) = 0;
+    virtual void NotifyError(int32_t buffer_id, Status status) = 0;
 
    protected:
     virtual ~Client() {}
@@ -88,18 +87,21 @@
 
   // Encodes the given |video_frame| that contains a YUV image. Client will
   // receive the encoded result in Client::VideoFrameReady() callback with the
-  // corresponding |unique_id_| in |video_frame|, or receive
+  // corresponding |output_buffer.id()|, or receive
   // Client::NotifyError() callback.
   // Parameters:
   //  |video_frame| contains the YUV image to be encoded.
   //  |quality| of JPEG image.
-  //  |bitstream_buffer| that contains output buffer for encoded result. Clients
+  //  |exif_buffer| contains Exif data to be inserted into JPEG image. If it's
+  //  nullptr, the JFIF APP0 segment will be inserted.
+  //  |output_buffer| that contains output buffer for encoded result. Clients
   //  should call GetMaxCodedBufferSize() and allocate the buffer accordingly.
   //  The buffer needs to be valid until VideoFrameReady() or NotifyError() is
   //  called.
   virtual void Encode(scoped_refptr<media::VideoFrame> video_frame,
                       int quality,
-                      const BitstreamBuffer& bitstream_buffer) = 0;
+                      const BitstreamBuffer* exif_buffer,
+                      const BitstreamBuffer& output_buffer) = 0;
 };
 
 }  // namespace media
diff --git a/mojo/edk/embedder/README.md b/mojo/edk/embedder/README.md
index b6e0a449..83ed35c 100644
--- a/mojo/edk/embedder/README.md
+++ b/mojo/edk/embedder/README.md
@@ -139,9 +139,9 @@
   base::ProcessHandle child_handle =
       LaunchCoolChildProcess(channel.PassClientHandle());
 
-  // At this point it's safe for |child| to go out of scope and nothing will
-  // break.
-  child.Connect(child_handle, channel.PassServerHandle());
+  // At this point it's safe for |invitation| to go out of scope and nothing
+  // will break.
+  invitation.Send(child_handle, channel.PassServerHandle());
 
   return 0;
 }
diff --git a/net/BUILD.gn b/net/BUILD.gn
index b7c1c98..c2d9a822 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1085,6 +1085,8 @@
       "proxy_resolution/proxy_info.h",
       "proxy_resolution/proxy_list.cc",
       "proxy_resolution/proxy_list.h",
+      "proxy_resolution/proxy_resolution_service.cc",
+      "proxy_resolution/proxy_resolution_service.h",
       "proxy_resolution/proxy_resolver.h",
       "proxy_resolution/proxy_resolver_error_observer.h",
       "proxy_resolution/proxy_resolver_factory.cc",
@@ -1094,8 +1096,6 @@
       "proxy_resolution/proxy_resolver_winhttp.cc",
       "proxy_resolution/proxy_resolver_winhttp.h",
       "proxy_resolution/proxy_retry_info.h",
-      "proxy_resolution/proxy_service.cc",
-      "proxy_resolution/proxy_service.h",
       "quic/chromium/bidirectional_stream_quic_impl.cc",
       "quic/chromium/bidirectional_stream_quic_impl.h",
       "quic/chromium/crypto/channel_id_chromium.cc",
@@ -5009,11 +5009,11 @@
     "proxy_resolution/proxy_config_unittest.cc",
     "proxy_resolution/proxy_info_unittest.cc",
     "proxy_resolution/proxy_list_unittest.cc",
+    "proxy_resolution/proxy_resolution_service_unittest.cc",
     "proxy_resolution/proxy_resolver_v8_tracing_unittest.cc",
     "proxy_resolution/proxy_resolver_v8_tracing_wrapper_unittest.cc",
     "proxy_resolution/proxy_resolver_v8_unittest.cc",
     "proxy_resolution/proxy_server_unittest.cc",
-    "proxy_resolution/proxy_service_unittest.cc",
     "quic/chromium/bidirectional_stream_quic_impl_unittest.cc",
     "quic/chromium/crypto/proof_test_chromium.cc",
     "quic/chromium/crypto/proof_verifier_chromium_test.cc",
diff --git a/net/base/mime_util.cc b/net/base/mime_util.cc
index d97f6cff..59cf91d 100644
--- a/net/base/mime_util.cc
+++ b/net/base/mime_util.cc
@@ -92,6 +92,7 @@
     {"image/gif", "gif"},
     {"image/jpeg", "jpeg,jpg"},
     {"image/png", "png"},
+    {"image/apng", "png"},
     {"image/webp", "webp"},
     {"multipart/related", "mht,mhtml"},
     {"text/css", "css"},
diff --git a/net/http/http_network_layer_unittest.cc b/net/http/http_network_layer_unittest.cc
index 818ed2a..c563937 100644
--- a/net/http/http_network_layer_unittest.cc
+++ b/net/http/http_network_layer_unittest.cc
@@ -16,7 +16,7 @@
 #include "net/http/http_transaction_test_util.h"
 #include "net/http/transport_security_state.h"
 #include "net/log/net_log_with_source.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/socket/socket_test_util.h"
 #include "net/spdy/chromium/spdy_session_pool.h"
 #include "net/ssl/ssl_config_service_defaults.h"
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index 4df631d4..d07f7352 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -25,7 +25,7 @@
 #include "net/http/http_response_body_drainer.h"
 #include "net/http/http_stream_factory_impl.h"
 #include "net/http/url_security_manager.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/quic/chromium/quic_crypto_client_stream_factory.h"
 #include "net/quic/chromium/quic_stream_factory.h"
 #include "net/quic/core/crypto/quic_random.h"
diff --git a/net/http/http_network_session_peer.cc b/net/http/http_network_session_peer.cc
index d132611b..e44be7fe 100644
--- a/net/http/http_network_session_peer.cc
+++ b/net/http/http_network_session_peer.cc
@@ -6,7 +6,7 @@
 
 #include "net/base/network_throttle_manager.h"
 #include "net/http/http_proxy_client_socket_pool.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/socket/client_socket_pool_manager.h"
 #include "net/socket/socks_client_socket_pool.h"
 #include "net/socket/ssl_client_socket_pool.h"
diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h
index 2fafc4b5..9ad57b9 100644
--- a/net/http/http_network_transaction.h
+++ b/net/http/http_network_transaction.h
@@ -25,7 +25,7 @@
 #include "net/http/http_stream_factory.h"
 #include "net/http/http_transaction.h"
 #include "net/log/net_log_with_source.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/socket/connection_attempts.h"
 #include "net/ssl/channel_id_service.h"
 #include "net/ssl/ssl_config_service.h"
diff --git a/net/http/http_network_transaction_ssl_unittest.cc b/net/http/http_network_transaction_ssl_unittest.cc
index e0657bc5..b2a63a4 100644
--- a/net/http/http_network_transaction_ssl_unittest.cc
+++ b/net/http/http_network_transaction_ssl_unittest.cc
@@ -23,7 +23,7 @@
 #include "net/http/http_server_properties_impl.h"
 #include "net/http/transport_security_state.h"
 #include "net/log/net_log_with_source.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/socket/socket_test_util.h"
 #include "net/ssl/default_channel_id_store.h"
 #include "net/test/gtest_util.h"
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 79ff5f4..6cc8169 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -72,9 +72,9 @@
 #include "net/proxy_resolution/mock_proxy_resolver.h"
 #include "net/proxy_resolution/proxy_config_service_fixed.h"
 #include "net/proxy_resolution/proxy_info.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/proxy_resolution/proxy_resolver.h"
 #include "net/proxy_resolution/proxy_resolver_factory.h"
-#include "net/proxy_resolution/proxy_service.h"
 #include "net/socket/client_socket_factory.h"
 #include "net/socket/client_socket_pool.h"
 #include "net/socket/client_socket_pool_manager.h"
diff --git a/net/http/http_response_body_drainer_unittest.cc b/net/http/http_response_body_drainer_unittest.cc
index 5ef18d73..ab7e7c50 100644
--- a/net/http/http_response_body_drainer_unittest.cc
+++ b/net/http/http_response_body_drainer_unittest.cc
@@ -28,7 +28,7 @@
 #include "net/http/http_server_properties_impl.h"
 #include "net/http/http_stream.h"
 #include "net/http/transport_security_state.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/ssl/ssl_config_service_defaults.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/net/http/http_stream_factory_impl_job.h b/net/http/http_stream_factory_impl_job.h
index 5600499..6c04cd6 100644
--- a/net/http/http_stream_factory_impl_job.h
+++ b/net/http/http_stream_factory_impl_job.h
@@ -22,7 +22,7 @@
 #include "net/http/http_request_info.h"
 #include "net/http/http_stream_factory_impl.h"
 #include "net/log/net_log_with_source.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/quic/chromium/quic_stream_factory.h"
 #include "net/socket/client_socket_handle.h"
 #include "net/socket/client_socket_pool_manager.h"
diff --git a/net/http/http_stream_factory_impl_job_controller_unittest.cc b/net/http/http_stream_factory_impl_job_controller_unittest.cc
index adc4da9..3465d3e 100644
--- a/net/http/http_stream_factory_impl_job_controller_unittest.cc
+++ b/net/http/http_stream_factory_impl_job_controller_unittest.cc
@@ -32,7 +32,7 @@
 #include "net/proxy_resolution/mock_proxy_resolver.h"
 #include "net/proxy_resolution/proxy_config_service_fixed.h"
 #include "net/proxy_resolution/proxy_info.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/quic/chromium/mock_crypto_client_stream_factory.h"
 #include "net/quic/chromium/mock_quic_data.h"
 #include "net/quic/chromium/quic_stream_factory.h"
diff --git a/net/http/http_stream_factory_impl_request_unittest.cc b/net/http/http_stream_factory_impl_request_unittest.cc
index 5cffaa6..6861019c 100644
--- a/net/http/http_stream_factory_impl_request_unittest.cc
+++ b/net/http/http_stream_factory_impl_request_unittest.cc
@@ -12,7 +12,7 @@
 #include "net/http/http_stream_factory_impl_job_controller.h"
 #include "net/http/http_stream_factory_test_util.h"
 #include "net/proxy_resolution/proxy_info.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/spdy/chromium/spdy_test_util_common.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/net/http/http_stream_factory_impl_unittest.cc b/net/http/http_stream_factory_impl_unittest.cc
index 8e0c9884..92075fc 100644
--- a/net/http/http_stream_factory_impl_unittest.cc
+++ b/net/http/http_stream_factory_impl_unittest.cc
@@ -40,7 +40,7 @@
 #include "net/http/transport_security_state.h"
 #include "net/log/net_log_with_source.h"
 #include "net/proxy_resolution/proxy_info.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/quic/chromium/mock_crypto_client_stream_factory.h"
 #include "net/quic/chromium/quic_http_utils.h"
 #include "net/quic/chromium/quic_stream_factory_peer.h"
diff --git a/net/log/net_log_util.cc b/net/log/net_log_util.cc
index 4cef960..cf0bac44 100644
--- a/net/log/net_log_util.cc
+++ b/net/log/net_log_util.cc
@@ -34,8 +34,8 @@
 #include "net/log/net_log_parameters_callback.h"
 #include "net/log/net_log_with_source.h"
 #include "net/proxy_resolution/proxy_config.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/proxy_resolution/proxy_retry_info.h"
-#include "net/proxy_resolution/proxy_service.h"
 #include "net/quic/core/quic_error_codes.h"
 #include "net/quic/core/quic_packets.h"
 #include "net/socket/ssl_client_socket.h"
diff --git a/net/proxy_resolution/proxy_service.cc b/net/proxy_resolution/proxy_resolution_service.cc
similarity index 99%
rename from net/proxy_resolution/proxy_service.cc
rename to net/proxy_resolution/proxy_resolution_service.cc
index b85ba76..9af2dc2 100644
--- a/net/proxy_resolution/proxy_service.cc
+++ b/net/proxy_resolution/proxy_resolution_service.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 
 #include <algorithm>
 #include <cmath>
diff --git a/net/proxy_resolution/proxy_service.h b/net/proxy_resolution/proxy_resolution_service.h
similarity index 98%
rename from net/proxy_resolution/proxy_service.h
rename to net/proxy_resolution/proxy_resolution_service.h
index 0bb7ab5..0319977 100644
--- a/net/proxy_resolution/proxy_service.h
+++ b/net/proxy_resolution/proxy_resolution_service.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef NET_PROXY_RESOLUTION_PROXY_SERVICE_H_
-#define NET_PROXY_RESOLUTION_PROXY_SERVICE_H_
+#ifndef NET_PROXY_RESOLUTION_PROXY_RESOLUTION_SERVICE_H_
+#define NET_PROXY_RESOLUTION_PROXY_RESOLUTION_SERVICE_H_
 
 #include <stddef.h>
 
@@ -460,4 +460,4 @@
 
 }  // namespace net
 
-#endif  // NET_PROXY_RESOLUTION_PROXY_SERVICE_H_
+#endif  // NET_PROXY_RESOLUTION_PROXY_RESOLUTION_SERVICE_H_
diff --git a/net/proxy_resolution/proxy_service_unittest.cc b/net/proxy_resolution/proxy_resolution_service_unittest.cc
similarity index 99%
rename from net/proxy_resolution/proxy_service_unittest.cc
rename to net/proxy_resolution/proxy_resolution_service_unittest.cc
index 6af3466e..2b16ea5 100644
--- a/net/proxy_resolution/proxy_service_unittest.cc
+++ b/net/proxy_resolution/proxy_resolution_service_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 
 #include <cstdarg>
 #include <string>
diff --git a/net/quic/chromium/quic_end_to_end_unittest.cc b/net/quic/chromium/quic_end_to_end_unittest.cc
index ae892be..ce0b3fbe 100644
--- a/net/quic/chromium/quic_end_to_end_unittest.cc
+++ b/net/quic/chromium/quic_end_to_end_unittest.cc
@@ -28,7 +28,7 @@
 #include "net/http/http_transaction_test_util.h"
 #include "net/http/transport_security_state.h"
 #include "net/log/net_log_with_source.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/quic/platform/api/quic_string_piece.h"
 #include "net/quic/test_tools/crypto_test_utils.h"
 #include "net/quic/test_tools/quic_test_utils.h"
diff --git a/net/quic/chromium/quic_network_transaction_unittest.cc b/net/quic/chromium/quic_network_transaction_unittest.cc
index 355f842..23bdc90 100644
--- a/net/quic/chromium/quic_network_transaction_unittest.cc
+++ b/net/quic/chromium/quic_network_transaction_unittest.cc
@@ -37,8 +37,8 @@
 #include "net/log/test_net_log_entry.h"
 #include "net/log/test_net_log_util.h"
 #include "net/proxy_resolution/proxy_config_service_fixed.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/proxy_resolution/proxy_resolver.h"
-#include "net/proxy_resolution/proxy_service.h"
 #include "net/quic/chromium/crypto/proof_verifier_chromium.h"
 #include "net/quic/chromium/mock_crypto_client_stream_factory.h"
 #include "net/quic/chromium/mock_quic_data.h"
diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc
index db01fe2..4f38d02c 100644
--- a/net/socket/ssl_client_socket_pool_unittest.cc
+++ b/net/socket/ssl_client_socket_pool_unittest.cc
@@ -27,7 +27,7 @@
 #include "net/http/transport_security_state.h"
 #include "net/log/net_log_source.h"
 #include "net/log/net_log_with_source.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/socket/client_socket_handle.h"
 #include "net/socket/next_proto.h"
 #include "net/socket/socket_tag.h"
diff --git a/net/spdy/chromium/spdy_test_util_common.h b/net/spdy/chromium/spdy_test_util_common.h
index c494d9e..44e0178 100644
--- a/net/spdy/chromium/spdy_test_util_common.h
+++ b/net/spdy/chromium/spdy_test_util_common.h
@@ -29,7 +29,7 @@
 #include "net/http/http_response_info.h"
 #include "net/http/http_server_properties_impl.h"
 #include "net/http/transport_security_state.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/socket/socket_test_util.h"
 #include "net/spdy/chromium/spdy_session.h"
 #include "net/spdy/core/spdy_protocol.h"
diff --git a/net/tools/net_watcher/net_watcher.cc b/net/tools/net_watcher/net_watcher.cc
index 6819f564..388dbd4d 100644
--- a/net/tools/net_watcher/net_watcher.cc
+++ b/net/tools/net_watcher/net_watcher.cc
@@ -28,7 +28,7 @@
 #include "net/base/network_change_notifier.h"
 #include "net/proxy_resolution/proxy_config.h"
 #include "net/proxy_resolution/proxy_config_service.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 
 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
 #include "net/base/network_change_notifier_linux.h"
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h
index 2ecaaf0..5a09960 100644
--- a/net/url_request/url_request_context_builder.h
+++ b/net/url_request/url_request_context_builder.h
@@ -37,7 +37,7 @@
 #include "net/http/http_network_session.h"
 #include "net/net_features.h"
 #include "net/proxy_resolution/proxy_config_service.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/quic/core/quic_packets.h"
 #include "net/socket/next_proto.h"
 #include "net/ssl/ssl_config_service.h"
diff --git a/net/url_request/url_request_context_storage.cc b/net/url_request/url_request_context_storage.cc
index ca3825c2..e337311 100644
--- a/net/url_request/url_request_context_storage.cc
+++ b/net/url_request/url_request_context_storage.cc
@@ -18,7 +18,7 @@
 #include "net/http/http_server_properties.h"
 #include "net/http/http_transaction_factory.h"
 #include "net/log/net_log.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/ssl/channel_id_service.h"
 #include "net/url_request/http_user_agent_settings.h"
 #include "net/url_request/url_request_context.h"
diff --git a/net/url_request/url_request_ftp_job.h b/net/url_request/url_request_ftp_job.h
index e6e8fde4e..9b56e7c 100644
--- a/net/url_request/url_request_ftp_job.h
+++ b/net/url_request/url_request_ftp_job.h
@@ -17,7 +17,7 @@
 #include "net/http/http_request_info.h"
 #include "net/http/http_transaction.h"
 #include "net/proxy_resolution/proxy_info.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/url_request/url_request_job.h"
 
 namespace net {
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index e433a22f..da697315 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -57,8 +57,8 @@
 #include "net/net_features.h"
 #include "net/nqe/network_quality_estimator.h"
 #include "net/proxy_resolution/proxy_info.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/proxy_resolution/proxy_retry_info.h"
-#include "net/proxy_resolution/proxy_service.h"
 #include "net/ssl/channel_id_service.h"
 #include "net/ssl/ssl_cert_request_info.h"
 #include "net/ssl/ssl_config_service.h"
diff --git a/net/url_request/url_request_test_util.h b/net/url_request/url_request_test_util.h
index a8bf758..6906d38 100644
--- a/net/url_request/url_request_test_util.h
+++ b/net/url_request/url_request_test_util.h
@@ -35,7 +35,7 @@
 #include "net/http/http_network_layer.h"
 #include "net/http/http_network_session.h"
 #include "net/http/http_request_headers.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/ssl/ssl_config_service_defaults.h"
 #include "net/url_request/url_request.h"
 #include "net/url_request/url_request_context.h"
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index a7bb6637..59a1c35e 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -89,7 +89,7 @@
 #include "net/log/test_net_log_entry.h"
 #include "net/log/test_net_log_util.h"
 #include "net/net_features.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/quic/chromium/mock_crypto_client_stream_factory.h"
 #include "net/quic/chromium/quic_server_info.h"
 #include "net/socket/socket_test_util.h"
diff --git a/net/websockets/websocket_end_to_end_test.cc b/net/websockets/websocket_end_to_end_test.cc
index 2ea4f44..4dba1fb 100644
--- a/net/websockets/websocket_end_to_end_test.cc
+++ b/net/websockets/websocket_end_to_end_test.cc
@@ -27,7 +27,7 @@
 #include "build/build_config.h"
 #include "net/base/auth.h"
 #include "net/base/proxy_delegate.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/spawned_test_server/spawned_test_server.h"
 #include "net/test/test_data_directory.h"
diff --git a/net/websockets/websocket_stream_test.cc b/net/websockets/websocket_stream_test.cc
index d5a8cc1..180be9c 100644
--- a/net/websockets/websocket_stream_test.cc
+++ b/net/websockets/websocket_stream_test.cc
@@ -22,7 +22,7 @@
 #include "net/base/net_errors.h"
 #include "net/http/http_request_headers.h"
 #include "net/http/http_response_headers.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/socket/client_socket_handle.h"
 #include "net/socket/socket_test_util.h"
 #include "net/spdy/chromium/spdy_test_util_common.h"
diff --git a/net/websockets/websocket_test_util.cc b/net/websockets/websocket_test_util.cc
index 112db2d..d7bfdbc 100644
--- a/net/websockets/websocket_test_util.cc
+++ b/net/websockets/websocket_test_util.cc
@@ -12,7 +12,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "net/http/http_network_session.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/socket/socket_test_util.h"
 #include "net/spdy/core/spdy_protocol.h"
 #include "net/websockets/websocket_basic_handshake_stream.h"
diff --git a/notification_helper/notification_activator.cc b/notification_helper/notification_activator.cc
index c4691651..51a926e 100644
--- a/notification_helper/notification_activator.cc
+++ b/notification_helper/notification_activator.cc
@@ -13,6 +13,13 @@
 #include "notification_helper/notification_helper_util.h"
 #include "notification_helper/trace_util.h"
 
+namespace {
+
+// The response entered by the user while interacting with the toast.
+const wchar_t kUserResponse[] = L"userResponse";
+
+}  // namespace
+
 namespace notification_helper {
 
 NotificationActivator::~NotificationActivator() = default;
@@ -55,6 +62,16 @@
   base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
   command_line.AppendSwitchNative(switches::kNotificationLaunchId,
                                   invoked_args);
+
+  // Check to see if a user response (inline reply) is also supplied.
+  for (ULONG i = 0; i < count; ++i) {
+    if (lstrcmpW(kUserResponse, data[i].Key) == 0) {
+      command_line.AppendSwitchNative(switches::kNotificationInlineReply,
+                                      data[i].Value);
+      break;
+    }
+  }
+
   base::string16 params(command_line.GetCommandLineString());
 
   SHELLEXECUTEINFO info;
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc
index 4e4d6abb..fe5984c 100644
--- a/services/network/network_context_unittest.cc
+++ b/services/network/network_context_unittest.cc
@@ -42,7 +42,7 @@
 #include "net/log/net_log_with_source.h"
 #include "net/proxy_resolution/proxy_config.h"
 #include "net/proxy_resolution/proxy_info.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_builder.h"
 #include "net/url_request/url_request_job_factory.h"
diff --git a/services/network/proxy_resolving_client_socket.h b/services/network/proxy_resolving_client_socket.h
index 8e9a957..7aa6185 100644
--- a/services/network/proxy_resolving_client_socket.h
+++ b/services/network/proxy_resolving_client_socket.h
@@ -20,7 +20,7 @@
 #include "net/base/net_errors.h"
 #include "net/log/net_log_with_source.h"
 #include "net/proxy_resolution/proxy_info.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/socket/next_proto.h"
 #include "net/socket/stream_socket.h"
 #include "net/ssl/ssl_config_service.h"
diff --git a/services/network/proxy_resolving_client_socket_unittest.cc b/services/network/proxy_resolving_client_socket_unittest.cc
index 7d323d2..17377421 100644
--- a/services/network/proxy_resolving_client_socket_unittest.cc
+++ b/services/network/proxy_resolving_client_socket_unittest.cc
@@ -20,7 +20,7 @@
 #include "net/dns/mock_host_resolver.h"
 #include "net/proxy_resolution/mock_proxy_resolver.h"
 #include "net/proxy_resolution/proxy_config_service_fixed.h"
-#include "net/proxy_resolution/proxy_service.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/socket/client_socket_pool_manager.h"
 #include "net/socket/socket_test_util.h"
 #include "net/test/gtest_util.h"
diff --git a/services/network/proxy_service_mojo.cc b/services/network/proxy_service_mojo.cc
index b52db8d7..d1c56147 100644
--- a/services/network/proxy_service_mojo.cc
+++ b/services/network/proxy_service_mojo.cc
@@ -11,8 +11,8 @@
 #include "base/memory/ptr_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "net/proxy_resolution/network_delegate_error_observer.h"
+#include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/proxy_resolution/proxy_resolver_factory.h"
-#include "net/proxy_resolution/proxy_service.h"
 #include "services/network/proxy_resolver_factory_mojo.h"
 
 namespace network {
diff --git a/services/network/public/cpp/BUILD.gn b/services/network/public/cpp/BUILD.gn
index d52aab8d..39f583e 100644
--- a/services/network/public/cpp/BUILD.gn
+++ b/services/network/public/cpp/BUILD.gn
@@ -35,6 +35,7 @@
 
   public_deps = [
     ":cpp_base",
+    "//net",
     "//services/network/public/mojom",
     "//url/ipc:url_ipc",
   ]
@@ -44,7 +45,6 @@
     "//components/prefs",
     "//ipc",
     "//mojo/common",
-    "//net",
     "//services/proxy_resolver/public/mojom",
   ]
 
diff --git a/services/ui/demo/mus_demo_external.h b/services/ui/demo/mus_demo_external.h
index 2b62462..2974b31 100644
--- a/services/ui/demo/mus_demo_external.h
+++ b/services/ui/demo/mus_demo_external.h
@@ -9,7 +9,6 @@
 #include <vector>
 
 #include "services/ui/demo/mus_demo.h"
-#include "services/ui/public/interfaces/window_tree_host_factory.mojom.h"
 
 namespace ui {
 namespace demo {
diff --git a/services/ui/demo/window_tree_data.cc b/services/ui/demo/window_tree_data.cc
index e298166..fcf140e 100644
--- a/services/ui/demo/window_tree_data.cc
+++ b/services/ui/demo/window_tree_data.cc
@@ -70,7 +70,7 @@
     std::unique_ptr<aura::WindowTreeHostMus> window_tree_host) {
   window_tree_host->Show();
   // Take ownership of the WTH.
-  window_tree_host_ = std::move(window_tree_host);
+  SetWindowTreeHost(std::move(window_tree_host));
 
   // Initialize the window for the bitmap.
   window_delegate_ = new aura_extra::ImageWindowDelegate();
diff --git a/services/ui/demo/window_tree_data.h b/services/ui/demo/window_tree_data.h
index 007b04f6d..15fd07c 100644
--- a/services/ui/demo/window_tree_data.h
+++ b/services/ui/demo/window_tree_data.h
@@ -27,12 +27,18 @@
 
   // Initializes the window tree host and start drawing frames.
   void Init(std::unique_ptr<aura::WindowTreeHostMus> window_tree_host);
-  bool IsInitialized() const { return !!window_tree_host_; }
+  bool IsInitialized() const { return !!window_delegate_; }
 
   const aura::WindowTreeHostMus* WindowTreeHost() const {
     return window_tree_host_.get();
   }
 
+ protected:
+  void SetWindowTreeHost(
+      std::unique_ptr<aura::WindowTreeHostMus> window_tree_host) {
+    window_tree_host_ = std::move(window_tree_host);
+  }
+
  private:
   // Draws one frame, incrementing the rotation angle.
   void DrawFrame();
diff --git a/services/ui/public/interfaces/window_tree.mojom b/services/ui/public/interfaces/window_tree.mojom
index 571e4bd..d2af92a 100644
--- a/services/ui/public/interfaces/window_tree.mojom
+++ b/services/ui/public/interfaces/window_tree.mojom
@@ -263,6 +263,24 @@
   // that client B may call EmbedUsingToken().
   ScheduleEmbed(WindowTreeClient client)
       => (mojo.common.mojom.UnguessableToken token);
+
+  // Creates an UnguessableToken for use in a future call, by another client, to
+  // EmbedUsingToken().
+  //
+  // The following example shows how to use this api. Client A wants client B
+  // to embed it in a window created by client B.
+  // 1. Client A calls ScheduleEmbedForExistingClient() to get a token.
+  // 2. Client A passes the token to client B. This communication is done using
+  //    an additional channel, outside of WindowTree/WindowTreeClient.
+  // 3. Client B calls EmbedUsingToken().
+  // 4. Client A receives OnEmbedFromToken() with the token from step 1.
+  //
+  // |window_id| is the id used for the window once EmbedUsingToken() is called.
+  ScheduleEmbedForExistingClient(uint32 window_id) => (
+      mojo.common.mojom.UnguessableToken token);
+
+  // Pair with ScheduleEmbed() or ScheduleEmbedForExistingClient() to complete
+  // an embedding, see them for details.
   EmbedUsingToken(uint64 window_id,
                   mojo.common.mojom.UnguessableToken token,
                   uint32 embed_flags)
@@ -373,6 +391,13 @@
           bool parent_drawn,
           viz.mojom.LocalSurfaceId? local_surface_id);
 
+  // See description in ScheduleEmbedForExistingClient() for details on this.
+  // Supplied arguments match that of OnEmbed().
+  OnEmbedFromToken(mojo.common.mojom.UnguessableToken token,
+                   WindowData root,
+                   int64 display_id,
+                   viz.mojom.LocalSurfaceId? local_surface_id);
+
   // Invoked when the application embedded at |window| is disconnected. In other
   // words the embedded app closes the connection to the server. This is called
   // on the connection that created |window| as well as any ancestors that have
diff --git a/services/ui/ws/BUILD.gn b/services/ui/ws/BUILD.gn
index b4897ad2..e557733 100644
--- a/services/ui/ws/BUILD.gn
+++ b/services/ui/ws/BUILD.gn
@@ -44,12 +44,12 @@
     "drag_cursor_updater.h",
     "drag_source.h",
     "drag_target_connection.h",
-    "event_dispatcher.cc",
-    "event_dispatcher.h",
-    "event_dispatcher_delegate.h",
     "event_location.h",
     "event_matcher.cc",
     "event_matcher.h",
+    "event_processor.cc",
+    "event_processor.h",
+    "event_processor_delegate.h",
     "event_targeter.cc",
     "event_targeter.h",
     "event_targeter_delegate.h",
@@ -250,8 +250,8 @@
     "cursor_unittest.cc",
     "display_unittest.cc",
     "drag_controller_unittest.cc",
-    "event_dispatcher_unittest.cc",
     "event_matcher_unittest.cc",
+    "event_processor_unittest.cc",
     "focus_controller_unittest.cc",
     "frame_generator_unittest.cc",
     "gpu_host_unittest.cc",
diff --git a/services/ui/ws/README.md b/services/ui/ws/README.md
index 3f89b32..3b25467 100644
--- a/services/ui/ws/README.md
+++ b/services/ui/ws/README.md
@@ -34,7 +34,13 @@
 embedder and embedded client use the same ClientWindowId for the Window. See
 discussion on FrameSinkId for more details.
 
-ClientWindowId is globally unique, but a Window may have multiple 
+For a client to establish an embed root, it first calls
+ScheduleEmbedForExistingClient(), so it can provide a window_id that is unique
+within its own scope. That client then passes the returned token to what will
+become its embedder to call EmbedUsingToken(). In this case, the embedder and
+embedded client do not use the same ClientWindowId for the Window.
+
+ClientWindowId is globally unique, but a Window may have multiple
 ClientWindowIds associated with it.
 
 TODO(sky): See http://crbug.com/817850 for making it so there is only one
@@ -59,6 +65,9 @@
 Manager). The Window Manager is told the updated FrameSinkId when it is asked
 to create the top-level (WmCreateTopLevelWindow()).
 
+The FrameSinkId of an embed root's Window is set to the ClientWindowId of the
+embed root's Window from the embedded client.
+
 ### LocalSurfaceId
 
 The LocalSurfaceId (which contains unguessable) is necessary if the client wants
diff --git a/services/ui/ws/display_manager.cc b/services/ui/ws/display_manager.cc
index 3691e0e..bf595c40 100644
--- a/services/ui/ws/display_manager.cc
+++ b/services/ui/ws/display_manager.cc
@@ -15,7 +15,7 @@
 #include "services/ui/ws/display.h"
 #include "services/ui/ws/display_binding.h"
 #include "services/ui/ws/display_creation_config.h"
-#include "services/ui/ws/event_dispatcher.h"
+#include "services/ui/ws/event_processor.h"
 #include "services/ui/ws/frame_generator.h"
 #include "services/ui/ws/server_window.h"
 #include "services/ui/ws/user_display_manager.h"
diff --git a/services/ui/ws/drag_controller.cc b/services/ui/ws/drag_controller.cc
index 4faf1b3..fa4afe5d 100644
--- a/services/ui/ws/drag_controller.cc
+++ b/services/ui/ws/drag_controller.cc
@@ -11,7 +11,6 @@
 #include "services/ui/ws/drag_cursor_updater.h"
 #include "services/ui/ws/drag_source.h"
 #include "services/ui/ws/drag_target_connection.h"
-#include "services/ui/ws/event_dispatcher.h"
 #include "services/ui/ws/server_window.h"
 #include "ui/base/cursor/cursor.h"
 
diff --git a/services/ui/ws/event_dispatcher.cc b/services/ui/ws/event_processor.cc
similarity index 83%
rename from services/ui/ws/event_dispatcher.cc
rename to services/ui/ws/event_processor.cc
index 9b51734b..4fd343c 100644
--- a/services/ui/ws/event_dispatcher.cc
+++ b/services/ui/ws/event_processor.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "services/ui/ws/event_dispatcher.h"
+#include "services/ui/ws/event_processor.h"
 
 #include <algorithm>
 
@@ -11,8 +11,8 @@
 #include "services/ui/ws/accelerator.h"
 #include "services/ui/ws/drag_controller.h"
 #include "services/ui/ws/drag_source.h"
-#include "services/ui/ws/event_dispatcher_delegate.h"
 #include "services/ui/ws/event_location.h"
+#include "services/ui/ws/event_processor_delegate.h"
 #include "services/ui/ws/server_window.h"
 #include "services/ui/ws/server_window_delegate.h"
 #include "services/ui/ws/server_window_drawn_tracker.h"
@@ -60,10 +60,10 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-EventDispatcher::ObservedWindow::ObservedWindow() = default;
-EventDispatcher::ObservedWindow::~ObservedWindow() = default;
+EventProcessor::ObservedWindow::ObservedWindow() = default;
+EventProcessor::ObservedWindow::~ObservedWindow() = default;
 
-EventDispatcher::EventDispatcher(EventDispatcherDelegate* delegate)
+EventProcessor::EventProcessor(EventProcessorDelegate* delegate)
     : delegate_(delegate),
       capture_window_(nullptr),
       capture_window_client_id_(kInvalidClientId),
@@ -72,7 +72,7 @@
       mouse_cursor_source_window_(nullptr),
       mouse_cursor_in_non_client_area_(false) {}
 
-EventDispatcher::~EventDispatcher() {
+EventProcessor::~EventProcessor() {
   SetMouseCursorSourceWindow(nullptr);
   if (capture_window_) {
     UnobserveWindow(capture_window_);
@@ -86,7 +86,7 @@
   pointer_targets_.clear();
 }
 
-void EventDispatcher::Reset() {
+void EventProcessor::Reset() {
   if (capture_window_) {
     CancelPointerEventsToTarget(capture_window_);
     DCHECK(capture_window_ == nullptr);
@@ -98,7 +98,7 @@
   mouse_button_down_ = false;
 }
 
-ui::CursorData EventDispatcher::GetCurrentMouseCursor() const {
+ui::CursorData EventProcessor::GetCurrentMouseCursor() const {
   if (drag_controller_)
     return drag_controller_->current_cursor();
 
@@ -112,8 +112,8 @@
   return window ? window->cursor() : ui::CursorData(ui::CursorType::kPointer);
 }
 
-bool EventDispatcher::SetCaptureWindow(ServerWindow* window,
-                                       ClientSpecificId client_id) {
+bool EventProcessor::SetCaptureWindow(ServerWindow* window,
+                                      ClientSpecificId client_id) {
   if (!window)
     client_id = kInvalidClientId;
 
@@ -161,7 +161,7 @@
   return true;
 }
 
-void EventDispatcher::SetDragDropSourceWindow(
+void EventProcessor::SetDragDropSourceWindow(
     DragSource* drag_source,
     ServerWindow* window,
     DragTargetConnection* source_connection,
@@ -174,27 +174,27 @@
       drag_operations);
 }
 
-void EventDispatcher::CancelDragDrop() {
+void EventProcessor::CancelDragDrop() {
   if (drag_controller_)
     drag_controller_->Cancel();
 }
 
-void EventDispatcher::EndDragDrop() {
+void EventProcessor::EndDragDrop() {
   drag_controller_.reset();
 }
 
-void EventDispatcher::OnWillDestroyDragTargetConnection(
+void EventProcessor::OnWillDestroyDragTargetConnection(
     DragTargetConnection* connection) {
   if (drag_controller_)
     drag_controller_->OnWillDestroyDragTargetConnection(connection);
 }
 
-void EventDispatcher::AddSystemModalWindow(ServerWindow* window) {
+void EventProcessor::AddSystemModalWindow(ServerWindow* window) {
   modal_window_controller_.AddSystemModalWindow(window);
   ReleaseCaptureBlockedByAnyModalWindow();
 }
 
-void EventDispatcher::ReleaseCaptureBlockedByAnyModalWindow() {
+void EventProcessor::ReleaseCaptureBlockedByAnyModalWindow() {
   if (!capture_window_)
     return;
 
@@ -202,7 +202,7 @@
     SetCaptureWindow(nullptr, kInvalidClientId);
 }
 
-const ServerWindow* EventDispatcher::GetWindowForMouseCursor() const {
+const ServerWindow* EventProcessor::GetWindowForMouseCursor() const {
   if (mouse_cursor_in_non_client_area_ || !mouse_cursor_source_window_)
     return mouse_cursor_source_window_;
 
@@ -218,32 +218,32 @@
   return window;
 }
 
-void EventDispatcher::UpdateNonClientAreaForCurrentWindow() {
+void EventProcessor::UpdateNonClientAreaForCurrentWindow() {
   if (!mouse_button_down_ && mouse_cursor_source_window_) {
     event_targeter_->FindTargetForLocation(
         EventSource::MOUSE,
         {mouse_pointer_last_location_, mouse_pointer_last_location_,
          mouse_pointer_display_id_},
         base::BindOnce(
-            &EventDispatcher::UpdateNonClientAreaForCurrentWindowOnFoundWindow,
+            &EventProcessor::UpdateNonClientAreaForCurrentWindowOnFoundWindow,
             base::Unretained(this)));
   }
 }
 
-void EventDispatcher::UpdateCursorProviderByLastKnownLocation() {
+void EventProcessor::UpdateCursorProviderByLastKnownLocation() {
   if (!mouse_button_down_) {
     event_targeter_->FindTargetForLocation(
         EventSource::MOUSE,
         {mouse_pointer_last_location_, mouse_pointer_last_location_,
          mouse_pointer_display_id_},
-        base::BindOnce(&EventDispatcher::
+        base::BindOnce(&EventProcessor::
                            UpdateCursorProviderByLastKnownLocationOnFoundWindow,
                        base::Unretained(this)));
   }
 }
 
-bool EventDispatcher::AddAccelerator(uint32_t id,
-                                     mojom::EventMatcherPtr event_matcher) {
+bool EventProcessor::AddAccelerator(uint32_t id,
+                                    mojom::EventMatcherPtr event_matcher) {
   std::unique_ptr<Accelerator> accelerator(new Accelerator(id, *event_matcher));
   // If an accelerator with the same id or matcher already exists, then abort.
   for (const auto& pair : accelerators_) {
@@ -263,14 +263,14 @@
   return true;
 }
 
-void EventDispatcher::RemoveAccelerator(uint32_t id) {
+void EventProcessor::RemoveAccelerator(uint32_t id) {
   auto it = accelerators_.find(id);
   // Clients may pass bogus ids.
   if (it != accelerators_.end())
     accelerators_.erase(it);
 }
 
-void EventDispatcher::SetKeyEventsThatDontHideCursor(
+void EventProcessor::SetKeyEventsThatDontHideCursor(
     std::vector<::ui::mojom::EventMatcherPtr> dont_hide_cursor_list) {
   dont_hide_cursor_matchers_.clear();
   for (auto& matcher_ptr : dont_hide_cursor_list) {
@@ -282,13 +282,13 @@
   }
 }
 
-bool EventDispatcher::IsProcessingEvent() const {
+bool EventProcessor::IsProcessingEvent() const {
   return waiting_on_event_targeter_;
 }
 
-void EventDispatcher::ProcessEvent(const ui::Event& event,
-                                   const EventLocation& event_location,
-                                   AcceleratorMatchPhase match_phase) {
+void EventProcessor::ProcessEvent(const ui::Event& event,
+                                  const EventLocation& event_location,
+                                  AcceleratorMatchPhase match_phase) {
 #if !defined(NDEBUG)
   if (match_phase == AcceleratorMatchPhase::POST_ONLY) {
     // POST_ONLY should always be preceeded by ANY with the same event.
@@ -309,9 +309,9 @@
       Accelerator* pre_target =
           FindAccelerator(*key_event, ui::mojom::AcceleratorPhase::PRE_TARGET);
       if (pre_target) {
-        delegate_->OnAccelerator(
-            pre_target->id(), event_location.display_id, event,
-            EventDispatcherDelegate::AcceleratorPhase::PRE);
+        delegate_->OnAccelerator(pre_target->id(), event_location.display_id,
+                                 event,
+                                 EventProcessorDelegate::AcceleratorPhase::PRE);
         return;
       }
     }
@@ -329,7 +329,7 @@
         event.IsMousePointerEvent() ? EventSource::MOUSE : EventSource::TOUCH;
     event_targeter_->FindTargetForLocation(
         event_source, event_location,
-        base::BindOnce(&EventDispatcher::ProcessEventOnFoundTarget,
+        base::BindOnce(&EventProcessor::ProcessEventOnFoundTarget,
                        base::Unretained(this), ui::Event::Clone(event)));
   } else {
     ProcessEventOnFoundTargetImpl(ui::Event::Clone(event), event_location,
@@ -337,21 +337,21 @@
   }
 }
 
-ServerWindow* EventDispatcher::GetRootWindowForDisplay(int64_t display_id) {
+ServerWindow* EventProcessor::GetRootWindowForDisplay(int64_t display_id) {
   return delegate_->GetRootWindowForDisplay(display_id);
 }
 
-viz::HitTestQuery* EventDispatcher::GetHitTestQueryForDisplay(
+viz::HitTestQuery* EventProcessor::GetHitTestQueryForDisplay(
     int64_t display_id) {
   return delegate_->GetHitTestQueryForDisplay(display_id);
 }
 
-ServerWindow* EventDispatcher::GetWindowFromFrameSinkId(
+ServerWindow* EventProcessor::GetWindowFromFrameSinkId(
     const viz::FrameSinkId& frame_sink_id) {
   return delegate_->GetWindowFromFrameSinkId(frame_sink_id);
 }
 
-DeepestWindow EventDispatcher::AdjustTargetForModal(
+DeepestWindow EventProcessor::AdjustTargetForModal(
     const DeepestWindow& target) const {
   const ServerWindow* modal_transient =
       modal_window_controller_.GetModalTransient(target.window);
@@ -369,7 +369,7 @@
   return updated_target;
 }
 
-void EventDispatcher::SetMouseCursorSourceWindow(ServerWindow* window) {
+void EventProcessor::SetMouseCursorSourceWindow(ServerWindow* window) {
   if (mouse_cursor_source_window_ == window)
     return;
 
@@ -380,7 +380,7 @@
     ObserveWindow(mouse_cursor_source_window_);
 }
 
-void EventDispatcher::SetMousePointerLocation(
+void EventProcessor::SetMousePointerLocation(
     const gfx::PointF& new_mouse_location,
     int64_t new_mouse_display_id) {
   // TODO: this needs to account for grab and a different display. By that I
@@ -390,9 +390,9 @@
   mouse_pointer_display_id_ = new_mouse_display_id;
 }
 
-void EventDispatcher::ProcessKeyEvent(const ui::KeyEvent& event,
-                                      int64_t display_id,
-                                      AcceleratorMatchPhase match_phase) {
+void EventProcessor::ProcessKeyEvent(const ui::KeyEvent& event,
+                                     int64_t display_id,
+                                     AcceleratorMatchPhase match_phase) {
   Accelerator* post_target =
       FindAccelerator(event, ui::mojom::AcceleratorPhase::POST_TARGET);
   if (drag_controller_ && event.type() == ui::ET_KEY_PRESSED &&
@@ -401,7 +401,7 @@
     return;
   }
   ServerWindow* focused_window =
-      delegate_->GetFocusedWindowForEventDispatcher(display_id);
+      delegate_->GetFocusedWindowForEventProcessor(display_id);
   if (focused_window) {
     // We only hide the cursor when there's a window to receive the key
     // event. We want to hide the cursor when the user is entering text
@@ -421,10 +421,10 @@
   delegate_->OnEventTargetNotFound(event, display_id);
   if (post_target)
     delegate_->OnAccelerator(post_target->id(), display_id, event,
-                             EventDispatcherDelegate::AcceleratorPhase::POST);
+                             EventProcessorDelegate::AcceleratorPhase::POST);
 }
 
-void EventDispatcher::HideCursorOnMatchedKeyEvent(const ui::KeyEvent& event) {
+void EventProcessor::HideCursorOnMatchedKeyEvent(const ui::KeyEvent& event) {
   if (event.IsSynthesized()) {
     // Don't bother performing the matching; it will be rejected anyway.
     return;
@@ -442,7 +442,7 @@
     delegate_->OnEventChangesCursorVisibility(event, false);
 }
 
-bool EventDispatcher::ShouldUseEventTargeter(const Event& event) const {
+bool EventProcessor::ShouldUseEventTargeter(const Event& event) const {
   if (drag_controller_)
     return true;
 
@@ -457,7 +457,7 @@
          event.type() == ET_POINTER_DOWN;
 }
 
-void EventDispatcher::ProcessEventOnFoundTarget(
+void EventProcessor::ProcessEventOnFoundTarget(
     std::unique_ptr<ui::Event> event,
     const EventLocation& event_location,
     const DeepestWindow& target) {
@@ -466,7 +466,7 @@
   ProcessEventOnFoundTargetImpl(std::move(event), event_location, &target);
 }
 
-void EventDispatcher::ProcessEventOnFoundTargetImpl(
+void EventProcessor::ProcessEventOnFoundTargetImpl(
     std::unique_ptr<ui::Event> event,
     const EventLocation& event_location,
     const DeepestWindow* found_target) {
@@ -571,7 +571,7 @@
   }
 }
 
-void EventDispatcher::UpdateCursorRelatedProperties(
+void EventProcessor::UpdateCursorRelatedProperties(
     const ui::Event& event,
     const EventLocation& event_location) {
   if (event.IsMousePointerEvent()) {
@@ -593,7 +593,7 @@
   }
 }
 
-void EventDispatcher::UpdateNonClientAreaForCurrentWindowOnFoundWindow(
+void EventProcessor::UpdateNonClientAreaForCurrentWindowOnFoundWindow(
     const EventLocation& event_location,
     const DeepestWindow& target) {
   if (!mouse_cursor_source_window_)
@@ -604,16 +604,16 @@
     mouse_cursor_in_non_client_area_ =
         mouse_cursor_source_window_ ? updated_target.in_non_client_area : false;
   }
-  delegate_->UpdateNativeCursorFromDispatcher();
+  delegate_->UpdateNativeCursorFromEventProcessor();
 }
 
-void EventDispatcher::UpdateCursorProviderByLastKnownLocationOnFoundWindow(
+void EventProcessor::UpdateCursorProviderByLastKnownLocationOnFoundWindow(
     const EventLocation& event_location,
     const DeepestWindow& target) {
   UpdateCursorProvider(AdjustTargetForModal(target));
 }
 
-void EventDispatcher::UpdateCursorProvider(const DeepestWindow& target) {
+void EventProcessor::UpdateCursorProvider(const DeepestWindow& target) {
   if (mouse_button_down_)
     return;
 
@@ -625,17 +625,17 @@
         delegate_->GetRootWindowForDisplay(mouse_pointer_display_id_));
     mouse_cursor_in_non_client_area_ = true;
   }
-  delegate_->UpdateNativeCursorFromDispatcher();
+  delegate_->UpdateNativeCursorFromEventProcessor();
 }
 
-void EventDispatcher::HandleClickOnBlockedWindow(const DeepestWindow& target) {
+void EventProcessor::HandleClickOnBlockedWindow(const DeepestWindow& target) {
   ServerWindow* modal_transient =
       modal_window_controller_.GetModalTransient(target.window);
   if (modal_transient) {
     ServerWindow* toplevel =
         modal_window_controller_.GetToplevelWindow(target.window);
     DCHECK(toplevel);
-    delegate_->SetFocusedWindowFromEventDispatcher(toplevel);
+    delegate_->SetFocusedWindowFromEventProcessor(toplevel);
     delegate_->OnEventOccurredOutsideOfModalWindow(modal_transient);
   } else if (target.window->IsDrawn() &&
              modal_window_controller_.IsWindowBlocked(target.window) &&
@@ -645,16 +645,15 @@
   }
 }
 
-void EventDispatcher::StartTrackingPointer(
-    int32_t pointer_id,
-    const PointerTarget& pointer_target) {
+void EventProcessor::StartTrackingPointer(int32_t pointer_id,
+                                          const PointerTarget& pointer_target) {
   DCHECK(!IsTrackingPointer(pointer_id));
   if (pointer_target.window)
     ObserveWindow(pointer_target.window);
   pointer_targets_[pointer_id] = pointer_target;
 }
 
-void EventDispatcher::StopTrackingPointer(int32_t pointer_id) {
+void EventProcessor::StopTrackingPointer(int32_t pointer_id) {
   DCHECK(IsTrackingPointer(pointer_id));
   ServerWindow* window = pointer_targets_[pointer_id].window;
   pointer_targets_.erase(pointer_id);
@@ -662,7 +661,7 @@
     UnobserveWindow(window);
 }
 
-void EventDispatcher::UpdateTargetForPointer(
+void EventProcessor::UpdateTargetForPointer(
     int32_t pointer_id,
     const ui::LocatedEvent& event,
     const PointerTarget& pointer_target,
@@ -700,7 +699,7 @@
   StartTrackingPointer(pointer_id, pointer_target);
 }
 
-bool EventDispatcher::AreAnyPointersDown() const {
+bool EventProcessor::AreAnyPointersDown() const {
   for (const auto& pair : pointer_targets_) {
     if (pair.second.is_pointer_down)
       return true;
@@ -708,7 +707,7 @@
   return false;
 }
 
-void EventDispatcher::DispatchToPointerTarget(
+void EventProcessor::DispatchToPointerTarget(
     const PointerTarget& target,
     const ui::LocatedEvent& event,
     const EventLocation& event_location) {
@@ -726,10 +725,10 @@
                    event, event_location);
 }
 
-void EventDispatcher::DispatchToClient(ServerWindow* window,
-                                       ClientSpecificId client_id,
-                                       const ui::LocatedEvent& event,
-                                       const EventLocation& event_location) {
+void EventProcessor::DispatchToClient(ServerWindow* window,
+                                      ClientSpecificId client_id,
+                                      const ui::LocatedEvent& event,
+                                      const EventLocation& event_location) {
   gfx::Point location = ConvertPointFromRootForEventDispatch(
       delegate_->GetRootWindowForEventDispatch(window), window,
       event.location());
@@ -741,7 +740,7 @@
                                         *clone, nullptr);
 }
 
-void EventDispatcher::CancelPointerEventsToTarget(ServerWindow* window) {
+void EventProcessor::CancelPointerEventsToTarget(ServerWindow* window) {
   if (capture_window_ == window) {
     UnobserveWindow(window);
     capture_window_ = nullptr;
@@ -764,7 +763,7 @@
   }
 }
 
-void EventDispatcher::ObserveWindow(ServerWindow* window) {
+void EventProcessor::ObserveWindow(ServerWindow* window) {
   auto iter = observed_windows_.find(window);
   if (iter != observed_windows_.end()) {
     iter->second->num_observers++;
@@ -778,7 +777,7 @@
   observed_windows_[window] = std::move(observed_window);
 }
 
-void EventDispatcher::UnobserveWindow(ServerWindow* window) {
+void EventProcessor::UnobserveWindow(ServerWindow* window) {
   auto it = observed_windows_.find(window);
   DCHECK(it != observed_windows_.end());
   DCHECK_LT(0u, it->second->num_observers);
@@ -786,7 +785,7 @@
     observed_windows_.erase(it);
 }
 
-Accelerator* EventDispatcher::FindAccelerator(
+Accelerator* EventProcessor::FindAccelerator(
     const ui::KeyEvent& event,
     const ui::mojom::AcceleratorPhase phase) {
   for (const auto& pair : accelerators_) {
@@ -796,8 +795,8 @@
   return nullptr;
 }
 
-void EventDispatcher::CancelImplicitCaptureExcept(ServerWindow* window,
-                                                  ClientSpecificId client_id) {
+void EventProcessor::CancelImplicitCaptureExcept(ServerWindow* window,
+                                                 ClientSpecificId client_id) {
   for (const auto& pair : pointer_targets_) {
     ServerWindow* target = pair.second.window;
     if (!target)
@@ -808,10 +807,8 @@
 
     // Don't send cancel events to the same client requesting capture,
     // otherwise the client can easily get confused.
-    if (window &&
-        client_id ==
-            delegate_->GetEventTargetClientId(target,
-                                              pair.second.in_nonclient_area)) {
+    if (window && client_id == delegate_->GetEventTargetClientId(
+                                   target, pair.second.in_nonclient_area)) {
       continue;
     }
 
@@ -833,29 +830,29 @@
   pointer_targets_.clear();
 }
 
-void EventDispatcher::WindowNoLongerValidTarget(ServerWindow* window) {
+void EventProcessor::WindowNoLongerValidTarget(ServerWindow* window) {
   CancelPointerEventsToTarget(window);
   if (mouse_cursor_source_window_ == window)
     SetMouseCursorSourceWindow(nullptr);
 }
 
-void EventDispatcher::OnDrawnStateChanged(ServerWindow* ancestor,
-                                          ServerWindow* window,
-                                          bool is_drawn) {
+void EventProcessor::OnDrawnStateChanged(ServerWindow* ancestor,
+                                         ServerWindow* window,
+                                         bool is_drawn) {
   if (!is_drawn)
     WindowNoLongerValidTarget(window);
 }
 
-void EventDispatcher::OnRootDidChange(ServerWindow* ancestor,
-                                      ServerWindow* window) {
+void EventProcessor::OnRootDidChange(ServerWindow* ancestor,
+                                     ServerWindow* window) {
   if (delegate_->IsWindowInDisplayRoot(window))
     return;
 
   WindowNoLongerValidTarget(window);
 }
 
-void EventDispatcher::OnDragCursorUpdated() {
-  delegate_->UpdateNativeCursorFromDispatcher();
+void EventProcessor::OnDragCursorUpdated() {
+  delegate_->UpdateNativeCursorFromEventProcessor();
 }
 
 }  // namespace ws
diff --git a/services/ui/ws/event_dispatcher.h b/services/ui/ws/event_processor.h
similarity index 94%
rename from services/ui/ws/event_dispatcher.h
rename to services/ui/ws/event_processor.h
index 866a1c5..08ce53b 100644
--- a/services/ui/ws/event_dispatcher.h
+++ b/services/ui/ws/event_processor.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SERVICES_UI_WS_EVENT_DISPATCHER_H_
-#define SERVICES_UI_WS_EVENT_DISPATCHER_H_
+#ifndef SERVICES_UI_WS_EVENT_PROCESSOR_H_
+#define SERVICES_UI_WS_EVENT_PROCESSOR_H_
 
 #include <stdint.h>
 
@@ -40,20 +40,23 @@
 class DragController;
 class DragSource;
 class DragTargetConnection;
-class EventDispatcherDelegate;
+class EventProcessorDelegate;
 class ServerWindow;
 class ServerWindowDrawnTracker;
 
 struct EventLocation;
 
 namespace test {
-class EventDispatcherTestApi;
+class EventProcessorTestApi;
 }
 
-// Handles dispatching events to the right location as well as updating focus.
-class EventDispatcher : public ServerWindowDrawnTrackerObserver,
-                        public DragCursorUpdater,
-                        public EventTargeterDelegate {
+// Processes events sent to the Window Service from the native platform. Updates
+// internale state associated with events (such as mouse, keyboard state,
+// capture, focus...). EventProcessorDelegate handles dispatching to the
+// appropriate client.
+class EventProcessor : public ServerWindowDrawnTrackerObserver,
+                       public DragCursorUpdater,
+                       public EventTargeterDelegate {
  public:
   enum class AcceleratorMatchPhase {
     // Both pre and post should be considered.
@@ -64,8 +67,8 @@
     POST_ONLY,
   };
 
-  explicit EventDispatcher(EventDispatcherDelegate* delegate);
-  ~EventDispatcher() override;
+  explicit EventProcessor(EventProcessorDelegate* delegate);
+  ~EventProcessor() override;
 
   ModalWindowController* modal_window_controller() {
     return &modal_window_controller_;
@@ -175,7 +178,7 @@
       const viz::FrameSinkId& frame_sink_id) override;
 
  private:
-  friend class test::EventDispatcherTestApi;
+  friend class test::EventProcessorTestApi;
 
   // Keeps track of state associated with an active pointer.
   struct PointerTarget {
@@ -248,7 +251,7 @@
                                  const EventLocation& event_location,
                                  const DeepestWindow& target);
 
-  // EventDispatcher provides the following logic for events:
+  // EventProcessor provides the following logic for events:
   // . wheel events go to the current target of the associated pointer. If
   //   there is no target, they go to the deepest window.
   // . move (not drag) events go to the deepest window.
@@ -351,7 +354,7 @@
   // DragCursorUpdater:
   void OnDragCursorUpdated() override;
 
-  EventDispatcherDelegate* delegate_;
+  EventProcessorDelegate* delegate_;
 
   ServerWindow* capture_window_;
   ClientSpecificId capture_window_client_id_;
@@ -401,10 +404,10 @@
       AcceleratorMatchPhase::ANY;
 #endif
 
-  DISALLOW_COPY_AND_ASSIGN(EventDispatcher);
+  DISALLOW_COPY_AND_ASSIGN(EventProcessor);
 };
 
 }  // namespace ws
 }  // namespace ui
 
-#endif  // SERVICES_UI_WS_EVENT_DISPATCHER_H_
+#endif  // SERVICES_UI_WS_EVENT_PROCESSOR_H_
diff --git a/services/ui/ws/event_dispatcher_delegate.h b/services/ui/ws/event_processor_delegate.h
similarity index 88%
rename from services/ui/ws/event_dispatcher_delegate.h
rename to services/ui/ws/event_processor_delegate.h
index 2084a7e..c639755 100644
--- a/services/ui/ws/event_dispatcher_delegate.h
+++ b/services/ui/ws/event_processor_delegate.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef SERVICES_UI_WS_EVENT_DISPATCHER_DELEGATE_H_
-#define SERVICES_UI_WS_EVENT_DISPATCHER_DELEGATE_H_
+#ifndef SERVICES_UI_WS_EVENT_PROCESSOR_DELEGATE_H_
+#define SERVICES_UI_WS_EVENT_PROCESSOR_DELEGATE_H_
 
 #include <stdint.h>
 
@@ -26,8 +26,9 @@
 class Accelerator;
 class ServerWindow;
 
-// Used by EventDispatcher for mocking in tests.
-class EventDispatcherDelegate {
+// Used by EventProcessor for dispatching of events, as well as to inform the
+// delegate of various state changes.
+class EventProcessorDelegate {
  public:
   enum class AcceleratorPhase {
     PRE,
@@ -39,8 +40,8 @@
                              const ui::Event& event,
                              AcceleratorPhase phase) = 0;
 
-  virtual void SetFocusedWindowFromEventDispatcher(ServerWindow* window) = 0;
-  virtual ServerWindow* GetFocusedWindowForEventDispatcher(
+  virtual void SetFocusedWindowFromEventProcessor(ServerWindow* window) = 0;
+  virtual ServerWindow* GetFocusedWindowForEventProcessor(
       int64_t display_id) = 0;
 
   // Called when capture should be set on the native display. |window| is the
@@ -51,9 +52,9 @@
   // longer a ServerWindow holding capture.
   virtual void ReleaseNativeCapture() = 0;
 
-  // Called when EventDispatcher has a new value for the cursor and our
+  // Called when EventProcessor has a new value for the cursor and our
   // delegate should perform the native updates.
-  virtual void UpdateNativeCursorFromDispatcher() = 0;
+  virtual void UpdateNativeCursorFromEventProcessor() = 0;
 
   // Called when |window| has lost capture. The native display may still be
   // holding capture. The delegate should not change native display capture.
@@ -125,10 +126,10 @@
       const viz::FrameSinkId& frame_sink_id) = 0;
 
  protected:
-  virtual ~EventDispatcherDelegate() {}
+  virtual ~EventProcessorDelegate() {}
 };
 
 }  // namespace ws
 }  // namespace ui
 
-#endif  // SERVICES_UI_WS_EVENT_DISPATCHER_DELEGATE_H_
+#endif  // SERVICES_UI_WS_EVENT_PROCESSOR_DELEGATE_H_
diff --git a/services/ui/ws/event_dispatcher_unittest.cc b/services/ui/ws/event_processor_unittest.cc
similarity index 85%
rename from services/ui/ws/event_dispatcher_unittest.cc
rename to services/ui/ws/event_processor_unittest.cc
index 784f83e..b0a4895 100644
--- a/services/ui/ws/event_dispatcher_unittest.cc
+++ b/services/ui/ws/event_processor_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "services/ui/ws/event_dispatcher.h"
+#include "services/ui/ws/event_processor.h"
 
 #include <stddef.h>
 #include <stdint.h>
@@ -21,8 +21,8 @@
 #include "services/ui/common/switches.h"
 #include "services/ui/public/interfaces/window_tree_constants.mojom.h"
 #include "services/ui/ws/accelerator.h"
-#include "services/ui/ws/event_dispatcher_delegate.h"
 #include "services/ui/ws/event_location.h"
+#include "services/ui/ws/event_processor_delegate.h"
 #include "services/ui/ws/server_window.h"
 #include "services/ui/ws/test_server_window_delegate.h"
 #include "services/ui/ws/test_utils.h"
@@ -52,7 +52,7 @@
   Accelerator* accelerator;
 };
 
-class TestEventDispatcherDelegate : public EventDispatcherDelegate {
+class TestEventProcessorDelegate : public EventProcessorDelegate {
  public:
   // Delegate interface used by this class to release capture on event
   // dispatcher.
@@ -61,12 +61,12 @@
     virtual void ReleaseCapture() = 0;
   };
 
-  explicit TestEventDispatcherDelegate(Delegate* delegate)
+  explicit TestEventProcessorDelegate(Delegate* delegate)
       : delegate_(delegate),
         focused_window_(nullptr),
         lost_capture_window_(nullptr),
         last_accelerator_(0) {}
-  ~TestEventDispatcherDelegate() override {}
+  ~TestEventProcessorDelegate() override {}
 
   void EnableFallbackToRoot() { fallback_to_root_ = true; }
 
@@ -125,13 +125,13 @@
 
   void AddWindow(ServerWindow* window) { windows_.push_back(window); }
 
-  // EventDispatcherDelegate:
-  void SetFocusedWindowFromEventDispatcher(ServerWindow* window) override {
+  // EventProcessorDelegate:
+  void SetFocusedWindowFromEventProcessor(ServerWindow* window) override {
     focused_window_ = window;
   }
 
  private:
-  // EventDispatcherDelegate:
+  // EventProcessorDelegate:
   void OnAccelerator(uint32_t accelerator,
                      int64_t display_id,
                      const ui::Event& event,
@@ -140,8 +140,7 @@
     last_accelerator_ = accelerator;
     last_accelerator_phase_ = phase;
   }
-  ServerWindow* GetFocusedWindowForEventDispatcher(
-      int64_t display_id) override {
+  ServerWindow* GetFocusedWindowForEventProcessor(int64_t display_id) override {
     return focused_window_;
   }
   void SetNativeCapture(ServerWindow* window) override {}
@@ -149,7 +148,7 @@
     if (delegate_)
       delegate_->ReleaseCapture();
   }
-  void UpdateNativeCursorFromDispatcher() override {}
+  void UpdateNativeCursorFromEventProcessor() override {}
   void OnCaptureChanged(ServerWindow* new_capture_window,
                         ServerWindow* old_capture_window) override {
     lost_capture_window_ = old_capture_window;
@@ -229,7 +228,7 @@
 
   bool is_window_in_display_root_ = true;
 
-  DISALLOW_COPY_AND_ASSIGN(TestEventDispatcherDelegate);
+  DISALLOW_COPY_AND_ASSIGN(TestEventProcessorDelegate);
 };
 
 // Used by RunMouseEventTests(). Can identify up to two generated events. The
@@ -282,30 +281,30 @@
 
 }  // namespace
 
-// Test fixture for EventDispatcher with friend access to verify the internal
+// Test fixture for EventProcessor with friend access to verify the internal
 // state. Setup creates a TestServerWindowDelegate, a visible root ServerWindow,
-// a TestEventDispatcher and the EventDispatcher for testing.
-class EventDispatcherTest : public testing::TestWithParam<bool>,
-                            public TestEventDispatcherDelegate::Delegate {
+// a TestEventProcessor and the EventProcessor for testing.
+class EventProcessorTest : public testing::TestWithParam<bool>,
+                           public TestEventProcessorDelegate::Delegate {
  public:
-  EventDispatcherTest() {}
-  ~EventDispatcherTest() override {}
+  EventProcessorTest() {}
+  ~EventProcessorTest() override {}
 
   ServerWindow* root_window() { return root_window_.get(); }
-  TestEventDispatcherDelegate* test_event_dispatcher_delegate() {
+  TestEventProcessorDelegate* test_event_dispatcher_delegate() {
     return test_event_dispatcher_delegate_.get();
   }
-  EventDispatcher* event_dispatcher() { return event_dispatcher_.get(); }
+  EventProcessor* event_dispatcher() { return event_dispatcher_.get(); }
   VizHostProxy* viz_host_proxy() {
     return ws_test_helper_.window_server()->GetVizHostProxy();
   }
   TestServerWindowDelegate* window_delegate() { return window_delegate_.get(); }
 
-  void DispatchEvent(EventDispatcher* dispatcher,
+  void DispatchEvent(EventProcessor* dispatcher,
                      const ui::Event& event,
-                     EventDispatcher::AcceleratorMatchPhase match_phase);
-  void RunMouseEventTests(EventDispatcher* dispatcher,
-                          TestEventDispatcherDelegate* dispatcher_delegate,
+                     EventProcessor::AcceleratorMatchPhase match_phase);
+  void RunMouseEventTests(EventProcessor* dispatcher,
+                          TestEventProcessorDelegate* dispatcher_delegate,
                           MouseEventTest* tests,
                           size_t test_count);
   bool AreAnyPointersDown() const;
@@ -330,7 +329,7 @@
   void RunTasks();
 
  private:
-  // TestEventDispatcherDelegate::Delegate:
+  // TestEventProcessorDelegate::Delegate:
   void ReleaseCapture() override {
     event_dispatcher_->SetCaptureWindow(nullptr, kInvalidClientId);
   }
@@ -339,23 +338,23 @@
 
   std::unique_ptr<TestServerWindowDelegate> window_delegate_;
   std::unique_ptr<ServerWindow> root_window_;
-  std::unique_ptr<TestEventDispatcherDelegate> test_event_dispatcher_delegate_;
-  std::unique_ptr<EventDispatcher> event_dispatcher_;
+  std::unique_ptr<TestEventProcessorDelegate> test_event_dispatcher_delegate_;
+  std::unique_ptr<EventProcessor> event_dispatcher_;
 
-  DISALLOW_COPY_AND_ASSIGN(EventDispatcherTest);
+  DISALLOW_COPY_AND_ASSIGN(EventProcessorTest);
 };
 
-void EventDispatcherTest::DispatchEvent(
-    EventDispatcher* dispatcher,
+void EventProcessorTest::DispatchEvent(
+    EventProcessor* dispatcher,
     const ui::Event& event,
-    EventDispatcher::AcceleratorMatchPhase match_phase) {
+    EventProcessor::AcceleratorMatchPhase match_phase) {
   dispatcher->ProcessEvent(event, EventLocationFromEvent(event), match_phase);
   RunTasks();
 }
 
-void EventDispatcherTest::RunMouseEventTests(
-    EventDispatcher* dispatcher,
-    TestEventDispatcherDelegate* dispatcher_delegate,
+void EventProcessorTest::RunMouseEventTests(
+    EventProcessor* dispatcher,
+    TestEventProcessorDelegate* dispatcher_delegate,
     MouseEventTest* tests,
     size_t test_count) {
   for (size_t i = 0; i < test_count; ++i) {
@@ -363,7 +362,7 @@
     ASSERT_FALSE(dispatcher_delegate->has_queued_events())
         << " unexpected queued events before running " << i;
     DispatchEvent(dispatcher, ui::PointerEvent(*test.input_event),
-                  EventDispatcher::AcceleratorMatchPhase::ANY);
+                  EventProcessor::AcceleratorMatchPhase::ANY);
 
     std::unique_ptr<DispatchedEventDetails> details =
         dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
@@ -381,11 +380,11 @@
   }
 }
 
-bool EventDispatcherTest::AreAnyPointersDown() const {
-  return EventDispatcherTestApi(event_dispatcher_.get()).AreAnyPointersDown();
+bool EventProcessorTest::AreAnyPointersDown() const {
+  return EventProcessorTestApi(event_dispatcher_.get()).AreAnyPointersDown();
 }
 
-void EventDispatcherTest::ClearSetup() {
+void EventProcessorTest::ClearSetup() {
   // ServerWindowDelegate should outlive ServerWindow.
   root_window_.reset();
   window_delegate_.reset();
@@ -393,7 +392,7 @@
   event_dispatcher_.reset();
 }
 
-std::unique_ptr<ServerWindow> EventDispatcherTest::CreateChildWindowWithParent(
+std::unique_ptr<ServerWindow> EventProcessorTest::CreateChildWindowWithParent(
     const viz::FrameSinkId& id,
     ServerWindow* parent) {
   std::unique_ptr<ServerWindow> child(
@@ -403,34 +402,34 @@
   return child;
 }
 
-std::unique_ptr<ServerWindow> EventDispatcherTest::CreateChildWindow(
+std::unique_ptr<ServerWindow> EventProcessorTest::CreateChildWindow(
     const viz::FrameSinkId& id) {
   return CreateChildWindowWithParent(id, root_window_.get());
 }
 
-bool EventDispatcherTest::IsMouseButtonDown() const {
-  return EventDispatcherTestApi(event_dispatcher_.get()).is_mouse_button_down();
+bool EventProcessorTest::IsMouseButtonDown() const {
+  return EventProcessorTestApi(event_dispatcher_.get()).is_mouse_button_down();
 }
 
-bool EventDispatcherTest::IsWindowPointerTarget(
+bool EventProcessorTest::IsWindowPointerTarget(
     const ServerWindow* window) const {
-  return EventDispatcherTestApi(event_dispatcher_.get())
+  return EventProcessorTestApi(event_dispatcher_.get())
       .IsWindowPointerTarget(window);
 }
 
-int EventDispatcherTest::NumberPointerTargetsForWindow(
+int EventProcessorTest::NumberPointerTargetsForWindow(
     ServerWindow* window) const {
-  return EventDispatcherTestApi(event_dispatcher_.get())
+  return EventProcessorTestApi(event_dispatcher_.get())
       .NumberPointerTargetsForWindow(window);
 }
 
-const ServerWindow* EventDispatcherTest::GetActiveSystemModalWindow() const {
+const ServerWindow* EventProcessorTest::GetActiveSystemModalWindow() const {
   ModalWindowController* mwc =
-      EventDispatcherTestApi(event_dispatcher_.get()).modal_window_controller();
+      EventProcessorTestApi(event_dispatcher_.get()).modal_window_controller();
   return ModalWindowControllerTestApi(mwc).GetActiveSystemModalWindow();
 }
 
-void EventDispatcherTest::RunTasks() {
+void EventProcessorTest::RunTasks() {
   if (!is_event_processing_async())
     return;
 
@@ -438,7 +437,7 @@
   runloop.RunUntilIdle();
 }
 
-void EventDispatcherTest::SetUp() {
+void EventProcessorTest::SetUp() {
   if (is_event_processing_async()) {
     base::CommandLine::ForCurrentProcess()->AppendSwitch(
         switches::kUseAsyncEventTargeting);
@@ -454,24 +453,24 @@
   root_window_->SetVisible(true);
 
   test_event_dispatcher_delegate_ =
-      std::make_unique<TestEventDispatcherDelegate>(this);
+      std::make_unique<TestEventProcessorDelegate>(this);
   event_dispatcher_ =
-      std::make_unique<EventDispatcher>(test_event_dispatcher_delegate_.get());
+      std::make_unique<EventProcessor>(test_event_dispatcher_delegate_.get());
   test_event_dispatcher_delegate_->set_root(root_window_.get());
 }
 
-class EventDispatcherVizTargeterTest
+class EventProcessorVizTargeterTest
     : public testing::TestWithParam<bool>,
-      public TestEventDispatcherDelegate::Delegate {
+      public TestEventProcessorDelegate::Delegate {
  public:
-  EventDispatcherVizTargeterTest() {}
-  ~EventDispatcherVizTargeterTest() override {}
+  EventProcessorVizTargeterTest() {}
+  ~EventProcessorVizTargeterTest() override {}
 
   ServerWindow* root_window() { return root_window_.get(); }
-  TestEventDispatcherDelegate* test_event_dispatcher_delegate() {
+  TestEventProcessorDelegate* test_event_dispatcher_delegate() {
     return test_event_dispatcher_delegate_.get();
   }
-  EventDispatcher* event_dispatcher() { return event_dispatcher_.get(); }
+  EventProcessor* event_dispatcher() { return event_dispatcher_.get(); }
   VizHostProxy* viz_host_proxy() {
     return ws_test_helper_.window_server()->GetVizHostProxy();
   }
@@ -479,9 +478,9 @@
     return static_cast<viz::AggregatedHitTestRegion*>(active_buffer_.get());
   }
 
-  void DispatchEvent(EventDispatcher* dispatcher,
+  void DispatchEvent(EventProcessor* dispatcher,
                      const ui::Event& event,
-                     EventDispatcher::AcceleratorMatchPhase match_phase) {
+                     EventProcessor::AcceleratorMatchPhase match_phase) {
     dispatcher->ProcessEvent(event, EventLocationFromEvent(event), match_phase);
 
     if (!is_event_processing_async())
@@ -506,7 +505,7 @@
   void SetUp() override;
 
  private:
-  // TestEventDispatcherDelegate::Delegate:
+  // TestEventProcessorDelegate::Delegate:
   void ReleaseCapture() override {
     event_dispatcher_->SetCaptureWindow(nullptr, kInvalidClientId);
   }
@@ -516,14 +515,14 @@
 
   std::unique_ptr<TestServerWindowDelegate> window_delegate_;
   std::unique_ptr<ServerWindow> root_window_;
-  std::unique_ptr<TestEventDispatcherDelegate> test_event_dispatcher_delegate_;
-  std::unique_ptr<EventDispatcher> event_dispatcher_;
+  std::unique_ptr<TestEventProcessorDelegate> test_event_dispatcher_delegate_;
+  std::unique_ptr<EventProcessor> event_dispatcher_;
   mojo::ScopedSharedBufferMapping active_buffer_;
 
-  DISALLOW_COPY_AND_ASSIGN(EventDispatcherVizTargeterTest);
+  DISALLOW_COPY_AND_ASSIGN(EventProcessorVizTargeterTest);
 };
 
-void EventDispatcherVizTargeterTest::SetUp() {
+void EventProcessorVizTargeterTest::SetUp() {
   feature_list_.InitAndEnableFeature(features::kEnableVizHitTestDrawQuad);
   if (is_event_processing_async()) {
     base::CommandLine::ForCurrentProcess()->AppendSwitch(
@@ -540,9 +539,9 @@
   root_window_->SetVisible(true);
 
   test_event_dispatcher_delegate_ =
-      std::make_unique<TestEventDispatcherDelegate>(this);
+      std::make_unique<TestEventProcessorDelegate>(this);
   event_dispatcher_ =
-      std::make_unique<EventDispatcher>(test_event_dispatcher_delegate_.get());
+      std::make_unique<EventProcessor>(test_event_dispatcher_delegate_.get());
   test_event_dispatcher_delegate_->set_root(root_window_.get());
 
   uint32_t handle_size = 100;
@@ -558,7 +557,7 @@
           handle_size);
 }
 
-TEST_P(EventDispatcherTest, ProcessEvent) {
+TEST_P(EventProcessorTest, ProcessEvent) {
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
 
@@ -570,7 +569,7 @@
       ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), gfx::Point(20, 25),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(event_dispatcher(), ui_event,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   std::unique_ptr<DispatchedEventDetails> details =
       test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
@@ -585,11 +584,11 @@
   EXPECT_EQ(gfx::Point(10, 15), dispatched_event->location());
 }
 
-TEST_P(EventDispatcherTest, ProcessEventNoTarget) {
+TEST_P(EventProcessorTest, ProcessEventNoTarget) {
   // Send event without a target.
   ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
   DispatchEvent(event_dispatcher(), key,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   // Event wasn't dispatched to a target.
   std::unique_ptr<DispatchedEventDetails> details =
@@ -604,10 +603,10 @@
   EXPECT_EQ(ui::VKEY_A, event_out->AsKeyEvent()->key_code());
 }
 
-TEST_P(EventDispatcherTest, AcceleratorBasic) {
+TEST_P(EventProcessorTest, AcceleratorBasic) {
   ClearSetup();
-  TestEventDispatcherDelegate event_dispatcher_delegate(nullptr);
-  EventDispatcher dispatcher(&event_dispatcher_delegate);
+  TestEventProcessorDelegate event_dispatcher_delegate(nullptr);
+  EventProcessor dispatcher(&event_dispatcher_delegate);
 
   uint32_t accelerator_1 = 1;
   mojom::EventMatcherPtr matcher = ui::CreateKeyMatcher(
@@ -642,10 +641,10 @@
   EXPECT_TRUE(dispatcher.AddAccelerator(accelerator_3, std::move(matcher)));
 }
 
-TEST_P(EventDispatcherTest, EventMatching) {
-  TestEventDispatcherDelegate* event_dispatcher_delegate =
+TEST_P(EventProcessorTest, EventMatching) {
+  TestEventProcessorDelegate* event_dispatcher_delegate =
       test_event_dispatcher_delegate();
-  EventDispatcher* dispatcher = event_dispatcher();
+  EventProcessor* dispatcher = event_dispatcher();
 
   mojom::EventMatcherPtr matcher = ui::CreateKeyMatcher(
       ui::mojom::KeyboardCode::W, ui::mojom::kEventFlagControlDown);
@@ -653,7 +652,7 @@
   dispatcher->AddAccelerator(accelerator_1, std::move(matcher));
 
   ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN);
-  DispatchEvent(dispatcher, key, EventDispatcher::AcceleratorMatchPhase::ANY);
+  DispatchEvent(dispatcher, key, EventProcessor::AcceleratorMatchPhase::ANY);
   EXPECT_EQ(accelerator_1,
             event_dispatcher_delegate->GetAndClearLastAccelerator());
 
@@ -661,32 +660,32 @@
   // ignoring.
   key = ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_W,
                      ui::EF_CONTROL_DOWN | ui::EF_NUM_LOCK_ON);
-  DispatchEvent(dispatcher, key, EventDispatcher::AcceleratorMatchPhase::ANY);
+  DispatchEvent(dispatcher, key, EventProcessor::AcceleratorMatchPhase::ANY);
   EXPECT_EQ(accelerator_1,
             event_dispatcher_delegate->GetAndClearLastAccelerator());
 
   key = ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_NONE);
-  DispatchEvent(dispatcher, key, EventDispatcher::AcceleratorMatchPhase::ANY);
+  DispatchEvent(dispatcher, key, EventProcessor::AcceleratorMatchPhase::ANY);
   EXPECT_EQ(0u, event_dispatcher_delegate->GetAndClearLastAccelerator());
 
   uint32_t accelerator_2 = 2;
   matcher = ui::CreateKeyMatcher(ui::mojom::KeyboardCode::W,
                                  ui::mojom::kEventFlagNone);
   dispatcher->AddAccelerator(accelerator_2, std::move(matcher));
-  DispatchEvent(dispatcher, key, EventDispatcher::AcceleratorMatchPhase::ANY);
+  DispatchEvent(dispatcher, key, EventProcessor::AcceleratorMatchPhase::ANY);
   EXPECT_EQ(accelerator_2,
             event_dispatcher_delegate->GetAndClearLastAccelerator());
 
   dispatcher->RemoveAccelerator(accelerator_2);
-  DispatchEvent(dispatcher, key, EventDispatcher::AcceleratorMatchPhase::ANY);
+  DispatchEvent(dispatcher, key, EventProcessor::AcceleratorMatchPhase::ANY);
   EXPECT_EQ(0u, event_dispatcher_delegate->GetAndClearLastAccelerator());
 }
 
 // Tests that a post-target accelerator is not triggered by ProcessEvent.
-TEST_P(EventDispatcherTest, PostTargetAccelerator) {
-  TestEventDispatcherDelegate* event_dispatcher_delegate =
+TEST_P(EventProcessorTest, PostTargetAccelerator) {
+  TestEventProcessorDelegate* event_dispatcher_delegate =
       test_event_dispatcher_delegate();
-  EventDispatcher* dispatcher = event_dispatcher();
+  EventProcessor* dispatcher = event_dispatcher();
 
   mojom::EventMatcherPtr matcher = ui::CreateKeyMatcher(
       ui::mojom::KeyboardCode::W, ui::mojom::kEventFlagControlDown);
@@ -696,20 +695,20 @@
 
   ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN);
   // The post-target accelerator should be fired if there is no focused window.
-  DispatchEvent(dispatcher, key, EventDispatcher::AcceleratorMatchPhase::ANY);
+  DispatchEvent(dispatcher, key, EventProcessor::AcceleratorMatchPhase::ANY);
   EXPECT_EQ(accelerator_1,
             event_dispatcher_delegate->GetAndClearLastAccelerator());
   std::unique_ptr<DispatchedEventDetails> details =
       event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
   EXPECT_FALSE(details);
 
-  // Set focused window for EventDispatcher dispatches key events.
+  // Set focused window for EventProcessor dispatches key events.
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
-  event_dispatcher_delegate->SetFocusedWindowFromEventDispatcher(child.get());
+  event_dispatcher_delegate->SetFocusedWindowFromEventProcessor(child.get());
 
   // With a focused window the event should be dispatched.
-  DispatchEvent(dispatcher, key, EventDispatcher::AcceleratorMatchPhase::ANY);
+  DispatchEvent(dispatcher, key, EventProcessor::AcceleratorMatchPhase::ANY);
   EXPECT_EQ(0u, event_dispatcher_delegate->GetAndClearLastAccelerator());
   details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
   EXPECT_TRUE(details);
@@ -721,17 +720,17 @@
   EXPECT_FALSE(accelerator_weak_ptr);
 
   // Post deletion there should be no accelerator
-  DispatchEvent(dispatcher, key, EventDispatcher::AcceleratorMatchPhase::ANY);
+  DispatchEvent(dispatcher, key, EventProcessor::AcceleratorMatchPhase::ANY);
   EXPECT_EQ(0u, event_dispatcher_delegate->GetAndClearLastAccelerator());
   details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
   EXPECT_TRUE(details);
   EXPECT_FALSE(details->accelerator);
 }
 
-TEST_P(EventDispatcherTest, ProcessPost) {
-  TestEventDispatcherDelegate* event_dispatcher_delegate =
+TEST_P(EventProcessorTest, ProcessPost) {
+  TestEventProcessorDelegate* event_dispatcher_delegate =
       test_event_dispatcher_delegate();
-  EventDispatcher* dispatcher = event_dispatcher();
+  EventProcessor* dispatcher = event_dispatcher();
 
   uint32_t pre_id = 1;
   {
@@ -749,23 +748,23 @@
     dispatcher->AddAccelerator(post_id, std::move(matcher));
   }
 
-  // Set focused window for EventDispatcher dispatches key events.
+  // Set focused window for EventProcessor dispatches key events.
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
-  event_dispatcher_delegate->SetFocusedWindowFromEventDispatcher(child.get());
+  event_dispatcher_delegate->SetFocusedWindowFromEventProcessor(child.get());
 
   // Dispatch for ANY, which should trigger PRE and not call
   // DispatchInputEventToWindow().
   ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_W, ui::EF_CONTROL_DOWN);
-  DispatchEvent(dispatcher, key, EventDispatcher::AcceleratorMatchPhase::ANY);
-  EXPECT_EQ(EventDispatcherDelegate::AcceleratorPhase::PRE,
+  DispatchEvent(dispatcher, key, EventProcessor::AcceleratorMatchPhase::ANY);
+  EXPECT_EQ(EventProcessorDelegate::AcceleratorPhase::PRE,
             event_dispatcher_delegate->last_accelerator_phase());
   EXPECT_EQ(pre_id, event_dispatcher_delegate->GetAndClearLastAccelerator());
   EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
 
   // Dispatch for POST, which should trigger POST.
   DispatchEvent(dispatcher, key,
-                EventDispatcher::AcceleratorMatchPhase::POST_ONLY);
+                EventProcessor::AcceleratorMatchPhase::POST_ONLY);
   std::unique_ptr<DispatchedEventDetails> details =
       event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
   ASSERT_TRUE(details);
@@ -773,7 +772,7 @@
   EXPECT_EQ(post_id, details->accelerator->id());
 }
 
-TEST_P(EventDispatcherTest, Capture) {
+TEST_P(EventProcessorTest, Capture) {
   ServerWindow* root = root_window();
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
@@ -821,7 +820,7 @@
                      tests, arraysize(tests));
 }
 
-TEST_P(EventDispatcherTest, CaptureMultipleMouseButtons) {
+TEST_P(EventProcessorTest, CaptureMultipleMouseButtons) {
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
 
@@ -868,7 +867,7 @@
                      tests, arraysize(tests));
 }
 
-TEST_P(EventDispatcherTest, ClientAreaGoesToOwner) {
+TEST_P(EventProcessorTest, ClientAreaGoesToOwner) {
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
 
@@ -877,16 +876,16 @@
 
   child->SetClientArea(gfx::Insets(5, 5, 5, 5), std::vector<gfx::Rect>());
 
-  TestEventDispatcherDelegate* event_dispatcher_delegate =
+  TestEventProcessorDelegate* event_dispatcher_delegate =
       test_event_dispatcher_delegate();
-  EventDispatcher* dispatcher = event_dispatcher();
+  EventProcessor* dispatcher = event_dispatcher();
 
   // Start move loop by sending mouse event over non-client area.
   const ui::PointerEvent press_event(ui::MouseEvent(
       ui::ET_MOUSE_PRESSED, gfx::Point(12, 12), gfx::Point(12, 12),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(dispatcher, press_event,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   // Events should target child and be in the non-client area.
   std::unique_ptr<DispatchedEventDetails> details =
@@ -901,7 +900,7 @@
       ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(17, 18), gfx::Point(17, 18),
                      base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0));
   DispatchEvent(dispatcher, move_event,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   // Still same target.
   details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
@@ -914,7 +913,7 @@
       ui::ET_MOUSE_RELEASED, gfx::Point(17, 18), gfx::Point(17, 18),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(dispatcher, release_event,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   // The event should not have been dispatched to the delegate.
   details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
@@ -928,7 +927,7 @@
       ui::ET_MOUSE_PRESSED, gfx::Point(21, 22), gfx::Point(21, 22),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(dispatcher, press_event2,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
   details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
   EXPECT_TRUE(event_dispatcher_delegate->has_queued_events());
   ASSERT_EQ(child.get(), details->window);
@@ -942,7 +941,7 @@
   EXPECT_EQ(ui::ET_POINTER_DOWN, details->event->type());
 }
 
-TEST_P(EventDispatcherTest, AdditionalClientArea) {
+TEST_P(EventProcessorTest, AdditionalClientArea) {
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
 
@@ -953,14 +952,14 @@
   additional_client_areas.push_back(gfx::Rect(18, 0, 2, 2));
   child->SetClientArea(gfx::Insets(5, 5, 5, 5), additional_client_areas);
 
-  TestEventDispatcherDelegate* event_dispatcher_delegate =
+  TestEventProcessorDelegate* event_dispatcher_delegate =
       test_event_dispatcher_delegate();
   // Press in the additional client area, it should go to the child.
   const ui::PointerEvent press_event(ui::MouseEvent(
       ui::ET_MOUSE_PRESSED, gfx::Point(28, 11), gfx::Point(28, 11),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(event_dispatcher(), press_event,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   // Events should target child and be in the client area.
   std::unique_ptr<DispatchedEventDetails> details =
@@ -970,7 +969,7 @@
   EXPECT_TRUE(details->IsClientArea());
 }
 
-TEST_P(EventDispatcherTest, HitTestMask) {
+TEST_P(EventProcessorTest, HitTestMask) {
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
 
@@ -979,11 +978,11 @@
   child->SetHitTestMask(gfx::Rect(2, 2, 16, 16));
 
   // Move in the masked area.
-  const ui::PointerEvent move1(ui::MouseEvent(
-      ui::ET_MOUSE_MOVED, gfx::Point(11, 11), gfx::Point(11, 11),
-      base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0));
+  const ui::PointerEvent move1(
+      ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(11, 11), gfx::Point(11, 11),
+                     base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0));
   DispatchEvent(event_dispatcher(), move1,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   // Event went through the child window and hit the root.
   std::unique_ptr<DispatchedEventDetails> details1 =
@@ -994,11 +993,11 @@
   child->ClearHitTestMask();
 
   // Move right in the same part of the window.
-  const ui::PointerEvent move2(ui::MouseEvent(
-      ui::ET_MOUSE_MOVED, gfx::Point(11, 12), gfx::Point(11, 12),
-      base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0));
+  const ui::PointerEvent move2(
+      ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(11, 12), gfx::Point(11, 12),
+                     base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0));
   DispatchEvent(event_dispatcher(), move2,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   // Mouse exits the root.
   std::unique_ptr<DispatchedEventDetails> details2 =
@@ -1012,23 +1011,23 @@
   EXPECT_TRUE(details3->IsClientArea());
 }
 
-TEST_P(EventDispatcherTest, DontFocusOnSecondDown) {
+TEST_P(EventProcessorTest, DontFocusOnSecondDown) {
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
 
   root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
   child->SetBounds(gfx::Rect(10, 10, 20, 20));
 
-  TestEventDispatcherDelegate* event_dispatcher_delegate =
+  TestEventProcessorDelegate* event_dispatcher_delegate =
       test_event_dispatcher_delegate();
-  EventDispatcher* dispatcher = event_dispatcher();
+  EventProcessor* dispatcher = event_dispatcher();
 
   // Press on |child|. Press should not change focus.
   const ui::PointerEvent press_event(ui::MouseEvent(
       ui::ET_MOUSE_PRESSED, gfx::Point(12, 12), gfx::Point(12, 12),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(dispatcher, press_event,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
   std::unique_ptr<DispatchedEventDetails> details =
       event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
   EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
@@ -1036,7 +1035,7 @@
   EXPECT_EQ(nullptr, event_dispatcher_delegate->GetAndClearLastFocusedWindow());
 }
 
-TEST_P(EventDispatcherTest, TwoPointersActive) {
+TEST_P(EventProcessorTest, TwoPointersActive) {
   std::unique_ptr<ServerWindow> child1 =
       CreateChildWindow(viz::FrameSinkId(1, 3));
   std::unique_ptr<ServerWindow> child2 =
@@ -1046,16 +1045,16 @@
   child1->SetBounds(gfx::Rect(10, 10, 20, 20));
   child2->SetBounds(gfx::Rect(50, 51, 11, 12));
 
-  TestEventDispatcherDelegate* event_dispatcher_delegate =
+  TestEventProcessorDelegate* event_dispatcher_delegate =
       test_event_dispatcher_delegate();
-  EventDispatcher* dispatcher = event_dispatcher();
+  EventProcessor* dispatcher = event_dispatcher();
 
   // Press on child1.
   const ui::PointerEvent touch_event1(ui::TouchEvent(
       ui::ET_TOUCH_PRESSED, gfx::Point(12, 13), base::TimeTicks(),
       ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1)));
   DispatchEvent(dispatcher, touch_event1,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
   std::unique_ptr<DispatchedEventDetails> details =
       event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
   EXPECT_EQ(child1.get(), details->window);
@@ -1065,7 +1064,7 @@
       ui::ET_TOUCH_MOVED, gfx::Point(53, 54), base::TimeTicks(),
       ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1)));
   DispatchEvent(dispatcher, drag_event1,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
   details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
   EXPECT_EQ(child1.get(), details->window);
 
@@ -1074,7 +1073,7 @@
       ui::ET_TOUCH_PRESSED, gfx::Point(54, 55), base::TimeTicks(),
       ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 2)));
   DispatchEvent(dispatcher, touch_event2,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
   details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
   EXPECT_EQ(child2.get(), details->window);
 
@@ -1083,13 +1082,13 @@
       ui::ET_TOUCH_MOVED, gfx::Point(13, 14), base::TimeTicks(),
       ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 2)));
   DispatchEvent(dispatcher, drag_event2,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
   details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
   EXPECT_EQ(child2.get(), details->window);
 
   // Drag again with id 1, child1 should continue to get it.
   DispatchEvent(dispatcher, drag_event1,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
   details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
   EXPECT_EQ(child1.get(), details->window);
 
@@ -1098,35 +1097,35 @@
       ui::ET_TOUCH_RELEASED, gfx::Point(54, 55), base::TimeTicks(),
       ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1)));
   DispatchEvent(dispatcher, touch_release,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
   details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
   EXPECT_EQ(child1.get(), details->window);
   const ui::PointerEvent touch_event3(ui::TouchEvent(
       ui::ET_TOUCH_PRESSED, gfx::Point(54, 55), base::TimeTicks(),
       ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 2)));
   DispatchEvent(dispatcher, touch_event3,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
   details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
   EXPECT_EQ(child2.get(), details->window);
 }
 
-TEST_P(EventDispatcherTest, DestroyWindowWhileGettingEvents) {
+TEST_P(EventProcessorTest, DestroyWindowWhileGettingEvents) {
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
 
   root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
   child->SetBounds(gfx::Rect(10, 10, 20, 20));
 
-  TestEventDispatcherDelegate* event_dispatcher_delegate =
+  TestEventProcessorDelegate* event_dispatcher_delegate =
       test_event_dispatcher_delegate();
-  EventDispatcher* dispatcher = event_dispatcher();
+  EventProcessor* dispatcher = event_dispatcher();
 
   // Press on child.
   const ui::PointerEvent touch_event1(ui::TouchEvent(
       ui::ET_TOUCH_PRESSED, gfx::Point(12, 13), base::TimeTicks(),
       ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1)));
   DispatchEvent(dispatcher, touch_event1,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
   std::unique_ptr<DispatchedEventDetails> details =
       event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
   EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
@@ -1139,12 +1138,12 @@
       ui::ET_TOUCH_MOVED, gfx::Point(53, 54), base::TimeTicks(),
       ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1)));
   DispatchEvent(dispatcher, drag_event1,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
   details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
   EXPECT_EQ(nullptr, details.get());
 }
 
-TEST_P(EventDispatcherTest, MouseInExtendedHitTestRegion) {
+TEST_P(EventProcessorTest, MouseInExtendedHitTestRegion) {
   ServerWindow* root = root_window();
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
@@ -1152,16 +1151,16 @@
   root->SetBounds(gfx::Rect(0, 0, 100, 100));
   child->SetBounds(gfx::Rect(10, 10, 20, 20));
 
-  TestEventDispatcherDelegate* event_dispatcher_delegate =
+  TestEventProcessorDelegate* event_dispatcher_delegate =
       test_event_dispatcher_delegate();
-  EventDispatcher* dispatcher = event_dispatcher();
+  EventProcessor* dispatcher = event_dispatcher();
 
   // Send event that is not over child.
   const ui::PointerEvent ui_event(ui::MouseEvent(
       ui::ET_MOUSE_PRESSED, gfx::Point(8, 9), gfx::Point(8, 9),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(dispatcher, ui_event,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
   std::unique_ptr<DispatchedEventDetails> details =
       event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
   ASSERT_EQ(root, details->window);
@@ -1171,7 +1170,7 @@
       ui::ET_MOUSE_RELEASED, gfx::Point(8, 9), gfx::Point(8, 9),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(dispatcher, release_event,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
   details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
   EXPECT_FALSE(event_dispatcher_delegate->has_queued_events());
   ASSERT_EQ(root, details->window);
@@ -1182,7 +1181,7 @@
   root->set_extended_hit_test_regions_for_children(gfx::Insets(-5, -5, -5, -5),
                                                    gfx::Insets(-5, -5, -5, -5));
   DispatchEvent(dispatcher, ui_event,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
   details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
   EXPECT_EQ(root, details->window);
   EXPECT_EQ(ui::ET_POINTER_EXITED, details->event->type());
@@ -1198,7 +1197,7 @@
   EXPECT_EQ(gfx::Point(-2, -1), details->event->AsPointerEvent()->location());
 }
 
-TEST_P(EventDispatcherTest, WheelWhileDown) {
+TEST_P(EventProcessorTest, WheelWhileDown) {
   std::unique_ptr<ServerWindow> child1 =
       CreateChildWindow(viz::FrameSinkId(1, 3));
   std::unique_ptr<ServerWindow> child2 =
@@ -1230,7 +1229,7 @@
 // Tests that when explicit capture has been set that all events go to the
 // designated window, and that when capture is cleared, events find the
 // appropriate target window.
-TEST_P(EventDispatcherTest, SetExplicitCapture) {
+TEST_P(EventProcessorTest, SetExplicitCapture) {
   ServerWindow* root = root_window();
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
@@ -1238,9 +1237,9 @@
   root->SetBounds(gfx::Rect(0, 0, 100, 100));
   child->SetBounds(gfx::Rect(10, 10, 20, 20));
 
-  TestEventDispatcherDelegate* event_dispatcher_delegate =
+  TestEventProcessorDelegate* event_dispatcher_delegate =
       test_event_dispatcher_delegate();
-  EventDispatcher* dispatcher = event_dispatcher();
+  EventProcessor* dispatcher = event_dispatcher();
 
   {
     // Send all pointer events to the child.
@@ -1252,7 +1251,7 @@
         ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), gfx::Point(5, 5),
         base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
     DispatchEvent(dispatcher, left_press_event,
-                  EventDispatcher::AcceleratorMatchPhase::ANY);
+                  EventProcessor::AcceleratorMatchPhase::ANY);
 
     // Events should target child.
     std::unique_ptr<DispatchedEventDetails> details =
@@ -1269,7 +1268,7 @@
         base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON,
         ui::EF_RIGHT_MOUSE_BUTTON));
     DispatchEvent(dispatcher, right_press_event,
-                  EventDispatcher::AcceleratorMatchPhase::ANY);
+                  EventProcessor::AcceleratorMatchPhase::ANY);
     details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
     EXPECT_TRUE(IsMouseButtonDown());
 
@@ -1279,7 +1278,7 @@
         base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON,
         ui::EF_LEFT_MOUSE_BUTTON));
     DispatchEvent(dispatcher, left_release_event,
-                  EventDispatcher::AcceleratorMatchPhase::ANY);
+                  EventProcessor::AcceleratorMatchPhase::ANY);
     details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
     EXPECT_TRUE(IsMouseButtonDown());
 
@@ -1288,7 +1287,7 @@
         ui::ET_TOUCH_PRESSED, gfx::Point(15, 15), base::TimeTicks(),
         ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 2)));
     DispatchEvent(dispatcher, touch_event,
-                  EventDispatcher::AcceleratorMatchPhase::ANY);
+                  EventProcessor::AcceleratorMatchPhase::ANY);
     details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
     EXPECT_TRUE(IsMouseButtonDown());
 
@@ -1298,7 +1297,7 @@
                        base::TimeTicks(), ui::EF_RIGHT_MOUSE_BUTTON,
                        ui::EF_RIGHT_MOUSE_BUTTON));
     DispatchEvent(dispatcher, move_event,
-                  EventDispatcher::AcceleratorMatchPhase::ANY);
+                  EventProcessor::AcceleratorMatchPhase::ANY);
     details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
     EXPECT_TRUE(IsMouseButtonDown());
 
@@ -1308,7 +1307,7 @@
                        gfx::Point(5, 5), base::TimeTicks(),
                        ui::EF_RIGHT_MOUSE_BUTTON, ui::EF_RIGHT_MOUSE_BUTTON));
     DispatchEvent(dispatcher, right_release_event,
-                  EventDispatcher::AcceleratorMatchPhase::ANY);
+                  EventProcessor::AcceleratorMatchPhase::ANY);
     details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
     EXPECT_FALSE(IsMouseButtonDown());
   }
@@ -1320,7 +1319,7 @@
         ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), gfx::Point(5, 5),
         base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
     DispatchEvent(dispatcher, press_event,
-                  EventDispatcher::AcceleratorMatchPhase::ANY);
+                  EventProcessor::AcceleratorMatchPhase::ANY);
 
     // Events should target the root.
     std::unique_ptr<DispatchedEventDetails> details =
@@ -1333,7 +1332,7 @@
 
 // This test verifies that explicit capture overrides and resets implicit
 // capture.
-TEST_P(EventDispatcherTest, ExplicitCaptureOverridesImplicitCapture) {
+TEST_P(EventProcessorTest, ExplicitCaptureOverridesImplicitCapture) {
   ServerWindow* root = root_window();
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
@@ -1341,9 +1340,9 @@
   root->SetBounds(gfx::Rect(0, 0, 100, 100));
   child->SetBounds(gfx::Rect(10, 10, 20, 20));
 
-  TestEventDispatcherDelegate* event_dispatcher_delegate =
+  TestEventProcessorDelegate* event_dispatcher_delegate =
       test_event_dispatcher_delegate();
-  EventDispatcher* dispatcher = event_dispatcher();
+  EventProcessor* dispatcher = event_dispatcher();
 
   // Run some implicit capture tests.
   MouseEventTest tests[] = {
@@ -1384,7 +1383,7 @@
         ui::ET_TOUCH_PRESSED, gfx::Point(12, 13), base::TimeTicks(),
         ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1)));
     DispatchEvent(dispatcher, touch_event,
-                  EventDispatcher::AcceleratorMatchPhase::ANY);
+                  EventProcessor::AcceleratorMatchPhase::ANY);
   }
 
   std::unique_ptr<DispatchedEventDetails> details =
@@ -1417,7 +1416,7 @@
       ui::ET_MOUSE_PRESSED, gfx::Point(15, 15), gfx::Point(15, 15),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(dispatcher, press_event,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   // Events should target the root.
   details = event_dispatcher_delegate->GetAndAdvanceDispatchedEventDetails();
@@ -1428,17 +1427,17 @@
 
 // Tests that setting capture does delete active pointer targets for the capture
 // window.
-TEST_P(EventDispatcherTest, CaptureUpdatesActivePointerTargets) {
+TEST_P(EventProcessorTest, CaptureUpdatesActivePointerTargets) {
   ServerWindow* root = root_window();
   root->SetBounds(gfx::Rect(0, 0, 100, 100));
 
-  EventDispatcher* dispatcher = event_dispatcher();
+  EventProcessor* dispatcher = event_dispatcher();
   {
     const ui::PointerEvent press_event(ui::MouseEvent(
         ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), gfx::Point(5, 5),
         base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
     DispatchEvent(dispatcher, press_event,
-                  EventDispatcher::AcceleratorMatchPhase::ANY);
+                  EventProcessor::AcceleratorMatchPhase::ANY);
 
     std::unique_ptr<DispatchedEventDetails> details =
         test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
@@ -1450,7 +1449,7 @@
         ui::ET_TOUCH_PRESSED, gfx::Point(12, 13), base::TimeTicks(),
         ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1)));
     DispatchEvent(dispatcher, touch_event,
-                  EventDispatcher::AcceleratorMatchPhase::ANY);
+                  EventProcessor::AcceleratorMatchPhase::ANY);
   }
 
   ASSERT_TRUE(AreAnyPointersDown());
@@ -1466,7 +1465,7 @@
 
 // Tests that when explicit capture is changed, that the previous window with
 // capture is no longer being observed.
-TEST_P(EventDispatcherTest, UpdatingCaptureStopsObservingPreviousCapture) {
+TEST_P(EventProcessorTest, UpdatingCaptureStopsObservingPreviousCapture) {
   std::unique_ptr<ServerWindow> child1 =
       CreateChildWindow(viz::FrameSinkId(1, 3));
   std::unique_ptr<ServerWindow> child2 =
@@ -1476,7 +1475,7 @@
   child1->SetBounds(gfx::Rect(10, 10, 20, 20));
   child2->SetBounds(gfx::Rect(50, 51, 11, 12));
 
-  EventDispatcher* dispatcher = event_dispatcher();
+  EventProcessor* dispatcher = event_dispatcher();
   ASSERT_FALSE(AreAnyPointersDown());
   ASSERT_FALSE(IsWindowPointerTarget(child1.get()));
   ASSERT_FALSE(IsWindowPointerTarget(child2.get()));
@@ -1486,17 +1485,17 @@
             test_event_dispatcher_delegate()->lost_capture_window());
 
   EXPECT_FALSE(
-      EventDispatcherTestApi(dispatcher).IsObservingWindow(child1.get()));
+      EventProcessorTestApi(dispatcher).IsObservingWindow(child1.get()));
 }
 
 // Tests that destroying a window with explicit capture clears the capture
 // state.
-TEST_P(EventDispatcherTest, DestroyingCaptureWindowRemovesExplicitCapture) {
+TEST_P(EventProcessorTest, DestroyingCaptureWindowRemovesExplicitCapture) {
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
   child->SetBounds(gfx::Rect(10, 10, 20, 20));
 
-  EventDispatcher* dispatcher = event_dispatcher();
+  EventProcessor* dispatcher = event_dispatcher();
   dispatcher->SetCaptureWindow(child.get(), kClientAreaId);
   EXPECT_EQ(child.get(), dispatcher->capture_window());
 
@@ -1509,22 +1508,22 @@
 
 // Tests that when |client_id| is set for a window performing capture, that this
 // preference is used regardless of whether an event targets the client region.
-TEST_P(EventDispatcherTest, CaptureInNonClientAreaOverridesActualPoint) {
+TEST_P(EventProcessorTest, CaptureInNonClientAreaOverridesActualPoint) {
   ServerWindow* root = root_window();
   root->SetBounds(gfx::Rect(0, 0, 100, 100));
 
   root->SetClientArea(gfx::Insets(5, 5, 5, 5), std::vector<gfx::Rect>());
-  EventDispatcher* dispatcher = event_dispatcher();
+  EventProcessor* dispatcher = event_dispatcher();
   dispatcher->SetCaptureWindow(root, kNonclientAreaId);
 
-  TestEventDispatcherDelegate* event_dispatcher_delegate =
+  TestEventProcessorDelegate* event_dispatcher_delegate =
       test_event_dispatcher_delegate();
   // Press in the client area, it should be marked as non client.
   const ui::PointerEvent press_event(ui::MouseEvent(
       ui::ET_MOUSE_PRESSED, gfx::Point(6, 6), gfx::Point(6, 6),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(event_dispatcher(), press_event,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   // Events should target child and be in the client area.
   std::unique_ptr<DispatchedEventDetails> details =
@@ -1534,7 +1533,7 @@
   EXPECT_TRUE(details->IsNonclientArea());
 }
 
-TEST_P(EventDispatcherTest, ProcessPointerEvents) {
+TEST_P(EventProcessorTest, ProcessPointerEvents) {
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
 
@@ -1546,7 +1545,7 @@
         ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), gfx::Point(20, 25),
         base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
     DispatchEvent(event_dispatcher(), pointer_event,
-                  EventDispatcher::AcceleratorMatchPhase::ANY);
+                  EventProcessor::AcceleratorMatchPhase::ANY);
 
     std::unique_ptr<DispatchedEventDetails> details =
         test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
@@ -1568,7 +1567,7 @@
         ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH,
                            touch_id)));
     DispatchEvent(event_dispatcher(), pointer_event,
-                  EventDispatcher::AcceleratorMatchPhase::ANY);
+                  EventProcessor::AcceleratorMatchPhase::ANY);
 
     std::unique_ptr<DispatchedEventDetails> details =
         test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
@@ -1585,7 +1584,7 @@
   }
 }
 
-TEST_P(EventDispatcherTest, ResetClearsPointerDown) {
+TEST_P(EventProcessorTest, ResetClearsPointerDown) {
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
 
@@ -1597,7 +1596,7 @@
       ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), gfx::Point(20, 25),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(event_dispatcher(), ui_event,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   std::unique_ptr<DispatchedEventDetails> details =
       test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
@@ -1611,12 +1610,12 @@
   EXPECT_FALSE(AreAnyPointersDown());
 }
 
-TEST_P(EventDispatcherTest, ResetClearsCapture) {
+TEST_P(EventProcessorTest, ResetClearsCapture) {
   ServerWindow* root = root_window();
   root->SetBounds(gfx::Rect(0, 0, 100, 100));
 
   root->SetClientArea(gfx::Insets(5, 5, 5, 5), std::vector<gfx::Rect>());
-  EventDispatcher* dispatcher = event_dispatcher();
+  EventProcessor* dispatcher = event_dispatcher();
   dispatcher->SetCaptureWindow(root, kNonclientAreaId);
 
   event_dispatcher()->Reset();
@@ -1625,7 +1624,7 @@
 }
 
 // Tests that events on a parent of a modal window are blocked.
-TEST_P(EventDispatcherTest, ModalWindowEventOnModalParent) {
+TEST_P(EventProcessorTest, ModalWindowEventOnModalParent) {
   std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3));
   std::unique_ptr<ServerWindow> w2 = CreateChildWindow(viz::FrameSinkId(1, 5));
 
@@ -1641,7 +1640,7 @@
       ui::ET_MOUSE_PRESSED, gfx::Point(15, 15), gfx::Point(15, 15),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(event_dispatcher(), mouse_pressed,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
   // As |w2| is modal and the event is over |w1|, no events should be queued,
   // and the delegate should be informed of this.
   ASSERT_FALSE(test_event_dispatcher_delegate()->has_queued_events());
@@ -1653,7 +1652,7 @@
       ui::ET_MOUSE_RELEASED, gfx::Point(15, 15), gfx::Point(15, 15),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(event_dispatcher(), mouse_released,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
   ASSERT_FALSE(test_event_dispatcher_delegate()->has_queued_events());
   EXPECT_FALSE(test_event_dispatcher_delegate()->window_that_blocked_event());
 
@@ -1662,7 +1661,7 @@
       ui::ET_MOUSE_PRESSED, gfx::Point(55, 15), gfx::Point(55, 15),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(event_dispatcher(), mouse_pressed2,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
   std::unique_ptr<DispatchedEventDetails> details =
       test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
   ASSERT_TRUE(details);
@@ -1678,7 +1677,7 @@
 }
 
 // Tests that events on a modal child target the modal child itself.
-TEST_P(EventDispatcherTest, ModalWindowEventOnModalChild) {
+TEST_P(EventProcessorTest, ModalWindowEventOnModalChild) {
   std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3));
   std::unique_ptr<ServerWindow> w2 = CreateChildWindow(viz::FrameSinkId(1, 5));
 
@@ -1694,7 +1693,7 @@
       ui::ET_MOUSE_PRESSED, gfx::Point(55, 15), gfx::Point(55, 15),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(event_dispatcher(), mouse_pressed,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   std::unique_ptr<DispatchedEventDetails> details =
       test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
@@ -1712,7 +1711,7 @@
 
 // Tests that events on an unrelated window are not affected by the modal
 // window.
-TEST_P(EventDispatcherTest, ModalWindowEventOnUnrelatedWindow) {
+TEST_P(EventProcessorTest, ModalWindowEventOnUnrelatedWindow) {
   std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3));
   std::unique_ptr<ServerWindow> w2 = CreateChildWindow(viz::FrameSinkId(1, 5));
   std::unique_ptr<ServerWindow> w3 = CreateChildWindow(viz::FrameSinkId(1, 6));
@@ -1730,7 +1729,7 @@
       ui::ET_MOUSE_PRESSED, gfx::Point(75, 15), gfx::Point(75, 15),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(event_dispatcher(), mouse_pressed,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   std::unique_ptr<DispatchedEventDetails> details =
       test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
@@ -1747,7 +1746,7 @@
 }
 
 // Tests that events on a descendant of a modal parent target the modal child.
-TEST_P(EventDispatcherTest, ModalWindowEventOnDescendantOfModalParent) {
+TEST_P(EventProcessorTest, ModalWindowEventOnDescendantOfModalParent) {
   std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3));
   std::unique_ptr<ServerWindow> w11 =
       CreateChildWindowWithParent(viz::FrameSinkId(1, 4), w1.get());
@@ -1766,7 +1765,7 @@
       ui::ET_MOUSE_PRESSED, gfx::Point(25, 25), gfx::Point(25, 25),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(event_dispatcher(), mouse_pressed,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   // The event is targeted at |w11|, but is blocked by the modal window |w2|.
   ASSERT_TRUE(test_event_dispatcher_delegate()->last_event_target_not_found());
@@ -1775,7 +1774,7 @@
 
 // Same as ModalWindowEventOnDescendantOfModalParent but with fallback to root
 // enabled.
-TEST_P(EventDispatcherTest,
+TEST_P(EventProcessorTest,
        ModalWindowEventOnDescendantOfModalParentWithFallback) {
   test_event_dispatcher_delegate()->EnableFallbackToRoot();
 
@@ -1797,7 +1796,7 @@
       ui::ET_MOUSE_PRESSED, gfx::Point(25, 25), gfx::Point(25, 25),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(event_dispatcher(), mouse_pressed,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   std::unique_ptr<DispatchedEventDetails> details =
       test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
@@ -1814,7 +1813,7 @@
 }
 
 // Tests that events on a system modal window target the modal window itself.
-TEST_P(EventDispatcherTest, ModalWindowEventOnSystemModal) {
+TEST_P(EventProcessorTest, ModalWindowEventOnSystemModal) {
   std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3));
 
   root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
@@ -1826,7 +1825,7 @@
       ui::ET_MOUSE_PRESSED, gfx::Point(15, 15), gfx::Point(15, 15),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(event_dispatcher(), mouse_pressed,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   std::unique_ptr<DispatchedEventDetails> details =
       test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
@@ -1843,7 +1842,7 @@
 }
 
 // Tests that events outside of system modal window target the modal window.
-TEST_P(EventDispatcherTest, ModalWindowEventOutsideSystemModal) {
+TEST_P(EventProcessorTest, ModalWindowEventOutsideSystemModal) {
   std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3));
 
   root_window()->SetBounds(gfx::Rect(0, 0, 100, 100));
@@ -1856,7 +1855,7 @@
       ui::ET_MOUSE_PRESSED, gfx::Point(45, 15), gfx::Point(45, 15),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(event_dispatcher(), mouse_pressed,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   ASSERT_TRUE(test_event_dispatcher_delegate()->last_event_target_not_found());
   ASSERT_FALSE(test_event_dispatcher_delegate()->has_queued_events());
@@ -1866,7 +1865,7 @@
 
 // Variant of ModalWindowEventOutsideSystemModal with
 // EnableFallbackToRoot().
-TEST_P(EventDispatcherTest, ModalWindowEventOutsideSystemModalWithFallback) {
+TEST_P(EventProcessorTest, ModalWindowEventOutsideSystemModalWithFallback) {
   test_event_dispatcher_delegate()->EnableFallbackToRoot();
 
   std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3));
@@ -1881,7 +1880,7 @@
       ui::ET_MOUSE_PRESSED, gfx::Point(45, 15), gfx::Point(45, 15),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(event_dispatcher(), mouse_pressed,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   std::unique_ptr<DispatchedEventDetails> details =
       test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
@@ -1898,7 +1897,7 @@
 }
 
 // Tests events on a sub-window of system modal window target the window itself.
-TEST_P(EventDispatcherTest, ModalWindowEventSubWindowSystemModal) {
+TEST_P(EventProcessorTest, ModalWindowEventSubWindowSystemModal) {
   std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3));
   w1->SetModalType(MODAL_TYPE_SYSTEM);
   event_dispatcher()->AddSystemModalWindow(w1.get());
@@ -1931,7 +1930,7 @@
         ui::PointerEvent(ui::TouchEvent(
             ui::ET_TOUCH_PRESSED, kTouchData[i].location, base::TimeTicks(),
             ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0))),
-        EventDispatcher::AcceleratorMatchPhase::ANY);
+        EventProcessor::AcceleratorMatchPhase::ANY);
     std::unique_ptr<DispatchedEventDetails> details =
         test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
     ASSERT_TRUE(details) << " details is nullptr " << i;
@@ -1943,13 +1942,13 @@
         ui::PointerEvent(ui::TouchEvent(
             ui::ET_TOUCH_RELEASED, kTouchData[i].location, base::TimeTicks(),
             ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0))),
-        EventDispatcher::AcceleratorMatchPhase::ANY);
+        EventProcessor::AcceleratorMatchPhase::ANY);
     test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
   }
 }
 
 // Tests that setting capture to a descendant of a modal parent fails.
-TEST_P(EventDispatcherTest, ModalWindowSetCaptureDescendantOfModalParent) {
+TEST_P(EventProcessorTest, ModalWindowSetCaptureDescendantOfModalParent) {
   std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3));
   std::unique_ptr<ServerWindow> w11 =
       CreateChildWindowWithParent(viz::FrameSinkId(1, 4), w1.get());
@@ -1968,7 +1967,7 @@
 }
 
 // Tests that setting capture to a window unrelated to a modal parent works.
-TEST_P(EventDispatcherTest, ModalWindowSetCaptureUnrelatedWindow) {
+TEST_P(EventProcessorTest, ModalWindowSetCaptureUnrelatedWindow) {
   std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3));
   std::unique_ptr<ServerWindow> w2 = CreateChildWindow(viz::FrameSinkId(1, 4));
   std::unique_ptr<ServerWindow> w3 = CreateChildWindow(viz::FrameSinkId(1, 5));
@@ -1986,7 +1985,7 @@
 }
 
 // Tests that setting capture fails when there is a system modal window.
-TEST_P(EventDispatcherTest, ModalWindowSystemSetCapture) {
+TEST_P(EventProcessorTest, ModalWindowSystemSetCapture) {
   std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3));
   std::unique_ptr<ServerWindow> w2 = CreateChildWindow(viz::FrameSinkId(1, 4));
 
@@ -2002,7 +2001,7 @@
 }
 
 // Tests having multiple system modal windows.
-TEST_P(EventDispatcherTest, ModalWindowMultipleSystemModals) {
+TEST_P(EventProcessorTest, ModalWindowMultipleSystemModals) {
   std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3));
   std::unique_ptr<ServerWindow> w2 = CreateChildWindow(viz::FrameSinkId(1, 4));
   std::unique_ptr<ServerWindow> w3 = CreateChildWindow(viz::FrameSinkId(1, 5));
@@ -2047,7 +2046,7 @@
   EXPECT_EQ(nullptr, GetActiveSystemModalWindow());
 }
 
-TEST_P(EventDispatcherTest, CaptureNotResetOnParentChange) {
+TEST_P(EventProcessorTest, CaptureNotResetOnParentChange) {
   std::unique_ptr<ServerWindow> w1 = CreateChildWindow(viz::FrameSinkId(1, 3));
   w1->set_event_targeting_policy(mojom::EventTargetingPolicy::DESCENDANTS_ONLY);
   std::unique_ptr<ServerWindow> w11 =
@@ -2065,7 +2064,7 @@
       ui::ET_MOUSE_PRESSED, gfx::Point(15, 15), gfx::Point(15, 15),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(event_dispatcher(), mouse_pressed,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
   event_dispatcher()->SetCaptureWindow(w11.get(), kClientAreaId);
 
   std::unique_ptr<DispatchedEventDetails> details =
@@ -2079,15 +2078,14 @@
   w2->Add(w11.get());
   EXPECT_TRUE(IsMouseButtonDown());
   EXPECT_EQ(w11.get(),
-            EventDispatcherTestApi(event_dispatcher()).capture_window());
+            EventProcessorTestApi(event_dispatcher()).capture_window());
 }
 
-TEST_P(EventDispatcherTest, ChangeCaptureFromClientToNonclient) {
+TEST_P(EventProcessorTest, ChangeCaptureFromClientToNonclient) {
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
   event_dispatcher()->SetCaptureWindow(child.get(), kNonclientAreaId);
-  EXPECT_EQ(kNonclientAreaId,
-            event_dispatcher()->capture_window_client_id());
+  EXPECT_EQ(kNonclientAreaId, event_dispatcher()->capture_window_client_id());
   EXPECT_EQ(nullptr, test_event_dispatcher_delegate()->lost_capture_window());
   event_dispatcher()->SetCaptureWindow(child.get(), kClientAreaId);
   // Changing capture from client to non-client should notify the delegate.
@@ -2098,7 +2096,7 @@
   EXPECT_EQ(kClientAreaId, event_dispatcher()->capture_window_client_id());
 }
 
-TEST_P(EventDispatcherTest, MoveMouseFromNoTargetToValidTarget) {
+TEST_P(EventProcessorTest, MoveMouseFromNoTargetToValidTarget) {
   ServerWindow* root = root_window();
   root->set_event_targeting_policy(
       mojom::EventTargetingPolicy::DESCENDANTS_ONLY);
@@ -2127,7 +2125,7 @@
                      tests, arraysize(tests));
 }
 
-TEST_P(EventDispatcherTest, NoTargetToTargetWithMouseDown) {
+TEST_P(EventProcessorTest, NoTargetToTargetWithMouseDown) {
   ServerWindow* root = root_window();
   root->set_event_targeting_policy(
       mojom::EventTargetingPolicy::DESCENDANTS_ONLY);
@@ -2163,7 +2161,7 @@
                      tests, arraysize(tests));
 }
 
-TEST_P(EventDispatcherTest, DontSendExitToSameClientWhenCaptureChanges) {
+TEST_P(EventProcessorTest, DontSendExitToSameClientWhenCaptureChanges) {
   ServerWindow* root = root_window();
   root->set_event_targeting_policy(
       mojom::EventTargetingPolicy::DESCENDANTS_ONLY);
@@ -2198,7 +2196,7 @@
   EXPECT_FALSE(test_event_dispatcher_delegate()->has_queued_events());
 }
 
-TEST_P(EventDispatcherTest, MousePointerClearedOnDestroy) {
+TEST_P(EventProcessorTest, MousePointerClearedOnDestroy) {
   root_window()->set_event_targeting_policy(
       mojom::EventTargetingPolicy::DESCENDANTS_ONLY);
   std::unique_ptr<ServerWindow> c1 = CreateChildWindow(viz::FrameSinkId(1, 3));
@@ -2210,14 +2208,14 @@
       ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(15, 15), gfx::Point(15, 15),
                      base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0));
   DispatchEvent(event_dispatcher(), move_event,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   EXPECT_EQ(c1.get(), event_dispatcher()->mouse_cursor_source_window());
   c1.reset();
   EXPECT_EQ(nullptr, event_dispatcher()->mouse_cursor_source_window());
 }
 
-TEST_P(EventDispatcherTest, LocationHonorsTransform) {
+TEST_P(EventProcessorTest, LocationHonorsTransform) {
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
 
@@ -2233,7 +2231,7 @@
       ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), gfx::Point(20, 25),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(event_dispatcher(), ui_event,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   std::unique_ptr<DispatchedEventDetails> details =
       test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
@@ -2248,7 +2246,7 @@
   EXPECT_EQ(gfx::Point(5, 7), dispatched_event->location());
 }
 
-TEST_P(EventDispatcherTest, MouseMovementsShowCursor) {
+TEST_P(EventProcessorTest, MouseMovementsShowCursor) {
   EXPECT_EQ(base::Optional<bool>(),
             test_event_dispatcher_delegate()->last_cursor_visibility());
 
@@ -2256,76 +2254,76 @@
       ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(11, 11), gfx::Point(11, 11),
                      base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0));
   DispatchEvent(event_dispatcher(), move1,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   EXPECT_EQ(base::Optional<bool>(true),
             test_event_dispatcher_delegate()->last_cursor_visibility());
 }
 
-TEST_P(EventDispatcherTest, KeyDoesntHideCursorWithNoList) {
+TEST_P(EventProcessorTest, KeyDoesntHideCursorWithNoList) {
   // In the case of mus, we don't send a list to the window server so ensure we
   // don't hide the cursor in this mode.
-  TestEventDispatcherDelegate* event_dispatcher_delegate =
+  TestEventProcessorDelegate* event_dispatcher_delegate =
       test_event_dispatcher_delegate();
   EXPECT_EQ(base::Optional<bool>(),
             event_dispatcher_delegate->last_cursor_visibility());
 
-  // Set focused window for EventDispatcher dispatches key events.
+  // Set focused window for EventProcessor dispatches key events.
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
-  event_dispatcher_delegate->SetFocusedWindowFromEventDispatcher(child.get());
+  event_dispatcher_delegate->SetFocusedWindowFromEventProcessor(child.get());
 
   ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
   DispatchEvent(event_dispatcher(), key,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   EXPECT_EQ(base::Optional<bool>(),
             event_dispatcher_delegate->last_cursor_visibility());
 }
 
-TEST_P(EventDispatcherTest, KeyDoesntHideCursorOnMatch) {
+TEST_P(EventProcessorTest, KeyDoesntHideCursorOnMatch) {
   // In the case of mash, we send a list of keys which don't hide the cursor.
   std::vector<ui::mojom::EventMatcherPtr> matchers;
   matchers.push_back(BuildKeyMatcher(ui::mojom::KeyboardCode::A));
   event_dispatcher()->SetKeyEventsThatDontHideCursor(std::move(matchers));
 
-  // Set focused window for EventDispatcher dispatches key events.
-  TestEventDispatcherDelegate* event_dispatcher_delegate =
+  // Set focused window for EventProcessor dispatches key events.
+  TestEventProcessorDelegate* event_dispatcher_delegate =
       test_event_dispatcher_delegate();
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
-  event_dispatcher_delegate->SetFocusedWindowFromEventDispatcher(child.get());
+  event_dispatcher_delegate->SetFocusedWindowFromEventProcessor(child.get());
 
   ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
   DispatchEvent(event_dispatcher(), key,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   EXPECT_EQ(base::Optional<bool>(),
             event_dispatcher_delegate->last_cursor_visibility());
 }
 
-TEST_P(EventDispatcherTest, KeyHidesCursorOnNoMatch) {
+TEST_P(EventProcessorTest, KeyHidesCursorOnNoMatch) {
   // In the case of mash, we send a list of keys which don't hide the cursor.
   std::vector<ui::mojom::EventMatcherPtr> matchers;
   matchers.push_back(BuildKeyMatcher(ui::mojom::KeyboardCode::B));
   event_dispatcher()->SetKeyEventsThatDontHideCursor(std::move(matchers));
 
-  // Set focused window for EventDispatcher dispatches key events.
-  TestEventDispatcherDelegate* event_dispatcher_delegate =
+  // Set focused window for EventProcessor dispatches key events.
+  TestEventProcessorDelegate* event_dispatcher_delegate =
       test_event_dispatcher_delegate();
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
-  event_dispatcher_delegate->SetFocusedWindowFromEventDispatcher(child.get());
+  event_dispatcher_delegate->SetFocusedWindowFromEventProcessor(child.get());
 
   ui::KeyEvent key(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
   DispatchEvent(event_dispatcher(), key,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   EXPECT_EQ(base::Optional<bool>(false),
             event_dispatcher_delegate->last_cursor_visibility());
 }
 
-TEST_P(EventDispatcherTest, ChildModal) {
+TEST_P(EventProcessorTest, ChildModal) {
   std::unique_ptr<ServerWindow> modal_parent =
       CreateChildWindow(viz::FrameSinkId(1, 3));
   std::unique_ptr<ServerWindow> child_modal_window =
@@ -2342,7 +2340,7 @@
       ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), gfx::Point(20, 25),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(event_dispatcher(), press_event,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   // As the event falls over |modal_parent|, but there is a CHILD_MODAL window,
   // the event is blocked and the delegate notified.
@@ -2351,7 +2349,7 @@
             test_event_dispatcher_delegate()->window_that_blocked_event());
 }
 
-TEST_P(EventDispatcherTest, DontCancelWhenMovedToSeparateDisplay) {
+TEST_P(EventProcessorTest, DontCancelWhenMovedToSeparateDisplay) {
   TestServerWindowDelegate window_delegate2(viz_host_proxy());
   ServerWindow root2(&window_delegate2, viz::FrameSinkId(1, 100));
   root2.set_is_activation_parent(true);
@@ -2368,7 +2366,7 @@
 }
 
 // Tests that setting capture to a window unrelated to a modal parent works.
-TEST_P(EventDispatcherTest, MouseCursorSourceWindowChangesWithSystemModal) {
+TEST_P(EventProcessorTest, MouseCursorSourceWindowChangesWithSystemModal) {
   BlockingContainers blocking_containers;
   blocking_containers.system_modal_container = root_window();
   event_dispatcher()->modal_window_controller()->SetBlockingContainers(
@@ -2389,17 +2387,17 @@
       ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(11, 11), gfx::Point(11, 11),
                      base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0));
   DispatchEvent(event_dispatcher(), move,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   EXPECT_EQ(nullptr, event_dispatcher()->mouse_cursor_source_window());
 
   event_dispatcher()->UpdateCursorProviderByLastKnownLocation();
   RunTasks();
-  // EventDispatcher fallsback to the root incase of invalid window.
+  // EventProcessor fallsback to the root incase of invalid window.
   EXPECT_EQ(root_window(), event_dispatcher()->mouse_cursor_source_window());
 }
 
-TEST_P(EventDispatcherTest, DontQueryWhileMouseIsDown) {
+TEST_P(EventProcessorTest, DontQueryWhileMouseIsDown) {
   // This test is easier to write with async event processing.
   if (!is_event_processing_async())
     return;
@@ -2414,7 +2412,7 @@
       ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), gfx::Point(20, 25),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(event_dispatcher(), press_event,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
   ASSERT_FALSE(event_dispatcher()->IsProcessingEvent());
 
   const ui::PointerEvent move_event(ui::MouseEvent(
@@ -2422,11 +2420,11 @@
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   event_dispatcher()->ProcessEvent(move_event,
                                    EventLocationFromEvent(move_event),
-                                   EventDispatcher::AcceleratorMatchPhase::ANY);
+                                   EventProcessor::AcceleratorMatchPhase::ANY);
   EXPECT_FALSE(event_dispatcher()->IsProcessingEvent());
 }
 
-TEST_P(EventDispatcherVizTargeterTest, ProcessEvent) {
+TEST_P(EventProcessorVizTargeterTest, ProcessEvent) {
   std::unique_ptr<ServerWindow> child =
       CreateChildWindow(viz::FrameSinkId(1, 3));
 
@@ -2450,7 +2448,7 @@
       ui::ET_MOUSE_PRESSED, gfx::Point(20, 25), gfx::Point(20, 25),
       base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
   DispatchEvent(event_dispatcher(), ui_event,
-                EventDispatcher::AcceleratorMatchPhase::ANY);
+                EventProcessor::AcceleratorMatchPhase::ANY);
 
   std::unique_ptr<DispatchedEventDetails> details =
       test_event_dispatcher_delegate()->GetAndAdvanceDispatchedEventDetails();
@@ -2465,9 +2463,9 @@
   EXPECT_EQ(gfx::Point(10, 15), dispatched_event->location());
 }
 
-INSTANTIATE_TEST_CASE_P(/* no prefix */, EventDispatcherTest, testing::Bool());
+INSTANTIATE_TEST_CASE_P(/* no prefix */, EventProcessorTest, testing::Bool());
 INSTANTIATE_TEST_CASE_P(/* no prefix */,
-                        EventDispatcherVizTargeterTest,
+                        EventProcessorVizTargeterTest,
                         testing::Bool());
 
 }  // namespace test
diff --git a/services/ui/ws/test_utils.cc b/services/ui/ws/test_utils.cc
index b4ec8b1..9fc7c44 100644
--- a/services/ui/ws/test_utils.cc
+++ b/services/ui/ws/test_utils.cc
@@ -170,28 +170,27 @@
   tree_->StopPointerWatcher();
 }
 
-// EventDispatcherTestApi  ----------------------------------------------------
+// EventProcessorTestApi  ----------------------------------------------------
 
-bool EventDispatcherTestApi::IsWindowPointerTarget(
+bool EventProcessorTestApi::IsWindowPointerTarget(
     const ServerWindow* window) const {
-  for (const auto& pair : ed_->pointer_targets_) {
+  for (const auto& pair : ep_->pointer_targets_) {
     if (pair.second.window == window)
       return true;
   }
   return false;
 }
 
-int EventDispatcherTestApi::NumberPointerTargetsForWindow(
-    ServerWindow* window) {
+int EventProcessorTestApi::NumberPointerTargetsForWindow(ServerWindow* window) {
   int count = 0;
-  for (const auto& pair : ed_->pointer_targets_)
+  for (const auto& pair : ep_->pointer_targets_)
     if (pair.second.window == window)
       count++;
   return count;
 }
 
-bool EventDispatcherTestApi::IsObservingWindow(ServerWindow* window) {
-  return ed_->observed_windows_.count(window) > 0;
+bool EventProcessorTestApi::IsObservingWindow(ServerWindow* window) {
+  return ep_->observed_windows_.count(window) > 0;
 }
 
 // TestDisplayBinding ---------------------------------------------------------
@@ -315,6 +314,12 @@
   tracker_.OnEmbed(std::move(root), drawn);
 }
 
+void TestWindowTreeClient::OnEmbedFromToken(
+    const base::UnguessableToken& token,
+    ::ui::mojom::WindowDataPtr root,
+    int64_t display_id,
+    const base::Optional<viz::LocalSurfaceId>& local_surface_id) {}
+
 void TestWindowTreeClient::OnEmbeddedAppDisconnected(Id window) {
   tracker_.OnEmbeddedAppDisconnected(window);
 }
diff --git a/services/ui/ws/test_utils.h b/services/ui/ws/test_utils.h
index 2477d94..b25d3136 100644
--- a/services/ui/ws/test_utils.h
+++ b/services/ui/ws/test_utils.h
@@ -24,7 +24,7 @@
 #include "services/ui/ws/display.h"
 #include "services/ui/ws/display_binding.h"
 #include "services/ui/ws/drag_controller.h"
-#include "services/ui/ws/event_dispatcher.h"
+#include "services/ui/ws/event_processor.h"
 #include "services/ui/ws/event_targeter.h"
 #include "services/ui/ws/gpu_host.h"
 #include "services/ui/ws/platform_display.h"
@@ -167,26 +167,26 @@
 
 // -----------------------------------------------------------------------------
 
-class EventDispatcherTestApi {
+class EventProcessorTestApi {
  public:
-  explicit EventDispatcherTestApi(EventDispatcher* ed) : ed_(ed) {}
-  ~EventDispatcherTestApi() {}
+  explicit EventProcessorTestApi(EventProcessor* ep) : ep_(ep) {}
+  ~EventProcessorTestApi() {}
 
-  bool AreAnyPointersDown() const { return ed_->AreAnyPointersDown(); }
-  bool is_mouse_button_down() const { return ed_->mouse_button_down_; }
+  bool AreAnyPointersDown() const { return ep_->AreAnyPointersDown(); }
+  bool is_mouse_button_down() const { return ep_->mouse_button_down_; }
   bool IsWindowPointerTarget(const ServerWindow* window) const;
   int NumberPointerTargetsForWindow(ServerWindow* window);
   ModalWindowController* modal_window_controller() const {
-    return &ed_->modal_window_controller_;
+    return &ep_->modal_window_controller_;
   }
-  ServerWindow* capture_window() { return ed_->capture_window_; }
-  EventTargeter* event_targeter() { return ed_->event_targeter_.get(); }
+  ServerWindow* capture_window() { return ep_->capture_window_; }
+  EventTargeter* event_targeter() { return ep_->event_targeter_.get(); }
   bool IsObservingWindow(ServerWindow* window);
 
  private:
-  EventDispatcher* ed_;
+  EventProcessor* ep_;
 
-  DISALLOW_COPY_AND_ASSIGN(EventDispatcherTestApi);
+  DISALLOW_COPY_AND_ASSIGN(EventProcessorTestApi);
 };
 
 // -----------------------------------------------------------------------------
@@ -473,6 +473,11 @@
       Id focused_window_id,
       bool drawn,
       const base::Optional<viz::LocalSurfaceId>& local_surface_id) override;
+  void OnEmbedFromToken(
+      const base::UnguessableToken& token,
+      mojom::WindowDataPtr root,
+      int64_t display_id,
+      const base::Optional<viz::LocalSurfaceId>& local_surface_id) override;
   void OnEmbeddedAppDisconnected(Id window) override;
   void OnUnembed(Id window_id) override;
   void OnCaptureChanged(Id new_capture_window_id,
diff --git a/services/ui/ws/window_manager_client_unittest.cc b/services/ui/ws/window_manager_client_unittest.cc
index 33c6c85..036187a 100644
--- a/services/ui/ws/window_manager_client_unittest.cc
+++ b/services/ui/ws/window_manager_client_unittest.cc
@@ -15,11 +15,14 @@
 #include "services/ui/ws/window_server_test_base.h"
 #include "ui/aura/client/transient_window_client.h"
 #include "ui/aura/env.h"
+#include "ui/aura/mus/embed_root.h"
+#include "ui/aura/mus/embed_root_delegate.h"
 #include "ui/aura/mus/window_port_mus.h"
 #include "ui/aura/mus/window_tree_client.h"
 #include "ui/aura/mus/window_tree_client_delegate.h"
 #include "ui/aura/mus/window_tree_host_mus.h"
 #include "ui/aura/mus/window_tree_host_mus_init_params.h"
+#include "ui/aura/test/mus/change_completion_waiter.h"
 #include "ui/aura/test/mus/test_window_manager_delegate.h"
 #include "ui/aura/test/mus/window_tree_client_private.h"
 #include "ui/aura/window.h"
@@ -747,5 +750,126 @@
             transient_window_client->GetTransientParent(transient_in_wm));
 }
 
+class TestEmbedRootDelegate : public aura::EmbedRootDelegate {
+ public:
+  TestEmbedRootDelegate() {}
+
+  void SetQuitClosure(base::Closure closure) { quit_closure_ = closure; }
+
+  const base::UnguessableToken& token() const { return token_; }
+  aura::Window* embed_window() { return embed_window_; }
+  bool got_unembed() const { return got_unembed_; }
+
+  // EmbedRootDelegate:
+  void OnEmbedTokenAvailable(const base::UnguessableToken& token) override {
+    token_ = token;
+    quit_closure_.Run();
+  }
+  void OnEmbed(aura::Window* window) override {
+    embed_window_ = window;
+    quit_closure_.Run();
+  }
+  void OnUnembed() override {
+    got_unembed_ = true;
+    quit_closure_.Run();
+  }
+
+ private:
+  base::Closure quit_closure_;
+  aura::Window* embed_window_ = nullptr;
+  bool got_unembed_ = false;
+
+  base::UnguessableToken token_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestEmbedRootDelegate);
+};
+
+// This test exercises multiple EmbedRoots for a single client.
+TEST_F(WindowServerTest, EmbedRoot) {
+  EstablishConnectionViaFactoryDelegate delegate(window_manager());
+  set_window_manager_delegate(&delegate);
+  std::unique_ptr<aura::WindowTreeClient> second_client =
+      aura::WindowTreeClient::CreateForWindowTreeFactory(connector(), this,
+                                                         false);
+
+  // Create a visible window so that the window-manager has a different number
+  // of initial windows than the client.
+  NewVisibleWindow(GetFirstWMRoot(), window_manager(),
+                   aura::WindowMusType::EMBED_IN_OWNER);
+  std::vector<std::unique_ptr<aura::EmbedRoot>> embed_roots;
+  for (int i = 0; i < 2; ++i) {
+    // Create a new EmbedRoot and wait for the token from the server.
+    TestEmbedRootDelegate test_embed_root_delegate;
+    std::unique_ptr<aura::EmbedRoot> embed_root =
+        second_client->CreateEmbedRoot(&test_embed_root_delegate);
+    base::RunLoop run_loop1;
+    test_embed_root_delegate.SetQuitClosure(run_loop1.QuitClosure());
+    run_loop1.Run();
+    ASSERT_TRUE(test_embed_root_delegate.token());
+
+    // Embed the token from the window manager's connection and wait for
+    // OnEmbed().
+    aura::Window* embed_window_in_wm =
+        NewVisibleWindow(GetFirstWMRoot(), window_manager(),
+                         aura::WindowMusType::EMBED_IN_OWNER);
+    window_manager()->EmbedUsingToken(embed_window_in_wm,
+                                      test_embed_root_delegate.token(), 0u,
+                                      base::DoNothing());
+
+    base::RunLoop run_loop2;
+    test_embed_root_delegate.SetQuitClosure(run_loop2.QuitClosure());
+    run_loop2.Run();
+    ASSERT_TRUE(test_embed_root_delegate.embed_window());
+    EXPECT_NE(test_embed_root_delegate.embed_window(), embed_window_in_wm);
+    // Create a child of the embed root's window in |second_client|. Then wait
+    // for completion to ensure all is well.
+    NewVisibleWindow(test_embed_root_delegate.embed_window(),
+                     second_client.get());
+    aura::test::WaitForAllChangesToComplete(second_client.get());
+    embed_roots.push_back(std::move(embed_root));
+  }
+}
+
+TEST_F(WindowServerTest, DeleteEmbedRoot) {
+  EstablishConnectionViaFactoryDelegate delegate(window_manager());
+  set_window_manager_delegate(&delegate);
+  std::unique_ptr<aura::WindowTreeClient> second_client =
+      aura::WindowTreeClient::CreateForWindowTreeFactory(connector(), this,
+                                                         false);
+
+  // Create a new EmbedRoot and wait for the token from the server.
+  TestEmbedRootDelegate test_embed_root_delegate;
+  std::unique_ptr<aura::EmbedRoot> embed_root =
+      second_client->CreateEmbedRoot(&test_embed_root_delegate);
+  base::RunLoop run_loop1;
+  test_embed_root_delegate.SetQuitClosure(run_loop1.QuitClosure());
+  run_loop1.Run();
+  ASSERT_TRUE(test_embed_root_delegate.token());
+
+  // Embed the token from the window manager's connection and wait for
+  // OnEmbed().
+  aura::Window* embed_window_in_wm = NewVisibleWindow(
+      GetFirstWMRoot(), window_manager(), aura::WindowMusType::EMBED_IN_OWNER);
+  window_manager()->EmbedUsingToken(embed_window_in_wm,
+                                    test_embed_root_delegate.token(), 0u,
+                                    base::DoNothing());
+
+  base::RunLoop run_loop2;
+  test_embed_root_delegate.SetQuitClosure(run_loop2.QuitClosure());
+  run_loop2.Run();
+  ASSERT_TRUE(test_embed_root_delegate.embed_window());
+  aura::WindowTracker embed_root_window_tracker;
+  embed_root_window_tracker.Add(test_embed_root_delegate.embed_window());
+
+  // Delete the embed root (from the window-manager).
+  delete embed_window_in_wm;
+  base::RunLoop run_loop3;
+  test_embed_root_delegate.SetQuitClosure(run_loop3.QuitClosure());
+  run_loop3.Run();
+  EXPECT_TRUE(test_embed_root_delegate.got_unembed());
+  // The EmbedRoot's window should still exist in the embedded client.
+  EXPECT_FALSE(embed_root_window_tracker.windows().empty());
+}
+
 }  // namespace ws
 }  // namespace ui
diff --git a/services/ui/ws/window_manager_state.cc b/services/ui/ws/window_manager_state.cc
index b550a14c..cccdb561 100644
--- a/services/ui/ws/window_manager_state.cc
+++ b/services/ui/ws/window_manager_state.cc
@@ -164,12 +164,12 @@
 // details.
 struct WindowManagerState::EventTask {
   enum class Type {
-    // ProcessEvent() was called while waiting on a client or EventDispatcher
+    // ProcessEvent() was called while waiting on a client or EventProcessor
     // to complete processing. |event| is non-null and |processed_target| is
     // null.
     kEvent,
 
-    // In certain situations EventDispatcher::ProcessEvent() generates more than
+    // In certain situations EventProcessor::ProcessEvent() generates more than
     // one event. When that happens, |kProcessedEvent| is used for all events
     // after the first. For example, a move may result in an exit for one
     // Window and and an enter for another Window. The event generated for the
@@ -178,7 +178,7 @@
     kProcessedEvent,
 
     // ScheduleCallbackWhenDoneProcessingEvents() is called while waiting on
-    // a client or EventDispatcher. |event| and |processed_target| are null.
+    // a client or EventProcessor. |event| and |processed_target| are null.
     kClosure
   };
 
@@ -204,7 +204,7 @@
 
 WindowManagerState::WindowManagerState(WindowTree* window_tree)
     : window_tree_(window_tree),
-      event_dispatcher_(this),
+      event_processor_(this),
       cursor_state_(window_tree_->display_manager(), this) {
   frame_decoration_values_ = mojom::FrameDecorationValues::New();
   frame_decoration_values_->max_title_bar_button_width = 0u;
@@ -239,7 +239,7 @@
 bool WindowManagerState::SetCapture(ServerWindow* window,
                                     ClientSpecificId client_id) {
   if (capture_window() == window &&
-      client_id == event_dispatcher_.capture_window_client_id()) {
+      client_id == event_processor_.capture_window_client_id()) {
     return true;
   }
 #if DCHECK_IS_ON()
@@ -249,11 +249,11 @@
     DCHECK(display_root && display_root->window_manager_state() == this);
   }
 #endif
-  return event_dispatcher_.SetCaptureWindow(window, client_id);
+  return event_processor_.SetCaptureWindow(window, client_id);
 }
 
 void WindowManagerState::ReleaseCaptureBlockedByAnyModalWindow() {
-  event_dispatcher_.ReleaseCaptureBlockedByAnyModalWindow();
+  event_processor_.ReleaseCaptureBlockedByAnyModalWindow();
 }
 
 void WindowManagerState::SetCursorLocation(const gfx::Point& display_pixels,
@@ -270,7 +270,7 @@
 
 void WindowManagerState::SetKeyEventsThatDontHideCursor(
     std::vector<::ui::mojom::EventMatcherPtr> dont_hide_cursor_list) {
-  event_dispatcher()->SetKeyEventsThatDontHideCursor(
+  event_processor()->SetKeyEventsThatDontHideCursor(
       std::move(dont_hide_cursor_list));
 }
 
@@ -297,22 +297,22 @@
     return;
   }
 
-  event_dispatcher_.SetDragDropSourceWindow(drag_source, window,
-                                            source_connection, drag_pointer,
-                                            drag_data, drag_operation);
+  event_processor_.SetDragDropSourceWindow(drag_source, window,
+                                           source_connection, drag_pointer,
+                                           drag_data, drag_operation);
 }
 
 void WindowManagerState::CancelDragDrop() {
-  event_dispatcher_.CancelDragDrop();
+  event_processor_.CancelDragDrop();
 }
 
 void WindowManagerState::EndDragDrop() {
-  event_dispatcher_.EndDragDrop();
-  UpdateNativeCursorFromDispatcher();
+  event_processor_.EndDragDrop();
+  UpdateNativeCursorFromEventProcessor();
 }
 
 void WindowManagerState::AddSystemModalWindow(ServerWindow* window) {
-  event_dispatcher_.AddSystemModalWindow(window);
+  event_processor_.AddSystemModalWindow(window);
 }
 
 void WindowManagerState::DeleteWindowManagerDisplayRoot(
@@ -336,7 +336,7 @@
 }
 
 void WindowManagerState::OnWillDestroyTree(WindowTree* tree) {
-  event_dispatcher_.OnWillDestroyDragTargetConnection(tree);
+  event_processor_.OnWillDestroyDragTargetConnection(tree);
 
   if (!in_flight_event_dispatch_details_ ||
       in_flight_event_dispatch_details_->tree != tree)
@@ -379,7 +379,7 @@
 
 bool WindowManagerState::IsProcessingEvent() const {
   return in_flight_event_dispatch_details_ ||
-         event_dispatcher_.IsProcessingEvent();
+         event_processor_.IsProcessingEvent();
 }
 
 void WindowManagerState::ScheduleCallbackWhenDoneProcessingEvents(
@@ -410,9 +410,9 @@
     DCHECK(details->event->IsKeyEvent());
     if (!properties.empty())
       details->event->AsKeyEvent()->SetProperties(properties);
-    event_dispatcher_.ProcessEvent(
+    event_processor_.ProcessEvent(
         *details->event, EventLocation(details->display_id),
-        EventDispatcher::AcceleratorMatchPhase::POST_ONLY);
+        EventProcessor::AcceleratorMatchPhase::POST_ONLY);
   } else {
     // We're not going to process the event any further, notify event observers.
     // We don't do this first to ensure we don't send an event twice to clients.
@@ -502,11 +502,11 @@
 void WindowManagerState::ProcessEventImpl(const ui::Event& event,
                                           const EventLocation& event_location) {
   DCHECK(!in_flight_event_dispatch_details_ &&
-         !event_dispatcher_.IsProcessingEvent());
+         !event_processor_.IsProcessingEvent());
   // Debug accelerators are always checked and don't interfere with processing.
   ProcessDebugAccelerator(event, event_location.display_id);
-  event_dispatcher_.ProcessEvent(event, event_location,
-                                 EventDispatcher::AcceleratorMatchPhase::ANY);
+  event_processor_.ProcessEvent(event, event_location,
+                                EventProcessor::AcceleratorMatchPhase::ANY);
 }
 
 void WindowManagerState::QueueEvent(
@@ -534,7 +534,7 @@
     target = GetWindowManagerRootForDisplayRoot(target);
 
   if (event.IsMousePointerEvent())
-    UpdateNativeCursorFromDispatcher();
+    UpdateNativeCursorFromEventProcessor();
 
   WindowTree* tree = window_server()->GetTreeWithId(client_id);
   DCHECK(tree);
@@ -586,7 +586,7 @@
                  << display_root->root()->GetDebugWindowHierarchy();
     }
   }
-  ServerWindow* focused_window = GetFocusedWindowForEventDispatcher(display_id);
+  ServerWindow* focused_window = GetFocusedWindowForEventProcessor(display_id);
   LOG(ERROR) << "Focused window: "
              << (focused_window ? focused_window->frame_sink_id().ToString()
                                 : "(null)");
@@ -697,7 +697,7 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// EventDispatcherDelegate:
+// EventProcessorDelegate:
 
 void WindowManagerState::OnAccelerator(uint32_t accelerator_id,
                                        int64_t display_id,
@@ -716,12 +716,12 @@
   window_tree_->OnAccelerator(accelerator_id, event, std::move(ack_callback));
 }
 
-void WindowManagerState::SetFocusedWindowFromEventDispatcher(
+void WindowManagerState::SetFocusedWindowFromEventProcessor(
     ServerWindow* new_focused_window) {
   window_server()->SetFocusedWindow(new_focused_window);
 }
 
-ServerWindow* WindowManagerState::GetFocusedWindowForEventDispatcher(
+ServerWindow* WindowManagerState::GetFocusedWindowForEventProcessor(
     int64_t display_id) {
   ServerWindow* focused_window = window_server()->GetFocusedWindow();
   if (focused_window)
@@ -767,8 +767,8 @@
   platform_display_with_capture_ = nullptr;
 }
 
-void WindowManagerState::UpdateNativeCursorFromDispatcher() {
-  const ui::CursorData cursor = event_dispatcher_.GetCurrentMouseCursor();
+void WindowManagerState::UpdateNativeCursorFromEventProcessor() {
+  const ui::CursorData cursor = event_processor_.GetCurrentMouseCursor();
   cursor_state_.SetCurrentWindowCursor(cursor);
 }
 
@@ -919,7 +919,7 @@
   window_server()->SendToPointerWatchers(event, nullptr, /* window */
                                          nullptr /* ignore_tree */, display_id);
   if (event.IsMousePointerEvent())
-    UpdateNativeCursorFromDispatcher();
+    UpdateNativeCursorFromEventProcessor();
 }
 
 ServerWindow* WindowManagerState::GetFallbackTargetForEventBlockedByModal(
diff --git a/services/ui/ws/window_manager_state.h b/services/ui/ws/window_manager_state.h
index 7c4fb35..d22948d 100644
--- a/services/ui/ws/window_manager_state.h
+++ b/services/ui/ws/window_manager_state.h
@@ -18,8 +18,8 @@
 #include "services/ui/public/interfaces/display_manager.mojom.h"
 #include "services/ui/ws/cursor_state.h"
 #include "services/ui/ws/cursor_state_delegate.h"
-#include "services/ui/ws/event_dispatcher.h"
-#include "services/ui/ws/event_dispatcher_delegate.h"
+#include "services/ui/ws/event_processor.h"
+#include "services/ui/ws/event_processor_delegate.h"
 #include "services/ui/ws/server_window_observer.h"
 #include "services/ui/ws/window_server.h"
 
@@ -42,7 +42,7 @@
 // Manages state specific to a WindowManager that is shared across displays.
 // WindowManagerState is owned by the WindowTree the window manager is
 // associated with.
-class WindowManagerState : public EventDispatcherDelegate,
+class WindowManagerState : public EventProcessorDelegate,
                            public ServerWindowObserver,
                            public CursorStateDelegate {
  public:
@@ -63,9 +63,9 @@
   }
 
   bool SetCapture(ServerWindow* window, ClientSpecificId client_id);
-  ServerWindow* capture_window() { return event_dispatcher_.capture_window(); }
+  ServerWindow* capture_window() { return event_processor_.capture_window(); }
   const ServerWindow* capture_window() const {
-    return event_dispatcher_.capture_window();
+    return event_processor_.capture_window();
   }
 
   void ReleaseCaptureBlockedByAnyModalWindow();
@@ -92,9 +92,9 @@
   // Deletes the WindowManagerDisplayRoot whose root is |display_root|.
   void DeleteWindowManagerDisplayRoot(ServerWindow* display_root);
 
-  // TODO(sky): EventDispatcher is really an implementation detail and should
+  // TODO(sky): EventProcessor is really an implementation detail and should
   // not be exposed.
-  EventDispatcher* event_dispatcher() { return &event_dispatcher_; }
+  EventProcessor* event_processor() { return &event_processor_; }
 
   CursorState& cursor_state() { return cursor_state_; }
 
@@ -199,7 +199,7 @@
   void OnEventAckTimeout(ClientSpecificId client_id);
 
   // Implemenation of processing an event with a match phase of all. This
-  // handles debug accelerators and forwards to EventDispatcher.
+  // handles debug accelerators and forwards to EventProcessor.
   void ProcessEventImpl(const Event& event,
                         const EventLocation& event_location);
 
@@ -246,16 +246,16 @@
 
   void AdjustEventLocation(int64_t display_id, LocatedEvent* event);
 
-  // EventDispatcherDelegate:
+  // EventProcessorDelegate:
   void OnAccelerator(uint32_t accelerator_id,
                      int64_t display_id,
                      const Event& event,
                      AcceleratorPhase phase) override;
-  void SetFocusedWindowFromEventDispatcher(ServerWindow* window) override;
-  ServerWindow* GetFocusedWindowForEventDispatcher(int64_t display_id) override;
+  void SetFocusedWindowFromEventProcessor(ServerWindow* window) override;
+  ServerWindow* GetFocusedWindowForEventProcessor(int64_t display_id) override;
   void SetNativeCapture(ServerWindow* window) override;
   void ReleaseNativeCapture() override;
-  void UpdateNativeCursorFromDispatcher() override;
+  void UpdateNativeCursorFromEventProcessor() override;
   void OnCaptureChanged(ServerWindow* new_capture,
                         ServerWindow* old_capture) override;
   void OnMouseCursorLocationChanged(const gfx::PointF& point,
@@ -308,7 +308,7 @@
   std::unique_ptr<InFlightEventDispatchDetails>
       in_flight_event_dispatch_details_;
 
-  EventDispatcher event_dispatcher_;
+  EventProcessor event_processor_;
 
   // PlatformDisplay that currently has capture.
   PlatformDisplay* platform_display_with_capture_ = nullptr;
diff --git a/services/ui/ws/window_manager_state_unittest.cc b/services/ui/ws/window_manager_state_unittest.cc
index 2bc7753..961734a 100644
--- a/services/ui/ws/window_manager_state_unittest.cc
+++ b/services/ui/ws/window_manager_state_unittest.cc
@@ -281,7 +281,7 @@
     mojom::EventMatcherPtr matcher = ui::CreateKeyMatcher(
         ui::mojom::KeyboardCode::W, ui::mojom::kEventFlagControlDown);
 
-    ASSERT_TRUE(window_manager_state()->event_dispatcher()->AddAccelerator(
+    ASSERT_TRUE(window_manager_state()->event_processor()->AddAccelerator(
         accelerator_id, std::move(matcher)));
   }
   TestChangeTracker* tracker = wm_client()->tracker();
@@ -351,7 +351,7 @@
     mojom::EventMatcherPtr matcher = ui::CreateKeyMatcher(
         ui::mojom::KeyboardCode::W, ui::mojom::kEventFlagControlDown);
 
-    ASSERT_TRUE(window_manager_state()->event_dispatcher()->AddAccelerator(
+    ASSERT_TRUE(window_manager_state()->event_processor()->AddAccelerator(
         accelerator_id, std::move(matcher)));
   }
   TestChangeTracker* tracker = wm_client()->tracker();
@@ -881,11 +881,11 @@
   // Setup steps already do hit-test for mouse cursor update so this should go
   // to the queue in EventTargeter.
   EventTargeterTestApi event_targeter_test_api(
-      EventDispatcherTestApi(window_manager_state()->event_dispatcher())
+      EventProcessorTestApi(window_manager_state()->event_processor())
           .event_targeter());
   EXPECT_TRUE(event_targeter_test_api.HasPendingQueries());
   // But no events have been generated, so IsProcessingEvent() should be false.
-  EXPECT_FALSE(window_manager_state()->event_dispatcher()->IsProcessingEvent());
+  EXPECT_FALSE(window_manager_state()->event_processor()->IsProcessingEvent());
   child_window->SetVisible(true);
   child_window->SetBounds(gfx::Rect(0, 0, 20, 20));
   child_window->parent()->SetCursor(ui::CursorData(ui::CursorType::kCopy));
@@ -899,7 +899,7 @@
   EXPECT_TRUE(test_api.is_event_tasks_empty());
   window_manager_state()->ProcessEvent(&move, 0);
   EXPECT_FALSE(test_api.tree_awaiting_input_ack());
-  EXPECT_TRUE(window_manager_state()->event_dispatcher()->IsProcessingEvent());
+  EXPECT_TRUE(window_manager_state()->event_processor()->IsProcessingEvent());
   EXPECT_TRUE(test_api.is_event_tasks_empty());
   task_runner_->RunUntilIdle();
   EXPECT_TRUE(test_api.is_event_tasks_empty());
diff --git a/services/ui/ws/window_server.cc b/services/ui/ws/window_server.cc
index 0550b18..fdf7d39 100644
--- a/services/ui/ws/window_server.cc
+++ b/services/ui/ws/window_server.cc
@@ -281,6 +281,12 @@
     tree_map_.erase(iter);
   }
 
+  base::EraseIf(scheduled_embeds_,
+                [&tree](const std::pair<base::UnguessableToken,
+                                        const WindowTreeAndWindowId&>& pair) {
+                  return (tree == pair.second.tree);
+                });
+
   // Notify remaining connections so that they can cleanup.
   for (auto& pair : tree_map_)
     pair.second->OnWillDestroyTree(tree);
@@ -313,6 +319,25 @@
   return nullptr;
 }
 
+base::UnguessableToken WindowServer::RegisterEmbedToken(
+    WindowTree* tree,
+    ClientSpecificId window_id) {
+  const base::UnguessableToken token = base::UnguessableToken::Create();
+  DCHECK(!scheduled_embeds_.count(token));
+  scheduled_embeds_[token] = {tree, window_id};
+  return token;
+}
+
+WindowTreeAndWindowId WindowServer::UnregisterEmbedToken(
+    const base::UnguessableToken& token) {
+  auto iter = scheduled_embeds_.find(token);
+  if (iter == scheduled_embeds_.end())
+    return {};
+  WindowTreeAndWindowId result = iter->second;
+  scheduled_embeds_.erase(iter);
+  return result;
+}
+
 void WindowServer::OnTreeMessagedClient(ClientSpecificId id) {
   if (current_operation_)
     current_operation_->MarkTreeAsMessaged(id);
@@ -744,9 +769,9 @@
   if (!display_root)
     return;
 
-  EventDispatcher* event_dispatcher =
-      display_root->window_manager_state()->event_dispatcher();
-  event_dispatcher->UpdateCursorProviderByLastKnownLocation();
+  EventProcessor* event_processor =
+      display_root->window_manager_state()->event_processor();
+  event_processor->UpdateCursorProviderByLastKnownLocation();
 }
 
 void WindowServer::UpdateNativeCursorIfOver(ServerWindow* window) {
@@ -755,12 +780,12 @@
   if (!display_root)
     return;
 
-  EventDispatcher* event_dispatcher =
-      display_root->window_manager_state()->event_dispatcher();
-  if (window != event_dispatcher->GetWindowForMouseCursor())
+  EventProcessor* event_processor =
+      display_root->window_manager_state()->event_processor();
+  if (window != event_processor->GetWindowForMouseCursor())
     return;
 
-  event_dispatcher->UpdateNonClientAreaForCurrentWindow();
+  event_processor->UpdateNonClientAreaForCurrentWindow();
 }
 
 void WindowServer::HandleTemporaryReferenceForNewSurface(
diff --git a/services/ui/ws/window_server.h b/services/ui/ws/window_server.h
index 4925a42..6be9d2d 100644
--- a/services/ui/ws/window_server.h
+++ b/services/ui/ws/window_server.h
@@ -12,6 +12,7 @@
 #include <string>
 #include <vector>
 
+#include "base/containers/flat_map.h"
 #include "base/macros.h"
 #include "base/optional.h"
 #include "components/viz/common/frame_sinks/begin_frame_source.h"
@@ -48,6 +49,11 @@
 
 enum class DisplayCreationConfig;
 
+struct WindowTreeAndWindowId {
+  WindowTree* tree = nullptr;
+  ClientSpecificId window_id = 0u;
+};
+
 // WindowServer manages the set of clients of the window server (all the
 // WindowTrees) as well as providing the root of the hierarchy.
 class WindowServer : public ServerWindowDelegate,
@@ -112,6 +118,17 @@
 
   size_t num_trees() const { return tree_map_.size(); }
 
+  // Creates and registers a token for use in a future embedding. |window_id|
+  // is the window_id portion of the ClientWindowId to use for the window in
+  // |tree|. |window_id| is validated during actual embed.
+  base::UnguessableToken RegisterEmbedToken(WindowTree* tree,
+                                            ClientSpecificId window_id);
+
+  // Unregisters the WindowTree associated with |token| and returns it. Returns
+  // null if RegisterEmbedToken() was not previously called for |token|.
+  WindowTreeAndWindowId UnregisterEmbedToken(
+      const base::UnguessableToken& token);
+
   OperationType current_operation_type() const {
     return current_operation_ ? current_operation_->type()
                               : OperationType::NONE;
@@ -410,6 +427,12 @@
 
   DisplayCreationConfig display_creation_config_;
 
+  // Tokens registered by ScheduleEmbedForExistingClient() that are removed when
+  // EmbedUsingToken() is called.
+  using ScheduledEmbeds =
+      base::flat_map<base::UnguessableToken, WindowTreeAndWindowId>;
+  ScheduledEmbeds scheduled_embeds_;
+
   DISALLOW_COPY_AND_ASSIGN(WindowServer);
 };
 
diff --git a/services/ui/ws/window_tree.cc b/services/ui/ws/window_tree.cc
index 7f6a13ba..1c6c3131 100644
--- a/services/ui/ws/window_tree.cc
+++ b/services/ui/ws/window_tree.cc
@@ -21,9 +21,9 @@
 #include "services/ui/ws/default_access_policy.h"
 #include "services/ui/ws/display.h"
 #include "services/ui/ws/display_manager.h"
-#include "services/ui/ws/event_dispatcher.h"
 #include "services/ui/ws/event_location.h"
 #include "services/ui/ws/event_matcher.h"
+#include "services/ui/ws/event_processor.h"
 #include "services/ui/ws/focus_controller.h"
 #include "services/ui/ws/frame_generator.h"
 #include "services/ui/ws/modal_window_controller.h"
@@ -163,7 +163,7 @@
   std::vector<const ServerWindow*> to_send;
   CHECK_EQ(1u, roots_.size());
   const ServerWindow* root = *roots_.begin();
-  GetUnknownWindowsFrom(root, &to_send);
+  GetUnknownWindowsFrom(root, &to_send, nullptr);
 
   Display* display = GetDisplay(root);
   int64_t display_id = display ? display->GetId() : display::kInvalidDisplayId;
@@ -437,7 +437,7 @@
         MakeClientWindowId(transport_container->min_container_id));
     all_containers.push_back(blocking_containers);
   }
-  window_manager_state_->event_dispatcher()
+  window_manager_state_->event_processor()
       ->modal_window_controller()
       ->SetBlockingContainers(all_containers);
   return true;
@@ -696,6 +696,7 @@
   if (!window_tree_client || !CanEmbed(window_id))
     return false;
   ServerWindow* window = GetWindowByClientId(window_id);
+  DCHECK(window);  // CanEmbed() returns false if no window.
   PrepareForEmbed(window);
   // mojom::kEmbedFlagEmbedderInterceptsEvents is inherited, otherwise an
   // embedder could effectively circumvent it by embedding itself.
@@ -708,6 +709,27 @@
   return true;
 }
 
+bool WindowTree::EmbedExistingTree(
+    const ClientWindowId& window_id,
+    const WindowTreeAndWindowId& tree_and_window_id,
+    const base::UnguessableToken& token) {
+  const ClientWindowId window_id_in_embedded(tree_and_window_id.tree->id(),
+                                             tree_and_window_id.window_id);
+  if (!CanEmbed(window_id) ||
+      !tree_and_window_id.tree->IsValidIdForNewWindow(window_id_in_embedded)) {
+    return false;
+  }
+  ServerWindow* window = GetWindowByClientId(window_id);
+  DCHECK(window);  // CanEmbed() returns false if no window.
+  PrepareForEmbed(window);
+  tree_and_window_id.tree->AddRootForToken(token, window,
+                                           window_id_in_embedded);
+  window->UpdateFrameSinkId(window_id_in_embedded);
+  client()->OnFrameSinkIdAllocated(ClientWindowIdToTransportId(window_id),
+                                   window->frame_sink_id());
+  return true;
+}
+
 void WindowTree::DispatchInputEvent(ServerWindow* target,
                                     const ui::Event& event,
                                     const EventLocation& event_location,
@@ -928,7 +950,7 @@
   // about.
   std::vector<const ServerWindow*> to_send;
   if (!IsWindowKnown(window))
-    GetUnknownWindowsFrom(window, &to_send);
+    GetUnknownWindowsFrom(window, &to_send, nullptr);
   const bool knows_old = old_parent && IsWindowKnown(old_parent);
   if (!knows_old && !knows_new)
     return;
@@ -1170,9 +1192,10 @@
 }
 
 bool WindowTree::IsValidIdForNewWindow(const ClientWindowId& id) const {
-  // Reserve 0 to indicate a null window.
+  // Reserve 0 (ClientWindowId() and sink_id) to indicate a null window.
   return client_id_to_window_map_.count(id) == 0u &&
-         access_policy_->IsValidIdForNewWindow(id) && id != ClientWindowId();
+         access_policy_->IsValidIdForNewWindow(id) && id != ClientWindowId() &&
+         id.sink_id() != 0;
 }
 
 bool WindowTree::CanReorderWindow(const ServerWindow* window,
@@ -1253,24 +1276,27 @@
 
 void WindowTree::GetUnknownWindowsFrom(
     const ServerWindow* window,
-    std::vector<const ServerWindow*>* windows) {
+    std::vector<const ServerWindow*>* windows,
+    const ClientWindowId* id_for_window) {
   if (!access_policy_->CanGetWindowTree(window))
     return;
 
   // This function is called in the context of a hierarchy change when the
   // parent wasn't known. We need to tell the client about the window so that
   // it can set the parent correctly.
-  windows->push_back(window);
+  if (windows)
+    windows->push_back(window);
   if (IsWindowKnown(window))
     return;
 
-  const ClientWindowId client_window_id = window->frame_sink_id();
+  const ClientWindowId client_window_id =
+      id_for_window ? *id_for_window : window->frame_sink_id();
   AddToMaps(window, client_window_id);
   if (!access_policy_->CanDescendIntoWindowForWindowTree(window))
     return;
   const ServerWindow::Windows& children = window->children();
   for (ServerWindow* child : children)
-    GetUnknownWindowsFrom(child, windows);
+    GetUnknownWindowsFrom(child, windows, nullptr);
 }
 
 void WindowTree::AddToMaps(const ServerWindow* window,
@@ -1280,6 +1306,20 @@
   window_to_client_id_map_[window] = client_window_id;
 }
 
+void WindowTree::AddRootForToken(const base::UnguessableToken& token,
+                                 ServerWindow* window,
+                                 const ClientWindowId& client_window_id) {
+  roots_.insert(window);
+  Display* display = GetDisplay(window);
+  int64_t display_id = display ? display->GetId() : display::kInvalidDisplayId;
+  // Caller should have verified there is no window already registered for
+  // |client_window_id|.
+  DCHECK(!GetWindowByClientId(client_window_id));
+  GetUnknownWindowsFrom(window, nullptr, &client_window_id);
+  client()->OnEmbedFromToken(token, WindowToWindowData(window), display_id,
+                             window->current_local_surface_id());
+}
+
 bool WindowTree::RemoveFromMaps(const ServerWindow* window) {
   auto iter = window_to_client_id_map_.find(window);
   if (iter == window_to_client_id_map_.end())
@@ -2010,13 +2050,33 @@
                                  EmbedUsingTokenCallback callback) {
   mojom::WindowTreeClientPtr client =
       GetAndRemoveScheduledEmbedWindowTreeClient(token);
-  if (!client) {
+  if (client) {
+    Embed(transport_window_id, std::move(client), flags, std::move(callback));
+    return;
+  }
+
+  WindowTreeAndWindowId tree_and_id =
+      window_server()->UnregisterEmbedToken(token);
+  if (!tree_and_id.tree) {
     DVLOG(1) << "EmbedUsingToken failed, no ScheduleEmbed(), token="
              << token.ToString();
     std::move(callback).Run(false);
     return;
   }
-  Embed(transport_window_id, std::move(client), flags, std::move(callback));
+  if (tree_and_id.tree == this) {
+    DVLOG(1) << "EmbedUsingToken failed, attempt to embed self, token="
+             << token.ToString();
+    std::move(callback).Run(false);
+    return;
+  }
+  std::move(callback).Run(EmbedExistingTree(
+      MakeClientWindowId(transport_window_id), tree_and_id, token));
+}
+
+void WindowTree::ScheduleEmbedForExistingClient(
+    uint32_t window_id,
+    ScheduleEmbedForExistingClientCallback callback) {
+  std::move(callback).Run(window_server()->RegisterEmbedToken(this, window_id));
 }
 
 void WindowTree::SetFocus(uint32_t change_id, Id transport_window_id) {
@@ -2427,7 +2487,7 @@
 
   bool success = true;
   for (auto iter = accelerators.begin(); iter != accelerators.end(); ++iter) {
-    if (!window_manager_state_->event_dispatcher()->AddAccelerator(
+    if (!window_manager_state_->event_processor()->AddAccelerator(
             iter->get()->id, std::move(iter->get()->event_matcher)))
       success = false;
   }
@@ -2435,7 +2495,7 @@
 }
 
 void WindowTree::RemoveAccelerator(uint32_t id) {
-  window_manager_state_->event_dispatcher()->RemoveAccelerator(id);
+  window_manager_state_->event_processor()->RemoveAccelerator(id);
 }
 
 void WindowTree::AddActivationParent(Id transport_window_id) {
diff --git a/services/ui/ws/window_tree.h b/services/ui/ws/window_tree.h
index bab6d2d..85e76ff 100644
--- a/services/ui/ws/window_tree.h
+++ b/services/ui/ws/window_tree.h
@@ -55,6 +55,7 @@
 class WindowServer;
 
 struct EventLocation;
+struct WindowTreeAndWindowId;
 
 namespace test {
 class WindowTreeTestApi;
@@ -197,6 +198,14 @@
              mojom::WindowTreeClientPtr window_tree_client,
              uint32_t flags);
 
+  // Called from EmbedUsingToken() to embed an existing client that previously
+  // called ScheduleEmbedForExistingClient(). |tree_and_window_id.tree| is the
+  // client that previously called ScheduleEmbedForExistingClient() and
+  // |token| is the token returned to the client.
+  bool EmbedExistingTree(const ClientWindowId& window_id,
+                         const WindowTreeAndWindowId& tree_and_window_id,
+                         const base::UnguessableToken& token);
+
   // Dispatches an event to the client. |callback| is run with the result from
   // the client.
   using DispatchEventCallback = base::OnceCallback<void(mojom::EventResult)>;
@@ -352,10 +361,20 @@
   // the tree that originated the change.
   bool DeleteWindowImpl(WindowTree* source, ServerWindow* window);
 
-  // If |window| is known does nothing. Otherwise adds |window| to |windows|,
-  // marks |window| as known and recurses.
+  // If |window| is known does nothing. Otherwise adds |window| to |windows| (if
+  // non-null) and marks |window| as known and recurses. If |window| is not
+  // known it assigned the ClientWindowId |id_for_window|, if |id_for_window|
+  // is null, then the FrameSinkId of |window| is used.
   void GetUnknownWindowsFrom(const ServerWindow* window,
-                             std::vector<const ServerWindow*>* windows);
+                             std::vector<const ServerWindow*>* windows,
+                             const ClientWindowId* id_for_window);
+
+  // Called to add |window| as an embed root. This matches a call from the
+  // client to ScheduleEmbedForExistingClient(). |client_window_id| is the
+  // ClientWindowId to use for |window|.
+  void AddRootForToken(const base::UnguessableToken& token,
+                       ServerWindow* window,
+                       const ClientWindowId& client_window_id);
 
   void AddToMaps(const ServerWindow* window,
                  const ClientWindowId& client_window_id);
@@ -511,6 +530,9 @@
                        const base::UnguessableToken& token,
                        uint32_t flags,
                        EmbedUsingTokenCallback callback) override;
+  void ScheduleEmbedForExistingClient(
+      ClientSpecificId window_id,
+      ScheduleEmbedForExistingClientCallback callback) override;
   void SetFocus(uint32_t change_id, Id transport_window_id) override;
   void SetCanFocus(Id transport_window_id, bool can_focus) override;
   void SetEventTargetingPolicy(Id transport_window_id,
diff --git a/services/ui/ws/window_tree_client_unittest.cc b/services/ui/ws/window_tree_client_unittest.cc
index 59a8b999..f8194266 100644
--- a/services/ui/ws/window_tree_client_unittest.cc
+++ b/services/ui/ws/window_tree_client_unittest.cc
@@ -316,6 +316,11 @@
     if (embed_run_loop_)
       embed_run_loop_->Quit();
   }
+  void OnEmbedFromToken(
+      const base::UnguessableToken& token,
+      mojom::WindowDataPtr root,
+      int64_t display_id,
+      const base::Optional<viz::LocalSurfaceId>& local_surface_id) override {}
   void OnEmbeddedAppDisconnected(Id window_id) override {
     tracker()->OnEmbeddedAppDisconnected(window_id);
   }
diff --git a/services/ui/ws/window_tree_unittest.cc b/services/ui/ws/window_tree_unittest.cc
index 1b3b089..dae95a0 100644
--- a/services/ui/ws/window_tree_unittest.cc
+++ b/services/ui/ws/window_tree_unittest.cc
@@ -306,12 +306,12 @@
 
   WindowManagerState* wms =
       display()->window_manager_display_root()->window_manager_state();
-  EXPECT_EQ(window, wms->event_dispatcher()->mouse_cursor_source_window());
+  EXPECT_EQ(window, wms->event_processor()->mouse_cursor_source_window());
 
   window->parent()->Remove(window);
   // The remove should reset the mouse_cursor_source_window(). The important
   // thing is it changes to something other than |window|.
-  EXPECT_NE(window, wms->event_dispatcher()->mouse_cursor_source_window());
+  EXPECT_NE(window, wms->event_processor()->mouse_cursor_source_window());
 }
 
 // Verifies SetChildModalParent() works correctly.
@@ -780,8 +780,7 @@
   WindowManagerState* wms =
       display()->window_manager_display_root()->window_manager_state();
   ModalWindowControllerTestApi modal_window_controller_test_api(
-      EventDispatcherTestApi(wms->event_dispatcher())
-          .modal_window_controller());
+      EventProcessorTestApi(wms->event_processor()).modal_window_controller());
   EXPECT_EQ(test_window,
             modal_window_controller_test_api.GetActiveSystemModalWindow());
   EXPECT_TRUE(wm_tree()->SetModalType(test_window_id, MODAL_TYPE_NONE));
@@ -800,8 +799,7 @@
   WindowManagerState* wms =
       display()->window_manager_display_root()->window_manager_state();
   ModalWindowControllerTestApi modal_window_controller_test_api(
-      EventDispatcherTestApi(wms->event_dispatcher())
-          .modal_window_controller());
+      EventProcessorTestApi(wms->event_processor()).modal_window_controller());
   EXPECT_EQ(nullptr,
             modal_window_controller_test_api.GetActiveSystemModalWindow());
   EXPECT_TRUE(wm_tree()->AddWindow(wm_root_id, test_window_id));
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json
index 0463bef0..71574f0 100644
--- a/testing/buildbot/chromium.clang.json
+++ b/testing/buildbot/chromium.clang.json
@@ -10121,12 +10121,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "notification_helper_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "pdf_unittests"
       },
       {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 0ebf7d44..c397f03 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -4966,8 +4966,7 @@
       },
       {
         "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_extensions_browsertests.filter"
+          "--enable-features=NetworkService"
         ],
         "name": "network_service_extensions_browsertests",
         "swarming": {
@@ -6293,8 +6292,7 @@
       },
       {
         "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_extensions_browsertests.filter"
+          "--enable-features=NetworkService"
         ],
         "name": "network_service_extensions_browsertests",
         "swarming": {
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index 0e67090..be54a3342 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -906,8 +906,7 @@
       },
       {
         "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_extensions_browsertests.filter"
+          "--enable-features=NetworkService"
         ],
         "name": "network_service_extensions_browsertests",
         "swarming": {
@@ -1707,8 +1706,7 @@
       },
       {
         "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_extensions_browsertests.filter"
+          "--enable-features=NetworkService"
         ],
         "name": "network_service_extensions_browsertests",
         "swarming": {
@@ -2348,8 +2346,7 @@
       },
       {
         "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_extensions_browsertests.filter"
+          "--enable-features=NetworkService"
         ],
         "name": "network_service_extensions_browsertests",
         "swarming": {
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn
index f4d0afa..ad22b6d 100644
--- a/testing/buildbot/filters/BUILD.gn
+++ b/testing/buildbot/filters/BUILD.gn
@@ -56,14 +56,6 @@
   ]
 }
 
-source_set("extensions_browsertests_filters") {
-  testonly = true
-
-  data = [
-    "//testing/buildbot/filters/mojo.fyi.network_extensions_browsertests.filter",
-  ]
-}
-
 source_set("interactive_ui_tests_filters") {
   testonly = true
 
diff --git a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
index 8a81dfe..86b11fc6 100644
--- a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
+++ b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
@@ -74,12 +74,6 @@
 -WebViewTests/WebViewTest.StoragePersistence/1
 -WebViewTests/WebViewTest.WebViewInBackgroundPage/0
 -WebViewTests/WebViewTest.WebViewInBackgroundPage/1
-
-# http://crbug.com/706030 handle external protocols
--ChromeSitePerProcessTest.LaunchExternalProtocolFromSubframe
--WebViewTests/WebViewTest.Shim_TestNavigationToExternalProtocol/0
--WebViewTests/WebViewTest.Shim_TestNavigationToExternalProtocol/1
-
 # Need support for blocking cookies via content settings:
 # https://crbug.com/803452.
 -ContentSettingsTest.AllowCookiesForASessionUsingExceptions
@@ -331,6 +325,7 @@
 # https://crbug.com/797292
 -SBNavigationObserverBrowserTest.DownloadViaHTML5FileApi
 -ProcessManagerBrowserTest.NestedURLNavigationsToExtensionBlocked
+-ProcessManagerBrowserTest.NestedURLDownloadsToExtensionAllowed
 
 # Flakes https://logs.chromium.org/v/?s=chromium%2Fbb%2Fchromium.linux%2FLinux_Tests%2F65822%2F%2B%2Frecipes%2Fsteps%2Fnetwork_service_browser_tests%2F0%2Flogs%2FNoSessionRestoreTest.PRE_CookiesClearedOnExit%2F0
 -NoSessionRestoreTest.CookiesClearedOnExit
diff --git a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
index 39aacc40..6f88b1e9 100644
--- a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
+++ b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
@@ -43,13 +43,6 @@
 -PreviewsStateResourceDispatcherHostBrowserTest.ShouldEnableLoFiModeReloadDisableLoFi
 
 -AsyncResourceHandlerBrowserTest/AsyncResourceHandlerBrowserTest.UploadProgress*
--DevToolsDownloadContentTest.MultiDownload
--DevToolsDownloadContentTest.DefaultDownload
--DevToolsDownloadContentTest.ResetDownloadState
--DevToolsDownloadContentTest.DownloadCancelled
--DevToolsDownloadContentTest.DeniedDownload
--DevToolsDownloadContentTest.DefaultDownloadHeadless
--DevToolsDownloadContentTest.SingleDownload
 -DevToolsProtocolTest.ControlNavigationsMainFrame
 -GetUserMediaVideoCaptureBrowserTest.RecoverFromCrashInVideoCaptureProcess
 -IsolatedDevToolsProtocolTest.ControlNavigationsChildFrames
@@ -113,5 +106,9 @@
 # Flakes https://logs.chromium.org/v/?s=chromium%2Fbb%2Fchromium.linux%2FLinux_Tests__dbg__1_%2F69105%2F%2B%2Frecipes%2Fsteps%2Fnetwork_service_content_browsertests%2F0%2Flogs%2FWebContentsImplBrowserTest.DownloadImage_Allow_FileImage%2F0
 -WebContentsImplBrowserTest.DownloadImage_Allow_FileImage
 
+# Network service path needs some way to update the per-WebContents load state.
+# http://crbug.com/819663.
+-WebContentsImplBrowserTest.UpdateLoadState
+
 # https://crbug.com/808759
 -DownloadContentTest.DownloadAttributeBlobURL
diff --git a/testing/buildbot/filters/mojo.fyi.network_extensions_browsertests.filter b/testing/buildbot/filters/mojo.fyi.network_extensions_browsertests.filter
deleted file mode 100644
index ddc3d60..0000000
--- a/testing/buildbot/filters/mojo.fyi.network_extensions_browsertests.filter
+++ /dev/null
@@ -1,5 +0,0 @@
-# These tests currently fail when run with enablefeatures=NetworkService

-# See https://crbug.com/819248

-

-# http://crbug.com/706030

--WebViewAPITest.TestNavigationToExternalProtocol

diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index e80b1ae..d8e353f 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -2559,6 +2559,7 @@
       'ToTWin64(dll)',
       'ToTWinCFI',
       'ToTWinCFI64',
+      'ToTWinLibcxx64',
       'ToTWinThinLTO64',
       # chromium.fyi
       'CrWinAsan tester',
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 80e766dd..3ef286b 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -1161,7 +1161,6 @@
     'network_service_extensions_browsertests': {
       'args': [
         '--enable-features=NetworkService',
-        '--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_extensions_browsertests.filter',
       ],
       'test': 'extensions_browsertests',
     },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 01b1bc78..55ef2ca 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -444,28 +444,6 @@
             ]
         }
     ],
-    "AutofillGooglePayBranding": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "ios",
-                "linux",
-                "mac",
-                "win"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "AutofillCreditCardDropdownGooglePayBranding",
-                        "AutofillUpstreamUseGooglePayBranding",
-                        "AutofillUseNewSettingsNameInDropdown"
-                    ]
-                }
-            ]
-        }
-    ],
     "AutofillProfileCleanup": [
         {
             "platforms": [
@@ -527,25 +505,6 @@
             ]
         }
     ],
-    "AutofillUpstreamSendDetectedValues": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "linux",
-                "mac",
-                "win"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "AutofillUpstreamSendDetectedValues"
-                    ]
-                }
-            ]
-        }
-    ],
     "AutomaticTabDiscarding": [
         {
             "platforms": [
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 57f1e7e..e3ca497 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1433,6 +1433,9 @@
 crbug.com/v8/7486 http/tests/devtools/startup/console/console-format-startup-bigint.js [ Skip ]
 crbug.com/v8/7486 http/tests/devtools/console/console-format-bigint.js [ Skip ]
 
+# Temporarily disable test until we land change to v8::ScriptCompiler::CompileFunctionInContext.
+crbug.com/v8/7172 inspector-protocol/debugger/step-into-inline-event-handler.js [ NeedsManualRebaseline ]
+
 crbug.com/564109 [ Win ]  http/tests/webfont/font-display-intervention.html [ Pass Failure Timeout ]
 
 crbug.com/399951 http/tests/mime/javascript-mimetype-usecounters.html [ Pass Failure ]
@@ -2926,6 +2929,8 @@
 crbug.com/757165 [ Win ] external/wpt/preload/download-resources.html [ Skip ]
 crbug.com/757165 [ Win ] external/wpt/preload/preload-default-csp.sub.html [ Skip ]
 crbug.com/757165 [ Win ] external/wpt/service-workers/service-worker/navigation-redirect.https.html [ Skip ]
+crbug.com/757165 [ Win ] virtual/navigation-mojo-response/external/wpt/service-workers/service-worker/navigation-redirect.https.html [ Skip ]
+crbug.com/757165 [ Win ] virtual/outofblink-cors/external/wpt/service-workers/service-worker/navigation-redirect.https.html [ Skip ]
 crbug.com/757165 [ Win ] fast/forms/file/recover-file-input-in-unposted-form.html [ Skip ]
 crbug.com/757165 [ Win ] fast/spatial-navigation/snav-aligned-not-aligned.html [ Pass Failure Timeout Crash ]
 crbug.com/757165 [ Win ] fast/spatial-navigation/snav-clipped-overflowed-content.html [ Pass Failure Timeout Crash ]
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index cd1a5e53..73ea8705 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -9493,6 +9493,18 @@
      {}
     ]
    ],
+   "css/CSS2/linebox/fractional-line-height.html": [
+    [
+     "/css/CSS2/linebox/fractional-line-height.html",
+     [
+      [
+       "/css/reference/nothing.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/CSS2/linebox/inline-box-001.xht": [
     [
      "/css/CSS2/linebox/inline-box-001.xht",
@@ -100142,6 +100154,316 @@
      {}
     ]
    ],
+   "cookies/http-state/all-tests-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/cookie-http-state-template.js": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/cookie-setter.py": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/debugging-single-test.html.py-str": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/iframe-content-pushing.js": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/iframe-expectation-doc.html.py-str": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0001-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0001-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0002-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0002-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0003-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0003-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0004-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0004-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0005-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0005-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0006-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0006-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0007-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0007-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0008-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0008-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0009-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0009-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0010-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0010-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0011-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0011-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0012-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0012-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0013-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0013-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0014-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0014-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0015-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0015-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0016-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0016-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0017-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0017-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0018-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0018-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0019-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0019-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0020-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0020-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0021-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0021-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0022-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0022-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0023-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0023-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0024-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0024-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0025-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0025-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0026-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0026-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0027-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0027-test": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0028-expected": [
+    [
+     {}
+    ]
+   ],
+   "cookies/http-state/resources/test-files/0028-test": [
+    [
+     {}
+    ]
+   ],
    "cookies/resources/echo-cookie.html": [
     [
      {}
@@ -172952,6 +173274,12 @@
      }
     ]
    ],
+   "apng/supported-in-source-type.html": [
+    [
+     "/apng/supported-in-source-type.html",
+     {}
+    ]
+   ],
    "audio-output/HTMLMediaElement-sinkId-idl.html": [
     [
      "/audio-output/HTMLMediaElement-sinkId-idl.html",
@@ -177332,6 +177660,12 @@
      {}
     ]
    ],
+   "cookies/http-state/all-tests.html": [
+    [
+     "/cookies/http-state/all-tests.html",
+     {}
+    ]
+   ],
    "cookies/meta-blocked.html": [
     [
      "/cookies/meta-blocked.html",
@@ -249523,6 +249857,10 @@
    "b9ba0287c92e5dbda1dc207ab45e9c90e8618878",
    "reftest"
   ],
+  "apng/supported-in-source-type.html": [
+   "32cf112fb1dcb4e7ec3c91bdf5bd6b976a1e4eac",
+   "testharness"
+  ],
   "audio-output/HTMLMediaElement-sinkId-idl.html": [
    "8f37d8d2fc1cb9b5ad0d85234f733f534f4f0db8",
    "testharness"
@@ -253735,6 +254073,258 @@
    "1949878db1be4093ec8d9595710f9fd8887434ba",
    "support"
   ],
+  "cookies/http-state/all-tests-expected.txt": [
+   "a12eb8f40571e4978d7e4d02c130859ce5acc20e",
+   "support"
+  ],
+  "cookies/http-state/all-tests.html": [
+   "4e030633623184b3e5705d312294412b96f28bf7",
+   "testharness"
+  ],
+  "cookies/http-state/resources/cookie-http-state-template.js": [
+   "2e096943b9071f912adf4b3fec3ecae8e6b68118",
+   "support"
+  ],
+  "cookies/http-state/resources/cookie-setter.py": [
+   "693d8ec6f340275e978db3ad9a8472c411ac733f",
+   "support"
+  ],
+  "cookies/http-state/resources/debugging-single-test.html.py-str": [
+   "654fd1e28ddb80d348177156be6891a69151bf35",
+   "support"
+  ],
+  "cookies/http-state/resources/iframe-content-pushing.js": [
+   "fbc5db2860aeda6f40ab030860ef0cad4269b623",
+   "support"
+  ],
+  "cookies/http-state/resources/iframe-expectation-doc.html.py-str": [
+   "75d7f676ea34a2de323a5e21fd0311fc6af10559",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0001-expected": [
+   "2017a6b45d4929c7f8ebbbaca36331cc11199f88",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0001-test": [
+   "39267fb59abc334f248787ad0b90fdb335b6d978",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0002-expected": [
+   "2017a6b45d4929c7f8ebbbaca36331cc11199f88",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0002-test": [
+   "831c8e90ead0291ffe36a82f0ada40c9a1b39f7f",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0003-expected": [
+   "6e46add5a20aed330c75fc95a727647a6a62085c",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0003-test": [
+   "10a97fd3dd221dc3681a548e166ff81d70623d85",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0004-expected": [
+   "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0004-test": [
+   "ca5e6a3fef1d281d2658efbb49a1d3d93cff5383",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0005-expected": [
+   "2017a6b45d4929c7f8ebbbaca36331cc11199f88",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0005-test": [
+   "21f309bbef82b8f40db76d4b2c16a70d7c48fa3d",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0006-expected": [
+   "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0006-test": [
+   "d65ef234d4b769ded714a2954f9911c231921e08",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0007-expected": [
+   "2017a6b45d4929c7f8ebbbaca36331cc11199f88",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0007-test": [
+   "6781b00cb8db2d51bcdea7f3e3898d2bf71a18ad",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0008-expected": [
+   "2017a6b45d4929c7f8ebbbaca36331cc11199f88",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0008-test": [
+   "e144c22f6b0f015e42bc99b7ede7533f88009a79",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0009-expected": [
+   "2017a6b45d4929c7f8ebbbaca36331cc11199f88",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0009-test": [
+   "6cc31bc3fadd075bc3df42200559a1c384b5954c",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0010-expected": [
+   "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0010-test": [
+   "8938cf5aeef5a84828a41424154e23d77503a7c2",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0011-expected": [
+   "2017a6b45d4929c7f8ebbbaca36331cc11199f88",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0011-test": [
+   "bb5a0e5a6cb4884e4161fa3aaef85f5c889aa2c3",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0012-expected": [
+   "2017a6b45d4929c7f8ebbbaca36331cc11199f88",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0012-test": [
+   "50f6b17f8663140ef6a8da5b0b808ddb75de3ff6",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0013-expected": [
+   "94ac42babde7e098c5a3b1a5b967a482661d34d9",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0013-test": [
+   "cfbaa5ec1434f310a2307f31384c5c802a41dcee",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0014-expected": [
+   "63b44fb34e929499aa6e7e10107ba42bed4bf102",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0014-test": [
+   "1bba693282c7a6cd8a8189e42f2223f664b70bc3",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0015-expected": [
+   "969c588efb9bed6d834836ab8c7154615981fcaf",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0015-test": [
+   "44b7c98589eb8c93ffb0d4b8410f683d789c3403",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0016-expected": [
+   "f6871163355cbcf80d33619af177c6dc6947d2f1",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0016-test": [
+   "21ce5420b2802c9a2c60c7f8cd4aa82b466cd6db",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0017-expected": [
+   "12081e8a1edca7056df86a2abd6156790ce00318",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0017-test": [
+   "e7816075c82788cd1de25dec77fb7ff1929f0d74",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0018-expected": [
+   "fa5f92ce177b11fc1b8df81abd75cc2d7feaa591",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0018-test": [
+   "27baa279199e4dd31a3008e59591ea4655c925cd",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0019-expected": [
+   "c72660a2dea4cc06221857e79d722cd656b7c797",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0019-test": [
+   "c43d87e073450f63b89a8b95603fd9b2f1c78c77",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0020-expected": [
+   "55019e1af5182dc7641f6ea731a65781ba7f6410",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0020-test": [
+   "280ee9a2f25bc8b68e6120e92199e8586a4b2095",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0021-expected": [
+   "55019e1af5182dc7641f6ea731a65781ba7f6410",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0021-test": [
+   "35805d1fb83bfbf179dc6ae01d7dfc0fab959f6b",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0022-expected": [
+   "4241a551c571283d8a8f5077351db5dc3f068dd6",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0022-test": [
+   "a22c4427ded3c9ee5b3bb8abf8c2f8d035a5df04",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0023-expected": [
+   "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0023-test": [
+   "b0e7f6e71e828d978b9cba6b78666313db236ac9",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0024-expected": [
+   "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0024-test": [
+   "eb071d44c0344f5a227f2fa5eebf0111a8a49683",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0025-expected": [
+   "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0025-test": [
+   "36a5c1062a93f924ee4db79cd8e4caa3df38c48e",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0026-expected": [
+   "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0026-test": [
+   "b0e7f6e71e828d978b9cba6b78666313db236ac9",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0027-expected": [
+   "da39a3ee5e6b4b0d3255bfef95601890afd80709",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0027-test": [
+   "d5d8e8d85183b6665438a42c14c17e56724ff0c7",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0028-expected": [
+   "b0e7f6e71e828d978b9cba6b78666313db236ac9",
+   "support"
+  ],
+  "cookies/http-state/resources/test-files/0028-test": [
+   "b0e7f6e71e828d978b9cba6b78666313db236ac9",
+   "support"
+  ],
   "cookies/meta-blocked.html": [
    "1ece2f38a340ff4ff4713ada5568281d0e1c5be2",
    "testharness"
@@ -256747,6 +257337,10 @@
    "7d267cb188014a18688e13806e095706f3f2d937",
    "reftest"
   ],
+  "css/CSS2/linebox/fractional-line-height.html": [
+   "d883c6dbf79c1da2c7a9a2261ec19eb6fc546082",
+   "reftest"
+  ],
   "css/CSS2/linebox/inline-box-001-ref.xht": [
    "55eee0833d9596605cb10d6bccfaedbe6f784027",
    "support"
@@ -290232,7 +290826,7 @@
    "testharness"
   ],
   "css/css-tables/width-distribution/td-with-subpixel-padding.html": [
-   "3f7a5f9c45ea9a664220ddaa45f7bc671810f9e6",
+   "b93845c332e5153c8a28085303b165d3c96f984e",
    "testharness"
   ],
   "css/css-tables/zero-rowspan-001-ref.html": [
@@ -373420,7 +374014,7 @@
    "support"
   ],
   "webrtc/interfaces.https-expected.txt": [
-   "2f9d764c647244a195e985d92ec10a31f96c35bf",
+   "c6d434a1c1082cd0046814f115b45535265068a4",
    "support"
   ],
   "webrtc/interfaces.https.html": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/apng/supported-in-source-type.html b/third_party/WebKit/LayoutTests/external/wpt/apng/supported-in-source-type.html
new file mode 100644
index 0000000..0a4d232
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/apng/supported-in-source-type.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>Animated PNG MIME type (image/apng) is recognized by &lt;source type></title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+function resolveUrl(relativeUrl) {
+  var a = document.createElement('a');
+  a.href = relativeUrl;
+  return a.href;
+}
+
+async_test(t => {
+  window.onload = t.step_func_done(() => {
+    let image = document.querySelector('img');
+    let apngSrc = document.querySelector('source');
+    assert_equals(image.currentSrc, resolveUrl(apngSrc.srcset));
+  });
+});
+</script>
+<picture>
+  <source srcset="/images/anim-gr.png" type="image/apng">
+  <img src="/images/anim-gr.gif" style="visibility: hidden">
+</picture>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-tables/width-distribution/td-with-subpixel-padding.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-tables/width-distribution/td-with-subpixel-padding.html
index c99f2c32..ff040773 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-tables/width-distribution/td-with-subpixel-padding.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-tables/width-distribution/td-with-subpixel-padding.html
@@ -1,6 +1,7 @@
 <!DOCTYPE html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://drafts.csswg.org/css-tables/#width-distribution" />
 <style>
 div {
   display: inline-block;
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-breakpoints/debugger-breakpoints-not-activated-on-reload.js b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-breakpoints/debugger-breakpoints-not-activated-on-reload.js
index 151c05ec..ea00647 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-breakpoints/debugger-breakpoints-not-activated-on-reload.js
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-breakpoints/debugger-breakpoints-not-activated-on-reload.js
@@ -31,7 +31,7 @@
 
   function step3() {
     TestRunner.addResult('Main resource was shown.');
-    if (!Bindings.breakpointManager.breakpointsActive())
+    if (!Common.moduleSetting('breakpointsActive').get())
       TestRunner.addResult('Breakpoints are deactivated.');
     else
       TestRunner.addResult('Error: breakpoints are activated.');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-breakpoints/disable-breakpoints.js b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-breakpoints/disable-breakpoints.js
index 0f1e21c..ac9baff 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-breakpoints/disable-breakpoints.js
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/sources/debugger-breakpoints/disable-breakpoints.js
@@ -46,7 +46,7 @@
         TestRunner.addResult('Test function finished.');
 
         TestRunner.addResult('Disabling breakpoints...');
-        Bindings.breakpointManager.setBreakpointsActive(false);
+        Common.moduleSetting('breakpointsActive').set(false);
 
         TestRunner.addResult('Running test function again...');
         ConsoleTestRunner.addConsoleSniffer(testFunctionFinishedForTheSecondTime);
@@ -65,7 +65,7 @@
       function didShowScriptSource(sourceFrame) {
         currentSourceFrame = sourceFrame;
         TestRunner.addResult('Enabling breakpoints...');
-        Bindings.breakpointManager.setBreakpointsActive(true);
+        Common.moduleSetting('breakpointsActive').set(true);
 
         TestRunner.addResult('Running test function...');
         SourcesTestRunner.runTestFunctionAndWaitUntilPaused(didPause);
diff --git a/third_party/WebKit/LayoutTests/images/missing-image-border-zoom.html b/third_party/WebKit/LayoutTests/images/missing-image-border-zoom.html
new file mode 100644
index 0000000..e1990d1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/images/missing-image-border-zoom.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<style>
+  body {
+    zoom: 200%;
+  }
+</style>
+<img src="https://www.example.com/doesntexist.png" style="width: 32px; height: 32px; background: orange;"/></p>
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-into-inline-event-handler.js b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-into-inline-event-handler.js
index 7f28143..76e3005 100644
--- a/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-into-inline-event-handler.js
+++ b/third_party/WebKit/LayoutTests/inspector-protocol/debugger/step-into-inline-event-handler.js
@@ -17,7 +17,7 @@
 
   function dumpTopCallFrame(result) {
     var frame = result.params.callFrames[0];
-    testRunner.log('functionName (should be empty): ' + (frame.functionName.length ? frame.functionName : 'empty'));
+    testRunner.log('functionName (should be onclick): ' + (frame.functionName.length ? frame.functionName : 'empty'));
   }
 
   await dp.Debugger.enable();
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/broken-image-with-size-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/broken-image-with-size-hidpi-expected.png
index e48a88e..d3b1b6348 100644
--- a/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/broken-image-with-size-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/hidpi/broken-image-with-size-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/missing-image-border-zoom-expected.png b/third_party/WebKit/LayoutTests/platform/mac/images/missing-image-border-zoom-expected.png
new file mode 100644
index 0000000..c75ab9b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/missing-image-border-zoom-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/images/missing-image-border-zoom-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/images/missing-image-border-zoom-expected.txt
new file mode 100644
index 0000000..e8dfab6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/images/missing-image-border-zoom-expected.txt
@@ -0,0 +1,14 @@
+Blocked access to external URL https://www.example.com/doesntexist.png
+Blocked access to external URL https://www.example.com/doesntexist.png
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x120
+  LayoutBlockFlow {HTML} at (0,0) size 800x120
+    LayoutBlockFlow {BODY} at (16,16) size 768x72
+      LayoutBlockFlow (anonymous) at (0,0) size 768x72
+        LayoutBlockFlow {IMG} at (0,0) size 64x64 [bgcolor=#FFA500]
+      LayoutBlockFlow {P} at (0,104) size 768x0
+layer at (16,16) size 64x64 clip at (18,18) size 60x60
+  LayoutBlockFlow {SPAN} at (0,0) size 64x64 [border: (2px solid #C0C0C0)]
+    LayoutImage (floating) {IMG} at (4,4) size 32x32
+    LayoutInline {SPAN} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/missing-image-border-zoom-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/missing-image-border-zoom-expected.png
new file mode 100644
index 0000000..60a01a45
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/exotic-color-space/images/missing-image-border-zoom-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/missing-image-border-zoom-expected.png b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/missing-image-border-zoom-expected.png
new file mode 100644
index 0000000..b218eb8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/gpu-rasterization/images/missing-image-border-zoom-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-with-size-hidpi-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-with-size-hidpi-expected.png
index 765b175..1313ea4 100644
--- a/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-with-size-hidpi-expected.png
+++ b/third_party/WebKit/LayoutTests/platform/win/fast/hidpi/broken-image-with-size-hidpi-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/missing-image-border-zoom-expected.png b/third_party/WebKit/LayoutTests/platform/win/images/missing-image-border-zoom-expected.png
new file mode 100644
index 0000000..98624a9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/missing-image-border-zoom-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/images/missing-image-border-zoom-expected.txt b/third_party/WebKit/LayoutTests/platform/win/images/missing-image-border-zoom-expected.txt
new file mode 100644
index 0000000..31ce5aa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/images/missing-image-border-zoom-expected.txt
@@ -0,0 +1,14 @@
+Blocked access to external URL https://www.example.com/doesntexist.png
+Blocked access to external URL https://www.example.com/doesntexist.png
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x121
+  LayoutBlockFlow {HTML} at (0,0) size 800x121
+    LayoutBlockFlow {BODY} at (16,16) size 768x73
+      LayoutBlockFlow (anonymous) at (0,0) size 768x73
+        LayoutBlockFlow {IMG} at (0,0) size 64x64 [bgcolor=#FFA500]
+      LayoutBlockFlow {P} at (0,105) size 768x0
+layer at (16,16) size 64x64 clip at (18,18) size 60x60
+  LayoutBlockFlow {SPAN} at (0,0) size 64x64 [border: (2px solid #C0C0C0)]
+    LayoutImage (floating) {IMG} at (4,4) size 32x32
+    LayoutInline {SPAN} at (0,0) size 0x0
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/missing-image-border-zoom-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/missing-image-border-zoom-expected.png
new file mode 100644
index 0000000..2eaf859
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/exotic-color-space/images/missing-image-border-zoom-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/missing-image-border-zoom-expected.png b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/missing-image-border-zoom-expected.png
new file mode 100644
index 0000000..141db2ca
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/win/virtual/gpu-rasterization/images/missing-image-border-zoom-expected.png
Binary files differ
diff --git a/third_party/WebKit/Source/build/scripts/make_computed_style_base.py b/third_party/WebKit/Source/build/scripts/make_computed_style_base.py
index 0e01019..6384357 100755
--- a/third_party/WebKit/Source/build/scripts/make_computed_style_base.py
+++ b/third_party/WebKit/Source/build/scripts/make_computed_style_base.py
@@ -553,14 +553,14 @@
 
         self._include_paths = _get_include_paths(self._properties)
         self._outputs = {
-            'ComputedStyleBase.h': self.generate_base_computed_style_h,
-            'ComputedStyleBase.cpp': self.generate_base_computed_style_cpp,
-            'ComputedStyleBaseConstants.h':
+            'computed_style_base.h': self.generate_base_computed_style_h,
+            'computed_style_base.cc': self.generate_base_computed_style_cpp,
+            'computed_style_base_constants.h':
                 self.generate_base_computed_style_constants,
         }
 
     @template_expander.use_jinja(
-        'templates/ComputedStyleBase.h.tmpl', tests={'in': lambda a, b: a in b})
+        'templates/computed_style_base.h.tmpl', tests={'in': lambda a, b: a in b})
     def generate_base_computed_style_h(self):
         return {
             'input_files': self._input_files,
@@ -572,7 +572,7 @@
         }
 
     @template_expander.use_jinja(
-        'templates/ComputedStyleBase.cpp.tmpl',
+        'templates/computed_style_base.cc.tmpl',
         tests={'in': lambda a, b: a in b})
     def generate_base_computed_style_cpp(self):
         return {
@@ -584,7 +584,7 @@
             'diff_functions_map': self._diff_functions_map,
         }
 
-    @template_expander.use_jinja('templates/ComputedStyleBaseConstants.h.tmpl')
+    @template_expander.use_jinja('templates/computed_style_base_constants.h.tmpl')
     def generate_base_computed_style_constants(self):
         return {
             'input_files': self._input_files,
diff --git a/third_party/WebKit/Source/build/scripts/templates/CSSValueIDMappingsGenerated.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/CSSValueIDMappingsGenerated.h.tmpl
index 5de0d725..2808bfed 100644
--- a/third_party/WebKit/Source/build/scripts/templates/CSSValueIDMappingsGenerated.h.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/CSSValueIDMappingsGenerated.h.tmpl
@@ -8,7 +8,7 @@
 
 #include "base/logging.h"
 #include "core/CSSValueKeywords.h"
-#include "core/ComputedStyleBaseConstants.h"
+#include "core/computed_style_base_constants.h"
 {% for path in include_paths %}
 #include "{{path}}"
 {% endfor %}
diff --git a/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.cpp.tmpl b/third_party/WebKit/Source/build/scripts/templates/computed_style_base.cc.tmpl
similarity index 98%
rename from third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.cpp.tmpl
rename to third_party/WebKit/Source/build/scripts/templates/computed_style_base.cc.tmpl
index cc8c72ce..ebb422ec 100644
--- a/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.cpp.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/computed_style_base.cc.tmpl
@@ -5,7 +5,7 @@
 
 {{source_files_for_generated_file(template_file, input_files)}}
 
-#include "core/ComputedStyleBase.h"
+#include "core/computed_style_base.h"
 #include "core/style/ComputedStyle.h"
 #include "platform/wtf/SizeAssertions.h"
 
diff --git a/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/computed_style_base.h.tmpl
similarity index 97%
rename from third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.h.tmpl
rename to third_party/WebKit/Source/build/scripts/templates/computed_style_base.h.tmpl
index f8ddcd66..9d442adf 100644
--- a/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.h.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/computed_style_base.h.tmpl
@@ -5,8 +5,8 @@
 
 {{source_files_for_generated_file(template_file, input_files)}}
 
-#ifndef ComputedStyleBase_h
-#define ComputedStyleBase_h
+#ifndef BLINK_CORE_COMPUTED_STYLE_BASE_H_
+#define BLINK_CORE_COMPUTED_STYLE_BASE_H_
 
 #include "core/CoreExport.h"
 #include "core/layout/LayoutTheme.h"
@@ -185,4 +185,4 @@
 
 } // namespace blink
 
-#endif // ComputedStyleBase_h
+#endif // BLINK_CORE_COMPUTED_STYLE_BASE_H_
diff --git a/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBaseConstants.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/computed_style_base_constants.h.tmpl
similarity index 86%
rename from third_party/WebKit/Source/build/scripts/templates/ComputedStyleBaseConstants.h.tmpl
rename to third_party/WebKit/Source/build/scripts/templates/computed_style_base_constants.h.tmpl
index 97209517..67eb2a2 100644
--- a/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBaseConstants.h.tmpl
+++ b/third_party/WebKit/Source/build/scripts/templates/computed_style_base_constants.h.tmpl
@@ -3,8 +3,8 @@
 
 {{source_files_for_generated_file(template_file, input_files)}}
 
-#ifndef ComputedStyleBaseConstants_h
-#define ComputedStyleBaseConstants_h
+#ifndef BLINK_CORE_COMPUTED_STYLE_BASE_CONSTANTS_H_
+#define BLINK_CORE_COMPUTED_STYLE_BASE_CONSTANTS_H_
 
 namespace blink {
 
@@ -36,4 +36,4 @@
 {% endfor %}
 } // namespace blink
 
-#endif // ComputedStyleBaseConstants_h
+#endif // BLINK_CORE_COMPUTED_STYLE_BASE_CONSTANTS_H_
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn
index cb98597c..59327fd 100644
--- a/third_party/WebKit/Source/core/BUILD.gn
+++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -502,15 +502,15 @@
     "../build/scripts/templates/fields/primitive.tmpl",
     "../build/scripts/templates/fields/monotonic_flag.tmpl",
     "../build/scripts/templates/fields/external.tmpl",
-    "../build/scripts/templates/ComputedStyleBase.h.tmpl",
-    "../build/scripts/templates/ComputedStyleBase.cpp.tmpl",
-    "../build/scripts/templates/ComputedStyleBaseConstants.h.tmpl",
+    "../build/scripts/templates/computed_style_base.h.tmpl",
+    "../build/scripts/templates/computed_style_base.cc.tmpl",
+    "../build/scripts/templates/computed_style_base_constants.h.tmpl",
     "../build/scripts/keyword_utils.py",
   ]
   outputs = [
-    "$blink_core_output_dir/ComputedStyleBase.h",
-    "$blink_core_output_dir/ComputedStyleBase.cpp",
-    "$blink_core_output_dir/ComputedStyleBaseConstants.h",
+    "$blink_core_output_dir/computed_style_base.h",
+    "$blink_core_output_dir/computed_style_base.cc",
+    "$blink_core_output_dir/computed_style_base_constants.h",
   ]
 }
 
diff --git a/third_party/WebKit/Source/core/html/HTMLImageFallbackHelper.cpp b/third_party/WebKit/Source/core/html/HTMLImageFallbackHelper.cpp
index 4dc07fc..70ca6f5 100644
--- a/third_party/WebKit/Source/core/html/HTMLImageFallbackHelper.cpp
+++ b/third_party/WebKit/Source/core/html/HTMLImageFallbackHelper.cpp
@@ -138,10 +138,16 @@
         new_style->Height().IsPercent()
             ? CSSPrimitiveValue::UnitType::kPercentage
             : CSSPrimitiveValue::UnitType::kPixels;
-    place_holder->SetInlineStyleProperty(CSSPropertyHeight,
-                                         new_style->Height().Value(), unit);
-    place_holder->SetInlineStyleProperty(CSSPropertyWidth,
-                                         new_style->Width().Value(), unit);
+
+    // The width and height reported by computed style are zoomed, but when
+    // setting the width and height CSS properties we want pre-zoomed sizes.
+    float scale_factor = unit == CSSPrimitiveValue::UnitType::kPixels
+                             ? new_style->EffectiveZoom()
+                             : 1.0f;
+    place_holder->SetInlineStyleProperty(
+        CSSPropertyHeight, new_style->Height().Value() / scale_factor, unit);
+    place_holder->SetInlineStyleProperty(
+        CSSPropertyWidth, new_style->Width().Value() / scale_factor, unit);
 
     // 16px for the image and 2px for its top/left border/padding offset.
     int pixels_for_alt_image = 18;
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
index 23bea1e..00be139 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
@@ -973,12 +973,18 @@
     if (!PositionWithBfcOffset(layout_result->BfcOffset().value(),
                                &child_bfc_offset))
       return false;
-  } else if (container_builder_.BfcOffset()) {
-    child_bfc_offset =
-        PositionWithParentBfc(child, *child_space, child_data, *layout_result,
-                              &empty_block_affected_by_clearance);
-  } else
+  } else {
+    // Layout wasn't able to determine the BFC offset of the child. This has to
+    // mean that the child is empty (block-size-wise).
     DCHECK(is_empty_block);
+    if (container_builder_.BfcOffset()) {
+      // Since we know our own BFC offset, though, we can calculate that of the
+      // child as well.
+      child_bfc_offset = PositionEmptyChildWithParentBfc(
+          child, *child_space, child_data, *layout_result,
+          &empty_block_affected_by_clearance);
+    }
+  }
 
   // We need to re-layout a child if it was affected by clearance in order to
   // produce a new margin strut. For example:
@@ -1194,12 +1200,12 @@
   return true;
 }
 
-NGBfcOffset NGBlockLayoutAlgorithm::PositionWithParentBfc(
+NGBfcOffset NGBlockLayoutAlgorithm::PositionEmptyChildWithParentBfc(
     const NGLayoutInputNode& child,
-    const NGConstraintSpace& space,
+    const NGConstraintSpace& child_space,
     const NGInflowChildData& child_data,
     const NGLayoutResult& layout_result,
-    bool* empty_block_affected_by_clearance) {
+    bool* has_clearance) const {
   DCHECK(IsEmptyBlock(child, layout_result));
 
   // The child must be an in-flow zero-block-size fragment, use its end margin
@@ -1217,8 +1223,8 @@
                                child_available_size_.inline_size);
   }
 
-  *empty_block_affected_by_clearance =
-      AdjustToClearance(space.ClearanceOffset(), &child_bfc_offset);
+  *has_clearance =
+      AdjustToClearance(child_space.ClearanceOffset(), &child_bfc_offset);
 
   return child_bfc_offset;
 }
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h
index c11c86438..b2948c9 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h
@@ -82,23 +82,22 @@
       bool empty_block_affected_by_clearance);
 
   // Positions the fragment that knows its BFC offset.
-  WTF::Optional<NGBfcOffset> PositionWithBfcOffset(
-      const NGBfcOffset& bfc_offset);
   bool PositionWithBfcOffset(const NGBfcOffset& bfc_offset,
                              WTF::Optional<NGBfcOffset>* child_bfc_offset);
 
-  // Positions using the parent BFC offset.
-  // Fragment doesn't know its offset but we can still calculate its BFC
+  // Position an empty child using the parent BFC offset.
+  // The fragment doesn't know its offset, but we can still calculate its BFC
   // position because the parent fragment's BFC is known.
   // Example:
   //   BFC Offset is known here because of the padding.
   //   <div style="padding: 1px">
-  //     <div id="empty-div" style="margins: 1px"></div>
-  NGBfcOffset PositionWithParentBfc(const NGLayoutInputNode& child,
-                                    const NGConstraintSpace&,
-                                    const NGInflowChildData& child_data,
-                                    const NGLayoutResult&,
-                                    bool* empty_block_affected_by_clearance);
+  //     <div id="empty-div" style="margin: 1px"></div>
+  NGBfcOffset PositionEmptyChildWithParentBfc(
+      const NGLayoutInputNode& child,
+      const NGConstraintSpace& child_space,
+      const NGInflowChildData& child_data,
+      const NGLayoutResult&,
+      bool* has_clearance) const;
 
   void HandleOutOfFlowPositioned(const NGPreviousInflowPosition&, NGBlockNode);
   void HandleFloat(const NGPreviousInflowPosition&,
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h
index c9f936768..5942b67 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -27,8 +27,8 @@
 #define ComputedStyle_h
 
 #include <memory>
-#include "core/ComputedStyleBase.h"
 #include "core/CoreExport.h"
+#include "core/computed_style_base.h"
 #include "core/css/StyleAutoColor.h"
 #include "core/css/StyleColor.h"
 #include "core/css/properties/CSSProperty.h"
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.md b/third_party/WebKit/Source/core/style/ComputedStyle.md
index 4f03151..79d6cc76 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyle.md
+++ b/third_party/WebKit/Source/core/style/ComputedStyle.md
@@ -17,14 +17,14 @@
 * [ComputedStyleDiffFunctions.json5](https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/css/ComputedStyleDiffFunctions.json5): Specifies the fields we want to diff in the various diff functions in ComputedStyle. It is used to generate the various diffing functions on ComputedStyle.
 
 ## Generator files:
-These scripts generate the ComputedStyleBase.{h,cpp} files. This is a list of the relevant generator files (more detailed documentation can be found in the files themselves):
+These scripts generate the computed_style_base.{h,cc} files. This is a list of the relevant generator files (more detailed documentation can be found in the files themselves):
 * [make_computed_style_base.py](https://cs.chromium.org/chromium/src/third_party/WebKit/Source/build/scripts/make_computed_style_base.py): Main file that handles the code generation logic. It consumes the JSON inputs provided and outputs fields and groups that encapsulate the structure of ComputedStyle.
 
 ## Template files:
 For each generate file, the Python script uses a Jinja template file to format the output:
-* [ComputedStyleBase.h.tmpl](https://cs.chromium.org/chromium/src/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.h.tmpl): Header file with the field and group declarations.
-* [ComputedStyleBase.cpp.tmpl](https://cs.chromium.org/chromium/src/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBase.cpp.tmpl): Implementation of various generated helper functions. Notably, contains implementation of functions that use ComputedStyle such as the diffing functions.
-* [ComputedStyleBaseConstants.h.tmpl](https://cs.chromium.org/chromium/src/third_party/WebKit/Source/build/scripts/templates/ComputedStyleBaseConstants.h.tmpl): Definitions of generated enums.
+* [computed_style_base.h.tmpl](https://cs.chromium.org/chromium/src/third_party/WebKit/Source/build/scripts/templates/computed_style_base.h.tmpl): Header file with the field and group declarations.
+* [computed_style_base.cc.tmpl](https://cs.chromium.org/chromium/src/third_party/WebKit/Source/build/scripts/templates/computed_style_base.cc.tmpl): Implementation of various generated helper functions. Notably, contains implementation of functions that use ComputedStyle such as the diffing functions.
+* [computed_style_base_constants.h.tmpl](https://cs.chromium.org/chromium/src/third_party/WebKit/Source/build/scripts/templates/computed_style_base_constants.h.tmpl): Definitions of generated enums.
 * [fields/*.tmpl](https://cs.chromium.org/chromium/src/third_party/WebKit/Source/build/scripts/templates/fields/): These files contain various macros that help us generate accessors for the fields depending on their field_template.
 
 # Understanding where to make changes:
diff --git a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
index 68fe6237..4e7ccd51 100644
--- a/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
+++ b/third_party/WebKit/Source/core/style/ComputedStyleConstants.h
@@ -28,8 +28,8 @@
 #ifndef ComputedStyleConstants_h
 #define ComputedStyleConstants_h
 
-#include "core/ComputedStyleBaseConstants.h"
 #include <cstddef>
+#include "core/computed_style_base_constants.h"
 
 namespace blink {
 
diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/BreakpointManager.js b/third_party/WebKit/Source/devtools/front_end/bindings/BreakpointManager.js
index ef94d0c6..d57b5ff0 100644
--- a/third_party/WebKit/Source/devtools/front_end/bindings/BreakpointManager.js
+++ b/third_party/WebKit/Source/devtools/front_end/bindings/BreakpointManager.js
@@ -29,7 +29,6 @@
  */
 /**
  * @unrestricted
- * @implements {SDK.SDKModelObserver<!SDK.DebuggerModel>}
  */
 Bindings.BreakpointManager = class extends Common.Object {
   /**
@@ -44,7 +43,6 @@
     this._targetManager = targetManager;
     this._debuggerWorkspaceBinding = debuggerWorkspaceBinding;
 
-    this._breakpointsActive = true;
     /** @type {!Map<!Workspace.UISourceCode, !Map<number, !Map<number, !Array<!Bindings.BreakpointManager.Breakpoint>>>>} */
     this._breakpointsForUISourceCode = new Map();
     /** @type {!Map<string, !Bindings.BreakpointManager.Breakpoint>} */
@@ -53,8 +51,6 @@
     this._workspace.addEventListener(Workspace.Workspace.Events.ProjectRemoved, this._projectRemoved, this);
     this._workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this);
     this._workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeRemoved, this._uiSourceCodeRemoved, this);
-
-    targetManager.observeModels(SDK.DebuggerModel, this);
   }
 
   /**
@@ -70,22 +66,6 @@
   }
 
   /**
-   * @override
-   * @param {!SDK.DebuggerModel} debuggerModel
-   */
-  modelAdded(debuggerModel) {
-    if (!this._breakpointsActive)
-      debuggerModel.setBreakpointsActive(this._breakpointsActive);
-  }
-
-  /**
-   * @override
-   * @param {!SDK.DebuggerModel} debuggerModel
-   */
-  modelRemoved(debuggerModel) {
-  }
-
-  /**
    * @param {string} fromURL
    * @param {!Workspace.UISourceCode} toSourceCode
    */
@@ -150,7 +130,6 @@
       Common.Revealer.reveal(normalizedLocation);
       uiLocation = normalizedLocation;
     }
-    this.setBreakpointsActive(true);
     return this._innerSetBreakpoint(
         uiLocation.uiSourceCode, uiLocation.lineNumber, uiLocation.columnNumber, condition, enabled);
   }
@@ -398,35 +377,12 @@
     this.dispatchEventToListeners(
         Bindings.BreakpointManager.Events.BreakpointRemoved, {breakpoint: breakpoint, uiLocation: uiLocation});
   }
-
-  /**
-   * @param {boolean} active
-   */
-  setBreakpointsActive(active) {
-    if (this._breakpointsActive === active)
-      return;
-
-    this._breakpointsActive = active;
-    const debuggerModels = SDK.targetManager.models(SDK.DebuggerModel);
-    for (let i = 0; i < debuggerModels.length; ++i)
-      debuggerModels[i].setBreakpointsActive(active);
-
-    this.dispatchEventToListeners(Bindings.BreakpointManager.Events.BreakpointsActiveStateChanged, active);
-  }
-
-  /**
-   * @return {boolean}
-   */
-  breakpointsActive() {
-    return this._breakpointsActive;
-  }
 };
 
 /** @enum {symbol} */
 Bindings.BreakpointManager.Events = {
   BreakpointAdded: Symbol('breakpoint-added'),
-  BreakpointRemoved: Symbol('breakpoint-removed'),
-  BreakpointsActiveStateChanged: Symbol('BreakpointsActiveStateChanged')
+  BreakpointRemoved: Symbol('breakpoint-removed')
 };
 
 
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js
index 062f275d..fd77d8a 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/DebuggerModel.js
@@ -63,6 +63,7 @@
     Common.moduleSetting('pauseOnExceptionEnabled').addChangeListener(this._pauseOnExceptionStateChanged, this);
     Common.moduleSetting('pauseOnCaughtException').addChangeListener(this._pauseOnExceptionStateChanged, this);
     Common.moduleSetting('disableAsyncStackTraces').addChangeListener(this._asyncStackTracesStateChanged, this);
+    Common.moduleSetting('breakpointsActive').addChangeListener(this._breakpointsActiveChanged, this);
 
     if (!target.suspended())
       this._enableDebugger();
@@ -119,6 +120,8 @@
     enablePromise.then(this._registerDebugger.bind(this));
     this._pauseOnExceptionStateChanged();
     this._asyncStackTracesStateChanged();
+    if (!Common.moduleSetting('breakpointsActive').get())
+      this._breakpointsActiveChanged();
     if (SDK.DebuggerModel._scheduledPauseOnAsyncCall)
       this._pauseOnAsyncCall(SDK.DebuggerModel._scheduledPauseOnAsyncCall);
     this.dispatchEventToListeners(SDK.DebuggerModel.Events.DebuggerWasEnabled, this);
@@ -200,6 +203,10 @@
     this._agent.setAsyncCallStackDepth(enabled ? maxAsyncStackChainDepth : 0);
   }
 
+  _breakpointsActiveChanged() {
+    this._agent.setBreakpointsActive(Common.moduleSetting('breakpointsActive').get());
+  }
+
   stepInto() {
     this._agent.stepInto();
   }
@@ -236,13 +243,6 @@
   }
 
   /**
-   * @param {boolean} active
-   */
-  setBreakpointsActive(active) {
-    this._agent.setBreakpointsActive(active);
-  }
-
-  /**
    * @param {string} url
    * @param {number} lineNumber
    * @param {number=} columnNumber
diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/module.json b/third_party/WebKit/Source/devtools/front_end/sdk/module.json
index 537ed6e..7edcfedf 100644
--- a/third_party/WebKit/Source/devtools/front_end/sdk/module.json
+++ b/third_party/WebKit/Source/devtools/front_end/sdk/module.json
@@ -100,6 +100,14 @@
         },
         {
             "type": "setting",
+            "category": "Debugger",
+            "settingName": "breakpointsActive",
+            "settingType": "boolean",
+            "storageType": "session",
+            "defaultValue": true
+        },
+        {
+            "type": "setting",
             "category": "Elements",
             "title": "Show rulers",
             "settingName": "showMetricsRulers",
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptBreakpointsSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptBreakpointsSidebarPane.js
index deebaaf..7d7f1e1 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptBreakpointsSidebarPane.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptBreakpointsSidebarPane.js
@@ -13,8 +13,7 @@
     this._breakpointManager = Bindings.breakpointManager;
     this._breakpointManager.addEventListener(Bindings.BreakpointManager.Events.BreakpointAdded, this.update, this);
     this._breakpointManager.addEventListener(Bindings.BreakpointManager.Events.BreakpointRemoved, this.update, this);
-    this._breakpointManager.addEventListener(
-        Bindings.BreakpointManager.Events.BreakpointsActiveStateChanged, this.update, this);
+    Common.moduleSetting('breakpointsActive').addChangeListener(this.update, this);
 
     /** @type {?Element} */
     this._listElement = null;
@@ -93,7 +92,8 @@
     }
     if (shouldShowView)
       UI.viewManager.showView('sources.jsBreakpoints');
-    this._listElement.classList.toggle('breakpoints-list-deactivated', !this._breakpointManager.breakpointsActive());
+    this._listElement.classList.toggle(
+        'breakpoints-list-deactivated', !Common.moduleSetting('breakpointsActive').get());
     Promise.all(promises).then(() => this._didUpdateForTest());
     return Promise.resolve();
   }
@@ -184,12 +184,11 @@
     contextMenu.defaultSection().appendItem(
         removeEntryTitle, () => breakpoints.map(breakpoint => breakpoint.remove(false /* keepInStorage */)));
 
-    const breakpointActive = this._breakpointManager.breakpointsActive();
+    const breakpointActive = Common.moduleSetting('breakpointsActive').get();
     const breakpointActiveTitle =
         breakpointActive ? Common.UIString('Deactivate breakpoints') : Common.UIString('Activate breakpoints');
     contextMenu.defaultSection().appendItem(
-        breakpointActiveTitle,
-        this._breakpointManager.setBreakpointsActive.bind(this._breakpointManager, !breakpointActive));
+        breakpointActiveTitle, () => Common.moduleSetting('breakpointsActive').set(!breakpointActive));
 
     if (breakpoints.some(breakpoint => !breakpoint.enabled())) {
       const enableTitle = Common.UIString('Enable all breakpoints');
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js
index 0db09031..3da17f04 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js
@@ -1556,6 +1556,7 @@
     if (!Bindings.CompilerScriptMapping.uiLineHasMapping(this._debuggerSourceCode, lineNumber))
       return;
 
+    Common.moduleSetting('breakpointsActive').set(true);
     this._breakpointManager.setBreakpoint(this._debuggerSourceCode, lineNumber, columnNumber, condition, enabled);
     this._breakpointWasSetForTest(lineNumber, columnNumber, condition, enabled);
   }
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js b/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
index e11b1629..f08809bc 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
@@ -110,8 +110,7 @@
     this._liveLocationPool = new Bindings.LiveLocationPool();
 
     this._setTarget(UI.context.flavor(SDK.Target));
-    Bindings.breakpointManager.addEventListener(
-        Bindings.BreakpointManager.Events.BreakpointsActiveStateChanged, this._breakpointsActiveStateChanged, this);
+    Common.moduleSetting('breakpointsActive').addChangeListener(this._breakpointsActiveStateChanged, this);
     UI.context.addFlavorChangeListener(SDK.Target, this._onCurrentTargetChanged, this);
     UI.context.addFlavorChangeListener(SDK.DebuggerModel.CallFrame, this._callFrameChanged, this);
     SDK.targetManager.addModelListener(
@@ -676,11 +675,11 @@
   }
 
   _toggleBreakpointsActive() {
-    Bindings.breakpointManager.setBreakpointsActive(!Bindings.breakpointManager.breakpointsActive());
+    Common.moduleSetting('breakpointsActive').set(!Common.moduleSetting('breakpointsActive').get());
   }
 
-  _breakpointsActiveStateChanged(event) {
-    const active = event.data;
+  _breakpointsActiveStateChanged() {
+    const active = Common.moduleSetting('breakpointsActive').get();
     this._toggleBreakpointsActiveAction.setToggled(!active);
     this._sourcesView.toggleBreakpointsActiveState(active);
   }
diff --git a/third_party/WebKit/Source/devtools/front_end/sources_test_runner/DebuggerTestRunner.js b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/DebuggerTestRunner.js
index 333450c..174dcdb 100644
--- a/third_party/WebKit/Source/devtools/front_end/sources_test_runner/DebuggerTestRunner.js
+++ b/third_party/WebKit/Source/devtools/front_end/sources_test_runner/DebuggerTestRunner.js
@@ -27,7 +27,7 @@
 };
 
 SourcesTestRunner.completeDebuggerTest = function() {
-  Bindings.breakpointManager.setBreakpointsActive(true);
+  Common.moduleSetting('breakpointsActive').set(true);
   SourcesTestRunner.resumeExecution(TestRunner.completeTest.bind(TestRunner));
 };
 
diff --git a/third_party/WebKit/Source/platform/blob/SerializedBlobStructTraits.h b/third_party/WebKit/Source/platform/blob/SerializedBlobStructTraits.h
index 6d9794f2..d61ecc9e 100644
--- a/third_party/WebKit/Source/platform/blob/SerializedBlobStructTraits.h
+++ b/third_party/WebKit/Source/platform/blob/SerializedBlobStructTraits.h
@@ -17,6 +17,14 @@
 struct PLATFORM_EXPORT
     StructTraits<blink::mojom::blink::SerializedBlob::DataView,
                  scoped_refptr<blink::BlobDataHandle>> {
+  static bool IsNull(const scoped_refptr<blink::BlobDataHandle>& input) {
+    return !input;
+  }
+
+  static void SetToNull(scoped_refptr<blink::BlobDataHandle>* output) {
+    *output = nullptr;
+  }
+
   static WTF::String uuid(const scoped_refptr<blink::BlobDataHandle>& input) {
     return input->Uuid();
   }
diff --git a/third_party/WebKit/Source/platform/testing/ImageDecodeBench.cpp b/third_party/WebKit/Source/platform/testing/ImageDecodeBench.cpp
index 8166eb1..0eb3abcb 100644
--- a/third_party/WebKit/Source/platform/testing/ImageDecodeBench.cpp
+++ b/third_party/WebKit/Source/platform/testing/ImageDecodeBench.cpp
@@ -40,11 +40,13 @@
   }
 
   file.seekg(0, std::ios::end);
-  size_t file_size = file.tellg();
+  int file_size = file.tellg();
   file.seekg(0, std::ios::beg);
 
-  if (!file || !file_size)
-    return SharedBuffer::Create();
+  if (!file || file_size <= 0) {
+    fprintf(stderr, "Error seeking file %s\n", name);
+    exit(2);
+  }
 
   Vector<char> buffer(file_size);
   if (!file.read(buffer.data(), file_size)) {
@@ -126,21 +128,11 @@
   class WebPlatform : public Platform {};
   Platform::Initialize(new WebPlatform());
 
-  // Read entire file content to data, and consolidate the SharedBuffer data
-  // segments into one, contiguous block of memory.
+  // Read entire file content into |data| (a contiguous block of memory) then
+  // decode it to verify the image and record its ImageMeta data.
 
+  ImageMeta image = {argv[1], 0, 0, 0, 0};
   scoped_refptr<SharedBuffer> data = ReadFile(argv[1]);
-  if (!data.get() || !data->size()) {
-    fprintf(stderr, "Error reading image %s\n", argv[1]);
-    exit(2);
-  }
-
-  data->Data();
-
-  // Warm-up: throw out the first iteration for more consistent results.
-
-  ImageMeta image;
-  image.name = argv[1];
   DecodeImageData(data.get(), &image);
 
   // Image decode bench for decode_iterations.
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py
index cc690ed..3d97b82 100644
--- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py
+++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/base.py
@@ -1732,6 +1732,10 @@
 
     def _wpt_test_urls_matching_paths(self, paths):
         tests = []
+        # '/' is used throughout this function instead of filesystem.sep as the WPT manifest always
+        # uses '/' for paths (it is not OS dependent).
+        if self._filesystem.sep != '/':
+            paths = [path.replace(self._filesystem.sep, '/') for path in paths]
 
         for test_url_path in self._wpt_manifest().all_urls():
             if test_url_path[0] == '/':
@@ -1752,8 +1756,8 @@
                 )
 
                 # Get a list of directories for both paths, filter empty strings
-                full_test_url_directories = filter(None, full_test_url_path.split(self._filesystem.sep))
-                path_directories = filter(None, path.split(self._filesystem.sep))
+                full_test_url_directories = filter(None, full_test_url_path.split('/'))
+                path_directories = filter(None, path.split('/'))
 
                 # For all other path matches within WPT
                 if matches_any_js_test or path_directories == full_test_url_directories[0:len(path_directories)]:
diff --git a/third_party/WebKit/common/mime_util/mime_util.cc b/third_party/WebKit/common/mime_util/mime_util.cc
index 410214c..1472c9e 100644
--- a/third_party/WebKit/common/mime_util/mime_util.cc
+++ b/third_party/WebKit/common/mime_util/mime_util.cc
@@ -29,6 +29,7 @@
                                             "image/jpg",
                                             "image/webp",
                                             "image/png",
+                                            "image/apng",
                                             "image/gif",
                                             "image/bmp",
                                             "image/vnd.microsoft.icon",  // ico
diff --git a/third_party/closure_compiler/externs/automation.js b/third_party/closure_compiler/externs/automation.js
index d7cb866..23f0d52 100644
--- a/third_party/closure_compiler/externs/automation.js
+++ b/third_party/closure_compiler/externs/automation.js
@@ -32,6 +32,7 @@
   DOCUMENT_SELECTION_CHANGED: 'documentSelectionChanged',
   EXPANDED_CHANGED: 'expandedChanged',
   FOCUS: 'focus',
+  FOCUS_CONTEXT: 'focusContext',
   IMAGE_FRAME_UPDATED: 'imageFrameUpdated',
   HIDE: 'hide',
   HIT_TEST_RESULT: 'hitTestResult',
diff --git a/tools/android/appstats.py b/tools/android/appstats.py
index 305176c..b59ac63 100755
--- a/tools/android/appstats.py
+++ b/tools/android/appstats.py
@@ -7,6 +7,7 @@
 
 import argparse
 import curses
+import logging
 import os
 import re
 import sys
@@ -127,27 +128,13 @@
     intersect the two.  The returned result is sorted based on userid."""
     pids = []
     try:
-      # TODO(catapult:#3215): Migrate to adb.GetPids().
-      pid_lines = adb.RunShellCommand(
-          ['ps'], large_output=True, check_return=True)
-      if default_pid:
-        pid_lines = Utils.FindLines(pid_lines, str(default_pid))
-      if process_filter:
-        pid_lines = Utils.FindLines(pid_lines, process_filter)
-      for line in pid_lines:
-        data = re.split('\s+', line.strip())
-        pid = data[1]
-        name = data[-1]
-
-        # Confirm that the pid and name match.  Using a regular grep isn't
-        # reliable when doing it on the whole 'ps' input line.
-        pid_matches = not default_pid or pid == str(default_pid)
-        name_matches = not process_filter or name.find(process_filter) != -1
-        if pid_matches and name_matches:
-          userid = DeviceHelper.__GetUserIdForProcessName(adb, name)
-          pids.append((userid, pid, name))
-    except device_errors.AdbShellCommandFailedError:
-      pass
+      for process in adb.ListProcesses(process_filter):
+        if default_pid and process.pid != default_pid:
+          continue
+        userid = DeviceHelper.__GetUserIdForProcessName(adb, process.name)
+        pids.append((userid, process.pid, process.name))
+    except device_errors.AdbShellCommandFailedError as exc:
+      logging.warning('Error getting PIDs to track: %s', exc)
     return sorted(pids, key=lambda tup: tup[0])
 
 class NetworkHelper(object):
diff --git a/tools/bisect_repackage/bisect_repackage.py b/tools/bisect_repackage/bisect_repackage.py
index 8538d34..d4c51d4 100644
--- a/tools/bisect_repackage/bisect_repackage.py
+++ b/tools/bisect_repackage/bisect_repackage.py
@@ -247,8 +247,13 @@
 def download_revision_map(context):
   """Downloads the revision map in original_gs_url in context."""
   download_file = '%s/%s' % (context.repackage_remote_path, REVISION_MAP_FILE)
-  cloud_storage.Get(context.repackage_gs_bucket, download_file,
-                    context.revision_file)
+  try:
+    cloud_storage.Get(context.original_gs_bucket,
+                      remote_file_path, zip_file_name)
+  except Exception, e:
+    logging.warning('Failed to download: %s, error: %s', zip_file_name, e)
+    return False
+  return True
 
 
 def get_revision_map(context):
@@ -350,7 +355,8 @@
   archive_name = '%s_%s' %(context.file_prefix, cp_num)
   file_archive = os.path.join(staging_dir, archive_name)
   zip_file_name = '%s.zip' % (file_archive)
-  download_build(cp_num, revision_map, zip_file_name, context)
+  if not download_build(cp_num, revision_map, zip_file_name, context):
+    return
 
   extract_dir = os.path.join(staging_dir, archive_name)
   is_android = context.archive in ['arm', 'arm64']
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 0f99594..9a61624 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -26879,6 +26879,7 @@
   <int value="1019857902"
       label="disable-hide-inactive-stacked-tab-close-buttons"/>
   <int value="1022992701" label="enable-origin-chip-always"/>
+  <int value="1033148287" label="NTPShortcuts:disabled"/>
   <int value="1033412163" label="OmniboxDisplayTitleForCurrentUrl:enabled"/>
   <int value="1033597574" label="disable-layer-squashing"/>
   <int value="1036068554" label="enable-android-pay-integration-v2"/>
@@ -27197,6 +27198,7 @@
   <int value="1786229999" label="disable-md-downloads"/>
   <int value="1786386775" label="TranslateCompactUI:disabled"/>
   <int value="1789517771" label="MacV2Sandbox:enabled"/>
+  <int value="1792609232" label="NTPShortcuts:enabled"/>
   <int value="1803465156" label="enable-zero-suggest-most-visited"/>
   <int value="1809323887"
       label="AutofillUpstreamUseGooglePayBranding:disabled"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 0102332c..1ee4d94f 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -11443,7 +11443,8 @@
   </summary>
 </histogram>
 
-<histogram name="Compositing.SurfaceAggregator.SurfaceDrawQuad.MissingSurface">
+<histogram name="Compositing.SurfaceAggregator.SurfaceDrawQuad.MissingSurface"
+    units="quads">
   <owner>kylechar@chromium.org</owner>
   <summary>
     The number of SurfaceDrawQuads where the surface doesn't exist. This is
@@ -11451,7 +11452,8 @@
   </summary>
 </histogram>
 
-<histogram name="Compositing.SurfaceAggregator.SurfaceDrawQuad.NoActiveFrame">
+<histogram name="Compositing.SurfaceAggregator.SurfaceDrawQuad.NoActiveFrame"
+    units="quads">
   <owner>kylechar@chromium.org</owner>
   <summary>
     The number of SurfaceDrawQuads where the surface exists but doesn't have an
@@ -11460,16 +11462,18 @@
 </histogram>
 
 <histogram
-    name="Compositing.SurfaceAggregator.SurfaceDrawQuad.UsingFallbackSurface">
+    name="Compositing.SurfaceAggregator.SurfaceDrawQuad.UsingFallbackSurface"
+    units="quads">
   <owner>fsamuel@chromium.org</owner>
   <summary>
-    The number of SurfaceDrawQuads where the primary SurfaceId doe not have a
+    The number of SurfaceDrawQuads where the primary SurfaceId does not have a
     corresponding active CompositorFrame and so the fallback surface is used
     instead. This is logged for each call to Aggregate().
   </summary>
 </histogram>
 
-<histogram name="Compositing.SurfaceAggregator.SurfaceDrawQuad.ValidSurface">
+<histogram name="Compositing.SurfaceAggregator.SurfaceDrawQuad.ValidSurface"
+    units="quads">
   <owner>kylechar@chromium.org</owner>
   <summary>
     The number of SurfaceDrawQuads where the surface exists and has an active
@@ -38045,6 +38049,9 @@
 </histogram>
 
 <histogram name="Memory.Browser.Committed" units="MB">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>bashi@chromium.org</owner>
   <owner>kouhei@chromium.org</owner>
   <summary>
@@ -38123,6 +38130,9 @@
 </histogram>
 
 <histogram name="Memory.ChromeProcessCount" units="processes">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -38577,6 +38587,9 @@
 </histogram>
 
 <histogram name="Memory.ExtensionProcessCount" units="processes">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -38786,6 +38799,9 @@
 </histogram>
 
 <histogram name="Memory.OtherProcessCount" units="processes">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -38833,6 +38849,9 @@
 </histogram>
 
 <histogram name="Memory.PepperPluginBrokerProcessCount" units="processes">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -38843,6 +38862,9 @@
 </histogram>
 
 <histogram name="Memory.PepperPluginProcessCount" units="processes">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -38894,6 +38916,9 @@
 </histogram>
 
 <histogram name="Memory.ProcessCount" units="processes">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -38903,6 +38928,9 @@
 </histogram>
 
 <histogram name="Memory.ProcessLimit">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -38924,6 +38952,9 @@
 </histogram>
 
 <histogram name="Memory.Renderer.Committed" units="MB">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>bashi@chromium.org</owner>
   <owner>kouhei@chromium.org</owner>
   <summary>
@@ -39003,6 +39034,9 @@
 </histogram>
 
 <histogram name="Memory.RendererGrowthIn30Min" units="KB">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39020,6 +39054,9 @@
 </histogram>
 
 <histogram name="Memory.RendererProcessCount" units="processes">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39029,6 +39066,9 @@
 </histogram>
 
 <histogram name="Memory.RendererShrinkIn30Min" units="KB">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39206,6 +39246,9 @@
 </histogram>
 
 <histogram name="Memory.Swap.Browser" units="KB">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39216,6 +39259,9 @@
 </histogram>
 
 <histogram name="Memory.Swap.Chrome" units="KB">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39226,6 +39272,9 @@
 </histogram>
 
 <histogram name="Memory.Swap.CompressedDataSize" units="MB">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39236,6 +39285,9 @@
 </histogram>
 
 <histogram name="Memory.Swap.CompressionRatio">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39246,6 +39298,9 @@
 </histogram>
 
 <histogram name="Memory.Swap.Extension" units="KB">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39256,6 +39311,9 @@
 </histogram>
 
 <histogram name="Memory.Swap.Gpu" units="KB">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39266,6 +39324,9 @@
 </histogram>
 
 <histogram name="Memory.Swap.HaveSwapped" enum="BooleanSuccess">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39276,6 +39337,9 @@
 </histogram>
 
 <histogram name="Memory.Swap.MemUsedTotal" units="MB">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39286,6 +39350,9 @@
 </histogram>
 
 <histogram name="Memory.Swap.NativeClient" units="KB">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39297,6 +39364,9 @@
 </histogram>
 
 <histogram name="Memory.Swap.NativeClientBroker" units="KB">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39308,6 +39378,9 @@
 </histogram>
 
 <histogram name="Memory.Swap.NumReads">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39318,6 +39391,9 @@
 </histogram>
 
 <histogram name="Memory.Swap.NumWrites">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39328,6 +39404,9 @@
 </histogram>
 
 <histogram name="Memory.Swap.OriginalDataSize" units="MB">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39338,6 +39417,9 @@
 </histogram>
 
 <histogram name="Memory.Swap.PepperPlugin" units="KB">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39349,6 +39431,9 @@
 </histogram>
 
 <histogram name="Memory.Swap.PepperPluginBroker" units="KB">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39373,6 +39458,9 @@
 </histogram>
 
 <histogram name="Memory.Swap.Renderer" units="KB">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39383,6 +39471,9 @@
 </histogram>
 
 <histogram name="Memory.Swap.SandboxHelper" units="KB">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39394,6 +39485,9 @@
 </histogram>
 
 <histogram name="Memory.Swap.Total" units="MB">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39405,6 +39499,9 @@
 </histogram>
 
 <histogram name="Memory.Swap.Total2" units="MiB">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39416,6 +39513,9 @@
 </histogram>
 
 <histogram name="Memory.Swap.Utility" units="KB">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39436,6 +39536,9 @@
 </histogram>
 
 <histogram name="Memory.Swap.Zygote" units="KB">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
@@ -39513,6 +39616,9 @@
 </histogram>
 
 <histogram name="Memory.WorkerProcessCount" units="processes">
+  <obsolete>
+    Deprecated 03/2018. No direct replacement.
+  </obsolete>
   <owner>hajimehoshi@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>kouhei@chromium.org</owner>
diff --git a/tools/perf/benchmarks/start_with_url.py b/tools/perf/benchmarks/start_with_url.py
index ea2e2f9..d8fb3ac 100644
--- a/tools/perf/benchmarks/start_with_url.py
+++ b/tools/perf/benchmarks/start_with_url.py
@@ -91,8 +91,8 @@
   def CreateCoreTimelineBasedMeasurementOptions(self):
     startup_category_filter = (
         chrome_trace_category_filter.ChromeTraceCategoryFilter(
-            filter_string=('loading,net,netlog,network,offline_pages,'
-                'startup,toplevel,Java,EarlyJava')))
+            filter_string=('navigation,loading,net,netlog,network,'
+                'offline_pages,startup,toplevel,Java,EarlyJava')))
     options = timeline_based_measurement.Options(
         overhead_level=startup_category_filter)
     options.config.enable_chrome_trace = True
diff --git a/ui/accessibility/ax_enum_util.cc b/ui/accessibility/ax_enum_util.cc
index 41620698..b9d4c9e5 100644
--- a/ui/accessibility/ax_enum_util.cc
+++ b/ui/accessibility/ax_enum_util.cc
@@ -32,6 +32,8 @@
       return "expandedChanged";
     case ax::mojom::Event::kFocus:
       return "focus";
+    case ax::mojom::Event::kFocusContext:
+      return "focusContext";
     case ax::mojom::Event::kHide:
       return "hide";
     case ax::mojom::Event::kHitTestResult:
diff --git a/ui/accessibility/ax_enums.mojom b/ui/accessibility/ax_enums.mojom
index 0d84da64..fa08af4 100644
--- a/ui/accessibility/ax_enums.mojom
+++ b/ui/accessibility/ax_enums.mojom
@@ -38,6 +38,7 @@
   kDocumentSelectionChanged,
   kExpandedChanged,           // Web
   kFocus,
+  kFocusContext,              // Contextual focus event that must delay the next focus event
   kHide,                      // Remove: http://crbug.com/392502
   kHitTestResult,
   kHover,
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc
index b502a678..ed48d12 100644
--- a/ui/accessibility/platform/ax_platform_node_auralinux.cc
+++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -1113,6 +1113,7 @@
     ax::mojom::Event event_type) {
   switch (event_type) {
     case ax::mojom::Event::kFocus:
+    case ax::mojom::Event::kFocusContext:
       OnFocused();
       break;
     default:
diff --git a/ui/accessibility/platform/ax_platform_node_mac.mm b/ui/accessibility/platform/ax_platform_node_mac.mm
index 6a439f1..81677fc 100644
--- a/ui/accessibility/platform/ax_platform_node_mac.mm
+++ b/ui/accessibility/platform/ax_platform_node_mac.mm
@@ -200,6 +200,8 @@
   const EventMap::value_type events[] = {
       {ax::mojom::Event::kFocus,
        NSAccessibilityFocusedUIElementChangedNotification},
+      {ax::mojom::Event::kFocusContext,
+       NSAccessibilityFocusedUIElementChangedNotification},
       {ax::mojom::Event::kTextChanged, NSAccessibilityTitleChangedNotification},
       {ax::mojom::Event::kValueChanged,
        NSAccessibilityValueChangedNotification},
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc
index b3c5d35..1173f486 100644
--- a/ui/accessibility/platform/ax_platform_node_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -3564,6 +3564,7 @@
     case ax::mojom::Event::kExpandedChanged:
       return EVENT_OBJECT_STATECHANGE;
     case ax::mojom::Event::kFocus:
+    case ax::mojom::Event::kFocusContext:
       return EVENT_OBJECT_FOCUS;
     case ax::mojom::Event::kMenuStart:
       return EVENT_SYSTEM_MENUSTART;
diff --git a/ui/android/java/res/values-v17/styles.xml b/ui/android/java/res/values-v17/styles.xml
index 9a84b39..5694b47 100644
--- a/ui/android/java/res/values-v17/styles.xml
+++ b/ui/android/java/res/values-v17/styles.xml
@@ -7,10 +7,6 @@
 -->
 
 <resources xmlns:tools="http://schemas.android.com/tools">
-    <style name="DropdownPopupWindow" parent="@android:style/Widget.ListPopupWindow">
-        <item name="android:popupBackground">@drawable/dropdown_popup_background</item>
-    </style>
-
     <!-- Buttons -->
     <style name="ButtonCompatOverlay">
         <item name="android:buttonStyle">@style/ButtonCompat</item>
diff --git a/ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java b/ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java
index e0dd191..337db5f 100644
--- a/ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java
+++ b/ui/android/java/src/org/chromium/ui/DropdownPopupWindow.java
@@ -6,25 +6,23 @@
 
 import android.content.Context;
 import android.graphics.Rect;
-import android.util.Log;
+import android.graphics.drawable.Drawable;
 import android.view.View;
 import android.view.View.OnLayoutChangeListener;
-import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.AdapterView;
 import android.widget.ListAdapter;
-import android.widget.ListPopupWindow;
 import android.widget.ListView;
 import android.widget.PopupWindow;
 
 import org.chromium.base.ApiCompatibilityUtils;
-
-import java.lang.reflect.Method;
+import org.chromium.ui.widget.AnchoredPopupWindow;
+import org.chromium.ui.widget.ViewRectProvider;
 
 /**
  * The dropdown list popup window.
  */
-public class DropdownPopupWindow {
+public class DropdownPopupWindow implements AnchoredPopupWindow.LayoutObserver {
     private final Context mContext;
     private final View mAnchorView;
     private boolean mRtl;
@@ -32,8 +30,10 @@
     private OnLayoutChangeListener mLayoutChangeListener;
     private PopupWindow.OnDismissListener mOnDismissListener;
     private CharSequence mDescription;
-    private ListPopupWindow mListPopupWindow;
+    private AnchoredPopupWindow mAnchoredPopupWindow;
     ListAdapter mAdapter;
+    private ListView mListView;
+    private Drawable mBackground;
 
     /**
      * Creates an DropdownPopupWindow with specified parameters.
@@ -41,7 +41,6 @@
      * @param anchorView Popup view to be anchored.
      */
     public DropdownPopupWindow(Context context, View anchorView) {
-        mListPopupWindow = new ListPopupWindow(context, null, 0, R.style.DropdownPopupWindow);
         mContext = context;
         mAnchorView = anchorView;
 
@@ -57,7 +56,7 @@
         };
         mAnchorView.addOnLayoutChangeListener(mLayoutChangeListener);
 
-        mListPopupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
+        PopupWindow.OnDismissListener onDismissLitener = new PopupWindow.OnDismissListener() {
             @Override
             public void onDismiss() {
                 if (mOnDismissListener != null) {
@@ -66,12 +65,16 @@
                 mAnchorView.removeOnLayoutChangeListener(mLayoutChangeListener);
                 mAnchorView.setTag(null);
             }
-        });
-
-        mListPopupWindow.setAnchorView(mAnchorView);
-        Rect originalPadding = new Rect();
-        mListPopupWindow.getBackground().getPadding(originalPadding);
-        mListPopupWindow.setVerticalOffset(-originalPadding.top);
+        };
+        mListView = new ListView(context);
+        ViewRectProvider rectProvider = new ViewRectProvider(mAnchorView);
+        rectProvider.setIncludePadding(true);
+        mBackground = ApiCompatibilityUtils.getDrawable(
+                context.getResources(), R.drawable.dropdown_popup_background);
+        mAnchoredPopupWindow =
+                new AnchoredPopupWindow(context, mAnchorView, mBackground, mListView, rectProvider);
+        mAnchoredPopupWindow.addOnDismissListener(onDismissLitener);
+        mAnchoredPopupWindow.setLayoutObserver(this);
     }
 
     /**
@@ -82,9 +85,20 @@
      */
     public void setAdapter(ListAdapter adapter) {
         mAdapter = adapter;
-        mListPopupWindow.setAdapter(adapter);
+        mListView.setAdapter(adapter);
+        mAnchoredPopupWindow.onRectChanged();
     }
 
+    @Override
+    public void onPreLayoutChange(
+            boolean positionBelow, int x, int y, int width, int height, Rect anchorRect) {
+        mBackground.setBounds(anchorRect);
+        mAnchoredPopupWindow.setBackgroundDrawable(positionBelow
+                        ? ApiCompatibilityUtils.getDrawable(mContext.getResources(),
+                                  R.drawable.dropdown_popup_background_down)
+                        : ApiCompatibilityUtils.getDrawable(mContext.getResources(),
+                                  R.drawable.dropdown_popup_background_up));
+    }
 
     public void setInitialSelection(int initialSelection) {
         mInitialSelection = initialSelection;
@@ -94,37 +108,23 @@
      * Shows the popup. The adapter should be set before calling this method.
      */
     public void show() {
-        // An ugly hack to keep the popup from expanding on top of the keyboard.
-        mListPopupWindow.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NEEDED);
-
         assert mAdapter != null : "Set the adapter before showing the popup.";
-        final int contentWidth = UiUtils.computeMaxWidthOfListAdapterItems(mAdapter);
-        final float anchorWidth = mAnchorView.getLayoutParams().width;
-        assert anchorWidth > 0;
-        Rect padding = new Rect();
-        mListPopupWindow.getBackground().getPadding(padding);
-        if (contentWidth + padding.left + padding.right > anchorWidth) {
-            mListPopupWindow.setContentWidth(contentWidth);
-            final Rect displayFrame = new Rect();
-            mAnchorView.getWindowVisibleDisplayFrame(displayFrame);
-            if (mListPopupWindow.getWidth() > displayFrame.width()) {
-                mListPopupWindow.setWidth(displayFrame.width());
-            }
-        } else {
-            mListPopupWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
-        }
-        boolean wasShowing = mListPopupWindow.isShowing();
-        mListPopupWindow.show();
-        mListPopupWindow.getListView().setDividerHeight(0);
-        ApiCompatibilityUtils.setLayoutDirection(mListPopupWindow.getListView(),
-                mRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
+        boolean wasShowing = mAnchoredPopupWindow.isShowing();
+        mAnchoredPopupWindow.setVerticalOverlapAnchor(false);
+        mAnchoredPopupWindow.setHorizontalOverlapAnchor(true);
+        mAnchoredPopupWindow.setMaxWidth(measureContentWidth()
+                + mContext.getResources().getDimensionPixelSize(
+                          R.dimen.dropdown_item_label_margin));
+        mAnchoredPopupWindow.show();
+        mListView.setDividerHeight(0);
+        ApiCompatibilityUtils.setLayoutDirection(
+                mListView, mRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
         if (!wasShowing) {
-            mListPopupWindow.getListView().setContentDescription(mDescription);
-            mListPopupWindow.getListView().sendAccessibilityEvent(
-                    AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+            mListView.setContentDescription(mDescription);
+            mListView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
         }
         if (mInitialSelection >= 0) {
-            mListPopupWindow.getListView().setSelection(mInitialSelection);
+            mListView.setSelection(mInitialSelection);
             mInitialSelection = -1;
         }
     }
@@ -151,19 +151,7 @@
      * will not hide the popup.
      */
     public void disableHideOnOutsideTap() {
-        // HACK: The ListPopupWindow's mPopup automatically dismisses on an outside tap. There's
-        // no way to override it or prevent it, except reaching into ListPopupWindow's hidden
-        // API. This allows the C++ controller to completely control showing/hiding the popup.
-        // See http://crbug.com/400601
-        try {
-            Method setForceIgnoreOutsideTouch = ListPopupWindow.class.getMethod(
-                    "setForceIgnoreOutsideTouch", new Class[] { boolean.class });
-            setForceIgnoreOutsideTouch.invoke(mListPopupWindow, new Object[] {true});
-        } catch (Exception e) {
-            Log.e("AutofillPopup",
-                    "ListPopupWindow.setForceIgnoreOutsideTouch not found",
-                    e);
-        }
+        mAnchoredPopupWindow.setDismissOnTouchInteraction(false);
     }
 
     /**
@@ -181,7 +169,7 @@
      * @param clickListener Listener to register
      */
     public void setOnItemClickListener(AdapterView.OnItemClickListener clickListener) {
-        mListPopupWindow.setOnItemClickListener(clickListener);
+        mListView.setOnItemClickListener(clickListener);
     }
 
     /**
@@ -189,28 +177,28 @@
      * Post a {@link #show()} call to the UI thread.
      */
     public void postShow() {
-        mListPopupWindow.postShow();
+        mAnchoredPopupWindow.show();
     }
 
     /**
      * Disposes of the popup window.
      */
     public void dismiss() {
-        mListPopupWindow.dismiss();
+        mAnchoredPopupWindow.dismiss();
     }
 
     /**
      * @return The {@link ListView} displayed within the popup window.
      */
     public ListView getListView() {
-        return mListPopupWindow.getListView();
+        return mListView;
     }
 
     /**
      * @return Whether the popup is currently showing.
      */
     public boolean isShowing() {
-        return mListPopupWindow.isShowing();
+        return mAnchoredPopupWindow.isShowing();
     }
 
     /**
diff --git a/ui/android/java/src/org/chromium/ui/widget/AnchoredPopupWindow.java b/ui/android/java/src/org/chromium/ui/widget/AnchoredPopupWindow.java
index c05845c..f63ce78 100644
--- a/ui/android/java/src/org/chromium/ui/widget/AnchoredPopupWindow.java
+++ b/ui/android/java/src/org/chromium/ui/widget/AnchoredPopupWindow.java
@@ -149,7 +149,8 @@
 
     private boolean mPositionBelow;
     private boolean mPositionToLeft;
-    private boolean mOverlapAnchor;
+    private boolean mVerticalOverlapAnchor;
+    private boolean mHorizontalOverlapAnchor;
 
     /**
      * Constructs an {@link AnchoredPopupWindow} instance.
@@ -295,12 +296,29 @@
     }
 
     /**
-     * Sets whether the popup should overlap the anchor {@link Rect}. Defaults to false.  This
-     * should be called before the popup is shown.
+     * Sets whether the popup should horizontally overlap the anchor {@link Rect}.
+     * Defaults to false.  This should be called before the popup is shown.
      * @param overlap Whether the popup should overlap the anchor.
      */
-    public void setOverlapAnchor(boolean overlap) {
-        mOverlapAnchor = overlap;
+    public void setHorizontalOverlapAnchor(boolean overlap) {
+        mHorizontalOverlapAnchor = overlap;
+    }
+
+    /**
+     * Sets whether the popup should vertically overlap the anchor {@link Rect}.
+     * Defaults to false.  This should be called before the popup is shown.
+     * @param overlap Whether the popup should overlap the anchor.
+     */
+    public void setVerticalOverlapAnchor(boolean overlap) {
+        mVerticalOverlapAnchor = overlap;
+    }
+
+    /**
+     * Changes the background of the popup.
+     * @param background The {@link Drawable} that is set to be background.
+     */
+    public void setBackgroundDrawable(Drawable background) {
+        mPopupWindow.setBackgroundDrawable(background);
     }
 
     // RectProvider.Observer implementation.
@@ -353,10 +371,11 @@
         // TODO(dtrainor): This follows the previous logic.  But we should look into if we want to
         // use the root view dimensions instead of the window dimensions here so the popup can't
         // bleed onto the decorations.
-        int spaceAboveAnchor = (mOverlapAnchor ? anchorRect.bottom : anchorRect.top)
+        int spaceAboveAnchor = (mVerticalOverlapAnchor ? anchorRect.bottom : anchorRect.top)
                 - mCachedWindowRect.top - paddingY - mMarginPx;
         int spaceBelowAnchor = mCachedWindowRect.bottom
-                - (mOverlapAnchor ? anchorRect.top : anchorRect.bottom) - paddingY - mMarginPx;
+                - (mVerticalOverlapAnchor ? anchorRect.top : anchorRect.bottom) - paddingY
+                - mMarginPx;
 
         // Bias based on the center of the popup and where it is on the screen.
         boolean idealFitsBelow = idealContentHeight <= spaceBelowAnchor;
@@ -382,9 +401,9 @@
 
         if (mPreferredHorizontalOrientation == HORIZONTAL_ORIENTATION_MAX_AVAILABLE_SPACE) {
             int spaceLeftOfAnchor =
-                    getSpaceLeftOfAnchor(anchorRect, mCachedWindowRect, mOverlapAnchor);
+                    getSpaceLeftOfAnchor(anchorRect, mCachedWindowRect, mHorizontalOverlapAnchor);
             int spaceRightOfAnchor =
-                    getSpaceRightOfAnchor(anchorRect, mCachedWindowRect, mOverlapAnchor);
+                    getSpaceRightOfAnchor(anchorRect, mCachedWindowRect, mHorizontalOverlapAnchor);
             mPositionToLeft = shouldPositionLeftOfAnchor(spaceLeftOfAnchor, spaceRightOfAnchor,
                     idealContentWidth + paddingY + mMarginPx, currentPositionToLeft,
                     preferCurrentOrientation);
@@ -401,9 +420,9 @@
         mHeight = contentView.getMeasuredHeight() + paddingY;
 
         // Determine the position of the text popup.
-        mX = getPopupX(anchorRect, mCachedWindowRect, mWidth, mMarginPx, mOverlapAnchor,
+        mX = getPopupX(anchorRect, mCachedWindowRect, mWidth, mMarginPx, mHorizontalOverlapAnchor,
                 mPreferredHorizontalOrientation, mPositionToLeft);
-        mY = getPopupY(anchorRect, mHeight, mOverlapAnchor, mPositionBelow);
+        mY = getPopupY(anchorRect, mHeight, mVerticalOverlapAnchor, mPositionBelow);
 
         if (mLayoutObserver != null) {
             mLayoutObserver.onPreLayoutChange(mPositionBelow, mX, mY, mWidth, mHeight, anchorRect);
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn
index c72fd583..9179229e 100644
--- a/ui/aura/BUILD.gn
+++ b/ui/aura/BUILD.gn
@@ -43,6 +43,8 @@
     "mus/client_surface_embedder.h",
     "mus/drag_drop_controller_host.h",
     "mus/drag_drop_controller_mus.h",
+    "mus/embed_root.h",
+    "mus/embed_root_delegate.h",
     "mus/focus_synchronizer.h",
     "mus/focus_synchronizer_delegate.h",
     "mus/focus_synchronizer_observer.h",
@@ -110,6 +112,7 @@
     "mus/capture_synchronizer.cc",
     "mus/client_surface_embedder.cc",
     "mus/drag_drop_controller_mus.cc",
+    "mus/embed_root.cc",
     "mus/focus_synchronizer.cc",
     "mus/in_flight_change.cc",
     "mus/input_method_mus.cc",
diff --git a/ui/aura/mus/embed_root.cc b/ui/aura/mus/embed_root.cc
new file mode 100644
index 0000000..c3b05e0
--- /dev/null
+++ b/ui/aura/mus/embed_root.cc
@@ -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.
+
+#include "ui/aura/mus/embed_root.h"
+
+#include "base/auto_reset.h"
+#include "base/bind.h"
+#include "ui/aura/mus/embed_root_delegate.h"
+#include "ui/aura/mus/window_tree_client.h"
+#include "ui/aura/window_tree_host.h"
+
+namespace aura {
+
+EmbedRoot::~EmbedRoot() {
+  window_tree_client_->OnEmbedRootDestroyed(this);
+}
+
+aura::Window* EmbedRoot::window() {
+  return window_tree_host_ ? window_tree_host_->window() : nullptr;
+}
+
+EmbedRoot::EmbedRoot(WindowTreeClient* window_tree_client,
+                     EmbedRootDelegate* delegate,
+                     ui::ClientSpecificId window_id)
+    : window_tree_client_(window_tree_client),
+      delegate_(delegate),
+      weak_factory_(this) {
+  window_tree_client_->tree_->ScheduleEmbedForExistingClient(
+      window_id, base::BindOnce(&EmbedRoot::OnScheduledEmbedForExistingClient,
+                                weak_factory_.GetWeakPtr()));
+}
+
+void EmbedRoot::OnScheduledEmbedForExistingClient(
+    const base::UnguessableToken& token) {
+  token_ = token;
+  delegate_->OnEmbedTokenAvailable(token);
+}
+
+void EmbedRoot::OnEmbed(std::unique_ptr<WindowTreeHost> window_tree_host) {
+  window_tree_host_ = std::move(window_tree_host);
+  delegate_->OnEmbed(window());
+}
+
+void EmbedRoot::OnUnembed() {
+  delegate_->OnUnembed();
+}
+
+}  // namespace aura
diff --git a/ui/aura/mus/embed_root.h b/ui/aura/mus/embed_root.h
new file mode 100644
index 0000000..7e60c99
--- /dev/null
+++ b/ui/aura/mus/embed_root.h
@@ -0,0 +1,73 @@
+// 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_AURA_MUS_EMBED_ROOT_H_
+#define UI_AURA_MUS_EMBED_ROOT_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/unguessable_token.h"
+#include "services/ui/common/types.h"
+#include "ui/aura/aura_export.h"
+
+namespace aura {
+
+class EmbedRootDelegate;
+class Window;
+class WindowTreeClient;
+class WindowTreeHost;
+
+// EmbedRoot represents a secondary embedding from the perspective of the
+// embedded client. More specifically an EmbedRoot allows a remote client to
+// embed this client in one of the remote client's Windows.
+//
+// See EmbedRootDelegate for details on how to use.
+//
+// EmbedRoot is created by way of WindowTreeClient::CreateEmbedRoot().
+class AURA_EXPORT EmbedRoot {
+ public:
+  ~EmbedRoot();
+
+  // Token for the embedding. Empty until OnEmbedTokenAvailable() is called on
+  // the delegate.
+  const base::UnguessableToken& token() const { return token_; }
+
+  // Window for the embedding, null until the OnEmbed() is called on the
+  // delegate.
+  aura::Window* window();
+
+ private:
+  friend class WindowTreeClient;
+
+  EmbedRoot(WindowTreeClient* window_tree_client,
+            EmbedRootDelegate* delegate,
+            ui::ClientSpecificId window_id);
+
+  // Callback from WindowTreeClient once the token has been determined.
+  void OnScheduledEmbedForExistingClient(const base::UnguessableToken& token);
+
+  // Called from WindowTreeClient when the embedding is established.
+  void OnEmbed(std::unique_ptr<WindowTreeHost> window_tree_host);
+
+  // Called from WindowTreeClient when unembedded from the Window.
+  void OnUnembed();
+
+  WindowTreeClient* window_tree_client_;
+
+  EmbedRootDelegate* delegate_;
+
+  base::UnguessableToken token_;
+
+  std::unique_ptr<WindowTreeHost> window_tree_host_;
+
+  base::WeakPtrFactory<EmbedRoot> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(EmbedRoot);
+};
+
+}  // namespace aura
+
+#endif  // UI_AURA_MUS_EMBED_ROOT_H_
diff --git a/ui/aura/mus/embed_root_delegate.h b/ui/aura/mus/embed_root_delegate.h
new file mode 100644
index 0000000..e2c6cd4
--- /dev/null
+++ b/ui/aura/mus/embed_root_delegate.h
@@ -0,0 +1,41 @@
+// 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_AURA_MUS_EMBED_ROOT_DELEGATE_H_
+#define UI_AURA_MUS_EMBED_ROOT_DELEGATE_H_
+
+#include "ui/aura/aura_export.h"
+
+namespace base {
+class UnguessableToken;
+}
+
+namespace aura {
+
+class Window;
+
+// Called from EmbedRoot at key points during the life-time of the embedding.
+class AURA_EXPORT EmbedRootDelegate {
+ public:
+  // Called first in the process of establishing an embedding. |token| is used
+  // by a remote client to embed this client in one of the remote client's
+  // windows. The delegate will typically pass the supplied token over mojo and
+  // the remote client will then call WindowTreeClient::EmbedUsingToken().
+  virtual void OnEmbedTokenAvailable(const base::UnguessableToken& token) = 0;
+
+  // Called once the embedding has been established. |window| is the root of
+  // the embedding and owned by the remote client.
+  virtual void OnEmbed(Window* window) = 0;
+
+  // Called if the remote client embeds another client in the root. The delegate
+  // will typically delete the EmbedRoot shortly after receiving this.
+  virtual void OnUnembed() = 0;
+
+ protected:
+  virtual ~EmbedRootDelegate() {}
+};
+
+}  // namespace aura
+
+#endif  // UI_AURA_MUS_EMBED_ROOT_DELEGATE_H_
diff --git a/ui/aura/mus/window_port_mus.cc b/ui/aura/mus/window_port_mus.cc
index 3f992885..16d6f490 100644
--- a/ui/aura/mus/window_port_mus.cc
+++ b/ui/aura/mus/window_port_mus.cc
@@ -103,6 +103,14 @@
                              std::move(callback));
 }
 
+void WindowPortMus::EmbedUsingToken(
+    const base::UnguessableToken& token,
+    uint32_t flags,
+    ui::mojom::WindowTree::EmbedCallback callback) {
+  window_tree_client_->EmbedUsingToken(window_, token, flags,
+                                       std::move(callback));
+}
+
 std::unique_ptr<viz::ClientLayerTreeFrameSink>
 WindowPortMus::RequestLayerTreeFrameSink(
     scoped_refptr<viz::ContextProvider> context_provider,
diff --git a/ui/aura/mus/window_port_mus.h b/ui/aura/mus/window_port_mus.h
index 1f0e3dd..b1b272a44 100644
--- a/ui/aura/mus/window_port_mus.h
+++ b/ui/aura/mus/window_port_mus.h
@@ -94,6 +94,9 @@
   void Embed(ui::mojom::WindowTreeClientPtr client,
              uint32_t flags,
              ui::mojom::WindowTree::EmbedCallback callback);
+  void EmbedUsingToken(const base::UnguessableToken& token,
+                       uint32_t flags,
+                       ui::mojom::WindowTree::EmbedCallback callback);
 
   std::unique_ptr<viz::ClientLayerTreeFrameSink> RequestLayerTreeFrameSink(
       scoped_refptr<viz::ContextProvider> context_provider,
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc
index 1209491..40bcfd4 100644
--- a/ui/aura/mus/window_tree_client.cc
+++ b/ui/aura/mus/window_tree_client.cc
@@ -38,6 +38,8 @@
 #include "ui/aura/env_input_state_controller.h"
 #include "ui/aura/mus/capture_synchronizer.h"
 #include "ui/aura/mus/drag_drop_controller_mus.h"
+#include "ui/aura/mus/embed_root.h"
+#include "ui/aura/mus/embed_root_delegate.h"
 #include "ui/aura/mus/focus_synchronizer.h"
 #include "ui/aura/mus/in_flight_change.h"
 #include "ui/aura/mus/input_method_mus.h"
@@ -291,6 +293,10 @@
   for (auto& pair : windows)
     WindowPortForShutdown::Install(pair.second->GetWindow());
 
+  // EmbedRoots keep a reference to this; so they must all be destroyed before
+  // the destructor completes.
+  DCHECK(embed_roots_.empty());
+
   env->WindowTreeClientDestroyed(this);
   CHECK(windows_.empty());
 }
@@ -364,6 +370,27 @@
                        base::AdaptCallbackForRepeating(std::move(callback)));
 }
 
+void WindowTreeClient::EmbedUsingToken(
+    Window* window,
+    const base::UnguessableToken& token,
+    uint32_t flags,
+    ui::mojom::WindowTree::EmbedCallback callback) {
+  DCHECK(tree_);
+  // Window::Init() must be called before Embed() (otherwise the server hasn't
+  // been told about the window).
+  DCHECK(window->layer());
+  if (!window->children().empty()) {
+    // The window server removes all children before embedding. In other words,
+    // it's generally an error to Embed() with existing children. So, fail
+    // early.
+    std::move(callback).Run(false);
+    return;
+  }
+
+  tree_->EmbedUsingToken(WindowMus::Get(window)->server_id(), token, flags,
+                         std::move(callback));
+}
+
 void WindowTreeClient::AttachCompositorFrameSink(
     ui::Id window_id,
     viz::mojom::CompositorFrameSinkRequest compositor_frame_sink,
@@ -373,6 +400,14 @@
                                    std::move(client));
 }
 
+std::unique_ptr<EmbedRoot> WindowTreeClient::CreateEmbedRoot(
+    EmbedRootDelegate* delegate) {
+  std::unique_ptr<EmbedRoot> embed_root =
+      base::WrapUnique(new EmbedRoot(this, delegate, next_window_id_++));
+  embed_roots_.insert(embed_root.get());
+  return embed_root;
+}
+
 WindowTreeClient::WindowTreeClient(
     service_manager::Connector* connector,
     WindowTreeClientDelegate* delegate,
@@ -756,6 +791,18 @@
   delegate_->OnEmbed(std::move(window_tree_host));
 }
 
+EmbedRoot* WindowTreeClient::GetEmbedRootWithRootWindow(aura::Window* window) {
+  for (EmbedRoot* embed_root : embed_roots_) {
+    if (embed_root->window() == window)
+      return embed_root;
+  }
+  return nullptr;
+}
+
+void WindowTreeClient::OnEmbedRootDestroyed(EmbedRoot* embed_root) {
+  embed_roots_.erase(embed_root);
+}
+
 WindowTreeHostMus* WindowTreeClient::WmNewDisplayAddedImpl(
     const display::Display& display,
     ui::mojom::WindowDataPtr root_data,
@@ -1211,6 +1258,20 @@
               focused_window_id, drawn, local_surface_id);
 }
 
+void WindowTreeClient::OnEmbedFromToken(
+    const base::UnguessableToken& token,
+    ui::mojom::WindowDataPtr root,
+    int64_t display_id,
+    const base::Optional<viz::LocalSurfaceId>& local_surface_id) {
+  for (EmbedRoot* embed_root : embed_roots_) {
+    if (embed_root->token() == token) {
+      embed_root->OnEmbed(CreateWindowTreeHost(WindowMusType::EMBED, *root,
+                                               display_id, local_surface_id));
+      break;
+    }
+  }
+}
+
 void WindowTreeClient::OnEmbeddedAppDisconnected(ui::Id window_id) {
   WindowMus* window = GetWindowByServerId(window_id);
   if (window)
@@ -1222,6 +1283,13 @@
   if (!window)
     return;
 
+  EmbedRoot* embed_root = GetEmbedRootWithRootWindow(window->GetWindow());
+  if (embed_root) {
+    embed_root->OnUnembed();
+    if (!GetWindowByServerId(window_id))
+      return;  // EmbedRoot was deleted, resulting in deleting window.
+  }
+
   delegate_->OnUnembed(window->GetWindow());
   delete window;
 }
@@ -1440,11 +1508,15 @@
   if (roots_.count(window)) {
     // Roots are associated with WindowTreeHosts. The WindowTreeHost owns the
     // root, so we have to delete the WindowTreeHost to indirectly delete the
-    // Window. Additionally clients may want to do extra processing before the
-    // delete, so call to the delegate to handle it. Let the window know it is
-    // going to be deleted so we don't callback to the server.
+    // Window. Clients may want to do extra processing before the delete,
+    // notify the appropriate delegate to handle the deletion. Let the window
+    // know it is going to be deleted so we don't callback to the server.
     window->PrepareForDestroy();
-    delegate_->OnEmbedRootDestroyed(GetWindowTreeHostMus(window));
+    EmbedRoot* embed_root = GetEmbedRootWithRootWindow(window->GetWindow());
+    if (embed_root)
+      embed_root->OnUnembed();
+    else
+      delegate_->OnEmbedRootDestroyed(GetWindowTreeHostMus(window));
   } else {
     window->DestroyFromServer();
   }
diff --git a/ui/aura/mus/window_tree_client.h b/ui/aura/mus/window_tree_client.h
index 38492d13..79354cd0 100644
--- a/ui/aura/mus/window_tree_client.h
+++ b/ui/aura/mus/window_tree_client.h
@@ -15,6 +15,7 @@
 
 #include "base/atomicops.h"
 #include "base/compiler_specific.h"
+#include "base/containers/flat_set.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
@@ -64,6 +65,8 @@
 namespace aura {
 class CaptureSynchronizer;
 class DragDropControllerMus;
+class EmbedRoot;
+class EmbedRootDelegate;
 class FocusSynchronizer;
 class InFlightBoundsChange;
 class InFlightChange;
@@ -166,6 +169,10 @@
              ui::mojom::WindowTreeClientPtr client,
              uint32_t flags,
              ui::mojom::WindowTree::EmbedCallback callback);
+  void EmbedUsingToken(Window* window,
+                       const base::UnguessableToken& token,
+                       uint32_t flags,
+                       ui::mojom::WindowTree::EmbedCallback callback);
 
   // Schedules an embed of a client. See
   // mojom::WindowTreeClient::ScheduleEmbed() for details.
@@ -173,6 +180,9 @@
       ui::mojom::WindowTreeClientPtr client,
       base::OnceCallback<void(const base::UnguessableToken&)> callback);
 
+  // Creates a new EmbedRoot. See EmbedRoot for details.
+  std::unique_ptr<EmbedRoot> CreateEmbedRoot(EmbedRootDelegate* delegate);
+
   void AttachCompositorFrameSink(
       ui::Id window_id,
       viz::mojom::CompositorFrameSinkRequest compositor_frame_sink,
@@ -203,6 +213,7 @@
   void RemoveTestObserver(WindowTreeClientTestObserver* observer);
 
  private:
+  friend class EmbedRoot;
   friend class InFlightBoundsChange;
   friend class InFlightFocusChange;
   friend class InFlightPropertyChange;
@@ -321,6 +332,12 @@
                    bool drawn,
                    const base::Optional<viz::LocalSurfaceId>& local_surface_id);
 
+  // Returns the EmbedRoot whose root is |window|, or null if there isn't one.
+  EmbedRoot* GetEmbedRootWithRootWindow(aura::Window* window);
+
+  // Called from EmbedRoot's destructor.
+  void OnEmbedRootDestroyed(EmbedRoot* embed_root);
+
   // Called by WmNewDisplayAdded().
   WindowTreeHostMus* WmNewDisplayAddedImpl(
       const display::Display& display,
@@ -385,6 +402,11 @@
       ui::Id focused_window_id,
       bool drawn,
       const base::Optional<viz::LocalSurfaceId>& local_surface_id) override;
+  void OnEmbedFromToken(
+      const base::UnguessableToken& token,
+      ui::mojom::WindowDataPtr root,
+      int64_t display_id,
+      const base::Optional<viz::LocalSurfaceId>& local_surface_id) override;
   void OnEmbeddedAppDisconnected(ui::Id window_id) override;
   void OnUnembed(ui::Id window_id) override;
   void OnCaptureChanged(ui::Id new_capture_window_id,
@@ -637,6 +659,8 @@
 
   std::set<WindowMus*> roots_;
 
+  base::flat_set<EmbedRoot*> embed_roots_;
+
   IdToWindowMap windows_;
   std::map<ui::ClientSpecificId, std::set<Window*>> embedded_windows_;
 
diff --git a/ui/aura/test/mus/change_completion_waiter.cc b/ui/aura/test/mus/change_completion_waiter.cc
index 56d44e47..930abce 100644
--- a/ui/aura/test/mus/change_completion_waiter.cc
+++ b/ui/aura/test/mus/change_completion_waiter.cc
@@ -24,7 +24,7 @@
 // all changes sent to mus have been acked.
 class AllChangesCompletedWaiter : public WindowTreeClientTestObserver {
  public:
-  AllChangesCompletedWaiter();
+  explicit AllChangesCompletedWaiter(WindowTreeClient* client);
   ~AllChangesCompletedWaiter() override;
 
   void Wait();
@@ -43,8 +43,8 @@
   DISALLOW_COPY_AND_ASSIGN(AllChangesCompletedWaiter);
 };
 
-AllChangesCompletedWaiter::AllChangesCompletedWaiter()
-    : client_(GetWindowTreeClient()) {}
+AllChangesCompletedWaiter::AllChangesCompletedWaiter(WindowTreeClient* client)
+    : client_(client) {}
 
 AllChangesCompletedWaiter::~AllChangesCompletedWaiter() = default;
 
@@ -110,10 +110,10 @@
   }
 }
 
-void WaitForAllChangesToComplete() {
+void WaitForAllChangesToComplete(WindowTreeClient* client) {
   if (Env::GetInstance()->mode() == Env::Mode::LOCAL)
     return;
-  AllChangesCompletedWaiter().Wait();
+  AllChangesCompletedWaiter(client ? client : GetWindowTreeClient()).Wait();
 }
 
 }  // namespace test
diff --git a/ui/aura/test/mus/change_completion_waiter.h b/ui/aura/test/mus/change_completion_waiter.h
index e149910..fe42a1e 100644
--- a/ui/aura/test/mus/change_completion_waiter.h
+++ b/ui/aura/test/mus/change_completion_waiter.h
@@ -53,10 +53,10 @@
   DISALLOW_COPY_AND_ASSIGN(ChangeCompletionWaiter);
 };
 
-// Under mus and mash, waits until there are no more pending changes on the
-// default window tree (e.g. window bounds, window visibility, cursor). Returns
-// immediately under classic ash because window operations are synchronous.
-void WaitForAllChangesToComplete();
+// Under mus and mash, waits until there are no more pending changes for
+// |client|. If |client| is null, the default is used. Returns immediately under
+// classic ash because window operations are synchronous.
+void WaitForAllChangesToComplete(WindowTreeClient* client = nullptr);
 
 }  // namespace test
 }  // namespace aura
diff --git a/ui/aura/test/mus/test_window_tree.cc b/ui/aura/test/mus/test_window_tree.cc
index e0cddb4d..d3bb905 100644
--- a/ui/aura/test/mus/test_window_tree.cc
+++ b/ui/aura/test/mus/test_window_tree.cc
@@ -280,6 +280,10 @@
                                      uint32_t embed_flags,
                                      EmbedUsingTokenCallback callback) {}
 
+void TestWindowTree::ScheduleEmbedForExistingClient(
+    ui::ClientSpecificId window_id,
+    ScheduleEmbedForExistingClientCallback callback) {}
+
 void TestWindowTree::SetFocus(uint32_t change_id, ui::Id window_id) {
   OnChangeReceived(change_id, WindowTreeChangeType::FOCUS);
 }
diff --git a/ui/aura/test/mus/test_window_tree.h b/ui/aura/test/mus/test_window_tree.h
index 4140b95..5ba297b0 100644
--- a/ui/aura/test/mus/test_window_tree.h
+++ b/ui/aura/test/mus/test_window_tree.h
@@ -202,6 +202,9 @@
                        const base::UnguessableToken& token,
                        uint32_t embed_flags,
                        EmbedUsingTokenCallback callback) override;
+  void ScheduleEmbedForExistingClient(
+      ui::ClientSpecificId window_id,
+      ScheduleEmbedForExistingClientCallback callback) override;
   void SetFocus(uint32_t change_id, ui::Id window_id) override;
   void SetCanFocus(ui::Id window_id, bool can_focus) override;
   void SetEventTargetingPolicy(ui::Id window_id,
diff --git a/ui/base/accelerators/accelerator.cc b/ui/base/accelerators/accelerator.cc
index 0694f74..a20b052 100644
--- a/ui/base/accelerators/accelerator.cc
+++ b/ui/base/accelerators/accelerator.cc
@@ -5,6 +5,7 @@
 #include "ui/base/accelerators/accelerator.h"
 
 #include <stdint.h>
+#include <tuple>
 
 #include "base/i18n/rtl.h"
 #include "base/logging.h"
@@ -39,10 +40,12 @@
 
 Accelerator::Accelerator(KeyboardCode key_code,
                          int modifiers,
-                         KeyState key_state)
+                         KeyState key_state,
+                         base::TimeTicks time_stamp)
     : key_code_(key_code),
       key_state_(key_state),
       modifiers_(modifiers & kInterestingFlagsMask),
+      time_stamp_(time_stamp),
       interrupted_by_mouse_event_(false) {}
 
 Accelerator::Accelerator(const KeyEvent& key_event)
@@ -51,12 +54,14 @@
                                                     : KeyState::RELEASED),
       // |modifiers_| may include the repeat flag.
       modifiers_(key_event.flags() & kInterestingFlagsMask),
+      time_stamp_(key_event.time_stamp()),
       interrupted_by_mouse_event_(false) {}
 
 Accelerator::Accelerator(const Accelerator& accelerator) {
   key_code_ = accelerator.key_code_;
   key_state_ = accelerator.key_state_;
   modifiers_ = accelerator.modifiers_;
+  time_stamp_ = accelerator.time_stamp_;
   interrupted_by_mouse_event_ = accelerator.interrupted_by_mouse_event_;
   if (accelerator.platform_accelerator_)
     platform_accelerator_ = accelerator.platform_accelerator_->CreateCopy();
@@ -74,7 +79,7 @@
   return KeyEvent(key_state() == Accelerator::KeyState::PRESSED
                       ? ET_KEY_PRESSED
                       : ET_KEY_RELEASED,
-                  key_code(), modifiers());
+                  key_code(), modifiers(), time_stamp());
 }
 
 Accelerator& Accelerator::operator=(const Accelerator& accelerator) {
@@ -82,6 +87,7 @@
     key_code_ = accelerator.key_code_;
     key_state_ = accelerator.key_state_;
     modifiers_ = accelerator.modifiers_;
+    time_stamp_ = accelerator.time_stamp_;
     interrupted_by_mouse_event_ = accelerator.interrupted_by_mouse_event_;
     if (accelerator.platform_accelerator_)
       platform_accelerator_ = accelerator.platform_accelerator_->CreateCopy();
@@ -92,14 +98,10 @@
 }
 
 bool Accelerator::operator <(const Accelerator& rhs) const {
-  if (key_code_ != rhs.key_code_)
-    return key_code_ < rhs.key_code_;
-  if (key_state_ != rhs.key_state_) {
-    return static_cast<int32_t>(key_state_) <
-           static_cast<int32_t>(rhs.key_state_);
-  }
-  return MaskOutKeyEventFlags(modifiers_) <
-         MaskOutKeyEventFlags(rhs.modifiers_);
+  const int modifiers_with_mask = MaskOutKeyEventFlags(modifiers_);
+  const int rhs_modifiers_with_mask = MaskOutKeyEventFlags(rhs.modifiers_);
+  return std::tie(key_code_, key_state_, modifiers_with_mask) <
+         std::tie(rhs.key_code_, rhs.key_state_, rhs_modifiers_with_mask);
 }
 
 bool Accelerator::operator ==(const Accelerator& rhs) const {
diff --git a/ui/base/accelerators/accelerator.h b/ui/base/accelerators/accelerator.h
index e6033bd..13c827a7 100644
--- a/ui/base/accelerators/accelerator.h
+++ b/ui/base/accelerators/accelerator.h
@@ -15,6 +15,7 @@
 #include <utility>
 
 #include "base/strings/string16.h"
+#include "base/time/time.h"
 #include "ui/base/accelerators/platform_accelerator.h"
 #include "ui/base/ui_base_export.h"
 #include "ui/events/event_constants.h"
@@ -44,7 +45,8 @@
   // NOTE: this constructor strips out non key related flags.
   Accelerator(KeyboardCode key_code,
               int modifiers,
-              KeyState key_state = KeyState::PRESSED);
+              KeyState key_state = KeyState::PRESSED,
+              base::TimeTicks time_stamp = base::TimeTicks());
   explicit Accelerator(const KeyEvent& key_event);
   Accelerator(const Accelerator& accelerator);
   ~Accelerator();
@@ -73,6 +75,8 @@
 
   int modifiers() const { return modifiers_; }
 
+  base::TimeTicks time_stamp() const { return time_stamp_; }
+
   bool IsShiftDown() const;
   bool IsCtrlDown() const;
   bool IsAltDown() const;
@@ -108,6 +112,9 @@
   // The state of the Shift/Ctrl/Alt keys. This corresponds to Event::flags().
   int modifiers_;
 
+  // The |time_stamp_| of the KeyEvent.
+  base::TimeTicks time_stamp_;
+
   // Stores platform specific data. May be NULL.
   // TODO: this is only used in Mac code and should be removed from here.
   // http://crbug.com/702823.
diff --git a/ui/base/accelerators/accelerator_unittest.cc b/ui/base/accelerators/accelerator_unittest.cc
index c6ec7b2..010755ea 100644
--- a/ui/base/accelerators/accelerator_unittest.cc
+++ b/ui/base/accelerators/accelerator_unittest.cc
@@ -5,6 +5,7 @@
 #include "ui/base/accelerators/accelerator.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/event.h"
 
 namespace ui {
 
@@ -19,4 +20,16 @@
   EXPECT_TRUE(accelerator_b_copy.IsRepeat());
 }
 
+TEST(AcceleratorTest, TimeStamp) {
+  const Accelerator accelerator_a(VKEY_A, EF_NONE);
+  EXPECT_EQ(base::TimeTicks(), accelerator_a.time_stamp());
+
+  const base::TimeTicks event_time =
+      base::TimeTicks() + base::TimeDelta::FromMilliseconds(1);
+  KeyEvent keyevent(ET_KEY_PRESSED, VKEY_SPACE, EF_NONE, event_time);
+
+  const Accelerator accelerator_b(keyevent);
+  EXPECT_EQ(event_time, accelerator_b.time_stamp());
+}
+
 }  // namespace ui
diff --git a/ui/base/accelerators/mojo/BUILD.gn b/ui/base/accelerators/mojo/BUILD.gn
index 3dd72e74..7682b707 100644
--- a/ui/base/accelerators/mojo/BUILD.gn
+++ b/ui/base/accelerators/mojo/BUILD.gn
@@ -9,6 +9,7 @@
     "accelerator.mojom",
   ]
   public_deps = [
+    "//mojo/common:common_custom_types",
     "//ui/events/mojo:interfaces",
   ]
 }
diff --git a/ui/base/accelerators/mojo/DEPS b/ui/base/accelerators/mojo/DEPS
new file mode 100644
index 0000000..6cfa565
--- /dev/null
+++ b/ui/base/accelerators/mojo/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+mojo/common",
+]
diff --git a/ui/base/accelerators/mojo/accelerator.mojom b/ui/base/accelerators/mojo/accelerator.mojom
index 9bb0329..d54cbf8 100644
--- a/ui/base/accelerators/mojo/accelerator.mojom
+++ b/ui/base/accelerators/mojo/accelerator.mojom
@@ -4,6 +4,7 @@
 
 module ui.mojom;
 
+import "mojo/common/time.mojom";
 import "ui/events/mojo/event_constants.mojom";
 import "ui/events/mojo/keyboard_codes.mojom";
 
@@ -20,4 +21,5 @@
   int32 key_code;
   AcceleratorKeyState key_state;
   int32 modifiers;
+  mojo.common.mojom.TimeTicks time_stamp;
 };
diff --git a/ui/base/accelerators/mojo/accelerator_struct_traits.h b/ui/base/accelerators/mojo/accelerator_struct_traits.h
index f42de0d..02f2da1 100644
--- a/ui/base/accelerators/mojo/accelerator_struct_traits.h
+++ b/ui/base/accelerators/mojo/accelerator_struct_traits.h
@@ -5,6 +5,7 @@
 #ifndef UI_BASE_ACCELERATORS_MOJO_ACCELERATOR_STRUCT_TRAITS_H_
 #define UI_BASE_ACCELERATORS_MOJO_ACCELERATOR_STRUCT_TRAITS_H_
 
+#include "mojo/common/time_struct_traits.h"
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/base/accelerators/mojo/accelerator.mojom.h"
 #include "ui/events/keycodes/keyboard_codes.h"
@@ -49,13 +50,18 @@
     return p.key_state();
   }
   static int32_t modifiers(const ui::Accelerator& p) { return p.modifiers(); }
+  static base::TimeTicks time_stamp(const ui::Accelerator& p) {
+    return p.time_stamp();
+  }
   static bool Read(ui::mojom::AcceleratorDataView data, ui::Accelerator* out) {
     ui::Accelerator::KeyState key_state;
     if (!data.ReadKeyState(&key_state))
       return false;
+    base::TimeTicks time_stamp;
+    if (!data.ReadTimeStamp(&time_stamp))
+      return false;
     *out = ui::Accelerator(static_cast<ui::KeyboardCode>(data.key_code()),
-                           data.modifiers());
-    out->set_key_state(key_state);
+                           data.modifiers(), key_state, time_stamp);
     return true;
   }
 };
diff --git a/ui/base/accelerators/mojo/accelerator_struct_traits_unittest.cc b/ui/base/accelerators/mojo/accelerator_struct_traits_unittest.cc
index 24256753..08c894fa 100644
--- a/ui/base/accelerators/mojo/accelerator_struct_traits_unittest.cc
+++ b/ui/base/accelerators/mojo/accelerator_struct_traits_unittest.cc
@@ -12,8 +12,10 @@
 namespace ui {
 
 TEST(AcceleratorStructTraitsTest, SerializeAndDeserialize1) {
-  Accelerator accelerator(KeyboardCode::VKEY_TAB, EF_NUM_LOCK_ON);
-  accelerator.set_key_state(ui::Accelerator::KeyState::RELEASED);
+  Accelerator accelerator(
+      KeyboardCode::VKEY_TAB, EF_NUM_LOCK_ON,
+      ui::Accelerator::KeyState::RELEASED,
+      base::TimeTicks() + base::TimeDelta::FromMilliseconds(1));
   Accelerator deserialized;
   ASSERT_TRUE(mojom::Accelerator::Deserialize(
       mojom::Accelerator::Serialize(&accelerator), &deserialized));
diff --git a/ui/base/ime/BUILD.gn b/ui/base/ime/BUILD.gn
index ee63a81..95dc069 100644
--- a/ui/base/ime/BUILD.gn
+++ b/ui/base/ime/BUILD.gn
@@ -192,6 +192,13 @@
       "input_method_win_tsf.h",
     ]
     libs = [ "imm32.lib" ]
+
+    jumbo_excluded_sources = [
+      # tsf_text_store.cc needs INITGUID to be defined before
+      # including any header to properly generate GUID objects. That
+      # is not guaranteed when included in a jumbo build.
+      "win/tsf_text_store.cc",
+    ]
   }
 
   if (is_mac) {
diff --git a/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc b/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc
index d4f5af78..f7597bb4 100644
--- a/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc
+++ b/ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cros.cc
@@ -211,6 +211,14 @@
     hwstate.buttons_down |= GESTURES_BUTTON_FORWARD;
   }
 
+  // Check if this event has an MSC_TIMESTAMP field
+  if (EvdevBitIsSet(evdev->info.msc_bitmask, MSC_TIMESTAMP)) {
+    hwstate.msc_timestamp = static_cast<stime_t>(Event_Get_Timestamp(evdev)) /
+                            base::Time::kMicrosecondsPerSecond;
+  } else {
+    hwstate.msc_timestamp = 0.0;
+  }
+
   GestureInterpreterPushHardwareState(interpreter_, &hwstate);
 }
 
diff --git a/ui/views/accessibility/native_view_accessibility_base.cc b/ui/views/accessibility/native_view_accessibility_base.cc
index 255cf47..62455b9a 100644
--- a/ui/views/accessibility/native_view_accessibility_base.cc
+++ b/ui/views/accessibility/native_view_accessibility_base.cc
@@ -7,7 +7,9 @@
 
 #include "ui/views/accessibility/native_view_accessibility_base.h"
 
+#include "base/lazy_instance.h"
 #include "base/memory/ptr_util.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "ui/accessibility/platform/ax_platform_node.h"
 #include "ui/events/event_utils.h"
 #include "ui/gfx/native_widget_types.h"
@@ -22,6 +24,17 @@
 base::LazyInstance<std::map<int32_t, ui::AXPlatformNode*>>::Leaky
     g_unique_id_to_ax_platform_node = LAZY_INSTANCE_INITIALIZER;
 
+// Information required to fire a delayed accessibility event.
+struct QueuedEvent {
+  ax::mojom::Event type;
+  int32_t node_id;
+};
+
+base::LazyInstance<std::vector<QueuedEvent>>::Leaky g_event_queue =
+    LAZY_INSTANCE_INITIALIZER;
+
+bool g_is_queueing_events = false;
+
 bool IsAccessibilityFocusableWhenEnabled(View* view) {
   return view->focus_behavior() != View::FocusBehavior::NEVER &&
          view->IsDrawn();
@@ -88,9 +101,49 @@
   return ax_node_->GetNativeViewAccessible();
 }
 
+ui::AXPlatformNode* PlatformNodeFromNodeID(int32_t id) {
+  // Note: For Views, node IDs and unique IDs are the same - but that isn't
+  // necessarily true for all AXPlatformNodes.
+  auto it = g_unique_id_to_ax_platform_node.Get().find(id);
+
+  if (it == g_unique_id_to_ax_platform_node.Get().end())
+    return nullptr;
+
+  return it->second;
+}
+
+void FireEvent(QueuedEvent event) {
+  ui::AXPlatformNode* node = PlatformNodeFromNodeID(event.node_id);
+  if (node)
+    node->NotifyAccessibilityEvent(event.type);
+}
+
+void FlushQueue() {
+  DCHECK(g_is_queueing_events);
+  for (QueuedEvent event : g_event_queue.Get())
+    FireEvent(event);
+  g_is_queueing_events = false;
+  g_event_queue.Get().clear();
+}
+
 void NativeViewAccessibilityBase::NotifyAccessibilityEvent(
     ax::mojom::Event event_type) {
+  if (g_is_queueing_events) {
+    g_event_queue.Get().push_back({event_type, GetUniqueId().Get()});
+    return;
+  }
+
   ax_node_->NotifyAccessibilityEvent(event_type);
+
+  // A focus context event is intended to send a focus event and a delay
+  // before the next focus event. It makes sense to delay the entire next
+  // synchronous batch of next events so that ordering remains the same.
+  if (event_type == ax::mojom::Event::kFocusContext) {
+    // Begin queueing subsequent events and flush queue asynchronously.
+    g_is_queueing_events = true;
+    base::OnceCallback<void()> cb = base::BindOnce(&FlushQueue);
+    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(cb));
+  }
 }
 
 // ui::AXPlatformNodeDelegate
@@ -250,7 +303,7 @@
   View* focused_view =
       focus_manager ? focus_manager->GetFocusedView() : nullptr;
   if (fake_focus_view_id_) {
-    ui::AXPlatformNode* ax_node = GetFromNodeID(fake_focus_view_id_);
+    ui::AXPlatformNode* ax_node = PlatformNodeFromNodeID(fake_focus_view_id_);
     if (ax_node)
       return ax_node->GetNativeViewAccessible();
   }
@@ -258,14 +311,7 @@
 }
 
 ui::AXPlatformNode* NativeViewAccessibilityBase::GetFromNodeID(int32_t id) {
-  // Note: For Views, node IDs and unique IDs are the same - but that isn't
-  // necessarily true for all AXPlatformNodes.
-  auto it = g_unique_id_to_ax_platform_node.Get().find(id);
-
-  if (it == g_unique_id_to_ax_platform_node.Get().end())
-    return nullptr;
-
-  return it->second;
+  return PlatformNodeFromNodeID(id);
 }
 
 int NativeViewAccessibilityBase::GetIndexInParent() const {
diff --git a/ui/views/mus/BUILD.gn b/ui/views/mus/BUILD.gn
index a8e4c99..aa31e409 100644
--- a/ui/views/mus/BUILD.gn
+++ b/ui/views/mus/BUILD.gn
@@ -80,9 +80,9 @@
   ]
 
   if (is_linux && !is_android) {
-    deps += [ "//components/font_service/public/cpp" ]
+    deps += [ "//components/services/font/public/cpp" ]
     data_deps = [
-      "//components/font_service",
+      "//components/services/font:font_service",
     ]
   }
 }
diff --git a/ui/views/mus/DEPS b/ui/views/mus/DEPS
index 4d8a1fd..21ea014 100644
--- a/ui/views/mus/DEPS
+++ b/ui/views/mus/DEPS
@@ -1,7 +1,7 @@
 include_rules = [
   "+cc",
   "-cc/blink",
-  "+components/font_service/public",
+  "+components/services/font/public",
   "+components/gpu",
   "+mojo/cc",
   "+mojo/common",
diff --git a/ui/views/mus/aura_init.cc b/ui/views/mus/aura_init.cc
index 7631ab5..ea6490d 100644
--- a/ui/views/mus/aura_init.cc
+++ b/ui/views/mus/aura_init.cc
@@ -25,7 +25,7 @@
 #include "ui/views/views_delegate.h"
 
 #if defined(OS_LINUX)
-#include "components/font_service/public/cpp/font_loader.h"
+#include "components/services/font/public/cpp/font_loader.h"
 #include "ui/gfx/platform_font_linux.h"
 #endif