diff --git a/DEPS b/DEPS
index f10b7b44..1149dd31 100644
--- a/DEPS
+++ b/DEPS
@@ -142,7 +142,7 @@
   # 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': '17007c11a74c87be69bf173e4db15d50bcaf1593',
+  'v8_revision': '84c5a5374f3fc14391d282d03493e32bda642659',
   # 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.
@@ -150,11 +150,11 @@
   # 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': '2d223552e3fe454420a8fcd936390104009e0ba5',
+  'angle_revision': '81b6acfb86850cd81fa70bccb44791d5e37a43fa',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '9283b2559c0580dbb8fb6effffd11dc3f28b5f42',
+  'swiftshader_revision': '67180a07f8d56f2092da889fbf26073d72d6b47d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -436,7 +436,7 @@
     Var('chromium_git') + '/external/github.com/toji/webvr.info.git' + '@' + 'c58ae99b9ff9e2aa4c524633519570bf33536248',
 
   'src/ios/third_party/earl_grey/src': {
-      'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + 'fb25165a5ec573ba31389b16fd43d56ccf7da9c9',
+      'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + 'e272bbd853eefcef4b5aeff5009d87bba5adea1c',
       'condition': 'checkout_ios',
   },
 
@@ -807,7 +807,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '7b8008e2e7e427eed20b92e4711478c0d64749bf',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '40ee745abc3b3dd0309c67d3cb0b4c29adc2c484',
       'condition': 'checkout_linux',
   },
 
@@ -832,7 +832,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '2313020206fce572179a52ac2cce0d342491e1ab',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '49131ca238ded3455771ba8b448a2f48dbf8597f',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -1355,7 +1355,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '6f0b34abee8dba611c253738d955c59f703c147a',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '61d8ee10b61171cd4b90ed36c178f223f99256cf',
+    Var('webrtc_git') + '/src.git' + '@' + '342f98b117653524dc08f585fd5053ceca5b4d40',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1396,7 +1396,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@a8103e5d2c6452965b6cf83373336a275827a1fe',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@88825299a7d45d0a57c209f55f1c7684d1a45243',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index a8a1de8..0bb5c1c 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -470,7 +470,7 @@
   host->AddFilter(new cdm::CdmMessageFilterAndroid(true, false));
 }
 
-bool AwContentBrowserClient::ShouldUseMobileFlingCurve() const {
+bool AwContentBrowserClient::ShouldUseMobileFlingCurve() {
   return true;
 }
 
@@ -1111,16 +1111,16 @@
       std::move(orig_request));
 }
 
-std::string AwContentBrowserClient::GetProduct() const {
+std::string AwContentBrowserClient::GetProduct() {
   return android_webview::GetProduct();
 }
 
-std::string AwContentBrowserClient::GetUserAgent() const {
+std::string AwContentBrowserClient::GetUserAgent() {
   return android_webview::GetUserAgent();
 }
 
 content::ContentBrowserClient::WideColorGamutHeuristic
-AwContentBrowserClient::GetWideColorGamutHeuristic() const {
+AwContentBrowserClient::GetWideColorGamutHeuristic() {
   if (base::FeatureList::IsEnabled(features::kWebViewWideColorGamutSupport))
     return WideColorGamutHeuristic::kUseWindow;
   return WideColorGamutHeuristic::kNone;
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h
index d429ed7..612cff9c 100644
--- a/android_webview/browser/aw_content_browser_client.h
+++ b/android_webview/browser/aw_content_browser_client.h
@@ -71,7 +71,7 @@
   void RenderProcessWillLaunch(
       content::RenderProcessHost* host,
       service_manager::mojom::ServiceRequest* service_request) override;
-  bool ShouldUseMobileFlingCurve() const override;
+  bool ShouldUseMobileFlingCurve() override;
   bool IsHandledURL(const GURL& url) override;
   bool ForceSniffingFileUrlsForHtml() override;
   void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
@@ -247,10 +247,10 @@
       int process_id,
       int routing_id,
       network::mojom::RestrictedCookieManagerRequest* request) override;
-  std::string GetProduct() const override;
-  std::string GetUserAgent() const override;
+  std::string GetProduct() override;
+  std::string GetUserAgent() override;
   ContentBrowserClient::WideColorGamutHeuristic GetWideColorGamutHeuristic()
-      const override;
+      override;
 
   AwFeatureListCreator* aw_feature_list_creator() {
     return aw_feature_list_creator_;
diff --git a/android_webview/browser/aw_web_contents_delegate.cc b/android_webview/browser/aw_web_contents_delegate.cc
index 54a8e1b..d898acdb 100644
--- a/android_webview/browser/aw_web_contents_delegate.cc
+++ b/android_webview/browser/aw_web_contents_delegate.cc
@@ -304,7 +304,7 @@
 }
 
 bool AwWebContentsDelegate::IsFullscreenForTabOrPending(
-    const content::WebContents* web_contents) const {
+    const content::WebContents* web_contents) {
   return is_fullscreen_;
 }
 
diff --git a/android_webview/browser/aw_web_contents_delegate.h b/android_webview/browser/aw_web_contents_delegate.h
index 3bd367d..719b6e95 100644
--- a/android_webview/browser/aw_web_contents_delegate.h
+++ b/android_webview/browser/aw_web_contents_delegate.h
@@ -72,7 +72,7 @@
       const blink::WebFullscreenOptions& options) override;
   void ExitFullscreenModeForTab(content::WebContents* web_contents) override;
   bool IsFullscreenForTabOrPending(
-      const content::WebContents* web_contents) const override;
+      const content::WebContents* web_contents) override;
   void UpdateUserGestureCarryoverInfo(
       content::WebContents* web_contents) override;
 
diff --git a/android_webview/browser/gfx/surfaces_instance.cc b/android_webview/browser/gfx/surfaces_instance.cc
index 79b257ef..8e61bba0 100644
--- a/android_webview/browser/gfx/surfaces_instance.cc
+++ b/android_webview/browser/gfx/surfaces_instance.cc
@@ -381,7 +381,9 @@
   }
   display_->Resize(viewport);
   display_->DrawAndSwap();
-  display_->DidReceiveSwapBuffersAck();
+  // TODO(dlibby): Consider sending real swap timings here for webview (or
+  // prove why it is not needed).
+  display_->DidReceiveSwapBuffersAck(gfx::SwapTimings());
   gl_surface_->MaybeDidPresent(gfx::PresentationFeedback(
       base::TimeTicks::Now(), base::TimeDelta(), 0 /* flags */));
 }
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 9ddd46c..77969f2 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -128,8 +128,8 @@
     "accessibility/accessibility_cursor_ring_layer.h",
     "accessibility/accessibility_focus_ring.cc",
     "accessibility/accessibility_focus_ring.h",
-    "accessibility/accessibility_focus_ring_controller.cc",
-    "accessibility/accessibility_focus_ring_controller.h",
+    "accessibility/accessibility_focus_ring_controller_impl.cc",
+    "accessibility/accessibility_focus_ring_controller_impl.h",
     "accessibility/accessibility_focus_ring_group.cc",
     "accessibility/accessibility_focus_ring_group.h",
     "accessibility/accessibility_focus_ring_layer.cc",
diff --git a/ash/accelerators/accelerator_controller_impl.cc b/ash/accelerators/accelerator_controller_impl.cc
index c6c21b1..d19b99a 100644
--- a/ash/accelerators/accelerator_controller_impl.cc
+++ b/ash/accelerators/accelerator_controller_impl.cc
@@ -119,6 +119,7 @@
 
 // Toast id and duration for voice interaction shortcuts
 constexpr char kVoiceInteractionErrorToastId[] = "voice_interaction_error";
+const char kFeatureDisabledByPolicyToastId[] = "disabled_by_policy_error";
 constexpr int kToastDurationMs = 2500;
 
 // Path of the json file that contains side volume button location info.
@@ -197,7 +198,8 @@
 }
 
 void ShowToast(std::string id, const base::string16& text) {
-  ToastData toast(id, text, kToastDurationMs, base::nullopt);
+  ToastData toast(id, text, kToastDurationMs, base::nullopt,
+                  /*visible_on_lock_screen=*/true);
   Shell::Get()->toast_manager()->Show(toast);
 }
 
@@ -739,6 +741,8 @@
                 l10n_util::GetStringUTF16(
                     IDS_ASH_VOICE_INTERACTION_DISABLED_IN_GUEST_MESSAGE));
       return;
+    // TODO(crbug.com/974228) Add final strings when we have them.
+    case mojom::AssistantAllowedState::DISALLOWED_BY_KIOSK_NEXT:
     case mojom::AssistantAllowedState::DISALLOWED_BY_ACCOUNT_TYPE:
       ShowToast(kVoiceInteractionErrorToastId,
                 l10n_util::GetStringUTF16(
@@ -873,15 +877,28 @@
                                                            false /* by_user */);
 }
 
+void ShowDisabledByPolicyToastMessage(int feature_name_string_id) {
+  ShowToast(kFeatureDisabledByPolicyToastId,
+            l10n_util::GetStringFUTF16(
+                IDS_ASH_FEATURE_DISABLED_BY_POLICY,
+                l10n_util::GetStringUTF16(feature_name_string_id)));
+}
 void SetDockedMagnifierEnabled(bool enabled) {
-  if (enabled) {
+  Shell::Get()->docked_magnifier_controller()->SetEnabled(enabled);
+
+  // We need to show the notification only if the state actually changed.
+  const bool actual_enabled =
+      Shell::Get()->docked_magnifier_controller()->GetEnabled();
+  if (enabled && actual_enabled) {
     CreateAndShowStickyNotification(IDS_DOCKED_MAGNIFIER_ACCEL_TITLE,
                                     IDS_DOCKED_MAGNIFIER_ACCEL_MSG,
                                     kDockedMagnifierToggleAccelNotificationId);
+  } else if (enabled != actual_enabled) {
+    ShowDisabledByPolicyToastMessage(
+        IDS_ASH_STATUS_TRAY_ACCESSIBILITY_DOCKED_MAGNIFIER);
   } else {
     RemoveStickyNotitification(kDockedMagnifierToggleAccelNotificationId);
   }
-  Shell::Get()->docked_magnifier_controller()->SetEnabled(enabled);
 }
 
 void HandleToggleDockedMagnifier() {
@@ -910,20 +927,26 @@
 }
 
 void SetFullscreenMagnifierEnabled(bool enabled) {
-  if (enabled) {
-    CreateAndShowStickyNotification(
-        IDS_FULLSCREEN_MAGNIFIER_ACCEL_TITLE,
-        IDS_FULLSCREEN_MAGNIFIER_ACCEL_MSG,
-        kFullscreenMagnifierToggleAccelNotificationId);
-  } else {
-    RemoveStickyNotitification(kFullscreenMagnifierToggleAccelNotificationId);
-  }
-
   // TODO (afakhry): Move the below into a single call (crbug/817157).
   // Necessary to make magnification controller in ash observe changes to the
   // prefs iteself.
   Shell* shell = Shell::Get();
   shell->accessibility_controller()->SetFullscreenMagnifierEnabled(enabled);
+
+  // We need to show the notification only if the state actually changed.
+  const bool actual_enabled =
+      Shell::Get()->magnification_controller()->IsEnabled();
+  if (enabled && actual_enabled) {
+    CreateAndShowStickyNotification(
+        IDS_FULLSCREEN_MAGNIFIER_ACCEL_TITLE,
+        IDS_FULLSCREEN_MAGNIFIER_ACCEL_MSG,
+        kFullscreenMagnifierToggleAccelNotificationId);
+  } else if (enabled != actual_enabled) {
+    ShowDisabledByPolicyToastMessage(
+        IDS_ASH_STATUS_TRAY_ACCESSIBILITY_SCREEN_MAGNIFIER);
+  } else {
+    RemoveStickyNotitification(kFullscreenMagnifierToggleAccelNotificationId);
+  }
 }
 
 void SetHighContrastEnabled(bool enabled) {
@@ -937,6 +960,9 @@
     CreateAndShowStickyNotification(IDS_HIGH_CONTRAST_ACCEL_TITLE,
                                     IDS_HIGH_CONTRAST_ACCEL_MSG,
                                     kHighContrastToggleAccelNotificationId);
+  } else if (enabled != actual_enabled) {
+    ShowDisabledByPolicyToastMessage(
+        IDS_ASH_STATUS_TRAY_ACCESSIBILITY_HIGH_CONTRAST_MODE);
   } else {
     RemoveStickyNotitification(kHighContrastToggleAccelNotificationId);
   }
@@ -994,8 +1020,15 @@
 
   AccessibilityController* controller =
       Shell::Get()->accessibility_controller();
+  bool old_value = controller->spoken_feedback_enabled();
   controller->SetSpokenFeedbackEnabled(!controller->spoken_feedback_enabled(),
                                        A11Y_NOTIFICATION_SHOW);
+  // If we tried to enable it and didn't succeed — show disabled by policy
+  // toast.
+  if (!controller->spoken_feedback_enabled() && !old_value) {
+    ShowDisabledByPolicyToastMessage(
+        IDS_ASH_STATUS_TRAY_ACCESSIBILITY_SPOKEN_FEEDBACK);
+  }
 }
 
 // Percent by which the volume should be changed when a volume key is pressed.
diff --git a/ash/accessibility/accessibility_focus_ring_controller.cc b/ash/accessibility/accessibility_focus_ring_controller_impl.cc
similarity index 79%
rename from ash/accessibility/accessibility_focus_ring_controller.cc
rename to ash/accessibility/accessibility_focus_ring_controller_impl.cc
index be919e2..7712c07 100644
--- a/ash/accessibility/accessibility_focus_ring_controller.cc
+++ b/ash/accessibility/accessibility_focus_ring_controller_impl.cc
@@ -1,8 +1,8 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2019 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/accessibility/accessibility_focus_ring_controller.h"
+#include "ash/accessibility/accessibility_focus_ring_controller_impl.h"
 
 #include <stddef.h>
 
@@ -43,8 +43,7 @@
 
 }  // namespace
 
-AccessibilityFocusRingController::AccessibilityFocusRingController()
-    : binding_(this) {
+AccessibilityFocusRingControllerImpl::AccessibilityFocusRingControllerImpl() {
   cursor_animation_info_.fade_in_time =
       base::TimeDelta::FromMilliseconds(kCursorFadeInTimeMilliseconds);
   cursor_animation_info_.fade_out_time =
@@ -55,24 +54,19 @@
       base::TimeDelta::FromMilliseconds(kCaretFadeOutTimeMilliseconds);
 }
 
-AccessibilityFocusRingController::~AccessibilityFocusRingController() = default;
+AccessibilityFocusRingControllerImpl::~AccessibilityFocusRingControllerImpl() =
+    default;
 
-void AccessibilityFocusRingController::BindRequest(
-    mojom::AccessibilityFocusRingControllerRequest request) {
-  binding_.Bind(std::move(request));
-}
-
-void AccessibilityFocusRingController::SetFocusRing(
+void AccessibilityFocusRingControllerImpl::SetFocusRing(
     const std::string& focus_ring_id,
-    mojom::FocusRingPtr focus_ring) {
+    std::unique_ptr<AccessibilityFocusRingInfo> focus_ring) {
   AccessibilityFocusRingGroup* focus_ring_group =
       GetFocusRingGroupForId(focus_ring_id, true /* Create if missing */);
-
   if (focus_ring_group->UpdateFocusRing(std::move(focus_ring), this))
     OnLayerChange(focus_ring_group->focus_animation_info());
 }
 
-void AccessibilityFocusRingController::HideFocusRing(
+void AccessibilityFocusRingControllerImpl::HideFocusRing(
     const std::string& focus_ring_id) {
   AccessibilityFocusRingGroup* focus_ring_group =
       GetFocusRingGroupForId(focus_ring_id, false /* Do not create */);
@@ -82,7 +76,7 @@
   OnLayerChange(focus_ring_group->focus_animation_info());
 }
 
-void AccessibilityFocusRingController::SetHighlights(
+void AccessibilityFocusRingControllerImpl::SetHighlights(
     const std::vector<gfx::Rect>& rects,
     SkColor color) {
   highlight_rects_ = rects;
@@ -91,26 +85,26 @@
   UpdateHighlightFromHighlightRects();
 }
 
-void AccessibilityFocusRingController::HideHighlights() {
+void AccessibilityFocusRingControllerImpl::HideHighlights() {
   highlight_rects_.clear();
   UpdateHighlightFromHighlightRects();
 }
 
-void AccessibilityFocusRingController::UpdateHighlightFromHighlightRects() {
+void AccessibilityFocusRingControllerImpl::UpdateHighlightFromHighlightRects() {
   if (!highlight_layer_)
     highlight_layer_ = std::make_unique<AccessibilityHighlightLayer>(this);
   highlight_layer_->Set(highlight_rects_, highlight_color_);
   highlight_layer_->SetOpacity(highlight_opacity_);
 }
 
-void AccessibilityFocusRingController::OnLayerChange(
+void AccessibilityFocusRingControllerImpl::OnLayerChange(
     LayerAnimationInfo* animation_info) {
   animation_info->change_time = base::TimeTicks::Now();
   if (animation_info->opacity == 0)
     animation_info->start_time = animation_info->change_time;
 }
 
-void AccessibilityFocusRingController::SetCursorRing(
+void AccessibilityFocusRingControllerImpl::SetCursorRing(
     const gfx::Point& location) {
   cursor_location_ = location;
   if (!cursor_layer_) {
@@ -122,11 +116,11 @@
   OnLayerChange(&cursor_animation_info_);
 }
 
-void AccessibilityFocusRingController::HideCursorRing() {
+void AccessibilityFocusRingControllerImpl::HideCursorRing() {
   cursor_layer_.reset();
 }
 
-void AccessibilityFocusRingController::SetCaretRing(
+void AccessibilityFocusRingControllerImpl::SetCaretRing(
     const gfx::Point& location) {
   caret_location_ = location;
 
@@ -139,11 +133,11 @@
   OnLayerChange(&caret_animation_info_);
 }
 
-void AccessibilityFocusRingController::HideCaretRing() {
+void AccessibilityFocusRingControllerImpl::HideCaretRing() {
   caret_layer_.reset();
 }
 
-void AccessibilityFocusRingController::SetNoFadeForTesting() {
+void AccessibilityFocusRingControllerImpl::SetNoFadeForTesting() {
   no_fade_for_testing_ = true;
   for (auto iter = focus_ring_groups_.begin(); iter != focus_ring_groups_.end();
        ++iter) {
@@ -159,12 +153,12 @@
 }
 
 const AccessibilityFocusRingGroup*
-AccessibilityFocusRingController::GetFocusRingGroupForTesting(
+AccessibilityFocusRingControllerImpl::GetFocusRingGroupForTesting(
     const std::string& focus_ring_id) {
   return GetFocusRingGroupForId(focus_ring_id, false /* create if missing */);
 }
 
-void AccessibilityFocusRingController::GetColorAndOpacityFromColor(
+void AccessibilityFocusRingControllerImpl::GetColorAndOpacityFromColor(
     SkColor color,
     float default_opacity,
     SkColor* result_color,
@@ -178,13 +172,13 @@
   *result_color = SkColorSetA(color, 0xFF);
 }
 
-void AccessibilityFocusRingController::OnDeviceScaleFactorChanged() {
+void AccessibilityFocusRingControllerImpl::OnDeviceScaleFactorChanged() {
   for (auto iter = focus_ring_groups_.begin(); iter != focus_ring_groups_.end();
        ++iter)
     iter->second->UpdateFocusRingsFromInfo(this);
 }
 
-void AccessibilityFocusRingController::OnAnimationStep(
+void AccessibilityFocusRingControllerImpl::OnAnimationStep(
     base::TimeTicks timestamp) {
   for (auto iter = focus_ring_groups_.begin(); iter != focus_ring_groups_.end();
        ++iter) {
@@ -199,7 +193,7 @@
     AnimateCaretRing(timestamp);
 }
 
-void AccessibilityFocusRingController::AnimateCursorRing(
+void AccessibilityFocusRingControllerImpl::AnimateCursorRing(
     base::TimeTicks timestamp) {
   CHECK(cursor_layer_);
 
@@ -211,7 +205,7 @@
   cursor_layer_->SetOpacity(cursor_animation_info_.opacity);
 }
 
-void AccessibilityFocusRingController::AnimateCaretRing(
+void AccessibilityFocusRingControllerImpl::AnimateCaretRing(
     base::TimeTicks timestamp) {
   CHECK(caret_layer_);
 
@@ -224,7 +218,7 @@
 }
 
 AccessibilityFocusRingGroup*
-AccessibilityFocusRingController::GetFocusRingGroupForId(
+AccessibilityFocusRingControllerImpl::GetFocusRingGroupForId(
     const std::string& focus_ring_id,
     bool create) {
   auto iter = focus_ring_groups_.find(focus_ring_id);
diff --git a/ash/accessibility/accessibility_focus_ring_controller.h b/ash/accessibility/accessibility_focus_ring_controller_impl.h
similarity index 71%
rename from ash/accessibility/accessibility_focus_ring_controller.h
rename to ash/accessibility/accessibility_focus_ring_controller_impl.h
index 973b1ca..0743ac1 100644
--- a/ash/accessibility/accessibility_focus_ring_controller.h
+++ b/ash/accessibility/accessibility_focus_ring_controller_impl.h
@@ -1,9 +1,9 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2019 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef ASH_ACCESSIBILITY_ACCESSIBILITY_FOCUS_RING_CONTROLLER_H_
-#define ASH_ACCESSIBILITY_ACCESSIBILITY_FOCUS_RING_CONTROLLER_H_
+#ifndef ASH_ACCESSIBILITY_ACCESSIBILITY_FOCUS_RING_CONTROLLER_IMPL_H_
+#define ASH_ACCESSIBILITY_ACCESSIBILITY_FOCUS_RING_CONTROLLER_IMPL_H_
 
 #include <memory>
 #include <vector>
@@ -13,12 +13,11 @@
 #include "ash/accessibility/accessibility_layer.h"
 #include "ash/accessibility/layer_animation_info.h"
 #include "ash/ash_export.h"
-#include "ash/public/interfaces/accessibility_focus_ring_controller.mojom.h"
+#include "ash/public/cpp/accessibility_focus_ring_controller.h"
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/optional.h"
 #include "base/time/time.h"
-#include "mojo/public/cpp/bindings/binding.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/geometry/rect.h"
 
@@ -27,21 +26,19 @@
 class AccessibilityCursorRingLayer;
 class AccessibilityHighlightLayer;
 
-// AccessibilityFocusRingController handles drawing custom rings around
-// the focused object, cursor, and/or caret for accessibility.
-class ASH_EXPORT AccessibilityFocusRingController
+// AccessibilityFocusRingControllerImpl handles drawing custom rings around the
+// focused object, cursor, and/or caret for accessibility.
+class ASH_EXPORT AccessibilityFocusRingControllerImpl
     : public AccessibilityLayerDelegate,
-      public mojom::AccessibilityFocusRingController {
+      public AccessibilityFocusRingController {
  public:
-  AccessibilityFocusRingController();
-  ~AccessibilityFocusRingController() override;
+  AccessibilityFocusRingControllerImpl();
+  ~AccessibilityFocusRingControllerImpl() override;
 
-  // Binds the mojom::AccessibilityFocusRingController interface to this object.
-  void BindRequest(mojom::AccessibilityFocusRingControllerRequest request);
-
-  // mojom::AccessibilityFocusRingController overrides:
-  void SetFocusRing(const std::string& focus_ring_id,
-                    mojom::FocusRingPtr focus_ring) override;
+  // AccessibilityFocusRingController overrides:
+  void SetFocusRing(
+      const std::string& focus_ring_id,
+      std::unique_ptr<AccessibilityFocusRingInfo> focus_ring) override;
   void HideFocusRing(const std::string& focus_ring_id) override;
   void SetHighlights(const std::vector<gfx::Rect>& rects,
                      SkColor color) override;
@@ -68,10 +65,8 @@
   const AccessibilityFocusRingGroup* GetFocusRingGroupForTesting(
       const std::string& focus_ring_id);
 
- protected:
-  // Breaks an SkColor into its opacity and color. If the opacity is
-  // not set (or is 0xFF), uses the |default_opacity| instead.
-  // Visible for testing.
+  // Breaks an SkColor into its opacity and color. If the opacity is not set
+  // (or is 0xFF), uses the |default_opacity| instead. Visible for testing.
   static void GetColorAndOpacityFromColor(SkColor color,
                                           float default_opacity,
                                           SkColor* result_color,
@@ -91,9 +86,6 @@
 
   void OnLayerChange(LayerAnimationInfo* animation_info);
 
-  // Binding for mojom::AccessibilityFocusRingController interface.
-  mojo::Binding<mojom::AccessibilityFocusRingController> binding_;
-
   AccessibilityFocusRingGroup* GetFocusRingGroupForId(
       const std::string& focus_ring_id,
       bool create);
@@ -115,9 +107,9 @@
 
   bool no_fade_for_testing_ = false;
 
-  DISALLOW_COPY_AND_ASSIGN(AccessibilityFocusRingController);
+  DISALLOW_COPY_AND_ASSIGN(AccessibilityFocusRingControllerImpl);
 };
 
 }  // namespace ash
 
-#endif  // ASH_ACCESSIBILITY_ACCESSIBILITY_FOCUS_RING_CONTROLLER_H_
+#endif  // ASH_ACCESSIBILITY_ACCESSIBILITY_FOCUS_RING_CONTROLLER_IMPL_H_
diff --git a/ash/accessibility/accessibility_focus_ring_controller_unittest.cc b/ash/accessibility/accessibility_focus_ring_controller_unittest.cc
index 9d79522..2a148fce 100644
--- a/ash/accessibility/accessibility_focus_ring_controller_unittest.cc
+++ b/ash/accessibility/accessibility_focus_ring_controller_unittest.cc
@@ -1,9 +1,11 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright 2019 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "ash/accessibility/accessibility_focus_ring_controller.h"
+#include "ash/accessibility/accessibility_focus_ring_controller_impl.h"
+
 #include "ash/accessibility/accessibility_cursor_ring_layer.h"
+#include "ash/public/cpp/accessibility_focus_ring_info.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -13,64 +15,44 @@
 
 namespace ash {
 
-class TestableAccessibilityFocusRingController
-    : public AccessibilityFocusRingController {
- public:
-  TestableAccessibilityFocusRingController() {}
-  ~TestableAccessibilityFocusRingController() override = default;
-
-  static void GetColorAndOpacityFromColor(SkColor color,
-                                          float default_opacity,
-                                          SkColor* result_color,
-                                          float* result_opacity) {
-    AccessibilityFocusRingController::GetColorAndOpacityFromColor(
-        color, default_opacity, result_color, result_opacity);
-  }
-};
-
-class AccessibilityFocusRingControllerTest : public AshTestBase {
- public:
-  AccessibilityFocusRingControllerTest() = default;
-  ~AccessibilityFocusRingControllerTest() override = default;
-
- protected:
-  TestableAccessibilityFocusRingController controller_;
-};
+using AccessibilityFocusRingControllerTest = AshTestBase;
 
 TEST_F(AccessibilityFocusRingControllerTest, CallingHideWhenEmpty) {
+  auto* controller = Shell::Get()->accessibility_focus_ring_controller();
   // Ensure that calling hide does not crash the controller if there are
   // no focus rings yet for a given ID.
-  controller_.HideFocusRing("catsRCute");
+  controller->HideFocusRing("catsRCute");
 }
 
 TEST_F(AccessibilityFocusRingControllerTest, SetFocusRingCorrectRingGroup) {
-  EXPECT_EQ(nullptr, controller_.GetFocusRingGroupForTesting("catsRCute"));
+  auto* controller = Shell::Get()->accessibility_focus_ring_controller();
+  EXPECT_EQ(nullptr, controller->GetFocusRingGroupForTesting("catsRCute"));
   SkColor cat_color = SkColorSetARGB(0xFF, 0x42, 0x42, 0x42);
 
-  mojom::FocusRingPtr cat_focus_ring = mojom::FocusRing::New();
+  auto cat_focus_ring = std::make_unique<AccessibilityFocusRingInfo>();
   cat_focus_ring->color = cat_color;
   cat_focus_ring->rects_in_screen.push_back(gfx::Rect(0, 0, 10, 10));
-  controller_.SetFocusRing("catsRCute", std::move(cat_focus_ring));
+  controller->SetFocusRing("catsRCute", std::move(cat_focus_ring));
 
   // A focus ring group was created.
-  ASSERT_NE(nullptr, controller_.GetFocusRingGroupForTesting("catsRCute"));
-  EXPECT_EQ(1u, controller_.GetFocusRingGroupForTesting("catsRCute")
+  ASSERT_NE(nullptr, controller->GetFocusRingGroupForTesting("catsRCute"));
+  EXPECT_EQ(1u, controller->GetFocusRingGroupForTesting("catsRCute")
                     ->focus_layers_for_testing()
                     .size());
 
-  EXPECT_EQ(nullptr, controller_.GetFocusRingGroupForTesting("dogsRCool"));
-  mojom::FocusRingPtr dog_focus_ring = mojom::FocusRing::New();
+  EXPECT_EQ(nullptr, controller->GetFocusRingGroupForTesting("dogsRCool"));
+  auto dog_focus_ring = std::make_unique<AccessibilityFocusRingInfo>();
   dog_focus_ring->rects_in_screen.push_back(gfx::Rect(10, 30, 70, 150));
-  controller_.SetFocusRing("dogsRCool", std::move(dog_focus_ring));
+  controller->SetFocusRing("dogsRCool", std::move(dog_focus_ring));
 
-  ASSERT_NE(nullptr, controller_.GetFocusRingGroupForTesting("dogsRCool"));
-  int size = controller_.GetFocusRingGroupForTesting("dogsRCool")
+  ASSERT_NE(nullptr, controller->GetFocusRingGroupForTesting("dogsRCool"));
+  int size = controller->GetFocusRingGroupForTesting("dogsRCool")
                  ->focus_layers_for_testing()
                  .size();
   EXPECT_EQ(1, size);
   // The first focus ring group was not updated.
   const std::vector<std::unique_ptr<AccessibilityFocusRingLayer>>& layers =
-      controller_.GetFocusRingGroupForTesting("catsRCute")
+      controller->GetFocusRingGroupForTesting("catsRCute")
           ->focus_layers_for_testing();
   EXPECT_EQ(1u, layers.size());
   EXPECT_EQ(cat_color, layers[0]->color_for_testing());
@@ -82,7 +64,7 @@
   ASSERT_EQ(2u, root_windows.size());
 
   // Simulate a mouse event on the primary display.
-  AccessibilityFocusRingController* controller =
+  AccessibilityFocusRingControllerImpl* controller =
       Shell::Get()->accessibility_focus_ring_controller();
   gfx::Point location(90, 90);
   controller->SetCursorRing(location);
@@ -115,11 +97,11 @@
   SkColor result_color = SK_ColorWHITE;
   float result_opacity = 0.0f;
 
-  TestableAccessibilityFocusRingController::GetColorAndOpacityFromColor(
+  AccessibilityFocusRingControllerImpl::GetColorAndOpacityFromColor(
       without_alpha, default_opacity, &result_color, &result_opacity);
   EXPECT_EQ(default_opacity, result_opacity);
 
-  TestableAccessibilityFocusRingController::GetColorAndOpacityFromColor(
+  AccessibilityFocusRingControllerImpl::GetColorAndOpacityFromColor(
       with_alpha, default_opacity, &result_color, &result_opacity);
   EXPECT_NEAR(0.239f, result_opacity, .001);
 }
diff --git a/ash/accessibility/accessibility_focus_ring_group.cc b/ash/accessibility/accessibility_focus_ring_group.cc
index 4c35e5a..9fd1fa2 100644
--- a/ash/accessibility/accessibility_focus_ring_group.cc
+++ b/ash/accessibility/accessibility_focus_ring_group.cc
@@ -11,7 +11,7 @@
 #include "ash/accessibility/accessibility_focus_ring_layer.h"
 #include "ash/accessibility/accessibility_layer.h"
 #include "ash/accessibility/layer_animation_info.h"
-#include "ash/public/interfaces/accessibility_focus_ring_controller.mojom.h"
+#include "ash/public/cpp/accessibility_focus_ring_info.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/geometry/rect.h"
 
@@ -69,8 +69,7 @@
           std::make_unique<AccessibilityFocusRingLayer>(delegate);
   }
 
-  if (focus_ring_info_->behavior ==
-          mojom::FocusRingBehavior::PERSIST_FOCUS_RING &&
+  if (focus_ring_info_->behavior == FocusRingBehavior::PERSIST &&
       focus_layers_[0]->CanAnimate() && !no_fade_for_testing_) {
     // In PERSIST mode, animate the first ring to its destination
     // location, then set the rest of the rings directly.
@@ -105,8 +104,7 @@
   if (timestamp < focus_animation_info_.change_time)
     timestamp = focus_animation_info_.change_time;
 
-  if (focus_ring_info_->behavior ==
-      mojom::FocusRingBehavior::PERSIST_FOCUS_RING) {
+  if (focus_ring_info_->behavior == FocusRingBehavior::PERSIST) {
     base::TimeDelta delta = timestamp - focus_animation_info_.change_time;
     base::TimeDelta transition_time =
         base::TimeDelta::FromMilliseconds(kTransitionTimeMilliseconds);
@@ -135,16 +133,18 @@
 }
 
 bool AccessibilityFocusRingGroup::UpdateFocusRing(
-    mojom::FocusRingPtr focus_ring,
+    std::unique_ptr<AccessibilityFocusRingInfo> focus_ring,
     AccessibilityLayerDelegate* delegate) {
-  std::vector<gfx::Rect> rects(focus_ring->rects_in_screen);
-  // Remove duplicates
-  if (rects.size() > 1) {
+  // Remove duplicate rects.
+  if (focus_ring && focus_ring->rects_in_screen.size() > 1) {
+    std::vector<gfx::Rect> rects(focus_ring->rects_in_screen);
     std::set<gfx::Rect> rects_set(rects.begin(), rects.end());
     focus_ring->rects_in_screen.assign(rects_set.begin(), rects_set.end());
   }
+
   // If there is no change, don't do any work.
-  if (focus_ring_info_ == focus_ring)
+  if ((!focus_ring_info_ && !focus_ring) ||
+      (focus_ring_info_ && focus_ring && *focus_ring_info_ == *focus_ring))
     return false;
 
   focus_ring_info_ = std::move(focus_ring);
diff --git a/ash/accessibility/accessibility_focus_ring_group.h b/ash/accessibility/accessibility_focus_ring_group.h
index b70038b2..257fb7d 100644
--- a/ash/accessibility/accessibility_focus_ring_group.h
+++ b/ash/accessibility/accessibility_focus_ring_group.h
@@ -13,7 +13,7 @@
 #include "ash/accessibility/accessibility_layer.h"
 #include "ash/accessibility/layer_animation_info.h"
 #include "ash/ash_export.h"
-#include "ash/public/interfaces/accessibility_focus_ring_controller.mojom.h"
+#include "ash/public/cpp/accessibility_focus_ring_info.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/geometry/rect.h"
 
@@ -33,7 +33,7 @@
   void AnimateFocusRings(base::TimeTicks timestamp);
 
   // Returns true if the focus ring has changed, false if there were no changes.
-  bool UpdateFocusRing(mojom::FocusRingPtr focus_ring,
+  bool UpdateFocusRing(std::unique_ptr<AccessibilityFocusRingInfo> focus_ring,
                        AccessibilityLayerDelegate* delegate);
 
   void ClearFocusRects(AccessibilityLayerDelegate* delegate);
@@ -70,7 +70,7 @@
                                gfx::Rect* bottom) const;
   bool Intersects(const gfx::Rect& r1, const gfx::Rect& r2) const;
 
-  mojom::FocusRingPtr focus_ring_info_;
+  std::unique_ptr<AccessibilityFocusRingInfo> focus_ring_info_;
   std::vector<AccessibilityFocusRing> previous_focus_rings_;
   std::vector<std::unique_ptr<AccessibilityFocusRingLayer>> focus_layers_;
   std::vector<AccessibilityFocusRing> focus_rings_;
diff --git a/ash/accessibility/accessibility_focus_ring_group_unittest.cc b/ash/accessibility/accessibility_focus_ring_group_unittest.cc
index 6427d97..2e790c47 100644
--- a/ash/accessibility/accessibility_focus_ring_group_unittest.cc
+++ b/ash/accessibility/accessibility_focus_ring_group_unittest.cc
@@ -10,9 +10,7 @@
 #include "ash/accessibility/accessibility_focus_ring.h"
 #include "ash/accessibility/accessibility_focus_ring_layer.h"
 #include "ash/accessibility/accessibility_layer.h"
-#include "ash/public/interfaces/accessibility_focus_ring_controller.mojom.h"
 #include "ash/test/ash_test_base.h"
-#include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/geometry/rect.h"
 
@@ -35,6 +33,7 @@
 
  private:
   int margin_;
+  DISALLOW_COPY_AND_ASSIGN(TestableAccessibilityFocusRingGroup);
 };
 
 class AccessibilityFocusRingGroupTest : public AshTestBase {
diff --git a/ash/accessibility/accessibility_focus_ring_layer.cc b/ash/accessibility/accessibility_focus_ring_layer.cc
index 99a946fb0..9008d34 100644
--- a/ash/accessibility/accessibility_focus_ring_layer.cc
+++ b/ash/accessibility/accessibility_focus_ring_layer.cc
@@ -105,7 +105,7 @@
   CreateOrUpdateLayer(root_window, "AccessibilityFocusRing", bounds);
 }
 
-void AccessibilityFocusRingLayer::SetAppearance(mojom::FocusRingType type,
+void AccessibilityFocusRingLayer::SetAppearance(FocusRingType type,
                                                 SkColor color,
                                                 SkColor secondary_color) {
   SetColor(color);
@@ -122,13 +122,13 @@
   flags.setStyle(cc::PaintFlags::kStroke_Style);
 
   switch (type_) {
-    case mojom::FocusRingType::GLOW:
+    case FocusRingType::GLOW:
       DrawGlowFocusRing(recorder, flags);
       break;
-    case mojom::FocusRingType::SOLID:
+    case FocusRingType::SOLID:
       DrawSolidFocusRing(recorder, flags);
       break;
-    case mojom::FocusRingType::DASHED:
+    case FocusRingType::DASHED:
       DrawDashedFocusRing(recorder, flags);
       break;
   }
diff --git a/ash/accessibility/accessibility_focus_ring_layer.h b/ash/accessibility/accessibility_focus_ring_layer.h
index 42ba115..49e214e2 100644
--- a/ash/accessibility/accessibility_focus_ring_layer.h
+++ b/ash/accessibility/accessibility_focus_ring_layer.h
@@ -8,7 +8,7 @@
 #include "ash/accessibility/accessibility_focus_ring.h"
 #include "ash/accessibility/focus_ring_layer.h"
 #include "ash/ash_export.h"
-#include "ash/public/interfaces/accessibility_focus_ring_controller.mojom.h"
+#include "ash/public/cpp/accessibility_focus_ring_info.h"
 #include "base/macros.h"
 #include "ui/compositor/paint_recorder.h"
 
@@ -25,7 +25,7 @@
   // Create the layer and update its bounds and position in the hierarchy.
   void Set(const AccessibilityFocusRing& ring);
 
-  void SetAppearance(mojom::FocusRingType type,
+  void SetAppearance(FocusRingType type,
                      SkColor color,
                      SkColor secondary_color);
 
@@ -42,7 +42,7 @@
   // The outline of the current focus ring.
   AccessibilityFocusRing ring_;
   // The type of focus ring.
-  mojom::FocusRingType type_;
+  FocusRingType type_;
   // The secondary color.
   SkColor secondary_color_;
 
diff --git a/ash/accessibility/accessibility_highlight_controller.cc b/ash/accessibility/accessibility_highlight_controller.cc
index b64422c..03d406f 100644
--- a/ash/accessibility/accessibility_highlight_controller.cc
+++ b/ash/accessibility/accessibility_highlight_controller.cc
@@ -6,9 +6,9 @@
 
 #include <vector>
 
-#include "ash/accessibility/accessibility_focus_ring_controller.h"
+#include "ash/accessibility/accessibility_focus_ring_controller_impl.h"
 #include "ash/display/window_tree_host_manager.h"
-#include "ash/public/interfaces/accessibility_focus_ring_controller.mojom.h"
+#include "ash/public/cpp/accessibility_focus_ring_info.h"
 #include "ash/shell.h"
 #include "ui/base/ime/input_method.h"
 #include "ui/base/ime/text_input_client.h"
@@ -34,10 +34,10 @@
 
 void SetFocusRing(AccessibilityFocusRingController* controller,
                   std::vector<gfx::Rect> rects) {
-  mojom::FocusRingPtr focus_ring = mojom::FocusRing::New();
+  auto focus_ring = std::make_unique<AccessibilityFocusRingInfo>();
   focus_ring->rects_in_screen = rects;
-  focus_ring->behavior = mojom::FocusRingBehavior::FADE_OUT_FOCUS_RING;
-  focus_ring->type = mojom::FocusRingType::GLOW;
+  focus_ring->behavior = FocusRingBehavior::FADE_OUT;
+  focus_ring->type = FocusRingType::GLOW;
   focus_ring->color = kFocusColor;
 
   controller->SetFocusRing(kHighlightCallerId, std::move(focus_ring));
@@ -56,7 +56,7 @@
 }
 
 AccessibilityHighlightController::~AccessibilityHighlightController() {
-  AccessibilityFocusRingController* controller =
+  AccessibilityFocusRingControllerImpl* controller =
       Shell::Get()->accessibility_focus_ring_controller();
   SetFocusRing(controller, std::vector<gfx::Rect>());
   controller->HideCaretRing();
@@ -162,7 +162,7 @@
 }
 
 void AccessibilityHighlightController::UpdateFocusAndCaretHighlights() {
-  AccessibilityFocusRingController* controller =
+  AccessibilityFocusRingControllerImpl* controller =
       Shell::Get()->accessibility_focus_ring_controller();
 
   // The caret highlight takes precedence over the focus highlight if
@@ -183,7 +183,7 @@
 }
 
 void AccessibilityHighlightController::UpdateCursorHighlight() {
-  AccessibilityFocusRingController* controller =
+  AccessibilityFocusRingControllerImpl* controller =
       Shell::Get()->accessibility_focus_ring_controller();
   if (cursor_ && IsCursorVisible())
     controller->SetCursorRing(cursor_point_);
diff --git a/ash/accessibility/accessibility_highlight_controller_unittest.cc b/ash/accessibility/accessibility_highlight_controller_unittest.cc
index 2bff3a8..b060268 100644
--- a/ash/accessibility/accessibility_highlight_controller_unittest.cc
+++ b/ash/accessibility/accessibility_highlight_controller_unittest.cc
@@ -9,7 +9,7 @@
 
 #include "ash/accessibility/accessibility_controller.h"
 #include "ash/accessibility/accessibility_cursor_ring_layer.h"
-#include "ash/accessibility/accessibility_focus_ring_controller.h"
+#include "ash/accessibility/accessibility_focus_ring_controller_impl.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "base/bind.h"
@@ -209,7 +209,7 @@
   event_mod.set_target(root_windows[0]);
   highlight_controller.OnMouseEvent(&event0);
 
-  AccessibilityFocusRingController* focus_ring_controller =
+  AccessibilityFocusRingControllerImpl* focus_ring_controller =
       Shell::Get()->accessibility_focus_ring_controller();
   auto* cursor_layer = focus_ring_controller->cursor_layer_for_testing();
   EXPECT_EQ(root_windows[0], cursor_layer->root_window());
@@ -251,7 +251,7 @@
   text_input_client.SetCaretBounds(caret_bounds);
   highlight_controller.OnCaretBoundsChanged(&text_input_client);
 
-  AccessibilityFocusRingController* focus_ring_controller =
+  AccessibilityFocusRingControllerImpl* focus_ring_controller =
       Shell::Get()->accessibility_focus_ring_controller();
   auto* caret_layer = focus_ring_controller->caret_layer_for_testing();
   EXPECT_EQ(
@@ -308,7 +308,7 @@
 
   // Bounds inside the active window create a highlight.
   accessibility_controller->SetCaretBounds(gfx::Rect(10, 10, 1, 16));
-  AccessibilityFocusRingController* focus_ring_controller =
+  AccessibilityFocusRingControllerImpl* focus_ring_controller =
       Shell::Get()->accessibility_focus_ring_controller();
   EXPECT_TRUE(focus_ring_controller->caret_layer_for_testing());
 
diff --git a/ash/accessibility/accessibility_panel_layout_manager.cc b/ash/accessibility/accessibility_panel_layout_manager.cc
index 890706e..e17cf78 100644
--- a/ash/accessibility/accessibility_panel_layout_manager.cc
+++ b/ash/accessibility/accessibility_panel_layout_manager.cc
@@ -104,12 +104,6 @@
   RootWindowController* root_controller =
       RootWindowController::ForWindow(root_window);
 
-  aura::Window* current = panel_window_;
-  while (current->parent()) {
-    current->parent()->StackChildAtTop(current);
-    current = current->parent();
-  }
-
   gfx::Rect bounds = panel_bounds_;
 
   // The panel can make itself fill the screen (including covering the shelf).
diff --git a/ash/accessibility/touch_exploration_manager.cc b/ash/accessibility/touch_exploration_manager.cc
index 3981923..67b94446 100644
--- a/ash/accessibility/touch_exploration_manager.cc
+++ b/ash/accessibility/touch_exploration_manager.cc
@@ -8,11 +8,11 @@
 #include <vector>
 
 #include "ash/accessibility/accessibility_controller.h"
-#include "ash/accessibility/accessibility_focus_ring_controller.h"
+#include "ash/accessibility/accessibility_focus_ring_controller_impl.h"
 #include "ash/accessibility/touch_exploration_controller.h"
 #include "ash/keyboard/ui/keyboard_controller.h"
+#include "ash/public/cpp/accessibility_focus_ring_info.h"
 #include "ash/public/cpp/app_types.h"
-#include "ash/public/interfaces/accessibility_focus_ring_controller.mojom.h"
 #include "ash/root_window_controller.h"
 #include "ash/shell.h"
 #include "ash/wm/window_util.h"
@@ -230,7 +230,7 @@
       SilenceSpokenFeedback();
       // Clear the focus highlight.
       Shell::Get()->accessibility_focus_ring_controller()->SetFocusRing(
-          extension_misc::kChromeVoxExtensionId, mojom::FocusRing::New());
+          extension_misc::kChromeVoxExtensionId, nullptr);
     } else {
       touch_exploration_controller_->SetExcludeBounds(gfx::Rect());
     }
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index 14f0625..0ef32d4d 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -401,6 +401,10 @@
         Mute
       </message>
 
+      <message name="IDS_ASH_FEATURE_DISABLED_BY_POLICY" desc="The message used to indicate that this feature is disabled by policy.">
+        <ph name="FEATURE_NAME">$1<ex>Docked magnifier</ex></ph> has been disabled by a policy applied to this device. Please talk to your administrator to request changes.
+      </message>
+
       <message name="IDS_ASH_STATUS_TRAY_IME_SHORT" desc="The short label used for IME button in system tray bubble.">
         Keyboard
       </message>
diff --git a/ash/login_status.h b/ash/login_status.h
index 072c29c4..c7d726c 100644
--- a/ash/login_status.h
+++ b/ash/login_status.h
@@ -11,7 +11,6 @@
   NOT_LOGGED_IN,  // Not logged in
   LOCKED,         // A user has locked the screen
   USER,           // A regular user is logged in
-  OWNER,          // The owner of the device is logged in
   GUEST,          // A guest is logged in (i.e. incognito)
   PUBLIC,         // A public account is logged in
   SUPERVISED,     // A supervised user is logged in
diff --git a/ash/mojo_interface_factory.cc b/ash/mojo_interface_factory.cc
index ab6fca97..167bf56 100644
--- a/ash/mojo_interface_factory.cc
+++ b/ash/mojo_interface_factory.cc
@@ -7,7 +7,6 @@
 #include <utility>
 
 #include "ash/accessibility/accessibility_controller.h"
-#include "ash/accessibility/accessibility_focus_ring_controller.h"
 #include "ash/app_list/app_list_controller_impl.h"
 #include "ash/assistant/assistant_alarm_timer_controller.h"
 #include "ash/assistant/assistant_controller.h"
@@ -43,12 +42,6 @@
   Shell::Get()->accessibility_controller()->BindRequest(std::move(request));
 }
 
-void BindAccessibilityFocusRingControllerRequestOnMainThread(
-    mojom::AccessibilityFocusRingControllerRequest request) {
-  Shell::Get()->accessibility_focus_ring_controller()->BindRequest(
-      std::move(request));
-}
-
 void BindAssistantAlarmTimerControllerRequestOnMainThread(
     mojom::AssistantAlarmTimerControllerRequest request) {
   Shell::Get()->assistant_controller()->alarm_timer_controller()->BindRequest(
@@ -119,10 +112,6 @@
   registry->AddInterface(
       base::BindRepeating(&BindAccessibilityControllerRequestOnMainThread),
       main_thread_task_runner);
-  registry->AddInterface(
-      base::BindRepeating(
-          &BindAccessibilityFocusRingControllerRequestOnMainThread),
-      main_thread_task_runner);
   if (chromeos::switches::IsAssistantEnabled()) {
     registry->AddInterface(
         base::BindRepeating(
diff --git a/ash/public/cpp/BUILD.gn b/ash/public/cpp/BUILD.gn
index 510c218..fa59943 100644
--- a/ash/public/cpp/BUILD.gn
+++ b/ash/public/cpp/BUILD.gn
@@ -9,6 +9,10 @@
   sources = [
     "accelerators.cc",
     "accelerators.h",
+    "accessibility_focus_ring_controller.cc",
+    "accessibility_focus_ring_controller.h",
+    "accessibility_focus_ring_info.cc",
+    "accessibility_focus_ring_info.h",
     "android_intent_helper.cc",
     "android_intent_helper.h",
     "app_list/app_list_client.h",
@@ -35,6 +39,8 @@
     "app_list/tokenized_string_match.h",
     "app_menu_constants.h",
     "app_types.h",
+    "arc_app_id_provider.cc",
+    "arc_app_id_provider.h",
     "ash_constants.h",
     "ash_features.cc",
     "ash_features.h",
diff --git a/ash/public/cpp/accessibility_focus_ring_controller.cc b/ash/public/cpp/accessibility_focus_ring_controller.cc
new file mode 100644
index 0000000..19e0214
--- /dev/null
+++ b/ash/public/cpp/accessibility_focus_ring_controller.cc
@@ -0,0 +1,29 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/public/cpp/accessibility_focus_ring_controller.h"
+
+#include "base/logging.h"
+
+namespace ash {
+
+namespace {
+AccessibilityFocusRingController* g_instance = nullptr;
+}
+
+AccessibilityFocusRingController* AccessibilityFocusRingController::Get() {
+  return g_instance;
+}
+
+AccessibilityFocusRingController::AccessibilityFocusRingController() {
+  DCHECK_EQ(nullptr, g_instance);
+  g_instance = this;
+}
+
+AccessibilityFocusRingController::~AccessibilityFocusRingController() {
+  DCHECK_EQ(this, g_instance);
+  g_instance = nullptr;
+}
+
+}  // namespace ash
diff --git a/ash/public/cpp/accessibility_focus_ring_controller.h b/ash/public/cpp/accessibility_focus_ring_controller.h
new file mode 100644
index 0000000..e609173
--- /dev/null
+++ b/ash/public/cpp/accessibility_focus_ring_controller.h
@@ -0,0 +1,59 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_PUBLIC_CPP_ACCESSIBILITY_FOCUS_RING_CONTROLLER_H_
+#define ASH_PUBLIC_CPP_ACCESSIBILITY_FOCUS_RING_CONTROLLER_H_
+
+#include <string>
+#include <vector>
+
+#include "ash/public/cpp/ash_public_export.h"
+#include "base/macros.h"
+#include "third_party/skia/include/core/SkColor.h"
+
+namespace gfx {
+class Rect;
+}
+
+namespace ash {
+
+struct AccessibilityFocusRingInfo;
+
+// Interface to control accessibility focus ring features.
+class ASH_PUBLIC_EXPORT AccessibilityFocusRingController {
+ public:
+  static AccessibilityFocusRingController* Get();
+
+  // Sets the focus ring with the given ID to the specifications of focus_ring.
+  virtual void SetFocusRing(
+      const std::string& focus_ring_id,
+      std::unique_ptr<AccessibilityFocusRingInfo> focus_ring) = 0;
+
+  // Hides focus ring on screen with the given ID.
+  virtual void HideFocusRing(const std::string& focus_ring_id) = 0;
+
+  // Draws a highlight at the given rects in screen coordinates. Rects may be
+  // overlapping and will be merged into one layer. This looks similar to
+  // selecting a region with the cursor, except it is drawn in the foreground
+  // rather than behind a text layer.
+  // TODO(katie): Add |caller_id| to highlights as well if other Accessibility
+  // tools or extensions want to use this API.
+  virtual void SetHighlights(const std::vector<gfx::Rect>& rects_in_screen,
+                             SkColor skcolor) = 0;
+
+  // Hides highlight on screen.
+  // TODO(katie): Add |caller_id| to highlights as well.
+  virtual void HideHighlights() = 0;
+
+ protected:
+  AccessibilityFocusRingController();
+  virtual ~AccessibilityFocusRingController();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AccessibilityFocusRingController);
+};
+
+}  // namespace ash
+
+#endif  // ASH_PUBLIC_CPP_ACCESSIBILITY_FOCUS_RING_CONTROLLER_H_
diff --git a/ash/public/cpp/accessibility_focus_ring_info.cc b/ash/public/cpp/accessibility_focus_ring_info.cc
new file mode 100644
index 0000000..e0082ea
--- /dev/null
+++ b/ash/public/cpp/accessibility_focus_ring_info.cc
@@ -0,0 +1,19 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/public/cpp/accessibility_focus_ring_info.h"
+
+namespace ash {
+
+AccessibilityFocusRingInfo::AccessibilityFocusRingInfo() = default;
+AccessibilityFocusRingInfo::~AccessibilityFocusRingInfo() = default;
+
+bool AccessibilityFocusRingInfo::operator==(
+    const AccessibilityFocusRingInfo& other) const {
+  return rects_in_screen == other.rects_in_screen &&
+         behavior == other.behavior && type == other.type &&
+         color == other.color && secondary_color == other.secondary_color;
+}
+
+}  // namespace ash
diff --git a/ash/public/cpp/accessibility_focus_ring_info.h b/ash/public/cpp/accessibility_focus_ring_info.h
new file mode 100644
index 0000000..90cfe50f5
--- /dev/null
+++ b/ash/public/cpp/accessibility_focus_ring_info.h
@@ -0,0 +1,48 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_PUBLIC_CPP_ACCESSIBILITY_FOCUS_RING_INFO_H_
+#define ASH_PUBLIC_CPP_ACCESSIBILITY_FOCUS_RING_INFO_H_
+
+#include <vector>
+
+#include "ash/public/cpp/ash_public_export.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace ash {
+
+// Whether the focus ring should persist or fade.
+enum class ASH_PUBLIC_EXPORT FocusRingBehavior { FADE_OUT, PERSIST };
+
+// The visual style of the focus ring.
+enum class ASH_PUBLIC_EXPORT FocusRingType { GLOW, SOLID, DASHED };
+
+// Defines a specific focus ring by specifying:
+// - |rects_in_screen| the regions around which to draw the focus ring (in
+//       screen coordinates).
+// - |focus_ring_behavior| whether it should persist or fade.
+// - |focus_ring_type| the visual style of the focus ring.
+// - |color| the color of the focus ring.
+// - |secondary_color| a secondary color, used by some visual styles.
+// TODO: This struct could possibly be merged with ash::AccessibilityFocusRing.
+struct ASH_PUBLIC_EXPORT AccessibilityFocusRingInfo {
+  AccessibilityFocusRingInfo();
+  ~AccessibilityFocusRingInfo();
+
+  bool operator==(const AccessibilityFocusRingInfo& other) const;
+
+  std::vector<gfx::Rect> rects_in_screen;
+  FocusRingBehavior behavior = FocusRingBehavior::FADE_OUT;
+  FocusRingType type = FocusRingType::GLOW;
+  SkColor color = SK_ColorTRANSPARENT;
+  SkColor secondary_color = SK_ColorTRANSPARENT;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AccessibilityFocusRingInfo);
+};
+
+}  // namespace ash
+
+#endif  // ASH_PUBLIC_CPP_ACCESSIBILITY_FOCUS_RING_INFO_H_
diff --git a/ash/public/cpp/arc_app_id_provider.cc b/ash/public/cpp/arc_app_id_provider.cc
new file mode 100644
index 0000000..99aeb3b
--- /dev/null
+++ b/ash/public/cpp/arc_app_id_provider.cc
@@ -0,0 +1,30 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/public/cpp/arc_app_id_provider.h"
+
+#include "base/logging.h"
+
+namespace ash {
+
+namespace {
+ArcAppIdProvider* g_instance = nullptr;
+}
+
+// static
+ArcAppIdProvider* ArcAppIdProvider::Get() {
+  return g_instance;
+}
+
+ArcAppIdProvider::ArcAppIdProvider() {
+  DCHECK_EQ(nullptr, g_instance);
+  g_instance = this;
+}
+
+ArcAppIdProvider::~ArcAppIdProvider() {
+  DCHECK_EQ(this, g_instance);
+  g_instance = nullptr;
+}
+
+}  // namespace ash
diff --git a/ash/public/cpp/arc_app_id_provider.h b/ash/public/cpp/arc_app_id_provider.h
new file mode 100644
index 0000000..185b44f
--- /dev/null
+++ b/ash/public/cpp/arc_app_id_provider.h
@@ -0,0 +1,28 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_PUBLIC_CPP_ARC_APP_ID_PROVIDER_H_
+#define ASH_PUBLIC_CPP_ARC_APP_ID_PROVIDER_H_
+
+#include <string>
+
+#include "ash/public/cpp/ash_public_export.h"
+
+namespace ash {
+
+class ASH_PUBLIC_EXPORT ArcAppIdProvider {
+ public:
+  static ArcAppIdProvider* Get();
+
+  virtual std::string GetAppIdByPackageName(
+      const std::string& package_name) = 0;
+
+ protected:
+  ArcAppIdProvider();
+  virtual ~ArcAppIdProvider();
+};
+
+}  // namespace ash
+
+#endif  // ASH_PUBLIC_CPP_ARC_APP_ID_PROVIDER_H_
diff --git a/ash/public/cpp/manifest.cc b/ash/public/cpp/manifest.cc
index 2da67c0..07d25a6 100644
--- a/ash/public/cpp/manifest.cc
+++ b/ash/public/cpp/manifest.cc
@@ -5,7 +5,6 @@
 #include "ash/public/cpp/manifest.h"
 
 #include "ash/public/interfaces/accessibility_controller.mojom.h"
-#include "ash/public/interfaces/accessibility_focus_ring_controller.mojom.h"
 #include "ash/public/interfaces/ash_message_center_controller.mojom.h"
 #include "ash/public/interfaces/assistant_controller.mojom.h"
 #include "ash/public/interfaces/assistant_volume_control.mojom.h"
@@ -48,7 +47,6 @@
               "system_ui",
               service_manager::Manifest::InterfaceList<
                   mojom::AccessibilityController,
-                  mojom::AccessibilityFocusRingController,
                   mojom::AshMessageCenterController,
                   mojom::AssistantAlarmTimerController,
                   mojom::AssistantController,
diff --git a/ash/public/cpp/session/user_info.cc b/ash/public/cpp/session/user_info.cc
index 8374ce7..b2abfee0 100644
--- a/ash/public/cpp/session/user_info.cc
+++ b/ash/public/cpp/session/user_info.cc
@@ -25,7 +25,6 @@
          a.display_email == b.display_email && a.avatar == b.avatar &&
          a.is_new_profile == b.is_new_profile &&
          a.is_ephemeral == b.is_ephemeral &&
-         a.is_device_owner == b.is_device_owner &&
          a.has_gaia_account == b.has_gaia_account &&
          a.should_display_managed_ui == b.should_display_managed_ui;
 }
diff --git a/ash/public/cpp/session/user_info.h b/ash/public/cpp/session/user_info.h
index 6656db1..c1eabe02 100644
--- a/ash/public/cpp/session/user_info.h
+++ b/ash/public/cpp/session/user_info.h
@@ -54,9 +54,6 @@
   // ephemeral. See |UserManager::IsUserNonCryptohomeDataEphemeral| for details.
   bool is_ephemeral = false;
 
-  // True if the user is also the device owner.
-  bool is_device_owner = false;
-
   // True if the user has a gaia account.
   bool has_gaia_account = false;
 
diff --git a/ash/public/interfaces/BUILD.gn b/ash/public/interfaces/BUILD.gn
index e797225..ef68aceb 100644
--- a/ash/public/interfaces/BUILD.gn
+++ b/ash/public/interfaces/BUILD.gn
@@ -10,7 +10,6 @@
   sources = [
     "accessibility_controller.mojom",
     "accessibility_controller_enums.mojom",
-    "accessibility_focus_ring_controller.mojom",
     "ash_message_center_controller.mojom",
     "assistant_controller.mojom",
     "assistant_volume_control.mojom",
diff --git a/ash/public/interfaces/accessibility_focus_ring_controller.mojom b/ash/public/interfaces/accessibility_focus_ring_controller.mojom
deleted file mode 100644
index 91cf8e0..0000000
--- a/ash/public/interfaces/accessibility_focus_ring_controller.mojom
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module ash.mojom;
-
-import "ui/gfx/geometry/mojo/geometry.mojom";
-
-enum FocusRingBehavior { FADE_OUT_FOCUS_RING, PERSIST_FOCUS_RING };
-
-enum FocusRingType { GLOW, SOLID, DASHED };
-
-// Defines a specific focus ring by specifying:
-// - |rects_in_screen| the regions around which to draw the focus ring (in
-//       screen coordinates).
-// - |focus_ring_behavior| whether it should persist or fade.
-// - |focus_ring_type| the visual style of the focus ring.
-// - |color| the color of the focus ring.
-// - |secondary_color| a secondary color, used by some visual styles. The
-//       default value is SK_ColorTRANSPARENT.
-struct FocusRing {
-  array<gfx.mojom.Rect> rects_in_screen;
-  FocusRingBehavior behavior;
-  FocusRingType type;
-  uint32 color;
-  uint32 secondary_color = 0; // SK_ColorTRANSPARENT
-};
-
-
-// Interface for ash client (e.g. Chrome) to control and query accessibility
-// focus ring features.
-interface AccessibilityFocusRingController {
-  // Sets the focus ring with the given ID to the specifications of focus_ring.
-  SetFocusRing(string focus_ring_id, FocusRing focus_ring);
-
-  // Hides focus ring on screen with the given ID.
-  HideFocusRing(string focus_ring_id);
-
-  // Draws a highlight at the given rects in screen coordinates. Rects may be
-  // overlapping and will be merged into one layer. This looks similar to
-  // selecting a region with the cursor, except it is drawn in the foreground
-  // rather than behind a text layer.
-  // TODO(katie): Add |caller_id| to highlights as well if other Accessibility
-  // tools or extensions want to use this API.
-  SetHighlights(array<gfx.mojom.Rect> rects_in_screen, uint32 skcolor);
-
-  // Hides highlight on screen.
-  // TODO(katie): Add |caller_id| to highlights as well.
-  HideHighlights();
-};
diff --git a/ash/public/interfaces/ash_message_center_controller.mojom b/ash/public/interfaces/ash_message_center_controller.mojom
index cd74659..1effb5a 100644
--- a/ash/public/interfaces/ash_message_center_controller.mojom
+++ b/ash/public/interfaces/ash_message_center_controller.mojom
@@ -6,23 +6,10 @@
 
 import "components/arc/common/notifications.mojom";
 
-// The message center controller funnels notification requests from the client
-// to the MessageCenter.
 interface AshMessageCenterController {
-  SetClient(associated AshMessageCenterClient client);
-
   // Sets the ARC notification instance.
   SetArcNotificationsInstance(arc.mojom.NotificationsInstance instance);
 
   // Changes the quiet mode state in the message center.
   SetQuietMode(bool enabled);
 };
-
-// The message center client interface mimics
-// message_center::NotificationDelegate. The ID strings match the id passed in
-// |notification| in ShowClientNotification and the format of the ID is up to
-// the client.
-interface AshMessageCenterClient {
-  // Gets ARC app id from a given package name.
-  GetArcAppIdByPackageName(string package_name) => (string app_id);
-};
diff --git a/ash/public/interfaces/voice_interaction_controller.mojom b/ash/public/interfaces/voice_interaction_controller.mojom
index 21b618f..8974772 100644
--- a/ash/public/interfaces/voice_interaction_controller.mojom
+++ b/ash/public/interfaces/voice_interaction_controller.mojom
@@ -44,7 +44,9 @@
   // Disallowed because the user's account type is currently not supported.
   DISALLOWED_BY_ACCOUNT_TYPE,
   // Disallowed because the device is in Kiosk mode.
-  DISALLOWED_BY_KIOSK_MODE
+  DISALLOWED_BY_KIOSK_MODE,
+  // Disallowed because Kiosk Next is enabled.
+  DISALLOWED_BY_KIOSK_NEXT,
 };
 
 // Allows observing changes to voice interaction status and settings.
diff --git a/ash/session/session_controller_impl.cc b/ash/session/session_controller_impl.cc
index 260fd6b8..1133cb7 100644
--- a/ash/session/session_controller_impl.cc
+++ b/ash/session/session_controller_impl.cc
@@ -561,8 +561,7 @@
 
   switch (user_sessions_[0]->user_info.type) {
     case user_manager::USER_TYPE_REGULAR:
-      return user_sessions_[0]->user_info.is_device_owner ? LoginStatus::OWNER
-                                                          : LoginStatus::USER;
+      return LoginStatus::USER;
     case user_manager::USER_TYPE_GUEST:
       return LoginStatus::GUEST;
     case user_manager::USER_TYPE_PUBLIC_ACCOUNT:
diff --git a/ash/session/session_controller_impl_unittest.cc b/ash/session/session_controller_impl_unittest.cc
index 7edb966..91d2601 100644
--- a/ash/session/session_controller_impl_unittest.cc
+++ b/ash/session/session_controller_impl_unittest.cc
@@ -312,25 +312,6 @@
   }
 }
 
-TEST_F(SessionControllerImplTest, GetLoginStateForOwner) {
-  // Simulate an active user session.
-  SessionInfo info;
-  FillDefaultSessionInfo(&info);
-  info.state = SessionState::ACTIVE;
-  SetSessionInfo(info);
-
-  UserSession session;
-  session.session_id = 1u;
-  session.user_info.type = user_manager::USER_TYPE_REGULAR;
-  session.user_info.account_id = AccountId::FromUserEmail("owner@test.com");
-  session.user_info.display_name = "Owner";
-  session.user_info.display_email = "owner@test.com";
-  session.user_info.is_device_owner = true;
-  controller()->UpdateUserSession(session);
-
-  EXPECT_EQ(LoginStatus::OWNER, controller()->login_status());
-}
-
 // Tests that user sessions can be set and updated.
 TEST_F(SessionControllerImplTest, UserSessions) {
   EXPECT_FALSE(controller()->IsActiveUserSessionStarted());
diff --git a/ash/shelf/shelf_context_menu_model.cc b/ash/shelf/shelf_context_menu_model.cc
index a0fc73d..dd5f546 100644
--- a/ash/shelf/shelf_context_menu_model.cc
+++ b/ash/shelf/shelf_context_menu_model.cc
@@ -162,7 +162,7 @@
   // Only allow shelf alignment modifications by the owner or user. In tablet
   // mode, the shelf alignment option is not shown.
   LoginStatus status = Shell::Get()->session_controller()->login_status();
-  if ((status == LoginStatus::USER || status == LoginStatus::OWNER) &&
+  if (status == LoginStatus::USER &&
       !Shell::Get()->tablet_mode_controller()->InTabletMode()) {
     alignment_submenu_ = std::make_unique<ui::SimpleMenuModel>(this);
 
diff --git a/ash/shell.cc b/ash/shell.cc
index b9bcf59..9e42f75 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -17,7 +17,7 @@
 #include "ash/accelerometer/accelerometer_reader.h"
 #include "ash/accessibility/accessibility_controller.h"
 #include "ash/accessibility/accessibility_delegate.h"
-#include "ash/accessibility/accessibility_focus_ring_controller.h"
+#include "ash/accessibility/accessibility_focus_ring_controller_impl.h"
 #include "ash/accessibility/key_accessibility_enabler.h"
 #include "ash/app_list/app_list_controller_impl.h"
 #include "ash/assistant/assistant_controller.h"
@@ -898,7 +898,7 @@
   tablet_mode_controller_ = std::make_unique<TabletModeController>();
 
   accessibility_focus_ring_controller_ =
-      std::make_unique<AccessibilityFocusRingController>();
+      std::make_unique<AccessibilityFocusRingControllerImpl>();
   accessibility_delegate_.reset(shell_delegate_->CreateAccessibilityDelegate());
   accessibility_controller_ = std::make_unique<AccessibilityController>();
   toast_manager_ = std::make_unique<ToastManagerImpl>();
diff --git a/ash/shell.h b/ash/shell.h
index ab7198c..6e1ecea 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -90,7 +90,7 @@
 class AcceleratorControllerImpl;
 class AccessibilityController;
 class AccessibilityDelegate;
-class AccessibilityFocusRingController;
+class AccessibilityFocusRingControllerImpl;
 class AshDBusHelper;
 class AshDBusServices;
 class AshFocusRules;
@@ -302,7 +302,7 @@
   AccessibilityDelegate* accessibility_delegate() {
     return accessibility_delegate_.get();
   }
-  AccessibilityFocusRingController* accessibility_focus_ring_controller() {
+  AccessibilityFocusRingControllerImpl* accessibility_focus_ring_controller() {
     return accessibility_focus_ring_controller_.get();
   }
   ::wm::ActivationClient* activation_client();
@@ -639,7 +639,7 @@
   std::unique_ptr<AcceleratorControllerImpl> accelerator_controller_;
   std::unique_ptr<AccessibilityController> accessibility_controller_;
   std::unique_ptr<AccessibilityDelegate> accessibility_delegate_;
-  std::unique_ptr<AccessibilityFocusRingController>
+  std::unique_ptr<AccessibilityFocusRingControllerImpl>
       accessibility_focus_ring_controller_;
   std::unique_ptr<AppListControllerImpl> app_list_controller_;
   std::unique_ptr<AshDBusHelper> ash_dbus_helper_;
diff --git a/ash/system/message_center/arc/arc_notification_manager.cc b/ash/system/message_center/arc/arc_notification_manager.cc
index 5192552..b5ed366 100644
--- a/ash/system/message_center/arc/arc_notification_manager.cc
+++ b/ash/system/message_center/arc/arc_notification_manager.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <utility>
 
+#include "ash/public/cpp/arc_app_id_provider.h"
 #include "ash/public/cpp/ash_features.h"
 #include "ash/system/message_center/arc/arc_notification_constants.h"
 #include "ash/system/message_center/arc/arc_notification_delegate.h"
@@ -191,10 +192,11 @@
     it = result.first;
   }
 
-  delegate_->GetAppIdByPackageName(
-      data->package_name.value_or(std::string()),
-      base::BindOnce(&ArcNotificationManager::OnGotAppId,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(data)));
+  std::string app_id =
+      data->package_name
+          ? ArcAppIdProvider::Get()->GetAppIdByPackageName(*data->package_name)
+          : std::string();
+  it->second->OnUpdatedFromAndroid(std::move(data), app_id);
 }
 
 void ArcNotificationManager::OnNotificationUpdated(
@@ -235,10 +237,11 @@
     previously_focused_notification_key_.clear();
   }
 
-  delegate_->GetAppIdByPackageName(
-      data->package_name.value_or(std::string()),
-      base::BindOnce(&ArcNotificationManager::OnGotAppId,
-                     weak_ptr_factory_.GetWeakPtr(), std::move(data)));
+  std::string app_id =
+      data->package_name
+          ? ArcAppIdProvider::Get()->GetAppIdByPackageName(*data->package_name)
+          : std::string();
+  it->second->OnUpdatedFromAndroid(std::move(data), app_id);
 }
 
 void ArcNotificationManager::OpenMessageCenter() {
@@ -489,16 +492,6 @@
   return false;
 }
 
-void ArcNotificationManager::OnGotAppId(ArcNotificationDataPtr data,
-                                        const std::string& app_id) {
-  const std::string& key = data->key;
-  auto it = items_.find(key);
-  if (it == items_.end())
-    return;
-
-  it->second->OnUpdatedFromAndroid(std::move(data), app_id);
-}
-
 void ArcNotificationManager::OnDoNotDisturbStatusUpdated(
     ArcDoNotDisturbStatusPtr status) {
   // Remove the observer to prevent from sending the command to Android since
diff --git a/ash/system/message_center/arc/arc_notification_manager.h b/ash/system/message_center/arc/arc_notification_manager.h
index 96326eb..3d2d4ce 100644
--- a/ash/system/message_center/arc/arc_notification_manager.h
+++ b/ash/system/message_center/arc/arc_notification_manager.h
@@ -81,10 +81,6 @@
   void PerformUserAction(uint32_t id, bool open_message_center);
   void CancelUserAction(uint32_t id);
 
-  // Invoked when |get_app_id_callback_| gets back the app id.
-  void OnGotAppId(arc::mojom::ArcNotificationDataPtr data,
-                  const std::string& app_id);
-
   std::unique_ptr<ArcNotificationManagerDelegate> delegate_;
   const AccountId main_profile_id_;
   message_center::MessageCenter* const message_center_;
diff --git a/ash/system/message_center/arc/arc_notification_manager_delegate.h b/ash/system/message_center/arc/arc_notification_manager_delegate.h
index 7ccf900..bc49ff4 100644
--- a/ash/system/message_center/arc/arc_notification_manager_delegate.h
+++ b/ash/system/message_center/arc/arc_notification_manager_delegate.h
@@ -19,13 +19,6 @@
   // Whether the current user session is public session or kiosk.
   virtual bool IsPublicSessionOrKiosk() const = 0;
 
-  // Gets app id by package name.
-  using GetAppIdByPackageNameCallback =
-      base::OnceCallback<void(const std::string& app_id)>;
-  virtual void GetAppIdByPackageName(
-      const std::string& package_name,
-      GetAppIdByPackageNameCallback callback) = 0;
-
   // Shows the message center.
   virtual void ShowMessageCenter() = 0;
 
diff --git a/ash/system/message_center/arc/arc_notification_manager_unittest.cc b/ash/system/message_center/arc/arc_notification_manager_unittest.cc
index b573022..20d5920 100644
--- a/ash/system/message_center/arc/arc_notification_manager_unittest.cc
+++ b/ash/system/message_center/arc/arc_notification_manager_unittest.cc
@@ -8,6 +8,7 @@
 #include <utility>
 #include <vector>
 
+#include "ash/public/cpp/arc_app_id_provider.h"
 #include "ash/system/message_center/arc/arc_notification_manager.h"
 #include "ash/system/message_center/arc/arc_notification_manager_delegate.h"
 #include "base/message_loop/message_loop.h"
@@ -27,6 +28,20 @@
 
 const char kDummyNotificationKey[] = "DUMMY_NOTIFICATION_KEY";
 
+class TestArcAppIdProvider : public ArcAppIdProvider {
+ public:
+  TestArcAppIdProvider() = default;
+  ~TestArcAppIdProvider() override = default;
+
+  // ArcAppIdProvider:
+  std::string GetAppIdByPackageName(const std::string& package_name) override {
+    return {};
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestArcAppIdProvider);
+};
+
 class MockMessageCenter : public message_center::FakeMessageCenter {
  public:
   MockMessageCenter() = default;
@@ -80,10 +95,6 @@
 
   // ArcNotificationManagerDelegate:
   bool IsPublicSessionOrKiosk() const override { return false; }
-  void GetAppIdByPackageName(const std::string& package_name,
-                             GetAppIdByPackageNameCallback callback) override {
-    std::move(callback).Run(std::string());
-  }
   void ShowMessageCenter() override {}
   void HideMessageCenter() override {}
 
@@ -157,6 +168,7 @@
   }
 
   base::MessageLoop loop_;
+  TestArcAppIdProvider app_id_provider_;
   std::unique_ptr<arc::FakeNotificationsInstance> arc_notifications_instance_;
   std::unique_ptr<mojo::Binding<arc::mojom::NotificationsInstance>> binding_;
   std::unique_ptr<ArcNotificationManager> arc_notification_manager_;
diff --git a/ash/system/message_center/arc_notification_manager_delegate_impl.cc b/ash/system/message_center/arc_notification_manager_delegate_impl.cc
index 66430f0..33b4015 100644
--- a/ash/system/message_center/arc_notification_manager_delegate_impl.cc
+++ b/ash/system/message_center/arc_notification_manager_delegate_impl.cc
@@ -28,18 +28,6 @@
          login_status == LoginStatus::ARC_KIOSK_APP;
 }
 
-void ArcNotificationManagerDelegateImpl::GetAppIdByPackageName(
-    const std::string& package_name,
-    GetAppIdByPackageNameCallback callback) {
-  if (package_name.empty()) {
-    std::move(callback).Run(std::string());
-    return;
-  }
-
-  Shell::Get()->message_center_controller()->GetArcAppIdByPackageName(
-      package_name, std::move(callback));
-}
-
 void ArcNotificationManagerDelegateImpl::ShowMessageCenter() {
   Shell::Get()
       ->GetPrimaryRootWindowController()
diff --git a/ash/system/message_center/arc_notification_manager_delegate_impl.h b/ash/system/message_center/arc_notification_manager_delegate_impl.h
index e3e45de..1e109cb0 100644
--- a/ash/system/message_center/arc_notification_manager_delegate_impl.h
+++ b/ash/system/message_center/arc_notification_manager_delegate_impl.h
@@ -5,6 +5,8 @@
 #ifndef ASH_SYSTEM_MESSAGE_CENTER_ARC_NOTIFICATION_MANAGER_DELEGATE_IMPL_H_
 #define ASH_SYSTEM_MESSAGE_CENTER_ARC_NOTIFICATION_MANAGER_DELEGATE_IMPL_H_
 
+#include <string>
+
 #include "ash/system/message_center/arc/arc_notification_manager_delegate.h"
 #include "base/macros.h"
 
@@ -18,8 +20,6 @@
 
   // ArcNotificationManagerDelegate:
   bool IsPublicSessionOrKiosk() const override;
-  void GetAppIdByPackageName(const std::string& package_name,
-                             GetAppIdByPackageNameCallback callback) override;
   void ShowMessageCenter() override;
   void HideMessageCenter() override;
 
diff --git a/ash/system/message_center/message_center_controller.cc b/ash/system/message_center/message_center_controller.cc
index 4204911..45566b46 100644
--- a/ash/system/message_center/message_center_controller.cc
+++ b/ash/system/message_center/message_center_controller.cc
@@ -8,19 +8,17 @@
 
 #include "ash/public/cpp/ash_pref_names.h"
 #include "ash/public/cpp/ash_switches.h"
-#include "ash/public/cpp/vector_icons/vector_icons.h"
 #include "ash/session/session_controller_impl.h"
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "ash/system/message_center/arc_notification_manager_delegate_impl.h"
 #include "ash/system/message_center/ash_message_center_lock_screen_controller.h"
-#include "base/bind.h"
+#include "ash/system/message_center/fullscreen_notification_blocker.h"
+#include "ash/system/message_center/inactive_user_notification_blocker.h"
+#include "ash/system/message_center/session_state_notification_blocker.h"
 #include "base/command_line.h"
-#include "base/unguessable_token.h"
-#include "components/account_id/account_id.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_registry_simple.h"
-#include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/message_center/message_center.h"
 #include "ui/message_center/public/cpp/notification.h"
@@ -79,32 +77,6 @@
         std::make_unique<PopupNotificationBlocker>(MessageCenter::Get());
   }
 
-  message_center::RegisterVectorIcons({&vector_icons::kBusinessIcon,
-                                       &kNotificationAssistantIcon,
-                                       &kNotificationCaptivePortalIcon,
-                                       &kNotificationCellularAlertIcon,
-                                       &kNotificationDownloadIcon,
-                                       &kNotificationEndOfSupportIcon,
-                                       &kNotificationFamilyLinkIcon,
-                                       &kNotificationGoogleIcon,
-                                       &kNotificationImageIcon,
-                                       &kNotificationInstalledIcon,
-                                       &kNotificationLinuxIcon,
-                                       &kNotificationMessagesIcon,
-                                       &kNotificationMultiDeviceSetupIcon,
-                                       &kNotificationMobileDataIcon,
-                                       &kNotificationMobileDataOffIcon,
-                                       &kNotificationPlayPrismIcon,
-                                       &kNotificationPrintingDoneIcon,
-                                       &kNotificationPrintingIcon,
-                                       &kNotificationPrintingWarningIcon,
-                                       &kNotificationSettingsIcon,
-                                       &kNotificationStorageFullIcon,
-                                       &kNotificationSupervisedUserIcon,
-                                       &kNotificationVpnIcon,
-                                       &kNotificationWarningIcon,
-                                       &kNotificationWifiOffIcon});
-
   // Set the system notification source display name ("Chrome OS" or "Chromium
   // OS").
   message_center::MessageCenter::Get()->SetSystemNotificationAppName(
@@ -128,12 +100,6 @@
   binding_set_.AddBinding(this, std::move(request));
 }
 
-void MessageCenterController::SetClient(
-    mojom::AshMessageCenterClientAssociatedPtrInfo client) {
-  DCHECK(!client_.is_bound());
-  client_.Bind(std::move(client));
-}
-
 void MessageCenterController::SetArcNotificationsInstance(
     arc::mojom::NotificationsInstancePtr arc_notification_instance) {
   if (!arc_notification_manager_) {
@@ -152,11 +118,4 @@
   MessageCenter::Get()->SetQuietMode(enabled);
 }
 
-void MessageCenterController::GetArcAppIdByPackageName(
-    const std::string& package_name,
-    GetAppIdByPackageNameCallback callback) {
-  DCHECK(client_.is_bound());
-  client_->GetArcAppIdByPackageName(package_name, std::move(callback));
-}
-
 }  // namespace ash
diff --git a/ash/system/message_center/message_center_controller.h b/ash/system/message_center/message_center_controller.h
index 209df05..b9161d3 100644
--- a/ash/system/message_center/message_center_controller.h
+++ b/ash/system/message_center/message_center_controller.h
@@ -6,24 +6,26 @@
 #define ASH_SYSTEM_MESSAGE_CENTER_MESSAGE_CENTER_CONTROLLER_H_
 
 #include <memory>
-#include <string>
-#include <vector>
 
 #include "ash/ash_export.h"
 #include "ash/public/interfaces/ash_message_center_controller.mojom.h"
 #include "ash/system/message_center/arc/arc_notification_manager.h"
-#include "ash/system/message_center/fullscreen_notification_blocker.h"
-#include "ash/system/message_center/inactive_user_notification_blocker.h"
-#include "ash/system/message_center/session_state_notification_blocker.h"
 #include "base/macros.h"
 #include "components/arc/common/notifications.mojom.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 
 class PrefRegistrySimple;
 
+namespace message_center {
+class NotificationBlocker;
+}
+
 namespace ash {
 
+class FullscreenNotificationBlocker;
+class InactiveUserNotificationBlocker;
+class SessionStateNotificationBlocker;
+
 // This class manages the ash message center and allows clients (like Chrome) to
 // add and remove notifications.
 class ASH_EXPORT MessageCenterController
@@ -37,18 +39,10 @@
   void BindRequest(mojom::AshMessageCenterControllerRequest request);
 
   // mojom::AshMessageCenterController:
-  void SetClient(
-      mojom::AshMessageCenterClientAssociatedPtrInfo client) override;
   void SetArcNotificationsInstance(
       arc::mojom::NotificationsInstancePtr arc_notification_instance) override;
   void SetQuietMode(bool enabled) override;
 
-  // Handles get app id calls from ArcNotificationManager.
-  using GetAppIdByPackageNameCallback =
-      base::OnceCallback<void(const std::string& app_id)>;
-  void GetArcAppIdByPackageName(const std::string& package_name,
-                                GetAppIdByPackageNameCallback callback);
-
   InactiveUserNotificationBlocker*
   inactive_user_notification_blocker_for_testing() {
     return inactive_user_notification_blocker_.get();
@@ -65,8 +59,6 @@
 
   mojo::BindingSet<mojom::AshMessageCenterController> binding_set_;
 
-  mojom::AshMessageCenterClientAssociatedPtr client_;
-
   std::unique_ptr<ArcNotificationManager> arc_notification_manager_;
 
   DISALLOW_COPY_AND_ASSIGN(MessageCenterController);
diff --git a/ash/system/message_center/notifier_settings_view_unittest.cc b/ash/system/message_center/notifier_settings_view_unittest.cc
index 6e9fe3c..e0e9426 100644
--- a/ash/system/message_center/notifier_settings_view_unittest.cc
+++ b/ash/system/message_center/notifier_settings_view_unittest.cc
@@ -8,20 +8,13 @@
 
 #include <memory>
 
-#include "ash/public/cpp/notifier_metadata.h"
 #include "ash/public/cpp/notifier_settings_controller.h"
-#include "ash/public/interfaces/ash_message_center_controller.mojom.h"
 #include "ash/shell.h"
-#include "ash/system/message_center/message_center_controller.h"
 #include "ash/system/message_center/test_notifier_settings_controller.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/test/ash_test_helper.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/message_center/public/cpp/notifier_id.h"
-#include "ui/views/controls/scroll_view.h"
 
 namespace ash {
 
diff --git a/cc/test/fake_output_surface_client.cc b/cc/test/fake_output_surface_client.cc
index ac1276b..c18dbdb 100644
--- a/cc/test/fake_output_surface_client.cc
+++ b/cc/test/fake_output_surface_client.cc
@@ -6,7 +6,8 @@
 
 namespace cc {
 
-void FakeOutputSurfaceClient::DidReceiveSwapBuffersAck() {
+void FakeOutputSurfaceClient::DidReceiveSwapBuffersAck(
+    const gfx::SwapTimings&) {
   swap_count_++;
 }
 
diff --git a/cc/test/fake_output_surface_client.h b/cc/test/fake_output_surface_client.h
index 1f29e37..9d6c3a2 100644
--- a/cc/test/fake_output_surface_client.h
+++ b/cc/test/fake_output_surface_client.h
@@ -14,7 +14,7 @@
   FakeOutputSurfaceClient() = default;
 
   void SetNeedsRedrawRect(const gfx::Rect& damage_rect) override {}
-  void DidReceiveSwapBuffersAck() override;
+  void DidReceiveSwapBuffersAck(const gfx::SwapTimings& timings) override;
   void DidReceiveTextureInUseResponses(
       const gpu::TextureInUseResponses& responses) override {}
   void DidReceiveCALayerParams(
diff --git a/cc/test/layer_tree_pixel_resource_test.cc b/cc/test/layer_tree_pixel_resource_test.cc
index f3880c7..6604228 100644
--- a/cc/test/layer_tree_pixel_resource_test.cc
+++ b/cc/test/layer_tree_pixel_resource_test.cc
@@ -17,21 +17,6 @@
 
 namespace cc {
 
-namespace {
-
-LayerTreeTest::RendererType GetRendererType(PixelResourceTestCase test_case) {
-  switch (test_case) {
-    case SOFTWARE:
-      return LayerTreeTest::RENDERER_SOFTWARE;
-    case SKIA_GL:
-      return LayerTreeTest::RENDERER_SKIA_GL;
-    default:
-      return LayerTreeTest::RENDERER_GL;
-  }
-}
-
-}  // namespace
-
 LayerTreeHostPixelResourceTest::LayerTreeHostPixelResourceTest(
     PixelResourceTestCase test_case,
     Layer::LayerMaskType mask_type)
@@ -82,17 +67,17 @@
     }
   }
 
-  switch (test_case_) {
+  switch (raster_type()) {
     case SOFTWARE:
       EXPECT_FALSE(compositor_context_provider);
-      EXPECT_EQ(RENDERER_SOFTWARE, renderer_type_);
+      EXPECT_EQ(RENDERER_SOFTWARE, renderer_type());
 
       return std::make_unique<BitmapRasterBufferProvider>(
           host_impl->layer_tree_frame_sink());
     case GPU:
       EXPECT_TRUE(compositor_context_provider);
       EXPECT_TRUE(worker_context_provider);
-      EXPECT_EQ(RENDERER_GL, renderer_type_);
+      EXPECT_NE(RENDERER_SOFTWARE, renderer_type());
 
       return std::make_unique<GpuRasterBufferProvider>(
           compositor_context_provider, worker_context_provider, false, 0,
@@ -100,7 +85,7 @@
     case ZERO_COPY:
       EXPECT_TRUE(compositor_context_provider);
       EXPECT_TRUE(gpu_memory_buffer_manager);
-      EXPECT_EQ(RENDERER_GL, renderer_type_);
+      EXPECT_NE(RENDERER_SOFTWARE, renderer_type());
 
       return std::make_unique<ZeroCopyRasterBufferProvider>(
           gpu_memory_buffer_manager, compositor_context_provider,
@@ -108,41 +93,32 @@
     case ONE_COPY:
       EXPECT_TRUE(compositor_context_provider);
       EXPECT_TRUE(worker_context_provider);
-      EXPECT_EQ(RENDERER_GL, renderer_type_);
+      EXPECT_NE(RENDERER_SOFTWARE, renderer_type());
 
       return std::make_unique<OneCopyRasterBufferProvider>(
           task_runner, compositor_context_provider, worker_context_provider,
           gpu_memory_buffer_manager, max_bytes_per_copy_operation, false, false,
           max_staging_buffer_usage_in_bytes, sw_raster_format);
-    case SKIA_GL:
-      EXPECT_TRUE(compositor_context_provider);
-      EXPECT_TRUE(worker_context_provider);
-      EXPECT_EQ(RENDERER_SKIA_GL, renderer_type_);
-
-      return std::make_unique<GpuRasterBufferProvider>(
-          compositor_context_provider, worker_context_provider, false, 0,
-          gpu_raster_format, gfx::Size(), true, false);
   }
-  return {};
 }
 
 void LayerTreeHostPixelResourceTest::RunPixelResourceTest(
     scoped_refptr<Layer> content_root,
     base::FilePath file_name) {
-  RunPixelTest(GetRendererType(test_case_), content_root, file_name);
+  RunPixelTest(renderer_type(), content_root, file_name);
 }
 
 void LayerTreeHostPixelResourceTest::RunPixelResourceTest(
     scoped_refptr<Layer> content_root,
     const SkBitmap& expected_bitmap) {
-  RunPixelTest(GetRendererType(test_case_), content_root, expected_bitmap);
+  RunPixelTest(renderer_type(), content_root, expected_bitmap);
 }
 
 void LayerTreeHostPixelResourceTest::RunPixelResourceTestWithLayerList(
     scoped_refptr<Layer> root_layer,
     base::FilePath file_name,
     PropertyTrees* property_trees) {
-  RunPixelTestWithLayerList(GetRendererType(test_case_), root_layer, file_name,
+  RunPixelTestWithLayerList(renderer_type(), root_layer, file_name,
                             property_trees);
 }
 
diff --git a/cc/test/layer_tree_pixel_resource_test.h b/cc/test/layer_tree_pixel_resource_test.h
index 2bc3f32..39bea17 100644
--- a/cc/test/layer_tree_pixel_resource_test.h
+++ b/cc/test/layer_tree_pixel_resource_test.h
@@ -10,12 +10,16 @@
 
 namespace cc {
 
-enum PixelResourceTestCase {
+enum RasterType {
   SOFTWARE,
   GPU,
   ONE_COPY,
   ZERO_COPY,
-  SKIA_GL,
+};
+
+struct PixelResourceTestCase {
+  LayerTreeTest::RendererType renderer_type;
+  RasterType raster_type;
 };
 
 class LayerTreeHostPixelResourceTest : public LayerTreePixelTest {
@@ -24,6 +28,10 @@
                                           Layer::LayerMaskType mask_type);
   LayerTreeHostPixelResourceTest();
 
+  RendererType renderer_type() const { return test_case_.renderer_type; }
+
+  RasterType raster_type() const { return test_case_.raster_type; }
+
   std::unique_ptr<RasterBufferProvider> CreateRasterBufferProvider(
       LayerTreeHostImpl* host_impl) override;
 
@@ -44,16 +52,6 @@
   void InitializeFromTestCase(PixelResourceTestCase test_case);
 };
 
-// TODO(sgilhuly): Skia tests are only run with GPU raster. Parameterize further
-// so that they can be run with zero copy and one copy raster.
-#define INSTANTIATE_PIXEL_RESOURCE_TEST_SUITE_P(framework_name)           \
-  INSTANTIATE_TEST_SUITE_P(                                               \
-      PixelResourceTest, framework_name,                                  \
-      ::testing::Combine(                                                 \
-          ::testing::Values(SOFTWARE, GPU, ONE_COPY, ZERO_COPY, SKIA_GL), \
-          ::testing::Values(Layer::LayerMaskType::SINGLE_TEXTURE_MASK,    \
-                            Layer::LayerMaskType::MULTI_TEXTURE_MASK)))
-
 class ParameterizedPixelResourceTest
     : public LayerTreeHostPixelResourceTest,
       public ::testing::WithParamInterface<
diff --git a/cc/test/pixel_test_output_surface.cc b/cc/test/pixel_test_output_surface.cc
index 1c16562a..a6fed43 100644
--- a/cc/test/pixel_test_output_surface.cc
+++ b/cc/test/pixel_test_output_surface.cc
@@ -77,7 +77,7 @@
 }
 
 void PixelTestOutputSurface::SwapBuffersCallback() {
-  client_->DidReceiveSwapBuffersAck();
+  client_->DidReceiveSwapBuffersAck(gfx::SwapTimings());
   client_->DidReceivePresentationFeedback(
       gfx::PresentationFeedback(base::TimeTicks::Now(), base::TimeDelta(), 0));
 }
diff --git a/cc/trees/layer_tree_host_pixeltest_blending.cc b/cc/trees/layer_tree_host_pixeltest_blending.cc
index ef787ba..96fa7cb 100644
--- a/cc/trees/layer_tree_host_pixeltest_blending.cc
+++ b/cc/trees/layer_tree_host_pixeltest_blending.cc
@@ -213,10 +213,10 @@
     InitializeFromTestCase(resource_type());
 
     // Force shaders only applies to gl renderer.
-    if (renderer_type_ != RENDERER_GL && flags & kForceShaders)
+    if (renderer_type() != RENDERER_GL && flags & kForceShaders)
       return;
 
-    SCOPED_TRACE(TestTypeToString(renderer_type_));
+    SCOPED_TRACE(TestTypeToString(renderer_type()));
     SCOPED_TRACE(SkBlendMode_Name(current_blend_mode()));
 
     scoped_refptr<SolidColorLayer> root = CreateSolidColorLayer(
@@ -232,7 +232,7 @@
     this->force_antialiasing_ = (flags & kUseAntialiasing);
     this->force_blending_with_shaders_ = (flags & kForceShaders);
 
-    if ((flags & kUseAntialiasing) && (renderer_type_ == RENDERER_GL)) {
+    if ((flags & kUseAntialiasing) && (renderer_type() == RENDERER_GL)) {
       // Blending results might differ with one pixel.
       // Don't allow large errors here, only off by ones.
       // However, large error still has to be specified to satisfy
@@ -262,11 +262,16 @@
   SkColor misc_opaque_color_ = 0xffc86464;
 };
 
-INSTANTIATE_TEST_SUITE_P(
-    B,
-    LayerTreeHostBlendingPixelTest,
-    ::testing::Combine(::testing::Values(SOFTWARE, ZERO_COPY, SKIA_GL),
-                       ::testing::ValuesIn(kBlendModes)));
+std::vector<PixelResourceTestCase> const kTestCases = {
+    {LayerTreeTest::RENDERER_SOFTWARE, SOFTWARE},
+    {LayerTreeTest::RENDERER_GL, ZERO_COPY},
+    {LayerTreeTest::RENDERER_SKIA_GL, GPU},
+};
+
+INSTANTIATE_TEST_SUITE_P(B,
+                         LayerTreeHostBlendingPixelTest,
+                         ::testing::Combine(::testing::ValuesIn(kTestCases),
+                                            ::testing::ValuesIn(kBlendModes)));
 
 TEST_P(LayerTreeHostBlendingPixelTest, BlendingWithRoot) {
   const int kRootWidth = 2;
diff --git a/cc/trees/layer_tree_host_pixeltest_masks.cc b/cc/trees/layer_tree_host_pixeltest_masks.cc
index 61836ca2..1fe0b37 100644
--- a/cc/trees/layer_tree_host_pixeltest_masks.cc
+++ b/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -26,9 +26,34 @@
 namespace cc {
 namespace {
 
+auto CombineWithLayerMaskTypes(
+    const std::vector<PixelResourceTestCase>& test_cases) {
+  return ::testing::Combine(
+      ::testing::ValuesIn(test_cases),
+      ::testing::Values(Layer::LayerMaskType::SINGLE_TEXTURE_MASK,
+                        Layer::LayerMaskType::MULTI_TEXTURE_MASK));
+}
+
+std::vector<PixelResourceTestCase> const kTestCases = {
+    {LayerTreeTest::RENDERER_SOFTWARE, SOFTWARE},
+    {LayerTreeTest::RENDERER_GL, GPU},
+    {LayerTreeTest::RENDERER_GL, ONE_COPY},
+    {LayerTreeTest::RENDERER_GL, ZERO_COPY},
+    {LayerTreeTest::RENDERER_SKIA_GL, GPU},
+};
+
+std::vector<PixelResourceTestCase> const kTestCasesNonSkia = {
+    {LayerTreeTest::RENDERER_SOFTWARE, SOFTWARE},
+    {LayerTreeTest::RENDERER_GL, GPU},
+    {LayerTreeTest::RENDERER_GL, ONE_COPY},
+    {LayerTreeTest::RENDERER_GL, ZERO_COPY},
+};
+
 using LayerTreeHostMasksPixelTest = ParameterizedPixelResourceTest;
 
-INSTANTIATE_PIXEL_RESOURCE_TEST_SUITE_P(LayerTreeHostMasksPixelTest);
+INSTANTIATE_TEST_SUITE_P(PixelResourceTest,
+                         LayerTreeHostMasksPixelTest,
+                         CombineWithLayerMaskTypes(kTestCases));
 
 class MaskContentLayerClient : public ContentLayerClient {
  public:
@@ -99,7 +124,9 @@
   }
 };
 
-INSTANTIATE_PIXEL_RESOURCE_TEST_SUITE_P(LayerTreeHostLayerListPixelTest);
+INSTANTIATE_TEST_SUITE_P(PixelResourceTest,
+                         LayerTreeHostLayerListPixelTest,
+                         CombineWithLayerMaskTypes(kTestCases));
 
 TEST_P(LayerTreeHostLayerListPixelTest, MaskWithEffect) {
   PropertyTrees property_trees;
@@ -421,13 +448,9 @@
 using LayerTreeHostLayerListPixelTestNonSkia = LayerTreeHostLayerListPixelTest;
 
 // TODO(crbug.com/948128): Enable this test for Skia.
-INSTANTIATE_TEST_SUITE_P(
-    PixelResourceTest,
-    LayerTreeHostLayerListPixelTestNonSkia,
-    ::testing::Combine(
-        ::testing::Values(SOFTWARE, GPU, ONE_COPY, ZERO_COPY),
-        ::testing::Values(Layer::LayerMaskType::SINGLE_TEXTURE_MASK,
-                          Layer::LayerMaskType::MULTI_TEXTURE_MASK)));
+INSTANTIATE_TEST_SUITE_P(PixelResourceTest,
+                         LayerTreeHostLayerListPixelTestNonSkia,
+                         CombineWithLayerMaskTypes(kTestCasesNonSkia));
 
 TEST_P(LayerTreeHostLayerListPixelTestNonSkia, ScaledMaskWithEffect) {
   PropertyTrees property_trees;
@@ -819,8 +842,9 @@
 using LayerTreeHostMasksForBackdropFiltersPixelTest =
     ParameterizedPixelResourceTest;
 
-INSTANTIATE_PIXEL_RESOURCE_TEST_SUITE_P(
-    LayerTreeHostMasksForBackdropFiltersPixelTest);
+INSTANTIATE_TEST_SUITE_P(PixelResourceTest,
+                         LayerTreeHostMasksForBackdropFiltersPixelTest,
+                         CombineWithLayerMaskTypes(kTestCases));
 
 TEST_P(LayerTreeHostMasksForBackdropFiltersPixelTest,
        MaskOfLayerWithBackdropFilter) {
@@ -853,7 +877,7 @@
   CHECK_EQ(Layer::LayerMaskType::SINGLE_TEXTURE_MASK, mask->mask_type());
 
   base::FilePath image_name =
-      (test_case_ == GPU || test_case_ == SKIA_GL)
+      (raster_type() == GPU)
           ? base::FilePath(FILE_PATH_LITERAL("mask_of_backdrop_filter_gpu.png"))
           : base::FilePath(FILE_PATH_LITERAL("mask_of_backdrop_filter.png"));
   RunPixelResourceTest(background, image_name);
@@ -963,7 +987,7 @@
       average_error_allowed_in_bad_pixels = 3.5f;
       large_error_allowed = 15;
       small_error_allowed = 1;
-    } else if (test_case_ != SOFTWARE) {
+    } else if (raster_type() != SOFTWARE) {
       percentage_pixels_small_error = 0.9f;
       percentage_pixels_error = 6.5f;
       average_error_allowed_in_bad_pixels = 3.5f;
@@ -1072,11 +1096,12 @@
 
 // TODO(crbug.com/948128): Enable these tests for Skia.
 MaskTestConfig const kTestConfigs[] = {
-    MaskTestConfig{SOFTWARE, 0},
-    MaskTestConfig{ZERO_COPY, 0},
-    MaskTestConfig{ZERO_COPY, kUseAntialiasing},
-    MaskTestConfig{ZERO_COPY, kForceShaders},
-    MaskTestConfig{ZERO_COPY, kUseAntialiasing | kForceShaders},
+    MaskTestConfig{{LayerTreeTest::RENDERER_SOFTWARE, SOFTWARE}, 0},
+    MaskTestConfig{{LayerTreeTest::RENDERER_GL, ZERO_COPY}, 0},
+    MaskTestConfig{{LayerTreeTest::RENDERER_GL, ZERO_COPY}, kUseAntialiasing},
+    MaskTestConfig{{LayerTreeTest::RENDERER_GL, ZERO_COPY}, kForceShaders},
+    MaskTestConfig{{LayerTreeTest::RENDERER_GL, ZERO_COPY},
+                   kUseAntialiasing | kForceShaders},
 };
 
 INSTANTIATE_TEST_SUITE_P(All,
@@ -1219,7 +1244,7 @@
   mask_isolation->AddChild(mask_layer);
 
   base::FilePath image_name =
-      (test_case_ == SOFTWARE)
+      (raster_type() == SOFTWARE)
           ? base::FilePath(
                 FILE_PATH_LITERAL("mask_as_blending_rotated_circle.png"))
           : base::FilePath(
@@ -1266,7 +1291,7 @@
   mask_isolation->AddChild(mask_layer);
 
   base::FilePath image_name =
-      (test_case_ == SOFTWARE)
+      (raster_type() == SOFTWARE)
           ? base::FilePath(FILE_PATH_LITERAL(
                 "mask_as_blending_rotated_circle_underflow.png"))
           : base::FilePath(FILE_PATH_LITERAL(
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index a21ca76..4437ed7c 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -1959,6 +1959,7 @@
                              "data_deps",
                              "loadable_modules",
                              "min_sdk_version",
+                             "proguard_configs",
                              "secondary_abi_loadable_modules",
                              "shared_libraries",
                              "target_sdk_version",
@@ -1986,8 +1987,11 @@
       additional_apks += invoker.additional_apks
     }
     if (!is_java_debug) {
+      if (!defined(proguard_configs)) {
+        proguard_configs = []
+      }
       proguard_enabled = true
-      proguard_configs = [ "//chrome/android/java/apk_for_test.flags" ]
+      proguard_configs += [ "//chrome/android/java/apk_for_test.flags" ]
     }
   }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuHeaderCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuHeaderCoordinator.java
index 98299fc..0d04e40 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuHeaderCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuHeaderCoordinator.java
@@ -11,6 +11,7 @@
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.webkit.URLUtil;
 
 import org.chromium.base.Callback;
 import org.chromium.chrome.R;
@@ -49,8 +50,13 @@
     }
 
     private String getTitle(ContextMenuParams params) {
-        return TextUtils.isEmpty(params.getTitleText()) ? params.getLinkText()
-                                                        : params.getTitleText();
+        if (!TextUtils.isEmpty(params.getTitleText())) {
+            return params.getTitleText();
+        }
+        if (!TextUtils.isEmpty(params.getLinkText())) {
+            return params.getLinkText();
+        }
+        return URLUtil.guessFileName(params.getSrcUrl(), null, null);
     }
 
     private CharSequence getUrl(Activity activity, ContextMenuParams params) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadDirectoryProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadDirectoryProvider.java
index 7b99dd4be..a04dd67 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadDirectoryProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadDirectoryProvider.java
@@ -13,6 +13,7 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.ContextUtils;
+import org.chromium.base.Log;
 import org.chromium.base.PathUtils;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.task.AsyncTask;
@@ -35,6 +36,41 @@
  * options accordingly.
  */
 public class DownloadDirectoryProvider {
+    private static final String TAG = "DownloadDirectory";
+
+    /**
+     * Delegate class to query directories from Android API. Should be created on main thread
+     * and used on background thread in {@link AsyncTask}.
+     */
+    public interface Delegate {
+        /**
+         * Get the primary download directory in public external storage. The directory will be
+         * created if it doesn't exist. Should be called on background thread.
+         * @return The download directory. Can be an invalid directory if failed to create the
+         *         directory.
+         */
+        File getPrimaryDownloadDirectory();
+
+        /**
+         * Get external files directories for {@link Environment#DIRECTORY_DOWNLOADS}.
+         * @return A list of directories.
+         */
+        File[] getExternalFilesDirs();
+    }
+
+    private static class DownloadDirectoryProviderDelegate implements Delegate {
+        @Override
+        public File getPrimaryDownloadDirectory() {
+            return DownloadDirectoryProvider.getPrimaryDownloadDirectory();
+        }
+
+        @Override
+        public File[] getExternalFilesDirs() {
+            return ContextUtils.getApplicationContext().getExternalFilesDirs(
+                    Environment.DIRECTORY_DOWNLOADS);
+        }
+    }
+
     /**
      * Asynchronous task to retrieve all download directories on a background thread. Only one task
      * can exist at the same time.
@@ -43,12 +79,18 @@
      * {@link PathUtils#getAllPrivateDownloadsDirectories}.
      */
     private class AllDirectoriesTask extends AsyncTask<ArrayList<DirectoryOption>> {
+        private DownloadDirectoryProvider.Delegate mDelegate;
+
+        AllDirectoriesTask(DownloadDirectoryProvider.Delegate delegate) {
+            mDelegate = delegate;
+        }
+
         @Override
         protected ArrayList<DirectoryOption> doInBackground() {
             ArrayList<DirectoryOption> dirs = new ArrayList<>();
 
             // Retrieve default directory.
-            File defaultDirectory = DownloadUtils.getPrimaryDownloadDirectory();
+            File defaultDirectory = mDelegate.getPrimaryDownloadDirectory();
 
             // If no default directory, return an error option.
             if (defaultDirectory == null) {
@@ -67,8 +109,7 @@
             File[] files;
 
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
-                files = ContextUtils.getApplicationContext().getExternalFilesDirs(
-                        Environment.DIRECTORY_DOWNLOADS);
+                files = mDelegate.getExternalFilesDirs();
             } else {
                 files = new File[] {Environment.getExternalStorageDirectory()};
             }
@@ -192,11 +233,32 @@
         return null;
     }
 
+    /**
+     * Get the primary download directory in public external storage. The directory will be created
+     * if it doesn't exist. Should be called on background thread.
+     * @return The download directory. Can be an invalid directory if failed to create the
+     *         directory.
+     */
+    public static File getPrimaryDownloadDirectory() {
+        File downloadDir =
+                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
+
+        // Create the directory if needed.
+        if (!downloadDir.exists()) {
+            try {
+                downloadDir.mkdirs();
+            } catch (SecurityException e) {
+                Log.e(TAG, "Exception when creating download directory.", e);
+            }
+        }
+        return downloadDir;
+    }
+
     private void updateDirectories() {
         // If asynchronous task is pending, wait for its result.
         if (mAllDirectoriesTask != null) return;
 
-        mAllDirectoriesTask = new AllDirectoriesTask();
+        mAllDirectoriesTask = new AllDirectoriesTask(new DownloadDirectoryProviderDelegate());
         mAllDirectoriesTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
index 28cf147..92932ff 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
@@ -1217,27 +1217,6 @@
     }
 
     /**
-     * Get the primary download directory in public external storage. The directory will be created
-     * if it doesn't exist.
-     * @return The download directory. Can be an invalid directory if failed to create the
-     *         directory.
-     */
-    public static File getPrimaryDownloadDirectory() {
-        File downloadDir =
-                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
-
-        // Create the directory if needed.
-        if (!downloadDir.exists()) {
-            try {
-                downloadDir.mkdirs();
-            } catch (SecurityException e) {
-                Log.e(TAG, "Exception when creating download directory.", e);
-            }
-        }
-        return downloadDir;
-    }
-
-    /**
      * Parses an originating URL string and returns a valid Uri that can be inserted into
      * DownloadProvider. The returned Uri has to be null or non-empty http(s) scheme.
      * @param originalUrl String representation of the originating URL.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/storage/StorageSummaryProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/storage/StorageSummaryProvider.java
index a2ae56b..1af5ee2d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/storage/StorageSummaryProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/storage/StorageSummaryProvider.java
@@ -10,6 +10,7 @@
 import org.chromium.base.task.AsyncTask;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.download.DirectoryOption;
+import org.chromium.chrome.browser.download.DownloadDirectoryProvider;
 import org.chromium.chrome.browser.download.DownloadUtils;
 import org.chromium.chrome.browser.download.home.filter.OfflineItemFilterObserver;
 import org.chromium.chrome.browser.download.home.filter.OfflineItemFilterSource;
@@ -88,7 +89,7 @@
         new AsyncTask<DirectoryOption>() {
             @Override
             protected DirectoryOption doInBackground() {
-                File defaultDownloadDir = DownloadUtils.getPrimaryDownloadDirectory();
+                File defaultDownloadDir = DownloadDirectoryProvider.getPrimaryDownloadDirectory();
                 DirectoryOption directoryOption = new DirectoryOption("",
                         defaultDownloadDir.getAbsolutePath(), defaultDownloadDir.getUsableSpace(),
                         defaultDownloadDir.getTotalSpace(),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/SpaceDisplay.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/SpaceDisplay.java
index 07f0753..ede11fe0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/SpaceDisplay.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/SpaceDisplay.java
@@ -19,6 +19,7 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.task.AsyncTask;
+import org.chromium.chrome.browser.download.DownloadDirectoryProvider;
 import org.chromium.chrome.browser.download.DownloadUtils;
 import org.chromium.chrome.browser.widget.MaterialProgressBar;
 import org.chromium.chrome.download.R;
@@ -62,7 +63,7 @@
 
         @Override
         protected Long doInBackground() {
-            File downloadDirectory = DownloadUtils.getPrimaryDownloadDirectory();
+            File downloadDirectory = DownloadDirectoryProvider.getPrimaryDownloadDirectory();
 
             // Determine how much space is available on the storage device where downloads
             // reside.  If the downloads directory doesn't exist, it is likely that the user
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java
index e2e1924f..dc40ab3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessor.java
@@ -120,8 +120,10 @@
         // Note: At the time of writing this functionality, AiS was offering at most one answer to
         // any query. If this changes before the metric is expired, the code below may need either
         // revisiting or a secondary metric telling us how many answer suggestions have been shown.
-        RecordHistogram.recordEnumeratedHistogram("Omnibox.AnswerInSuggestShown",
-                suggestion.getAnswer().getType(), AnswerType.TOTAL_COUNT);
+        if (suggestion.hasAnswer()) {
+            RecordHistogram.recordEnumeratedHistogram("Omnibox.AnswerInSuggestShown",
+                    suggestion.getAnswer().getType(), AnswerType.TOTAL_COUNT);
+        }
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewViewBinder.java
index c24d68d..e3394eb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewViewBinder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewViewBinder.java
@@ -77,7 +77,8 @@
                     model.get(SuggestionViewProperties.TEXT_LINE_1_TEXT_DIRECTION));
         } else if (SuggestionViewProperties.TEXT_LINE_1_TEXT.equals(propertyKey)) {
             view.getTextLine1().setText(model.get(SuggestionViewProperties.TEXT_LINE_1_TEXT).text);
-        } else if (SuggestionViewProperties.TEXT_LINE_2_SIZING.equals(propertyKey)) {
+        } else if (SuggestionViewProperties.TEXT_LINE_2_SIZING.equals(propertyKey)
+                && model.get(SuggestionViewProperties.TEXT_LINE_2_SIZING) != null) {
             Pair<Integer, Integer> sizing = model.get(SuggestionViewProperties.TEXT_LINE_2_SIZING);
             view.getTextLine2().setTextSize(sizing.first, sizing.second);
         } else if (SuggestionViewProperties.TEXT_LINE_2_MAX_LINES.equals(propertyKey)) {
@@ -97,7 +98,11 @@
                             : R.dimen.omnibox_suggestion_start_offset_without_icon);
             updateSuggestionIcon(view, model);
         } else if (SuggestionViewProperties.TEXT_LINE_2_TEXT.equals(propertyKey)) {
-            Spannable line2Text = model.get(SuggestionViewProperties.TEXT_LINE_2_TEXT).text;
+            // TEXT_LINE_2_TEXT may be not be set if {@code view} is being rebound to a new model
+            // with only one line of text while the previous model had two lines of answer text.
+            Spannable line2Text = model.get(SuggestionViewProperties.TEXT_LINE_2_TEXT) == null
+                    ? null
+                    : model.get(SuggestionViewProperties.TEXT_LINE_2_TEXT).text;
             if (TextUtils.isEmpty(line2Text)) {
                 view.getTextLine2().setVisibility(View.INVISIBLE);
             } else {
diff --git a/chrome/android/touchless/java/res/color/touchless_default_text_color_list.xml b/chrome/android/touchless/java/res/color/touchless_default_text_color_list.xml
new file mode 100644
index 0000000..15732ab
--- /dev/null
+++ b/chrome/android/touchless/java/res/color/touchless_default_text_color_list.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2019 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:alpha="@dimen/default_disabled_alpha" android:color="@color/default_text_color"
+          android:state_enabled="false"/>
+    <item android:color="@color/modern_blue_800" android:state_focused="true"/>
+    <item android:color="@color/default_text_color"/>
+</selector>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/color/touchless_default_text_color_secondary_list.xml b/chrome/android/touchless/java/res/color/touchless_default_text_color_secondary_list.xml
new file mode 100644
index 0000000..44ec600
--- /dev/null
+++ b/chrome/android/touchless/java/res/color/touchless_default_text_color_secondary_list.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2019 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:alpha="@dimen/default_disabled_alpha"
+          android:color="@color/default_text_color_secondary" android:state_enabled="false"/>
+    <item android:color="@color/modern_blue_800" android:state_focused="true"/>
+    <item android:color="@color/default_text_color_secondary"/>
+</selector>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/color/touchless_icon_color.xml b/chrome/android/touchless/java/res/color/touchless_icon_color.xml
new file mode 100644
index 0000000..67b3937
--- /dev/null
+++ b/chrome/android/touchless/java/res/color/touchless_icon_color.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2019 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@color/modern_blue_800" android:state_focused="true"/>
+    <item android:color="@color/default_icon_color"/>
+</selector>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/drawable/ic_add_circle_outline_24dp.xml b/chrome/android/touchless/java/res/drawable/ic_add_circle_outline_24dp.xml
index 305a233..1cace257 100644
--- a/chrome/android/touchless/java/res/drawable/ic_add_circle_outline_24dp.xml
+++ b/chrome/android/touchless/java/res/drawable/ic_add_circle_outline_24dp.xml
@@ -9,6 +9,6 @@
         android:viewportHeight="24.0"
         tools:targetApi="21">
     <path
-        android:fillColor="@color/default_icon_color"
+        android:fillColor="@color/touchless_icon_color"
         android:pathData="M13,7h-2v4L7,11v2h4v4h2v-4h4v-2h-4L13,7zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
 </vector>
diff --git a/chrome/android/touchless/java/res/drawable/ic_help_outline_24dp.xml b/chrome/android/touchless/java/res/drawable/ic_help_outline_24dp.xml
index c2c667f..d21627d7 100644
--- a/chrome/android/touchless/java/res/drawable/ic_help_outline_24dp.xml
+++ b/chrome/android/touchless/java/res/drawable/ic_help_outline_24dp.xml
@@ -9,7 +9,7 @@
         android:viewportHeight="24.0"
         tools:ignore="NewApi">
     <path
-        android:fillColor="@color/default_icon_color"
+        android:fillColor="@color/touchless_icon_color"
         android:fillType="evenOdd"
         android:pathData="M11,18h2v-2h-2v2zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM12,6c-2.21,0 -4,1.79 -4,4h2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2c0,2 -3,1.75 -3,5h2c0,-2.25 3,-2.5 3,-5 0,-2.21 -1.79,-4 -4,-4z"/>
 </vector>
diff --git a/chrome/android/touchless/java/res/drawable/ic_note_add.xml b/chrome/android/touchless/java/res/drawable/ic_note_add.xml
index 7cdfba3..55149c24 100644
--- a/chrome/android/touchless/java/res/drawable/ic_note_add.xml
+++ b/chrome/android/touchless/java/res/drawable/ic_note_add.xml
@@ -9,6 +9,6 @@
         android:viewportHeight="24.0"
         tools:targetApi="21">
   <path
-      android:fillColor="@color/default_icon_color"
+      android:fillColor="@color/touchless_icon_color"
       android:pathData="M13,10h-2v3L8,13v2h3v3h2v-3h3v-2h-3zM14,2L6,2c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.89,2 1.99,2L18,22c1.1,0 2,-0.9 2,-2L20,8l-6,-6zM18,20L6,20L6,4h7v5h5v11z"/>
 </vector>
diff --git a/chrome/android/touchless/java/res/drawable/ic_remove_circle_outline_24dp.xml b/chrome/android/touchless/java/res/drawable/ic_remove_circle_outline_24dp.xml
index 2ce2e107..e3e5741 100644
--- a/chrome/android/touchless/java/res/drawable/ic_remove_circle_outline_24dp.xml
+++ b/chrome/android/touchless/java/res/drawable/ic_remove_circle_outline_24dp.xml
@@ -9,7 +9,7 @@
         android:viewportHeight="24.0"
         tools:ignore="NewApi">
     <path
-        android:fillColor="@color/default_icon_color"
+        android:fillColor="@color/touchless_icon_color"
         android:fillType="evenOdd"
         android:pathData="M7,11v2h10v-2L7,11zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
 </vector>
diff --git a/chrome/android/touchless/java/res/layout/dialog_list_item.xml b/chrome/android/touchless/java/res/layout/dialog_list_item.xml
index aa2268f..a18102f 100644
--- a/chrome/android/touchless/java/res/layout/dialog_list_item.xml
+++ b/chrome/android/touchless/java/res/layout/dialog_list_item.xml
@@ -20,14 +20,15 @@
         android:layout_height="18dp"
         android:layout_gravity="center_vertical"
         android:layout_marginEnd="10dp"
+        android:duplicateParentState="true"
         android:scaleType="centerInside"
         android:visibility="gone"/>
 
     <TextView
         android:id="@+id/dialog_item_text"
+        style="@style/TextAppearance.BlackBodyDefault.Touchless"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:gravity="center_vertical"
-        android:textAppearance="@style/TextAppearance.BlackBody"/>
+        android:gravity="center_vertical"/>
 
 </LinearLayout>
\ No newline at end of file
diff --git a/chrome/android/touchless/java/res/layout/open_last_tab_button.xml b/chrome/android/touchless/java/res/layout/open_last_tab_button.xml
index 3527ae3..978f5c5 100644
--- a/chrome/android/touchless/java/res/layout/open_last_tab_button.xml
+++ b/chrome/android/touchless/java/res/layout/open_last_tab_button.xml
@@ -18,7 +18,7 @@
         android:paddingHorizontal="@dimen/open_last_tab_button_padding_horizontal"
         android:paddingVertical="@dimen/open_last_tab_button_padding_vertical"
         android:background="@drawable/hairline_border_card_background"
-        android:theme="@style/Theme.AppCompat.Light">
+        style="@style/Theme.AppCompat.Light">
 
         <org.chromium.ui.widget.ChromeImageView
             android:id="@+id/favicon"
@@ -29,20 +29,20 @@
 
         <TextView
             android:id="@+id/title"
+            style="@style/TextAppearance.BlackBodyDefault.Touchless"
             android:layout_width="0dp"
             android:layout_height="wrap_content"
             android:layout_weight="1"
             android:layout_marginStart="@dimen/open_last_tab_title_text_margin_left"
-            android:textAppearance="@style/TextAppearance.BlackTitle2"
             android:ellipsize="end"
             android:maxLines="1"/>
 
         <TextView
             android:id="@+id/timestamp"
+            style="@style/TextAppearance.BlackCaption.Touchless"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginStart="@dimen/open_last_tab_timestamp_text_margin_left"
-            android:textAppearance="@style/TextAppearance.BlackCaption"
             android:ellipsize="end"
             android:maxLines="1" />
 
diff --git a/chrome/android/touchless/java/res/values-v17/styles.xml b/chrome/android/touchless/java/res/values-v17/styles.xml
index 0ebe1e4..0a7a125 100644
--- a/chrome/android/touchless/java/res/values-v17/styles.xml
+++ b/chrome/android/touchless/java/res/values-v17/styles.xml
@@ -4,6 +4,16 @@
      found in the LICENSE file. -->
 
 <resources xmlns:tools="http://schemas.android.com/tools">
+    <style name="TextAppearance.BlackBodyDefault.Touchless">
+        <item name="android:textColor">@color/touchless_default_text_color_list</item>
+        <item name="android:duplicateParentState">true</item>
+    </style>
+
+    <style name="TextAppearance.BlackCaption.Touchless">
+        <item name="android:textColor">@color/touchless_default_text_color_secondary_list</item>
+        <item name="android:duplicateParentState">true</item>
+    </style>
+
     <style name="TextAppearance.NoTouchProgressBar">
         <item name="android:textSize">14sp</item>
         <item name="android:textColor">@color/notouch_progress_bar_text</item>
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogPresenter.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogPresenter.java
index 4c015361..02fbd1a 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogPresenter.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogPresenter.java
@@ -5,8 +5,6 @@
 package org.chromium.chrome.browser.touchless.dialog;
 
 import android.app.Dialog;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
 import android.graphics.drawable.Drawable;
 import android.support.v4.view.ViewCompat;
 import android.util.Pair;
@@ -162,7 +160,6 @@
             PropertyModel[] models = model.get(TouchlessDialogProperties.LIST_MODELS);
             ArrayList<Pair<Integer, PropertyModel>> modelPairs = new ArrayList<>();
             for (int i = 0; i < models.length; i++) {
-                models[i].set(DialogListItemProperties.FOCUS_LISTENER_SET, true);
                 modelPairs.add(Pair.create(0, models[i]));
             }
             optionsAdapter.updateModels(modelPairs);
@@ -207,23 +204,6 @@
                 ((ClickThrottlingListener) listener)
                         .setIsMultiClickable(model.get(DialogListItemProperties.MULTI_CLICKABLE));
             }
-        } else if (DialogListItemProperties.FOCUS_LISTENER_SET == propertyKey) {
-            if (model.get(DialogListItemProperties.FOCUS_LISTENER_SET)) {
-                view.setOnFocusChangeListener((v, hasFocus) -> {
-                    textView.setTextColor(hasFocus
-                            ? view.getResources().getColor(R.color.modern_blue_800)
-                            : view.getResources().getColor(android.R.color.black));
-                    if (imageView.getDrawable() != null) {
-                        if (hasFocus) {
-                            imageView.getDrawable().setColorFilter(new PorterDuffColorFilter(
-                                    view.getResources().getColor(R.color.modern_blue_800),
-                                    PorterDuff.Mode.SRC_ATOP));
-                        } else {
-                            imageView.getDrawable().clearColorFilter();
-                        }
-                    }
-                });
-            }
         }
     }
 
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogProperties.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogProperties.java
index 77be679..86fba6e 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogProperties.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/dialog/TouchlessDialogProperties.java
@@ -69,12 +69,7 @@
         public static final WritableObjectPropertyKey<View.OnClickListener> CLICK_LISTENER =
                 new WritableObjectPropertyKey<>();
 
-        /** Whether this item has a focus change listener attached to its view. */
-        public static final WritableBooleanPropertyKey FOCUS_LISTENER_SET =
-                new WritableBooleanPropertyKey();
-
-        public static final PropertyKey[] ALL_KEYS = {
-                ICON, TEXT, MULTI_CLICKABLE, CLICK_LISTENER, FOCUS_LISTENER_SET};
+        public static final PropertyKey[] ALL_KEYS = {ICON, TEXT, MULTI_CLICKABLE, CLICK_LISTENER};
     }
 
     /**
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index d10ecaa..9e01f123 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -7807,6 +7807,22 @@
         <message name="IDS_EDIT_CHECK_GRAMMAR_MAC" desc="The Mac menu item for check grammar with spelling in the edit menu.">
           Check Grammar With Spelling
         </message>
+        <!-- Edit::Substitutions submenu -->
+        <message name="IDS_EDIT_SUBSTITUTIONS_MAC" desc="The Mac menu item for the substitutions submenu in the edit menu.">
+          Substitutions
+        </message>
+        <message name="IDS_EDIT_SHOW_SUBSTITUTIONS_MAC" desc="The Mac menu item for showing the substitutions panel in the edit menu.">
+          Show Substitutions
+        </message>
+        <message name="IDS_EDIT_SMART_QUOTES_MAC" desc="The Mac menu item for toggling smart quotes in the edit menu.">
+          Smart Quotes
+        </message>
+        <message name="IDS_EDIT_SMART_DASHES_MAC" desc="The Mac menu item for toggling smart dashes in the edit menu.">
+          Smart Dashes
+        </message>
+        <message name="IDS_EDIT_TEXT_REPLACEMENT_MAC" desc="The Mac menu item for toggling text replacement in the edit menu.">
+          Text Replacement
+        </message>
         <!-- View menu -->
         <message name="IDS_BOOKMARK_BAR_ALWAYS_SHOW_MAC" desc="The Mac menu item for having bookmark bar always visible in the view menu.">
           Always Show Bookmarks Bar
diff --git a/chrome/app/helper-plugin-entitlements.plist b/chrome/app/helper-plugin-entitlements.plist
new file mode 100644
index 0000000..6883e4a
--- /dev/null
+++ b/chrome/app/helper-plugin-entitlements.plist
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
+	<true/>
+	<key>com.apple.security.cs.disable-library-validation</key>
+	<true/>
+</dict>
+</plist>
diff --git a/chrome/app/helper-renderer-entitlements.plist b/chrome/app/helper-renderer-entitlements.plist
new file mode 100644
index 0000000..d35e43a
--- /dev/null
+++ b/chrome/app/helper-renderer-entitlements.plist
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>com.apple.security.cs.allow-jit</key>
+	<true/>
+</dict>
+</plist>
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index c480927..dd17b9c 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -1967,6 +1967,15 @@
     <message name="IDS_SETTINGS_SETTINGS_NETWORK_ALLOW_DATA_ROAMING" desc="Settings > Internet > Network details: Toggle label to allow mobile data roaming.">
       Allow mobile data roaming
     </message>
+    <message name="IDS_SETTINGS_SETTINGS_NETWORK_ALLOW_DATA_ROAMING_ENABLED_HOME" desc="Settings > Internet > Network details: Toggle sublabel when roaming is allowed and it's connected to the home network.">
+      On, not roaming
+    </message>
+    <message name="IDS_SETTINGS_SETTINGS_NETWORK_ALLOW_DATA_ROAMING_ENABLED_ROAMING" desc="Settings > Internet > Network details: Toggle sublabel when roaming is allowed and it's connected to a roaming network">
+      On, roaming
+    </message>
+    <message name="IDS_SETTINGS_SETTINGS_NETWORK_ALLOW_DATA_ROAMING_DISABLED" desc="Settings > Internet > Network details: Toggle sublabel when roaming is not allowed.">
+      Roaming off
+    </message>
     <message name="IDS_SETTINGS_INTERNET_NETWORK_CHOOSE_MOBILE" desc="Settings > Internet > Network details: Label for control to choose a mobile data network.">
       Mobile data network
     </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 9d1b2531..6c6e4ec 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1300,6 +1300,8 @@
     "previews/previews_lite_page_navigation_throttle.cc",
     "previews/previews_lite_page_navigation_throttle.h",
     "previews/previews_lite_page_navigation_throttle_manager.h",
+    "previews/previews_lite_page_predictor.cc",
+    "previews/previews_lite_page_predictor.h",
     "previews/previews_lite_page_redirect_url_loader.cc",
     "previews/previews_lite_page_redirect_url_loader.h",
     "previews/previews_lite_page_serving_url_loader.cc",
@@ -2836,6 +2838,7 @@
       "apps/intent_helper/page_transition_util.h",
       "background/background_contents.cc",
       "background/background_contents.h",
+      "background/background_contents_service_observer.h",
       "badging/badge_manager.cc",
       "badging/badge_manager.h",
       "badging/badge_manager_delegate.h",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 7c07f583..bb6e5d5 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1356,6 +1356,12 @@
      flag_descriptions::kAshEnableUnifiedDesktopName,
      flag_descriptions::kAshEnableUnifiedDesktopDescription, kOsCrOS,
      SINGLE_VALUE_TYPE(switches::kEnableUnifiedDesktop)},
+    {"bluetooth-aggressive-appearance-filter",
+     flag_descriptions::kBluetoothAggressiveAppearanceFilterName,
+     flag_descriptions::kBluetoothAggressiveAppearanceFilterDescription,
+     kOsCrOS,
+     FEATURE_VALUE_TYPE(
+         chromeos::features::kBluetoothAggressiveAppearanceFilter)},
     {"cryptauth-v2-enrollment", flag_descriptions::kCryptAuthV2EnrollmentName,
      flag_descriptions::kCryptAuthV2EnrollmentDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(chromeos::features::kCryptAuthV2Enrollment)},
@@ -1405,9 +1411,18 @@
      flag_descriptions::kUnfilteredBluetoothDevicesName,
      flag_descriptions::kUnfilteredBluetoothDevicesDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(device::kUnfilteredBluetoothDevices)},
+    {"shelf-dense-clamshell", flag_descriptions::kShelfDenseClamshellName,
+     flag_descriptions::kShelfDenseClamshellDescription, kOsCrOS,
+     SINGLE_VALUE_TYPE(chromeos::switches::kShelfDenseClamshell)},
     {"shelf-hover-previews", flag_descriptions::kShelfHoverPreviewsName,
      flag_descriptions::kShelfHoverPreviewsDescription, kOsCrOS,
      SINGLE_VALUE_TYPE(chromeos::switches::kShelfHoverPreviews)},
+    {"shelf-new-ui", flag_descriptions::kShelfNewUiName,
+     flag_descriptions::kShelfNewUiDescription, kOsCrOS,
+     SINGLE_VALUE_TYPE(chromeos::switches::kShelfNewUi)},
+    {"shelf-scrollable", flag_descriptions::kShelfScrollableName,
+     flag_descriptions::kShelfScrollableDescription, kOsCrOS,
+     SINGLE_VALUE_TYPE(chromeos::switches::kShelfScrollable)},
     {"show-bluetooth-device-battery",
      flag_descriptions::kShowBluetoothDeviceBatteryName,
      flag_descriptions::kShowBluetoothDeviceBatteryDescription, kOsCrOS,
diff --git a/chrome/browser/accessibility/accessibility_extension_api.cc b/chrome/browser/accessibility/accessibility_extension_api.cc
index 081b24f..9973a6b2 100644
--- a/chrome/browser/accessibility/accessibility_extension_api.cc
+++ b/chrome/browser/accessibility/accessibility_extension_api.cc
@@ -36,9 +36,9 @@
 #include "ui/events/keycodes/keyboard_codes.h"
 
 #if defined(OS_CHROMEOS)
+#include "ash/public/cpp/accessibility_focus_ring_info.h"
 #include "ash/public/cpp/event_rewriter_controller.h"
 #include "ash/public/cpp/window_tree_host_lookup.h"
-#include "ash/public/interfaces/accessibility_focus_ring_controller.mojom.h"
 #include "ash/public/interfaces/constants.mojom.h"
 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
 #include "chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.h"
@@ -95,42 +95,41 @@
 
   for (const accessibility_private::FocusRingInfo& focus_ring_info :
        params->focus_rings) {
-    ash::mojom::FocusRingPtr focus_ring_ptr = ash::mojom::FocusRing::New();
-    focus_ring_ptr->behavior =
-        ash::mojom::FocusRingBehavior::PERSIST_FOCUS_RING;
+    auto focus_ring = std::make_unique<ash::AccessibilityFocusRingInfo>();
+    focus_ring->behavior = ash::FocusRingBehavior::PERSIST;
 
     // Convert the given rects into gfx::Rect objects.
     for (const accessibility_private::ScreenRect& rect :
          focus_ring_info.rects) {
-      focus_ring_ptr->rects_in_screen.push_back(
+      focus_ring->rects_in_screen.push_back(
           gfx::Rect(rect.left, rect.top, rect.width, rect.height));
     }
 
     const std::string id = accessibility_manager->GetFocusRingId(
         extension_id(), focus_ring_info.id ? *(focus_ring_info.id) : "");
 
-    if (!extensions::image_util::ParseHexColorString(
-            focus_ring_info.color, &(focus_ring_ptr->color))) {
+    if (!extensions::image_util::ParseHexColorString(focus_ring_info.color,
+                                                     &(focus_ring->color))) {
       return RespondNow(Error("Could not parse hex color"));
     }
 
     if (focus_ring_info.secondary_color) {
       if (!extensions::image_util::ParseHexColorString(
               *(focus_ring_info.secondary_color),
-              &(focus_ring_ptr->secondary_color))) {
+              &(focus_ring->secondary_color))) {
         return RespondNow(Error("Could not parse secondary hex color"));
       }
     }
 
     switch (focus_ring_info.type) {
       case accessibility_private::FOCUS_TYPE_SOLID:
-        focus_ring_ptr->type = ash::mojom::FocusRingType::SOLID;
+        focus_ring->type = ash::FocusRingType::SOLID;
         break;
       case accessibility_private::FOCUS_TYPE_DASHED:
-        focus_ring_ptr->type = ash::mojom::FocusRingType::DASHED;
+        focus_ring->type = ash::FocusRingType::DASHED;
         break;
       case accessibility_private::FOCUS_TYPE_GLOW:
-        focus_ring_ptr->type = ash::mojom::FocusRingType::GLOW;
+        focus_ring->type = ash::FocusRingType::GLOW;
         break;
       default:
         NOTREACHED();
@@ -140,13 +139,13 @@
     // are anchored within the focused object.
     // NOTE: The final anchor point will be determined by the first rect of the
     // final focus ring.
-    if (!focus_ring_ptr->rects_in_screen.empty()) {
+    if (!focus_ring->rects_in_screen.empty()) {
       accessibility_manager->SetTouchAccessibilityAnchorPoint(
-          focus_ring_ptr->rects_in_screen[0].CenterPoint());
+          focus_ring->rects_in_screen[0].CenterPoint());
     }
 
     // Set the focus ring.
-    accessibility_manager->SetFocusRing(id, std::move(focus_ring_ptr));
+    accessibility_manager->SetFocusRing(id, std::move(focus_ring));
   }
 
   return RespondNow(NoArguments());
diff --git a/chrome/browser/android/favicon_helper.cc b/chrome/browser/android/favicon_helper.cc
index b253ac0b..db70943 100644
--- a/chrome/browser/android/favicon_helper.cc
+++ b/chrome/browser/android/favicon_helper.cc
@@ -80,18 +80,6 @@
       env, j_availability_callback, newly_available);
 }
 
-scoped_refptr<base::RefCountedMemory> GetSyncedFaviconForPageURL(
-    Profile* profile,
-    const GURL& page_url) {
-  sync_sessions::SessionSyncService* session_sync_service =
-      SessionSyncServiceFactory::GetInstance()->GetForProfile(profile);
-  DCHECK(session_sync_service);
-  sync_sessions::OpenTabsUIDelegate* open_tabs =
-      session_sync_service->GetOpenTabsUIDelegate();
-  return open_tabs ? open_tabs->GetSyncedFaviconForPageURL(page_url.spec())
-                   : nullptr;
-}
-
 // Check if user settings allow querying a Google server using history
 // information.
 bool CanSendHistoryDataToServer(Profile* profile) {
@@ -188,7 +176,6 @@
       favicon::FaviconRequestPlatform::kMobile,
       /*icon_url_for_uma=*/
       open_tabs ? open_tabs->GetIconUrlForPageUrl(page_url) : GURL(),
-      base::BindOnce(&GetSyncedFaviconForPageURL, profile),
       CanSendHistoryDataToServer(profile), cancelable_task_tracker_.get());
   return true;
 }
diff --git a/chrome/browser/android/tab_web_contents_delegate_android.cc b/chrome/browser/android/tab_web_contents_delegate_android.cc
index f9bc6833..a2b977c1 100644
--- a/chrome/browser/android/tab_web_contents_delegate_android.cc
+++ b/chrome/browser/android/tab_web_contents_delegate_android.cc
@@ -204,7 +204,7 @@
 }
 
 blink::WebDisplayMode TabWebContentsDelegateAndroid::GetDisplayMode(
-    const WebContents* web_contents) const {
+    const WebContents* web_contents) {
   JNIEnv* env = base::android::AttachCurrentThread();
 
   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
diff --git a/chrome/browser/android/tab_web_contents_delegate_android.h b/chrome/browser/android/tab_web_contents_delegate_android.h
index 332dfed..eeed982 100644
--- a/chrome/browser/android/tab_web_contents_delegate_android.h
+++ b/chrome/browser/android/tab_web_contents_delegate_android.h
@@ -45,7 +45,7 @@
   void CloseContents(content::WebContents* web_contents) override;
   bool ShouldFocusLocationBarByDefault(content::WebContents* source) override;
   blink::WebDisplayMode GetDisplayMode(
-      const content::WebContents* web_contents) const override;
+      const content::WebContents* web_contents) override;
   void FindReply(content::WebContents* web_contents,
                  int request_id,
                  int number_of_matches,
diff --git a/chrome/browser/android/tab_web_contents_delegate_android_unittest.cc b/chrome/browser/android/tab_web_contents_delegate_android_unittest.cc
index 3b10d06..454fb44 100644
--- a/chrome/browser/android/tab_web_contents_delegate_android_unittest.cc
+++ b/chrome/browser/android/tab_web_contents_delegate_android_unittest.cc
@@ -20,7 +20,7 @@
   }
 
   blink::WebDisplayMode GetDisplayMode(
-      const content::WebContents* web_contents) const override {
+      const content::WebContents* web_contents) override {
     return display_mode_;
   }
 
diff --git a/chrome/browser/background/background_application_list_model.cc b/chrome/browser/background/background_application_list_model.cc
index ef747c3..f1750d3 100644
--- a/chrome/browser/background/background_application_list_model.cc
+++ b/chrome/browser/background/background_application_list_model.cc
@@ -142,21 +142,17 @@
       base::Bind(&Application::OnImageLoaded, AsWeakPtr()));
 }
 
-BackgroundApplicationListModel::~BackgroundApplicationListModel() {
-}
+BackgroundApplicationListModel::~BackgroundApplicationListModel() = default;
 
 BackgroundApplicationListModel::BackgroundApplicationListModel(Profile* profile)
-    : profile_(profile),
-      ready_(false),
-      extension_registry_observer_(this),
-      weak_ptr_factory_(this) {
+    : profile_(profile) {
   DCHECK(profile_);
+  background_contents_service_observer_.Add(
+      BackgroundContentsServiceFactory::GetForProfile(profile));
+
   registrar_.Add(this,
                  extensions::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED,
                  content::Source<Profile>(profile));
-  registrar_.Add(this,
-                 chrome::NOTIFICATION_BACKGROUND_CONTENTS_SERVICE_CHANGED,
-                 content::Source<Profile>(profile));
   extensions::ExtensionSystem::Get(profile_)->ready().Post(
       FROM_HERE,
       base::BindOnce(&BackgroundApplicationListModel::OnExtensionSystemReady,
@@ -280,25 +276,11 @@
     int type,
     const content::NotificationSource& source,
     const content::NotificationDetails& details) {
-  extensions::ExtensionService* service =
-      extensions::ExtensionSystem::Get(profile_)->extension_service();
-  if (!service || !service->is_ready())
-    return;
-
-  switch (type) {
-    case extensions::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED:
-      OnExtensionPermissionsUpdated(
-          content::Details<UpdatedExtensionPermissionsInfo>(details)->extension,
-          content::Details<UpdatedExtensionPermissionsInfo>(details)->reason,
-          content::Details<UpdatedExtensionPermissionsInfo>(details)->
-              permissions);
-      break;
-    case chrome::NOTIFICATION_BACKGROUND_CONTENTS_SERVICE_CHANGED:
-      Update();
-      break;
-    default:
-      NOTREACHED() << "Received unexpected notification";
-  }
+  DCHECK_EQ(type, extensions::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED);
+  OnExtensionPermissionsUpdated(
+      content::Details<UpdatedExtensionPermissionsInfo>(details)->extension,
+      content::Details<UpdatedExtensionPermissionsInfo>(details)->reason,
+      content::Details<UpdatedExtensionPermissionsInfo>(details)->permissions);
 }
 
 void BackgroundApplicationListModel::SendApplicationDataChangedNotifications() {
@@ -327,6 +309,7 @@
 }
 
 void BackgroundApplicationListModel::OnExtensionSystemReady() {
+  ready_ = true;
   // All initial extensions will be loaded when extension system ready. So we
   // can get everything here.
   Update();
@@ -338,7 +321,6 @@
   // for the extension system, which isn't a guarantee. Thus, register here and
   // associate all initial extensions.
   extension_registry_observer_.Add(ExtensionRegistry::Get(profile_));
-  ready_ = true;
 }
 
 void BackgroundApplicationListModel::OnShutdown(ExtensionRegistry* registry) {
@@ -346,6 +328,14 @@
   extension_registry_observer_.Remove(registry);
 }
 
+void BackgroundApplicationListModel::OnBackgroundContentsServiceChanged() {
+  Update();
+}
+
+void BackgroundApplicationListModel::OnBackgroundContentsServiceDestroying() {
+  background_contents_service_observer_.RemoveAll();
+}
+
 void BackgroundApplicationListModel::OnExtensionPermissionsUpdated(
     const Extension* extension,
     UpdatedExtensionPermissionsInfo::Reason reason,
@@ -377,6 +367,9 @@
 // differs from the old list, it generates OnApplicationListChanged events for
 // each observer.
 void BackgroundApplicationListModel::Update() {
+  if (!ready_)
+    return;
+
   extensions::ExtensionService* service =
       extensions::ExtensionSystem::Get(profile_)->extension_service();
 
diff --git a/chrome/browser/background/background_application_list_model.h b/chrome/browser/background/background_application_list_model.h
index 6812848..f4026ac 100644
--- a/chrome/browser/background/background_application_list_model.h
+++ b/chrome/browser/background/background_application_list_model.h
@@ -15,6 +15,8 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/scoped_observer.h"
+#include "chrome/browser/background/background_contents_service.h"
+#include "chrome/browser/background/background_contents_service_observer.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "extensions/browser/extension_registry_observer.h"
@@ -35,7 +37,8 @@
 // BackgroundContents).
 class BackgroundApplicationListModel
     : public content::NotificationObserver,
-      public extensions::ExtensionRegistryObserver {
+      public extensions::ExtensionRegistryObserver,
+      public BackgroundContentsServiceObserver {
  public:
   // Observer is informed of changes to the model.  Users of the
   // BackgroundApplicationListModel should anticipate that associated data,
@@ -120,12 +123,12 @@
   // Returns the Application associated with |extension| or NULL.
   Application* FindApplication(const extensions::Extension* extension);
 
-  // content::NotificationObserver implementation.
+  // content::NotificationObserver:
   void Observe(int type,
                const content::NotificationSource& source,
                const content::NotificationDetails& details) override;
 
-  // extensions::ExtensionRegistryObserver implementation.
+  // extensions::ExtensionRegistryObserver:
   void OnExtensionLoaded(content::BrowserContext* browser_context,
                          const extensions::Extension* extension) override;
   void OnExtensionUnloaded(content::BrowserContext* browser_context,
@@ -133,6 +136,10 @@
                            extensions::UnloadedExtensionReason reason) override;
   void OnShutdown(extensions::ExtensionRegistry* registry) override;
 
+  // BackgroundContentsServiceObserver:
+  void OnBackgroundContentsServiceChanged() override;
+  void OnBackgroundContentsServiceDestroying() override;
+
   // Intended to be called when extension system is ready.
   void OnExtensionSystemReady();
 
@@ -160,14 +167,17 @@
   base::ObserverList<Observer, true>::Unchecked observers_;
   Profile* const profile_;
   content::NotificationRegistrar registrar_;
-  bool ready_;
+  bool ready_{false};
 
   // Listens to extension load, unload notifications.
   ScopedObserver<extensions::ExtensionRegistry,
                  extensions::ExtensionRegistryObserver>
-      extension_registry_observer_;
+      extension_registry_observer_{this};
 
-  base::WeakPtrFactory<BackgroundApplicationListModel> weak_ptr_factory_;
+  ScopedObserver<BackgroundContentsService, BackgroundContentsServiceObserver>
+      background_contents_service_observer_{this};
+
+  base::WeakPtrFactory<BackgroundApplicationListModel> weak_ptr_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(BackgroundApplicationListModel);
 };
diff --git a/chrome/browser/background/background_application_list_model_unittest.cc b/chrome/browser/background/background_application_list_model_unittest.cc
index bce56a3..0e8861e 100644
--- a/chrome/browser/background/background_application_list_model_unittest.cc
+++ b/chrome/browser/background/background_application_list_model_unittest.cc
@@ -304,24 +304,24 @@
 
   scoped_refptr<Extension> bgapp =
       CreateExtension("background_application", true);
-  ASSERT_TRUE(
+  EXPECT_TRUE(
       bgapp->permissions_data()->HasAPIPermission(APIPermission::kBackground));
-  ASSERT_TRUE(registry()->enabled_extensions().is_empty());
-  ASSERT_EQ(0U, model()->size());
+  EXPECT_TRUE(registry()->enabled_extensions().is_empty());
+  EXPECT_EQ(0U, model()->size());
 
   extensions::TestExtensionRegistryObserver load_observer(registry());
   // extensions can be loaded before ExtensionSystem::ready() is dispatched.
   service()->AddExtension(bgapp.get());
   load_observer.WaitForExtensionLoaded();
-  ASSERT_EQ(1U, registry()->enabled_extensions().size());
+  EXPECT_EQ(1U, registry()->enabled_extensions().size());
   // Model still has 0 item. since OnExtensionSystemReady is not called yet.
-  ASSERT_EQ(0U, model()->size());
+  EXPECT_EQ(0U, model()->size());
 
   // Wait Until OnExtensionSystemReady called.
   base::RunLoop().RunUntilIdle();
   // Make sure background model holds extensions.
-  ASSERT_TRUE(model()->is_ready());
-  ASSERT_EQ(1U, model()->size());
+  EXPECT_TRUE(model()->is_ready());
+  EXPECT_EQ(1U, model()->size());
 }
 
 typedef std::set<scoped_refptr<Extension> > ExtensionCollection;
diff --git a/chrome/browser/background/background_contents.cc b/chrome/browser/background/background_contents.cc
index b5353da7..d57e7c1 100644
--- a/chrome/browser/background/background_contents.cc
+++ b/chrome/browser/background/background_contents.cc
@@ -101,10 +101,7 @@
   // (http://crbug.com/237781).
   registrar_.RemoveAll();
 
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED,
-      content::Source<Profile>(profile_),
-      content::Details<BackgroundContents>(this));
+  delegate_->OnBackgroundContentsDeleted(this);
   for (auto& observer : deferred_start_render_host_observer_list_)
     observer.OnDeferredStartRenderHostDestroyed(this);
 
@@ -121,10 +118,7 @@
 }
 
 void BackgroundContents::CloseContents(WebContents* source) {
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_BACKGROUND_CONTENTS_CLOSED,
-      content::Source<Profile>(profile_),
-      content::Details<BackgroundContents>(this));
+  delegate_->OnBackgroundContentsClosed(this);
   delete this;
 }
 
@@ -140,10 +134,7 @@
   // some way to scope navigation of a background page to its opener's security
   // origin. Note: if the first navigation is to a URL outside the app's
   // extent a background page will be opened but will remain at about:blank.
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED,
-      content::Source<Profile>(profile_),
-      content::Details<BackgroundContents>(this));
+  delegate_->OnBackgroundContentsNavigated(this);
 }
 
 // Forward requests to add a new WebContents to our delegate.
@@ -165,10 +156,7 @@
 }
 
 void BackgroundContents::RenderProcessGone(base::TerminationStatus status) {
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_BACKGROUND_CONTENTS_TERMINATED,
-      content::Source<Profile>(profile_),
-      content::Details<BackgroundContents>(this));
+  delegate_->OnBackgroundContentsTerminated(this);
 
   // Our RenderView went away, so we should go away also, so killing the process
   // via the TaskManager doesn't permanently leave a BackgroundContents hanging
diff --git a/chrome/browser/background/background_contents.h b/chrome/browser/background/background_contents.h
index b5ec608..8bf9528 100644
--- a/chrome/browser/background/background_contents.h
+++ b/chrome/browser/background/background_contents.h
@@ -51,6 +51,14 @@
         const gfx::Rect& initial_rect,
         bool* was_blocked) = 0;
 
+    // Informs the delegate of lifetime events.
+    virtual void OnBackgroundContentsNavigated(
+        BackgroundContents* contents) = 0;
+    virtual void OnBackgroundContentsTerminated(
+        BackgroundContents* contents) = 0;
+    virtual void OnBackgroundContentsClosed(BackgroundContents* contents) = 0;
+    virtual void OnBackgroundContentsDeleted(BackgroundContents* contents) = 0;
+
    protected:
     virtual ~Delegate() {}
   };
diff --git a/chrome/browser/background/background_contents_service.cc b/chrome/browser/background/background_contents_service.cc
index b97054aa..112f87d 100644
--- a/chrome/browser/background/background_contents_service.cc
+++ b/chrome/browser/background/background_contents_service.cc
@@ -21,6 +21,7 @@
 #include "base/values.h"
 #include "chrome/browser/apps/platform_apps/app_load_service.h"
 #include "chrome/browser/background/background_contents_service_factory.h"
+#include "chrome/browser/background/background_contents_service_observer.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/extension_service.h"
@@ -248,22 +249,23 @@
 BackgroundContentsService::BackgroundContentsService(
     Profile* profile,
     const base::CommandLine* command_line)
-    : prefs_(nullptr),
-      extension_registry_observer_(this),
-      weak_ptr_factory_(this) {
+    : profile_(profile) {
   // Don't load/store preferences if the parent profile is incognito.
   if (!profile->IsOffTheRecord())
     prefs_ = profile->GetPrefs();
 
   // Listen for events to tell us when to load/unload persisted background
   // contents.
-  StartObserving(profile);
+  StartObserving();
 }
 
 BackgroundContentsService::~BackgroundContentsService() {
   // BackgroundContents should be shutdown before we go away, as otherwise
   // our browser process refcount will be off.
   DCHECK(contents_map_.empty());
+
+  for (auto& observer : observers_)
+    observer.OnBackgroundContentsServiceDestroying();
 }
 
 // static
@@ -301,45 +303,25 @@
   return contents;
 }
 
-void BackgroundContentsService::StartObserving(Profile* profile) {
+void BackgroundContentsService::StartObserving() {
   // On startup, load our background pages after extension-apps have loaded.
-  extensions::ExtensionSystem::Get(profile)->ready().Post(
+  extensions::ExtensionSystem::Get(profile_)->ready().Post(
       FROM_HERE,
       base::BindOnce(&BackgroundContentsService::OnExtensionSystemReady,
-                     weak_ptr_factory_.GetWeakPtr(), profile));
+                     weak_ptr_factory_.GetWeakPtr()));
 
-  // Track the lifecycle of all BackgroundContents in the system to allow us
-  // to store an up-to-date list of the urls. Start tracking contents when they
-  // have been opened via CreateBackgroundContents(), and stop tracking them
-  // when they are closed by script.
-  registrar_.Add(this, chrome::NOTIFICATION_BACKGROUND_CONTENTS_CLOSED,
-                 content::Source<Profile>(profile));
-
-  // Stop tracking BackgroundContents when they have been deleted (happens
-  // during shutdown or if the render process dies).
-  registrar_.Add(this, chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED,
-                 content::Source<Profile>(profile));
-
-  // Track when the BackgroundContents navigates to a new URL so we can update
-  // our persisted information as appropriate.
-  registrar_.Add(this, chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED,
-                 content::Source<Profile>(profile));
-
-  // Track when the extensions crash so that the user can be notified
-  // about it, and the crashed contents can be restarted.
   registrar_.Add(this, extensions::NOTIFICATION_EXTENSION_PROCESS_TERMINATED,
-                 content::Source<Profile>(profile));
-  registrar_.Add(this, chrome::NOTIFICATION_BACKGROUND_CONTENTS_TERMINATED,
-                 content::Source<Profile>(profile));
+                 content::Source<Profile>(profile_));
 
   // Listen for extension uninstall, load, unloaded notification.
-  extension_registry_observer_.Add(extensions::ExtensionRegistry::Get(profile));
+  extension_registry_observer_.Add(
+      extensions::ExtensionRegistry::Get(profile_));
 }
 
-void BackgroundContentsService::OnExtensionSystemReady(Profile* profile) {
-  LoadBackgroundContentsFromManifests(profile);
-  LoadBackgroundContentsFromPrefs(profile);
-  SendChangeNotification(profile);
+void BackgroundContentsService::OnExtensionSystemReady() {
+  LoadBackgroundContentsFromManifests(profile_);
+  LoadBackgroundContentsFromPrefs(profile_);
+  SendChangeNotification();
 }
 
 void BackgroundContentsService::Observe(
@@ -347,83 +329,9 @@
     const content::NotificationSource& source,
     const content::NotificationDetails& details) {
   TRACE_EVENT0("browser,startup", "BackgroundContentsService::Observe");
-  switch (type) {
-    case chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED:
-      BackgroundContentsShutdown(
-          content::Details<BackgroundContents>(details).ptr());
-      SendChangeNotification(content::Source<Profile>(source).ptr());
-      break;
-    case chrome::NOTIFICATION_BACKGROUND_CONTENTS_CLOSED:
-      DCHECK(IsTracked(content::Details<BackgroundContents>(details).ptr()));
-      UnregisterBackgroundContents(
-          content::Details<BackgroundContents>(details).ptr());
-      // CLOSED is always followed by a DELETED notification so we'll send our
-      // change notification there.
-      break;
-    case chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED: {
-      DCHECK(IsTracked(content::Details<BackgroundContents>(details).ptr()));
-
-      // Do not register in the pref if the extension has a manifest-specified
-      // background page.
-      BackgroundContents* bgcontents =
-          content::Details<BackgroundContents>(details).ptr();
-      Profile* profile = content::Source<Profile>(source).ptr();
-      const std::string& appid = GetParentApplicationId(bgcontents);
-      extensions::ExtensionService* extension_service =
-          extensions::ExtensionSystem::Get(profile)->extension_service();
-      // extension_service can be nullptr when running tests.
-      if (extension_service) {
-        const Extension* extension =
-            extension_service->GetExtensionById(appid, false);
-        if (extension && BackgroundInfo::HasBackgroundPage(extension))
-          break;
-      }
-      RegisterBackgroundContents(bgcontents);
-      break;
-    }
-    case extensions::NOTIFICATION_EXTENSION_PROCESS_TERMINATED:
-    case chrome::NOTIFICATION_BACKGROUND_CONTENTS_TERMINATED: {
-      Profile* profile = content::Source<Profile>(source).ptr();
-      const Extension* extension = nullptr;
-      if (type == chrome::NOTIFICATION_BACKGROUND_CONTENTS_TERMINATED) {
-        BackgroundContents* bg =
-            content::Details<BackgroundContents>(details).ptr();
-        std::string extension_id =
-            BackgroundContentsServiceFactory::GetForProfile(profile)
-                ->GetParentApplicationId(bg);
-        extension = extensions::ExtensionSystem::Get(profile)
-                        ->extension_service()
-                        ->GetExtensionById(extension_id, false);
-      } else {
-        extensions::ExtensionHost* extension_host =
-            content::Details<extensions::ExtensionHost>(details).ptr();
-        extension = extension_host->extension();
-      }
-      if (!extension)
-        break;
-
-      const bool force_installed =
-          extensions::Manifest::IsComponentLocation(extension->location()) ||
-          extensions::Manifest::IsPolicyLocation(extension->location());
-      if (!force_installed) {
-#if defined(OS_CHROMEOS)
-        chromeos::UserFlow* user_flow =
-            chromeos::ChromeUserManager::Get()->GetCurrentUserFlow();
-        if (!user_flow->AllowsNotificationBalloons())
-          break;
-#endif
-        ShowBalloon(extension, profile);
-      } else {
-        // Restart the extension.
-        RestartForceInstalledExtensionOnCrash(extension, profile);
-      }
-      break;
-    }
-
-    default:
-      NOTREACHED();
-      break;
-  }
+  DCHECK_EQ(type, extensions::NOTIFICATION_EXTENSION_PROCESS_TERMINATED);
+  HandleExtensionCrashed(
+      content::Details<extensions::ExtensionHost>(details).ptr()->extension());
 }
 
 void BackgroundContentsService::OnExtensionLoaded(
@@ -468,7 +376,7 @@
 
   // Close the crash notification balloon for the app/extension, if any.
   CloseBalloon(extension->id(), profile);
-  SendChangeNotification(profile);
+  SendChangeNotification();
 }
 
 void BackgroundContentsService::OnExtensionUnloaded(
@@ -484,7 +392,7 @@
     case UnloadedExtensionReason::MIGRATED_TO_COMPONENT:  // Fall through.
     case UnloadedExtensionReason::PROFILE_SHUTDOWN:
       ShutdownAssociatedBackgroundContents(extension->id());
-      SendChangeNotification(Profile::FromBrowserContext(browser_context));
+      SendChangeNotification();
       return;
     case UnloadedExtensionReason::UPDATE: {
       // If there is a manifest specified background page, then shut it down
@@ -582,11 +490,9 @@
   }
 }
 
-void BackgroundContentsService::SendChangeNotification(Profile* profile) {
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_BACKGROUND_CONTENTS_SERVICE_CHANGED,
-      content::Source<Profile>(profile),
-      content::Details<BackgroundContentsService>(this));
+void BackgroundContentsService::SendChangeNotification() {
+  for (auto& observer : observers_)
+    observer.OnBackgroundContentsServiceChanged();
 }
 
 void BackgroundContentsService::MaybeClearBackoffEntry(
@@ -704,13 +610,11 @@
   BackgroundContentsOpenedDetails details = {contents, frame_name,
                                              application_id};
   BackgroundContentsOpened(&details, profile);
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_BACKGROUND_CONTENTS_OPENED,
-      content::Source<Profile>(profile),
-      content::Details<BackgroundContentsOpenedDetails>(&details));
+  for (auto& observer : observers_)
+    observer.OnBackgroundContentsOpened(details);
 
   // A new background contents has been created - notify our listeners.
-  SendChangeNotification(profile);
+  SendChangeNotification();
   return contents;
 }
 
@@ -786,11 +690,14 @@
   return !GetParentApplicationId(background_contents).empty();
 }
 
-void BackgroundContentsService::BackgroundContentsShutdown(
-    BackgroundContents* background_contents) {
-  // Remove the passed object from our list.
-  DCHECK(IsTracked(background_contents));
-  contents_map_.erase(GetParentApplicationId(background_contents));
+void BackgroundContentsService::AddObserver(
+    BackgroundContentsServiceObserver* observer) {
+  observers_.AddObserver(observer);
+}
+
+void BackgroundContentsService::RemoveObserver(
+    BackgroundContentsServiceObserver* observer) {
+  observers_.RemoveObserver(observer);
 }
 
 BackgroundContents* BackgroundContentsService::GetAppBackgroundContents(
@@ -820,3 +727,70 @@
                            disposition, initial_rect);
   }
 }
+
+void BackgroundContentsService::OnBackgroundContentsNavigated(
+    BackgroundContents* contents) {
+  DCHECK(IsTracked(contents));
+  // Do not register in the pref if the extension has a manifest-specified
+  // background page.
+  const std::string& appid = GetParentApplicationId(contents);
+  extensions::ExtensionService* extension_service =
+      extensions::ExtensionSystem::Get(profile_)->extension_service();
+  // extension_service can be nullptr when running tests.
+  if (extension_service) {
+    const Extension* extension =
+        extension_service->GetExtensionById(appid, false);
+    if (extension && BackgroundInfo::HasBackgroundPage(extension))
+      return;
+  }
+  RegisterBackgroundContents(contents);
+}
+
+void BackgroundContentsService::OnBackgroundContentsTerminated(
+    BackgroundContents* contents) {
+  HandleExtensionCrashed(
+      extensions::ExtensionSystem::Get(profile_)
+          ->extension_service()
+          ->GetExtensionById(GetParentApplicationId(contents), false));
+}
+
+void BackgroundContentsService::OnBackgroundContentsClosed(
+    BackgroundContents* contents) {
+  DCHECK(IsTracked(contents));
+  UnregisterBackgroundContents(contents);
+  // CLOSED is always followed by a DELETED notification so we'll send our
+  // change notification there.
+}
+
+void BackgroundContentsService::OnBackgroundContentsDeleted(
+    BackgroundContents* contents) {
+  // Stop tracking BackgroundContents when they have been deleted (happens
+  // during shutdown or if the render process dies).
+  DCHECK(IsTracked(contents));
+  contents_map_.erase(GetParentApplicationId(contents));
+  SendChangeNotification();
+}
+
+void BackgroundContentsService::HandleExtensionCrashed(
+    const extensions::Extension* extension) {
+  // When the extensions crash, notify the user about it and restart the crashed
+  // contents.
+  if (!extension)
+    return;
+
+  const bool force_installed =
+      extensions::Manifest::IsComponentLocation(extension->location()) ||
+      extensions::Manifest::IsPolicyLocation(extension->location());
+  if (!force_installed) {
+#if defined(OS_CHROMEOS)
+    chromeos::UserFlow* user_flow =
+        chromeos::ChromeUserManager::Get()->GetCurrentUserFlow();
+    if (!user_flow->AllowsNotificationBalloons())
+      return;
+#endif
+    ShowBalloon(extension, profile_);
+  } else {
+    // Restart the extension.
+    RestartForceInstalledExtensionOnCrash(extension, profile_);
+  }
+}
diff --git a/chrome/browser/background/background_contents_service.h b/chrome/browser/background/background_contents_service.h
index 9566270..0a07b76 100644
--- a/chrome/browser/background/background_contents_service.h
+++ b/chrome/browser/background/background_contents_service.h
@@ -46,6 +46,7 @@
 class Rect;
 }
 
+class BackgroundContentsServiceObserver;
 struct BackgroundContentsOpenedDetails;
 
 // BackgroundContentsService is owned by the profile, and is responsible for
@@ -83,6 +84,9 @@
   static void DisableCloseBalloonForTesting(
       bool disable_close_balloon_for_testing);
 
+  void AddObserver(BackgroundContentsServiceObserver* observer);
+  void RemoveObserver(BackgroundContentsServiceObserver* observer);
+
   // Returns the BackgroundContents associated with the passed application id,
   // or NULL if none.
   BackgroundContents* GetAppBackgroundContents(const std::string& appid);
@@ -101,6 +105,10 @@
                       WindowOpenDisposition disposition,
                       const gfx::Rect& initial_rect,
                       bool* was_blocked) override;
+  void OnBackgroundContentsNavigated(BackgroundContents* contents) override;
+  void OnBackgroundContentsTerminated(BackgroundContents* contents) override;
+  void OnBackgroundContentsClosed(BackgroundContents* contents) override;
+  void OnBackgroundContentsDeleted(BackgroundContents* contents) override;
 
   // Gets the parent application id for the passed BackgroundContents. Returns
   // an empty string if no parent application found (e.g. passed
@@ -142,7 +150,7 @@
                            TestApplicationIDLinkage);
 
   // Registers for various notifications.
-  void StartObserving(Profile* profile);
+  void StartObserving();
 
   // content::NotificationObserver implementation.
   void Observe(int type,
@@ -150,7 +158,7 @@
                const content::NotificationDetails& details) override;
 
   // Called when ExtensionSystem is ready.
-  void OnExtensionSystemReady(Profile* profile);
+  void OnExtensionSystemReady();
 
   // extensions::ExtensionRegistryObserver implementation.
   void OnExtensionLoaded(content::BrowserContext* browser_context,
@@ -193,9 +201,6 @@
   void BackgroundContentsOpened(BackgroundContentsOpenedDetails* details,
                                 Profile* profile);
 
-  // Invoked when a BackgroundContents object is destroyed.
-  void BackgroundContentsShutdown(BackgroundContents* contents);
-
   // Registers the |contents->GetURL()| to be run at startup. Only happens for
   // the first navigation after window.open() (future calls to
   // RegisterBackgroundContents() for the same BackgroundContents will do
@@ -215,19 +220,25 @@
   // Sends out a notification when our association of background contents with
   // apps may have changed (used by BackgroundApplicationListModel to update the
   // set of background apps as new background contents are opened/closed).
-  void SendChangeNotification(Profile* profile);
+  void SendChangeNotification();
 
   // Checks whether there has been additional |extension_id| failures. If not,
   // delete the BackoffEntry corresponding to |extension_id|, if exists.
   void MaybeClearBackoffEntry(const std::string extension_id,
                               int expected_failure_count);
 
+  void HandleExtensionCrashed(const extensions::Extension* extension);
+
   // Delay (in ms) before restarting a force-installed extension that crashed.
   static int restart_delay_in_ms_;
 
+  Profile* profile_;
+
+  base::ObserverList<BackgroundContentsServiceObserver> observers_;
+
   // PrefService used to store list of background pages (or NULL if this is
   // running under an incognito profile).
-  PrefService* prefs_;
+  PrefService* prefs_ = nullptr;
   content::NotificationRegistrar registrar_;
 
   // Information we track about each BackgroundContents.
@@ -253,9 +264,9 @@
 
   ScopedObserver<extensions::ExtensionRegistry,
                  extensions::ExtensionRegistryObserver>
-      extension_registry_observer_;
+      extension_registry_observer_{this};
 
-  base::WeakPtrFactory<BackgroundContentsService> weak_ptr_factory_;
+  base::WeakPtrFactory<BackgroundContentsService> weak_ptr_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(BackgroundContentsService);
 };
diff --git a/chrome/browser/background/background_contents_service_factory.cc b/chrome/browser/background/background_contents_service_factory.cc
index c3e5f94..f866434c 100644
--- a/chrome/browser/background/background_contents_service_factory.cc
+++ b/chrome/browser/background/background_contents_service_factory.cc
@@ -59,7 +59,3 @@
     const {
   return true;
 }
-
-bool BackgroundContentsServiceFactory::ServiceIsNULLWhileTesting() const {
-  return true;
-}
diff --git a/chrome/browser/background/background_contents_service_factory.h b/chrome/browser/background/background_contents_service_factory.h
index 850f3a9..0b266f7b 100644
--- a/chrome/browser/background/background_contents_service_factory.h
+++ b/chrome/browser/background/background_contents_service_factory.h
@@ -36,7 +36,8 @@
   content::BrowserContext* GetBrowserContextToUse(
       content::BrowserContext* context) const override;
   bool ServiceIsCreatedWithBrowserContext() const override;
-  bool ServiceIsNULLWhileTesting() const override;
+
+  DISALLOW_COPY_AND_ASSIGN(BackgroundContentsServiceFactory);
 };
 
 #endif  // CHROME_BROWSER_BACKGROUND_BACKGROUND_CONTENTS_SERVICE_FACTORY_H_
diff --git a/chrome/browser/background/background_contents_service_observer.h b/chrome/browser/background/background_contents_service_observer.h
new file mode 100644
index 0000000..e72506105
--- /dev/null
+++ b/chrome/browser/background/background_contents_service_observer.h
@@ -0,0 +1,23 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_BACKGROUND_BACKGROUND_CONTENTS_SERVICE_OBSERVER_H_
+#define CHROME_BROWSER_BACKGROUND_BACKGROUND_CONTENTS_SERVICE_OBSERVER_H_
+
+#include "base/observer_list_types.h"
+
+struct BackgroundContentsOpenedDetails;
+
+class BackgroundContentsServiceObserver : public base::CheckedObserver {
+ public:
+  virtual void OnBackgroundContentsServiceChanged() {}
+  virtual void OnBackgroundContentsOpened(
+      const BackgroundContentsOpenedDetails& details) {}
+  virtual void OnBackgroundContentsServiceDestroying() {}
+
+ protected:
+  ~BackgroundContentsServiceObserver() override = default;
+};
+
+#endif  // CHROME_BROWSER_BACKGROUND_BACKGROUND_CONTENTS_SERVICE_OBSERVER_H_
diff --git a/chrome/browser/background/background_contents_service_unittest.cc b/chrome/browser/background/background_contents_service_unittest.cc
index 8ebc2aa..b1435f69 100644
--- a/chrome/browser/background/background_contents_service_unittest.cc
+++ b/chrome/browser/background/background_contents_service_unittest.cc
@@ -67,38 +67,31 @@
 
 class MockBackgroundContents : public BackgroundContents {
  public:
-  explicit MockBackgroundContents(Profile* profile)
-      : appid_("app_id"), profile_(profile) {}
-  MockBackgroundContents(Profile* profile, const std::string& id)
-      : appid_(id), profile_(profile) {}
+  MockBackgroundContents(BackgroundContentsService* service,
+                         Profile* profile,
+                         const std::string& id)
+      : service_(service), appid_(id), profile_(profile) {}
+  MockBackgroundContents(BackgroundContentsService* service, Profile* profile)
+      : MockBackgroundContents(service, profile, "app_id") {}
 
-  void SendOpenedNotification(BackgroundContentsService* service) {
+  void SendOpenedNotification() {
     BackgroundContentsOpenedDetails details = {this, "background", appid_};
-    service->BackgroundContentsOpened(&details, profile_);
+    service_->BackgroundContentsOpened(&details, profile_);
   }
 
-  virtual void Navigate(GURL url) {
+  void Navigate(GURL url) {
     url_ = url;
-    content::NotificationService::current()->Notify(
-        chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED,
-        content::Source<Profile>(profile_),
-        content::Details<BackgroundContents>(this));
+    service_->OnBackgroundContentsNavigated(this);
   }
   const GURL& GetURL() const override { return url_; }
 
   void MockClose(Profile* profile) {
-    content::NotificationService::current()->Notify(
-        chrome::NOTIFICATION_BACKGROUND_CONTENTS_CLOSED,
-        content::Source<Profile>(profile),
-        content::Details<BackgroundContents>(this));
+    service_->OnBackgroundContentsClosed(this);
     delete this;
   }
 
   ~MockBackgroundContents() override {
-    content::NotificationService::current()->Notify(
-        chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED,
-        content::Source<Profile>(profile_),
-        content::Details<BackgroundContents>(this));
+    service_->OnBackgroundContentsDeleted(this);
   }
 
   const std::string& appid() { return appid_; }
@@ -106,11 +99,15 @@
  private:
   GURL url_;
 
+  BackgroundContentsService* service_;
+
   // The ID of our parent application
   std::string appid_;
 
   // Parent profile
   Profile* profile_;
+
+  DISALLOW_COPY_AND_ASSIGN(MockBackgroundContents);
 };
 
 class BackgroundContentsServiceNotificationTest
@@ -157,9 +154,10 @@
 TEST_F(BackgroundContentsServiceTest, BackgroundContentsCreateDestroy) {
   TestingProfile profile;
   BackgroundContentsService service(&profile, command_line_.get());
-  MockBackgroundContents* contents = new MockBackgroundContents(&profile);
+  MockBackgroundContents* contents =
+      new MockBackgroundContents(&service, &profile);
   EXPECT_FALSE(service.IsTracked(contents));
-  contents->SendOpenedNotification(&service);
+  contents->SendOpenedNotification();
   EXPECT_TRUE(service.IsTracked(contents));
   delete contents;
   EXPECT_FALSE(service.IsTracked(contents));
@@ -174,9 +172,9 @@
   GURL url2("http://a/");
   {
     std::unique_ptr<MockBackgroundContents> contents(
-        new MockBackgroundContents(&profile));
+        new MockBackgroundContents(&service, &profile));
     EXPECT_EQ(0U, GetPrefs(&profile)->size());
-    contents->SendOpenedNotification(&service);
+    contents->SendOpenedNotification();
 
     contents->Navigate(url);
     EXPECT_EQ(1U, GetPrefs(&profile)->size());
@@ -196,9 +194,10 @@
   BackgroundContentsService service(&profile, command_line_.get());
 
   GURL url("http://a/");
-  MockBackgroundContents* contents = new MockBackgroundContents(&profile);
+  MockBackgroundContents* contents =
+      new MockBackgroundContents(&service, &profile);
   EXPECT_EQ(0U, GetPrefs(&profile)->size());
-  contents->SendOpenedNotification(&service);
+  contents->SendOpenedNotification();
   contents->Navigate(url);
   EXPECT_EQ(1U, GetPrefs(&profile)->size());
   EXPECT_EQ(url.spec(), GetPrefURLForApp(&profile, contents->appid()));
@@ -217,8 +216,8 @@
   GURL url("http://a/");
   {
     std::unique_ptr<MockBackgroundContents> contents(
-        new MockBackgroundContents(&profile, "appid"));
-    contents->SendOpenedNotification(&service);
+        new MockBackgroundContents(&service, &profile, "appid"));
+    contents->SendOpenedNotification();
     contents->Navigate(url);
     EXPECT_EQ(1U, GetPrefs(&profile)->size());
     EXPECT_EQ(url.spec(), GetPrefURLForApp(&profile, contents->appid()));
@@ -230,8 +229,8 @@
     // Reopen the BackgroundContents to the same URL, we should not register the
     // URL again.
     std::unique_ptr<MockBackgroundContents> contents(
-        new MockBackgroundContents(&profile, "appid"));
-    contents->SendOpenedNotification(&service);
+        new MockBackgroundContents(&service, &profile, "appid"));
+    contents->SendOpenedNotification();
     contents->Navigate(url);
     EXPECT_EQ(1U, GetPrefs(&profile)->size());
   }
@@ -246,12 +245,12 @@
 
   EXPECT_EQ(NULL, service.GetAppBackgroundContents("appid"));
   MockBackgroundContents* contents =
-      new MockBackgroundContents(&profile, "appid");
+      new MockBackgroundContents(&service, &profile, "appid");
   std::unique_ptr<MockBackgroundContents> contents2(
-      new MockBackgroundContents(&profile, "appid2"));
-  contents->SendOpenedNotification(&service);
+      new MockBackgroundContents(&service, &profile, "appid2"));
+  contents->SendOpenedNotification();
   EXPECT_EQ(contents, service.GetAppBackgroundContents(contents->appid()));
-  contents2->SendOpenedNotification(&service);
+  contents2->SendOpenedNotification();
   EXPECT_EQ(contents2.get(),
             service.GetAppBackgroundContents(contents2->appid()));
   EXPECT_EQ(0U, GetPrefs(&profile)->size());
diff --git a/chrome/browser/background/background_mode_manager.cc b/chrome/browser/background/background_mode_manager.cc
index 72db2b3..7574b4f 100644
--- a/chrome/browser/background/background_mode_manager.cc
+++ b/chrome/browser/background/background_mode_manager.cc
@@ -617,11 +617,6 @@
   in_background_mode_ = true;
 
   UpdateKeepAliveAndTrayIcon();
-
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_BACKGROUND_MODE_CHANGED,
-      content::Source<BackgroundModeManager>(this),
-      content::Details<bool>(&in_background_mode_));
 }
 
 void BackgroundModeManager::EndBackgroundMode() {
@@ -630,11 +625,6 @@
   in_background_mode_ = false;
 
   UpdateKeepAliveAndTrayIcon();
-
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_BACKGROUND_MODE_CHANGED,
-      content::Source<BackgroundModeManager>(this),
-      content::Details<bool>(&in_background_mode_));
 }
 
 void BackgroundModeManager::EnableBackgroundMode() {
diff --git a/chrome/browser/browser_process_platform_part_chromeos.cc b/chrome/browser/browser_process_platform_part_chromeos.cc
index e65af396..70df3b2 100644
--- a/chrome/browser/browser_process_platform_part_chromeos.cc
+++ b/chrome/browser/browser_process_platform_part_chromeos.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/chrome_service_name.h"
 #include "chrome/browser/chromeos/kerberos/kerberos_credentials_manager.h"
+#include "chrome/browser/chromeos/login/saml/in_session_password_change_manager.h"
 #include "chrome/browser/chromeos/login/session/chrome_session_manager.h"
 #include "chrome/browser/chromeos/login/users/chrome_user_manager_impl.h"
 #include "chrome/browser/chromeos/net/delay_network_call.h"
@@ -160,6 +161,12 @@
   kerberos_credentials_manager_ =
       std::make_unique<chromeos::KerberosCredentialsManager>(
           g_browser_process->local_state(), primary_user);
+
+  DCHECK(!in_session_password_change_manager_);
+  in_session_password_change_manager_ =
+      chromeos::InSessionPasswordChangeManager::CreateIfEnabled(primary_profile,
+                                                                primary_user);
+
   primary_profile_shutdown_subscription_ =
       PrimaryProfileServicesShutdownNotifierFactory::GetInstance()
           ->Get(primary_profile)
@@ -170,6 +177,7 @@
 
 void BrowserProcessPlatformPart::ShutdownPrimaryProfileServices() {
   kerberos_credentials_manager_.reset();
+  in_session_password_change_manager_.reset();
 }
 
 void BrowserProcessPlatformPart::RegisterKeepAlive() {
diff --git a/chrome/browser/browser_process_platform_part_chromeos.h b/chrome/browser/browser_process_platform_part_chromeos.h
index 5ad1879b..3c0927d 100644
--- a/chrome/browser/browser_process_platform_part_chromeos.h
+++ b/chrome/browser/browser_process_platform_part_chromeos.h
@@ -22,6 +22,7 @@
 class ChromeSessionManager;
 class ChromeUserManager;
 class KerberosCredentialsManager;
+class InSessionPasswordChangeManager;
 class ProfileHelper;
 class TimeZoneResolver;
 
@@ -123,6 +124,11 @@
 
   chromeos::AccountManagerFactory* GetAccountManagerFactory();
 
+  chromeos::InSessionPasswordChangeManager*
+  in_session_password_change_manager() {
+    return in_session_password_change_manager_.get();
+  }
+
  private:
   friend class BrowserProcessPlatformPartTestApi;
 
@@ -164,6 +170,9 @@
   std::unique_ptr<chromeos::KerberosCredentialsManager>
       kerberos_credentials_manager_;
 
+  std::unique_ptr<chromeos::InSessionPasswordChangeManager>
+      in_session_password_change_manager_;
+
   std::unique_ptr<KeyedServiceShutdownNotifier::Subscription>
       primary_profile_shutdown_subscription_;
 
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 5dbee70..492db91 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -153,6 +153,10 @@
       <include name="IDR_DOWNLOAD_INTERNALS_JS" file="resources\download_internals\download_internals.js" type="BINDATA" compress="gzip" />
       <include name="IDR_DOWNLOAD_INTERNALS_BROWSER_PROXY_JS" file="resources\download_internals\download_internals_browser_proxy.js" type="BINDATA" compress="gzip" />
       <include name="IDR_DOWNLOAD_INTERNALS_VISUALS_JS" file="resources\download_internals\download_internals_visuals.js" type="BINDATA" compress="gzip" />
+      <include name="IDR_NOTIFICATIONS_INTERNALS_HTML" file="resources\notifications_internals\notifications_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
+      <include name="IDR_NOTIFICATIONS_INTERNALS_CSS" file="resources\notifications_internals\notifications_internals.css" type="BINDATA" compress="gzip" />
+      <include name="IDR_NOTIFICATIONS_INTERNALS_JS" file="resources\notifications_internals\notifications_internals.js" type="BINDATA" compress="gzip" />
+      <include name="IDR_NOTIFICATIONS_INTERNALS_BROWSER_PROXY_JS" file="resources\notifications_internals\notifications_internals_browser_proxy.js" type="BINDATA" compress="gzip" />
       <include name="IDR_UKM_INTERNALS_HTML" file="../../components/ukm/debug/ukm_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
       <include name="IDR_UKM_INTERNALS_JS" file="../../components/ukm/debug/ukm_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
       <include name="IDR_UKM_INTERNALS_CSS" file="../../components/ukm/debug/ukm_internals.css" flattenhtml="true" compress="gzip" type="BINDATA" />
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 9f83820..2c45195 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -1528,7 +1528,7 @@
 #endif
 }
 
-bool ChromeContentBrowserClient::ShouldUseMobileFlingCurve() const {
+bool ChromeContentBrowserClient::ShouldUseMobileFlingCurve() {
 #if defined(OS_ANDROID)
   return true;
 #elif defined(OS_CHROMEOS)
@@ -1680,7 +1680,7 @@
 #endif
 }
 
-bool ChromeContentBrowserClient::LogWebUIUrl(const GURL& web_ui_url) const {
+bool ChromeContentBrowserClient::LogWebUIUrl(const GURL& web_ui_url) {
   return webui::LogWebUIUrl(web_ui_url);
 }
 
@@ -3691,7 +3691,7 @@
 
 #if defined(OS_WIN)
 base::string16 ChromeContentBrowserClient::GetAppContainerSidForSandboxType(
-    int sandbox_type) const {
+    int sandbox_type) {
   // TODO(wfh): Add support for more process types here. crbug.com/499523
   switch (sandbox_type) {
     case service_manager::SANDBOX_TYPE_RENDERER:
@@ -5624,21 +5624,19 @@
       render_frame_host, new_features);
 }
 
-std::string ChromeContentBrowserClient::GetProduct() const {
+std::string ChromeContentBrowserClient::GetProduct() {
   return ::GetProduct();
 }
 
-std::string ChromeContentBrowserClient::GetUserAgent() const {
+std::string ChromeContentBrowserClient::GetUserAgent() {
   return ::GetUserAgent();
 }
 
-blink::UserAgentMetadata ChromeContentBrowserClient::GetUserAgentMetadata()
-    const {
+blink::UserAgentMetadata ChromeContentBrowserClient::GetUserAgentMetadata() {
   return ::GetUserAgentMetadata();
 }
 
-base::Optional<gfx::ImageSkia> ChromeContentBrowserClient::GetProductLogo()
-    const {
+base::Optional<gfx::ImageSkia> ChromeContentBrowserClient::GetProductLogo() {
   // This icon is available on Android, but adds 19KiB to the APK. Since it
   // isn't used on Android we exclude it to avoid bloat.
 #if !defined(OS_ANDROID)
@@ -5680,7 +5678,7 @@
 
 #if defined(OS_ANDROID)
 content::ContentBrowserClient::WideColorGamutHeuristic
-ChromeContentBrowserClient::GetWideColorGamutHeuristic() const {
+ChromeContentBrowserClient::GetWideColorGamutHeuristic() {
   if (features::UseDisplayWideColorGamut()) {
     return WideColorGamutHeuristic::kUseDisplay;
   }
@@ -5704,7 +5702,7 @@
     const content::WebContents* web_contents,
     const content::RenderFrameHost* frame_host,
     bool user_gesture,
-    content::NavigationDownloadPolicy* download_policy) const {
+    content::NavigationDownloadPolicy* download_policy) {
   const ChromeSubresourceFilterClient* client =
       ChromeSubresourceFilterClient::FromWebContents(web_contents);
   if (client && client->GetThrottleManager()->IsFrameTaggedAsAd(frame_host)) {
@@ -5728,7 +5726,7 @@
 bool ChromeContentBrowserClient::IsBluetoothScanningBlocked(
     content::BrowserContext* browser_context,
     const url::Origin& requesting_origin,
-    const url::Origin& embedding_origin) const {
+    const url::Origin& embedding_origin) {
   const HostContentSettingsMap* const content_settings =
       HostContentSettingsMapFactory::GetForProfile(
           Profile::FromBrowserContext(browser_context));
@@ -5746,7 +5744,7 @@
 void ChromeContentBrowserClient::BlockBluetoothScanning(
     content::BrowserContext* browser_context,
     const url::Origin& requesting_origin,
-    const url::Origin& embedding_origin) const {
+    const url::Origin& embedding_origin) {
   HostContentSettingsMap* const content_settings =
       HostContentSettingsMapFactory::GetForProfile(
           Profile::FromBrowserContext(browser_context));
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index d654bcc8..89593fd 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -140,7 +140,7 @@
       bool is_main_frame,
       const GURL& candidate_url,
       const GURL& destination_url) override;
-  bool ShouldUseMobileFlingCurve() const override;
+  bool ShouldUseMobileFlingCurve() override;
   bool ShouldUseProcessPerSite(content::BrowserContext* browser_context,
                                const GURL& effective_url) override;
   bool ShouldUseSpareRenderProcessHost(content::BrowserContext* browser_context,
@@ -165,7 +165,7 @@
       std::vector<std::string>* additional_schemes) override;
   void GetAdditionalViewSourceSchemes(
       std::vector<std::string>* additional_schemes) override;
-  bool LogWebUIUrl(const GURL& web_ui_url) const override;
+  bool LogWebUIUrl(const GURL& web_ui_url) override;
   bool IsWebUIAllowedToMakeNetworkRequests(const url::Origin& origin) override;
   bool IsHandledURL(const GURL& url) override;
   bool CanCommitURL(content::RenderProcessHost* process_host,
@@ -393,8 +393,7 @@
 #endif  // defined(OS_POSIX) && !defined(OS_MACOSX)
 #if defined(OS_WIN)
   bool PreSpawnRenderer(sandbox::TargetPolicy* policy) override;
-  base::string16 GetAppContainerSidForSandboxType(
-      int sandbox_type) const override;
+  base::string16 GetAppContainerSidForSandboxType(int sandbox_type) override;
 #endif
   void ExposeInterfacesToRenderer(
       service_manager::BinderRegistry* registry,
@@ -578,11 +577,11 @@
   void LogWebFeatureForCurrentPage(content::RenderFrameHost* render_frame_host,
                                    blink::mojom::WebFeature feature) override;
 
-  std::string GetProduct() const override;
-  std::string GetUserAgent() const override;
-  blink::UserAgentMetadata GetUserAgentMetadata() const override;
+  std::string GetProduct() override;
+  std::string GetUserAgent() override;
+  blink::UserAgentMetadata GetUserAgentMetadata() override;
 
-  base::Optional<gfx::ImageSkia> GetProductLogo() const override;
+  base::Optional<gfx::ImageSkia> GetProductLogo() override;
 
   bool IsBuiltinComponent(content::BrowserContext* browser_context,
                           const url::Origin& origin) override;
@@ -595,7 +594,7 @@
 
 #if defined(OS_ANDROID)
   ContentBrowserClient::WideColorGamutHeuristic GetWideColorGamutHeuristic()
-      const override;
+      override;
 #endif
 
   base::flat_set<std::string> GetPluginMimeTypesWithExternalHandlers(
@@ -605,17 +604,15 @@
       const content::WebContents* web_contents,
       const content::RenderFrameHost* frame_host,
       bool user_gesture,
-      content::NavigationDownloadPolicy* download_policy) const override;
+      content::NavigationDownloadPolicy* download_policy) override;
 
-  bool IsBluetoothScanningBlocked(
-      content::BrowserContext* browser_context,
-      const url::Origin& requesting_origin,
-      const url::Origin& embedding_origin) const override;
+  bool IsBluetoothScanningBlocked(content::BrowserContext* browser_context,
+                                  const url::Origin& requesting_origin,
+                                  const url::Origin& embedding_origin) override;
 
-  void BlockBluetoothScanning(
-      content::BrowserContext* browser_context,
-      const url::Origin& requesting_origin,
-      const url::Origin& embedding_origin) const override;
+  void BlockBluetoothScanning(content::BrowserContext* browser_context,
+                              const url::Origin& requesting_origin,
+                              const url::Origin& embedding_origin) override;
 
   content::PreviewsState DetermineAllowedPreviewsWithoutHoldback(
       content::PreviewsState initial_state,
diff --git a/chrome/browser/chrome_notification_types.h b/chrome/browser/chrome_notification_types.h
index ba93653..59b253a 100644
--- a/chrome/browser/chrome_notification_types.h
+++ b/chrome/browser/chrome_notification_types.h
@@ -130,41 +130,7 @@
   // match was found or not found.
   NOTIFICATION_FIND_RESULT_AVAILABLE,
 
-  // BackgroundContents ------------------------------------------------------
-
-  // A new background contents was opened by script. The source is the parent
-  // profile and the details are BackgroundContentsOpenedDetails.
-  NOTIFICATION_BACKGROUND_CONTENTS_OPENED,
-
-  // The background contents navigated to a new location. The source is the
-  // parent Profile, and the details are the BackgroundContents that was
-  // navigated.
-  NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED,
-
-  // The background contents were closed by someone invoking window.close()
-  // or the parent application was uninstalled.
-  // The source is the parent profile, and the details are the
-  // BackgroundContents.
-  NOTIFICATION_BACKGROUND_CONTENTS_CLOSED,
-
-  // The background contents is being deleted. The source is the
-  // parent Profile, and the details are the BackgroundContents being deleted.
-  NOTIFICATION_BACKGROUND_CONTENTS_DELETED,
-
-  // The background contents has crashed. The source is the parent Profile,
-  // and the details are the BackgroundContents.
-  NOTIFICATION_BACKGROUND_CONTENTS_TERMINATED,
-
-  // The background contents associated with a hosted app has changed (either
-  // a new background contents has been created, or an existing background
-  // contents has closed). The source is the parent Profile, and the details
-  // are the BackgroundContentsService.
-  NOTIFICATION_BACKGROUND_CONTENTS_SERVICE_CHANGED,
-
-  // Chrome has entered/exited background mode. The source is the
-  // BackgroundModeManager and the details are a boolean value which is set to
-  // true if Chrome is now in background mode.
-  NOTIFICATION_BACKGROUND_MODE_CHANGED,
+  // Authentication ----------------------------------------------------------
 
   // This is sent when a login prompt is shown.  The source is the
   // Source<NavigationController> for the tab in which the prompt is shown.
diff --git a/chrome/browser/chrome_security_exploit_browsertest.cc b/chrome/browser/chrome_security_exploit_browsertest.cc
index 7bafd37c..dd16bcd 100644
--- a/chrome/browser/chrome_security_exploit_browsertest.cc
+++ b/chrome/browser/chrome_security_exploit_browsertest.cc
@@ -490,15 +490,18 @@
 class BlobURLStoreInterceptor
     : public blink::mojom::BlobURLStoreInterceptorForTesting {
  public:
-  explicit BlobURLStoreInterceptor(GURL target_url) : target_url_(target_url) {}
-
-  void Intercept(
+  static void Intercept(
+      GURL target_url,
       mojo::StrongAssociatedBindingPtr<blink::mojom::BlobURLStore> binding) {
-    url_store_ = binding->SwapImplForTesting(this);
+    auto interceptor =
+        base::WrapUnique(new BlobURLStoreInterceptor(target_url));
+    auto* raw_interceptor = interceptor.get();
+    auto impl = binding->SwapImplForTesting(std::move(interceptor));
+    raw_interceptor->url_store_ = std::move(impl);
   }
 
   blink::mojom::BlobURLStore* GetForwardingInterface() override {
-    return url_store_;
+    return url_store_.get();
   }
 
   void Register(blink::mojom::BlobPtr blob,
@@ -509,7 +512,9 @@
   }
 
  private:
-  blink::mojom::BlobURLStore* url_store_;
+  explicit BlobURLStoreInterceptor(GURL target_url) : target_url_(target_url) {}
+
+  std::unique_ptr<blink::mojom::BlobURLStore> url_store_;
   GURL target_url_;
 };
 
@@ -537,10 +542,9 @@
   // Target an extension.
   std::string target_origin = "chrome-extension://" + extension()->id();
   std::string blob_path = "5881f76e-10d2-410d-8c61-ef210502acfd";
-  BlobURLStoreInterceptor interceptor(
-      GURL("blob:" + target_origin + "/" + blob_path));
-  auto intercept_hook = base::BindRepeating(&BlobURLStoreInterceptor::Intercept,
-                                            base::Unretained(&interceptor));
+  auto intercept_hook =
+      base::BindRepeating(&BlobURLStoreInterceptor::Intercept,
+                          GURL("blob:" + target_origin + "/" + blob_path));
   storage::BlobRegistryImpl::SetURLStoreCreationHookForTesting(&intercept_hook);
 
   ui_test_utils::NavigateToURL(
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 612a68c7..baddca6 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -429,6 +429,8 @@
     "arc/app_shortcuts/arc_app_shortcuts_menu_builder.h",
     "arc/app_shortcuts/arc_app_shortcuts_request.cc",
     "arc/app_shortcuts/arc_app_shortcuts_request.h",
+    "arc/arc_app_id_provider_impl.cc",
+    "arc/arc_app_id_provider_impl.h",
     "arc/arc_migration_constants.h",
     "arc/arc_migration_guide_notification.cc",
     "arc/arc_migration_guide_notification.h",
@@ -1251,6 +1253,8 @@
     "login/quick_unlock/quick_unlock_utils.h",
     "login/reauth_stats.cc",
     "login/reauth_stats.h",
+    "login/saml/in_session_password_change_manager.cc",
+    "login/saml/in_session_password_change_manager.h",
     "login/saml/saml_offline_signin_limiter.cc",
     "login/saml/saml_offline_signin_limiter.h",
     "login/saml/saml_offline_signin_limiter_factory.cc",
@@ -2200,8 +2204,6 @@
   testonly = true
 
   sources = [
-    "accessibility/test_accessibility_focus_ring_controller.cc",
-    "accessibility/test_accessibility_focus_ring_controller.h",
     "android_sms/fake_android_sms_app_manager.cc",
     "android_sms/fake_android_sms_app_manager.h",
     "android_sms/fake_android_sms_app_setup_controller.cc",
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
index 34f8f2f3..237eeb3 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -13,8 +13,9 @@
 
 #include "ash/accessibility/accessibility_controller.h"
 #include "ash/public/cpp/accelerators.h"
+#include "ash/public/cpp/accessibility_focus_ring_controller.h"
+#include "ash/public/cpp/accessibility_focus_ring_info.h"
 #include "ash/public/cpp/ash_pref_names.h"
-#include "ash/public/interfaces/accessibility_focus_ring_controller.mojom.h"
 #include "ash/public/interfaces/constants.mojom.h"
 #include "ash/root_window_controller.h"
 #include "ash/shell.h"
@@ -327,12 +328,6 @@
       ->GetConnector()
       ->BindInterface(ash::mojom::kServiceName, &accessibility_controller_);
 
-  // Connect to ash's AccessibilityFocusRingController interface.
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->BindInterface(ash::mojom::kServiceName,
-                      &accessibility_focus_ring_controller_);
-
   // Connect to the media session service.
   content::ServiceManagerConnection::GetForProcess()
       ->GetConnector()
@@ -1526,17 +1521,18 @@
   focus_ring_names_for_extension_id_.erase(extension_id);
 }
 
-void AccessibilityManager::SetFocusRing(std::string focus_ring_id,
-                                        ash::mojom::FocusRingPtr focus_ring) {
-  accessibility_focus_ring_controller_->SetFocusRing(focus_ring_id,
-                                                     std::move(focus_ring));
+void AccessibilityManager::SetFocusRing(
+    std::string focus_ring_id,
+    std::unique_ptr<ash::AccessibilityFocusRingInfo> focus_ring) {
+  ash::AccessibilityFocusRingController::Get()->SetFocusRing(
+      focus_ring_id, std::move(focus_ring));
 
   if (focus_ring_observer_for_test_)
     focus_ring_observer_for_test_.Run();
 }
 
 void AccessibilityManager::HideFocusRing(std::string focus_ring_id) {
-  accessibility_focus_ring_controller_->HideFocusRing(focus_ring_id);
+  ash::AccessibilityFocusRingController::Get()->HideFocusRing(focus_ring_id);
   if (focus_ring_observer_for_test_)
     focus_ring_observer_for_test_.Run();
 }
@@ -1544,11 +1540,12 @@
 void AccessibilityManager::SetHighlights(
     const std::vector<gfx::Rect>& rects_in_screen,
     SkColor color) {
-  accessibility_focus_ring_controller_->SetHighlights(rects_in_screen, color);
+  ash::AccessibilityFocusRingController::Get()->SetHighlights(rects_in_screen,
+                                                              color);
 }
 
 void AccessibilityManager::HideHighlights() {
-  accessibility_focus_ring_controller_->HideHighlights();
+  ash::AccessibilityFocusRingController::Get()->HideHighlights();
 }
 
 void AccessibilityManager::SetCaretBounds(const gfx::Rect& bounds_in_screen) {
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.h b/chrome/browser/chromeos/accessibility/accessibility_manager.h
index 52fb13b3..42523c45 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.h
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.h
@@ -12,7 +12,6 @@
 #include <vector>
 
 #include "ash/public/interfaces/accessibility_controller.mojom.h"
-#include "ash/public/interfaces/accessibility_focus_ring_controller.mojom.h"
 #include "base/callback_forward.h"
 #include "base/callback_list.h"
 #include "base/macros.h"
@@ -37,6 +36,10 @@
 class Profile;
 class SwitchAccessEventHandlerDelegate;
 
+namespace ash {
+struct AccessibilityFocusRingInfo;
+}  // namespace ash
+
 namespace gfx {
 class Rect;
 }  // namespace gfx
@@ -291,8 +294,9 @@
   bool ToggleDictation();
 
   // Sets the focus ring with the given ID based on |focus_ring|.
-  void SetFocusRing(std::string focus_ring_id,
-                    ash::mojom::FocusRingPtr focus_ring);
+  void SetFocusRing(
+      std::string focus_ring_id,
+      std::unique_ptr<ash::AccessibilityFocusRingInfo> focus_ring);
 
   // Hides focus ring on screen.
   void HideFocusRing(std::string caller_id);
@@ -465,11 +469,6 @@
   // Ash's mojom::AccessibilityController used to request Ash's a11y feature.
   ash::mojom::AccessibilityControllerPtr accessibility_controller_;
 
-  // Ash's mojom::AccessibilityFocusRingController used to request Ash's a11y
-  // focus ring feature.
-  ash::mojom::AccessibilityFocusRingControllerPtr
-      accessibility_focus_ring_controller_;
-
   std::map<std::string, std::set<std::string>>
       focus_ring_names_for_extension_id_;
 
diff --git a/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc b/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc
index 0b8f9dd..78cc880c 100644
--- a/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc
+++ b/chrome/browser/chromeos/accessibility/select_to_speak_browsertest.cc
@@ -5,7 +5,7 @@
 #include <memory>
 #include <vector>
 
-#include "ash/accessibility/accessibility_focus_ring_controller.h"
+#include "ash/accessibility/accessibility_focus_ring_controller_impl.h"
 #include "ash/accessibility/accessibility_focus_ring_layer.h"
 #include "ash/public/cpp/ash_features.h"
 #include "ash/public/interfaces/constants.mojom.h"
@@ -335,7 +335,7 @@
       chromeos::AccessibilityManager::Get()->GetFocusRingId(
           extension_misc::kSelectToSpeakExtensionId, "");
 
-  ash::AccessibilityFocusRingController* controller =
+  ash::AccessibilityFocusRingControllerImpl* controller =
       ash::Shell::Get()->accessibility_focus_ring_controller();
   controller->SetNoFadeForTesting();
   const ash::AccessibilityFocusRingGroup* focus_ring_group =
diff --git a/chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.cc b/chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.cc
deleted file mode 100644
index 048efda..0000000
--- a/chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.h"
-
-#include <utility>
-
-#include "ash/public/interfaces/constants.mojom.h"
-#include "content/public/common/service_manager_connection.h"
-#include "services/service_manager/public/cpp/connector.h"
-#include "services/service_manager/public/cpp/service_filter.h"
-
-TestAccessibilityFocusRingController::TestAccessibilityFocusRingController() {
-  CHECK(content::ServiceManagerConnection::GetForProcess())
-      << "ServiceManager is uninitialized. Did you forget to create a "
-         "content::TestServiceManagerContext?";
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->OverrideBinderForTesting(
-          service_manager::ServiceFilter::ByName(ash::mojom::kServiceName),
-          ash::mojom::AccessibilityFocusRingController::Name_,
-          base::BindRepeating(&TestAccessibilityFocusRingController::Bind,
-                              base::Unretained(this)));
-}
-
-TestAccessibilityFocusRingController::~TestAccessibilityFocusRingController() {
-  content::ServiceManagerConnection::GetForProcess()
-      ->GetConnector()
-      ->ClearBinderOverrideForTesting(
-          service_manager::ServiceFilter::ByName(ash::mojom::kServiceName),
-          ash::mojom::AccessibilityFocusRingController::Name_);
-}
-
-void TestAccessibilityFocusRingController::SetFocusRing(
-    const std::string& focus_ring_id,
-    ash::mojom::FocusRingPtr focus_ring) {}
-
-void TestAccessibilityFocusRingController::HideFocusRing(
-    const std::string& focus_ring_id) {}
-
-void TestAccessibilityFocusRingController::SetHighlights(
-    const std::vector<gfx::Rect>& rects_in_screen,
-    uint32_t skcolor) {}
-
-void TestAccessibilityFocusRingController::HideHighlights() {}
-
-void TestAccessibilityFocusRingController::Bind(
-    mojo::ScopedMessagePipeHandle handle) {
-  binding_.Bind(
-      ash::mojom::AccessibilityFocusRingControllerRequest(std::move(handle)));
-}
-
diff --git a/chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.h b/chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.h
deleted file mode 100644
index 9908beb..0000000
--- a/chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_TEST_ACCESSIBILITY_FOCUS_RING_CONTROLLER_H_
-#define CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_TEST_ACCESSIBILITY_FOCUS_RING_CONTROLLER_H_
-
-#include <string>
-#include <vector>
-
-#include "ash/public/interfaces/accessibility_focus_ring_controller.mojom.h"
-#include "base/macros.h"
-#include "mojo/public/cpp/bindings/binding.h"
-
-// Test implementation of ash's mojo AccessibilityFocusRingController interface.
-//
-// Registers itself to ServiceManager on construction and deregisters
-// on destruction.
-//
-// Note: A ServiceManagerConnection must be initialized before constructing this
-// object. Consider using content::TestServiceManagerContext on your tests.
-class TestAccessibilityFocusRingController
-    : public ash::mojom::AccessibilityFocusRingController {
- public:
-  TestAccessibilityFocusRingController();
-  ~TestAccessibilityFocusRingController() override;
-
-  // ash::mojom::AccessibilityFocusRingController:
-  void SetFocusRing(const std::string& focus_ring_id,
-                    ash::mojom::FocusRingPtr focus_ring) override;
-  void HideFocusRing(const std::string& focus_ring_id) override;
-  void SetHighlights(const std::vector<gfx::Rect>& rects_in_screen,
-                     uint32_t skcolor) override;
-  void HideHighlights() override;
-
- private:
-  void Bind(mojo::ScopedMessagePipeHandle handle);
-  mojo::Binding<ash::mojom::AccessibilityFocusRingController> binding_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(TestAccessibilityFocusRingController);
-};
-
-#endif  // CHROME_BROWSER_CHROMEOS_ACCESSIBILITY_TEST_ACCESSIBILITY_FOCUS_RING_CONTROLLER_H_
diff --git a/chrome/browser/chromeos/arc/arc_app_id_provider_impl.cc b/chrome/browser/chromeos/arc/arc_app_id_provider_impl.cc
new file mode 100644
index 0000000..caf9ae44
--- /dev/null
+++ b/chrome/browser/chromeos/arc/arc_app_id_provider_impl.cc
@@ -0,0 +1,22 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/arc/arc_app_id_provider_impl.h"
+
+#include "chrome/browser/chromeos/arc/arc_session_manager.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
+
+namespace arc {
+
+ArcAppIdProviderImpl::ArcAppIdProviderImpl() = default;
+ArcAppIdProviderImpl::~ArcAppIdProviderImpl() = default;
+
+std::string ArcAppIdProviderImpl::GetAppIdByPackageName(
+    const std::string& package_name) {
+  return ArcAppListPrefs::Get(ArcSessionManager::Get()->profile())
+      ->GetAppIdByPackageName(package_name);
+}
+
+}  // namespace arc
diff --git a/chrome/browser/chromeos/arc/arc_app_id_provider_impl.h b/chrome/browser/chromeos/arc/arc_app_id_provider_impl.h
new file mode 100644
index 0000000..83bc450
--- /dev/null
+++ b/chrome/browser/chromeos/arc/arc_app_id_provider_impl.h
@@ -0,0 +1,27 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_ARC_ARC_APP_ID_PROVIDER_IMPL_H_
+#define CHROME_BROWSER_CHROMEOS_ARC_ARC_APP_ID_PROVIDER_IMPL_H_
+
+#include "ash/public/cpp/arc_app_id_provider.h"
+#include "base/macros.h"
+
+namespace arc {
+
+class ArcAppIdProviderImpl : public ash::ArcAppIdProvider {
+ public:
+  ArcAppIdProviderImpl();
+  ~ArcAppIdProviderImpl() override;
+
+  // ash::ArcAppIdProvider:
+  std::string GetAppIdByPackageName(const std::string& package_name) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ArcAppIdProviderImpl);
+};
+
+}  // namespace arc
+
+#endif  // CHROME_BROWSER_CHROMEOS_ARC_ARC_APP_ID_PROVIDER_IMPL_H_
diff --git a/chrome/browser/chromeos/arc/arc_session_manager.cc b/chrome/browser/chromeos/arc/arc_session_manager.cc
index be61dc3..a326ee0 100644
--- a/chrome/browser/chromeos/arc/arc_session_manager.cc
+++ b/chrome/browser/chromeos/arc/arc_session_manager.cc
@@ -30,6 +30,7 @@
 #include "chrome/browser/policy/profile_policy_connector.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_launcher.h"
+#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
 #include "chrome/browser/ui/app_list/arc/arc_fast_app_reinstall_starter.h"
 #include "chrome/browser/ui/app_list/arc/arc_pai_starter.h"
diff --git a/chrome/browser/chromeos/arc/arc_session_manager.h b/chrome/browser/chromeos/arc/arc_session_manager.h
index 0ef6c4a..549c6c9 100644
--- a/chrome/browser/chromeos/arc/arc_session_manager.h
+++ b/chrome/browser/chromeos/arc/arc_session_manager.h
@@ -12,6 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/timer/timer.h"
+#include "chrome/browser/chromeos/arc/arc_app_id_provider_impl.h"
 #include "chrome/browser/chromeos/arc/arc_support_host.h"
 #include "chrome/browser/chromeos/policy/android_management_client.h"
 #include "chromeos/dbus/session_manager/session_manager_client.h"
@@ -381,6 +382,8 @@
   base::Time arc_start_time_;
   base::Closure attempt_user_exit_callback_;
 
+  ArcAppIdProviderImpl app_id_provider_;
+
   // Must be the last member.
   base::WeakPtrFactory<ArcSessionManager> weak_ptr_factory_;
 
diff --git a/chrome/browser/chromeos/assistant/assistant_util.cc b/chrome/browser/chromeos/assistant/assistant_util.cc
index 6a5e9ee7..c570a712 100644
--- a/chrome/browser/chromeos/assistant/assistant_util.cc
+++ b/chrome/browser/chromeos/assistant/assistant_util.cc
@@ -6,6 +6,7 @@
 
 #include <string>
 
+#include "ash/public/cpp/ash_pref_names.h"
 #include "ash/public/interfaces/voice_interaction_controller.mojom-shared.h"
 #include "chrome/browser/chromeos/login/demo_mode/demo_session.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
@@ -88,6 +89,9 @@
   if (prefs->GetBoolean(::assistant::prefs::kAssistantDisabledByPolicy))
     return ash::mojom::AssistantAllowedState::DISALLOWED_BY_POLICY;
 
+  if (prefs->GetBoolean(ash::prefs::kKioskNextShellEnabled))
+    return ash::mojom::AssistantAllowedState::DISALLOWED_BY_KIOSK_NEXT;
+
   // Bypass the account type check when using fake gaia login, e.g. in Tast
   // tests, or the account is logged in a device with a physical Assistant key
   // on keyboard.
diff --git a/chrome/browser/chromeos/assistant/assistant_util_unittest.cc b/chrome/browser/chromeos/assistant/assistant_util_unittest.cc
index 89f9a2e..3c8a1573 100644
--- a/chrome/browser/chromeos/assistant/assistant_util_unittest.cc
+++ b/chrome/browser/chromeos/assistant/assistant_util_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "ash/public/cpp/ash_pref_names.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/test/scoped_command_line.h"
 #include "base/test/scoped_feature_list.h"
@@ -272,4 +273,14 @@
             IsAssistantAllowedForProfile(profile()));
 }
 
+TEST_F(ChromeAssistantUtilTest, IsAssistantAllowedForKioskNext) {
+  ScopedLogIn login(GetFakeUserManager(),
+                    AccountId::FromUserEmailGaiaId(
+                        profile()->GetProfileUserName(), kTestGaiaId));
+  profile()->GetPrefs()->SetBoolean(ash::prefs::kKioskNextShellEnabled, true);
+
+  EXPECT_EQ(ash::mojom::AssistantAllowedState::DISALLOWED_BY_KIOSK_NEXT,
+            IsAssistantAllowedForProfile(profile()));
+}
+
 }  // namespace assistant
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
index 6da2702..937d6b4 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -13,7 +13,6 @@
 #include "ash/public/cpp/shelf_item.h"
 #include "ash/public/cpp/shelf_prefs.h"
 #include "ash/public/cpp/tablet_mode.h"
-#include "ash/public/interfaces/ash_message_center_controller.mojom.h"
 #include "ash/public/interfaces/constants.mojom.h"
 #include "ash/shell.h"
 #include "base/base64.h"
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
index 0d348ab..8f7693a 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.h
@@ -11,7 +11,6 @@
 
 #include "ash/public/cpp/assistant/assistant_state_proxy.h"
 #include "ash/public/cpp/assistant/default_voice_interaction_observer.h"
-#include "ash/public/interfaces/ash_message_center_controller.mojom.h"
 #include "base/compiler_specific.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/chromeos/printing/cups_printers_manager.h"
@@ -194,8 +193,6 @@
  private:
   ~AutotestPrivateGetVisibleNotificationsFunction() override;
   ResponseAction Run() override;
-
-  ash::mojom::AshMessageCenterControllerPtr controller_;
 };
 
 class AutotestPrivateGetPlayStoreStateFunction
diff --git a/chrome/browser/chromeos/first_run/drive_first_run_controller.cc b/chrome/browser/chromeos/first_run/drive_first_run_controller.cc
index ca4b4c2..c64a3c1 100644
--- a/chrome/browser/chromeos/first_run/drive_first_run_controller.cc
+++ b/chrome/browser/chromeos/first_run/drive_first_run_controller.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/chromeos/first_run/drive_first_run_controller.h"
 
 #include <stdint.h>
+
 #include <utility>
 
 #include "base/bind.h"
@@ -19,6 +20,7 @@
 #include "chrome/browser/background/background_contents.h"
 #include "chrome/browser/background/background_contents_service.h"
 #include "chrome/browser/background/background_contents_service_factory.h"
+#include "chrome/browser/background/background_contents_service_observer.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
 #include "chrome/browser/extensions/extension_service.h"
@@ -31,11 +33,6 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_handle.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
-#include "content/public/browser/notification_source.h"
-#include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/web_contents.h"
@@ -86,7 +83,7 @@
 // files for offline use.
 class DriveWebContentsManager : public content::WebContentsObserver,
                                 public content::WebContentsDelegate,
-                                public content::NotificationObserver {
+                                public BackgroundContentsServiceObserver {
  public:
   typedef base::Callback<
       void(bool, DriveFirstRunController::UMAOutcome)> CompletionCallback;
@@ -138,19 +135,17 @@
       const std::string& partition_id,
       content::SessionStorageNamespace* session_storage_namespace) override;
 
-  // content::NotificationObserver overrides:
-  void Observe(int type,
-               const content::NotificationSource& source,
-               const content::NotificationDetails& details) override;
+  // BackgroundContentsServiceObserver:
+  void OnBackgroundContentsOpened(
+      const BackgroundContentsOpenedDetails& details) override;
 
   Profile* profile_;
   const std::string app_id_;
   const std::string endpoint_url_;
   std::unique_ptr<content::WebContents> web_contents_;
-  content::NotificationRegistrar registrar_;
-  bool started_;
+  bool started_ = false;
   CompletionCallback completion_callback_;
-  base::WeakPtrFactory<DriveWebContentsManager> weak_ptr_factory_;
+  base::WeakPtrFactory<DriveWebContentsManager> weak_ptr_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(DriveWebContentsManager);
 };
@@ -163,15 +158,14 @@
     : profile_(profile),
       app_id_(app_id),
       endpoint_url_(endpoint_url),
-      started_(false),
-      completion_callback_(completion_callback),
-      weak_ptr_factory_(this) {
+      completion_callback_(completion_callback) {
   DCHECK(!completion_callback_.is_null());
-  registrar_.Add(this, chrome::NOTIFICATION_BACKGROUND_CONTENTS_OPENED,
-                 content::Source<Profile>(profile_));
+  BackgroundContentsServiceFactory::GetForProfile(profile)->AddObserver(this);
 }
 
 DriveWebContentsManager::~DriveWebContentsManager() {
+  BackgroundContentsServiceFactory::GetForProfile(profile_)->RemoveObserver(
+      this);
 }
 
 void DriveWebContentsManager::StartLoad() {
@@ -290,15 +284,9 @@
   return false;
 }
 
-void DriveWebContentsManager::Observe(
-    int type,
-    const content::NotificationSource& source,
-    const content::NotificationDetails& details) {
-  DCHECK_EQ(chrome::NOTIFICATION_BACKGROUND_CONTENTS_OPENED, type);
-  const std::string& app_id =
-      content::Details<BackgroundContentsOpenedDetails>(details)
-          ->application_id;
-  if (app_id == app_id_)
+void DriveWebContentsManager::OnBackgroundContentsOpened(
+    const BackgroundContentsOpenedDetails& details) {
+  if (details.application_id == app_id_)
     OnOfflineInit(true, DriveFirstRunController::OUTCOME_OFFLINE_ENABLED);
 }
 
diff --git a/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc b/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc
index cb86068..7fd22443 100644
--- a/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc
+++ b/chrome/browser/chromeos/login/enterprise_enrollment_browsertest.cc
@@ -707,7 +707,7 @@
   test::OobeJS().TapOnPath({kEnrollmentUI, kAdDialog, kSkipButton});
   CheckActiveDirectoryCredentialsShown();
   CheckConfigurationSelectionVisible(false);
-  test::OobeJS().TapOnPath({kEnrollmentUI, kAdDialog, kAdBackToUnlockButton});
+  test::OobeJS().ClickOnPath({kEnrollmentUI, kAdDialog, kAdBackToUnlockButton});
   CheckActiveDirectoryUnlockConfigurationShown();
 
   // Enter wrong unlock password.
diff --git a/chrome/browser/chromeos/login/lock/screen_locker_unittest.cc b/chrome/browser/chromeos/login/lock/screen_locker_unittest.cc
index 4a918bf..5f25041 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker_unittest.cc
+++ b/chrome/browser/chromeos/login/lock/screen_locker_unittest.cc
@@ -11,7 +11,6 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
-#include "chrome/browser/chromeos/accessibility/test_accessibility_focus_ring_controller.h"
 #include "chrome/browser/chromeos/input_method/mock_input_method_manager_impl.h"
 #include "chrome/browser/chromeos/lock_screen_apps/state_controller.h"
 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
@@ -130,8 +129,6 @@
   // ScreenLocker dependencies:
   // * AccessibilityManager dependencies:
   FakeAccessibilityController fake_accessibility_controller_;
-  TestAccessibilityFocusRingController
-      test_accessibility_focus_ring_controller_;
   // * LoginScreenClient dependencies:
   session_manager::SessionManager session_manager_;
   TestLoginScreen test_login_screen_;
diff --git a/chrome/browser/chromeos/login/saml/in_session_password_change_manager.cc b/chrome/browser/chromeos/login/saml/in_session_password_change_manager.cc
new file mode 100644
index 0000000..47b3e4a
--- /dev/null
+++ b/chrome/browser/chromeos/login/saml/in_session_password_change_manager.cc
@@ -0,0 +1,69 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/saml/in_session_password_change_manager.h"
+
+#include "chrome/browser/chromeos/login/auth/chrome_cryptohome_authenticator.h"
+#include "chrome/browser/chromeos/login/saml/saml_password_expiry_notification.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/pref_names.h"
+#include "chromeos/login/auth/user_context.h"
+#include "components/prefs/pref_service.h"
+#include "components/user_manager/user_manager.h"
+
+namespace chromeos {
+
+// static
+std::unique_ptr<InSessionPasswordChangeManager>
+InSessionPasswordChangeManager::CreateIfEnabled(
+    Profile* primary_profile,
+    const user_manager::User* primary_user) {
+  if (primary_profile->GetPrefs()->GetBoolean(
+          prefs::kSamlInSessionPasswordChangeEnabled)) {
+    return std::make_unique<InSessionPasswordChangeManager>(primary_profile,
+                                                            primary_user);
+  }
+  return nullptr;
+}
+
+InSessionPasswordChangeManager::InSessionPasswordChangeManager(
+    Profile* primary_profile,
+    const user_manager::User* primary_user)
+    : primary_profile_(primary_profile),
+      primary_user_(primary_user),
+      authenticator_(new ChromeCryptohomeAuthenticator(this)) {}
+
+InSessionPasswordChangeManager::~InSessionPasswordChangeManager() {}
+
+void InSessionPasswordChangeManager::ChangePassword(
+    const std::string& old_password,
+    const std::string& new_password) {
+  UserContext user_context(*primary_user_);
+  user_context.SetKey(Key(new_password));
+  authenticator_->MigrateKey(user_context, old_password);
+}
+
+void InSessionPasswordChangeManager::OnAuthSuccess(
+    const UserContext& user_context) {
+  VLOG(3) << "Cryptohome password is changed.";
+  user_manager::UserManager::Get()->SaveForceOnlineSignin(
+      user_context.GetAccountId(), false);
+
+  // Clear expiration time from prefs so that we don't keep nagging the user to
+  // change password (until the SAML provider tells us a new expiration time).
+  SamlPasswordAttributes loaded =
+      SamlPasswordAttributes::LoadFromPrefs(primary_profile_->GetPrefs());
+  SamlPasswordAttributes(
+      /*modified_time=*/base::Time::Now(), /*expiration_time=*/base::Time(),
+      loaded.password_change_url())
+      .SaveToPrefs(primary_profile_->GetPrefs());
+  DismissSamlPasswordExpiryNotification(primary_profile_);
+}
+
+void InSessionPasswordChangeManager::OnAuthFailure(const AuthFailure& error) {
+  // TODO(https://crbug.com/930109): Ask user for the old password.
+  VLOG(1) << "Failed to change cryptohome password: " << error.GetErrorString();
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/saml/in_session_password_change_manager.h b/chrome/browser/chromeos/login/saml/in_session_password_change_manager.h
new file mode 100644
index 0000000..1adfc22
--- /dev/null
+++ b/chrome/browser/chromeos/login/saml/in_session_password_change_manager.h
@@ -0,0 +1,56 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SAML_IN_SESSION_PASSWORD_CHANGE_MANAGER_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_SAML_IN_SESSION_PASSWORD_CHANGE_MANAGER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/memory/scoped_refptr.h"
+#include "chromeos/login/auth/auth_status_consumer.h"
+
+class Profile;
+
+namespace user_manager {
+class User;
+}
+
+namespace chromeos {
+class CryptohomeAuthenticator;
+class UserContext;
+
+// Manages the flow of changing a password in-session - handles user
+// response from dialogs, and callbacks from subsystems.
+class InSessionPasswordChangeManager : public AuthStatusConsumer {
+ public:
+  // Returns null if in-session password change is disabled.
+  static std::unique_ptr<InSessionPasswordChangeManager> CreateIfEnabled(
+      Profile* primary_profile,
+      const user_manager::User* primary_user);
+
+  InSessionPasswordChangeManager(Profile* primary_profile,
+                                 const user_manager::User* primary_user);
+  ~InSessionPasswordChangeManager() override;
+
+  // Change cryptohome password for primary user.
+  void ChangePassword(const std::string& old_password,
+                      const std::string& new_password);
+
+  // AuthStatusConsumer:
+  void OnAuthFailure(const AuthFailure& error) override;
+  void OnAuthSuccess(const UserContext& user_context) override;
+
+ private:
+  Profile* primary_profile_;
+  const user_manager::User* primary_user_;
+
+  scoped_refptr<CryptohomeAuthenticator> authenticator_;
+
+  DISALLOW_COPY_AND_ASSIGN(InSessionPasswordChangeManager);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_SAML_IN_SESSION_PASSWORD_CHANGE_MANAGER_H_
diff --git a/chrome/browser/chromeos/login/saml/saml_browsertest.cc b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
index 810b400..7e01123 100644
--- a/chrome/browser/chromeos/login/saml/saml_browsertest.cc
+++ b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
@@ -497,7 +497,7 @@
   content::ExecuteScriptAsync(
       GetLoginUI()->GetWebContents(),
       test::GetOobeElementPath({"gaia-signin", "signin-back-button"}) +
-          ".fire('tap');");
+          ".fire('click');");
 
   // Auth flow should change back to Gaia.
   std::string message;
diff --git a/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc
index 4c16261..e1a78cd 100644
--- a/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc
@@ -638,7 +638,7 @@
       {"oobe-update-md", "checking-for-updates-dialog"});
   test::OobeJS().ExpectHiddenPath({"oobe-update-md", "updating-dialog"});
 
-  test::OobeJS().TapOnPath({"oobe-update-md", "cellular-permission-back"});
+  test::OobeJS().ClickOnPath({"oobe-update-md", "cellular-permission-back"});
 
   WaitForScreenResult();
   EXPECT_EQ(UpdateScreen::Result::UPDATE_ERROR, last_screen_result_.value());
diff --git a/chrome/browser/chromeos/login/webview_login_browsertest.cc b/chrome/browser/chromeos/login/webview_login_browsertest.cc
index 6753eb2..1745861 100644
--- a/chrome/browser/chromeos/login/webview_login_browsertest.cc
+++ b/chrome/browser/chromeos/login/webview_login_browsertest.cc
@@ -277,7 +277,7 @@
   ExpectPasswordPage();
 
   // Click back to identifier page.
-  test::OobeJS().TapOnPath({"gaia-signin", "signin-back-button"});
+  test::OobeJS().ClickOnPath({"gaia-signin", "signin-back-button"});
   WaitForGaiaPageBackButtonUpdate();
   ExpectIdentifierPage();
   // Click next to password page, user id is remembered.
@@ -351,7 +351,7 @@
 
   // Press the back button at a sign-in screen without pre-existing users to
   // start a new sign-in attempt.
-  test::OobeJS().TapOnPath({"gaia-signin", "signin-back-button"});
+  test::OobeJS().ClickOnPath({"gaia-signin", "signin-back-button"});
   WaitForGaiaPageBackButtonUpdate();
   // Expect that we got back to the identifier page, as there are no known users
   // so the sign-in screen will not display user pods.
@@ -1022,7 +1022,7 @@
   // start a new sign-in attempt.
   // This will re-load gaia, rotating the StoragePartition. The new
   // StoragePartition must also have the proxy auth details.
-  test::OobeJS().TapOnPath({"gaia-signin", "signin-back-button"});
+  test::OobeJS().ClickOnPath({"gaia-signin", "signin-back-button"});
   WaitForGaiaPageBackButtonUpdate();
   // Expect that we got back to the identifier page, as there are no known users
   // so the sign-in screen will not display user pods.
diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc
index 858f432..e813e62 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate.cc
@@ -770,7 +770,7 @@
 }
 
 std::string
-ChromeDownloadManagerDelegate::ApplicationClientIdForFileScanning() const {
+ChromeDownloadManagerDelegate::ApplicationClientIdForFileScanning() {
   return std::string(chrome::kApplicationClientIDStringForAVScanning);
 }
 
diff --git a/chrome/browser/download/chrome_download_manager_delegate.h b/chrome/browser/download/chrome_download_manager_delegate.h
index 672eb50..8f63737 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.h
+++ b/chrome/browser/download/chrome_download_manager_delegate.h
@@ -117,7 +117,7 @@
   void CheckForFileExistence(
       download::DownloadItem* download,
       content::CheckForFileExistenceCallback callback) override;
-  std::string ApplicationClientIdForFileScanning() const override;
+  std::string ApplicationClientIdForFileScanning() override;
   void CheckDownloadAllowed(
       const content::ResourceRequestInfo::WebContentsGetter&
           web_contents_getter,
diff --git a/chrome/browser/extensions/app_background_page_apitest.cc b/chrome/browser/extensions/app_background_page_apitest.cc
index 4847583..5117c2a 100644
--- a/chrome/browser/extensions/app_background_page_apitest.cc
+++ b/chrome/browser/extensions/app_background_page_apitest.cc
@@ -5,6 +5,7 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/path_service.h"
+#include "base/scoped_observer.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread_restrictions.h"
@@ -12,6 +13,7 @@
 #include "build/build_config.h"
 #include "chrome/browser/background/background_contents_service.h"
 #include "chrome/browser/background/background_contents_service_factory.h"
+#include "chrome/browser/background/background_contents_service_observer.h"
 #include "chrome/browser/background/background_mode_manager.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -28,7 +30,6 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/test/browser_test_utils.h"
-#include "content/public/test/test_notification_tracker.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/process_manager.h"
 #include "extensions/common/extension.h"
@@ -49,6 +50,36 @@
 
 using extensions::Extension;
 
+namespace {
+
+class BackgroundContentsCreationObserver
+    : public BackgroundContentsServiceObserver {
+ public:
+  explicit BackgroundContentsCreationObserver(Profile* profile) {
+    observer_.Add(BackgroundContentsServiceFactory::GetForProfile(profile));
+  }
+
+  ~BackgroundContentsCreationObserver() override = default;
+
+  void OnBackgroundContentsOpened(
+      const BackgroundContentsOpenedDetails& details) override {
+    ++opens_;
+  }
+
+  int opens() const { return opens_; }
+
+ private:
+  // The number of background contents that have been opened since creation.
+  int opens_ = 0;
+
+  ScopedObserver<BackgroundContentsService, BackgroundContentsServiceObserver>
+      observer_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(BackgroundContentsCreationObserver);
+};
+
+}  // namespace
+
 class AppBackgroundPageApiTest : public extensions::ExtensionApiTest {
  public:
   void SetUpCommandLine(base::CommandLine* command_line) override {
@@ -84,12 +115,7 @@
     return true;
   }
 
-  bool WaitForBackgroundMode(bool expected_background_mode) {
-#if defined(OS_CHROMEOS)
-    // BackgroundMode is not supported on chromeos, so we should test the
-    // behavior of BackgroundContents, but not the background mode state itself.
-    return true;
-#else
+  bool VerifyBackgroundMode(bool expected_background_mode) {
     BackgroundModeManager* manager =
         g_browser_process->background_mode_manager();
     // If background mode is disabled on this platform (e.g. cros), then skip
@@ -98,17 +124,8 @@
       DLOG(WARNING) << "Skipping check - background mode disabled";
       return true;
     }
-    if (manager->IsBackgroundModeActive() == expected_background_mode)
-      return true;
 
-    // We are not currently in the expected state - wait for the state to
-    // change.
-    content::WindowedNotificationObserver watcher(
-        chrome::NOTIFICATION_BACKGROUND_MODE_CHANGED,
-        content::NotificationService::AllSources());
-    watcher.Wait();
     return manager->IsBackgroundModeActive() == expected_background_mode;
-#endif
   }
 
   void UnloadExtensionViaTask(const std::string& id) {
@@ -185,11 +202,11 @@
   ASSERT_TRUE(CreateApp(app_manifest, &app_dir));
   ASSERT_TRUE(LoadExtension(app_dir));
   // Background mode should not be active until a background page is created.
-  ASSERT_TRUE(WaitForBackgroundMode(false));
+  ASSERT_TRUE(VerifyBackgroundMode(false));
   ASSERT_TRUE(RunExtensionTest("app_background_page/basic")) << message_;
   // The test closes the background contents, so we should fall back to no
   // background mode at the end.
-  ASSERT_TRUE(WaitForBackgroundMode(false));
+  ASSERT_TRUE(VerifyBackgroundMode(false));
 }
 
 // Crashy, http://crbug.com/69215.
@@ -215,7 +232,7 @@
   ASSERT_TRUE(LoadExtension(app_dir));
   ASSERT_TRUE(RunExtensionTest("app_background_page/lacks_permission"))
       << message_;
-  ASSERT_TRUE(WaitForBackgroundMode(false));
+  ASSERT_TRUE(VerifyBackgroundMode(false));
 }
 
 IN_PROC_BROWSER_TEST_F(AppBackgroundPageApiTest, ManifestBackgroundPage) {
@@ -247,7 +264,7 @@
   ASSERT_TRUE(LoadExtension(app_dir));
   // Background mode be active now because a background page was created when
   // the app was loaded.
-  ASSERT_TRUE(WaitForBackgroundMode(true));
+  ASSERT_TRUE(VerifyBackgroundMode(true));
 
   // Verify that the background contents exist.
   const Extension* extension = GetSingleLoadedExtension();
@@ -275,13 +292,8 @@
   // happen when window.open creates a background page that switches
   // RenderViewHosts. See http://crbug.com/165138.
   chrome::ShowTaskManager(browser());
+  BackgroundContentsCreationObserver creation_observer(browser()->profile());
 
-  // Make sure that no BackgroundContentses get deleted (a signal that repeated
-  // window.open calls recreate instances, instead of being no-ops).
-  content::TestNotificationTracker background_deleted_tracker;
-  background_deleted_tracker.ListenFor(
-      chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED,
-      content::Source<Profile>(browser()->profile()));
   std::string app_manifest = base::StringPrintf(
       "{"
       "  \"name\": \"App\","
@@ -329,7 +341,9 @@
       &window_opener_null_in_js));
   EXPECT_TRUE(window_opener_null_in_js);
 
-  EXPECT_EQ(0u, background_deleted_tracker.size());
+  // Verify multiple BackgroundContents don't get opened despite multiple
+  // window.open calls.
+  EXPECT_EQ(1, creation_observer.opens());
   UnloadExtension(extension->id());
 }
 
@@ -507,10 +521,10 @@
       BackgroundContentsServiceFactory::GetForProfile(browser()->profile())
           ->GetAppBackgroundContents(extension->id()));
   // Background mode should not be active until a background page is created.
-  ASSERT_TRUE(WaitForBackgroundMode(false));
+  ASSERT_TRUE(VerifyBackgroundMode(false));
   ASSERT_TRUE(RunExtensionTest("app_background_page/basic_open")) << message_;
   // Background mode should be active now because a background page was created.
-  ASSERT_TRUE(WaitForBackgroundMode(true));
+  ASSERT_TRUE(VerifyBackgroundMode(true));
 
   // Verify that the background contents exist.
   BackgroundContents* background_contents =
@@ -534,7 +548,7 @@
   ASSERT_TRUE(RunExtensionTest("app_background_page/basic_close")) << message_;
 
   // Background mode should no longer be active.
-  ASSERT_TRUE(WaitForBackgroundMode(false));
+  ASSERT_TRUE(VerifyBackgroundMode(false));
   ASSERT_FALSE(
       BackgroundContentsServiceFactory::GetForProfile(browser()->profile())
           ->GetAppBackgroundContents(extension->id()));
@@ -569,7 +583,7 @@
   ASSERT_TRUE(LoadExtension(app_dir));
   // Background mode be active now because a background page was created when
   // the app was loaded.
-  ASSERT_TRUE(WaitForBackgroundMode(true));
+  ASSERT_TRUE(VerifyBackgroundMode(true));
 
   const Extension* extension = GetSingleLoadedExtension();
   ASSERT_TRUE(
@@ -584,7 +598,7 @@
   // cleanly (not crash).
   UnloadExtensionViaTask(extension->id());
   content::RunAllPendingInMessageLoop();
-  ASSERT_TRUE(WaitForBackgroundMode(false));
+  ASSERT_TRUE(VerifyBackgroundMode(false));
 }
 
 #if BUILDFLAG(ENABLE_NACL)
diff --git a/chrome/browser/extensions/background_xhr_browsertest.cc b/chrome/browser/extensions/background_xhr_browsertest.cc
index 41b2527..42dca06 100644
--- a/chrome/browser/extensions/background_xhr_browsertest.cc
+++ b/chrome/browser/extensions/background_xhr_browsertest.cc
@@ -8,6 +8,7 @@
 #include "base/json/json_reader.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/task/post_task.h"
 #include "base/test/scoped_feature_list.h"
@@ -159,19 +160,20 @@
     ASSERT_TRUE(embedded_test_server()->Start());
   }
 
-  bool CanFetch(const Extension* extension, const GURL& url) {
+  std::string ExecuteFetch(const Extension* extension, const GURL& url) {
     content::DOMMessageQueue message_queue;
     browsertest_util::ExecuteScriptInBackgroundPageNoWait(
         profile(), extension->id(),
-        base::StringPrintf("canFetch('%s');", url.spec().c_str()));
+        content::JsReplace("executeFetch($1);", url));
     std::string json;
     EXPECT_TRUE(message_queue.WaitForMessage(&json));
     base::JSONReader reader(base::JSON_ALLOW_TRAILING_COMMAS);
     std::unique_ptr<base::Value> value = reader.ReadToValueDeprecated(json);
     std::string result;
     EXPECT_TRUE(value->GetAsString(&result));
-    EXPECT_TRUE(result == "true" || result == "false") << result;
-    return result == "true";
+    std::string trimmed_result;
+    base::TrimWhitespaceASCII(result, base::TRIM_ALL, &trimmed_result);
+    return trimmed_result;
   }
 
   const Extension* LoadXhrExtension(const std::string& host) {
@@ -186,18 +188,12 @@
       "permissions": [")" + host + R"("]
     })");
     constexpr char kBackgroundScriptFile[] = R"(
-    function canFetch(url) {
+    function executeFetch(url) {
       console.warn('Fetching: ' + url);
-      fetch(url).then((response) => {
-        domAutomationController.send('true');
-      }).catch((e) => {
-        let message;
-        if (e.message == 'Failed to fetch')
-          message = 'false'
-        else
-          message = 'Unexpected Error: ' + e.message;
-        domAutomationController.send(message);
-      });
+      fetch(url)
+          .then(response => response.text())
+          .then(text => domAutomationController.send(text))
+          .catch(err => domAutomationController.send('ERROR: ' + err));
     }
     chrome.test.sendMessage('ready');)";
 
@@ -222,12 +218,14 @@
   GURL webstore_url_to_fetch = embedded_test_server()->GetURL(
       webstore_launch_url.host(), "/simple.html");
 
-  EXPECT_FALSE(CanFetch(extension, webstore_url_to_fetch));
+  EXPECT_EQ("ERROR: TypeError: Failed to fetch",
+            ExecuteFetch(extension, webstore_url_to_fetch));
 
   // Sanity check: the extension should be able to fetch google.com.
   GURL google_url =
       embedded_test_server()->GetURL("google.com", "/simple.html");
-  EXPECT_TRUE(CanFetch(extension, google_url));
+  EXPECT_THAT(ExecuteFetch(extension, google_url),
+              ::testing::HasSubstr("<head><title>OK</title></head>"));
 }
 
 // Extensions should not be able to XHR to the webstore regardless of policy.
@@ -244,12 +242,14 @@
   GURL webstore_url_to_fetch = embedded_test_server()->GetURL(
       webstore_launch_url.host(), "/simple.html");
 
-  EXPECT_FALSE(CanFetch(extension, webstore_url_to_fetch));
+  EXPECT_EQ("ERROR: TypeError: Failed to fetch",
+            ExecuteFetch(extension, webstore_url_to_fetch));
 
   // Sanity check: the extension should be able to fetch google.com.
   GURL google_url =
       embedded_test_server()->GetURL("google.com", "/simple.html");
-  EXPECT_TRUE(CanFetch(extension, google_url));
+  EXPECT_THAT(ExecuteFetch(extension, google_url),
+              ::testing::HasSubstr("<head><title>OK</title></head>"));
 }
 
 // Extensions should not be able to bypass same-origin despite declaring
@@ -266,12 +266,14 @@
   // Should block due to "runtime_blocked_hosts" section of policy.
   GURL protected_url_to_fetch =
       embedded_test_server()->GetURL("example.com", "/simple.html");
-  EXPECT_FALSE(CanFetch(extension, protected_url_to_fetch));
+  EXPECT_EQ("ERROR: TypeError: Failed to fetch",
+            ExecuteFetch(extension, protected_url_to_fetch));
 
   // Should allow due to "runtime_allowed_hosts" section of policy.
   GURL exempted_url_to_fetch =
       embedded_test_server()->GetURL("public.example.com", "/simple.html");
-  EXPECT_TRUE(CanFetch(extension, exempted_url_to_fetch));
+  EXPECT_THAT(ExecuteFetch(extension, exempted_url_to_fetch),
+              ::testing::HasSubstr("<head><title>OK</title></head>"));
 }
 
 // Verify that policy blocklists apply to XHRs done from injected scripts.
@@ -287,12 +289,12 @@
     })");
 
   constexpr char kBackgroundScript[] =
-      R"(function canFetch(url) {
+      R"(function executeFetch(url) {
            chrome.tabs.executeScript({code: `
              fetch("${url}")
              .then(response => response.text())
-             .then(text => domAutomationController.send('true'))
-             .catch(err => domAutomationController.send('false'));
+             .then(text => domAutomationController.send(text))
+             .catch(err => domAutomationController.send('ERROR: ' + err));
            `});
          }
       )";
@@ -308,14 +310,20 @@
   ui_test_utils::NavigateToURL(browser(), page_url);
   EXPECT_EQ(page_url, web_contents->GetMainFrame()->GetLastCommittedURL());
 
+  // Using "/non-corb.octet-stream" resource (instead of "/simple.html" as in
+  // most other tests here) because XHRs/fetches from content scripts are
+  // subject to CORB (which is already covered by
+  // CrossOriginReadBlockingExtensionTest) and we want to focus the test below
+  // on policy behavior (which should be independent from whether or not CORB
+  // blocks the response).
   GURL example_url =
-      embedded_test_server()->GetURL("example.com", "/simple.html");
-  GURL public_example_url =
-      embedded_test_server()->GetURL("public.example.com", "/simple.html");
+      embedded_test_server()->GetURL("example.com", "/non-corb.octet-stream");
+  GURL public_example_url = embedded_test_server()->GetURL(
+      "public.example.com", "/non-corb.octet-stream");
 
   // Sanity Check: Should be able to fetch cross origin.
-  EXPECT_TRUE(CanFetch(extension, example_url));
-  EXPECT_TRUE(CanFetch(extension, public_example_url));
+  EXPECT_EQ("octet-stream-body", ExecuteFetch(extension, example_url));
+  EXPECT_EQ("octet-stream-body", ExecuteFetch(extension, public_example_url));
 
   {
     ExtensionManagementPolicyUpdater pref(&policy_provider_);
@@ -324,8 +332,9 @@
   }
 
   // Policies apply to XHR from a content script.
-  EXPECT_FALSE(CanFetch(extension, example_url));
-  EXPECT_TRUE(CanFetch(extension, public_example_url));
+  EXPECT_EQ("ERROR: TypeError: Failed to fetch",
+            ExecuteFetch(extension, example_url));
+  EXPECT_EQ("octet-stream-body", ExecuteFetch(extension, public_example_url));
 }
 
 // Make sure the blocklist and allowlist update for both Default and Individual
@@ -339,8 +348,10 @@
       embedded_test_server()->GetURL("public.example.com", "/simple.html");
 
   // Sanity check: Without restrictions all fetches should work.
-  EXPECT_TRUE(CanFetch(extension, public_example_url));
-  EXPECT_TRUE(CanFetch(extension, example_url));
+  EXPECT_THAT(ExecuteFetch(extension, public_example_url),
+              ::testing::HasSubstr("<head><title>OK</title></head>"));
+  EXPECT_THAT(ExecuteFetch(extension, example_url),
+              ::testing::HasSubstr("<head><title>OK</title></head>"));
 
   {
     ExtensionManagementPolicyUpdater pref(&policy_provider_);
@@ -349,8 +360,10 @@
   }
 
   // Default policies propagate.
-  EXPECT_TRUE(CanFetch(extension, public_example_url));
-  EXPECT_FALSE(CanFetch(extension, example_url));
+  EXPECT_THAT(ExecuteFetch(extension, public_example_url),
+              ::testing::HasSubstr("<head><title>OK</title></head>"));
+  EXPECT_EQ("ERROR: TypeError: Failed to fetch",
+            ExecuteFetch(extension, example_url));
   {
     ExtensionManagementPolicyUpdater pref(&policy_provider_);
     pref.AddPolicyBlockedHost(extension->id(), "*://*.example2.com");
@@ -358,8 +371,10 @@
   }
 
   // Default policies overridden when individual scope policies applied.
-  EXPECT_TRUE(CanFetch(extension, public_example_url));
-  EXPECT_TRUE(CanFetch(extension, example_url));
+  EXPECT_THAT(ExecuteFetch(extension, public_example_url),
+              ::testing::HasSubstr("<head><title>OK</title></head>"));
+  EXPECT_THAT(ExecuteFetch(extension, example_url),
+              ::testing::HasSubstr("<head><title>OK</title></head>"));
 
   GURL example2_url =
       embedded_test_server()->GetURL("example2.com", "/simple.html");
@@ -367,8 +382,10 @@
       embedded_test_server()->GetURL("public.example2.com", "/simple.html");
 
   // Individual scope policies propagate.
-  EXPECT_TRUE(CanFetch(extension, public_example2_url));
-  EXPECT_FALSE(CanFetch(extension, example2_url));
+  EXPECT_THAT(ExecuteFetch(extension, public_example2_url),
+              ::testing::HasSubstr("<head><title>OK</title></head>"));
+  EXPECT_EQ("ERROR: TypeError: Failed to fetch",
+            ExecuteFetch(extension, example2_url));
 }
 
 // Make sure the allowlist entries added due to host permissions are removed
@@ -383,8 +400,10 @@
       embedded_test_server()->GetURL("public.example.com", "/simple.html");
 
   // Sanity check: Without restrictions only public.example.com should work.
-  EXPECT_TRUE(CanFetch(extension, public_example_url));
-  EXPECT_FALSE(CanFetch(extension, example_url));
+  EXPECT_THAT(ExecuteFetch(extension, public_example_url),
+              ::testing::HasSubstr("<head><title>OK</title></head>"));
+  EXPECT_EQ("ERROR: TypeError: Failed to fetch",
+            ExecuteFetch(extension, example_url));
 
   {
     ExtensionManagementPolicyUpdater pref(&policy_provider_);
@@ -392,8 +411,10 @@
   }
 
   // The blocklist of example.com overrides allowlist of public.example.com.
-  EXPECT_FALSE(CanFetch(extension, example_url));
-  EXPECT_FALSE(CanFetch(extension, public_example_url));
+  EXPECT_EQ("ERROR: TypeError: Failed to fetch",
+            ExecuteFetch(extension, example_url));
+  EXPECT_EQ("ERROR: TypeError: Failed to fetch",
+            ExecuteFetch(extension, public_example_url));
 }
 
 // Make sure the allowlist entries added due to host permissions are removed
@@ -408,8 +429,10 @@
       embedded_test_server()->GetURL("public.example.com", "/simple.html");
 
   // Sanity check: Without restrictions only public.example.com should work.
-  EXPECT_TRUE(CanFetch(extension, public_example_url));
-  EXPECT_FALSE(CanFetch(extension, example_url));
+  EXPECT_THAT(ExecuteFetch(extension, public_example_url),
+              ::testing::HasSubstr("<head><title>OK</title></head>"));
+  EXPECT_EQ("ERROR: TypeError: Failed to fetch",
+            ExecuteFetch(extension, example_url));
 
   {
     ExtensionManagementPolicyUpdater pref(&policy_provider_);
@@ -417,8 +440,10 @@
   }
 
   // The blocklist of example.com overrides allowlist of public.example.com.
-  EXPECT_FALSE(CanFetch(extension, example_url));
-  EXPECT_FALSE(CanFetch(extension, public_example_url));
+  EXPECT_EQ("ERROR: TypeError: Failed to fetch",
+            ExecuteFetch(extension, example_url));
+  EXPECT_EQ("ERROR: TypeError: Failed to fetch",
+            ExecuteFetch(extension, public_example_url));
 }
 
 IN_PROC_BROWSER_TEST_P(BackgroundXhrWebstoreTest, XHRAnyPortPermission) {
@@ -427,7 +452,8 @@
   GURL permitted_url_to_fetch =
       embedded_test_server()->GetURL("example.com", "/simple.html");
 
-  EXPECT_TRUE(CanFetch(extension, permitted_url_to_fetch));
+  EXPECT_THAT(ExecuteFetch(extension, permitted_url_to_fetch),
+              ::testing::HasSubstr("<head><title>OK</title></head>"));
 }
 
 IN_PROC_BROWSER_TEST_P(BackgroundXhrWebstoreTest,
@@ -439,7 +465,8 @@
   GURL permitted_url_to_fetch =
       embedded_test_server()->GetURL("example.com", "/simple.html");
 
-  EXPECT_TRUE(CanFetch(extension, permitted_url_to_fetch));
+  EXPECT_THAT(ExecuteFetch(extension, permitted_url_to_fetch),
+              ::testing::HasSubstr("<head><title>OK</title></head>"));
 }
 
 IN_PROC_BROWSER_TEST_P(BackgroundXhrWebstoreTest,
@@ -451,7 +478,8 @@
   GURL not_permitted_url_to_fetch =
       embedded_test_server()->GetURL("example.com", "/simple.html");
 
-  EXPECT_FALSE(CanFetch(extension, not_permitted_url_to_fetch));
+  EXPECT_EQ("ERROR: TypeError: Failed to fetch",
+            ExecuteFetch(extension, not_permitted_url_to_fetch));
 }
 
 INSTANTIATE_TEST_SUITE_P(WithoutAny,
diff --git a/chrome/browser/extensions/tab_helper_unittest.cc b/chrome/browser/extensions/tab_helper_unittest.cc
index f8031ac..cf86f48 100644
--- a/chrome/browser/extensions/tab_helper_unittest.cc
+++ b/chrome/browser/extensions/tab_helper_unittest.cc
@@ -25,7 +25,7 @@
   EXPECT_EQ(extension->id(), tab_helper->GetAppId());
   EXPECT_TRUE(tab_helper->is_app());
   service()->UnloadExtension(extension->id(),
-                             UnloadedExtensionReason::UNDEFINED);
+                             UnloadedExtensionReason::TERMINATE);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(ExtensionId(), tab_helper->GetAppId());
 }
diff --git a/chrome/browser/favicon/favicon_request_handler_factory.cc b/chrome/browser/favicon/favicon_request_handler_factory.cc
index 30c6775..46cb2d13 100644
--- a/chrome/browser/favicon/favicon_request_handler_factory.cc
+++ b/chrome/browser/favicon/favicon_request_handler_factory.cc
@@ -10,10 +10,26 @@
 #include "chrome/browser/favicon/large_icon_service_factory.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sync/session_sync_service_factory.h"
 #include "components/favicon/core/favicon_request_handler.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/sync_sessions/open_tabs_ui_delegate.h"
+#include "components/sync_sessions/session_sync_service.h"
 #include "content/public/browser/browser_context.h"
 
+namespace {
+
+scoped_refptr<base::RefCountedMemory> GetSyncedFaviconForPageUrl(
+    sync_sessions::SessionSyncService* session_sync_service,
+    const GURL& page_url) {
+  sync_sessions::OpenTabsUIDelegate* open_tabs =
+      session_sync_service->GetOpenTabsUIDelegate();
+  return open_tabs ? open_tabs->GetSyncedFaviconForPageURL(page_url.spec())
+                   : nullptr;
+}
+
+}  // namespace
+
 // static
 favicon::FaviconRequestHandler*
 FaviconRequestHandlerFactory::GetForBrowserContext(
@@ -33,6 +49,7 @@
           BrowserContextDependencyManager::GetInstance()) {
   DependsOn(FaviconServiceFactory::GetInstance());
   DependsOn(LargeIconServiceFactory::GetInstance());
+  DependsOn(SessionSyncServiceFactory::GetInstance());
 }
 
 FaviconRequestHandlerFactory::~FaviconRequestHandlerFactory() {}
@@ -46,6 +63,8 @@
     content::BrowserContext* context) const {
   Profile* profile = Profile::FromBrowserContext(context);
   return new favicon::FaviconRequestHandler(
+      base::BindRepeating(&GetSyncedFaviconForPageUrl,
+                          SessionSyncServiceFactory::GetForProfile(profile)),
       FaviconServiceFactory::GetForProfile(profile,
                                            ServiceAccessType::EXPLICIT_ACCESS),
       LargeIconServiceFactory::GetForBrowserContext(context));
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 226ebfa..8416b4cc 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -341,6 +341,11 @@
     "expiry_milestone": 76
   },
   {
+    "name": "bluetooth-aggressive-appearance-filter",
+    "owners": [ "hansberry" ],
+    "expiry_milestone": 80
+  },
+  {
     "name": "bypass-app-banner-engagement-checks",
     "owners": [ "dominickn" ],
     "expiry_milestone": 78
@@ -2692,11 +2697,26 @@
     "expiry_milestone": 78
   },
   {
+    "name": "shelf-dense-clamshell",
+    "owners": [ "manucornet", "mmourgos" ],
+    "expiry_milestone": 82
+  },
+  {
     "name": "shelf-hover-previews",
     "owners": [ "manucornet" ],
     "expiry_milestone": 77
   },
   {
+    "name": "shelf-new-ui",
+    "owners": [ "manucornet", "newcomer" ],
+    "expiry_milestone": 82
+  },
+  {
+    "name": "shelf-scrollable",
+    "owners": [ "andrewxu", "manucornet" ],
+    "expiry_milestone": 82
+  },
+  {
     "name": "shopping-assist",
     "owners": [ "yusufo", "donnd" ],
     // This is a shopping assistance experiment for Android.
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 34decc3..5116734 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1656,12 +1656,27 @@
     "Enables device registration with Sharing infrastructure. Required to use "
     "cross-device Sharing features.";
 
+const char kShelfDenseClamshellName[] =
+    "Show a smaller, denser shelf in laptop mode.";
+const char kShelfDenseClamshellDescription[] =
+    "Reduces the size of the shelf and its apps when in laptop mode.";
+
 const char kShelfHoverPreviewsName[] =
     "Show previews of running apps when hovering over the shelf.";
 const char kShelfHoverPreviewsDescription[] =
     "Shows previews of the open windows for a given running app when hovering "
     "over the shelf.";
 
+const char kShelfNewUiName[] = "Enable a new modular design for the shelf.";
+const char kShelfNewUiDescription[] =
+    "Shows a new modular design for the shelf where the various pieces are "
+    "separate and behave independently, especially in tablet mode.";
+
+const char kShelfScrollableName[] =
+    "Enable a scrollable list of apps on the shelf";
+const char kShelfScrollableDescription[] =
+    "Shows a list of applications that is scrollable by default on tablets.";
+
 const char kShowAndroidFilesInFilesAppName[] =
     "Show Android files in Files app";
 const char kShowAndroidFilesInFilesAppDescription[] =
@@ -2895,6 +2910,12 @@
     "increase the volume and the button that's closer to the bottom/left "
     "always decrease the volume.";
 
+const char kBluetoothAggressiveAppearanceFilterName[] =
+    "Aggressive Bluetooth device filtering";
+const char kBluetoothAggressiveAppearanceFilterDescription[] =
+    "Enables a more aggressive Bluetooth filter in the UI to hide devices that "
+    "likely cannot be connected to.";
+
 const char kBulkPrintersName[] = "Bulk Printers Policy";
 const char kBulkPrintersDescription[] = "Enables the new bulk printers policy";
 
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 69ef78d..81bb1b7 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -980,9 +980,18 @@
 extern const char kSharingDeviceRegistrationName[];
 extern const char kSharingDeviceRegistrationDescription[];
 
+extern const char kShelfDenseClamshellName[];
+extern const char kShelfDenseClamshellDescription[];
+
 extern const char kShelfHoverPreviewsName[];
 extern const char kShelfHoverPreviewsDescription[];
 
+extern const char kShelfNewUiName[];
+extern const char kShelfNewUiDescription[];
+
+extern const char kShelfScrollableName[];
+extern const char kShelfScrollableDescription[];
+
 extern const char kShowAndroidFilesInFilesAppName[];
 extern const char kShowAndroidFilesInFilesAppDescription[];
 
@@ -1722,6 +1731,9 @@
 extern const char kAshSwapSideVolumeButtonsForOrientationName[];
 extern const char kAshSwapSideVolumeButtonsForOrientationDescription[];
 
+extern const char kBluetoothAggressiveAppearanceFilterName[];
+extern const char kBluetoothAggressiveAppearanceFilterDescription[];
+
 extern const char kBulkPrintersName[];
 extern const char kBulkPrintersDescription[];
 
diff --git a/chrome/browser/lookalikes/lookalike_url_interstitial_page.cc b/chrome/browser/lookalikes/lookalike_url_interstitial_page.cc
index 1d034c55..21407c16 100644
--- a/chrome/browser/lookalikes/lookalike_url_interstitial_page.cc
+++ b/chrome/browser/lookalikes/lookalike_url_interstitial_page.cc
@@ -71,7 +71,7 @@
 }
 
 content::InterstitialPageDelegate::TypeID
-LookalikeUrlInterstitialPage::GetTypeForTesting() const {
+LookalikeUrlInterstitialPage::GetTypeForTesting() {
   return LookalikeUrlInterstitialPage::kTypeForTesting;
 }
 
diff --git a/chrome/browser/lookalikes/lookalike_url_interstitial_page.h b/chrome/browser/lookalikes/lookalike_url_interstitial_page.h
index c98b603e..4f4fd226 100644
--- a/chrome/browser/lookalikes/lookalike_url_interstitial_page.h
+++ b/chrome/browser/lookalikes/lookalike_url_interstitial_page.h
@@ -62,7 +62,7 @@
   ~LookalikeUrlInterstitialPage() override;
 
   // InterstitialPageDelegate method:
-  InterstitialPageDelegate::TypeID GetTypeForTesting() const override;
+  InterstitialPageDelegate::TypeID GetTypeForTesting() override;
 
   // Allow easier reporting of UKM when no interstitial is shown.
   static void RecordUkmEvent(ukm::SourceId source_id,
diff --git a/chrome/browser/media/offscreen_tab.cc b/chrome/browser/media/offscreen_tab.cc
index ecf4ec49..2ce550bc 100644
--- a/chrome/browser/media/offscreen_tab.cc
+++ b/chrome/browser/media/offscreen_tab.cc
@@ -300,7 +300,7 @@
   return false;
 }
 
-bool OffscreenTab::EmbedsFullscreenWidget() const {
+bool OffscreenTab::EmbedsFullscreenWidget() {
   // OffscreenTab will manage fullscreen widgets.
   return true;
 }
@@ -330,14 +330,13 @@
   non_fullscreen_size_ = gfx::Size();
 }
 
-bool OffscreenTab::IsFullscreenForTabOrPending(
-    const WebContents* contents) const {
+bool OffscreenTab::IsFullscreenForTabOrPending(const WebContents* contents) {
   DCHECK_EQ(offscreen_tab_web_contents_.get(), contents);
   return in_fullscreen_mode();
 }
 
 blink::WebDisplayMode OffscreenTab::GetDisplayMode(
-    const WebContents* contents) const {
+    const WebContents* contents) {
   DCHECK_EQ(offscreen_tab_web_contents_.get(), contents);
   return in_fullscreen_mode() ? blink::kWebDisplayModeFullscreen
                               : blink::kWebDisplayModeBrowser;
diff --git a/chrome/browser/media/offscreen_tab.h b/chrome/browser/media/offscreen_tab.h
index 32a62ef..9a8b9cc 100644
--- a/chrome/browser/media/offscreen_tab.h
+++ b/chrome/browser/media/offscreen_tab.h
@@ -114,16 +114,15 @@
       const GURL& target_url,
       const std::string& partition_id,
       content::SessionStorageNamespace* session_storage_namespace) final;
-  bool EmbedsFullscreenWidget() const final;
+  bool EmbedsFullscreenWidget() final;
   void EnterFullscreenModeForTab(
       content::WebContents* contents,
       const GURL& origin,
       const blink::WebFullscreenOptions& options) final;
   void ExitFullscreenModeForTab(content::WebContents* contents) final;
-  bool IsFullscreenForTabOrPending(
-      const content::WebContents* contents) const final;
+  bool IsFullscreenForTabOrPending(const content::WebContents* contents) final;
   blink::WebDisplayMode GetDisplayMode(
-      const content::WebContents* contents) const final;
+      const content::WebContents* contents) final;
   void RequestMediaAccessPermission(
       content::WebContents* contents,
       const content::MediaStreamRequest& request,
diff --git a/chrome/browser/media/webrtc/webrtc_browsertest.cc b/chrome/browser/media/webrtc/webrtc_browsertest.cc
index 8dbad7d..3e7d274d 100644
--- a/chrome/browser/media/webrtc/webrtc_browsertest.cc
+++ b/chrome/browser/media/webrtc/webrtc_browsertest.cc
@@ -15,6 +15,7 @@
 #include "content/public/common/buildflags.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/feature_h264_with_openh264_ffmpeg.h"
+#include "content/public/common/network_service_util.h"
 #include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/test/browser_test_utils.h"
@@ -256,6 +257,11 @@
 
 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
                        GetPeerToPeerConnectionsCountChangeFromNetworkService) {
+  // https://crbug.com/976186: Test fails when network service is in process.
+  // Network Service runs in-process only on Android.
+  if (content::IsInProcessNetworkService())
+    return;
+
   EXPECT_EQ(0u, GetPeerToPeerConnectionsCountChangeFromNetworkService());
 
   StartServerAndOpenTabs();
@@ -302,6 +308,27 @@
   SetupPeerconnectionWithLocalStream(left_tab_);
   SetupPeerconnectionWithLocalStream(right_tab_);
   NegotiateCall(left_tab_, right_tab_);
+
+  std::string ice_gatheringstate =
+      ExecuteJavascript("getLastGatheringState()", left_tab_);
+
+  EXPECT_EQ("complete", ice_gatheringstate);
+  DetectVideoAndHangUp();
+}
+
+IN_PROC_BROWSER_TEST_F(
+    MAYBE_WebRtcBrowserTest,
+    RunsAudioVideoWebRTCCallInTwoTabsEmitsGatheringStateChange_ConnectionCount) {
+  // https://crbug.com/976186: Test fails when network service is in process.
+  // Network Service runs in-process only on Android.
+  if (content::IsInProcessNetworkService())
+    return;
+
+  EXPECT_EQ(0u, GetPeerToPeerConnectionsCountChangeFromNetworkService());
+  StartServerAndOpenTabs();
+  SetupPeerconnectionWithLocalStream(left_tab_);
+  SetupPeerconnectionWithLocalStream(right_tab_);
+  NegotiateCall(left_tab_, right_tab_);
   EXPECT_EQ(2u, GetPeerToPeerConnectionsCountChangeFromNetworkService());
 
   std::string ice_gatheringstate =
diff --git a/chrome/browser/notifications/chrome_ash_message_center_client.cc b/chrome/browser/notifications/chrome_ash_message_center_client.cc
index 93e7231a..b304b9d 100644
--- a/chrome/browser/notifications/chrome_ash_message_center_client.cc
+++ b/chrome/browser/notifications/chrome_ash_message_center_client.cc
@@ -6,23 +6,18 @@
 
 #include "ash/public/cpp/notifier_metadata.h"
 #include "ash/public/cpp/notifier_settings_observer.h"
-#include "ash/public/interfaces/constants.mojom.h"
 #include "base/i18n/string_compare.h"
 #include "base/stl_util.h"
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/chromeos/arc/arc_session_manager.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/notifications/arc_application_notifier_controller.h"
 #include "chrome/browser/notifications/extension_notifier_controller.h"
 #include "chrome/browser/notifications/web_page_notifier_controller.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
 #include "chrome/browser/ui/settings_window_manager_chromeos.h"
 #include "chrome/common/webui_url_constants.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/notification_service.h"
-#include "content/public/common/service_manager_connection.h"
-#include "services/service_manager/public/cpp/connector.h"
 #include "ui/message_center/message_center.h"
 #include "ui/message_center/public/cpp/notifier_id.h"
 
@@ -108,22 +103,10 @@
 
 ChromeAshMessageCenterClient::ChromeAshMessageCenterClient(
     NotificationPlatformBridgeDelegate* delegate)
-    : delegate_(delegate), binding_(this) {
+    : delegate_(delegate) {
   DCHECK(!g_chrome_ash_message_center_client);
   g_chrome_ash_message_center_client = this;
 
-  // May be null in unit tests.
-  auto* connection = content::ServiceManagerConnection::GetForProcess();
-  if (connection) {
-    connection->GetConnector()->BindInterface(ash::mojom::kServiceName,
-                                              &controller_);
-
-    // Register this object as the client interface implementation.
-    ash::mojom::AshMessageCenterClientAssociatedPtrInfo ptr_info;
-    binding_.Bind(mojo::MakeRequest(&ptr_info));
-    controller_->SetClient(std::move(ptr_info));
-  }
-
   sources_.insert(
       std::make_pair(message_center::NotifierType::APPLICATION,
                      std::make_unique<ExtensionNotifierController>(this)));
@@ -203,14 +186,6 @@
   notifier_observers_.RemoveObserver(observer);
 }
 
-void ChromeAshMessageCenterClient::GetArcAppIdByPackageName(
-    const std::string& package_name,
-    GetArcAppIdByPackageNameCallback callback) {
-  std::move(callback).Run(
-      ArcAppListPrefs::Get(arc::ArcSessionManager::Get()->profile())
-          ->GetAppIdByPackageName(package_name));
-}
-
 void ChromeAshMessageCenterClient::OnIconImageUpdated(
     const NotifierId& notifier_id,
     const gfx::ImageSkia& image) {
@@ -225,25 +200,14 @@
     MessageCenter::Get()->RemoveNotificationsForNotifierId(notifier_id);
 }
 
-// static
-void ChromeAshMessageCenterClient::FlushForTesting() {
-  g_chrome_ash_message_center_client->binding_.FlushForTesting();
-}
-
 void ChromeAshMessageCenterClient::Observe(
     int type,
     const content::NotificationSource& source,
     const content::NotificationDetails& details) {
-  switch (type) {
-    case chrome::NOTIFICATION_PROFILE_ADDED: {
-      Profile* profile = GetProfileForNotifiers();
-      if (profile) {
-        GetNotifiers();
-        registrar_.RemoveAll();
-      }
-      break;
-    }
-    default:
-      NOTREACHED();
+  DCHECK_EQ(type, chrome::NOTIFICATION_PROFILE_ADDED);
+  Profile* profile = GetProfileForNotifiers();
+  if (profile) {
+    GetNotifiers();
+    registrar_.RemoveAll();
   }
 }
diff --git a/chrome/browser/notifications/chrome_ash_message_center_client.h b/chrome/browser/notifications/chrome_ash_message_center_client.h
index afdb52f..2fca655 100644
--- a/chrome/browser/notifications/chrome_ash_message_center_client.h
+++ b/chrome/browser/notifications/chrome_ash_message_center_client.h
@@ -6,14 +6,12 @@
 #define CHROME_BROWSER_NOTIFICATIONS_CHROME_ASH_MESSAGE_CENTER_CLIENT_H_
 
 #include "ash/public/cpp/notifier_settings_controller.h"
-#include "ash/public/interfaces/ash_message_center_controller.mojom.h"
+#include "base/observer_list.h"
 #include "chrome/browser/notifications/notification_platform_bridge.h"
 #include "chrome/browser/notifications/notification_platform_bridge_chromeos.h"
 #include "chrome/browser/notifications/notifier_controller.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
-#include "mojo/public/cpp/bindings/associated_binding.h"
-#include "ui/message_center/public/cpp/notifier_id.h"
 
 // This class serves as Chrome's AshMessageCenterClient, as well as the
 // NotificationPlatformBridge for ChromeOS. It dispatches notifications to Ash
@@ -21,7 +19,6 @@
 // NotifierControllers to provide notifier settings information to Ash (visible
 // in NotifierSettingsView).
 class ChromeAshMessageCenterClient : public ash::NotifierSettingsController,
-                                     public ash::mojom::AshMessageCenterClient,
                                      public NotifierController::Observer,
                                      public content::NotificationObserver {
  public:
@@ -42,20 +39,12 @@
   void RemoveNotifierSettingsObserver(
       ash::NotifierSettingsObserver* observer) override;
 
-  // ash::mojom::AshMessageCenterClient:
-  void GetArcAppIdByPackageName(
-      const std::string& package_name,
-      GetArcAppIdByPackageNameCallback callback) override;
-
   // NotifierController::Observer:
   void OnIconImageUpdated(const message_center::NotifierId& notifier_id,
                           const gfx::ImageSkia& icon) override;
   void OnNotifierEnabledChanged(const message_center::NotifierId& notifier_id,
                                 bool enabled) override;
 
-  // Flushs |binding_|.
-  static void FlushForTesting();
-
  private:
   // content::NotificationObserver override.
   void Observe(int type,
@@ -70,8 +59,6 @@
 
   base::ObserverList<ash::NotifierSettingsObserver> notifier_observers_;
 
-  ash::mojom::AshMessageCenterControllerPtr controller_;
-  mojo::AssociatedBinding<ash::mojom::AshMessageCenterClient> binding_;
   content::NotificationRegistrar registrar_;
 
   DISALLOW_COPY_AND_ASSIGN(ChromeAshMessageCenterClient);
diff --git a/chrome/browser/notifications/proto/client_state.proto b/chrome/browser/notifications/proto/client_state.proto
index f60cee1f..49372212 100644
--- a/chrome/browser/notifications/proto/client_state.proto
+++ b/chrome/browser/notifications/proto/client_state.proto
@@ -16,6 +16,7 @@
   TEST_2 = -2;
   TEST_3 = -3;
   UNKNOWN = 0;
+  WEBUI = 1;
 }
 
 // Contains details about supression and recovery after suppression expired.
diff --git a/chrome/browser/notifications/scheduler/OWNERS b/chrome/browser/notifications/scheduler/OWNERS
index eae9c737..44ed43a 100644
--- a/chrome/browser/notifications/scheduler/OWNERS
+++ b/chrome/browser/notifications/scheduler/OWNERS
@@ -1,2 +1,4 @@
 dtrainor@chromium.org
-xingliu@chromium.org
\ No newline at end of file
+xingliu@chromium.org
+
+# COMPONENT: UI>Notifications
diff --git a/chrome/browser/notifications/scheduler/internal/BUILD.gn b/chrome/browser/notifications/scheduler/internal/BUILD.gn
index c8638e0..7535011 100644
--- a/chrome/browser/notifications/scheduler/internal/BUILD.gn
+++ b/chrome/browser/notifications/scheduler/internal/BUILD.gn
@@ -55,6 +55,8 @@
     "scheduler_config.h",
     "scheduler_utils.cc",
     "scheduler_utils.h",
+    "webui_client.cc",
+    "webui_client.h",
   ]
 
   # This target should not depend on anything in //chrome/* except the proto library.
diff --git a/chrome/browser/notifications/scheduler/internal/impression_history_tracker.cc b/chrome/browser/notifications/scheduler/internal/impression_history_tracker.cc
index 154b22df..f8ebff8 100644
--- a/chrome/browser/notifications/scheduler/internal/impression_history_tracker.cc
+++ b/chrome/browser/notifications/scheduler/internal/impression_history_tracker.cc
@@ -31,6 +31,8 @@
     case SchedulerClientType::kUnknown:
       NOTREACHED();
       return std::string();
+    case SchedulerClientType::kWebUI:
+      return "WebUI";
   }
 }
 
diff --git a/chrome/browser/notifications/scheduler/internal/notification_scheduler_context.cc b/chrome/browser/notifications/scheduler/internal/notification_scheduler_context.cc
index 1ba5799..f67c8d90 100644
--- a/chrome/browser/notifications/scheduler/internal/notification_scheduler_context.cc
+++ b/chrome/browser/notifications/scheduler/internal/notification_scheduler_context.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/notifications/scheduler/internal/notification_scheduler_context.h"
 
+#include <memory>
 #include <utility>
 
 #include "base/time/default_clock.h"
@@ -13,7 +14,9 @@
 #include "chrome/browser/notifications/scheduler/internal/impression_history_tracker.h"
 #include "chrome/browser/notifications/scheduler/internal/scheduled_notification_manager.h"
 #include "chrome/browser/notifications/scheduler/internal/scheduler_config.h"
+#include "chrome/browser/notifications/scheduler/internal/webui_client.h"
 #include "chrome/browser/notifications/scheduler/public/notification_background_task_scheduler.h"
+#include "chrome/browser/notifications/scheduler/public/notification_scheduler_client.h"
 #include "chrome/browser/notifications/scheduler/public/notification_scheduler_client_registrar.h"
 
 namespace notifications {
@@ -34,7 +37,10 @@
       background_task_coordinator_(std::make_unique<BackgroundTaskCoordinator>(
           std::move(background_task),
           config_.get(),
-          base::DefaultClock::GetInstance())) {}
+          base::DefaultClock::GetInstance())) {
+  client_registrar_->RegisterClient(SchedulerClientType::kWebUI,
+                                    std::make_unique<WebUIClient>());
+}
 
 NotificationSchedulerContext::~NotificationSchedulerContext() = default;
 
diff --git a/chrome/browser/notifications/scheduler/internal/proto_conversion.cc b/chrome/browser/notifications/scheduler/internal/proto_conversion.cc
index 4fa2624..f0c4342 100644
--- a/chrome/browser/notifications/scheduler/internal/proto_conversion.cc
+++ b/chrome/browser/notifications/scheduler/internal/proto_conversion.cc
@@ -49,6 +49,8 @@
       return proto::SchedulerClientType::TEST_3;
     case SchedulerClientType::kUnknown:
       return proto::SchedulerClientType::UNKNOWN;
+    case SchedulerClientType::kWebUI:
+      return proto::SchedulerClientType::WEBUI;
   }
   NOTREACHED();
 }
@@ -65,6 +67,8 @@
       return SchedulerClientType::kTest3;
     case proto::SchedulerClientType::UNKNOWN:
       return SchedulerClientType::kUnknown;
+    case proto::SchedulerClientType::WEBUI:
+      return SchedulerClientType::kWebUI;
   }
   NOTREACHED();
 }
diff --git a/chrome/browser/notifications/scheduler/internal/webui_client.cc b/chrome/browser/notifications/scheduler/internal/webui_client.cc
new file mode 100644
index 0000000..a511d7a
--- /dev/null
+++ b/chrome/browser/notifications/scheduler/internal/webui_client.cc
@@ -0,0 +1,31 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/notifications/scheduler/internal/webui_client.h"
+
+#include "base/logging.h"
+
+namespace notifications {
+
+WebUIClient::WebUIClient() = default;
+
+WebUIClient::~WebUIClient() = default;
+
+void WebUIClient::ShowNotification(std::unique_ptr<DisplayData> display_data,
+                                   DisplayCallback callback) {
+  NOTIMPLEMENTED();
+}
+
+void WebUIClient::OnSchedulerInitialized(bool success,
+                                         std::set<std::string> guids) {
+  NOTIMPLEMENTED();
+}
+
+void WebUIClient::OnUserAction(UserActionType action_type,
+                               const std::string& notification_id,
+                               base::Optional<ButtonClickInfo> button_info) {
+  NOTIMPLEMENTED();
+}
+
+}  // namespace notifications
diff --git a/chrome/browser/notifications/scheduler/internal/webui_client.h b/chrome/browser/notifications/scheduler/internal/webui_client.h
new file mode 100644
index 0000000..bf291f0e
--- /dev/null
+++ b/chrome/browser/notifications/scheduler/internal/webui_client.h
@@ -0,0 +1,37 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_INTERNAL_WEBUI_CLIENT_H_
+#define CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_INTERNAL_WEBUI_CLIENT_H_
+
+#include <memory>
+#include <set>
+#include <string>
+
+#include "chrome/browser/notifications/scheduler/public/notification_scheduler_client.h"
+
+namespace notifications {
+
+// The client used in chrome://notifications-internals for debugging purposes.
+class WebUIClient : public NotificationSchedulerClient {
+ public:
+  WebUIClient();
+  ~WebUIClient() override;
+
+ private:
+  // NotificationSchedulerClient implementation.
+  void ShowNotification(std::unique_ptr<DisplayData> display_data,
+                        DisplayCallback callback) override;
+  void OnSchedulerInitialized(bool success,
+                              std::set<std::string> guids) override;
+  void OnUserAction(UserActionType action_type,
+                    const std::string& notification_id,
+                    base::Optional<ButtonClickInfo> button_info) override;
+
+  DISALLOW_COPY_AND_ASSIGN(WebUIClient);
+};
+
+}  // namespace notifications
+
+#endif  // CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_INTERNAL_WEBUI_CLIENT_H_
diff --git a/chrome/browser/notifications/scheduler/public/notification_scheduler_client.h b/chrome/browser/notifications/scheduler/public/notification_scheduler_client.h
index 75916ce..c9888336 100644
--- a/chrome/browser/notifications/scheduler/public/notification_scheduler_client.h
+++ b/chrome/browser/notifications/scheduler/public/notification_scheduler_client.h
@@ -49,8 +49,8 @@
   using DisplayCallback =
       base::OnceCallback<void(std::unique_ptr<DisplayData>)>;
 
-  NotificationSchedulerClient();
-  virtual ~NotificationSchedulerClient();
+  NotificationSchedulerClient() = default;
+  virtual ~NotificationSchedulerClient() = default;
 
   // Called when the notification should be displayed to the user. The clients
   // can overwrite data in |display_data| and return the updated data in
diff --git a/chrome/browser/notifications/scheduler/public/notification_scheduler_types.h b/chrome/browser/notifications/scheduler/public/notification_scheduler_types.h
index 604b4c9..7c7a59d 100644
--- a/chrome/browser/notifications/scheduler/public/notification_scheduler_types.h
+++ b/chrome/browser/notifications/scheduler/public/notification_scheduler_types.h
@@ -30,7 +30,9 @@
 
   // Default value of client type.
   kUnknown = 0,
-  kMaxValue = kUnknown
+  // Client used in chrome://notifications-internals for debugging.
+  kWebUI = 1,
+  kMaxValue = kWebUI
 };
 
 // The type of user feedback from a displayed notification.
diff --git a/chrome/browser/prerender/prerender_contents.cc b/chrome/browser/prerender/prerender_contents.cc
index a8063d2..86b46462 100644
--- a/chrome/browser/prerender/prerender_contents.cc
+++ b/chrome/browser/prerender/prerender_contents.cc
@@ -158,7 +158,7 @@
     prerender_contents_->Destroy(FINAL_STATUS_REGISTER_PROTOCOL_HANDLER);
   }
 
-  gfx::Size GetSizeForNewRenderView(WebContents* web_contents) const override {
+  gfx::Size GetSizeForNewRenderView(WebContents* web_contents) override {
     // Have to set the size of the RenderView on initialization to be sure it is
     // set before the RenderView is hidden on all platforms (esp. Android).
     return prerender_contents_->bounds_.size();
diff --git a/chrome/browser/previews/hints_fetcher_browsertest.cc b/chrome/browser/previews/hints_fetcher_browsertest.cc
index a234d8e6..fdf8582 100644
--- a/chrome/browser/previews/hints_fetcher_browsertest.cc
+++ b/chrome/browser/previews/hints_fetcher_browsertest.cc
@@ -25,6 +25,7 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
 #include "components/optimization_guide/hints_component_info.h"
+#include "components/optimization_guide/optimization_guide_prefs.h"
 #include "components/optimization_guide/optimization_guide_service.h"
 #include "components/optimization_guide/proto/hints.pb.h"
 #include "components/optimization_guide/test_hints_component_creator.h"
@@ -185,6 +186,19 @@
     service->AddPointsForTesting(http_url2, 2);
   }
 
+  void SetTopHostBlacklistState(
+      optimization_guide::prefs::HintsFetcherTopHostBlacklistState
+          blacklist_state) {
+    Profile::FromBrowserContext(browser()
+                                    ->tab_strip_model()
+                                    ->GetActiveWebContents()
+                                    ->GetBrowserContext())
+        ->GetPrefs()
+        ->SetInteger(
+            optimization_guide::prefs::kHintsFetcherTopHostBlacklistState,
+            static_cast<int>(blacklist_state));
+  }
+
   void LoadHintsForUrl(const GURL& url) {
     base::HistogramTester histogram_tester;
 
@@ -571,3 +585,57 @@
           previews::HintCacheStore::StoreEntryType::kComponentHint),
       1);
 }
+
+IN_PROC_BROWSER_TEST_F(
+    HintsFetcherBrowserTest,
+    DISABLE_ON_WIN_MAC_CHROMESOS(HintsFetcherOverrideTimer)) {
+  const base::HistogramTester* histogram_tester = GetHistogramTester();
+  GURL url = https_url();
+  base::CommandLine::ForCurrentProcess()->RemoveSwitch(
+      previews::switches::kFetchHintsOverride);
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
+      previews::switches::kFetchHintsOverrideTimer);
+
+  SeedSiteEngagementService();
+
+  // Set the blacklist state to initialized so the sites in the engagement
+  // service will be used and not blacklisted on the first GetTopHosts request.
+  SetTopHostBlacklistState(optimization_guide::prefs::
+                               HintsFetcherTopHostBlacklistState::kInitialized);
+
+  // Whitelist NoScript for https_url()'s' host.
+  SetUpComponentUpdateHints(https_url());
+
+  // Expect that the browser initialization will record at least one sample
+  // in each of the follow histograms as OnePlatform Hints are enabled.
+  EXPECT_GE(RetryForHistogramUntilCountReached(
+                histogram_tester,
+                "Previews.HintsFetcher.GetHintsRequest.HostCount", 1),
+            1);
+
+  // There should be 2 sites in the engagement service.
+  histogram_tester->ExpectBucketCount(
+      "Previews.HintsFetcher.GetHintsRequest.HostCount", 2, 1);
+
+  EXPECT_GE(
+      RetryForHistogramUntilCountReached(
+          histogram_tester, "Previews.HintsFetcher.GetHintsRequest.Status", 1),
+      1);
+
+  LoadHintsForUrl(https_url());
+
+  ui_test_utils::NavigateToURL(browser(), https_url());
+
+  // Verifies that the fetched hint is loaded and not the component hint as
+  // fetched hints are prioritized.
+  histogram_tester->ExpectBucketCount(
+      "Previews.OptimizationGuide.HintCache.HintType.Loaded",
+      static_cast<int>(previews::HintCacheStore::StoreEntryType::kFetchedHint),
+      1);
+
+  histogram_tester->ExpectBucketCount(
+      "Previews.OptimizationGuide.HintCache.HintType.Loaded",
+      static_cast<int>(
+          previews::HintCacheStore::StoreEntryType::kComponentHint),
+      0);
+}
diff --git a/chrome/browser/previews/previews_lite_page_predictor.cc b/chrome/browser/previews/previews_lite_page_predictor.cc
new file mode 100644
index 0000000..d3604c2
--- /dev/null
+++ b/chrome/browser/previews/previews_lite_page_predictor.cc
@@ -0,0 +1,143 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/previews/previews_lite_page_predictor.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/feature_list.h"
+#include "base/metrics/histogram_macros.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.h"
+#include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings_factory.h"
+#include "chrome/browser/predictors/loading_predictor.h"
+#include "chrome/browser/predictors/loading_predictor_factory.h"
+#include "chrome/browser/previews/previews_lite_page_navigation_throttle.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h"
+#include "components/previews/core/previews_experiments.h"
+#include "components/previews/core/previews_features.h"
+#include "components/previews/core/previews_lite_page_redirect.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/web_contents.h"
+#include "url/gurl.h"
+
+PreviewsLitePagePredictor::~PreviewsLitePagePredictor() = default;
+
+PreviewsLitePagePredictor::PreviewsLitePagePredictor(
+    content::WebContents* web_contents)
+    : content::WebContentsObserver(web_contents) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+  drp_settings_ = DataReductionProxyChromeSettingsFactory::GetForBrowserContext(
+      web_contents->GetBrowserContext());
+}
+
+bool PreviewsLitePagePredictor::DataSaverIsEnabled() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  return drp_settings_ && drp_settings_->IsDataReductionProxyEnabled();
+}
+
+bool PreviewsLitePagePredictor::ShouldPreresolveOnPage() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (!previews::params::LitePageRedirectPreviewShouldPresolve())
+    return false;
+
+  if (!web_contents()->GetController().GetLastCommittedEntry())
+    return false;
+
+  if (web_contents()->GetController().GetPendingEntry())
+    return false;
+
+  if (!DataSaverIsEnabled())
+    return false;
+
+  // TODO(crbug.com/971918): Maybe preconnect to origin if this is true by
+  // returning an optional URL.
+  if (!previews::params::IsLitePageServerPreviewsEnabled())
+    return false;
+
+  GURL url = web_contents()->GetController().GetLastCommittedEntry()->GetURL();
+
+  if (previews::IsLitePageRedirectPreviewDomain(url))
+    return false;
+
+  return true;
+}
+
+void PreviewsLitePagePredictor::MaybeTogglePreresolveTimer() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  // If the timer is not null, it should be running.
+  DCHECK(!timer_ || timer_->IsRunning());
+
+  bool should_have_timer = ShouldPreresolveOnPage();
+  if (should_have_timer == bool(timer_))
+    return;
+
+  UMA_HISTOGRAM_BOOLEAN("Previews.ServerLitePage.ToggledPreresolve",
+                        should_have_timer);
+
+  if (should_have_timer) {
+    timer_.reset(new base::RepeatingTimer());
+    // base::Unretained is safe because the timer will stop firing once deleted,
+    // and |timer_| is owned by this.
+    timer_->Start(FROM_HERE,
+                  previews::params::LitePageRedirectPreviewPresolveInterval(),
+                  base::BindRepeating(&PreviewsLitePagePredictor::Preresolve,
+                                      base::Unretained(this)));
+    Preresolve();
+  } else {
+    // Resetting the unique_ptr will delete the timer itself, causing it to stop
+    // calling its callback.
+    timer_.reset();
+  }
+}
+
+void PreviewsLitePagePredictor::Preresolve() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(timer_);
+
+  // TODO(crbug.com/971918): Add remaining conditions.
+  return;
+
+  GURL previews_url = PreviewsLitePageNavigationThrottle::GetPreviewsURLForURL(
+      web_contents()->GetController().GetLastCommittedEntry()->GetURL());
+
+  predictors::LoadingPredictor* loading_predictor =
+      predictors::LoadingPredictorFactory::GetForProfile(
+          Profile::FromBrowserContext(web_contents()->GetBrowserContext()));
+
+  if (!loading_predictor || !loading_predictor->preconnect_manager())
+    return;
+
+  loading_predictor->preconnect_manager()->StartPreresolveHost(previews_url);
+
+  // Record a local histogram for browser testing.
+  base::BooleanHistogram::FactoryGet("Previews.ServerLitePage.Preresolved",
+                                     base::HistogramBase::kNoFlags)
+      ->Add(true);
+}
+
+void PreviewsLitePagePredictor::DidStartNavigation(
+    content::NavigationHandle* handle) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (!handle->IsInMainFrame())
+    return;
+  MaybeTogglePreresolveTimer();
+}
+
+void PreviewsLitePagePredictor::DidFinishNavigation(
+    content::NavigationHandle* handle) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  if (!handle->IsInMainFrame())
+    return;
+  MaybeTogglePreresolveTimer();
+}
+
+WEB_CONTENTS_USER_DATA_KEY_IMPL(PreviewsLitePagePredictor)
diff --git a/chrome/browser/previews/previews_lite_page_predictor.h b/chrome/browser/previews/previews_lite_page_predictor.h
new file mode 100644
index 0000000..8324d1f
--- /dev/null
+++ b/chrome/browser/previews/previews_lite_page_predictor.h
@@ -0,0 +1,98 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PREVIEWS_PREVIEWS_LITE_PAGE_PREDICTOR_H_
+#define CHROME_BROWSER_PREVIEWS_PREVIEWS_LITE_PAGE_PREDICTOR_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+#include "base/sequence_checker.h"
+#include "base/timer/timer.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_user_data.h"
+#include "net/nqe/effective_connection_type.h"
+#include "services/network/public/cpp/network_quality_tracker.h"
+
+namespace content {
+class NavigationHandle;
+}  // namespace content
+
+namespace data_reduction_proxy {
+class DataReductionProxySettings;
+}
+
+// Manages background preresolving or preconnecting for lite page redirect
+// previews. When a set of conditions are met, this class causes the litepage
+// version of the current committed page URL to be preresolved in a loop so that
+// the DNS entry for the litepage is always cached. This helps to mitigate the
+// delay of loading a preview of the same origin.
+//
+// All of the following conditions must be met to preresolve the litepages host
+// on a background loop during a page load:
+// * We allow preresolving by feature param.
+// * A page is committed.
+// * There is no ongoing navigation.
+// * Lite mode is enabled for the user. - Note this change is not directly
+// observed because we find that it seldom changes in practice.
+// * The lite page redirect feature is enabled.
+// * ECT is at or below the lite page redirect threshold.
+// * The current page's host is not blacklisted by server hints.
+// * The current page isn't a litepage preview already.
+// * Chrome is in the foreground.
+// * This' |web_contents| is in the foreground.
+class PreviewsLitePagePredictor
+    : public content::WebContentsObserver,
+      public content::WebContentsUserData<PreviewsLitePagePredictor> {
+ public:
+  ~PreviewsLitePagePredictor() override;
+
+  // content::WebContentsObserver:
+  void DidFinishNavigation(content::NavigationHandle* handle) override;
+  void DidStartNavigation(content::NavigationHandle* handle) override;
+
+ protected:
+  explicit PreviewsLitePagePredictor(content::WebContents* web_contents);
+
+  // Virtual for testing.
+  virtual bool DataSaverIsEnabled() const;
+
+ private:
+  friend class content::WebContentsUserData<PreviewsLitePagePredictor>;
+  FRIEND_TEST_ALL_PREFIXES(PreviewsLitePagePredictorUnitTest, AllConditionsMet);
+  FRIEND_TEST_ALL_PREFIXES(PreviewsLitePagePredictorUnitTest, FeatureDisabled);
+  FRIEND_TEST_ALL_PREFIXES(PreviewsLitePagePredictorUnitTest,
+                           DataSaverDisabled);
+  FRIEND_TEST_ALL_PREFIXES(PreviewsLitePagePredictorUnitTest, NoNavigation);
+  FRIEND_TEST_ALL_PREFIXES(PreviewsLitePagePredictorUnitTest,
+                           ToggleMultipleTimes_Navigations);
+
+  // Returns true if the current page should be preresolved.
+  bool ShouldPreresolveOnPage() const;
+
+  // Toggles preresolving to either start or stop as needed. This operates
+  // statelessly, but should be called every time a change potentially needs to
+  // be made. See observers below.
+  void MaybeTogglePreresolveTimer();
+
+  // Immediately causes the preview URL for the current committed page to be
+  // preresolved.
+  void Preresolve();
+
+  // Set if the preview URL is actively being preresolved.
+  std::unique_ptr<base::RepeatingTimer> timer_;
+
+  // A reference to the DRP Settings.
+  data_reduction_proxy::DataReductionProxySettings* drp_settings_;
+
+  WEB_CONTENTS_USER_DATA_KEY_DECL();
+
+  SEQUENCE_CHECKER(sequence_checker_);
+
+  DISALLOW_COPY_AND_ASSIGN(PreviewsLitePagePredictor);
+};
+
+#endif  // CHROME_BROWSER_PREVIEWS_PREVIEWS_LITE_PAGE_PREDICTOR_H_
diff --git a/chrome/browser/previews/previews_lite_page_predictor_unittest.cc b/chrome/browser/previews/previews_lite_page_predictor_unittest.cc
new file mode 100644
index 0000000..93fbd1e3
--- /dev/null
+++ b/chrome/browser/previews/previews_lite_page_predictor_unittest.cc
@@ -0,0 +1,126 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/previews/previews_lite_page_predictor.h"
+
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "components/previews/core/previews_features.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/mock_navigation_handle.h"
+#include "content/public/test/web_contents_tester.h"
+#include "url/gurl.h"
+
+namespace {
+const char kTestUrl[] = "http://www.test.com/";
+}
+
+class TestPreviewsLitePagePredictor : public PreviewsLitePagePredictor {
+ public:
+  TestPreviewsLitePagePredictor(content::WebContents* web_contents,
+                                bool data_saver_enabled)
+      : PreviewsLitePagePredictor(web_contents),
+        data_saver_enabled_(data_saver_enabled) {}
+
+  // PreviewsLitePagePredictor:
+  bool DataSaverIsEnabled() const override { return data_saver_enabled_; }
+
+ private:
+  bool data_saver_enabled_;
+};
+
+class PreviewsLitePagePredictorUnitTest
+    : public ChromeRenderViewHostTestHarness {
+ public:
+  void RunTest(bool feature_enabled, bool data_saver_enabled) {
+    scoped_feature_list_.InitWithFeatureState(
+        previews::features::kLitePageServerPreviews, feature_enabled);
+    preresolver_.reset(
+        new TestPreviewsLitePagePredictor(web_contents(), data_saver_enabled));
+    test_handle_.reset(
+        new content::MockNavigationHandle(GURL(kTestUrl), main_rfh()));
+    std::vector<GURL> redirect_chain;
+    redirect_chain.push_back(GURL(kTestUrl));
+    test_handle_->set_redirect_chain(redirect_chain);
+    content::RenderFrameHostTester::For(main_rfh())
+        ->InitializeRenderFrameIfNeeded();
+  }
+
+  void SimulateWillProcessResponse() { SimulateCommit(); }
+
+  void SimulateCommit() {
+    test_handle_->set_has_committed(true);
+    test_handle_->set_url(GURL(kTestUrl));
+  }
+
+  void CallDidFinishNavigation() {
+    preresolver()->DidFinishNavigation(test_handle_.get());
+  }
+
+  TestPreviewsLitePagePredictor* preresolver() const {
+    return preresolver_.get();
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+  std::unique_ptr<TestPreviewsLitePagePredictor> preresolver_;
+  std::unique_ptr<content::MockNavigationHandle> test_handle_;
+};
+
+TEST_F(PreviewsLitePagePredictorUnitTest, AllConditionsMet) {
+  RunTest(true /* feature_enabled */, true /* data_saver_enabled */);
+
+  base::HistogramTester histogram_tester;
+
+  content::WebContentsTester::For(web_contents())
+      ->NavigateAndCommit(GURL(kTestUrl));
+
+  EXPECT_TRUE(preresolver()->ShouldPreresolveOnPage());
+  histogram_tester.ExpectUniqueSample(
+      "Previews.ServerLitePage.ToggledPreresolve", true, 1);
+}
+
+TEST_F(PreviewsLitePagePredictorUnitTest, FeatureDisabled) {
+  RunTest(false /* feature_enabled */, true /* data_saver_enabled */);
+
+  content::WebContentsTester::For(web_contents())
+      ->NavigateAndCommit(GURL(kTestUrl));
+
+  EXPECT_FALSE(preresolver()->ShouldPreresolveOnPage());
+}
+
+TEST_F(PreviewsLitePagePredictorUnitTest, DataSaverDisabled) {
+  RunTest(true /* feature_enabled */, false /* data_saver_enabled */);
+
+  content::WebContentsTester::For(web_contents())
+      ->NavigateAndCommit(GURL(kTestUrl));
+
+  EXPECT_FALSE(preresolver()->ShouldPreresolveOnPage());
+}
+
+TEST_F(PreviewsLitePagePredictorUnitTest, NoNavigation) {
+  RunTest(true /* feature_enabled */, true /* data_saver_enabled */);
+
+  EXPECT_FALSE(preresolver()->ShouldPreresolveOnPage());
+}
+
+TEST_F(PreviewsLitePagePredictorUnitTest, ToggleMultipleTimes_Navigations) {
+  RunTest(true /* feature_enabled */, true /* data_saver_enabled */);
+
+  base::HistogramTester histogram_tester;
+
+  content::WebContentsTester::For(web_contents())
+      ->NavigateAndCommit(GURL(kTestUrl));
+  EXPECT_TRUE(preresolver()->ShouldPreresolveOnPage());
+
+  content::WebContentsTester::For(web_contents())
+      ->NavigateAndCommit(GURL(kTestUrl));
+  EXPECT_TRUE(preresolver()->ShouldPreresolveOnPage());
+
+  histogram_tester.ExpectBucketCount(
+      "Previews.ServerLitePage.ToggledPreresolve", true, 2);
+  histogram_tester.ExpectBucketCount(
+      "Previews.ServerLitePage.ToggledPreresolve", false, 1);
+}
diff --git a/chrome/browser/previews/previews_top_host_provider_impl.cc b/chrome/browser/previews/previews_top_host_provider_impl.cc
index acdb84d..9d0700e 100644
--- a/chrome/browser/previews/previews_top_host_provider_impl.cc
+++ b/chrome/browser/previews/previews_top_host_provider_impl.cc
@@ -12,6 +12,7 @@
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/previews/content/previews_hints_util.h"
+#include "components/previews/core/previews_experiments.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/web_contents.h"
@@ -44,10 +45,45 @@
   DCHECK(browser_context_);
   DCHECK_EQ(GetCurrentBlacklistState(),
             HintsFetcherTopHostBlacklistState::kNotInitialized);
+  DCHECK(pref_service_
+             ->GetDictionary(
+                 optimization_guide::prefs::kHintsFetcherTopHostBlacklist)
+             ->empty());
 
-  // TODO(mcrouse): When the blacklist state is kNotInitialized, the
-  // |kHintsFetcherTopHostBlacklist| dictionary should be populated with the
-  // hosts currently in the Site Engagement Service.
+  Profile* profile = Profile::FromBrowserContext(browser_context_);
+  SiteEngagementService* engagement_service =
+      SiteEngagementService::Get(profile);
+
+  std::unique_ptr<base::DictionaryValue> top_host_blacklist =
+      std::make_unique<base::DictionaryValue>();
+
+  std::vector<mojom::SiteEngagementDetails> engagement_details =
+      engagement_service->GetAllDetails();
+
+  std::sort(engagement_details.begin(), engagement_details.end(),
+            [](const mojom::SiteEngagementDetails& lhs,
+               const mojom::SiteEngagementDetails& rhs) {
+              return lhs.total_score > rhs.total_score;
+            });
+
+  for (const auto& detail : engagement_details) {
+    if (top_host_blacklist->size() >=
+        previews::params::MaxHintsFetcherTopHostBlacklistSize()) {
+      break;
+    }
+    if (detail.origin.SchemeIsHTTPOrHTTPS()) {
+      top_host_blacklist->SetBoolKey(
+          HashHostForDictionary(detail.origin.host()), true);
+    }
+  }
+
+  UMA_HISTOGRAM_COUNTS_1000(
+      "Previews.HintsFetcher.TopHostProvider.BlacklistSize.OnInitialize",
+      top_host_blacklist->size());
+
+  pref_service_->Set(optimization_guide::prefs::kHintsFetcherTopHostBlacklist,
+                     *top_host_blacklist);
+
   UpdateCurrentBlacklistState(HintsFetcherTopHostBlacklistState::kInitialized);
 }
 
@@ -137,14 +173,15 @@
   if (GetCurrentBlacklistState() != HintsFetcherTopHostBlacklistState::kEmpty) {
     top_host_blacklist =
         pref_service_->GetDictionary(kHintsFetcherTopHostBlacklist);
+    UMA_HISTOGRAM_COUNTS_1000(
+        "Previews.HintsFetcher.TopHostProvider.BlacklistSize.OnRequest",
+        top_host_blacklist->size());
     // This check likely should not be needed as the process of removing hosts
     // from the blacklist should check and update the pref state.
     if (top_host_blacklist->size() == 0) {
       UpdateCurrentBlacklistState(HintsFetcherTopHostBlacklistState::kEmpty);
       top_host_blacklist = nullptr;
     }
-    // TODO(mcrouse): Add histogram to record the size of the blacklist on
-    // request for top hosts.
   }
 
   std::vector<std::string> top_hosts;
@@ -156,6 +193,13 @@
   // populated when DataSaver is first enabled.
   std::vector<mojom::SiteEngagementDetails> engagement_details =
       engagement_service->GetAllDetails();
+
+  std::sort(engagement_details.begin(), engagement_details.end(),
+            [](const mojom::SiteEngagementDetails& lhs,
+               const mojom::SiteEngagementDetails& rhs) {
+              return lhs.total_score > rhs.total_score;
+            });
+
   for (const auto& detail : engagement_details) {
     if (top_hosts.size() >= max_sites)
       return top_hosts;
diff --git a/chrome/browser/previews/previews_top_host_provider_impl.h b/chrome/browser/previews/previews_top_host_provider_impl.h
index 8aac274..dd13886 100644
--- a/chrome/browser/previews/previews_top_host_provider_impl.h
+++ b/chrome/browser/previews/previews_top_host_provider_impl.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_PREVIEWS_PREVIEWS_TOP_HOST_PROVIDER_IMPL_H_
 #define CHROME_BROWSER_PREVIEWS_PREVIEWS_TOP_HOST_PROVIDER_IMPL_H_
 
+#include <memory>
 #include <string>
 #include <vector>
 
diff --git a/chrome/browser/previews/previews_top_host_provider_impl_unittest.cc b/chrome/browser/previews/previews_top_host_provider_impl_unittest.cc
index e3cb5505..c1d20ea 100644
--- a/chrome/browser/previews/previews_top_host_provider_impl_unittest.cc
+++ b/chrome/browser/previews/previews_top_host_provider_impl_unittest.cc
@@ -11,6 +11,7 @@
 #include "components/optimization_guide/optimization_guide_prefs.h"
 #include "components/prefs/pref_service.h"
 #include "components/previews/content/previews_hints_util.h"
+#include "components/previews/core/previews_experiments.h"
 #include "content/public/test/mock_navigation_handle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -181,10 +182,6 @@
   size_t max_top_hosts = 5;
   size_t num_hosts_blacklisted = 5;
   AddEngagedHosts(engaged_hosts);
-  // TODO(mcrouse): Remove once the blacklist is populated on initialization.
-  // The expected behavior will be that all hosts in the engagement service will
-  // be blacklisted on initialization.
-  PopulateTopHostBlacklist(num_hosts_blacklisted);
 
   std::vector<std::string> hosts =
       top_host_provider()->GetTopHosts(max_top_hosts);
@@ -208,10 +205,6 @@
   size_t max_top_hosts = 5;
   size_t num_hosts_blacklisted = 5;
   AddEngagedHosts(engaged_hosts);
-  // TODO(mcrouse): Remove once the blacklist is populated on initialization.
-  // The expected behavior will be that all hosts in the engagement service will
-  // be blacklisted on initialization.
-  PopulateTopHostBlacklist(num_hosts_blacklisted);
 
   std::vector<std::string> hosts =
       top_host_provider()->GetTopHosts(max_top_hosts);
@@ -233,15 +226,10 @@
        MaybeUpdateTopHostBlacklistNavigationsOnBlacklist) {
   size_t engaged_hosts = 5;
   size_t max_top_hosts = 5;
-  size_t num_hosts_blacklisted = 5;
   size_t num_top_hosts = 3;
   AddEngagedHosts(engaged_hosts);
-  // TODO(mcrouse): Remove once the blacklist is populated on initialization.
-  // The expected behavior will be that all hosts in the engagement service will
-  // be blacklisted on initialization.
-  PopulateTopHostBlacklist(num_hosts_blacklisted);
 
-  // Verify that all engaged hosts are blacklisted.
+  // The blacklist should be populated on the first request.
   std::vector<std::string> hosts =
       top_host_provider()->GetTopHosts(max_top_hosts);
   EXPECT_EQ(hosts.size(), 0u);
@@ -258,13 +246,8 @@
        MaybeUpdateTopHostBlacklistEmptyBlacklist) {
   size_t engaged_hosts = 5;
   size_t max_top_hosts = 5;
-  size_t num_hosts_blacklisted = 5;
   size_t num_top_hosts = 5;
   AddEngagedHosts(engaged_hosts);
-  // TODO(mcrouse): Remove once the blacklist is populated on initialization.
-  // The expected behavior will be that all hosts in the engagement service will
-  // be blacklisted on initialization.
-  PopulateTopHostBlacklist(num_hosts_blacklisted);
 
   std::vector<std::string> hosts =
       top_host_provider()->GetTopHosts(max_top_hosts);
@@ -289,9 +272,7 @@
   GURL file_url = GURL("file://anyscheme.com");
   AddEngagedHosts(engaged_hosts);
   AddEngagedHost(http_url, 5);
-  // TODO(mcrouse): Remove once the blacklist is populated on initialization.
-  // The expected behavior will be that all hosts in the engagement service will
-  // be blacklisted on initialization.
+
   PopulateTopHostBlacklist(num_hosts_blacklisted);
   AddHostToBlackList(http_url.host());
 
@@ -314,4 +295,35 @@
   EXPECT_FALSE(IsHostBlacklisted(http_url.host()));
 }
 
+TEST_F(PreviewsTopHostProviderImplTest,
+       IntializeTopHostBlacklistWithMaxTopSites) {
+  size_t engaged_hosts =
+      previews::params::MaxHintsFetcherTopHostBlacklistSize() + 1;
+  size_t max_top_hosts =
+      previews::params::MaxHintsFetcherTopHostBlacklistSize() + 1;
+  AddEngagedHosts(engaged_hosts);
+
+  // Blacklist should be populated on the first request.
+  std::vector<std::string> hosts =
+      top_host_provider()->GetTopHosts(max_top_hosts);
+  EXPECT_EQ(hosts.size(), 0u);
+
+  hosts = top_host_provider()->GetTopHosts(max_top_hosts);
+  EXPECT_EQ(
+      hosts.size(),
+      engaged_hosts - previews::params::MaxHintsFetcherTopHostBlacklistSize());
+  EXPECT_EQ(GetCurrentTopHostBlacklistState(),
+            optimization_guide::prefs::HintsFetcherTopHostBlacklistState::
+                kInitialized);
+
+  // The last host has the most engagement points so it will be blacklisted. The
+  // first host has the lowest engagement score and will not be blacklisted
+  // because it is not in the top MaxHintsFetcherTopHostBlacklistSize engaged
+  // hosts by engagement score.
+  EXPECT_TRUE(IsHostBlacklisted(base::StringPrintf(
+      "domain%zu.com",
+      previews::params::MaxHintsFetcherTopHostBlacklistSize())));
+  EXPECT_FALSE(IsHostBlacklisted(base::StringPrintf("domain%u.com", 1u)));
+}
+
 }  // namespace previews
diff --git a/chrome/browser/previews/previews_ui_tab_helper.cc b/chrome/browser/previews/previews_ui_tab_helper.cc
index f28d555a..e4f58a4 100644
--- a/chrome/browser/previews/previews_ui_tab_helper.cc
+++ b/chrome/browser/previews/previews_ui_tab_helper.cc
@@ -250,6 +250,33 @@
   }
 }
 
+void PreviewsUITabHelper::MaybeShowInfoBarForHintsFetcher() {
+  if (!base::FeatureList::IsEnabled(
+          previews::features::kOptimizationHintsFetching))
+    return;
+
+  PreviewsService* previews_service = PreviewsServiceFactory::GetForProfile(
+      Profile::FromBrowserContext(web_contents()->GetBrowserContext()));
+
+  if (!previews_service)
+    return;
+
+  PreviewsHTTPSNotificationInfoBarDecider* decider =
+      previews_service->previews_https_notification_infobar_decider();
+
+  DataReductionProxyChromeSettings* drp_settings =
+      DataReductionProxyChromeSettingsFactory::GetForBrowserContext(
+          web_contents()->GetBrowserContext());
+
+  if (!drp_settings)
+    return;
+
+  if (drp_settings->IsDataReductionProxyEnabled() &&
+      decider->NeedsToNotifyUser()) {
+    decider->NotifyUser(web_contents());
+  }
+}
+
 void PreviewsUITabHelper::DidStartNavigation(
     content::NavigationHandle* navigation_handle) {
   if (!navigation_handle->IsInMainFrame())
@@ -259,6 +286,8 @@
 
   previews::PreviewsTopHostProviderImpl::MaybeUpdateTopHostBlacklist(
       navigation_handle);
+
+  MaybeShowInfoBarForHintsFetcher();
 }
 
 void PreviewsUITabHelper::DidFinishNavigation(
diff --git a/chrome/browser/previews/previews_ui_tab_helper.h b/chrome/browser/previews/previews_ui_tab_helper.h
index e6c137a..9d9df97 100644
--- a/chrome/browser/previews/previews_ui_tab_helper.h
+++ b/chrome/browser/previews/previews_ui_tab_helper.h
@@ -135,6 +135,10 @@
   // and a preview was shown.
   void MaybeRecordPreviewReload(content::NavigationHandle* navigation_handle);
 
+  // Show the user the Infobar if they need to be to notified that Lite mode
+  // now optimizes HTTPS pages when HintsFetcher is enabled.
+  void MaybeShowInfoBarForHintsFetcher();
+
   // True if the UI for a preview has been shown for the page.
   bool displayed_preview_ui_ = false;
 
diff --git a/chrome/browser/previews/previews_ui_tab_helper_unittest.cc b/chrome/browser/previews/previews_ui_tab_helper_unittest.cc
index 06b2a88..714fa90 100644
--- a/chrome/browser/previews/previews_ui_tab_helper_unittest.cc
+++ b/chrome/browser/previews/previews_ui_tab_helper_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
@@ -16,8 +17,10 @@
 #include "build/build_config.h"
 #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.h"
 #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings_factory.h"
+#include "chrome/browser/previews/previews_https_notification_infobar_decider.h"
 #include "chrome/browser/previews/previews_lite_page_navigation_throttle.h"
-#include "chrome/browser/previews/previews_ui_tab_helper.h"
+#include "chrome/browser/previews/previews_service.h"
+#include "chrome/browser/previews/previews_service_factory.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h"
@@ -371,3 +374,41 @@
                                            ->GetTransitionType();
   EXPECT_TRUE(transition_type & ui::PAGE_TRANSITION_RELOAD);
 }
+
+TEST_F(PreviewsUITabHelperUnitTest, TestInfoBarShownOnHintsFetcherEnabled) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures(
+      {previews::features::kOptimizationHintsFetching}, {});
+
+  data_reduction_proxy::DataReductionProxySettings::
+      SetDataSaverEnabledForTesting(drp_test_context_->pref_service(), true);
+
+  PreviewsService* previews_service = PreviewsServiceFactory::GetForProfile(
+      Profile::FromBrowserContext(web_contents()->GetBrowserContext()));
+
+  PreviewsHTTPSNotificationInfoBarDecider* decider =
+      previews_service->previews_https_notification_infobar_decider();
+
+  EXPECT_TRUE(decider->NeedsToNotifyUser());
+
+  GURL test_url("https://tribbles.com");
+  content::WebContentsTester::For(web_contents())->NavigateAndCommit(test_url);
+  EXPECT_FALSE(decider->NeedsToNotifyUser());
+}
+
+TEST_F(PreviewsUITabHelperUnitTest, TestInfoBarNotShownOnHintsFetcherDisabled) {
+  data_reduction_proxy::DataReductionProxySettings::
+      SetDataSaverEnabledForTesting(drp_test_context_->pref_service(), true);
+
+  PreviewsService* previews_service = PreviewsServiceFactory::GetForProfile(
+      Profile::FromBrowserContext(web_contents()->GetBrowserContext()));
+
+  PreviewsHTTPSNotificationInfoBarDecider* decider =
+      previews_service->previews_https_notification_infobar_decider();
+
+  EXPECT_TRUE(decider->NeedsToNotifyUser());
+
+  GURL test_url("https://tribbles.com");
+  content::WebContentsTester::For(web_contents())->NavigateAndCommit(test_url);
+  EXPECT_TRUE(decider->NeedsToNotifyUser());
+}
diff --git a/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc b/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc
index 9e3c55f..e903595 100644
--- a/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc
+++ b/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc
@@ -93,6 +93,9 @@
     https_url_ = https_server_->GetURL("/resource_loading_hints.html");
     ASSERT_TRUE(https_url_.SchemeIs(url::kHttpsScheme));
 
+    https_url_preload_ =
+        https_server_->GetURL("/resource_loading_hints_preload.html");
+
     https_second_url_ =
         https_server_->GetURL("/resource_loading_hints_second.html");
     ASSERT_TRUE(https_second_url_.SchemeIs(url::kHttpsScheme));
@@ -251,7 +254,8 @@
     LoadHintsForUrl(hint_setup_url);
   }
 
-  const GURL& https_url() const { return https_url_; }
+  virtual const GURL& https_url() const { return https_url_; }
+  const GURL& https_url_preload() const { return https_url_preload_; }
   const GURL& https_second_url() const { return https_second_url_; }
   const GURL& https_no_transform_url() const { return https_no_transform_url_; }
   const GURL& https_hint_setup_url() const { return https_hint_setup_url_; }
@@ -337,6 +341,7 @@
   std::unique_ptr<net::EmbeddedTestServer> https_server_;
   std::unique_ptr<net::EmbeddedTestServer> http_server_;
   GURL https_url_;
+  GURL https_url_preload_;
   GURL https_second_url_;
   GURL https_no_transform_url_;
   GURL https_hint_setup_url_;
@@ -356,8 +361,11 @@
 };
 
 // This test class enables ResourceLoadingHints with OptimizationHints.
+// Parameter is true if the test should be run with a webpage that preloads
+// resources in the HTML head using link-rel preload.
 class ResourceLoadingHintsBrowserTest
-    : public ResourceLoadingNoFeaturesBrowserTest {
+    : public ::testing::WithParamInterface<bool>,
+      public ResourceLoadingNoFeaturesBrowserTest {
  public:
   ResourceLoadingHintsBrowserTest() = default;
 
@@ -376,10 +384,22 @@
     ResourceLoadingNoFeaturesBrowserTest::SetUp();
   }
 
+  const GURL& https_url() const override {
+    if (GetParam())
+      return ResourceLoadingNoFeaturesBrowserTest::https_url_preload();
+    return ResourceLoadingNoFeaturesBrowserTest::https_url();
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(ResourceLoadingHintsBrowserTest);
 };
 
+// Parameter is true if the test should be run with a webpage that preloads
+// resources in the HTML head using link-rel preload.
+INSTANTIATE_TEST_SUITE_P(,
+                         ResourceLoadingHintsBrowserTest,
+                         ::testing::Values(false, true));
+
 // Previews InfoBar (which these tests triggers) does not work on Mac.
 // See https://crbug.com/782322 for details. Also occasional flakes on win7
 // (https://crbug.com/789542).
@@ -389,9 +409,14 @@
 #define DISABLE_ON_WIN_MAC_CHROMESOS(x) x
 #endif
 
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     ResourceLoadingHintsBrowserTest,
     DISABLE_ON_WIN_MAC_CHROMESOS(ResourceLoadingHintsHttpsWhitelisted)) {
+  // TODO(https://crbug.com/891328): The test does not pass when resources are
+  // loaded using link-rel preload.
+  if (GetParam())
+    return;
+
   GURL url = https_url();
 
   // Whitelist resource loading hints for https_hint_setup_url()'s' host.
@@ -451,7 +476,7 @@
 // Sets only the experimental hints, but does not enable the matching
 // experiment. Verifies that the hints are not used, and the resource loading is
 // not blocked.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     ResourceLoadingHintsBrowserTest,
     DISABLE_ON_WIN_MAC_CHROMESOS(ExperimentalHints_ExperimentIsNotEnabled)) {
   GURL url = https_url();
@@ -479,9 +504,14 @@
 
 // Sets only the experimental hints, and enables the matching experiment.
 // Verifies that the hints are used, and the resource loading is blocked.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     ResourceLoadingHintsBrowserTest,
     DISABLE_ON_WIN_MAC_CHROMESOS(ExperimentalHints_ExperimentIsEnabled)) {
+  // TODO(https://crbug.com/891328): The test does not pass when resources are
+  // loaded using link-rel preload.
+  if (GetParam())
+    return;
+
   base::test::ScopedFeatureList scoped_list;
   scoped_list.InitAndEnableFeatureWithParameters(
       previews::features::kOptimizationHintsExperiments,
@@ -522,9 +552,13 @@
 // Sets both the experimental and default hints, and enables the matching
 // experiment. Verifies that the hints are used, and the resource loading is
 // blocked.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     ResourceLoadingHintsBrowserTest,
     DISABLE_ON_WIN_MAC_CHROMESOS(MixExperimentalHints_ExperimentIsEnabled)) {
+  // TODO(https://crbug.com/891328): The test does not pass when resources are
+  // loaded using link-rel preload.
+  if (GetParam())
+    return;
   base::test::ScopedFeatureList scoped_list;
   scoped_list.InitAndEnableFeatureWithParameters(
       previews::features::kOptimizationHintsExperiments,
@@ -566,7 +600,7 @@
 // Sets the default hints with a non-wildcard page pattern. Loads a webpage from
 // an origin for which the hints are present, but the page pattern does not
 // match. Verifies that the hints are not used on that webpage.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     ResourceLoadingHintsBrowserTest,
     DISABLE_ON_WIN_MAC_CHROMESOS(MatchingOrigin_NonMatchingPagePattern)) {
   const GURL url = https_url();
@@ -604,9 +638,13 @@
 // webpage from a host for which the hints are present (page pattern matches).
 // Next, loads a webpage from the same host but the webpage's URL does not match
 // the page patterns. Verifies that the hints are not used on that webpage.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     ResourceLoadingHintsBrowserTest,
     DISABLE_ON_WIN_MAC_CHROMESOS(SameOriginDifferentPattern)) {
+  // TODO(https://crbug.com/891328): The test does not pass when resources are
+  // loaded using link-rel preload.
+  if (GetParam())
+    return;
   // Whitelist resource loading hints for https_url()'s' host and pattern.
   SetDefaultOnlyResourceLoadingHintsWithPagePattern(https_url(),
                                                     https_url().path());
@@ -667,9 +705,13 @@
 // Sets both the experimental and default hints, but does not enable the
 // matching experiment. Verifies that the hints from the experiment are not
 // used.
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     ResourceLoadingHintsBrowserTest,
     DISABLE_ON_WIN_MAC_CHROMESOS(MixExperimentalHints_ExperimentIsNotEnabled)) {
+  // TODO(https://crbug.com/891328): The test does not pass when resources are
+  // loaded using link-rel preload.
+  if (GetParam())
+    return;
   base::test::ScopedFeatureList scoped_list;
   scoped_list.InitAndEnableFeatureWithParameters(
       previews::features::kOptimizationHintsExperiments,
@@ -702,10 +744,14 @@
   EXPECT_TRUE(resource_loading_hint_intervention_header_seen());
 }
 
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     ResourceLoadingHintsBrowserTest,
     DISABLE_ON_WIN_MAC_CHROMESOS(
         ResourceLoadingHintsHttpsWhitelistedRedirectToHttps)) {
+  // TODO(https://crbug.com/891328): The test does not pass when resources are
+  // loaded using link-rel preload.
+  if (GetParam())
+    return;
   GURL url = redirect_url();
 
   // Whitelist resource loading hints for https_hint_setup_url()'s' host.
@@ -738,7 +784,7 @@
   EXPECT_TRUE(resource_loading_hint_intervention_header_seen());
 }
 
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     ResourceLoadingHintsBrowserTest,
     DISABLE_ON_WIN_MAC_CHROMESOS(ResourceLoadingHintsHttpsNotWhitelisted)) {
   GURL url = https_url();
@@ -766,7 +812,7 @@
   EXPECT_FALSE(resource_loading_hint_intervention_header_seen());
 }
 
-IN_PROC_BROWSER_TEST_F(ResourceLoadingHintsBrowserTest,
+IN_PROC_BROWSER_TEST_P(ResourceLoadingHintsBrowserTest,
                        DISABLE_ON_WIN_MAC_CHROMESOS(ResourceLoadingHintsHttp)) {
   GURL url = http_url();
 
@@ -792,7 +838,7 @@
   EXPECT_FALSE(resource_loading_hint_intervention_header_seen());
 }
 
-IN_PROC_BROWSER_TEST_F(ResourceLoadingHintsBrowserTest,
+IN_PROC_BROWSER_TEST_P(ResourceLoadingHintsBrowserTest,
                        DISABLE_ON_WIN_MAC_CHROMESOS(
                            ResourceLoadingHintsHttpsWhitelistedNoTransform)) {
   GURL url = https_no_transform_url();
@@ -819,7 +865,7 @@
   EXPECT_FALSE(resource_loading_hint_intervention_header_seen());
 }
 
-IN_PROC_BROWSER_TEST_F(
+IN_PROC_BROWSER_TEST_P(
     ResourceLoadingHintsBrowserTest,
     DISABLE_ON_WIN_MAC_CHROMESOS(
         ResourceLoadingHintsHttpsWhitelistedButShouldNotApplyBecauseCoinFlipHoldback)) {
diff --git a/chrome/browser/resources/bookmarks/list.js b/chrome/browser/resources/bookmarks/list.js
index c3a9c3d..3ff90db0c 100644
--- a/chrome/browser/resources/bookmarks/list.js
+++ b/chrome/browser/resources/bookmarks/list.js
@@ -101,10 +101,12 @@
    */
   onDisplayedIdsChanged_: async function(newValue, oldValue) {
     const updatedList = newValue.map(id => ({id: id}));
+    let skipFocus = false;
     let selectIndex = -1;
     if (this.matches(':focus-within')) {
       if (this.selectedItems_.size > 0) {
         const selectedId = Array.from(this.selectedItems_)[0];
+        skipFocus = newValue.some(id => id == selectedId);
         selectIndex = this.displayedList_.findIndex(({id}) => selectedId == id);
       }
       if (selectIndex == -1 && updatedList.length > 0) {
@@ -121,7 +123,7 @@
         'getPluralString', 'listChanged', this.displayedList_.length);
     this.fire('iron-announce', {text: label});
 
-    if (selectIndex > -1) {
+    if (!skipFocus && selectIndex > -1) {
       setTimeout(() => {
         this.$.list.focusItem(selectIndex);
         // Focus menu button so 'Undo' is only one tab stop away on delete.
diff --git a/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog.html b/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog.html
index 5e56d30..c5d7d1e 100644
--- a/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog.html
+++ b/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/bluetooth_pairing_dialog.html
@@ -27,12 +27,10 @@
           @apply --cr-page-host;
         }
 
-        bluetooth-dialog {
-          --cr-dialog-native: {
-            border-radius: 0;
-            height: 100%;
-            width: 100%;
-          }
+        bluetooth-dialog::part(dialog) {
+          border-radius: 0;
+          height: 100%;
+          width: 100%;
         }
       </style>
 
diff --git a/chrome/browser/resources/chromeos/internet_config_dialog/internet_config_dialog.html b/chrome/browser/resources/chromeos/internet_config_dialog/internet_config_dialog.html
index 7cee689..3a239189 100644
--- a/chrome/browser/resources/chromeos/internet_config_dialog/internet_config_dialog.html
+++ b/chrome/browser/resources/chromeos/internet_config_dialog/internet_config_dialog.html
@@ -32,12 +32,10 @@
           @apply --cr-page-host;
         }
 
-        cr-dialog {
-          --cr-dialog-native: {
-            border-radius: 0;
-            height: 100%;
-            width: 100%;
-          }
+        cr-dialog::part(dialog) {
+          border-radius: 0;
+          height: 100%;
+          width: 100%;
         }
 
         cr-dialog [slot=body] {
diff --git a/chrome/browser/resources/chromeos/login/arc_terms_of_service.html b/chrome/browser/resources/chromeos/login/arc_terms_of_service.html
index ce8cad4..3c0dd76 100644
--- a/chrome/browser/resources/chromeos/login/arc_terms_of_service.html
+++ b/chrome/browser/resources/chromeos/login/arc_terms_of_service.html
@@ -62,7 +62,8 @@
         </div>
       </div>
       <div slot="bottom-buttons" class="flex layout horizontal">
-        <oobe-back-button id="arc-tos-back-button" on-tap="onBack_"></oobe-back-button>
+        <oobe-back-button id="arc-tos-back-button" on-click="onBack_">
+        </oobe-back-button>
         <div class="flex">
         </div>
         <oobe-text-button id="arc-tos-skip-button" border on-tap="onSkip_"
diff --git a/chrome/browser/resources/chromeos/login/demo_preferences.html b/chrome/browser/resources/chromeos/login/demo_preferences.html
index 83adc379..f9c0ba8 100644
--- a/chrome/browser/resources/chromeos/login/demo_preferences.html
+++ b/chrome/browser/resources/chromeos/login/demo_preferences.html
@@ -73,7 +73,7 @@
         </div>
       </div>
       <div slot="bottom-buttons" class="layout horizontal justified">
-        <oobe-back-button on-tap="onBackClicked_"></oobe-back-button>
+        <oobe-back-button on-click="onBackClicked_"></oobe-back-button>
         <oobe-text-button inverse on-tap="onNextClicked_">
           <div>
             [[i18nDynamic(locale, 'demoPreferencesNextButtonLabel')]]
diff --git a/chrome/browser/resources/chromeos/login/demo_setup.html b/chrome/browser/resources/chromeos/login/demo_setup.html
index ba2d535..b29c5ab 100644
--- a/chrome/browser/resources/chromeos/login/demo_setup.html
+++ b/chrome/browser/resources/chromeos/login/demo_setup.html
@@ -51,7 +51,7 @@
             images/alert-illustration_2x.svg 2x">
       </div>
       <div slot="bottom-buttons" class="layout horizontal justified">
-        <oobe-back-button inverse on-tap="onCloseClicked_"
+        <oobe-back-button inverse on-click="onCloseClicked_"
             disabled="[[isPowerwashRequired_]]"></oobe-back-button>
         <oobe-text-button id="retryButton" on-tap="onRetryClicked_"
             inverse hidden="[[isPowerwashRequired_]]">
diff --git a/chrome/browser/resources/chromeos/login/enterprise_enrollment.js b/chrome/browser/resources/chromeos/login/enterprise_enrollment.js
index 725d648..52f44e5 100644
--- a/chrome/browser/resources/chromeos/login/enterprise_enrollment.js
+++ b/chrome/browser/resources/chromeos/login/enterprise_enrollment.js
@@ -237,8 +237,8 @@
     this.navigation_.addEventListener('close', this.cancel.bind(this));
     this.navigation_.addEventListener('refresh', this.cancel.bind(this));
 
-    this.$['oobe-signin-back-button']
-        .addEventListener('tap', this.onBackButtonClicked_.bind(this));
+    this.$['oobe-signin-back-button'].addEventListener(
+        'click', this.onBackButtonClicked_.bind(this));
 
 
     this.$['oauth-enroll-learn-more-link']
diff --git a/chrome/browser/resources/chromeos/login/offline_ad_login.html b/chrome/browser/resources/chromeos/login/offline_ad_login.html
index fba9732..b731571f 100644
--- a/chrome/browser/resources/chromeos/login/offline_ad_login.html
+++ b/chrome/browser/resources/chromeos/login/offline_ad_login.html
@@ -144,9 +144,9 @@
         </div>
       </div>
       <div slot="bottom-buttons" class="layout horizontal" hidden="[[loading]]">
-        <oobe-back-button id="backToUnlockButton" on-tap="onBackToUnlock_"
+        <oobe-back-button id="backToUnlockButton" on-click="onBackToUnlock_"
             disabled="[[disabled]]" hidden></oobe-back-button>
-        <oobe-back-button id="backButton" on-tap="onBackButton_"
+        <oobe-back-button id="backButton" on-click="onBackButton_"
             hidden="[[isDomainJoin]]"></oobe-back-button>
         <div class="flex"></div>
         <oobe-next-button id="nextButton" on-tap="onSubmit_"
diff --git a/chrome/browser/resources/chromeos/login/offline_gaia.html b/chrome/browser/resources/chromeos/login/offline_gaia.html
index 6358e83..49c74fb 100644
--- a/chrome/browser/resources/chromeos/login/offline_gaia.html
+++ b/chrome/browser/resources/chromeos/login/offline_gaia.html
@@ -106,7 +106,7 @@
       </div>
       <div slot="bottom-buttons" class="flex layout horizontal">
         <oobe-back-button id="offline-gaia-back-button"
-            on-tap="onBackButtonClicked_"></oobe-back-button>
+            on-click="onBackButtonClicked_"></oobe-back-button>
         <div class="flex">
         </div>
       </div>
diff --git a/chrome/browser/resources/chromeos/login/oobe_back_button.css b/chrome/browser/resources/chromeos/login/oobe_back_button.css
index a27fc40..7ca7bc1 100644
--- a/chrome/browser/resources/chromeos/login/oobe_back_button.css
+++ b/chrome/browser/resources/chromeos/login/oobe_back_button.css
@@ -2,7 +2,7 @@
    Use of this source code is governed by a BSD-style license that can be
    found in the LICENSE file. */
 
-paper-button {
+cr-button {
   padding-inline-end: 16px;
   padding-inline-start: 8px;
 }
diff --git a/chrome/browser/resources/chromeos/login/oobe_buttons.html b/chrome/browser/resources/chromeos/login/oobe_buttons.html
index 6fee019..9ce7c8a 100644
--- a/chrome/browser/resources/chromeos/login/oobe_buttons.html
+++ b/chrome/browser/resources/chromeos/login/oobe_buttons.html
@@ -2,6 +2,7 @@
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file. -->
 
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html">
 <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
@@ -74,12 +75,12 @@
   Text is blue, background is white.
 
   Example:
-    <oobe-back-button on-tap="handleOnTap_"></oobe-back-button>
+    <oobe-back-button on-click="handleOnClick_"></oobe-back-button>
 
   (Note that there is no space between opening and closing tag.)
 
   Content is optional, "Back" and "Next" will be used if not specified.
-    <oobe-back-button on-tap="handleOnTap_">
+    <oobe-back-button on-click="handleOnClick_">
       Continue
     </oobe-back-button>
 
@@ -92,11 +93,11 @@
   <template>
     <style include="iron-flex iron-flex-alignment iron-positioning"></style>
     <link rel="stylesheet" href="oobe_iron_flex_layout_fix.css">
-    <style include="paper-button-style cr-icons cr-shared-style"></style>
+    <style include="cr-icons cr-shared-style"></style>
     <link rel="stylesheet" href="oobe_fonts.css">
     <link rel="stylesheet" href="oobe_text_buttons.css">
     <link rel="stylesheet" href="oobe_back_button.css">
-    <paper-button id="button" on-tap="onClick_" disabled="[[disabled]]"
+    <cr-button id="button" on-click="onClick_" disabled="[[disabled]]"
         aria-label$="[[labelForAria]]">
       <div class="flex horizontal layout start center">
         <hd-iron-icon
@@ -107,7 +108,7 @@
           <div id="text" i18n-content="back"></div>
         </slot>
       </div>
-    </paper-button>
+    </cr-button>
   </template>
 </dom-module>
 
diff --git a/chrome/browser/resources/chromeos/login/oobe_buttons.js b/chrome/browser/resources/chromeos/login/oobe_buttons.js
index d422a50..57d018a 100644
--- a/chrome/browser/resources/chromeos/login/oobe_buttons.js
+++ b/chrome/browser/resources/chromeos/login/oobe_buttons.js
@@ -42,7 +42,11 @@
   is: 'oobe-back-button',
 
   properties: {
-    disabled: {type: Boolean, value: false, reflectToAttribute: true},
+    disabled: {
+      type: Boolean,
+      value: false,
+      reflectToAttribute: true,
+    },
 
     /* Note that we are not using "aria-label" property here, because
      * we want to pass the label value but not actually declare it as an
@@ -55,10 +59,15 @@
     this.$.button.focus();
   },
 
+  /**
+   * @param {!Event} e
+   * @private
+   */
   onClick_: function(e) {
-    if (this.disabled)
+    if (this.disabled) {
       e.stopPropagation();
-  }
+    }
+  },
 });
 
 Polymer({
diff --git a/chrome/browser/resources/chromeos/login/oobe_eula.html b/chrome/browser/resources/chromeos/login/oobe_eula.html
index 9bc2a14..52ba307 100644
--- a/chrome/browser/resources/chromeos/login/oobe_eula.html
+++ b/chrome/browser/resources/chromeos/login/oobe_eula.html
@@ -78,7 +78,8 @@
         </div>
       </div>
       <div slot="bottom-buttons" class="flex layout horizontal">
-        <oobe-back-button on-tap="onEulaBackButtonPressed_"></oobe-back-button>
+        <oobe-back-button on-click="onEulaBackButtonPressed_">
+        </oobe-back-button>
         <div class="flex">
         </div>
         <oobe-text-button id="acceptButton" inverse on-tap="eulaAccepted_"
diff --git a/chrome/browser/resources/chromeos/login/oobe_network.html b/chrome/browser/resources/chromeos/login/oobe_network.html
index d32689b4..72c8f1a 100644
--- a/chrome/browser/resources/chromeos/login/oobe_network.html
+++ b/chrome/browser/resources/chromeos/login/oobe_network.html
@@ -24,7 +24,7 @@
         </network-select-login>
       </div>
       <div slot="bottom-buttons" class="layout horizontal justified">
-        <oobe-back-button on-tap="onBackClicked_"></oobe-back-button>
+        <oobe-back-button on-click="onBackClicked_"></oobe-back-button>
         <oobe-next-button id="nextButton" disabled="[[!isConnected_]]"
             on-tap="onNextClicked_"></oobe-next-button>
       </div>
diff --git a/chrome/browser/resources/chromeos/login/oobe_update.html b/chrome/browser/resources/chromeos/login/oobe_update.html
index abf7b40..8a06be5 100644
--- a/chrome/browser/resources/chromeos/login/oobe_update.html
+++ b/chrome/browser/resources/chromeos/login/oobe_update.html
@@ -59,7 +59,7 @@
       </div>
       <div slot="bottom-buttons" class="layout horizontal justified">
         <oobe-back-button id="cellular-permission-back" inverse
-            on-tap="onBackClicked_"></oobe-back-button>
+            on-click="onBackClicked_"></oobe-back-button>
         <oobe-next-button id="cellular-permission-next" inverse
             on-tap="onNextClicked_"></oobe-next-button>
       </div>
diff --git a/chrome/browser/resources/chromeos/login/screen_error_message.js b/chrome/browser/resources/chromeos/login/screen_error_message.js
index a80680c..f33c577e 100644
--- a/chrome/browser/resources/chromeos/login/screen_error_message.js
+++ b/chrome/browser/resources/chromeos/login/screen_error_message.js
@@ -105,7 +105,7 @@
 
       var self = this;
       $('error-message-back-button')
-          .addEventListener('tap', this.cancel.bind(this));
+          .addEventListener('click', this.cancel.bind(this));
 
       $('error-message-md-reboot-button').addEventListener('tap', function(e) {
         self.send(login.Screen.CALLBACK_USER_ACTED, USER_ACTION_REBOOT);
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
index 48acd2f..adb264c6 100644
--- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
+++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
@@ -266,7 +266,7 @@
         'identifierEntered', this.onIdentifierEnteredMessage_.bind(this));
 
     this.$['signin-back-button'].addEventListener(
-        'tap', this.onBackButtonClicked_.bind(this));
+        'click', this.onBackButtonClicked_.bind(this));
     this.$['offline-gaia'].addEventListener(
         'offline-gaia-cancel', this.cancel.bind(this));
 
diff --git a/chrome/browser/resources/chromeos/login/supervision_onboarding.html b/chrome/browser/resources/chromeos/login/supervision_onboarding.html
index 4e9e289..40859b59 100644
--- a/chrome/browser/resources/chromeos/login/supervision_onboarding.html
+++ b/chrome/browser/resources/chromeos/login/supervision_onboarding.html
@@ -105,7 +105,7 @@
         <div id="supervision-onboarding-flow-buttons" slot="bottom-buttons"
             class="layout horizontal end-justified">
           <oobe-back-button id="supervision-onboarding-back-button"
-              hidden="[[hideBackButton_]]" on-tap="onBack_">
+              hidden="[[hideBackButton_]]" on-click="onBack_">
             <div i18n-content="supervisionOnboardingBackButtonLabel"></div>
           </oobe-back-button>
           <div class="flex">
diff --git a/chrome/browser/resources/chromeos/set_time_dialog/set_time_dialog.html b/chrome/browser/resources/chromeos/set_time_dialog/set_time_dialog.html
index 53277c7..0d49dd9 100644
--- a/chrome/browser/resources/chromeos/set_time_dialog/set_time_dialog.html
+++ b/chrome/browser/resources/chromeos/set_time_dialog/set_time_dialog.html
@@ -30,12 +30,10 @@
           user-select: none;
         }
 
-        cr-dialog {
-          --cr-dialog-native: {
-            border-radius: 0;
-            height: 100%;
-            width: 100%;
-          }
+        cr-dialog::part(dialog) {
+          border-radius: 0;
+          height: 100%;
+          width: 100%;
         }
 
         cr-dialog [slot=title] {
diff --git a/chrome/browser/resources/chromeos/set_time_dialog/set_time_dialog.js b/chrome/browser/resources/chromeos/set_time_dialog/set_time_dialog.js
index 3dfc945..a02df75 100644
--- a/chrome/browser/resources/chromeos/set_time_dialog/set_time_dialog.js
+++ b/chrome/browser/resources/chromeos/set_time_dialog/set_time_dialog.js
@@ -78,28 +78,6 @@
   return dateToHtmlValues(maxDate).date;
 }
 
-/**
- * Gets the current time in a different timezone.
- * @param {!string} timezoneId The timezone to be used to convert the time.
- * @return {Date} The converted time.
- */
-function getDateInTimezone(timezoneId) {
-  return new Date(new Date().toLocaleString('en-US', {timeZone: timezoneId}));
-}
-
-/**
- * Gives the time difference between two timezones.
- * @param {!string} firstTimezoneId The timezone on the left-hand size of the
- *     subtraction.
- * @param {!string} secondsTimezoneId The timezone on the right-hand side of the
- *     subtraction.
- * @return {number} Delta in milliseconds between the two timezones.
- */
-function getTimezoneDelta(firstTimezoneId, secondsTimezoneId) {
-  return getDateInTimezone(firstTimezoneId) -
-      getDateInTimezone(secondsTimezoneId);
-}
-
 Polymer({
   is: 'set-time-dialog',
 
@@ -146,16 +124,6 @@
       readonly: true,
       value: getMaxDate,
     },
-
-    /**
-     * The last timezone selected.
-     * @private
-     */
-    selectedTimezone_: {
-      type: String,
-      value: () =>
-          /** @type {string} */ (loadTimeData.getValue('currentTimezoneId')),
-    },
   },
 
   /**
@@ -181,14 +149,13 @@
 
   /** @override */
   ready: function() {
-    this.updateTime_(new Date());
+    this.updateTime_();
   },
 
   /** @override */
   attached: function() {
     // Register listeners for updates from C++ code.
-    this.addWebUIListener(
-        'system-clock-updated', this.updateTime_.bind(this, new Date()));
+    this.addWebUIListener('system-clock-updated', this.updateTime_.bind(this));
     this.addWebUIListener(
         'system-timezone-changed', this.setTimezone_.bind(this));
     this.addWebUIListener('validation-complete', this.saveAndClose_.bind(this));
@@ -199,23 +166,6 @@
   },
 
   /**
-   * @return {!Date} The date that is currently displayed on the dialog.
-   * @private
-   */
-  getInputTime_: function() {
-    // Midnight of the current day in GMT.
-    const date = this.$.dateInput.valueAsDate;
-    // Add hours and minutes as set on the time input field.
-    date.setMilliseconds(this.$.timeInput.valueAsNumber);
-    // Add seconds from the system time, since the input fields only allow
-    // setting hour and minute.
-    date.setSeconds(date.getSeconds() + new Date().getSeconds());
-    // Add timezone offset to get real time.
-    date.setMinutes(date.getMinutes() + date.getTimezoneOffset());
-    return date;
-  },
-
-  /**
    * Sets the current timezone.
    * @param {string} timezoneId The timezone ID to select.
    * @private
@@ -224,26 +174,21 @@
     const timezoneSelect = this.$$('#timezoneSelect');
     assert(timezoneSelect.childElementCount > 0);
     timezoneSelect.value = timezoneId;
-
-    const now = this.getInputTime_();
-    const timezoneDelta = getTimezoneDelta(timezoneId, this.selectedTimezone_);
-    now.setMilliseconds(now.getMilliseconds() + timezoneDelta);
-
-    this.selectedTimezone_ = timezoneId;
-    this.updateTime_(now);
+    this.updateTime_();
   },
 
   /**
-   * Updates the date/time controls time.
+   * Updates the date/time controls to the current local time.
    * Called initially, then called again once a minute.
-   * @param {!Date} newTime Time used to update the date/time controls.
    * @private
    */
-  updateTime_: function(newTime) {
+  updateTime_: function() {
+    const now = new Date();
+
     // Only update time controls if neither is focused.
     if (document.activeElement.id != 'dateInput' &&
         document.activeElement.id != 'timeInput') {
-      const htmlValues = dateToHtmlValues(newTime);
+      const htmlValues = dateToHtmlValues(now);
       this.prevValues_.date = this.$.dateInput.value = htmlValues.date;
       this.prevValues_.time = this.$.timeInput.value = htmlValues.time;
     }
@@ -253,11 +198,9 @@
     }
 
     // Start timer to update these inputs every minute.
-    const secondsRemaining = 60 - newTime.getSeconds();
-    const nextTime =
-        new Date(newTime.setSeconds(newTime.getSeconds() + secondsRemaining));
-    this.timeTimeoutId_ = window.setTimeout(
-        this.updateTime_.bind(this, nextTime), secondsRemaining * 1000);
+    const secondsRemaining = 60 - now.getSeconds();
+    this.timeTimeoutId_ =
+        window.setTimeout(this.updateTime_.bind(this), secondsRemaining * 1000);
   },
 
   /**
@@ -265,15 +208,14 @@
    * @private
    */
   applyTime_: function() {
-    const now = this.getInputTime_();
+    const date = this.$.dateInput.valueAsDate;
+    date.setMilliseconds(
+        date.getMilliseconds() + this.$.timeInput.valueAsNumber);
 
     // Add timezone offset to get real time.
-    const timezoneDelta = getTimezoneDelta(
-        /** @type {string} */ (loadTimeData.getValue('currentTimezoneId')),
-        this.selectedTimezone_);
-    now.setMilliseconds(now.getMilliseconds() + timezoneDelta);
+    date.setMinutes(date.getMinutes() + date.getTimezoneOffset());
 
-    const seconds = Math.floor(now / 1000);
+    const seconds = Math.floor(date / 1000);
     this.browserProxy_.setTimeInSeconds(seconds);
   },
 
@@ -290,9 +232,6 @@
       // Restore previous value.
       e.target.value = this.prevValues_[e.target.id];
     }
-
-    // Schedule periodic updates with the new time.
-    this.updateTime_(this.getInputTime_());
   },
 
   /**
@@ -300,7 +239,7 @@
    * @private
    */
   onTimezoneChange_: function(e) {
-    this.setTimezone_(e.currentTarget.value);
+    this.browserProxy_.setTimezone(e.currentTarget.value);
   },
 
   /**
@@ -319,7 +258,6 @@
   /** @private */
   saveAndClose_: function() {
     this.applyTime_();
-    this.browserProxy_.setTimezone(this.selectedTimezone_);
     this.browserProxy_.dialogClose();
   },
 });
diff --git a/chrome/browser/resources/chromeos/smb_shares/smb_credentials_dialog.html b/chrome/browser/resources/chromeos/smb_shares/smb_credentials_dialog.html
index 576fc8c..ca51bc27 100644
--- a/chrome/browser/resources/chromeos/smb_shares/smb_credentials_dialog.html
+++ b/chrome/browser/resources/chromeos/smb_shares/smb_credentials_dialog.html
@@ -10,12 +10,10 @@
 <dom-module id="smb-credentials-dialog">
   <template>
     <style>
-      cr-dialog {
-        --cr-dialog-native: {
-          border-radius: 0;
-          height: 100%;
-          width: 100%;
-        }
+      cr-dialog::part(dialog) {
+        border-radius: 0;
+        height: 100%;
+        width: 100%;
       }
 
       cr-input {
@@ -46,4 +44,4 @@
     </cr-dialog>
   </template>
   <script src="smb_credentials_dialog.js"></script>
-</dom-module>
\ No newline at end of file
+</dom-module>
diff --git a/chrome/browser/resources/chromeos/smb_shares/smb_share_dialog.html b/chrome/browser/resources/chromeos/smb_shares/smb_share_dialog.html
index 99bfb88a..45d5486 100644
--- a/chrome/browser/resources/chromeos/smb_shares/smb_share_dialog.html
+++ b/chrome/browser/resources/chromeos/smb_shares/smb_share_dialog.html
@@ -7,12 +7,10 @@
 <dom-module id="smb-share-dialog">
   <template>
     <style>
-      add-smb-share-dialog {
-        --cr-dialog-native: {
-          border-radius: 0;
-          height: 100%;
-          width: 100%;
-        }
+      add-smb-share-dialog::part(dialog) {
+        border-radius: 0;
+        height: 100%;
+        width: 100%;
       }
     </style>
 
@@ -20,4 +18,4 @@
     </add-smb-share-dialog>
   </template>
   <script src="smb_share_dialog.js"></script>
-</dom-module>
\ No newline at end of file
+</dom-module>
diff --git a/chrome/browser/resources/extensions/options_dialog.html b/chrome/browser/resources/extensions/options_dialog.html
index 59ced39..0824582 100644
--- a/chrome/browser/resources/extensions/options_dialog.html
+++ b/chrome/browser/resources/extensions/options_dialog.html
@@ -26,6 +26,18 @@
         overflow: hidden;
       }
 
+      cr-dialog::part(dialog) {
+        /* CSS variables are set by the JS. */
+        height: var(--dialog-height);
+        opacity: var(--dialog-opacity, 0);
+        /* When loading, it's possible for an size update to follow after the
+           initial size update. The debounce time on size updates is 50ms.
+           A 100ms delay for the opacity transition will allow two updates to
+           occur without showing the dialog resizing to the user. */
+        transition: opacity 100ms ease 100ms;
+        width: var(--dialog-width);
+      }
+
       cr-dialog {
         --cr-dialog-body: {
           height: 100%;
@@ -40,14 +52,6 @@
           height: 100%;
           min-height: initial;
         }
-        --cr-dialog-native: {
-          opacity: 0;
-          /* When loading, it's possible for an size update to follow after the
-             initial size update. The debounce time on size updates is 50ms.
-             A 100ms delay for the opacity transition will allow two updates to
-             occur without showing the dialog resizing to the user. */
-          transition: opacity 100ms ease 100ms;
-        }
         --cr-dialog-wrapper: {
           height: 100%;
           max-height: initial;
diff --git a/chrome/browser/resources/extensions/options_dialog.js b/chrome/browser/resources/extensions/options_dialog.js
index a3fe717..b3b68bd 100644
--- a/chrome/browser/resources/extensions/options_dialog.js
+++ b/chrome/browser/resources/extensions/options_dialog.js
@@ -66,10 +66,10 @@
           Math.min(maxHeight, headerHeight + this.preferredSize_.height);
       const effectiveWidth = Math.max(MIN_WIDTH, this.preferredSize_.width);
 
-      const nativeDialog = this.$.dialog.getNative();
-      nativeDialog.style.height = `${effectiveHeight}px`;
-      nativeDialog.style.width = `${effectiveWidth}px`;
-      nativeDialog.style.opacity = '1';
+      this.$.dialog.style.setProperty(
+          '--dialog-height', `${effectiveHeight}px`);
+      this.$.dialog.style.setProperty('--dialog-width', `${effectiveWidth}px`);
+      this.$.dialog.style.setProperty('--dialog-opacity', 1);
     },
 
     /** @param {chrome.developerPrivate.ExtensionInfo} data */
diff --git a/chrome/browser/resources/notifications_internals/BUILD.gn b/chrome/browser/resources/notifications_internals/BUILD.gn
new file mode 100644
index 0000000..bd68968e
--- /dev/null
+++ b/chrome/browser/resources/notifications_internals/BUILD.gn
@@ -0,0 +1,27 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_type_check("closure_compile") {
+  deps = [
+    ":notifications_internals",
+    ":notifications_internals_browser_proxy",
+  ]
+}
+
+js_library("notifications_internals") {
+  deps = [
+    ":notifications_internals_browser_proxy",
+    "//ui/webui/resources/js:assert",
+    "//ui/webui/resources/js:cr",
+    "//ui/webui/resources/js:util",
+  ]
+}
+
+js_library("notifications_internals_browser_proxy") {
+  deps = [
+    "//ui/webui/resources/js:cr",
+  ]
+}
diff --git a/chrome/browser/resources/notifications_internals/notifications_internals.css b/chrome/browser/resources/notifications_internals/notifications_internals.css
new file mode 100644
index 0000000..aa7e8f93
--- /dev/null
+++ b/chrome/browser/resources/notifications_internals/notifications_internals.css
@@ -0,0 +1,9 @@
+/* Copyright 2019 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+h1 {
+  color: rgb(74, 142, 230);
+  margin: 0;
+  padding: 0;
+}
\ No newline at end of file
diff --git a/chrome/browser/resources/notifications_internals/notifications_internals.html b/chrome/browser/resources/notifications_internals/notifications_internals.html
new file mode 100644
index 0000000..ef676a9
--- /dev/null
+++ b/chrome/browser/resources/notifications_internals/notifications_internals.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html lang="en" dir="ltr">
+  <head>
+    <meta charset="utf-8">
+    <title>Notifications Internals</title>
+    <meta name="viewport" content="width=device-width">
+    <link rel="stylesheet" href="chrome://resources/css/list.css">
+    <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
+    <link rel="stylesheet" href="notifications_internals.css">
+  </head>
+  <body>
+    <h1>Notifications Internals</h1>
+    <h4>Notification Scheduler</h4>
+    <table id="notification-scheduler-request">
+      <tr>
+        <td>Url:</td>
+        <td>
+          <input id="notification-scheduler-url" type="url"
+              placeholder="http://www.example.com">
+        </td>
+      </tr>
+      <tr>
+        <td>Title:</td><td><input id="notification-scheduler-title"
+            type="text" placeholder="Notification title">
+        </td>
+      </tr>
+      <tr>
+        <td>Message:</td><td><input id="notification-scheduler-message"
+            type="text" placeholder="Notification message">
+        </td>
+      </tr>
+    </table>
+    <div>
+      <button id="schedule-notification">Schedule</button>
+    </div>
+    <script src="chrome://resources/js/cr.js"></script>
+    <script src="chrome://resources/js/promise_resolver.js"></script>
+    <script src="chrome://resources/js/util.js"></script>
+    <script src="notifications_internals_browser_proxy.js"></script>
+    <script src="notifications_internals.js"></script>
+  </body>
+</html>
diff --git a/chrome/browser/resources/notifications_internals/notifications_internals.js b/chrome/browser/resources/notifications_internals/notifications_internals.js
new file mode 100644
index 0000000..1fc2717
--- /dev/null
+++ b/chrome/browser/resources/notifications_internals/notifications_internals.js
@@ -0,0 +1,28 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('notificationsInternals', function() {
+  'use strict';
+
+  const browserProxy =
+      notificationsInternals.NotificationsInternalsBrowserProxyImpl
+          .getInstance();
+
+  function initialize() {
+    // Register all event listeners.
+    $('schedule-notification').onclick = function() {
+      browserProxy.scheduleNotification(
+          $('notification-scheduler-url').value,
+          $('notification-scheduler-title').value,
+          $('notification-scheduler-message').value);
+    };
+  }
+
+  return {
+    initialize: initialize,
+  };
+});
+
+document.addEventListener(
+    'DOMContentLoaded', notificationsInternals.initialize);
diff --git a/chrome/browser/resources/notifications_internals/notifications_internals_browser_proxy.js b/chrome/browser/resources/notifications_internals/notifications_internals_browser_proxy.js
new file mode 100644
index 0000000..0c30a8e3
--- /dev/null
+++ b/chrome/browser/resources/notifications_internals/notifications_internals_browser_proxy.js
@@ -0,0 +1,34 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('notificationsInternals', function() {
+  /** @interface */
+  class NotificationsInternalsBrowserProxy {
+    /**
+     * Schedules a notification through notification schedule service.
+     * @param {string} url URL to open after clicking the notification.
+     * @param {string} title Title of the notification.
+     * @param {string} message Message of the notification.
+     */
+    scheduleNotification(url, title, message) {}
+  }
+
+  /**
+   * @implements {notificationsInternals.NotificationsInternalsBrowserProxy}
+   */
+  class NotificationsInternalsBrowserProxyImpl {
+    /** @override */
+    scheduleNotification(url, title, message) {
+      return cr.sendWithPromise('scheduleNotification', url, title, message);
+    }
+  }
+
+  cr.addSingletonGetter(NotificationsInternalsBrowserProxyImpl);
+
+  return {
+    NotificationsInternalsBrowserProxy: NotificationsInternalsBrowserProxy,
+    NotificationsInternalsBrowserProxyImpl:
+        NotificationsInternalsBrowserProxyImpl
+  };
+});
diff --git a/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.html b/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.html
index 3ce7f148..a81ba439 100644
--- a/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.html
+++ b/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.html
@@ -16,12 +16,10 @@
 <dom-module id="print-preview-advanced-settings-dialog">
   <template>
     <style include="print-preview-shared cr-hidden-style">
-      #dialog {
-        --cr-dialog-native: {
-          height: -webkit-fit-content;
-          max-height: calc(100vh - 2 * var(--print-preview-dialog-margin));
-          max-width:  calc(100vw - 2 * var(--print-preview-dialog-margin));
-        };
+      #dialog::part(dialog) {
+        height: -webkit-fit-content;
+        max-height: calc(100vh - 2 * var(--print-preview-dialog-margin));
+        max-width:  calc(100vw - 2 * var(--print-preview-dialog-margin));
       }
 
       print-preview-search-box {
diff --git a/chrome/browser/resources/print_preview/ui/destination_dialog.html b/chrome/browser/resources/print_preview/ui/destination_dialog.html
index 8fc3327..85f1d20 100644
--- a/chrome/browser/resources/print_preview/ui/destination_dialog.html
+++ b/chrome/browser/resources/print_preview/ui/destination_dialog.html
@@ -36,12 +36,13 @@
   <template>
     <style include="print-preview-shared action-link md-select cr-hidden-style
         throbber">
+      #dialog::part(dialog) {
+        height: calc(100vh - 2 * var(--print-preview-dialog-margin));
+        max-width: 640px;
+        width:  calc(100vw - 2 * var(--print-preview-dialog-margin));
+      }
+
       #dialog {
-        --cr-dialog-native: {
-          height: calc(100vh - 2 * var(--print-preview-dialog-margin));
-          max-width: 640px;
-          width:  calc(100vw - 2 * var(--print-preview-dialog-margin));
-        };
         --cr-dialog-wrapper: {
           height: calc(100vh - 2 * var(--print-preview-dialog-margin));
         };
diff --git a/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.html b/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.html
index ad16a11..f77b393 100644
--- a/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.html
+++ b/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.html
@@ -16,12 +16,10 @@
 <dom-module id="print-preview-provisional-destination-resolver">
   <template>
     <style include="print-preview-shared cr-hidden-style throbber">
-      #dialog {
-        --cr-dialog-native: {
-          height: -webkit-fit-content;
-          max-height: calc(100vh - 4 * var(--print-preview-dialog-margin));
-          max-width:  calc(100vw - 4 * var(--print-preview-dialog-margin));
-        };
+      #dialog::part(dialog) {
+        height: -webkit-fit-content;
+        max-height: calc(100vh - 4 * var(--print-preview-dialog-margin));
+        max-width:  calc(100vw - 4 * var(--print-preview-dialog-margin));
       }
 
       .throbber-placeholder {
diff --git a/chrome/browser/resources/settings/internet_page/internet_config.html b/chrome/browser/resources/settings/internet_page/internet_config.html
index 8294c7c..3313aca 100644
--- a/chrome/browser/resources/settings/internet_page/internet_config.html
+++ b/chrome/browser/resources/settings/internet_page/internet_config.html
@@ -11,10 +11,8 @@
 <dom-module id="internet-config">
   <template>
     <style include="internet-shared iron-flex">
-      cr-dialog {
-        --cr-dialog-native: {
-          width: 460px;
-        };
+      cr-dialog::part(dialog) {
+        width: 460px;
       }
 
       .error {
diff --git a/chrome/browser/resources/settings/internet_page/internet_detail_page.html b/chrome/browser/resources/settings/internet_page/internet_detail_page.html
index a6b78bae..874d28e4 100644
--- a/chrome/browser/resources/settings/internet_page/internet_detail_page.html
+++ b/chrome/browser/resources/settings/internet_page/internet_detail_page.html
@@ -197,7 +197,8 @@
       <template is="dom-if" if="[[isCellular_(networkProperties_)]]">
         <settings-toggle-button id="allowDataRoaming"
             pref="{{prefs.cros.signed.data_roaming_enabled}}"
-            label="$i18n{networkAllowDataRoaming}">
+            label="$i18n{networkAllowDataRoaming}"
+            sub-label="[[getRoamingDetails_(networkProperties_)]]">
         </settings-toggle-button>
       </template>
       <!-- SIM Info (Cellular only). -->
diff --git a/chrome/browser/resources/settings/internet_page/internet_detail_page.js b/chrome/browser/resources/settings/internet_page/internet_detail_page.js
index d7522a5..bb91f119f 100644
--- a/chrome/browser/resources/settings/internet_page/internet_detail_page.js
+++ b/chrome/browser/resources/settings/internet_page/internet_detail_page.js
@@ -572,6 +572,22 @@
 
   /**
    * @param {!CrOnc.NetworkProperties} networkProperties
+   * @return {string} The text to display with roaming details.
+   * @private
+   */
+  getRoamingDetails_: function(networkProperties) {
+    if (!networkProperties.Cellular.AllowRoaming) {
+      return this.i18n('networkAllowDataRoamingDisabled');
+    }
+
+    return networkProperties.Cellular.RoamingState ===
+            CrOnc.RoamingState.ROAMING ?
+        this.i18n('networkAllowDataRoamingEnabledRoaming') :
+        this.i18n('networkAllowDataRoamingEnabledHome');
+  },
+
+  /**
+   * @param {!CrOnc.NetworkProperties} networkProperties
    * @return {boolean} True if the network is connected.
    * @private
    */
@@ -1276,8 +1292,8 @@
     const type = this.networkProperties_.Type;
     if (type == CrOnc.Type.CELLULAR && !!this.networkProperties_.Cellular) {
       fields.push(
-          'Cellular.ActivationState', 'Cellular.RoamingState',
-          'RestrictedConnectivity', 'Cellular.ServingOperator.Name');
+          'Cellular.ActivationState', 'RestrictedConnectivity',
+          'Cellular.ServingOperator.Name');
     } else if (type == CrOnc.Type.TETHER && !!this.networkProperties_.Tether) {
       fields.push(
           'Tether.BatteryPercentage', 'Tether.SignalStrength',
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_smartlock_subpage.html b/chrome/browser/resources/settings/multidevice_page/multidevice_smartlock_subpage.html
index 382c8b11..ba36e990 100644
--- a/chrome/browser/resources/settings/multidevice_page/multidevice_smartlock_subpage.html
+++ b/chrome/browser/resources/settings/multidevice_page/multidevice_smartlock_subpage.html
@@ -30,12 +30,12 @@
           page-content-data="[[pageContentData]]">
       </settings-multidevice-feature-toggle>
     </div>
-    <div class="settings-box first line-only">
-      <h2 class="start first">
-        $i18n{multideviceSmartLockOptions}
-      </h2>
-    </div>
     <iron-collapse opened="[[smartLockEnabled_]]">
+      <div class="settings-box first line-only">
+          <h2 class="start first">
+            $i18n{multideviceSmartLockOptions}
+          </h2>
+      </div>
       <div class="list-frame">
         <cr-radio-group
             selected="[[smartLockSignInEnabled_]]"
diff --git a/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html b/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html
index 9ba6b52..6f118634 100644
--- a/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html
+++ b/chrome/browser/resources/settings/people_page/setup_fingerprint_dialog.html
@@ -15,11 +15,9 @@
 <dom-module id="settings-setup-fingerprint-dialog">
   <template>
     <style include="settings-shared">
-      #dialog {
-        --cr-dialog-native: {
-          min-width: 500px;
-          width: 500px;
-        };
+      #dialog::part(dialog) {
+        min-width: 500px;
+        width: 500px;
       }
 
       .fingerprint-scanner-tablet {
diff --git a/chrome/browser/resources/settings/people_page/user_list.html b/chrome/browser/resources/settings/people_page/user_list.html
index 3423195..bc59dbd 100644
--- a/chrome/browser/resources/settings/people_page/user_list.html
+++ b/chrome/browser/resources/settings/people_page/user_list.html
@@ -36,6 +36,10 @@
       .user-info {
         padding-inline-start: 20px;
       }
+
+      :host([disabled]) .user-list {
+        opacity: var(--cr-disabled-opacity);
+      }
     </style>
     <div class="user-list" scrollable>
       <template is="dom-repeat" items="[[users_]]">
diff --git a/chrome/browser/resources/settings/people_page/user_list.js b/chrome/browser/resources/settings/people_page/user_list.js
index 8da449a..6678688 100644
--- a/chrome/browser/resources/settings/people_page/user_list.js
+++ b/chrome/browser/resources/settings/people_page/user_list.js
@@ -42,6 +42,7 @@
     disabled: {
       type: Boolean,
       value: false,
+      reflectToAttribute: true,
     }
   },
 
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
index 65a06b5..b3f9faf 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.cc
@@ -184,7 +184,7 @@
 }
 
 content::InterstitialPageDelegate::TypeID
-SafeBrowsingBlockingPage::GetTypeForTesting() const {
+SafeBrowsingBlockingPage::GetTypeForTesting() {
   return SafeBrowsingBlockingPage::kTypeForTesting;
 }
 
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page.h b/chrome/browser/safe_browsing/safe_browsing_blocking_page.h
index 69ac09e..c66047b9 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page.h
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page.h
@@ -83,7 +83,7 @@
 
   // InterstitialPageDelegate method:
   void OverrideRendererPrefs(blink::mojom::RendererPreferences* prefs) override;
-  content::InterstitialPageDelegate::TypeID GetTypeForTesting() const override;
+  content::InterstitialPageDelegate::TypeID GetTypeForTesting() override;
 
  protected:
   friend class SafeBrowsingBlockingPageFactoryImpl;
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
index cf7aa30..b0baa85 100644
--- a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
@@ -1114,7 +1114,7 @@
     ASSERT_EQ(2, report.dom_size());
     // Because the order of elements is not deterministic, we basically need to
     // verify the relationship. Namely that there is an IFRAME element and that
-    // its has a DIV as its parent.
+    // it has a DIV as its parent.
     int iframe_node_id = -1;
     for (const HTMLElement& elem : report.dom()) {
       if (elem.tag() == "IFRAME") {
diff --git a/chrome/browser/ssl/bad_clock_blocking_page.cc b/chrome/browser/ssl/bad_clock_blocking_page.cc
index a6f658cc..d99f479 100644
--- a/chrome/browser/ssl/bad_clock_blocking_page.cc
+++ b/chrome/browser/ssl/bad_clock_blocking_page.cc
@@ -103,8 +103,7 @@
   return true;
 }
 
-InterstitialPageDelegate::TypeID BadClockBlockingPage::GetTypeForTesting()
-    const {
+InterstitialPageDelegate::TypeID BadClockBlockingPage::GetTypeForTesting() {
   return BadClockBlockingPage::kTypeForTesting;
 }
 
diff --git a/chrome/browser/ssl/bad_clock_blocking_page.h b/chrome/browser/ssl/bad_clock_blocking_page.h
index fcca7ef..58300d5 100644
--- a/chrome/browser/ssl/bad_clock_blocking_page.h
+++ b/chrome/browser/ssl/bad_clock_blocking_page.h
@@ -48,7 +48,7 @@
   ~BadClockBlockingPage() override;
 
   // InterstitialPageDelegate method:
-  InterstitialPageDelegate::TypeID GetTypeForTesting() const override;
+  InterstitialPageDelegate::TypeID GetTypeForTesting() override;
 
  protected:
   // InterstitialPageDelegate implementation:
diff --git a/chrome/browser/ssl/captive_portal_blocking_page.cc b/chrome/browser/ssl/captive_portal_blocking_page.cc
index 88d9b6df..f23fd70 100644
--- a/chrome/browser/ssl/captive_portal_blocking_page.cc
+++ b/chrome/browser/ssl/captive_portal_blocking_page.cc
@@ -99,7 +99,7 @@
 CaptivePortalBlockingPage::~CaptivePortalBlockingPage() {
 }
 
-const void* CaptivePortalBlockingPage::GetTypeForTesting() const {
+const void* CaptivePortalBlockingPage::GetTypeForTesting() {
   return CaptivePortalBlockingPage::kTypeForTesting;
 }
 
diff --git a/chrome/browser/ssl/captive_portal_blocking_page.h b/chrome/browser/ssl/captive_portal_blocking_page.h
index d262bf3..effd30d2 100644
--- a/chrome/browser/ssl/captive_portal_blocking_page.h
+++ b/chrome/browser/ssl/captive_portal_blocking_page.h
@@ -51,7 +51,7 @@
   ~CaptivePortalBlockingPage() override;
 
   // InterstitialPageDelegate method:
-  const void* GetTypeForTesting() const override;
+  const void* GetTypeForTesting() override;
 
  protected:
   // Returns true if the connection is a Wi-Fi connection. Virtual for tests.
diff --git a/chrome/browser/ssl/mitm_software_blocking_page.cc b/chrome/browser/ssl/mitm_software_blocking_page.cc
index 0da50aa..842b2695 100644
--- a/chrome/browser/ssl/mitm_software_blocking_page.cc
+++ b/chrome/browser/ssl/mitm_software_blocking_page.cc
@@ -103,8 +103,7 @@
   return true;
 }
 
-InterstitialPageDelegate::TypeID MITMSoftwareBlockingPage::GetTypeForTesting()
-    const {
+InterstitialPageDelegate::TypeID MITMSoftwareBlockingPage::GetTypeForTesting() {
   return MITMSoftwareBlockingPage::kTypeForTesting;
 }
 
diff --git a/chrome/browser/ssl/mitm_software_blocking_page.h b/chrome/browser/ssl/mitm_software_blocking_page.h
index 7236581..314766c2 100644
--- a/chrome/browser/ssl/mitm_software_blocking_page.h
+++ b/chrome/browser/ssl/mitm_software_blocking_page.h
@@ -50,7 +50,7 @@
   ~MITMSoftwareBlockingPage() override;
 
   // InterstitialPageDelegate method:
-  InterstitialPageDelegate::TypeID GetTypeForTesting() const override;
+  InterstitialPageDelegate::TypeID GetTypeForTesting() override;
 
  protected:
   // InterstitialPageDelegate implementation:
diff --git a/chrome/browser/ssl/ssl_blocking_page.cc b/chrome/browser/ssl/ssl_blocking_page.cc
index a39ca4f..6f77a27 100644
--- a/chrome/browser/ssl/ssl_blocking_page.cc
+++ b/chrome/browser/ssl/ssl_blocking_page.cc
@@ -122,7 +122,7 @@
   return true;
 }
 
-InterstitialPageDelegate::TypeID SSLBlockingPage::GetTypeForTesting() const {
+InterstitialPageDelegate::TypeID SSLBlockingPage::GetTypeForTesting() {
   return SSLBlockingPage::kTypeForTesting;
 }
 
diff --git a/chrome/browser/ssl/ssl_blocking_page.h b/chrome/browser/ssl/ssl_blocking_page.h
index 22584f61..2ea50da 100644
--- a/chrome/browser/ssl/ssl_blocking_page.h
+++ b/chrome/browser/ssl/ssl_blocking_page.h
@@ -68,7 +68,7 @@
           callback);
 
   // InterstitialPageDelegate method:
-  InterstitialPageDelegate::TypeID GetTypeForTesting() const override;
+  InterstitialPageDelegate::TypeID GetTypeForTesting() override;
 
   // Returns true if |options_mask| refers to a soft-overridable SSL error and
   // if SSL error overriding is allowed by policy.
diff --git a/chrome/browser/supervised_user/supervised_user_interstitial.cc b/chrome/browser/supervised_user/supervised_user_interstitial.cc
index db5244180..c477a0c 100644
--- a/chrome/browser/supervised_user/supervised_user_interstitial.cc
+++ b/chrome/browser/supervised_user/supervised_user_interstitial.cc
@@ -288,7 +288,7 @@
 }
 
 content::InterstitialPageDelegate::TypeID
-SupervisedUserInterstitial::GetTypeForTesting() const {
+SupervisedUserInterstitial::GetTypeForTesting() {
   return SupervisedUserInterstitial::kTypeForTesting;
 }
 
diff --git a/chrome/browser/supervised_user/supervised_user_interstitial.h b/chrome/browser/supervised_user/supervised_user_interstitial.h
index a57fc7e..c378ef5 100644
--- a/chrome/browser/supervised_user/supervised_user_interstitial.h
+++ b/chrome/browser/supervised_user/supervised_user_interstitial.h
@@ -71,7 +71,7 @@
   std::string GetHTMLContents() override;
   void OnProceed() override;
   void OnDontProceed() override;
-  content::InterstitialPageDelegate::TypeID GetTypeForTesting() const override;
+  content::InterstitialPageDelegate::TypeID GetTypeForTesting() override;
 
   // SupervisedUserServiceObserver implementation.
   void OnURLFilterChanged() override;
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index ece6553..70d4d12 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -269,6 +269,10 @@
     "webui/net_export_ui.h",
     "webui/net_internals/net_internals_ui.cc",
     "webui/net_internals/net_internals_ui.h",
+    "webui/notifications_internals/notifications_internals_ui.cc",
+    "webui/notifications_internals/notifications_internals_ui.h",
+    "webui/notifications_internals/notifications_internals_ui_message_handler.cc",
+    "webui/notifications_internals/notifications_internals_ui_message_handler.h",
     "webui/ntp_tiles_internals_ui.cc",
     "webui/ntp_tiles_internals_ui.h",
     "webui/omnibox/omnibox_page_handler.cc",
@@ -387,6 +391,7 @@
     "//chrome/browser/devtools",
     "//chrome/browser/engagement:mojo_bindings",
     "//chrome/browser/media:mojo_bindings",
+    "//chrome/browser/notifications/scheduler/public",
     "//chrome/browser/profiling_host",
     "//chrome/browser/safe_browsing",
     "//chrome/browser/ssl:proto",
diff --git a/chrome/browser/ui/ash/assistant/assistant_client.cc b/chrome/browser/ui/ash/assistant/assistant_client.cc
index 0b3ace2..83f6dbe9 100644
--- a/chrome/browser/ui/ash/assistant/assistant_client.cc
+++ b/chrome/browser/ui/ash/assistant/assistant_client.cc
@@ -19,8 +19,15 @@
 #include "services/service_manager/public/cpp/connector.h"
 
 namespace {
+
 // Owned by ChromeBrowserMainChromeOS:
 AssistantClient* g_instance = nullptr;
+
+bool IsAssistantAllowed(Profile* profile) {
+  return assistant::IsAssistantAllowedForProfile(profile) ==
+         ash::mojom::AssistantAllowedState::ALLOWED;
+}
+
 }  // namespace
 
 // static
@@ -43,10 +50,8 @@
 }
 
 void AssistantClient::MaybeInit(Profile* profile) {
-  if (assistant::IsAssistantAllowedForProfile(profile) !=
-      ash::mojom::AssistantAllowedState::ALLOWED) {
+  if (!IsAssistantAllowed(profile))
     return;
-  }
 
   if (!profile_) {
     profile_ = profile;
@@ -77,14 +82,18 @@
 }
 
 void AssistantClient::MaybeStartAssistantOptInFlow() {
-  if (!initialized_)
+  // We need to check if the Assistant is allowed here again, since the result
+  // might have changed from the last time we checked. This usually happens if
+  // any post-OOBE screen changes any property that determines Assistant
+  // availability.
+  if (!initialized_ || !IsAssistantAllowed(profile_))
     return;
 
   assistant_setup_->MaybeStartAssistantOptInFlow();
 }
 
 void AssistantClient::OnAssistantStatusChanged(bool running) {
-  // |running| means assistent mojom service is running. This maps to
+  // |running| means assistant mojom service is running. This maps to
   // |STOPPED| and |NOT_READY|. |RUNNING| maps to UI is shown and an assistant
   // session is running.
   arc::VoiceInteractionControllerClient::Get()->NotifyStatusChanged(
diff --git a/chrome/browser/ui/ash/session_controller_client_impl.cc b/chrome/browser/ui/ash/session_controller_client_impl.cc
index b94012f..6604a15 100644
--- a/chrome/browser/ui/ash/session_controller_client_impl.cc
+++ b/chrome/browser/ui/ash/session_controller_client_impl.cc
@@ -104,9 +104,6 @@
   session->user_info.has_gaia_account = user.has_gaia_account();
   session->user_info.should_display_managed_ui =
       profile && chrome::ShouldDisplayManagedUi(profile);
-  const AccountId& owner_id = UserManager::Get()->GetOwnerAccountId();
-  session->user_info.is_device_owner =
-      owner_id.is_valid() && owner_id == user.GetAccountId();
   if (profile) {
     session->user_info.service_instance_group =
         content::BrowserContext::GetServiceInstanceGroupFor(profile);
@@ -175,7 +172,6 @@
   SessionManager::Get()->AddObserver(this);
   UserManager::Get()->AddSessionStateObserver(this);
   UserManager::Get()->AddObserver(this);
-  chromeos::LoginState::Get()->AddObserver(this);
 
   registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
                  content::NotificationService::AllSources());
@@ -212,7 +208,6 @@
         ->RemoveObserver(this);
   }
 
-  chromeos::LoginState::Get()->RemoveObserver(this);
   SessionManager::Get()->RemoveObserver(this);
   UserManager::Get()->RemoveObserver(this);
   UserManager::Get()->RemoveSessionStateObserver(this);
@@ -526,10 +521,6 @@
     SendUserSession(*user);
 }
 
-void SessionControllerClientImpl::LoggedInStateChanged() {
-  SendUserSession(*UserManager::Get()->GetActiveUser());
-}
-
 void SessionControllerClientImpl::Observe(
     int type,
     const content::NotificationSource& source,
diff --git a/chrome/browser/ui/ash/session_controller_client_impl.h b/chrome/browser/ui/ash/session_controller_client_impl.h
index 2a95b5c..c9c3ee7 100644
--- a/chrome/browser/ui/ash/session_controller_client_impl.h
+++ b/chrome/browser/ui/ash/session_controller_client_impl.h
@@ -41,7 +41,6 @@
       public user_manager::UserManager::Observer,
       public session_manager::SessionManagerObserver,
       public SupervisedUserServiceObserver,
-      public chromeos::LoginState::Observer,
       public content::NotificationObserver,
       public policy::off_hours::DeviceOffHoursController::Observer {
  public:
@@ -100,9 +99,6 @@
   // SupervisedUserServiceObserver:
   void OnCustodianInfoChanged() override;
 
-  // chromeos::LoginState::Observer:
-  void LoggedInStateChanged() override;
-
   // content::NotificationObserver:
   void Observe(int type,
                const content::NotificationSource& source,
diff --git a/chrome/browser/ui/ash/session_controller_client_impl_unittest.cc b/chrome/browser/ui/ash/session_controller_client_impl_unittest.cc
index 6809cc45..c0d239c 100644
--- a/chrome/browser/ui/ash/session_controller_client_impl_unittest.cc
+++ b/chrome/browser/ui/ash/session_controller_client_impl_unittest.cc
@@ -500,44 +500,6 @@
             session_controller.last_user_session()->custodian_email);
 }
 
-TEST_F(SessionControllerClientImplTest, DeviceOwner) {
-  // Create an object to test and connect it to our test interface.
-  SessionControllerClientImpl client;
-  TestSessionController session_controller;
-  client.Init();
-
-  const AccountId owner =
-      AccountId::FromUserEmailGaiaId("owner@test.com", "1111111111");
-  const AccountId normal_user =
-      AccountId::FromUserEmailGaiaId("user@test.com", "2222222222");
-  user_manager()->SetOwnerId(owner);
-  UserAddedToSession(owner);
-  EXPECT_TRUE(
-      session_controller.last_user_session()->user_info.is_device_owner);
-
-  UserAddedToSession(normal_user);
-  EXPECT_FALSE(
-      session_controller.last_user_session()->user_info.is_device_owner);
-}
-
-TEST_F(SessionControllerClientImplTest, UserBecomesDeviceOwner) {
-  // Create an object to test and connect it to our test interface.
-  SessionControllerClientImpl client;
-  TestSessionController session_controller;
-  client.Init();
-
-  const AccountId owner =
-      AccountId::FromUserEmailGaiaId("owner@test.com", "1111111111");
-  UserAddedToSession(owner);
-  // The device owner is empty, the current session shouldn't be the owner.
-  EXPECT_FALSE(
-      session_controller.last_user_session()->user_info.is_device_owner);
-
-  user_manager()->SetOwnerId(owner);
-  EXPECT_TRUE(
-      session_controller.last_user_session()->user_info.is_device_owner);
-}
-
 TEST_F(SessionControllerClientImplTest, UserPrefsChange) {
   // Create an object to test and connect it to our test interface.
   SessionControllerClientImpl client;
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 50b2b45e..081d341a 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -508,6 +508,9 @@
   // It will be reset after the drag ends.
   if (params.in_tab_dragging)
     SetIsInTabDragging(true);
+
+  if (is_focus_mode_)
+    focus_mode_start_time_ = base::TimeTicks::Now();
 }
 
 Browser::~Browser() {
@@ -603,6 +606,13 @@
   // away so they don't try and call back to us.
   if (select_file_dialog_.get())
     select_file_dialog_->ListenerDestroyed();
+
+  if (is_focus_mode_) {
+    auto duration = base::TimeTicks::Now() - focus_mode_start_time_;
+    UMA_HISTOGRAM_CUSTOM_COUNTS("Session.TimeSpentInFocusMode",
+                                duration.InSeconds(), 1,
+                                base::TimeDelta::FromHours(24).InSeconds(), 50);
+  }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1081,12 +1091,12 @@
   window_->SetTopControlsShownRatio(web_contents, ratio);
 }
 
-int Browser::GetTopControlsHeight() const {
+int Browser::GetTopControlsHeight() {
   return window_->GetTopControlsHeight();
 }
 
 bool Browser::DoBrowserControlsShrinkRendererSize(
-    const content::WebContents* contents) const {
+    const content::WebContents* contents) {
   return window_->DoBrowserControlsShrinkRendererSize(contents);
 }
 
@@ -1094,7 +1104,7 @@
   window_->SetTopControlsGestureScrollInProgress(in_progress);
 }
 
-bool Browser::CanOverscrollContent() const {
+bool Browser::CanOverscrollContent() {
 #if defined(USE_AURA)
   return !is_devtools() &&
          base::FeatureList::IsEnabled(features::kOverscrollHistoryNavigation);
@@ -1651,7 +1661,7 @@
   FileSelectHelper::EnumerateDirectory(web_contents, std::move(listener), path);
 }
 
-bool Browser::EmbedsFullscreenWidget() const {
+bool Browser::EmbedsFullscreenWidget() {
   return true;
 }
 
@@ -1668,14 +1678,12 @@
       web_contents);
 }
 
-bool Browser::IsFullscreenForTabOrPending(
-    const WebContents* web_contents) const {
+bool Browser::IsFullscreenForTabOrPending(const WebContents* web_contents) {
   return exclusive_access_manager_->fullscreen_controller()
       ->IsFullscreenForTabOrPending(web_contents);
 }
 
-blink::WebDisplayMode Browser::GetDisplayMode(
-    const WebContents* web_contents) const {
+blink::WebDisplayMode Browser::GetDisplayMode(const WebContents* web_contents) {
   if (window_->IsFullscreen())
     return blink::kWebDisplayModeFullscreen;
 
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index f3220390..961ce64 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -518,11 +518,11 @@
   // Overridden from content::WebContentsDelegate:
   void SetTopControlsShownRatio(content::WebContents* web_contents,
                                 float ratio) override;
-  int GetTopControlsHeight() const override;
+  int GetTopControlsHeight() override;
   bool DoBrowserControlsShrinkRendererSize(
-      const content::WebContents* contents) const override;
+      const content::WebContents* contents) override;
   void SetTopControlsGestureScrollInProgress(bool in_progress) override;
-  bool CanOverscrollContent() const override;
+  bool CanOverscrollContent() override;
   bool ShouldPreserveAbortedURLs(content::WebContents* source) override;
   void SetFocusToLocationBar() override;
   content::KeyboardEventProcessingResult PreHandleKeyboardEvent(
@@ -726,16 +726,16 @@
   void EnumerateDirectory(content::WebContents* web_contents,
                           std::unique_ptr<content::FileSelectListener> listener,
                           const base::FilePath& path) override;
-  bool EmbedsFullscreenWidget() const override;
+  bool EmbedsFullscreenWidget() override;
   void EnterFullscreenModeForTab(
       content::WebContents* web_contents,
       const GURL& origin,
       const blink::WebFullscreenOptions& options) override;
   void ExitFullscreenModeForTab(content::WebContents* web_contents) override;
   bool IsFullscreenForTabOrPending(
-      const content::WebContents* web_contents) const override;
+      const content::WebContents* web_contents) override;
   blink::WebDisplayMode GetDisplayMode(
-      const content::WebContents* web_contents) const override;
+      const content::WebContents* web_contents) override;
   void RegisterProtocolHandler(content::WebContents* web_contents,
                                const std::string& protocol,
                                const GURL& url,
@@ -1060,6 +1060,8 @@
   // Tracks when this browser is being created by session restore.
   bool is_session_restore_;
 
+  base::TimeTicks focus_mode_start_time_;
+
   UnloadController unload_controller_;
 
   std::unique_ptr<ChromeBubbleManager> bubble_manager_;
diff --git a/chrome/browser/ui/cocoa/main_menu_builder.mm b/chrome/browser/ui/cocoa/main_menu_builder.mm
index ba20044..158d636 100644
--- a/chrome/browser/ui/cocoa/main_menu_builder.mm
+++ b/chrome/browser/ui/cocoa/main_menu_builder.mm
@@ -198,6 +198,17 @@
                           Item(IDS_EDIT_CHECK_GRAMMAR_MAC)
                               .action(@selector(toggleGrammarChecking:)),
                     }),
+                Item(IDS_EDIT_SUBSTITUTIONS_MAC).submenu({
+                  Item(IDS_EDIT_SHOW_SUBSTITUTIONS_MAC)
+                      .action(@selector(orderFrontSubstitutionsPanel:)),
+                      Item().is_separator(),
+                      Item(IDS_EDIT_SMART_QUOTES_MAC)
+                          .action(@selector(toggleAutomaticQuoteSubstitution:)),
+                      Item(IDS_EDIT_SMART_DASHES_MAC)
+                          .action(@selector(toggleAutomaticDashSubstitution:)),
+                      Item(IDS_EDIT_TEXT_REPLACEMENT_MAC)
+                          .action(@selector(toggleAutomaticTextReplacement:)),
+                }),
                 Item(IDS_SPEECH_MAC).tag(50158).submenu({
                   Item(IDS_SPEECH_START_SPEAKING_MAC)
                       .action(@selector(startSpeaking:)),
diff --git a/chrome/browser/ui/login/login_interstitial_delegate.cc b/chrome/browser/ui/login/login_interstitial_delegate.cc
index e98c39c6..c1a918e 100644
--- a/chrome/browser/ui/login/login_interstitial_delegate.cc
+++ b/chrome/browser/ui/login/login_interstitial_delegate.cc
@@ -45,7 +45,7 @@
 }
 
 content::InterstitialPageDelegate::TypeID
-LoginInterstitialDelegate::GetTypeForTesting() const {
+LoginInterstitialDelegate::GetTypeForTesting() {
   return LoginInterstitialDelegate::kTypeForTesting;
 }
 
diff --git a/chrome/browser/ui/login/login_interstitial_delegate.h b/chrome/browser/ui/login/login_interstitial_delegate.h
index c63bd0e4..19429f3 100644
--- a/chrome/browser/ui/login/login_interstitial_delegate.h
+++ b/chrome/browser/ui/login/login_interstitial_delegate.h
@@ -37,7 +37,7 @@
 
   // content::InterstitialPageDelegate:
   void CommandReceived(const std::string& command) override;
-  content::InterstitialPageDelegate::TypeID GetTypeForTesting() const override;
+  content::InterstitialPageDelegate::TypeID GetTypeForTesting() override;
 
  protected:
   std::string GetHTMLContents() override;
diff --git a/chrome/browser/ui/manifest_web_app_browsertest.cc b/chrome/browser/ui/manifest_web_app_browsertest.cc
index 6098d89..3d991e8 100644
--- a/chrome/browser/ui/manifest_web_app_browsertest.cc
+++ b/chrome/browser/ui/manifest_web_app_browsertest.cc
@@ -2,16 +2,37 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/run_loop.h"
+#include "base/task/post_task.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
 #include "chrome/browser/ui/manifest_web_app_browser_controller.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/test/browser_test_utils.h"
 
-using ManifestWebAppTest = InProcessBrowserTest;
+class ManifestWebAppTest : public InProcessBrowserTest {
+ public:
+  ManifestWebAppTest() = default;
+  ~ManifestWebAppTest() override {}
+
+  void PreRunTestOnMainThread() override {
+    InProcessBrowserTest::PreRunTestOnMainThread();
+    histogram_tester_ = std::make_unique<base::HistogramTester>();
+  }
+
+ protected:
+  base::HistogramTester* histogram_tester() const {
+    return histogram_tester_.get();
+  }
+
+ private:
+  std::unique_ptr<base::HistogramTester> histogram_tester_;
+};
 
 // Opens a basic example site in focus mode window.
 IN_PROC_BROWSER_TEST_F(ManifestWebAppTest, OpenExampleSite) {
@@ -33,3 +54,21 @@
   // Theme color should be default color (white).
   EXPECT_EQ(controller->GetThemeColor(), SK_ColorWHITE);
 }
+
+IN_PROC_BROWSER_TEST_F(ManifestWebAppTest, MetricsTest) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(features::kFocusMode);
+  Browser* app_browser = ReparentWebContentsForFocusMode(
+      browser()->tab_strip_model()->GetWebContentsAt(0));
+
+  const base::TimeDelta duration = base::TimeDelta::FromSeconds(5);
+  base::RunLoop run_loop;
+  base::PostDelayedTask(FROM_HERE, run_loop.QuitClosure(), duration);
+  run_loop.Run();
+
+  CloseBrowserSynchronously(app_browser);
+  auto samples =
+      histogram_tester()->GetAllSamples("Session.TimeSpentInFocusMode");
+  EXPECT_EQ(1u, samples.size());
+  EXPECT_LE(duration.InSeconds(), samples.front().min);
+}
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc
index 9e9585e..8530e121 100644
--- a/chrome/browser/ui/tab_helpers.cc
+++ b/chrome/browser/ui/tab_helpers.cc
@@ -42,6 +42,7 @@
 #include "chrome/browser/predictors/loading_predictor_factory.h"
 #include "chrome/browser/predictors/loading_predictor_tab_helper.h"
 #include "chrome/browser/prerender/prerender_tab_helper.h"
+#include "chrome/browser/previews/previews_lite_page_predictor.h"
 #include "chrome/browser/previews/previews_ui_tab_helper.h"
 #include "chrome/browser/previews/resource_loading_hints/resource_loading_hints_web_contents_observer.h"
 #include "chrome/browser/profiles/profile.h"
@@ -237,6 +238,7 @@
       web_contents, base::DefaultTickClock::GetInstance());
   PrefsTabHelper::CreateForWebContents(web_contents);
   prerender::PrerenderTabHelper::CreateForWebContents(web_contents);
+  PreviewsLitePagePredictor::CreateForWebContents(web_contents);
   PreviewsUITabHelper::CreateForWebContents(web_contents);
   RecentlyAudibleHelper::CreateForWebContents(web_contents);
   ResourceLoadingHintsWebContentsObserver::CreateForWebContents(web_contents);
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
index 4de954a..d0243de 100644
--- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
+++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
@@ -134,16 +134,6 @@
                                 ui::NativeTheme::kColorId_DefaultIconColor)));
 }
 
-scoped_refptr<base::RefCountedMemory> RecentTabsGetSyncedFaviconForPageURL(
-    sync_sessions::SessionSyncService* session_sync_service,
-    const GURL& page_url) {
-  DCHECK(session_sync_service);
-  sync_sessions::OpenTabsUIDelegate* open_tabs =
-      session_sync_service->GetOpenTabsUIDelegate();
-  return open_tabs ? open_tabs->GetSyncedFaviconForPageURL(page_url.spec())
-                   : nullptr;
-}
-
 // Check if user settings allow querying a Google server using history
 // information.
 bool CanSendHistoryDataToServer(bool is_local_tab, Browser* browser) {
@@ -608,8 +598,6 @@
                      base::Unretained(this), command_id),
       favicon::FaviconRequestOrigin::RECENTLY_CLOSED_TABS,
       open_tabs ? open_tabs->GetIconUrlForPageUrl(url) : GURL(),
-      base::BindOnce(&RecentTabsGetSyncedFaviconForPageURL,
-                     base::Unretained(session_sync_service_)),
       CanSendHistoryDataToServer(is_local_tab, browser_),
       is_local_tab ? &local_tab_cancelable_task_tracker_
                    : &other_devices_tab_cancelable_task_tracker_);
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.cc b/chrome/browser/ui/views/translate/translate_bubble_view.cc
index 761475b..f1243ec 100644
--- a/chrome/browser/ui/views/translate/translate_bubble_view.cc
+++ b/chrome/browser/ui/views/translate/translate_bubble_view.cc
@@ -57,6 +57,7 @@
 #include "ui/views/controls/link.h"
 #include "ui/views/controls/styled_label.h"
 #include "ui/views/controls/tabbed_pane/tabbed_pane.h"
+#include "ui/views/controls/throbber.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/grid_layout.h"
 #include "ui/views/style/platform_style.h"
@@ -220,13 +221,15 @@
   should_always_translate_ = model_->ShouldAlwaysTranslate();
   // Create different view based on user selection in
   // kUseButtonTranslateBubbleUI.
-  if (bubble_ui_model_ != language::TranslateUIBubbleModel::TAB) {
-    before_translate_view_ = CreateViewBeforeTranslate();
-    translating_view_ = CreateViewTranslating();
-    after_translate_view_ = CreateViewAfterTranslate();
+  if (bubble_ui_model_ == language::TranslateUIBubbleModel::BUTTON_GM2) {
+    before_translate_view_ = GM2CreateViewBeforeTranslate();
+    translating_view_ = GM2CreateViewTranslating();
+    after_translate_view_ = GM2CreateViewAfterTranslate();
     error_view_ = CreateViewError();
     advanced_view_ = CreateViewAdvanced();
-  } else {
+  } else if (bubble_ui_model_ == language::TranslateUIBubbleModel::TAB) {
+    // |tab_translate_view| is the child view being used before/during/after
+    // translate in TAB UI.
     tab_translate_view_ = CreateViewTab();
     before_translate_view_ = tab_translate_view_;
     translating_view_ = tab_translate_view_;
@@ -234,6 +237,12 @@
     advanced_view_source_ = TabUiCreateViewAdvanedSource();
     advanced_view_target_ = TabUiCreateViewAdvanedTarget();
     error_view_ = CreateViewError();
+  } else {
+    before_translate_view_ = CreateViewBeforeTranslate();
+    translating_view_ = CreateViewTranslating();
+    after_translate_view_ = CreateViewAfterTranslate();
+    error_view_ = CreateViewError();
+    advanced_view_ = CreateViewAdvanced();
   }
   AddChildView(before_translate_view_);
   AddChildView(translating_view_);
@@ -308,7 +317,6 @@
       GetWidget()->Close();
       break;
     }
-    // TODO(crbug.com/963148): implement handler to take care of RESET action.
     case BUTTON_ID_RESET: {
       ResetLanguage();
       break;
@@ -321,11 +329,15 @@
 }
 
 bool TranslateBubbleView::ShouldShowCloseButton() const {
-  return bubble_ui_model_ != language::TranslateUIBubbleModel::TAB;
+  return bubble_ui_model_ != language::TranslateUIBubbleModel::TAB &&
+         bubble_ui_model_ != language::TranslateUIBubbleModel::BUTTON_GM2 &&
+         model_->GetViewState() != TranslateBubbleModel::VIEW_STATE_ERROR;
 }
 
 bool TranslateBubbleView::ShouldShowWindowTitle() const {
-  return bubble_ui_model_ != language::TranslateUIBubbleModel::TAB;
+  return bubble_ui_model_ != language::TranslateUIBubbleModel::TAB &&
+         bubble_ui_model_ != language::TranslateUIBubbleModel::BUTTON_GM2 &&
+         model_->GetViewState() != TranslateBubbleModel::VIEW_STATE_ERROR;
 }
 
 void TranslateBubbleView::ResetLanguage() {
@@ -339,7 +351,6 @@
         previous_source_language_index_ + 1);
     model_->UpdateOriginalLanguageIndex(
         source_language_combobox_->GetSelectedIndex() - 1);
-    UpdateAdvancedView();
   } else {
     if (target_language_combobox_->GetSelectedIndex() ==
         previous_target_language_index_) {
@@ -349,8 +360,8 @@
         previous_target_language_index_);
     model_->UpdateTargetLanguageIndex(
         target_language_combobox_->GetSelectedIndex());
-    UpdateAdvancedView();
   }
+  UpdateAdvancedView();
 }
 
 void TranslateBubbleView::WindowClosing() {
@@ -655,7 +666,45 @@
 
 void TranslateBubbleView::ConfirmAdvancedOptions() {
   model_->SetAlwaysTranslate(should_always_translate_);
-  if (bubble_ui_model_ != language::TranslateUIBubbleModel::TAB) {
+  if (bubble_ui_model_ == language::TranslateUIBubbleModel::BUTTON_GM2) {
+    if (model_->IsPageTranslatedInCurrentLanguages()) {
+      model_->GoBackFromAdvanced();
+      UpdateChildVisibilities();
+      SizeToContents();
+    } else {
+      model_->Translate();
+      // TODO(crbug.com/963148): Label text doesn't change immediately at
+      // translating view, but reflected at after translate view.
+      gm2_source_language_label_->SetText(
+          model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex()));
+      gm2_target_language_label_->SetText(
+          model_->GetLanguageNameAt(model_->GetTargetLanguageIndex()));
+      UpdateChildVisibilities();
+      SwitchView(TranslateBubbleModel::VIEW_STATE_TRANSLATING);
+    }
+  } else if (bubble_ui_model_ == language::TranslateUIBubbleModel::TAB) {
+    if (model_->IsPageTranslatedInCurrentLanguages()) {
+      SwitchView(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE);
+      SizeToContents();
+    } else {
+      // Remove and re-add the child view to update tab title without modifying
+      // existing tabbed_pane class. RemoveChildView doesn't delete the child
+      // view. It only removes child view from the children() vector.
+      // TODO(crbug.com/974811): Update tab title using setter and getter when
+      // it's available.
+      RemoveChildView(before_translate_view_);
+      delete before_translate_view_;
+
+      tab_translate_view_ = CreateViewTab();
+      before_translate_view_ = tab_translate_view_;
+      translating_view_ = tab_translate_view_;
+      after_translate_view_ = tab_translate_view_;
+
+      AddChildView(tab_translate_view_);
+      SwitchView(TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE);
+      tabbed_pane_->SelectTabAt(1);
+    }
+  } else {
     if (model_->IsPageTranslatedInCurrentLanguages()) {
       model_->GoBackFromAdvanced();
       UpdateChildVisibilities();
@@ -664,24 +713,6 @@
       model_->Translate();
       SwitchView(TranslateBubbleModel::VIEW_STATE_TRANSLATING);
     }
-  } else {
-    if (model_->IsPageTranslatedInCurrentLanguages()) {
-      SwitchView(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE);
-      SizeToContents();
-    } else {
-      RemoveChildView(before_translate_view_);
-      RemoveChildView(translating_view_);
-      RemoveChildView(after_translate_view_);
-      tab_translate_view_ = CreateViewTab();
-      before_translate_view_ = tab_translate_view_;
-      translating_view_ = tab_translate_view_;
-      after_translate_view_ = tab_translate_view_;
-      AddChildView(before_translate_view_);
-      AddChildView(translating_view_);
-      AddChildView(after_translate_view_);
-      SwitchView(TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE);
-      tabbed_pane_->SelectTabAt(1);
-    }
   }
   translate::ReportUiAction(translate::DONE_BUTTON_CLICKED);
 }
@@ -807,11 +838,11 @@
   before_translate_options_button_->set_request_focus_on_press(true);
 
   if (views::PlatformStyle::kIsOkButtonLeading) {
-    layout->AddView(accept_button.release());
+    layout->AddView(std::move(accept_button));
     layout->AddView(before_translate_options_button_);
   } else {
     layout->AddView(before_translate_options_button_);
-    layout->AddView(accept_button.release());
+    layout->AddView(std::move(accept_button));
   }
 
   return view;
@@ -858,7 +889,7 @@
   // when we release ownership of the unique_ptr.
   // TODO(crbug.com/963148): Initial auto translate doesn't trigger tabbed pane
   // to highlight the correct pane.
-  tabbed_pane_ = new views::TabbedPane();
+  auto tabbed_pane = std::make_unique<views::TabbedPane>();
 
   // Three dots options menu button
   const SkColor option_icon_color = gfx::kChromeIconGrey;
@@ -878,7 +909,6 @@
   // Close button
   const SkColor close_icon_color = gfx::kChromeIconGrey;
   const gfx::VectorIcon* close_icon_id = &vector_icons::kCloseRoundedIcon;
-
   // Use CreateVectorImageButton automatically enables background ink drop
   auto close_button = views::CreateVectorImageButton(this);
   // Size 18 is set for |translate_menu_button| while 16 is set for
@@ -893,7 +923,6 @@
   close_button->SetFocusForPlatform();
   close_button->SetID(BUTTON_ID_CLOSE);
 
-  // Initialize a column
   constexpr int kColumnSetId = 0;
   views::ColumnSet* cs = layout->AddColumnSet(kColumnSetId);
   cs->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
@@ -918,10 +947,10 @@
                 0);
 
   layout->StartRow(1, kColumnSetId);
-  layout->AddView(language_icon.release());
-  layout->AddView(tabbed_pane_);
-  layout->AddView(tab_translate_options_button.release());
-  layout->AddView(close_button.release());
+  layout->AddView(std::move(language_icon));
+  tabbed_pane_ = layout->AddView(std::move(tabbed_pane));
+  layout->AddView(std::move(tab_translate_options_button));
+  layout->AddView(std::move(close_button));
 
   // NOTE: Panes must be added after |tabbed_pane| has been added to its parent.
   tabbed_pane_->AddTab(original_language_name, CreateEmptyPane());
@@ -931,6 +960,190 @@
   return view;
 }
 
+views::View* TranslateBubbleView::GM2CreateView(
+    std::unique_ptr<views::Button> action_button,
+    std::unique_ptr<views::View> status_indicator,
+    bool active_option_button,
+    std::unique_ptr<views::Label> source_language_label,
+    std::unique_ptr<views::Label> target_language_label) {
+  views::View* view = new views::View();
+  views::GridLayout* layout =
+      view->SetLayoutManager(std::make_unique<views::GridLayout>());
+  ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
+
+  enum { COLUMN_SET_ID_TITLE, COLUMN_SET_ID_BUTTONS };
+
+  // Language icon
+  const int language_icon_id = IDR_TRANSLATE_BUBBLE_ICON;
+  std::unique_ptr<views::ImageView> language_icon =
+      std::make_unique<views::ImageView>();
+  gfx::ImageSkia* language_icon_image =
+      ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+          language_icon_id);
+  language_icon->SetImage(*language_icon_image);
+
+  // Close button
+  const SkColor close_icon_color = gfx::kChromeIconGrey;
+  const gfx::VectorIcon* close_icon_id = &vector_icons::kCloseRoundedIcon;
+  // Use CreateVectorImageButton automatically enables background ink drop
+  auto close_button = views::CreateVectorImageButton(this);
+  // Size 18 is set for |translate_menu_button| while 16 is set for
+  // |close_button| so that the ink down shadow for both buttons are the same.
+  // MenuButton's insets is smaller than ImageButton by 2. Height is
+  // unadjustable through AddColumn so setting column width will result in
+  // rectangular instead of square column shape.
+  close_button->SetImage(
+      views::Button::STATE_NORMAL,
+      gfx::CreateVectorIcon(*close_icon_id, 16, close_icon_color));
+  close_button->set_ink_drop_base_color(gfx::kChromeIconGrey);
+  close_button->SetID(BUTTON_ID_CLOSE);
+
+  // Initialize a columnset
+  views::ColumnSet* cs = layout->AddColumnSet(COLUMN_SET_ID_TITLE);
+  cs->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
+                views::GridLayout::kFixedSize, views::GridLayout::USE_PREF, 0,
+                0);
+  cs->AddPaddingColumn(views::GridLayout::kFixedSize,
+                       2 * provider->GetDistanceMetric(
+                               views::DISTANCE_RELATED_BUTTON_HORIZONTAL));
+  cs->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
+                views::GridLayout::kFixedSize, views::GridLayout::FIXED, 100,
+                0);
+  cs->AddPaddingColumn(views::GridLayout::kFixedSize,
+                       2 * provider->GetDistanceMetric(
+                               views::DISTANCE_RELATED_BUTTON_HORIZONTAL));
+  cs->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
+                views::GridLayout::kFixedSize, views::GridLayout::USE_PREF, 0,
+                0);
+  cs->AddPaddingColumn(views::GridLayout::kFixedSize,
+                       2 * provider->GetDistanceMetric(
+                               views::DISTANCE_RELATED_BUTTON_HORIZONTAL));
+  cs->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
+                views::GridLayout::kFixedSize, views::GridLayout::FIXED, 100,
+                0);
+  cs->AddPaddingColumn(views::GridLayout::kFixedSize,
+                       4 * provider->GetDistanceMetric(
+                               views::DISTANCE_UNRELATED_CONTROL_VERTICAL));
+  cs->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
+                views::GridLayout::kFixedSize, views::GridLayout::USE_PREF, 0,
+                0);
+
+  cs = layout->AddColumnSet(COLUMN_SET_ID_BUTTONS);
+  cs->AddPaddingColumn(1.0, 0);
+  cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
+                views::GridLayout::kFixedSize, views::GridLayout::USE_PREF, 0,
+                0);
+  cs->AddPaddingColumn(
+      views::GridLayout::kFixedSize,
+      provider->GetDistanceMetric(views::DISTANCE_RELATED_BUTTON_HORIZONTAL));
+  cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
+                views::GridLayout::kFixedSize, views::GridLayout::USE_PREF, 0,
+                0);
+
+  layout->StartRowWithPadding(
+      views::GridLayout::kFixedSize, COLUMN_SET_ID_TITLE,
+      views::GridLayout::kFixedSize,
+      provider->GetDistanceMetric(views::DISTANCE_UNRELATED_CONTROL_VERTICAL) /
+          2);
+  layout->AddView(std::move(language_icon));
+  gm2_source_language_label_ =
+      layout->AddView(std::move(source_language_label));
+  layout->AddView(std::move(status_indicator));
+  gm2_target_language_label_ =
+      layout->AddView(std::move(target_language_label));
+  layout->AddView(std::move(close_button));
+
+  layout->StartRowWithPadding(
+      views::GridLayout::kFixedSize, COLUMN_SET_ID_BUTTONS,
+      views::GridLayout::kFixedSize,
+      provider->GetDistanceMetric(views::DISTANCE_UNRELATED_CONTROL_VERTICAL) *
+          1.5);
+
+  std::unique_ptr<views::MdTextButtonWithDownArrow>
+      before_translate_options_button =
+          std::make_unique<views::MdTextButtonWithDownArrow>(
+              this, l10n_util::GetStringUTF16(
+                        IDS_TRANSLATE_BUBBLE_OPTIONS_MENU_BUTTON));
+  before_translate_options_button->SetID(BUTTON_ID_OPTIONS_MENU);
+  before_translate_options_button->set_request_focus_on_press(true);
+  before_translate_options_button->SetEnabled(active_option_button);
+
+  layout->AddView(std::move(action_button));
+  before_translate_options_button_ =
+      layout->AddView(std::move(before_translate_options_button));
+
+  return view;
+}
+
+views::View* TranslateBubbleView::GM2CreateViewBeforeTranslate() {
+  base::string16 gm2_source_language =
+      model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex());
+  base::string16 gm2_target_language =
+      model_->GetLanguageNameAt(model_->GetTargetLanguageIndex());
+  if (gm2_source_language.empty()) {
+    gm2_source_language =
+        l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_UNKNOWN_LANGUAGE);
+  }
+  // Source language label
+  auto gm2_source_language_label = std::make_unique<views::Label>(
+      gm2_source_language, views::style::CONTEXT_LABEL,
+      views::style::STYLE_LINK);
+
+  // Forward arrow
+  std::unique_ptr<views::ImageView> forward_arrow =
+      std::make_unique<views::ImageView>();
+  const gfx::VectorIcon& forward_arrow_image = vector_icons::kForwardArrowIcon;
+  const SkColor forward_arrow_image_color = gfx::kChromeIconGrey;
+  forward_arrow->SetImage(
+      gfx::CreateVectorIcon(forward_arrow_image, forward_arrow_image_color));
+
+  // Target language label
+  auto gm2_target_language_label = std::make_unique<views::Label>(
+      gm2_target_language, views::style::CONTEXT_LABEL,
+      views::style::STYLE_PRIMARY);
+
+  auto accept_button = views::MdTextButton::CreateSecondaryUiButton(
+      this, l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ACCEPT));
+  accept_button->SetID(BUTTON_ID_TRANSLATE);
+  accept_button->SetIsDefault(true);
+  return GM2CreateView(std::move(accept_button), std::move(forward_arrow), true,
+                       std::move(gm2_source_language_label),
+                       std::move(gm2_target_language_label));
+}
+
+views::View* TranslateBubbleView::GM2CreateViewTranslating() {
+  base::string16 gm2_source_language =
+      model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex());
+  base::string16 gm2_target_language =
+      model_->GetLanguageNameAt(model_->GetTargetLanguageIndex());
+  if (gm2_source_language.empty()) {
+    gm2_source_language =
+        l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_UNKNOWN_LANGUAGE);
+  }
+  // Source language label
+  auto gm2_source_language_label = std::make_unique<views::Label>(
+      gm2_source_language, views::style::CONTEXT_LABEL,
+      views::style::STYLE_LINK);
+  // Spinning Throb
+  std::unique_ptr<views::Throbber> spinning_throbber =
+      std::make_unique<views::Throbber>();
+  spinning_throbber->Start();
+
+  // Target language label
+  auto gm2_target_language_label = std::make_unique<views::Label>(
+      gm2_target_language, views::style::CONTEXT_LABEL,
+      views::style::STYLE_PRIMARY);
+
+  auto accept_button = views::MdTextButton::CreateSecondaryUiButton(
+      this, l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ACCEPT));
+  accept_button->SetID(BUTTON_ID_TRANSLATE);
+  accept_button->SetIsDefault(false);
+  accept_button->SetEnabled(false);
+  return GM2CreateView(std::move(accept_button), std::move(spinning_throbber),
+                       false, std::move(gm2_source_language_label),
+                       std::move(gm2_target_language_label));
+}
+
 views::View* TranslateBubbleView::CreateViewTranslating() {
   base::string16 target_language_name =
       model_->GetLanguageNameAt(model_->GetTargetLanguageIndex());
@@ -965,11 +1178,47 @@
       this, l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_REVERT));
   revert_button->SetID(BUTTON_ID_SHOW_ORIGINAL);
   revert_button->SetEnabled(false);
-  layout->AddView(revert_button.release());
+  layout->AddView(std::move(revert_button));
 
   return view;
 }
 
+views::View* TranslateBubbleView::GM2CreateViewAfterTranslate() {
+  base::string16 gm2_source_language =
+      model_->GetLanguageNameAt(model_->GetOriginalLanguageIndex());
+  base::string16 gm2_target_language =
+      model_->GetLanguageNameAt(model_->GetTargetLanguageIndex());
+  if (gm2_source_language.empty()) {
+    gm2_source_language =
+        l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_UNKNOWN_LANGUAGE);
+  }
+  // Source language label
+  auto gm2_source_language_label = std::make_unique<views::Label>(
+      gm2_source_language, views::style::CONTEXT_LABEL,
+      views::style::STYLE_PRIMARY);
+  // Forward arrow
+  std::unique_ptr<views::ImageView> forward_arrow =
+      std::make_unique<views::ImageView>();
+  const gfx::VectorIcon& forward_arrow_image = vector_icons::kForwardArrowIcon;
+  const SkColor forward_arrow_image_color = gfx::kChromeIconGrey;
+  forward_arrow->SetImage(
+      gfx::CreateVectorIcon(forward_arrow_image, forward_arrow_image_color));
+
+  // Target language label
+  auto gm2_target_language_label = std::make_unique<views::Label>(
+      gm2_target_language, views::style::CONTEXT_LABEL,
+      views::style::STYLE_LINK);
+
+  auto revert_button = views::MdTextButton::CreateSecondaryUiButton(
+      this, l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_REVERT));
+  revert_button->SetID(BUTTON_ID_SHOW_ORIGINAL);
+  revert_button->SetEnabled(true);
+
+  return GM2CreateView(std::move(revert_button), std::move(forward_arrow), true,
+                       std::move(gm2_source_language_label),
+                       std::move(gm2_target_language_label));
+}
+
 views::View* TranslateBubbleView::CreateViewAfterTranslate() {
   views::View* view = new views::View();
   views::GridLayout* layout =
@@ -999,7 +1248,7 @@
   auto button = views::MdTextButton::CreateSecondaryUiButton(
       this, l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_REVERT));
   button->SetID(BUTTON_ID_SHOW_ORIGINAL);
-  layout->AddView(button.release());
+  layout->AddView(std::move(button));
 
   views::Button* options_menu_button = new views::MdTextButtonWithDownArrow(
       this,
@@ -1042,13 +1291,13 @@
   auto try_again_button = views::MdTextButton::CreateSecondaryUiButton(
       this, l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_TRY_AGAIN));
   try_again_button->SetID(BUTTON_ID_TRY_AGAIN);
-  layout->AddView(try_again_button.release());
+  layout->AddView(std::move(try_again_button));
 
   auto advanced_button = views::MdTextButton::CreateSecondaryUiButton(
       this, l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ADVANCED_BUTTON));
   advanced_button->SetID(BUTTON_ID_ADVANCED);
-  layout->AddView(advanced_button.release());
-
+  layout->AddView(std::move(advanced_button));
+  Layout();
   return view;
 }
 
@@ -1177,11 +1426,10 @@
 
 views::View* TranslateBubbleView::TabUiCreateViewAdvanedSource() {
   // Bubble title
-  // TODO(crbug.com/963148): Update label font to be the same as widget title
-  // font.
   std::unique_ptr<views::Label> source_language_title_label =
       std::make_unique<views::Label>(
-          l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ADVANCED_SOURCE));
+          l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ADVANCED_SOURCE),
+          views::style::CONTEXT_DIALOG_TITLE);
 
   // Index + 1 because GetOriginalLanguageIndex() returns the actual index - 1
   // to accommodate added label "Unknown". (crbug/721600)
@@ -1203,11 +1451,10 @@
 
 views::View* TranslateBubbleView::TabUiCreateViewAdvanedTarget() {
   // Bubble title
-  // TODO(crbug.com/963148): Update label font to be the same as widget title
-  // font.
   std::unique_ptr<views::Label> target_language_title_label =
       std::make_unique<views::Label>(
-          l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ADVANCED_TARGET));
+          l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ADVANCED_TARGET),
+          views::style::CONTEXT_DIALOG_TITLE);
 
   int target_default_index = model_->GetTargetLanguageIndex();
   target_language_combobox_model_.reset(
@@ -1257,11 +1504,7 @@
   views::GridLayout* layout =
       view->SetLayoutManager(std::make_unique<views::GridLayout>());
 
-  enum {
-    COLUMN_SET_ID_TITLE,
-    COLUMN_SET_ID_LANGUAGES,
-    COLUMN_SET_ID_BUTTONS,
-  };
+  enum { COLUMN_SET_ID_TITLE, COLUMN_SET_ID_LANGUAGES, COLUMN_SET_ID_BUTTONS };
 
   ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
 
@@ -1286,16 +1529,19 @@
   cs->AddPaddingColumn(1.0, 0);
 
   cs = layout->AddColumnSet(COLUMN_SET_ID_LANGUAGES);
-  cs->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER,
-                views::GridLayout::kFixedSize, views::GridLayout::USE_PREF, 0,
-                0);
+
+  cs->AddPaddingColumn(
+      views::GridLayout::kFixedSize,
+      provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_HORIZONTAL));
+  cs->AddPaddingColumn(
+      views::GridLayout::kFixedSize,
+      provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_HORIZONTAL));
   cs->AddPaddingColumn(
       views::GridLayout::kFixedSize,
       provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_HORIZONTAL));
   cs->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
                 views::GridLayout::kFixedSize, views::GridLayout::USE_PREF, 0,
                 0);
-  cs->AddPaddingColumn(1.0, 0);
 
   cs = layout->AddColumnSet(COLUMN_SET_ID_BUTTONS);
   cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
@@ -1314,16 +1560,16 @@
                 0);
 
   layout->StartRow(views::GridLayout::kFixedSize, COLUMN_SET_ID_TITLE);
-  layout->AddView(language_icon.release());
-  layout->AddView(language_title_label.release());
-  layout->AddView(close_button.release());
+  layout->AddView(std::move(language_icon));
+  layout->AddView(std::move(language_title_label));
+  layout->AddView(std::move(close_button));
 
   const int vertical_spacing =
       provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL);
   layout->AddPaddingRow(views::GridLayout::kFixedSize, vertical_spacing);
 
   layout->StartRow(views::GridLayout::kFixedSize, COLUMN_SET_ID_LANGUAGES);
-  layout->SkipColumns(1);
+
   // TODO(crbug.com/963148): Combobox doesn't take up the whole row as shown
   // in mock.
   layout->AddView(combobox);
@@ -1340,11 +1586,8 @@
   auto advanced_reset_button = views::MdTextButton::CreateSecondaryUiButton(
       this, l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_RESET));
   advanced_reset_button->SetID(BUTTON_ID_RESET);
-  advanced_done_button_ = advanced_done_button.release();
-  advanced_cancel_button_ = advanced_reset_button.release();
-
-  layout->AddView(advanced_done_button_);
-  layout->AddView(advanced_cancel_button_);
+  advanced_done_button_ = layout->AddView(std::move(advanced_done_button));
+  advanced_cancel_button_ = layout->AddView(std::move(advanced_reset_button));
 
   UpdateAdvancedView();
 
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.h b/chrome/browser/ui/views/translate/translate_bubble_view.h
index 2fb896b..29be5ba0 100644
--- a/chrome/browser/ui/views/translate/translate_bubble_view.h
+++ b/chrome/browser/ui/views/translate/translate_bubble_view.h
@@ -220,7 +220,7 @@
   // Triggers options menu.
   void ShowOptionsMenu(views::Button* source);
 
-  // Triggers options menu in TAB ui.
+  // Triggers options menu in TAB UI.
   void ShowOptionsMenuTab(views::Button* source);
 
   // Handles the event when the user clicks a link.
@@ -232,9 +232,8 @@
   // Updates the visibilities of child views according to the current view type.
   void UpdateChildVisibilities();
 
-  // Creates the 'before translate' view. Caller takes ownership of the returned
-  // view. Three options depending on UI selection in
-  // kUseButtonTranslateBubbleUI.
+  // Creates the 'before translate' view for the existing Button UI. Caller
+  // takes ownership of the returned view.
   views::View* CreateViewBeforeTranslate();
 
   // Creates the view for TAB UI. This view is being used before/during/after
@@ -245,14 +244,12 @@
   // This function creates an empty view so no extra white space below the tab.
   views::View* CreateEmptyPane();
 
-  // Creates the 'translating' view. Caller takes ownership of the returned
-  // view. Three options depending on UI selection in
-  // kUseButtonTranslateBubbleUI.
+  // Creates the 'translating' view for the existing Button UI. Caller takes
+  // ownership of the returned view.
   views::View* CreateViewTranslating();
 
-  // Creates the 'after translate' view. Caller takes ownership of the returned
-  // view. Three options depending on UI selection in
-  // kUseButtonTranslateBubbleUI.
+  // Creates the 'after translate' view for the existing Button UI. Caller takes
+  // ownership of the returned view.
   views::View* CreateViewAfterTranslate();
 
   // Creates the 'error' view. Caller takes ownership of the returned view.
@@ -263,12 +260,32 @@
   // Three options depending on UI selection in kUseButtonTranslateBubbleUI.
   views::View* CreateViewAdvanced();
 
-  // Creates source language label and combobox for Tab Ui advanced view
+  // Creates source language label and combobox for Tab UI advanced view.
   views::View* TabUiCreateViewAdvanedSource();
 
-  // Creates source language label and combobox for Tab Ui advanced view
+  // Creates source language label and combobox for Tab UI advanced view.
   views::View* TabUiCreateViewAdvanedTarget();
 
+  // Creates the skeleton view for GM2 UI.
+  views::View* GM2CreateView(
+      std::unique_ptr<views::Button> action_button,
+      std::unique_ptr<views::View> status_indicator,
+      bool active_option_button,
+      std::unique_ptr<views::Label> source_language_label,
+      std::unique_ptr<views::Label> target_language_label);
+
+  // Creates the 'before translate' view for Button_GM2 UI. Caller takes
+  // ownership of the returned view.
+  views::View* GM2CreateViewBeforeTranslate();
+
+  // Creates the 'translating' view for Button_GM2 UI. Caller takes ownership
+  // of the returned view.
+  views::View* GM2CreateViewTranslating();
+
+  // Creates the 'after translate' view for Button_GM2 UI. Caller takes
+  // ownership of the returned view.
+  views::View* GM2CreateViewAfterTranslate();
+
   // Creates the 'advanced' view to show source/target language combobox under
   // TAB UI. Caller takes ownership of the returned view.
   views::View* CreateViewAdvancedTabUi(
@@ -295,7 +312,7 @@
   // Return true if the current state is in advanced state for TAB UI.
   bool TabUiIsAdvancedState(TranslateBubbleModel::ViewState view_state);
 
-  // Handles the reset button in advanced view under Tab Ui.
+  // Handles the reset button in advanced view under Tab UI.
   void ResetLanguage();
 
   static TranslateBubbleView* translate_bubble_view_;
@@ -319,6 +336,11 @@
   views::Checkbox* advanced_always_translate_checkbox_;
   views::TabbedPane* tabbed_pane_;
 
+  // Button_GM2 UI source/target language label class variable to be updated
+  // based on user selction in
+  views::Label* gm2_source_language_label_;
+  views::Label* gm2_target_language_label_;
+
   views::LabelButton* advanced_cancel_button_;
   views::LabelButton* advanced_done_button_;
 
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index 155d86d..a8fe7c7 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -48,6 +48,7 @@
 #include "chrome/browser/ui/webui/memory_internals_ui.h"
 #include "chrome/browser/ui/webui/net_export_ui.h"
 #include "chrome/browser/ui/webui/net_internals/net_internals_ui.h"
+#include "chrome/browser/ui/webui/notifications_internals/notifications_internals_ui.h"
 #include "chrome/browser/ui/webui/ntp_tiles_internals_ui.h"
 #include "chrome/browser/ui/webui/omnibox/omnibox_ui.h"
 #include "chrome/browser/ui/webui/password_manager_internals/password_manager_internals_ui.h"
@@ -393,6 +394,8 @@
     return &NewWebUI<NetExportUI>;
   if (url.host_piece() == chrome::kChromeUINetInternalsHost)
     return &NewWebUI<NetInternalsUI>;
+  if (url.host_piece() == chrome::kChromeUINotificationsInternalsHost)
+    return &NewWebUI<NotificationsInternalsUI>;
   if (url.host_piece() == chrome::kChromeUINTPTilesInternalsHost)
     return &NewWebUI<NTPTilesInternalsUI>;
   if (url.host_piece() == chrome::kChromeUIOmniboxHost)
diff --git a/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.cc b/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.cc
index 31b9f17..5d25b7f2 100644
--- a/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.cc
@@ -25,7 +25,7 @@
 
 namespace {
 
-constexpr int kDialogHeightPx = 672;
+constexpr int kDialogHeightPx = 640;
 constexpr int kDialogWidthPx = 768;
 // Id of System Dialog used to show the Add Supervision flow.
 std::string& GetDialogId() {
diff --git a/chrome/browser/ui/webui/chromeos/insession_password_change_handler_chromeos.cc b/chrome/browser/ui/webui/chromeos/insession_password_change_handler_chromeos.cc
index 6ff7c11..6b829f1f3 100644
--- a/chrome/browser/ui/webui/chromeos/insession_password_change_handler_chromeos.cc
+++ b/chrome/browser/ui/webui/chromeos/insession_password_change_handler_chromeos.cc
@@ -9,7 +9,10 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_process_platform_part_chromeos.h"
 #include "chrome/browser/chromeos/login/auth/chrome_cryptohome_authenticator.h"
+#include "chrome/browser/chromeos/login/saml/in_session_password_change_manager.h"
 #include "chrome/browser/chromeos/login/saml/saml_password_expiry_notification.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/profiles/profile.h"
@@ -57,12 +60,16 @@
                                                           true);
   if (new_passwords.GetList().size() == 1 &&
       old_passwords.GetList().size() > 0) {
-    UserContext user_context(*user);
-    user_context.SetKey(Key(new_passwords.GetList()[0].GetString()));
-    authenticator_ = new ChromeCryptohomeAuthenticator(this);
-    authenticator_->MigrateKey(user_context,
-                               old_passwords.GetList()[0].GetString());
+    auto* in_session_password_change_manager =
+        g_browser_process->platform_part()
+            ->in_session_password_change_manager();
+    CHECK(in_session_password_change_manager);
+    in_session_password_change_manager->ChangePassword(
+        old_passwords.GetList()[0].GetString(),
+        new_passwords.GetList()[0].GetString());
   }
+
+  // TODO(https://crbug.com/930109): Failed to scrape passwords - show dialog.
 }
 
 void InSessionPasswordChangeHandler::RegisterMessages() {
@@ -76,29 +83,4 @@
                           weak_factory_.GetWeakPtr()));
 }
 
-void InSessionPasswordChangeHandler::OnAuthSuccess(
-    const UserContext& user_context) {
-  VLOG(3) << "Cryptohome password is changed.";
-  user_manager::UserManager::Get()->SaveForceOnlineSignin(
-      user_context.GetAccountId(), false);
-  authenticator_.reset();
-
-  // Clear expiration time from prefs so that we don't keep nagging the user to
-  // change password (until the SAML provider tells us a new expiration time).
-  Profile* profile = Profile::FromWebUI(web_ui());
-  SamlPasswordAttributes loaded =
-      SamlPasswordAttributes::LoadFromPrefs(profile->GetPrefs());
-  SamlPasswordAttributes(
-      /*modified_time=*/base::Time::Now(), /*expiration_time=*/base::Time(),
-      loaded.password_change_url())
-      .SaveToPrefs(profile->GetPrefs());
-  DismissSamlPasswordExpiryNotification(profile);
-}
-
-void InSessionPasswordChangeHandler::OnAuthFailure(const AuthFailure& error) {
-  // TODO(rsorokin): Ask user for the old password
-  VLOG(1) << "Failed to change cryptohome password: " << error.GetErrorString();
-  authenticator_.reset();
-}
-
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/insession_password_change_handler_chromeos.h b/chrome/browser/ui/webui/chromeos/insession_password_change_handler_chromeos.h
index 97eb55e..8e40a84 100644
--- a/chrome/browser/ui/webui/chromeos/insession_password_change_handler_chromeos.h
+++ b/chrome/browser/ui/webui/chromeos/insession_password_change_handler_chromeos.h
@@ -7,14 +7,12 @@
 
 #include "base/memory/weak_ptr.h"
 #include "base/values.h"
-#include "chromeos/login/auth/auth_status_consumer.h"
 #include "chromeos/login/auth/cryptohome_authenticator.h"
 #include "content/public/browser/web_ui_message_handler.h"
 
 namespace chromeos {
 
-class InSessionPasswordChangeHandler : public content::WebUIMessageHandler,
-                                       AuthStatusConsumer {
+class InSessionPasswordChangeHandler : public content::WebUIMessageHandler {
  public:
   explicit InSessionPasswordChangeHandler(
       const std::string& password_change_url);
@@ -26,10 +24,6 @@
   void HandleInitialize(const base::ListValue*);
   void HandleChangePassword(const base::ListValue* passwords);
 
-  // AuthStatusConsumer:
-  void OnAuthFailure(const AuthFailure& error) override;
-  void OnAuthSuccess(const UserContext& user_context) override;
-
  private:
   const std::string password_change_url_;
   scoped_refptr<CryptohomeAuthenticator> authenticator_;
diff --git a/chrome/browser/ui/webui/favicon_source.cc b/chrome/browser/ui/webui/favicon_source.cc
index f866bd30..7b14ed5 100644
--- a/chrome/browser/ui/webui/favicon_source.cc
+++ b/chrome/browser/ui/webui/favicon_source.cc
@@ -44,21 +44,6 @@
   return favicon::FaviconRequestOrigin::UNKNOWN;
 }
 
-sync_sessions::OpenTabsUIDelegate* GetOpenTabsUIDelegate(Profile* profile) {
-  sync_sessions::SessionSyncService* session_sync_service =
-      SessionSyncServiceFactory::GetInstance()->GetForProfile(profile);
-  DCHECK(session_sync_service);
-  return session_sync_service->GetOpenTabsUIDelegate();
-}
-
-scoped_refptr<base::RefCountedMemory> GetSyncedFaviconForPageURL(
-    Profile* profile,
-    const GURL& page_url) {
-  sync_sessions::OpenTabsUIDelegate* open_tabs = GetOpenTabsUIDelegate(profile);
-  return open_tabs ? open_tabs->GetSyncedFaviconForPageURL(page_url.spec())
-                   : nullptr;
-}
-
 // Check if user settings allow querying a Google server using history
 // information.
 bool CanSendHistoryDataToServer(Profile* profile) {
@@ -166,8 +151,10 @@
       SendDefaultResponse(callback);
       return;
     }
+    sync_sessions::SessionSyncService* session_sync_service =
+        SessionSyncServiceFactory::GetInstance()->GetForProfile(profile_);
     sync_sessions::OpenTabsUIDelegate* open_tabs =
-        GetOpenTabsUIDelegate(profile_);
+        session_sync_service->GetOpenTabsUIDelegate();
     favicon_request_handler->GetRawFaviconForPageURL(
         url, desired_size_in_pixel,
         base::BindOnce(&FaviconSource::OnFaviconDataAvailable,
@@ -177,7 +164,6 @@
         unsafe_request_origin, favicon::FaviconRequestPlatform::kDesktop,
         /*icon_url_for_uma=*/
         open_tabs ? open_tabs->GetIconUrlForPageUrl(url) : GURL(),
-        base::BindOnce(&GetSyncedFaviconForPageURL, base::Unretained(profile_)),
         CanSendHistoryDataToServer(profile_), &cancelable_task_tracker_);
   }
 }
diff --git a/chrome/browser/ui/webui/notifications_internals/OWNERS b/chrome/browser/ui/webui/notifications_internals/OWNERS
new file mode 100644
index 0000000..1ce49a53
--- /dev/null
+++ b/chrome/browser/ui/webui/notifications_internals/OWNERS
@@ -0,0 +1,2 @@
+file://chrome/browser/notifications/OWNERS
+file://chrome/browser/notifications/scheduler/OWNERS
diff --git a/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui.cc b/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui.cc
new file mode 100644
index 0000000..596be278
--- /dev/null
+++ b/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui.cc
@@ -0,0 +1,36 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/notifications_internals/notifications_internals_ui.h"
+
+#include <memory>
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/notifications_internals/notifications_internals_ui_message_handler.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/grit/browser_resources.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_controller.h"
+#include "content/public/browser/web_ui_data_source.h"
+
+NotificationsInternalsUI::NotificationsInternalsUI(content::WebUI* web_ui)
+    : content::WebUIController(web_ui) {
+  content::WebUIDataSource* html_source = content::WebUIDataSource::Create(
+      chrome::kChromeUINotificationsInternalsHost);
+  html_source->AddResourcePath("notifications_internals.css",
+                               IDR_NOTIFICATIONS_INTERNALS_CSS);
+  html_source->AddResourcePath("notifications_internals.js",
+                               IDR_NOTIFICATIONS_INTERNALS_JS);
+  html_source->AddResourcePath("notifications_internals_browser_proxy.js",
+                               IDR_NOTIFICATIONS_INTERNALS_BROWSER_PROXY_JS);
+  html_source->SetDefaultResource(IDR_NOTIFICATIONS_INTERNALS_HTML);
+
+  Profile* profile = Profile::FromWebUI(web_ui);
+  content::WebUIDataSource::Add(profile, html_source);
+
+  web_ui->AddMessageHandler(
+      std::make_unique<NotificationsInternalsUIMessageHandler>(profile));
+}
+
+NotificationsInternalsUI::~NotificationsInternalsUI() = default;
diff --git a/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui.h b/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui.h
new file mode 100644
index 0000000..7507bcf
--- /dev/null
+++ b/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui.h
@@ -0,0 +1,25 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_NOTIFICATIONS_INTERNALS_NOTIFICATIONS_INTERNALS_UI_H_
+#define CHROME_BROWSER_UI_WEBUI_NOTIFICATIONS_INTERNALS_NOTIFICATIONS_INTERNALS_UI_H_
+
+#include "base/macros.h"
+#include "content/public/browser/web_ui_controller.h"
+
+namespace content {
+class WebUI;
+}  // namespace content
+
+// The WebUI for chrome://notifications-internals.
+class NotificationsInternalsUI : public content::WebUIController {
+ public:
+  explicit NotificationsInternalsUI(content::WebUI* web_ui);
+  ~NotificationsInternalsUI() override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NotificationsInternalsUI);
+};
+
+#endif  // CHROME_BROWSER_UI_WEBUI_NOTIFICATIONS_INTERNALS_NOTIFICATIONS_INTERNALS_UI_H_
diff --git a/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui_message_handler.cc b/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui_message_handler.cc
new file mode 100644
index 0000000..a74af87
--- /dev/null
+++ b/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui_message_handler.cc
@@ -0,0 +1,47 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/notifications_internals/notifications_internals_ui_message_handler.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/values.h"
+#include "chrome/browser/notifications/scheduler/notification_schedule_service_factory.h"
+#include "chrome/browser/notifications/scheduler/public/notification_params.h"
+#include "chrome/browser/notifications/scheduler/public/notification_schedule_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "content/public/browser/web_ui.h"
+
+NotificationsInternalsUIMessageHandler::NotificationsInternalsUIMessageHandler(
+    Profile* profile)
+    : schedule_service_(
+          NotificationScheduleServiceFactory::GetForBrowserContext(profile)) {}
+
+NotificationsInternalsUIMessageHandler::
+    ~NotificationsInternalsUIMessageHandler() = default;
+
+void NotificationsInternalsUIMessageHandler::RegisterMessages() {
+  web_ui()->RegisterMessageCallback(
+      "scheduleNotification",
+      base::BindRepeating(
+          &NotificationsInternalsUIMessageHandler::HandleScheduleNotification,
+          base::Unretained(this)));
+}
+
+void NotificationsInternalsUIMessageHandler::HandleScheduleNotification(
+    const base::ListValue* args) {
+  CHECK_EQ(args->GetList().size(), 4u);
+  notifications::ScheduleParams schedule_params;
+  notifications::NotificationData data;
+  data.url = args->GetList()[1].GetString();
+  data.title = args->GetList()[2].GetString();
+  data.message = args->GetList()[3].GetString();
+  auto params = std::make_unique<notifications::NotificationParams>(
+      notifications::SchedulerClientType::kWebUI, std::move(data),
+      std::move(schedule_params));
+  schedule_service_->Schedule(std::move(params));
+}
diff --git a/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui_message_handler.h b/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui_message_handler.h
new file mode 100644
index 0000000..35fe4ea
--- /dev/null
+++ b/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui_message_handler.h
@@ -0,0 +1,41 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_NOTIFICATIONS_INTERNALS_NOTIFICATIONS_INTERNALS_UI_MESSAGE_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_NOTIFICATIONS_INTERNALS_NOTIFICATIONS_INTERNALS_UI_MESSAGE_HANDLER_H_
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "content/public/browser/web_ui_message_handler.h"
+
+namespace base {
+class ListValue;
+}  // namespace base
+
+namespace notifications {
+class NotificationScheduleService;
+}  // namespace notifications
+
+class Profile;
+
+// Routes html events to native notification systems in
+// chrome://notifications-internals.
+class NotificationsInternalsUIMessageHandler
+    : public content::WebUIMessageHandler {
+ public:
+  explicit NotificationsInternalsUIMessageHandler(Profile* profile);
+  ~NotificationsInternalsUIMessageHandler() override;
+
+  // content::WebUIMessageHandler implementation.
+  void RegisterMessages() override;
+
+ private:
+  void HandleScheduleNotification(const base::ListValue* args);
+
+  notifications::NotificationScheduleService* schedule_service_;
+
+  DISALLOW_COPY_AND_ASSIGN(NotificationsInternalsUIMessageHandler);
+};
+
+#endif  // CHROME_BROWSER_UI_WEBUI_NOTIFICATIONS_INTERNALS_NOTIFICATIONS_INTERNALS_UI_MESSAGE_HANDLER_H_
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
index 4612d36..8960616 100644
--- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
@@ -836,21 +836,21 @@
 void CupsPrintersHandler::HandleGetCupsPrinterManufacturers(
     const base::ListValue* args) {
   AllowJavascript();
-  std::string js_callback;
+  std::string callback_id;
   CHECK_EQ(1U, args->GetSize());
-  CHECK(args->GetString(0, &js_callback));
+  CHECK(args->GetString(0, &callback_id));
   ppd_provider_->ResolveManufacturers(
       base::Bind(&CupsPrintersHandler::ResolveManufacturersDone,
-                 weak_factory_.GetWeakPtr(), js_callback));
+                 weak_factory_.GetWeakPtr(), callback_id));
 }
 
 void CupsPrintersHandler::HandleGetCupsPrinterModels(
     const base::ListValue* args) {
   AllowJavascript();
-  std::string js_callback;
+  std::string callback_id;
   std::string manufacturer;
   CHECK_EQ(2U, args->GetSize());
-  CHECK(args->GetString(0, &js_callback));
+  CHECK(args->GetString(0, &callback_id));
   CHECK(args->GetString(1, &manufacturer));
 
   // Empty manufacturer queries may be triggered as a part of the ui
@@ -859,14 +859,14 @@
     base::DictionaryValue response;
     response.SetBoolean("success", true);
     response.Set("models", std::make_unique<base::ListValue>());
-    ResolveJavascriptCallback(base::Value(js_callback), response);
+    ResolveJavascriptCallback(base::Value(callback_id), response);
     return;
   }
 
   ppd_provider_->ResolvePrinters(
       manufacturer,
       base::Bind(&CupsPrintersHandler::ResolvePrintersDone,
-                 weak_factory_.GetWeakPtr(), manufacturer, js_callback));
+                 weak_factory_.GetWeakPtr(), manufacturer, callback_id));
 }
 
 void CupsPrintersHandler::HandleSelectPPDFile(const base::ListValue* args) {
@@ -891,7 +891,7 @@
 }
 
 void CupsPrintersHandler::ResolveManufacturersDone(
-    const std::string& js_callback,
+    const std::string& callback_id,
     PpdProvider::CallbackResultCode result_code,
     const std::vector<std::string>& manufacturers) {
   auto manufacturers_value = std::make_unique<base::ListValue>();
@@ -901,12 +901,12 @@
   base::DictionaryValue response;
   response.SetBoolean("success", result_code == PpdProvider::SUCCESS);
   response.Set("manufacturers", std::move(manufacturers_value));
-  ResolveJavascriptCallback(base::Value(js_callback), response);
+  ResolveJavascriptCallback(base::Value(callback_id), response);
 }
 
 void CupsPrintersHandler::ResolvePrintersDone(
     const std::string& manufacturer,
-    const std::string& js_callback,
+    const std::string& callback_id,
     PpdProvider::CallbackResultCode result_code,
     const PpdProvider::ResolvedPrintersList& printers) {
   auto printers_value = std::make_unique<base::ListValue>();
@@ -919,7 +919,7 @@
   base::DictionaryValue response;
   response.SetBoolean("success", result_code == PpdProvider::SUCCESS);
   response.Set("models", std::move(printers_value));
-  ResolveJavascriptCallback(base::Value(js_callback), response);
+  ResolveJavascriptCallback(base::Value(callback_id), response);
 }
 
 void CupsPrintersHandler::FileSelected(const base::FilePath& path,
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
index 42c17f4..d87c857 100644
--- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
@@ -136,11 +136,11 @@
   void HandleSelectPPDFile(const base::ListValue* args);
 
   // PpdProvider callback handlers.
-  void ResolveManufacturersDone(const std::string& js_callback,
+  void ResolveManufacturersDone(const std::string& callback_id,
                                 PpdProvider::CallbackResultCode result_code,
                                 const std::vector<std::string>& available);
   void ResolvePrintersDone(const std::string& manufacturer,
-                           const std::string& js_callback,
+                           const std::string& callback_id,
                            PpdProvider::CallbackResultCode result_code,
                            const PpdProvider::ResolvedPrintersList& printers);
 
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
index 40ec7601..cdea805 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -1333,6 +1333,12 @@
        IDS_SETTINGS_INTERNET_KNOWN_NETWORKS_MENU_FORGET},
       {"networkAllowDataRoaming",
        IDS_SETTINGS_SETTINGS_NETWORK_ALLOW_DATA_ROAMING},
+      {"networkAllowDataRoamingEnabledHome",
+       IDS_SETTINGS_SETTINGS_NETWORK_ALLOW_DATA_ROAMING_ENABLED_HOME},
+      {"networkAllowDataRoamingEnabledRoaming",
+       IDS_SETTINGS_SETTINGS_NETWORK_ALLOW_DATA_ROAMING_ENABLED_ROAMING},
+      {"networkAllowDataRoamingDisabled",
+       IDS_SETTINGS_SETTINGS_NETWORK_ALLOW_DATA_ROAMING_DISABLED},
       {"networkAlwaysOnVpn", IDS_SETTINGS_INTERNET_NETWORK_ALWAYS_ON_VPN},
       {"networkAutoConnect", IDS_SETTINGS_INTERNET_NETWORK_AUTO_CONNECT},
       {"networkAutoConnectCellular",
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc
index 6160b13..04f1337 100644
--- a/chrome/common/webui_url_constants.cc
+++ b/chrome/common/webui_url_constants.cc
@@ -107,6 +107,7 @@
 const char kChromeUINewTabHost[] = "newtab";
 const char kChromeUINewTabIconHost[] = "ntpicon";
 const char kChromeUINewTabURL[] = "chrome://newtab/";
+const char kChromeUINotificationsInternalsHost[] = "notifications-internals";
 const char kChromeUIOmniboxHost[] = "omnibox";
 const char kChromeUIOmniboxURL[] = "chrome://omnibox/";
 const char kChromeUIPasswordManagerInternalsHost[] =
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h
index 9a26a1b1..d58f6f0 100644
--- a/chrome/common/webui_url_constants.h
+++ b/chrome/common/webui_url_constants.h
@@ -112,6 +112,7 @@
 extern const char kChromeUINewTabHost[];
 extern const char kChromeUINewTabIconHost[];
 extern const char kChromeUINewTabURL[];
+extern const char kChromeUINotificationsInternalsHost[];
 extern const char kChromeUIOfflineInternalsHost[];
 extern const char kChromeUIOmniboxHost[];
 extern const char kChromeUIOmniboxURL[];
diff --git a/chrome/installer/mac/BUILD.gn b/chrome/installer/mac/BUILD.gn
index 8834cc2..90f132a 100644
--- a/chrome/installer/mac/BUILD.gn
+++ b/chrome/installer/mac/BUILD.gn
@@ -81,6 +81,8 @@
     "$root_out_dir/liblzma_decompress.dylib",
     "$root_out_dir/xz",
     "$root_out_dir/xzdec",
+    "//chrome/app/helper-plugin-entitlements.plist",
+    "//chrome/app/helper-renderer-entitlements.plist",
     "app_resource_rules.plist",
     "dirdiffer.sh",
     "dirpatcher.sh",
diff --git a/chrome/installer/mac/signing/modification.py b/chrome/installer/mac/signing/modification.py
index 05a8acb..62ae769 100644
--- a/chrome/installer/mac/signing/modification.py
+++ b/chrome/installer/mac/signing/modification.py
@@ -161,9 +161,11 @@
         if dist.channel_customize:
             with commands.PlistContext(
                     entitlements_file, rewrite=True) as entitlements:
-                app_id = entitlements[_ENT_APP_ID]
-                entitlements[_ENT_APP_ID] = app_id.replace(
-                    config.base_config.base_bundle_id, config.base_bundle_id)
+                if _ENT_APP_ID in entitlements:
+                    app_id = entitlements[_ENT_APP_ID]
+                    entitlements[_ENT_APP_ID] = app_id.replace(
+                        config.base_config.base_bundle_id,
+                        config.base_bundle_id)
 
 
 def customize_distribution(paths, dist, config):
diff --git a/chrome/installer/mac/signing/modification_test.py b/chrome/installer/mac/signing/modification_test.py
index 9bbc0fe..32f3b9b2 100644
--- a/chrome/installer/mac/signing/modification_test.py
+++ b/chrome/installer/mac/signing/modification_test.py
@@ -26,6 +26,8 @@
         '$W/app-entitlements.plist': {
             'com.apple.application-identifier': bundle_id
         },
+        '$W/helper-renderer-entitlements.plist': {},
+        '$W/helper-plugin-entitlements.plist': {},
         '$W/App Product Canary.app/Contents/Resources/test.signing.bundle_id.canary.manifest/Contents/Resources/test.signing.bundle_id.canary.manifest':
             {
                 'pfm_domain': bundle_id
@@ -64,9 +66,15 @@
             '$W/App Product.app/Contents/Info.plist',
         )
 
-        kwargs['copy_files'].assert_called_once_with(
-            '$I/Product Packaging/app-entitlements.plist',
-            '$W/app-entitlements.plist')
+        self.assertEqual(3, kwargs['copy_files'].call_count)
+        kwargs['copy_files'].assert_has_calls([
+            mock.call('$I/Product Packaging/app-entitlements.plist',
+                      '$W/app-entitlements.plist'),
+            mock.call('$I/Product Packaging/helper-renderer-entitlements.plist',
+                      '$W/helper-renderer-entitlements.plist'),
+            mock.call('$I/Product Packaging/helper-plugin-entitlements.plist',
+                      '$W/helper-plugin-entitlements.plist')
+        ])
         self.assertEqual(0, kwargs['move_file'].call_count)
         self.assertEqual(0, kwargs['write_file'].call_count)
 
@@ -86,9 +94,15 @@
             '$W/App Product.app/Contents/Info.plist',
         )
 
-        kwargs['copy_files'].assert_called_once_with(
-            '$I/Product Packaging/app-entitlements.plist',
-            '$W/app-entitlements.plist')
+        self.assertEqual(3, kwargs['copy_files'].call_count)
+        kwargs['copy_files'].assert_has_calls([
+            mock.call('$I/Product Packaging/app-entitlements.plist',
+                      '$W/app-entitlements.plist'),
+            mock.call('$I/Product Packaging/helper-renderer-entitlements.plist',
+                      '$W/helper-renderer-entitlements.plist'),
+            mock.call('$I/Product Packaging/helper-plugin-entitlements.plist',
+                      '$W/helper-plugin-entitlements.plist')
+        ])
         self.assertEqual(0, kwargs['move_file'].call_count)
 
     def test_distribution_with_channel(self, plistlib, **kwargs):
@@ -108,9 +122,15 @@
             '$W/App Product.app/Contents/Info.plist',
         )
 
-        kwargs['copy_files'].assert_called_once_with(
-            '$I/Product Packaging/app-entitlements.plist',
-            '$W/app-entitlements.plist')
+        self.assertEqual(3, kwargs['copy_files'].call_count)
+        kwargs['copy_files'].assert_has_calls([
+            mock.call('$I/Product Packaging/app-entitlements.plist',
+                      '$W/app-entitlements.plist'),
+            mock.call('$I/Product Packaging/helper-renderer-entitlements.plist',
+                      '$W/helper-renderer-entitlements.plist'),
+            mock.call('$I/Product Packaging/helper-plugin-entitlements.plist',
+                      '$W/helper-plugin-entitlements.plist')
+        ])
         self.assertEqual(0, kwargs['move_file'].call_count)
         self.assertEqual(0, kwargs['write_file'].call_count)
 
@@ -130,9 +150,15 @@
             '$W/App Product.app/Contents/Info.plist',
         )
 
-        kwargs['copy_files'].assert_called_once_with(
-            '$I/Product Packaging/app-entitlements.plist',
-            '$W/app-entitlements.plist')
+        self.assertEqual(3, kwargs['copy_files'].call_count)
+        kwargs['copy_files'].assert_has_calls([
+            mock.call('$I/Product Packaging/app-entitlements.plist',
+                      '$W/app-entitlements.plist'),
+            mock.call('$I/Product Packaging/helper-renderer-entitlements.plist',
+                      '$W/helper-renderer-entitlements.plist'),
+            mock.call('$I/Product Packaging/helper-plugin-entitlements.plist',
+                      '$W/helper-plugin-entitlements.plist')
+        ])
         self.assertEqual(0, kwargs['move_file'].call_count)
         self.assertEqual(0, kwargs['write_file'].call_count)
 
@@ -152,9 +178,15 @@
             '$W/App Product.app/Contents/Info.plist',
         )
 
-        kwargs['copy_files'].assert_called_once_with(
-            '$I/Product Packaging/app-entitlements.plist',
-            '$W/app-entitlements.plist')
+        self.assertEqual(3, kwargs['copy_files'].call_count)
+        kwargs['copy_files'].assert_has_calls([
+            mock.call('$I/Product Packaging/app-entitlements.plist',
+                      '$W/app-entitlements.plist'),
+            mock.call('$I/Product Packaging/helper-renderer-entitlements.plist',
+                      '$W/helper-renderer-entitlements.plist'),
+            mock.call('$I/Product Packaging/helper-plugin-entitlements.plist',
+                      '$W/helper-plugin-entitlements.plist')
+        ])
         kwargs['write_file'].assert_called_once_with(
             '$W/App Product.app/Contents/PkgInfo', 'APPLMooo')
         self.assertEqual(0, kwargs['move_file'].call_count)
@@ -177,9 +209,15 @@
             '$W/App Product.app/Contents/Info.plist',
         )
 
-        kwargs['copy_files'].assert_called_once_with(
-            '$I/Product Packaging/app-entitlements.plist',
-            '$W/app-entitlements.plist')
+        self.assertEqual(3, kwargs['copy_files'].call_count)
+        kwargs['copy_files'].assert_has_calls([
+            mock.call('$I/Product Packaging/app-entitlements.plist',
+                      '$W/app-entitlements.plist'),
+            mock.call('$I/Product Packaging/helper-renderer-entitlements.plist',
+                      '$W/helper-renderer-entitlements.plist'),
+            mock.call('$I/Product Packaging/helper-plugin-entitlements.plist',
+                      '$W/helper-plugin-entitlements.plist')
+        ])
         self.assertEqual(0, kwargs['move_file'].call_count)
         self.assertEqual(0, kwargs['write_file'].call_count)
 
@@ -210,10 +248,14 @@
             ),
         ])
 
-        self.assertEqual(3, kwargs['copy_files'].call_count)
+        self.assertEqual(5, kwargs['copy_files'].call_count)
         kwargs['copy_files'].assert_has_calls([
             mock.call('$I/Product Packaging/app-entitlements.plist',
                       '$W/app-entitlements.plist'),
+            mock.call('$I/Product Packaging/helper-renderer-entitlements.plist',
+                      '$W/helper-renderer-entitlements.plist'),
+            mock.call('$I/Product Packaging/helper-plugin-entitlements.plist',
+                      '$W/helper-plugin-entitlements.plist'),
             mock.call('$I/Product Packaging/app_canary.icns',
                       '$W/App Product Canary.app/Contents/Resources/app.icns'),
             mock.call(
@@ -223,7 +265,7 @@
         kwargs['write_file'].assert_called_once_with(
             '$W/App Product Canary.app/Contents/PkgInfo', 'APPLMooo')
 
-        self.assertEqual(4, plistlib.writePlist.call_count)
+        self.assertEqual(6, plistlib.writePlist.call_count)
         plistlib.writePlist.assert_has_calls([
             mock.call({
                 'CFBundleIdentifier':
@@ -243,6 +285,8 @@
                 'com.apple.application-identifier':
                     'test.signing.bundle_id.canary'
             }, '$W/app-entitlements.plist'),
+            mock.call({}, '$W/helper-renderer-entitlements.plist'),
+            mock.call({}, '$W/helper-plugin-entitlements.plist'),
             mock.call({
                 'pfm_domain': 'test.signing.bundle_id.canary'
             }, '$W/App Product Canary.app/Contents/Resources/test.signing.bundle_id.canary.manifest/Contents/Resources/test.signing.bundle_id.canary.manifest'
diff --git a/chrome/installer/mac/signing/signing.py b/chrome/installer/mac/signing/signing.py
index 5e684384..c33971b7 100644
--- a/chrome/installer/mac/signing/signing.py
+++ b/chrome/installer/mac/signing/signing.py
@@ -81,6 +81,7 @@
                 .format(config),
                 '{}.helper.renderer'.format(uncustomized_bundle_id),
                 options=CodeSignOptions.RESTRICT,
+                entitlements='helper-renderer-entitlements.plist',
                 verify_options=VerifyOptions.DEEP),
         'helper-plugin-app':
             CodeSignedProduct(
@@ -88,6 +89,7 @@
                 .format(config),
                 '{}.helper.plugin'.format(uncustomized_bundle_id),
                 options=CodeSignOptions.RESTRICT,
+                entitlements='helper-plugin-entitlements.plist',
                 verify_options=VerifyOptions.DEEP),
         'app-mode-app':
             CodeSignedProduct(
diff --git a/chrome/renderer/safe_browsing/threat_dom_details_browsertest.cc b/chrome/renderer/safe_browsing/threat_dom_details_browsertest.cc
index c07409e..ac4439b2 100644
--- a/chrome/renderer/safe_browsing/threat_dom_details_browsertest.cc
+++ b/chrome/renderer/safe_browsing/threat_dom_details_browsertest.cc
@@ -54,7 +54,7 @@
   safe_browsing::ThreatDOMDetails::kMaxNodes = 50;
   safe_browsing::ThreatDOMDetails::kMaxAttributes = 5;
 
-  const char urlprefix[] = "data:text/html;charset=utf-8,";
+  const char kUrlPrefix[] = "data:text/html;charset=utf-8,";
   const char kMaxNodesExceededMetric[] =
       "SafeBrowsing.ThreatReport.MaxNodesExceededInFrame";
   {
@@ -66,7 +66,7 @@
     details->ExtractResources(&params);
     ASSERT_EQ(1u, params.size());
     auto* param = params[0].get();
-    EXPECT_EQ(GURL(urlprefix + net::EscapeQueryParamValue(html, false)),
+    EXPECT_EQ(GURL(kUrlPrefix + net::EscapeQueryParamValue(html, false)),
               param->url);
     EXPECT_EQ(0, param->node_id);
     EXPECT_EQ(0, param->parent_node_id);
@@ -84,7 +84,7 @@
     std::string html = "<html><head><script src=\"" + script1_url.spec() +
                        "\"></script><script src=\"" + script2_url.spec() +
                        "\"></script></head></html>";
-    GURL url(urlprefix + net::EscapeQueryParamValue(html, false));
+    GURL url(kUrlPrefix + net::EscapeQueryParamValue(html, false));
 
     LoadHTML(html.c_str());
     std::vector<safe_browsing::mojom::ThreatDOMDetailsNodePtr> params;
@@ -131,17 +131,17 @@
     // divs with attribute bar. So div foo will be collected and contain iframe1
     // and div baz as children.
     std::string iframe2_html = "<html><body>iframe2</body></html>";
-    GURL iframe2_url(urlprefix + iframe2_html);
+    GURL iframe2_url(kUrlPrefix + iframe2_html);
     std::string iframe1_html = "<iframe src=\"" +
                                net::EscapeForHTML(iframe2_url.spec()) +
                                "\"></iframe>";
-    GURL iframe1_url(urlprefix + iframe1_html);
+    GURL iframe1_url(kUrlPrefix + iframe1_html);
     std::string html =
         "<html><head><div foo=1 foo2=2><img foo=1><div bar=1><div baz=1></div>"
         "<iframe src=\"" +
         net::EscapeForHTML(iframe1_url.spec()) +
         "\"></iframe></div></div></head></html>";
-    GURL url(urlprefix + net::EscapeQueryParamValue(html, false));
+    GURL url(kUrlPrefix + net::EscapeQueryParamValue(html, false));
 
     LoadHTML(html.c_str());
     std::vector<safe_browsing::mojom::ThreatDOMDetailsNodePtr> params;
@@ -199,11 +199,11 @@
     std::string html;
     for (int i = 0; i < 55; ++i) {
       // The iframe contents is just a number.
-      GURL iframe_url(base::StringPrintf("%s%d", urlprefix, i));
+      GURL iframe_url(base::StringPrintf("%s%d", kUrlPrefix, i));
       html += "<iframe src=\"" + net::EscapeForHTML(iframe_url.spec()) +
               "\"></iframe>";
     }
-    GURL url(urlprefix + html);
+    GURL url(kUrlPrefix + html);
 
     LoadHTML(html.c_str());
     base::HistogramTester histograms;
@@ -228,11 +228,11 @@
     std::string html;
     for (int i = 0; i < 55; ++i) {
       // The iframe contents is just a number.
-      GURL script_url(base::StringPrintf("%s%d", urlprefix, i));
+      GURL script_url(base::StringPrintf("%s%d", kUrlPrefix, i));
       html += "<script src=\"" + net::EscapeForHTML(script_url.spec()) +
               "\"></script>";
     }
-    GURL url(urlprefix + html);
+    GURL url(kUrlPrefix + html);
 
     LoadHTML(html.c_str());
     base::HistogramTester histograms;
@@ -261,7 +261,7 @@
     LoadHTML(html.c_str());
     std::vector<safe_browsing::mojom::ThreatDOMDetailsNodePtr> params;
     details->ExtractResources(&params);
-    GURL url = GURL(urlprefix + net::EscapeQueryParamValue(html, false));
+    GURL url = GURL(kUrlPrefix + net::EscapeQueryParamValue(html, false));
     ASSERT_EQ(2u, params.size());
     auto* param = params[0].get();
     EXPECT_TRUE(param->url.is_empty());
@@ -302,7 +302,7 @@
   std::unique_ptr<safe_browsing::ThreatDOMDetails> details(
       safe_browsing::ThreatDOMDetails::Create(view_->GetMainRenderFrame(),
                                               registry_.get()));
-  const char urlprefix[] = "data:text/html;charset=utf-8,";
+  const char kUrlPrefix[] = "data:text/html;charset=utf-8,";
 
   // A page with some divs containing an iframe which itself contains an
   // iframe. Tag "img foo" exists to ensure we honour both the tag name and
@@ -320,13 +320,13 @@
   // since it is the direct child of the main frame, but it would not
   // go inside of the iframe.
   std::string iframe2_html = "<html><body>iframe2</body></html>";
-  GURL iframe2_url(urlprefix + iframe2_html);
+  GURL iframe2_url(kUrlPrefix + iframe2_html);
   std::string html =
       "<html><head><div data-google-query-id=foo><div id=bar>"
       "<iframe id=baz><iframe src=\"" +
       net::EscapeForHTML(iframe2_url.spec()) +
       "\"></iframe></iframe></div></div></head></html>";
-  GURL url(urlprefix + net::EscapeQueryParamValue(html, false));
+  GURL url(kUrlPrefix + net::EscapeQueryParamValue(html, false));
 
   LoadHTML(html.c_str());
   std::vector<safe_browsing::mojom::ThreatDOMDetailsNodePtr> params;
@@ -382,3 +382,92 @@
   EXPECT_EQ(0, param->parent_node_id);
   EXPECT_TRUE(param->child_node_ids.empty());
 }
+
+TEST_F(ThreatDOMDetailsTest, CheckTagAndAttributeListIsSorted) {
+  std::unique_ptr<base::test::ScopedFeatureList> scoped_list(
+      new base::test::ScopedFeatureList);
+  scoped_list->InitAndEnableFeature(
+      safe_browsing::kCaptureInlineJavascriptForGoogleAds);
+
+  std::unique_ptr<safe_browsing::ThreatDOMDetails> details(
+      safe_browsing::ThreatDOMDetails::Create(view_->GetMainRenderFrame(),
+                                              registry_.get()));
+  std::vector<safe_browsing::TagAndAttributesItem> tag_and_attr_list =
+      details->GetTagAndAttributesListForTest();
+  bool is_sorted;
+  std::vector<std::string> tag_names;
+  for (auto item : tag_and_attr_list) {
+    tag_names.push_back(item.tag_name);
+    // Check that list of attributes is sorted.
+    is_sorted = std::is_sorted(item.attributes.begin(), item.attributes.end());
+    EXPECT_TRUE(is_sorted);
+  }
+  // Check that the tags are sorted.
+  is_sorted = std::is_sorted(tag_names.begin(), tag_names.end());
+  EXPECT_TRUE(is_sorted);
+}
+
+TEST_F(ThreatDOMDetailsTest, CaptureInnerHtmlContent) {
+  std::unique_ptr<base::test::ScopedFeatureList> scoped_list(
+      new base::test::ScopedFeatureList);
+  scoped_list->InitAndEnableFeature(
+      safe_browsing::kCaptureInlineJavascriptForGoogleAds);
+  std::unique_ptr<safe_browsing::ThreatDOMDetails> details(
+      safe_browsing::ThreatDOMDetails::Create(view_->GetMainRenderFrame(),
+                                              registry_.get()));
+
+  const char kUrlPrefix[] = "data:text/html;charset=utf-8,";
+  const char kMaxNodesExceededMetric[] =
+      "SafeBrowsing.ThreatReport.MaxNodesExceededInFrame";
+  {
+    // A page with a html element without an onclick element, html element with
+    // an onclick element, an internal script. Html elements without onclick
+    // elements should not be recorded in ThreatDomDetails.
+    std::string html =
+        "<html><head><a></a><a onclick=\"var y = 2;\"></a><img onclick=\"var z "
+        "= 3;\"></img><script>var x = 1;</script></head></html>";
+    LoadHTML(html.c_str());
+    base::HistogramTester histograms;
+    std::vector<safe_browsing::mojom::ThreatDOMDetailsNodePtr> params;
+
+    details->ExtractResources(&params);
+    ASSERT_EQ(4u, params.size());
+    auto* param = params[0].get();
+    EXPECT_EQ(GURL(), param->url);
+    EXPECT_EQ("A", param->tag_name);
+    EXPECT_EQ(1, param->node_id);
+    EXPECT_EQ(0, param->parent_node_id);
+    EXPECT_TRUE(param->child_node_ids.empty());
+    EXPECT_EQ(1u, param->attributes.size());
+    EXPECT_EQ("onclick", param->attributes[0]->name);
+    EXPECT_EQ("var y = 2;", param->attributes[0]->value);
+
+    param = params[1].get();
+    EXPECT_EQ(GURL(), param->url);
+    EXPECT_EQ("IMG", param->tag_name);
+    EXPECT_EQ(2, param->node_id);
+    EXPECT_EQ(0, param->parent_node_id);
+    EXPECT_TRUE(param->child_node_ids.empty());
+    EXPECT_TRUE(param->child_node_ids.empty());
+    EXPECT_EQ(1u, param->attributes.size());
+    EXPECT_EQ("onclick", param->attributes[0]->name);
+    EXPECT_EQ("var z = 3;", param->attributes[0]->value);
+
+    param = params[2].get();
+    EXPECT_EQ(GURL(), param->url);
+    EXPECT_EQ("SCRIPT", param->tag_name);
+    EXPECT_EQ(3, param->node_id);
+    EXPECT_EQ(0, param->parent_node_id);
+    EXPECT_TRUE(param->child_node_ids.empty());
+    EXPECT_EQ("var x = 1;", param->inner_html);
+
+    param = params[3].get();
+    EXPECT_EQ(GURL(kUrlPrefix + net::EscapeQueryParamValue(html, false)),
+              param->url);
+    EXPECT_EQ(0, param->node_id);
+    EXPECT_EQ(0, param->parent_node_id);
+    EXPECT_TRUE(param->child_node_ids.empty());
+
+    histograms.ExpectBucketCount(kMaxNodesExceededMetric, false, 1);
+  }
+}
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 62da5c0..b7fe1a2 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -3005,6 +3005,7 @@
     "../browser/previews/previews_lite_page_decider_unittest.cc",
     "../browser/previews/previews_lite_page_infobar_delegate_unittest.cc",
     "../browser/previews/previews_lite_page_navigation_throttle_unittest.cc",
+    "../browser/previews/previews_lite_page_predictor_unittest.cc",
     "../browser/previews/previews_lite_page_url_loader_interceptor_unittest.cc",
     "../browser/previews/previews_offline_helper_unittest.cc",
     "../browser/previews/previews_service_unittest.cc",
diff --git a/chrome/test/chromedriver/element_commands.cc b/chrome/test/chromedriver/element_commands.cc
index 6196b16b..7f730c3 100644
--- a/chrome/test/chromedriver/element_commands.cc
+++ b/chrome/test/chromedriver/element_commands.cc
@@ -32,8 +32,8 @@
 #include "third_party/webdriver/atoms.h"
 
 const int kFlickTouchEventsPerSecond = 30;
-const std::set<std::string> textControlTypes = {"text", "search", "tel",
-                                                "url",  "email",  "password"};
+const std::set<std::string> textControlTypes = {"text", "search", "tel", "url",
+                                                "password"};
 
 namespace {
 
@@ -92,8 +92,8 @@
   Status status = FocusToElement(session, web_view, element_id);
   if (status.IsError())
         return Status(kElementNotInteractable);
-  // Move cursor/caret to append the input keys if element's type is
-  // text-related
+  // Move cursor/caret to append the input
+  // keys if element's type is text-related
   if (is_text) {
     base::ListValue args;
     args.Append(CreateElement(element_id));
@@ -441,6 +441,46 @@
     return web_view->SetFileInputFiles(session->GetCurrentFrameId(), *element,
                                        paths, multiple);
   } else {
+    std::unique_ptr<base::Value> get_content_editable;
+    base::ListValue args;
+    args.Append(CreateElement(element_id));
+    status = web_view->CallFunction(session->GetCurrentFrameId(),
+                                    "element => element.isContentEditable",
+                                    args, &get_content_editable);
+    if (status.IsError())
+      return status;
+    bool is_content_editable;
+    if (get_content_editable->GetAsBoolean(&is_content_editable) &&
+        is_content_editable) {
+      // If element is contentEditable, will move caret
+      // at end of element text. W3C mandates that the
+      // caret be moved "after any child content"
+      std::unique_ptr<base::Value> result;
+      status = web_view->CallFunction(
+          session->GetCurrentFrameId(),
+          "function(element) {"
+          "var range = document.createRange();"
+          "range.selectNodeContents(element);"
+          "range.collapse();"
+          "var sel = window.getSelection();"
+          "sel.removeAllRanges();"
+          "sel.addRange(range);"
+          "while (element.parentElement.isContentEditable) {"
+          "    element = element.parentElement;"
+          "  }"
+          "return element;"
+          "}",
+          args, &result);
+      if (status.IsError())
+        return status;
+      const base::DictionaryValue* element_dict;
+      std::string target_element_id;
+      if (!result->GetAsDictionary(&element_dict) ||
+          !element_dict->GetString(GetElementKey(), &target_element_id))
+        return Status(kUnknownError, "no element reference returned by script");
+      return SendKeysToElement(session, web_view, target_element_id, false,
+                               key_list);
+    }
     // If element_type is in textControlTypes, sendKeys should append
     bool is_text = is_input && textControlTypes.find(element_type) !=
                                    textControlTypes.end();
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py
index 4c3a52c2..aec71a2c 100755
--- a/chrome/test/chromedriver/test/run_py_tests.py
+++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -1966,16 +1966,44 @@
   def testSendKeysToElementAppend(self):
       self._driver.Load(self.GetHttpUrlForFile(
           '/chromedriver/empty.html'))
+      textControlTypes = ["text", "search", "tel", "url",  "password"]
+      for textType in textControlTypes:
+          element = self._driver.ExecuteScript(
+              'document.body.innerHTML = '
+              '\'<input type="{}" value="send_this_value">\';'
+              'var input = document.getElementsByTagName("input")[0];'
+              'input.focus();'
+              'input.setSelectionRange(0,0);'
+              'return input;'.format(textType))
+          element.SendKeys('hello')
+          value = self._driver.ExecuteScript('return arguments[0].value;',
+                                             element)
+          self.assertEquals('send_this_valuehello', value)
+
+  def testSendKeysToEditableElement(self):
+      self._driver.Load(self.GetHttpUrlForFile(
+          '/chromedriver/empty.html'))
       element = self._driver.ExecuteScript(
           'document.body.innerHTML = '
-          '\'<input type="text" value="send_this_value">\';'
-          'var input = document.getElementsByTagName("input")[0];'
+          '\'<p contentEditable="true"> <i>hello-></i> '
+          '<b>send_this_value </b> </p>\';'
+          'var input = document.getElementsByTagName("i")[0];'
           'input.focus();'
-          'input.setSelectionRange(0,0);'
           'return input;')
       element.SendKeys('hello')
-      value = self._driver.ExecuteScript('return arguments[0].value;', element)
-      self.assertEquals('send_this_valuehello', value)
+      self.assertEquals(u'hello->hello', element.GetText())
+
+      self._driver.Load(self.GetHttpUrlForFile(
+          '/chromedriver/empty.html'))
+      element = self._driver.ExecuteScript(
+          'document.body.innerHTML = '
+          '\'<p contentEditable="true"> <i>hello</i> '
+          '<b>-></b> </p>\';'
+          'var input = document.getElementsByTagName("p")[0];'
+          'input.focus();'
+          'return input;')
+      element.SendKeys('hello')
+      self.assertEquals(u'hello ->hello', element.GetText())
 
   def testUnexpectedAlertOpenExceptionMessage(self):
     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
diff --git a/chrome/test/chromedriver/test/run_webdriver_tests.py b/chrome/test/chromedriver/test/run_webdriver_tests.py
index dcd3598..cffc3f80 100644
--- a/chrome/test/chromedriver/test/run_webdriver_tests.py
+++ b/chrome/test/chromedriver/test/run_webdriver_tests.py
@@ -33,9 +33,10 @@
 sys.path.insert(0, BLINK_TOOLS_ABS_PATH)
 from blinkpy.common import exit_codes
 from blinkpy.common.host import Host
-from blinkpy.common.system.log_utils import configure_logging
-from blinkpy.web_tests.models import test_expectations
 from blinkpy.common.path_finder import PathFinder
+from blinkpy.common.system.log_utils import configure_logging
+from blinkpy.w3c.common import CHROMIUM_WPT_DIR
+from blinkpy.web_tests.models import test_expectations
 
 WD_CLIENT_PATH = 'blinkpy/third_party/wpt/wpt/tools/webdriver'
 WEBDRIVER_CLIENT_ABS_PATH = os.path.join(BLINK_TOOLS_ABS_PATH, WD_CLIENT_PATH)
@@ -127,7 +128,7 @@
     self.result.append(WebDriverTestResult(
         output_name, status, message))
 
-def set_up_config(chromedriver_server):
+def set_up_config(path_finder, chromedriver_server):
   # These envs are used to create a WebDriver session in the fixture.py file.
   os.environ["WD_HOST"] = chromedriver_server.GetHost()
   os.environ["WD_PORT"] = str(chromedriver_server.GetPort())
@@ -155,7 +156,13 @@
   # /blinkpy/web_tests/servers/wptserve.py?l=23&rcl=375b34c6ba64
   # 5d00c1413e4c6106c7bb74581c85
   os.environ["WD_SERVER_CONFIG"] = json.dumps({
+    "doc_root": path_finder.path_from_chromium_base(CHROMIUM_WPT_DIR),
     "browser_host": "web-platform.test",
+    "domains": {"": {"": "web-platform.test",
+                     "www": "www.web-platform.test",
+                     "www.www": "www.www.web-platform.test",
+                     "www1": "www1.web-platform.test",
+                     "www2": "www2.web-platform.test"}},
     "ports": {"ws": [9001], "wss": [9444], "http": [8001], "https": [8444]}})
 
 def run_test(path, path_finder, port, skipped_tests=[]):
@@ -193,6 +200,7 @@
       help='JSON perf output file used by swarming, ignored')
   parser.add_argument(
       '--test-path',
+      required=True,
       help='Path to the WPT WebDriver tests')
   parser.add_argument(
       '-v', '--verbose', action='store_true',
@@ -252,7 +260,7 @@
     _log.error('ChromeDriver is not running.')
     sys.exit(1)
 
-  set_up_config(chromedriver_server)
+  set_up_config(path_finder, chromedriver_server)
 
   test_path = options.test_path
   start_time = time.time()
@@ -264,7 +272,7 @@
     elif os.path.isdir(test_path):
       for root, dirnames, filenames in os.walk(test_path):
         for filename in filenames:
-          if '__init__' in filename:
+          if '__init__' in filename or not filename.endswith('.py'):
             continue
 
           test_file = os.path.join(root, filename)
diff --git a/chrome/test/data/non-corb.octet-stream b/chrome/test/data/non-corb.octet-stream
new file mode 100644
index 0000000..cd2f0ed
--- /dev/null
+++ b/chrome/test/data/non-corb.octet-stream
@@ -0,0 +1 @@
+octet-stream-body
diff --git a/chrome/test/data/non-corb.octet-stream.mock-http-headers b/chrome/test/data/non-corb.octet-stream.mock-http-headers
new file mode 100644
index 0000000..4e52840
--- /dev/null
+++ b/chrome/test/data/non-corb.octet-stream.mock-http-headers
@@ -0,0 +1,3 @@
+HTTP/1.1 200 OK
+Content-Type: application/octet-stream
+X-Content-Type-Options: nosniff
diff --git a/chrome/test/data/previews/resource_loading_hints_preload.html b/chrome/test/data/previews/resource_loading_hints_preload.html
new file mode 100644
index 0000000..fe59ed7
--- /dev/null
+++ b/chrome/test/data/previews/resource_loading_hints_preload.html
@@ -0,0 +1,9 @@
+<html>
+  <head>
+    <link rel="stylesheet" href="foo.jpg" as="style">
+    <link rel="stylesheet" href="bar.jpg" as="style">
+  </head>
+  <body>
+    <p>Test page for Resource Loading Hints.</p>
+   </body>
+</html>
diff --git a/chrome/test/data/webui/bookmarks/bookmarks_focus_test.js b/chrome/test/data/webui/bookmarks/bookmarks_focus_test.js
index 1aa4eb1..f6c24ae 100644
--- a/chrome/test/data/webui/bookmarks/bookmarks_focus_test.js
+++ b/chrome/test/data/webui/bookmarks/bookmarks_focus_test.js
@@ -245,6 +245,45 @@
       MockInteractions.keyDownOn(item, '', modifiers, key);
     }
 
+    /**
+     * @param {string} id
+     * @return {!HTMLElement}
+     */
+    function getItem(id) {
+      return assert(
+          Array.from(items).find(({itemId}) => itemId == id),
+          `Item ${id} does not exist in items.`);
+    }
+
+    /** @param {string} id */
+    function selectAndFocus(id) {
+      getItem(id).focus();
+      store.data.selection.items = new Set([id]);
+      store.notifyObservers();
+    }
+
+    /** @param {!Array<string>} ids */
+    function updateIds(ids) {
+      store.data.nodes[store.data.selectedFolder].children = ids;
+      store.notifyObservers();
+    }
+
+    /**
+     * @param {!function} fn
+     * @return {!Promise}
+     */
+    async function doAndWait(fn) {
+      fn();
+      await PolymerTest.flushTasks();
+      // Focus is done asynchronously.
+      await PolymerTest.flushTasks();
+    }
+
+    /** @param {string} id */
+    function checkMenuButtonFocus(id) {
+      assertEquals(getItem(id).$.menuButton, getDeepActiveElement());
+    }
+
     setup(function() {
       const nodes = testTree(createFolder('1', [
         createItem('2'),
@@ -444,6 +483,38 @@
       commandManager.closeCommandMenu();
       assertEquals(button, items[0].root.activeElement);
     });
+
+    test('remove first item, focus on first item', async () => {
+      await doAndWait(() => {
+        selectAndFocus('2');
+        updateIds(['3', '4', '5', '6', '7']);
+      });
+      checkMenuButtonFocus('3');
+    });
+
+    test('remove last item, focus on last item', async () => {
+      await doAndWait(() => {
+        selectAndFocus('7');
+        updateIds(['2', '3', '4', '5', '6']);
+      });
+      checkMenuButtonFocus('6');
+    });
+
+    test('remove middle item, focus on item with same index', async () => {
+      await doAndWait(() => {
+        selectAndFocus('3');
+        updateIds(['2', '4', '5', '6', '7']);
+      });
+      checkMenuButtonFocus('4');
+    });
+
+    test('reorder items, focus does not change', async () => {
+      await doAndWait(() => {
+        selectAndFocus('3');
+        updateIds(['2', '4', '5', '6', '3', '7']);
+      });
+      assertEquals(document.body, getDeepActiveElement());
+    });
   });
 
   suite('DialogFocusManager', function() {
diff --git a/chrome/test/data/webui/set_time_dialog_browsertest.js b/chrome/test/data/webui/set_time_dialog_browsertest.js
index f921cabc..ae6014f 100644
--- a/chrome/test/data/webui/set_time_dialog_browsertest.js
+++ b/chrome/test/data/webui/set_time_dialog_browsertest.js
@@ -48,7 +48,7 @@
 
       /** @override */
       setTimezone(timezone) {
-        this.methodCalled('setTimezone', timezone);
+        this.methodCalled('setTimezone');
       }
 
       /** @override */
@@ -64,18 +64,12 @@
     }
 
     suiteSetup(function() {
-      // Must use existing timezones in the test.
       loadTimeData.overrideValues({
-        currentTimezoneId: 'America/Sao_Paulo',
+        currentTimezoneId: 'Westeros/Highgarden',
         timezoneList: [
-          [
-            'America/Los_Angeles',
-            '(GMT-7:00) Pacific Daylight Time (Los Angeles)'
-          ],
-          [
-            'America/Sao_Paulo', '(GMT-3:00) Brasilis Standard Time (Sao Paulo)'
-          ],
-          ['Asia/Seoul', '(GMT+9:00) Korean Standard Time (Seoul)'],
+          ['Westeros/Highgarden', '(KNG-2:00) The Reach Time (Highgarden)'],
+          ['Westeros/Winterfell', '(KNG-1:00) The North Time (Winterfell)'],
+          ['Westeros/Sunspear', '(KNG+2:00) Dorne Time (Sunspear)'],
         ],
       });
     });
@@ -134,58 +128,14 @@
     test('SystemTimezoneChanged', () => {
       const timezoneSelect = setTimeElement.$$('#timezoneSelect');
       assertTrue(!!timezoneSelect);
-      expectEquals('America/Sao_Paulo', timezoneSelect.value);
+      expectEquals('Westeros/Highgarden', timezoneSelect.value);
 
       cr.webUIListenerCallback(
-          'system-timezone-changed', 'America/Los_Angeles');
-      expectEquals('America/Los_Angeles', timezoneSelect.value);
+          'system-timezone-changed', 'Westeros/Winterfell');
+      expectEquals('Westeros/Winterfell', timezoneSelect.value);
 
-      cr.webUIListenerCallback('system-timezone-changed', 'Asia/Seoul');
-      expectEquals('Asia/Seoul', timezoneSelect.value);
-    });
-
-    test('SetDateAndTimezone', () => {
-      const dateInput = setTimeElement.$$('#dateInput');
-      assertTrue(!!dateInput);
-
-      const timeInput = setTimeElement.$$('#timeInput');
-      assertTrue(!!timeInput);
-
-      const timezoneSelect = setTimeElement.$$('#timezoneSelect');
-      assertTrue(!!timezoneSelect);
-      expectEquals('America/Sao_Paulo', timezoneSelect.value);
-
-      // Simulate the user changing the time by forwarding it 15 minutes.
-      const originalTime = dateInput.valueAsDate;
-      originalTime.setMilliseconds(timeInput.valueAsNumber);
-      const updatedTime = new Date(originalTime.getTime() + 15 * 60 * 1000);
-      dateInput.focus();
-      dateInput.valueAsDate = updatedTime;
-      setTimeElement.$$('#doneButton').click();
-
-      // Simulate timezone change.
-      cr.webUIListenerCallback(
-          'system-timezone-changed', 'America/Los_Angeles');
-      expectEquals('America/Los_Angeles', timezoneSelect.value);
-
-      // Make sure that time on input field was updated.
-      const updatedTimeAndTimezone = dateInput.valueAsDate;
-      updatedTimeAndTimezone.setMilliseconds(timeInput.valueAsNumber);
-      // updatedTimeAndTimezone reflects the new timezone so it should be
-      // smaller, because it is more to the west than the original
-      // one, therefore even with the 15 minutes forwarded it should be smaller.
-      expectGT(updatedTime.getHours(), updatedTimeAndTimezone.getHours());
-
-
-      return testBrowserProxy.whenCalled('setTimeInSeconds')
-          .then(timeInSeconds => {
-            const todaySeconds = originalTime.getTime() / 1000;
-            // The exact value isn't important (it depends on the current time).
-            // timeInSeconds should be bigger, because this timestamp is seconds
-            // since epoch and it does not hold any information regarding the
-            // current timezone.
-            assertGT(timeInSeconds, todaySeconds);
-          });
+      cr.webUIListenerCallback('system-timezone-changed', 'Westeros/Sunspear');
+      expectEquals('Westeros/Sunspear', timezoneSelect.value);
     });
   });
 
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index 535dd78a1..a1dac14 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -1085,7 +1085,7 @@
 #endif
 }
 
-std::string CastContentBrowserClient::GetUserAgent() const {
+std::string CastContentBrowserClient::GetUserAgent() {
   return chromecast::shell::GetUserAgent();
 }
 
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h
index ce869e6a..f3a6f49 100644
--- a/chromecast/browser/cast_content_browser_client.h
+++ b/chromecast/browser/cast_content_browser_client.h
@@ -227,7 +227,7 @@
       content::BrowserContext* context,
       bool in_memory,
       const base::FilePath& relative_partition_path) override;
-  std::string GetUserAgent() const override;
+  std::string GetUserAgent() override;
   bool DoesSiteRequireDedicatedProcess(
       content::BrowserOrResourceContext browser_or_resource_context,
       const GURL& effective_site_url) override;
diff --git a/chromecast/browser/cast_extension_host.cc b/chromecast/browser/cast_extension_host.cc
index abbfb131..3572655 100644
--- a/chromecast/browser/cast_extension_host.cc
+++ b/chromecast/browser/cast_extension_host.cc
@@ -116,7 +116,7 @@
   SetFullscreen(web_contents, false);
 }
 bool CastExtensionHost::IsFullscreenForTabOrPending(
-    const content::WebContents* web_contents) const {
+    const content::WebContents* web_contents) {
   return is_fullscreen_;
 }
 
diff --git a/chromecast/browser/cast_extension_host.h b/chromecast/browser/cast_extension_host.h
index 812ab44..47dba29 100644
--- a/chromecast/browser/cast_extension_host.h
+++ b/chromecast/browser/cast_extension_host.h
@@ -51,7 +51,7 @@
       const blink::WebFullscreenOptions& options) override;
   void ExitFullscreenModeForTab(content::WebContents*) override;
   bool IsFullscreenForTabOrPending(
-      const content::WebContents* web_contents) const override;
+      const content::WebContents* web_contents) override;
 
  private:
   void SetFullscreen(content::WebContents* web_contents, bool value);
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc
index 1e1d676..1c7dcac 100644
--- a/chromeos/constants/chromeos_features.cc
+++ b/chromeos/constants/chromeos_features.cc
@@ -13,6 +13,11 @@
 const base::Feature kAutoScreenBrightness{"AutoScreenBrightness",
                                           base::FEATURE_ENABLED_BY_DEFAULT};
 
+// Enables or disables more aggressive filtering out of Bluetooth devices with
+// "appearances" that are less likely to be pairable or useful.
+const base::Feature kBluetoothAggressiveAppearanceFilter{
+    "BluetoothAggressiveAppearanceFilter", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Feature containing param to block provided long term keys.
 const base::Feature kBlueZLongTermKeyBlocklist{
     "BlueZLongTermKeyBlocklist", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h
index f144fca4..5bbd097 100644
--- a/chromeos/constants/chromeos_features.h
+++ b/chromeos/constants/chromeos_features.h
@@ -18,6 +18,8 @@
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kAutoScreenBrightness;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
+extern const base::Feature kBluetoothAggressiveAppearanceFilter;
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kBlueZLongTermKeyBlocklist;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const char kBlueZLongTermKeyBlocklistParamName[];
diff --git a/chromeos/constants/chromeos_switches.cc b/chromeos/constants/chromeos_switches.cc
index 764e03c..fd7bb9b 100644
--- a/chromeos/constants/chromeos_switches.cc
+++ b/chromeos/constants/chromeos_switches.cc
@@ -471,9 +471,18 @@
 // fixed.
 const char kSamlPasswordChangeUrl[] = "saml-password-change-url";
 
+// Smaller, denser shelf in clamshell mode.
+const char kShelfDenseClamshell[] = "shelf-dense-clamshell";
+
 // App window previews when hovering over the shelf.
 const char kShelfHoverPreviews[] = "shelf-hover-previews";
 
+// New modular UI design for the shelf.
+const char kShelfNewUi[] = "shelf-new-ui";
+
+// Scrollable list of apps on the shelf.
+const char kShelfScrollable[] = "shelf-scrollable";
+
 // If true, files in Android internal storage will be shown in Files app.
 const char kShowAndroidFilesInFilesApp[] = "show-android-files-in-files-app";
 
@@ -601,10 +610,23 @@
       kDisableSigninFrameClientCertUserSelection);
 }
 
+bool ShouldShowShelfDenseClamshell() {
+  return base::CommandLine::ForCurrentProcess()->HasSwitch(
+      kShelfDenseClamshell);
+}
+
 bool ShouldShowShelfHoverPreviews() {
   return base::CommandLine::ForCurrentProcess()->HasSwitch(kShelfHoverPreviews);
 }
 
+bool ShouldShowShelfNewUi() {
+  return base::CommandLine::ForCurrentProcess()->HasSwitch(kShelfNewUi);
+}
+
+bool ShouldShowScrollableShelf() {
+  return base::CommandLine::ForCurrentProcess()->HasSwitch(kShelfScrollable);
+}
+
 bool IsInstantTetheringBackgroundAdvertisingSupported() {
   return base::FeatureList::IsEnabled(
       kInstantTetheringBackgroundAdvertisementSupport);
diff --git a/chromeos/constants/chromeos_switches.h b/chromeos/constants/chromeos_switches.h
index adb46302..eb496ee 100644
--- a/chromeos/constants/chromeos_switches.h
+++ b/chromeos/constants/chromeos_switches.h
@@ -176,7 +176,10 @@
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kRegulatoryLabelDir[];
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kRlzPingDelay[];
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kSamlPasswordChangeUrl[];
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kShelfDenseClamshell[];
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kShelfHoverPreviews[];
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kShelfNewUi[];
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kShelfScrollable[];
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const char kShowAndroidFilesInFilesApp[];
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
@@ -261,10 +264,19 @@
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 bool IsSigninFrameClientCertUserSelectionEnabled();
 
+// Returns true if we should show a smaller, denser shelf in clamshell mode.
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool ShouldShowShelfDenseClamshell();
+
 // Returns true if we should show window previews when hovering over an app
 // on the shelf.
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool ShouldShowShelfHoverPreviews();
 
+// Returns true if we should show the new modular shelf UI.
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool ShouldShowShelfNewUi();
+
+// Returns true if we should show a scrollable list of apps in the main shelf.
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool ShouldShowScrollableShelf();
+
 // Returns true if Instant Tethering should support hosts which use the
 // background advertisement model.
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.cc b/chromeos/services/assistant/assistant_manager_service_impl.cc
index 1da3f277..7ff8a5c 100644
--- a/chromeos/services/assistant/assistant_manager_service_impl.cc
+++ b/chromeos/services/assistant/assistant_manager_service_impl.cc
@@ -317,7 +317,8 @@
   }
   // Both LibAssistant and Chrome threads may access |display_connection_|.
   // |display_connection_| is thread safe.
-  display_connection_->SetArcPlayStoreEnabled(enable);
+  if (assistant::features::IsAppSupportEnabled())
+    display_connection_->SetArcPlayStoreEnabled(enable);
 }
 
 AssistantSettingsManager*
diff --git a/chromeos/services/device_sync/cryptauth_device.cc b/chromeos/services/device_sync/cryptauth_device.cc
index c689047..88cb89b 100644
--- a/chromeos/services/device_sync/cryptauth_device.cc
+++ b/chromeos/services/device_sync/cryptauth_device.cc
@@ -111,6 +111,11 @@
                          *better_together_device_metadata, *feature_states);
 }
 
+CryptAuthDevice::CryptAuthDevice(const std::string& instance_id)
+    : instance_id_(instance_id) {
+  DCHECK(!instance_id.empty());
+}
+
 CryptAuthDevice::CryptAuthDevice(
     const std::string& instance_id,
     const std::string& device_name,
@@ -120,16 +125,13 @@
         better_together_device_metadata,
     const std::map<multidevice::SoftwareFeature,
                    multidevice::SoftwareFeatureState>& feature_states)
-    : instance_id_(instance_id),
-      device_name_(device_name),
-      device_better_together_public_key_(device_better_together_public_key),
-      last_update_time_(last_update_time),
-      better_together_device_metadata_(better_together_device_metadata),
-      feature_states_(feature_states) {
+    : device_name(device_name),
+      device_better_together_public_key(device_better_together_public_key),
+      last_update_time(last_update_time),
+      better_together_device_metadata(better_together_device_metadata),
+      feature_states(feature_states),
+      instance_id_(instance_id) {
   DCHECK(!instance_id.empty());
-  DCHECK(!device_name.empty());
-  DCHECK(!device_better_together_public_key.empty());
-  DCHECK(!last_update_time.is_null());
 }
 
 CryptAuthDevice::CryptAuthDevice(const CryptAuthDevice&) = default;
@@ -139,28 +141,27 @@
 base::Value CryptAuthDevice::AsDictionary() const {
   base::Value dict(base::Value::Type::DICTIONARY);
   dict.SetKey(kInstanceIdDictKey, util::EncodeAsValueString(instance_id_));
-  dict.SetKey(kDeviceNameDictKey, util::EncodeAsValueString(device_name_));
+  dict.SetKey(kDeviceNameDictKey, util::EncodeAsValueString(device_name));
   dict.SetKey(kDeviceBetterTogetherPublicKeyDictKey,
-              util::EncodeAsValueString(device_better_together_public_key_));
-  dict.SetKey(kLastUpdateTimeDictKey, ::util::TimeToValue(last_update_time_));
+              util::EncodeAsValueString(device_better_together_public_key));
+  dict.SetKey(kLastUpdateTimeDictKey, ::util::TimeToValue(last_update_time));
   dict.SetKey(
       kBetterTogetherDeviceMetadataDictKey,
-      util::EncodeProtoMessageAsValueString(&better_together_device_metadata_));
-  dict.SetKey(kFeatureStatesDictKey,
-              FeatureStatesToDictionary(feature_states_));
+      util::EncodeProtoMessageAsValueString(&better_together_device_metadata));
+  dict.SetKey(kFeatureStatesDictKey, FeatureStatesToDictionary(feature_states));
 
   return dict;
 }
 
 bool CryptAuthDevice::operator==(const CryptAuthDevice& other) const {
   return instance_id_ == other.instance_id_ &&
-         device_name_ == other.device_name_ &&
-         device_better_together_public_key_ ==
-             other.device_better_together_public_key_ &&
-         last_update_time_ == other.last_update_time_ &&
-         better_together_device_metadata_.SerializeAsString() ==
-             other.better_together_device_metadata_.SerializeAsString() &&
-         feature_states_ == other.feature_states_;
+         device_name == other.device_name &&
+         device_better_together_public_key ==
+             other.device_better_together_public_key &&
+         last_update_time == other.last_update_time &&
+         better_together_device_metadata.SerializeAsString() ==
+             other.better_together_device_metadata.SerializeAsString() &&
+         feature_states == other.feature_states;
 }
 
 bool CryptAuthDevice::operator!=(const CryptAuthDevice& other) const {
diff --git a/chromeos/services/device_sync/cryptauth_device.h b/chromeos/services/device_sync/cryptauth_device.h
index 1bf35265..c9ca6e2 100644
--- a/chromeos/services/device_sync/cryptauth_device.h
+++ b/chromeos/services/device_sync/cryptauth_device.h
@@ -28,20 +28,7 @@
 
   // |instance_id|: The Instance ID, used as a unique device identifier. Cannot
   //     be empty.
-  // |device_name|: The name known to the CryptAuth server or which was assigned
-  //     by the user to the device. Might contain personally identifiable
-  //     information. Cannot be empty.
-  // |device_better_together_public_key|: The device's
-  //     "DeviceSync:BetterTogether" public key that is enrolled with
-  //     CryptAuth--known as CryptAuthKeyBundle::kDeviceSyncBetterTogether on
-  //     Chrome OS. This is not to be confused with the shared, unenrolled group
-  //     public key. Cannot be empty.
-  // |last_update_time|: The last time the device updated its information with
-  //     the CryptAuth server. Cannot be null.
-  // |better_together_device_metadata|: Device metadata relevant to the suite of
-  //     multi-device ("Better Together") features.
-  // |feature_states|: A map from the multi-device feature type (example:
-  //     kBetterTogetherHost) to feature state (example: kEnabled).
+  explicit CryptAuthDevice(const std::string& instance_id);
   CryptAuthDevice(
       const std::string& instance_id,
       const std::string& device_name,
@@ -58,25 +45,6 @@
 
   const std::string& instance_id() const { return instance_id_; }
 
-  const std::string& device_name() const { return device_name_; }
-
-  const std::string& device_better_together_public_key() const {
-    return device_better_together_public_key_;
-  }
-
-  const base::Time& last_update_time() const { return last_update_time_; }
-
-  const cryptauthv2::BetterTogetherDeviceMetadata&
-  better_together_device_metadata() const {
-    return better_together_device_metadata_;
-  }
-
-  const std::map<multidevice::SoftwareFeature,
-                 multidevice::SoftwareFeatureState>&
-  feature_states() const {
-    return feature_states_;
-  }
-
   // Converts CryptAuthDevice to a dictionary-type Value of the form
   //   {
   //     "instance_id": |instance_id_|,
@@ -93,14 +61,30 @@
   bool operator==(const CryptAuthDevice& other) const;
   bool operator!=(const CryptAuthDevice& other) const;
 
+  // The name known to the CryptAuth server or which was assigned by the user to
+  // the device. Might contain personally identifiable information.
+  std::string device_name;
+
+  // The device's "DeviceSync:BetterTogether" public key that is enrolled with
+  // CryptAuth--known as CryptAuthKeyBundle::kDeviceSyncBetterTogether on Chrome
+  // OS. This is not to be confused with the shared, unenrolled group public
+  // key.
+  std::string device_better_together_public_key;
+
+  // The last time the device updated its information with the CryptAuth server.
+  base::Time last_update_time;
+
+  // Device metadata relevant to the suite of multi-device ("Better Together")
+  // features.
+  cryptauthv2::BetterTogetherDeviceMetadata better_together_device_metadata;
+
+  // A map from the multi-device feature type (example: kBetterTogetherHost) to
+  // feature state (example: kEnabled).
+  std::map<multidevice::SoftwareFeature, multidevice::SoftwareFeatureState>
+      feature_states;
+
  private:
   std::string instance_id_;
-  std::string device_name_;
-  std::string device_better_together_public_key_;
-  base::Time last_update_time_;
-  cryptauthv2::BetterTogetherDeviceMetadata better_together_device_metadata_;
-  std::map<multidevice::SoftwareFeature, multidevice::SoftwareFeatureState>
-      feature_states_;
 };
 
 }  // namespace device_sync
diff --git a/components/autofill/core/browser/data_model/contact_info.cc b/components/autofill/core/browser/data_model/contact_info.cc
index 2f3b4a6..895e1ed 100644
--- a/components/autofill/core/browser/data_model/contact_info.cc
+++ b/components/autofill/core/browser/data_model/contact_info.cc
@@ -159,13 +159,7 @@
 }
 
 base::string16 NameInfo::MiddleInitial() const {
-  if (middle_.empty())
-    return base::string16();
-
-  base::string16 middle_name(middle_);
-  base::string16 initial;
-  initial.push_back(middle_name[0]);
-  return initial;
+  return middle_.empty() ? base::string16() : middle_.substr(0U, 1U);
 }
 
 void NameInfo::SetFullName(const base::string16& full) {
diff --git a/components/autofill/ios/browser/autofill_agent.mm b/components/autofill/ios/browser/autofill_agent.mm
index 4be7d25..217b154 100644
--- a/components/autofill/ios/browser/autofill_agent.mm
+++ b/components/autofill/ios/browser/autofill_agent.mm
@@ -400,6 +400,7 @@
   if (suggestion.identifier > 0) {
     pendingAutocompleteField_ = base::SysNSStringToUTF16(fieldIdentifier);
     if (popupDelegate_) {
+      // TODO(966411): Replace 0 with the index of the selected suggestion.
       popupDelegate_->DidAcceptSuggestion(
           base::SysNSStringToUTF16(suggestion.value), suggestion.identifier, 0);
     }
diff --git a/components/crash/core/common/crash_key_breakpad_unittest.cc b/components/crash/core/common/crash_key_breakpad_unittest.cc
index e077766..4e3e71e2 100644
--- a/components/crash/core/common/crash_key_breakpad_unittest.cc
+++ b/components/crash/core/common/crash_key_breakpad_unittest.cc
@@ -12,6 +12,7 @@
 class CrashKeyBreakpadTest : public testing::Test {
  public:
   void SetUp() override {
+    internal::ResetCrashKeyStorageForTesting();
     InitializeCrashKeys();
     ASSERT_TRUE(internal::GetCrashKeyStorage());
   }
diff --git a/components/dom_distiller/content/browser/distiller_page_web_contents.cc b/components/dom_distiller/content/browser/distiller_page_web_contents.cc
index f36e5ad..4c93d6f 100644
--- a/components/dom_distiller/content/browser/distiller_page_web_contents.cc
+++ b/components/dom_distiller/content/browser/distiller_page_web_contents.cc
@@ -137,7 +137,7 @@
 }
 
 gfx::Size DistillerPageWebContents::GetSizeForNewRenderView(
-    content::WebContents* web_contents) const {
+    content::WebContents* web_contents) {
   gfx::Size size(render_view_size_);
   if (size.IsEmpty())
     size = web_contents->GetContainerBounds().size();
diff --git a/components/dom_distiller/content/browser/distiller_page_web_contents.h b/components/dom_distiller/content/browser/distiller_page_web_contents.h
index 5e357dc..6ae7769 100644
--- a/components/dom_distiller/content/browser/distiller_page_web_contents.h
+++ b/components/dom_distiller/content/browser/distiller_page_web_contents.h
@@ -60,7 +60,7 @@
 
   // content::WebContentsDelegate implementation.
   gfx::Size GetSizeForNewRenderView(
-      content::WebContents* web_contents) const override;
+      content::WebContents* web_contents) override;
 
   // content::WebContentsObserver implementation.
   void DocumentLoadedInFrame(
diff --git a/components/embedder_support/android/delegate/web_contents_delegate_android.cc b/components/embedder_support/android/delegate/web_contents_delegate_android.cc
index 39c893e..08a213b 100644
--- a/components/embedder_support/android/delegate/web_contents_delegate_android.cc
+++ b/components/embedder_support/android/delegate/web_contents_delegate_android.cc
@@ -367,7 +367,7 @@
 }
 
 bool WebContentsDelegateAndroid::IsFullscreenForTabOrPending(
-    const WebContents* web_contents) const {
+    const WebContents* web_contents) {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
   if (obj.is_null())
@@ -379,7 +379,7 @@
     content::WebContents* web_contents,
     const GURL& url) {}
 
-int WebContentsDelegateAndroid::GetTopControlsHeight() const {
+int WebContentsDelegateAndroid::GetTopControlsHeight() {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
   if (obj.is_null())
@@ -387,7 +387,7 @@
   return Java_WebContentsDelegateAndroid_getTopControlsHeight(env, obj);
 }
 
-int WebContentsDelegateAndroid::GetBottomControlsHeight() const {
+int WebContentsDelegateAndroid::GetBottomControlsHeight() {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
   if (obj.is_null())
@@ -396,7 +396,7 @@
 }
 
 bool WebContentsDelegateAndroid::DoBrowserControlsShrinkRendererSize(
-    const content::WebContents* contents) const {
+    const content::WebContents* contents) {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
   if (obj.is_null())
diff --git a/components/embedder_support/android/delegate/web_contents_delegate_android.h b/components/embedder_support/android/delegate/web_contents_delegate_android.h
index d617996a..e535b00 100644
--- a/components/embedder_support/android/delegate/web_contents_delegate_android.h
+++ b/components/embedder_support/android/delegate/web_contents_delegate_android.h
@@ -109,13 +109,13 @@
       const blink::WebFullscreenOptions& options) override;
   void ExitFullscreenModeForTab(content::WebContents* web_contents) override;
   bool IsFullscreenForTabOrPending(
-      const content::WebContents* web_contents) const override;
+      const content::WebContents* web_contents) override;
   void OnDidBlockFramebust(content::WebContents* web_contents,
                            const GURL& url) override;
-  int GetTopControlsHeight() const override;
-  int GetBottomControlsHeight() const override;
+  int GetTopControlsHeight() override;
+  int GetBottomControlsHeight() override;
   bool DoBrowserControlsShrinkRendererSize(
-      const content::WebContents* contents) const override;
+      const content::WebContents* contents) override;
 
  protected:
   base::android::ScopedJavaLocalRef<jobject> GetJavaDelegate(JNIEnv* env) const;
diff --git a/components/exo/keyboard.cc b/components/exo/keyboard.cc
index 8676a34..ebc3a9b 100644
--- a/components/exo/keyboard.cc
+++ b/components/exo/keyboard.cc
@@ -14,6 +14,7 @@
 #include "components/exo/keyboard_device_configuration_delegate.h"
 #include "components/exo/seat.h"
 #include "components/exo/shell_surface.h"
+#include "components/exo/shell_surface_util.h"
 #include "components/exo/surface.h"
 #include "components/exo/wm_helper.h"
 #include "ui/aura/client/aura_constants.h"
@@ -236,6 +237,14 @@
   if (event->is_repeat())
     return;
 
+  // If the event target is not an exo::Surface, let another handler process the
+  // event. This check may not be necessary once https://crbug.com/624168 is
+  // resolved.
+  if (!GetShellMainSurface(static_cast<aura::Window*>(event->target())) &&
+      !Surface::AsSurface(static_cast<aura::Window*>(event->target()))) {
+    return;
+  }
+
   TRACE_EXO_INPUT_EVENT(event);
 
   // Process reserved accelerators before sending it to client.
diff --git a/components/exo/keyboard_unittest.cc b/components/exo/keyboard_unittest.cc
index 205a01d..72e7310 100644
--- a/components/exo/keyboard_unittest.cc
+++ b/components/exo/keyboard_unittest.cc
@@ -238,6 +238,28 @@
   EXPECT_CALL(delegate, OnKeyboardKey(testing::_, ui::DomCode::US_W, false));
   generator.ReleaseKey(ui::VKEY_W, ui::EF_CONTROL_DOWN);
 
+  // Key events should be ignored when the focused window is not an
+  // exo::Surface.
+  auto window = CreateChildWindow(shell_surface->GetWidget()->GetNativeWindow(),
+                                  gfx::Rect(buffer_size));
+  // Moving the focus away will trigger the fallback path in GetEffectiveFocus.
+  // TODO(oshima): Consider removing the fallback path.
+  EXPECT_CALL(delegate, CanAcceptKeyboardEventsForSurface(surface.get()))
+      .WillOnce(testing::Return(true));
+  focus_client->FocusWindow(window.get());
+
+  EXPECT_CALL(delegate,
+              OnKeyboardKey(testing::_, ui::DomCode::ARROW_LEFT, true))
+      .Times(0);
+  seat.set_physical_code_for_currently_processing_event_for_testing(
+      ui::DomCode::ARROW_LEFT);
+  generator.PressKey(ui::VKEY_LEFT, 0);
+
+  EXPECT_CALL(delegate,
+              OnKeyboardKey(testing::_, ui::DomCode::ARROW_LEFT, false))
+      .Times(0);
+  generator.ReleaseKey(ui::VKEY_LEFT, 0);
+
   keyboard.reset();
 }
 
diff --git a/components/favicon/core/favicon_request_handler.cc b/components/favicon/core/favicon_request_handler.cc
index 55f897e..cd63cb2 100644
--- a/components/favicon/core/favicon_request_handler.cc
+++ b/components/favicon/core/favicon_request_handler.cc
@@ -113,10 +113,12 @@
 }  // namespace
 
 FaviconRequestHandler::FaviconRequestHandler(
+    const SyncedFaviconGetter& synced_favicon_getter,
     FaviconService* favicon_service,
     LargeIconService* large_icon_service)
     : favicon_service_(favicon_service),
-      large_icon_service_(large_icon_service) {
+      large_icon_service_(large_icon_service),
+      synced_favicon_getter_(synced_favicon_getter) {
   DCHECK(favicon_service);
   DCHECK(large_icon_service);
 }
@@ -130,7 +132,6 @@
     FaviconRequestOrigin request_origin,
     FaviconRequestPlatform request_platform,
     const GURL& icon_url_for_uma,
-    FaviconRequestHandler::SyncedFaviconGetter synced_favicon_getter,
     bool can_send_history_data,
     base::CancelableTaskTracker* tracker) {
   // First attempt to find the icon locally.
@@ -141,7 +142,7 @@
           &FaviconRequestHandler::OnBitmapLocalDataAvailable,
           weak_ptr_factory_.GetWeakPtr(), page_url, desired_size_in_pixel,
           /*response_callback=*/std::move(callback), request_origin,
-          request_platform, icon_url_for_uma, std::move(synced_favicon_getter),
+          request_platform, icon_url_for_uma,
           CanQueryGoogleServer(request_origin, can_send_history_data), tracker),
       tracker);
 }
@@ -151,7 +152,6 @@
     favicon_base::FaviconImageCallback callback,
     FaviconRequestOrigin request_origin,
     const GURL& icon_url_for_uma,
-    FaviconRequestHandler::SyncedFaviconGetter synced_favicon_getter,
     bool can_send_history_data,
     base::CancelableTaskTracker* tracker) {
   // First attempt to find the icon locally.
@@ -161,7 +161,7 @@
           &FaviconRequestHandler::OnImageLocalDataAvailable,
           weak_ptr_factory_.GetWeakPtr(), page_url,
           /*response_callback=*/std::move(callback), request_origin,
-          icon_url_for_uma, std::move(synced_favicon_getter),
+          icon_url_for_uma,
           CanQueryGoogleServer(request_origin, can_send_history_data), tracker),
       tracker);
 }
@@ -173,7 +173,6 @@
     FaviconRequestOrigin origin,
     FaviconRequestPlatform platform,
     const GURL& icon_url_for_uma,
-    FaviconRequestHandler::SyncedFaviconGetter synced_favicon_getter,
     bool can_query_google_server,
     base::CancelableTaskTracker* tracker,
     const favicon_base::FaviconRawBitmapResult& bitmap_result) {
@@ -214,7 +213,7 @@
   }
 
   scoped_refptr<base::RefCountedMemory> sync_bitmap =
-      std::move(synced_favicon_getter).Run(page_url);
+      synced_favicon_getter_.Run(page_url);
   if (sync_bitmap) {
     // If request to sync succeeds, send the retrieved bitmap.
     RecordFaviconAvailabilityMetric(origin, FaviconAvailability::kSync);
@@ -234,7 +233,6 @@
     favicon_base::FaviconImageCallback response_callback,
     FaviconRequestOrigin origin,
     const GURL& icon_url_for_uma,
-    FaviconRequestHandler::SyncedFaviconGetter synced_favicon_getter,
     bool can_query_google_server,
     base::CancelableTaskTracker* tracker,
     const favicon_base::FaviconImageResult& image_result) {
@@ -269,7 +267,7 @@
   }
 
   scoped_refptr<base::RefCountedMemory> sync_bitmap =
-      std::move(synced_favicon_getter).Run(page_url);
+      synced_favicon_getter_.Run(page_url);
   if (sync_bitmap) {
     // If request to sync succeeds, convert the retrieved bitmap to image and
     // send.
diff --git a/components/favicon/core/favicon_request_handler.h b/components/favicon/core/favicon_request_handler.h
index 11e2c0d..eab6b1b 100644
--- a/components/favicon/core/favicon_request_handler.h
+++ b/components/favicon/core/favicon_request_handler.h
@@ -61,9 +61,11 @@
  public:
   // Callback that requests the synced bitmap for a page url.
   using SyncedFaviconGetter =
-      base::OnceCallback<scoped_refptr<base::RefCountedMemory>(const GURL&)>;
+      base::RepeatingCallback<scoped_refptr<base::RefCountedMemory>(
+          const GURL&)>;
 
-  FaviconRequestHandler(FaviconService* favicon_service,
+  FaviconRequestHandler(const SyncedFaviconGetter& synced_favicon_getter,
+                        FaviconService* favicon_service,
                         LargeIconService* large_icon_service);
 
   ~FaviconRequestHandler() override;
@@ -83,7 +85,6 @@
                                FaviconRequestOrigin request_origin,
                                FaviconRequestPlatform request_platform,
                                const GURL& icon_url_for_uma,
-                               SyncedFaviconGetter synced_favicon_getter,
                                bool can_send_history_data,
                                base::CancelableTaskTracker* tracker);
 
@@ -100,7 +101,6 @@
                                  favicon_base::FaviconImageCallback callback,
                                  FaviconRequestOrigin request_origin,
                                  const GURL& icon_url_for_uma,
-                                 SyncedFaviconGetter synced_favicon_getter,
                                  bool can_send_history_data,
                                  base::CancelableTaskTracker* tracker);
 
@@ -116,7 +116,6 @@
       FaviconRequestOrigin origin,
       FaviconRequestPlatform platform,
       const GURL& icon_url_for_uma,
-      SyncedFaviconGetter synced_favicon_getter,
       bool can_query_google_server,
       base::CancelableTaskTracker* tracker,
       const favicon_base::FaviconRawBitmapResult& bitmap_result);
@@ -130,7 +129,6 @@
       favicon_base::FaviconImageCallback response_callback,
       FaviconRequestOrigin origin,
       const GURL& icon_url_for_uma,
-      SyncedFaviconGetter synced_favicon_getter,
       bool can_query_google_server,
       base::CancelableTaskTracker* tracker,
       const favicon_base::FaviconImageResult& image_result);
@@ -162,6 +160,8 @@
 
   LargeIconService* const large_icon_service_;
 
+  SyncedFaviconGetter const synced_favicon_getter_;
+
   // Map from a group identifier to the number of callbacks in that group which
   // would be waiting for execution. Used for recording metrics for the possible
   // benefit of grouping.
diff --git a/components/favicon/core/favicon_request_handler_unittest.cc b/components/favicon/core/favicon_request_handler_unittest.cc
index d076cdfd..2988a7a 100644
--- a/components/favicon/core/favicon_request_handler_unittest.cc
+++ b/components/favicon/core/favicon_request_handler_unittest.cc
@@ -114,7 +114,8 @@
 class FaviconRequestHandlerTest : public ::testing::Test {
  public:
   FaviconRequestHandlerTest()
-      : favicon_request_handler_(&mock_favicon_service_,
+      : favicon_request_handler_(synced_favicon_getter_.Get(),
+                                 &mock_favicon_service_,
                                  &mock_large_icon_service_) {}
 
  protected:
@@ -146,7 +147,7 @@
       GURL(kDummyPageUrl), kDesiredSizeInPixel,
       base::BindOnce(&StoreBitmap, &result), FaviconRequestOrigin::UNKNOWN,
       kDummyPlatform,
-      /*icon_url_for_uma=*/GURL(), synced_favicon_getter_.Get(),
+      /*icon_url_for_uma=*/GURL(),
       /*can_send_history_data=*/true, &tracker_);
   EXPECT_FALSE(result.is_valid());
   histogram_tester_.ExpectUniqueSample("Sync.FaviconAvailability.UNKNOWN",
@@ -171,7 +172,7 @@
       GURL(kDummyPageUrl), kDesiredSizeInPixel,
       base::BindOnce(&StoreBitmap, &result), FaviconRequestOrigin::UNKNOWN,
       kDummyPlatform,
-      /*icon_url_for_uma=*/GURL(), synced_favicon_getter_.Get(),
+      /*icon_url_for_uma=*/GURL(),
       /*can_send_history_data=*/true, &tracker_);
   EXPECT_TRUE(result.is_valid());
   histogram_tester_.ExpectUniqueSample("Sync.FaviconAvailability.UNKNOWN",
@@ -197,7 +198,7 @@
       GURL(kDummyPageUrl), kDesiredSizeInPixel,
       base::BindOnce(&StoreBitmap, &result), FaviconRequestOrigin::UNKNOWN,
       kDummyPlatform,
-      /*icon_url_for_uma=*/GURL(), synced_favicon_getter_.Get(),
+      /*icon_url_for_uma=*/GURL(),
       /*can_send_history_data=*/true, &tracker_);
   EXPECT_TRUE(result.is_valid());
   histogram_tester_.ExpectUniqueSample("Sync.FaviconAvailability.UNKNOWN",
@@ -234,7 +235,7 @@
       GURL(kDummyPageUrl), kDesiredSizeInPixel,
       base::BindOnce(&StoreBitmap, &result), FaviconRequestOrigin::HISTORY,
       kDummyPlatform,
-      /*icon_url_for_uma=*/GURL(), synced_favicon_getter_.Get(),
+      /*icon_url_for_uma=*/GURL(),
       /*can_send_history_data=*/true, &tracker_);
   EXPECT_TRUE(result.is_valid());
 }
@@ -269,7 +270,7 @@
       GURL(kDummyPageUrl), kDesiredSizeInPixel,
       base::BindOnce(&StoreBitmap, &result), FaviconRequestOrigin::HISTORY,
       kDummyPlatform,
-      /*icon_url_for_uma=*/GURL(), synced_favicon_getter_.Get(),
+      /*icon_url_for_uma=*/GURL(),
       /*can_send_history_data=*/true, &tracker_);
   EXPECT_TRUE(result.is_valid());
   histogram_tester_.ExpectUniqueSample("Sync.FaviconAvailability.HISTORY",
@@ -293,7 +294,7 @@
   favicon_request_handler_.GetFaviconImageForPageURL(
       GURL(kDummyPageUrl), base::BindOnce(&StoreImage, &result),
       FaviconRequestOrigin::UNKNOWN,
-      /*icon_url_for_uma=*/GURL(), synced_favicon_getter_.Get(),
+      /*icon_url_for_uma=*/GURL(),
       /*can_send_history_data=*/true, &tracker_);
   EXPECT_TRUE(result.image.IsEmpty());
   histogram_tester_.ExpectUniqueSample("Sync.FaviconAvailability.UNKNOWN",
@@ -315,7 +316,7 @@
   favicon_request_handler_.GetFaviconImageForPageURL(
       GURL(kDummyPageUrl), base::BindOnce(&StoreImage, &result),
       FaviconRequestOrigin::UNKNOWN,
-      /*icon_url_for_uma=*/GURL(), synced_favicon_getter_.Get(),
+      /*icon_url_for_uma=*/GURL(),
       /*can_send_history_data=*/true, &tracker_);
   EXPECT_FALSE(result.image.IsEmpty());
   histogram_tester_.ExpectUniqueSample("Sync.FaviconAvailability.UNKNOWN",
@@ -338,7 +339,7 @@
   favicon_request_handler_.GetFaviconImageForPageURL(
       GURL(kDummyPageUrl), base::BindOnce(&StoreImage, &result),
       FaviconRequestOrigin::UNKNOWN,
-      /*icon_url_for_uma=*/GURL(), synced_favicon_getter_.Get(),
+      /*icon_url_for_uma=*/GURL(),
       /*can_send_history_data=*/true, &tracker_);
   EXPECT_FALSE(result.image.IsEmpty());
   histogram_tester_.ExpectUniqueSample("Sync.FaviconAvailability.UNKNOWN",
@@ -371,7 +372,7 @@
   favicon_request_handler_.GetFaviconImageForPageURL(
       GURL(kDummyPageUrl), base::BindOnce(&StoreImage, &result),
       FaviconRequestOrigin::RECENTLY_CLOSED_TABS, /*icon_url_for_uma=*/GURL(),
-      synced_favicon_getter_.Get(), /*can_send_history_data=*/true, &tracker_);
+      /*can_send_history_data=*/true, &tracker_);
   EXPECT_FALSE(result.image.IsEmpty());
   histogram_tester_.ExpectUniqueSample(
       "Sync.FaviconAvailability.RECENTLY_CLOSED_TABS",
@@ -406,7 +407,7 @@
   favicon_request_handler_.GetFaviconImageForPageURL(
       GURL(kDummyPageUrl), base::BindOnce(&StoreImage, &result),
       FaviconRequestOrigin::RECENTLY_CLOSED_TABS, /*icon_url_for_uma=*/GURL(),
-      synced_favicon_getter_.Get(),
+
       /*can_send_history_data=*/true, &tracker_);
   EXPECT_FALSE(result.image.IsEmpty());
 }
@@ -431,7 +432,7 @@
       GURL(kDummyPageUrl), kDesiredSizeInPixel,
       base::BindOnce(&StoreBitmap, &result), FaviconRequestOrigin::HISTORY,
       kDummyPlatform,
-      /*icon_url_for_uma=*/GURL(), synced_favicon_getter_.Get(),
+      /*icon_url_for_uma=*/GURL(),
       /*can_send_history_data=*/false, &tracker_);
 }
 
diff --git a/components/guest_view/browser/guest_view_base.cc b/components/guest_view/browser/guest_view_base.cc
index 08e1e0e6..20467419 100644
--- a/components/guest_view/browser/guest_view_base.cc
+++ b/components/guest_view/browser/guest_view_base.cc
@@ -447,7 +447,7 @@
     Destroy(true);
 }
 
-WebContents* GuestViewBase::GetOwnerWebContents() const {
+WebContents* GuestViewBase::GetOwnerWebContents() {
   return owner_web_contents_;
 }
 
diff --git a/components/guest_view/browser/guest_view_base.h b/components/guest_view/browser/guest_view_base.h
index 292c37c..bddbcf5 100644
--- a/components/guest_view/browser/guest_view_base.h
+++ b/components/guest_view/browser/guest_view_base.h
@@ -345,7 +345,7 @@
       const content::WebContents::CreateParams& create_params) final;
   void DidAttach(int guest_proxy_routing_id) final;
   void DidDetach() final;
-  content::WebContents* GetOwnerWebContents() const final;
+  content::WebContents* GetOwnerWebContents() final;
   void SetGuestHost(content::GuestHost* guest_host) final;
   void WillAttach(content::WebContents* embedder_web_contents,
                   int browser_plugin_instance_id,
diff --git a/components/previews/content/previews_optimization_guide.cc b/components/previews/content/previews_optimization_guide.cc
index 3496445..59ee2db 100644
--- a/components/previews/content/previews_optimization_guide.cc
+++ b/components/previews/content/previews_optimization_guide.cc
@@ -114,6 +114,11 @@
   return hosts;
 }
 
+bool ShouldOverrideFetchHintsTimer() {
+  return base::CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kFetchHintsOverrideTimer);
+}
+
 // Provides a random time delta in seconds between |kFetchRandomMinDelay| and
 // |kFetchRandomMaxDelay|.
 base::TimeDelta RandomFetchDelay() {
@@ -413,7 +418,8 @@
   if (!previews::params::IsHintsFetchingEnabled())
     return;
 
-  if (ParseHintsFetchOverrideFromCommandLine()) {
+  if (ParseHintsFetchOverrideFromCommandLine() ||
+      ShouldOverrideFetchHintsTimer()) {
     // Skip the fetch scheduling logic and perform a hints fetch immediately
     // after initialization.
     last_fetch_attempt_ = time_clock_->Now();
diff --git a/components/previews/core/previews_experiments.cc b/components/previews/core/previews_experiments.cc
index d33b9d0..ecb559f 100644
--- a/components/previews/core/previews_experiments.cc
+++ b/components/previews/core/previews_experiments.cc
@@ -115,6 +115,15 @@
                               "max_hosts_in_blacklist", 100);
 }
 
+size_t MaxHintsFetcherTopHostBlacklistSize() {
+  // The blacklist will be limited to the most engaged hosts and will hold twice
+  // (2*N) as many hosts that the HintsFetcher request hints for. The extra N
+  // hosts on the blacklist are meant to cover the case that the engagement
+  // scores on some of the top N host engagement scores decay and they fall out
+  // of the top N.
+  return 2 * MaxHostsForOptimizationGuideServiceHintsFetch();
+}
+
 size_t MaxHostsForOptimizationGuideServiceHintsFetch() {
   return GetFieldTrialParamByFeatureAsInt(
       features::kOptimizationHintsFetching,
@@ -268,6 +277,17 @@
       features::kLitePageServerPreviews, "control_group", false);
 }
 
+bool LitePageRedirectPreviewShouldPresolve() {
+  return base::GetFieldTrialParamByFeatureAsBool(
+      features::kLitePageServerPreviews, "preresolve_on_slow_connections",
+      true);
+}
+
+base::TimeDelta LitePageRedirectPreviewPresolveInterval() {
+  return base::TimeDelta::FromSeconds(base::GetFieldTrialParamByFeatureAsInt(
+      features::kLitePageServerPreviews, "preresolve_interval_in_seconds", 60));
+}
+
 net::EffectiveConnectionType GetECTThresholdForPreview(
     previews::PreviewsType type) {
   switch (type) {
diff --git a/components/previews/core/previews_experiments.h b/components/previews/core/previews_experiments.h
index 1986d0a..2fd9ea4 100644
--- a/components/previews/core/previews_experiments.h
+++ b/components/previews/core/previews_experiments.h
@@ -85,6 +85,13 @@
 // The maximum number of hosts allowed in the in memory black list.
 size_t MaxInMemoryHostsInBlackList();
 
+// The maximum number of hosts that can be stored in the
+// |kHintsFetcherTopHostBlacklist| dictionary pref when initialized. The top
+// hosts will also be returned in order of most engaged. This prevents the most
+// engaged hosts in a user's history before DataSaver being enabled from being
+// requested until the user navigates to the host again.
+size_t MaxHintsFetcherTopHostBlacklistSize();
+
 // The maximum number of hosts allowed to be requested by the client to the
 // remote Optimzation Guide Service.
 size_t MaxHostsForOptimizationGuideServiceHintsFetch();
@@ -147,6 +154,12 @@
 // a navigation.
 size_t LitePageRedirectPreviewMaxNavigationRestarts();
 
+// Whether we should preresolve the lite page redirect server.
+bool LitePageRedirectPreviewShouldPresolve();
+
+// The duration in between preresolving the lite page redirect server.
+base::TimeDelta LitePageRedirectPreviewPresolveInterval();
+
 // The maximum number of seconds to loadshed the Previews server for.
 int PreviewServerLoadshedMaxSeconds();
 
diff --git a/components/previews/core/previews_switches.cc b/components/previews/core/previews_switches.cc
index c61559ba..60a2d43 100644
--- a/components/previews/core/previews_switches.cc
+++ b/components/previews/core/previews_switches.cc
@@ -50,6 +50,11 @@
 // hosts.
 const char kFetchHintsOverride[] = "optimization-guide-fetch-hints-override";
 
+// Overrides the hints fetch scheduling and delay, causing a hints fetch
+// immediately on start up using the TopHostProvider. This is meant for testing.
+const char kFetchHintsOverrideTimer[] =
+    "optimization-guide-fetch-hints-override-timer";
+
 // Overrides the Optimization Guide Service URL that the HintsFetcher will
 // request remote hints from.
 const char kOptimizationGuideServiceURL[] = "optimization-guide-service-url";
diff --git a/components/previews/core/previews_switches.h b/components/previews/core/previews_switches.h
index 0d030acf..142993d6 100644
--- a/components/previews/core/previews_switches.h
+++ b/components/previews/core/previews_switches.h
@@ -20,6 +20,7 @@
 extern const char kClearLitePageRedirectLocalBlacklist[];
 extern const char kHintsProtoOverride[];
 extern const char kFetchHintsOverride[];
+extern const char kFetchHintsOverrideTimer[];
 extern const char kOptimizationGuideServiceURL[];
 extern const char kOptimizationGuideServiceAPIKey[];
 extern const char kPurgeHintCacheStore[];
diff --git a/components/safe_browsing/browser/threat_details.cc b/components/safe_browsing/browser/threat_details.cc
index 3a9b8d943..dbc8385 100644
--- a/components/safe_browsing/browser/threat_details.cc
+++ b/components/safe_browsing/browser/threat_details.cc
@@ -488,6 +488,7 @@
     const std::string& tagname,
     const int parent_element_node_id,
     const std::vector<mojom::AttributeNameValuePtr> attributes,
+    const std::string& inner_html,
     const ClientSafeBrowsingReportRequest::Resource* resource) {
   // Create the element. It should not exist already since this function should
   // only be called once for each element.
@@ -512,6 +513,10 @@
     }
   }
 
+  if (!inner_html.empty()) {
+    cur_element->set_inner_html(inner_html);
+  }
+
   if (resource) {
     cur_element->set_resource_id(resource->id());
   }
@@ -718,7 +723,8 @@
     // Check for a tag_name to avoid adding the summary node to the DOM.
     if (!node.tag_name.empty()) {
       AddDomElement(frame_tree_node_id, node.node_id, node.tag_name,
-                    node.parent_node_id, std::move(node.attributes), resource);
+                    node.parent_node_id, std::move(node.attributes),
+                    node.inner_html, resource);
     }
   }
 }
diff --git a/components/safe_browsing/browser/threat_details.h b/components/safe_browsing/browser/threat_details.h
index ca0c746..0a7461d 100644
--- a/components/safe_browsing/browser/threat_details.h
+++ b/components/safe_browsing/browser/threat_details.h
@@ -177,12 +177,14 @@
   // ID of the element within the frame. |tag_name| is the tag of the element.
   // |parent_element_node_id| is the unique ID of the parent element within the
   // frame. |attributes| contains the names and values of the element's
-  // attributes. |resource| is set if this element is a resource.
+  // attributes. |inner_html| is set if the element contains inline JavaScript.
+  // |resource| is set if this element is a resource.
   void AddDomElement(const int frame_tree_node_id,
                      const int element_node_id,
                      const std::string& tag_name,
                      const int parent_element_node_id,
                      const std::vector<mojom::AttributeNameValuePtr> attributes,
+                     const std::string& inner_html,
                      const ClientSafeBrowsingReportRequest::Resource* resource);
 
   // Populates the referrer chain data in |report_|. This may be skipped if the
diff --git a/components/safe_browsing/common/safe_browsing.mojom b/components/safe_browsing/common/safe_browsing.mojom
index ebe4ffc..52cc061 100644
--- a/components/safe_browsing/common/safe_browsing.mojom
+++ b/components/safe_browsing/common/safe_browsing.mojom
@@ -95,6 +95,8 @@
   // routing ID of the local or remote frame in this renderer process that is
   // responsible for rendering the contents of this frame (to handle OOPIFs).
   int32 child_frame_routing_id;
+  // This field holds inline JavaScript content and remotely hosted scripts.
+  string inner_html;
 };
 
 interface ThreatReporter {
diff --git a/components/safe_browsing/features.cc b/components/safe_browsing/features.cc
index 8f978e0..98e0073 100644
--- a/components/safe_browsing/features.cc
+++ b/components/safe_browsing/features.cc
@@ -23,6 +23,9 @@
 const base::Feature kAdSamplerTriggerFeature{"SafeBrowsingAdSamplerTrigger",
                                              base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kCaptureInlineJavascriptForGoogleAds{
+    "CaptureInlineJavascriptForGoogleAds", base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kCaptureSafetyNetId{"SafeBrowsingCaptureSafetyNetId",
                                         base::FEATURE_DISABLED_BY_DEFAULT};
 
@@ -75,6 +78,7 @@
   bool show_state;
 } kExperimentalFeatures[]{
     {&kAdSamplerTriggerFeature, false},
+    {&kCaptureInlineJavascriptForGoogleAds, true},
     {&kCaptureSafetyNetId, true},
     {&kCheckByURLLoaderThrottle, true},
     {&kCommittedSBInterstitials, true},
diff --git a/components/safe_browsing/features.h b/components/safe_browsing/features.h
index 1508523..e9c8ba67 100644
--- a/components/safe_browsing/features.h
+++ b/components/safe_browsing/features.h
@@ -21,6 +21,10 @@
 // Features list
 extern const base::Feature kAdSamplerTriggerFeature;
 
+// Controls whether we sample inline JavaScript for ads in RIND
+// reports.
+extern const base::Feature kCaptureInlineJavascriptForGoogleAds;
+
 // Controls whether we try to get the SafetyNet ID of the device for use when
 // a SBER user downloads an APK file.
 extern const base::Feature kCaptureSafetyNetId;
diff --git a/components/safe_browsing/renderer/threat_dom_details.cc b/components/safe_browsing/renderer/threat_dom_details.cc
index 076a8a1..4286530 100644
--- a/components/safe_browsing/renderer/threat_dom_details.cc
+++ b/components/safe_browsing/renderer/threat_dom_details.cc
@@ -56,12 +56,19 @@
 void GetDefaultTagAndAttributeList(
     std::vector<TagAndAttributesItem>* tag_and_attributes_list) {
   tag_and_attributes_list->clear();
-
+  // These entries must be sorted by tag name.
+  bool should_capture_js =
+      base::FeatureList::IsEnabled(kCaptureInlineJavascriptForGoogleAds);
+  if (should_capture_js)
+    tag_and_attributes_list->push_back(TagAndAttributesItem("a", {"onclick"}));
   // These entries must be sorted by tag name.
   // These tags are related to identifying Google ads.
   tag_and_attributes_list->push_back(
       TagAndAttributesItem("div", {"data-google-query-id", "id"}));
   tag_and_attributes_list->push_back(TagAndAttributesItem("iframe", {"id"}));
+  if (should_capture_js)
+    tag_and_attributes_list->push_back(
+        TagAndAttributesItem("img", {"onclick"}));
 }
 
 void ParseTagAndAttributeParams(
@@ -153,7 +160,6 @@
   child_node->url = child_url;
   child_node->tag_name = element.TagName().Utf8();
   child_node->parent = summary_node->url;
-
   // The body of an iframe may be in a different renderer. Look up the routing
   // ID of the local or remote frame and store it with the iframe node. If this
   // element is not a frame then the result of the lookup will be null.
@@ -162,7 +168,10 @@
     child_node->child_frame_routing_id =
         content::RenderFrame::GetRoutingIdForWebFrame(subframe);
   }
-
+  if (base::FeatureList::IsEnabled(kCaptureInlineJavascriptForGoogleAds) &&
+      child_node->tag_name == "SCRIPT") {
+    child_node->inner_html = element.TextContent().Utf8();
+  }
   // Populate the element's attributes, but only collect the ones that are
   // configured in the finch study.
   const auto& tag_attribute_iter = std::find_if(
@@ -226,7 +235,10 @@
       element.HasAttribute("src")) {
     return true;
   }
-
+  if (base::FeatureList::IsEnabled(kCaptureInlineJavascriptForGoogleAds) &&
+      element.HasHTMLTagName("script")) {
+    return true;
+  }
   std::string tag_name_lower = base::ToLowerASCII(element.TagName().Ascii());
   const auto& tag_attribute_iter =
       std::find_if(tag_and_attributes_list.begin(),
diff --git a/components/safe_browsing/renderer/threat_dom_details.h b/components/safe_browsing/renderer/threat_dom_details.h
index 9aae208..09f2b57 100644
--- a/components/safe_browsing/renderer/threat_dom_details.h
+++ b/components/safe_browsing/renderer/threat_dom_details.h
@@ -60,6 +60,10 @@
   // Exposed for testing.
   void ExtractResources(std::vector<mojom::ThreatDOMDetailsNodePtr>* resources);
 
+  std::vector<TagAndAttributesItem> GetTagAndAttributesListForTest() {
+    return tag_and_attributes_list_;
+  }
+
  private:
   // Creates a ThreatDOMDetails for the specified RenderFrame.
   // The ThreatDOMDetails should be destroyed prior to destroying
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc
index 008bb39..0e5fad13 100644
--- a/components/viz/service/display/display.cc
+++ b/components/viz/service/display/display.cc
@@ -39,6 +39,7 @@
 #include "ui/gfx/geometry/rect_conversions.h"
 #include "ui/gfx/overlay_transform_utils.h"
 #include "ui/gfx/presentation_feedback.h"
+#include "ui/gfx/swap_result.h"
 
 namespace viz {
 
@@ -599,7 +600,7 @@
   return true;
 }
 
-void Display::DidReceiveSwapBuffersAck() {
+void Display::DidReceiveSwapBuffersAck(const gfx::SwapTimings& timings) {
   if (scheduler_) {
     scheduler_->DidReceiveSwapBuffersAck();
     if (no_pending_swaps_callback_ && scheduler_->pending_swaps() == 0)
@@ -608,6 +609,19 @@
 
   if (renderer_)
     renderer_->SwapBuffersComplete();
+
+  // Adding to pending_presented_callbacks_ must have been done in DrawAndSwap,
+  // and should not be popped until DidReceivePresentationFeedback. Therefore
+  // we must not have an empty list when getting the SwapBuffers ACK (this is
+  // required to happen between those two events).
+  DCHECK(!pending_presented_callbacks_.empty());
+
+  // Check that the swap timings correspond with the timestamp from when
+  // the swap was triggered. Note that not all output surfaces provide timing
+  // information, hence the check for a valid swap_start.
+  const auto swap_time = pending_presented_callbacks_.front().first;
+  if (!timings.swap_start.is_null())
+    DCHECK_LE(swap_time, timings.swap_start);
 }
 
 void Display::DidReceiveTextureInUseResponses(
diff --git a/components/viz/service/display/display.h b/components/viz/service/display/display.h
index 38208d7..289e775 100644
--- a/components/viz/service/display/display.h
+++ b/components/viz/service/display/display.h
@@ -126,7 +126,7 @@
 
   // OutputSurfaceClient implementation.
   void SetNeedsRedrawRect(const gfx::Rect& damage_rect) override;
-  void DidReceiveSwapBuffersAck() override;
+  void DidReceiveSwapBuffersAck(const gfx::SwapTimings& timings) override;
   void DidReceiveTextureInUseResponses(
       const gpu::TextureInUseResponses& responses) override;
   void DidReceiveCALayerParams(
diff --git a/components/viz/service/display/output_surface_client.h b/components/viz/service/display/output_surface_client.h
index aeb78a7d..fa55464 100644
--- a/components/viz/service/display/output_surface_client.h
+++ b/components/viz/service/display/output_surface_client.h
@@ -18,6 +18,7 @@
 namespace gfx {
 struct CALayerParams;
 struct PresentationFeedback;
+struct SwapTimings;
 }  // namespace gfx
 
 namespace viz {
@@ -25,8 +26,9 @@
 class VIZ_SERVICE_EXPORT OutputSurfaceClient {
  public:
   // A notification that the swap of the backbuffer to the hardware is complete
-  // and is now visible to the user.
-  virtual void DidReceiveSwapBuffersAck() = 0;
+  // and is now visible to the user, along with timing information on when the
+  // swapping of the backbuffer started and completed.
+  virtual void DidReceiveSwapBuffersAck(const gfx::SwapTimings& timings) = 0;
 
   // For surfaceless/ozone implementations to create damage for the next frame.
   virtual void SetNeedsRedrawRect(const gfx::Rect& damage_rect) = 0;
diff --git a/components/viz/service/display_embedder/gl_output_surface.cc b/components/viz/service/display_embedder/gl_output_surface.cc
index b5b356b..f422160 100644
--- a/components/viz/service/display_embedder/gl_output_surface.cc
+++ b/components/viz/service/display_embedder/gl_output_surface.cc
@@ -154,8 +154,9 @@
 
 void GLOutputSurface::ApplyExternalStencil() {}
 
-void GLOutputSurface::DidReceiveSwapBuffersAck(gfx::SwapResult result) {
-  client_->DidReceiveSwapBuffersAck();
+void GLOutputSurface::DidReceiveSwapBuffersAck(
+    const gfx::SwapResponse& response) {
+  client_->DidReceiveSwapBuffersAck(response.timings);
 }
 
 void GLOutputSurface::HandlePartialSwap(
@@ -176,7 +177,7 @@
     client_->DidReceiveTextureInUseResponses(params.texture_in_use_responses);
   if (!params.ca_layer_params.is_empty)
     client_->DidReceiveCALayerParams(params.ca_layer_params);
-  DidReceiveSwapBuffersAck(params.swap_response.result);
+  DidReceiveSwapBuffersAck(params.swap_response);
 
   UpdateLatencyInfoOnSwap(params.swap_response, &latency_info);
   latency_tracker_.OnGpuSwapBuffersCompleted(latency_info);
diff --git a/components/viz/service/display_embedder/gl_output_surface.h b/components/viz/service/display_embedder/gl_output_surface.h
index e50654b..ce845635 100644
--- a/components/viz/service/display_embedder/gl_output_surface.h
+++ b/components/viz/service/display_embedder/gl_output_surface.h
@@ -59,7 +59,7 @@
   ui::LatencyTracker* latency_tracker() { return &latency_tracker_; }
 
   // Called when a swap completion is signaled from ImageTransportSurface.
-  virtual void DidReceiveSwapBuffersAck(gfx::SwapResult result);
+  virtual void DidReceiveSwapBuffersAck(const gfx::SwapResponse& response);
 
   // Called in SwapBuffers() when a swap is determined to be partial. Subclasses
   // might override this method because different platforms handle partial swaps
diff --git a/components/viz/service/display_embedder/gl_output_surface_buffer_queue.cc b/components/viz/service/display_embedder/gl_output_surface_buffer_queue.cc
index f03d47c..d343b9f9 100644
--- a/components/viz/service/display_embedder/gl_output_surface_buffer_queue.cc
+++ b/components/viz/service/display_embedder/gl_output_surface_buffer_queue.cc
@@ -102,18 +102,17 @@
 }
 
 void GLOutputSurfaceBufferQueue::DidReceiveSwapBuffersAck(
-    gfx::SwapResult result) {
+    const gfx::SwapResponse& response) {
   bool force_swap = false;
-  if (result == gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS) {
+  if (response.result == gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS) {
     // Even through the swap failed, this is a fixable error so we can pretend
     // it succeeded to the rest of the system.
-    result = gfx::SwapResult::SWAP_ACK;
     buffer_queue_->RecreateBuffers();
     force_swap = true;
   }
 
   buffer_queue_->PageFlipComplete();
-  client()->DidReceiveSwapBuffersAck();
+  client()->DidReceiveSwapBuffersAck(response.timings);
 
   if (force_swap)
     client()->SetNeedsRedrawRect(gfx::Rect(swap_size_));
diff --git a/components/viz/service/display_embedder/gl_output_surface_buffer_queue.h b/components/viz/service/display_embedder/gl_output_surface_buffer_queue.h
index 4da65a4..476cb0b 100644
--- a/components/viz/service/display_embedder/gl_output_surface_buffer_queue.h
+++ b/components/viz/service/display_embedder/gl_output_surface_buffer_queue.h
@@ -62,7 +62,7 @@
   void SetDrawRectangle(const gfx::Rect& damage) override;
 
   // GLOutputSurface:
-  void DidReceiveSwapBuffersAck(gfx::SwapResult result) override;
+  void DidReceiveSwapBuffersAck(const gfx::SwapResponse& response) override;
 
   std::unique_ptr<BufferQueue> buffer_queue_;
 
diff --git a/components/viz/service/display_embedder/gl_output_surface_offscreen.cc b/components/viz/service/display_embedder/gl_output_surface_offscreen.cc
index 6fe0bf1..0efe65f 100644
--- a/components/viz/service/display_embedder/gl_output_surface_offscreen.cc
+++ b/components/viz/service/display_embedder/gl_output_surface_offscreen.cc
@@ -117,7 +117,9 @@
 void GLOutputSurfaceOffscreen::OnSwapBuffersComplete(
     std::vector<ui::LatencyInfo> latency_info) {
   latency_tracker()->OnGpuSwapBuffersCompleted(latency_info);
-  client()->DidReceiveSwapBuffersAck();
+  // Swap timings are not available since for offscreen there is no Swap, just
+  // a SignalSyncToken.
+  client()->DidReceiveSwapBuffersAck(gfx::SwapTimings());
   client()->DidReceivePresentationFeedback(gfx::PresentationFeedback());
 }
 
diff --git a/components/viz/service/display_embedder/skia_output_device.cc b/components/viz/service/display_embedder/skia_output_device.cc
index 568e5ea..a07b5b1 100644
--- a/components/viz/service/display_embedder/skia_output_device.cc
+++ b/components/viz/service/display_embedder/skia_output_device.cc
@@ -46,6 +46,9 @@
 
   params_->swap_response.result = result;
   params_->swap_response.timings.swap_end = base::TimeTicks::Now();
+  did_swap_buffer_complete_callback_.Run(
+      *params_, gfx::Size(draw_surface_->width(), draw_surface_->height()));
+
   if (feedback_) {
     std::move(*feedback_)
         .Run(gfx::PresentationFeedback(
@@ -55,8 +58,6 @@
                 ? 0
                 : gfx::PresentationFeedback::Flags::kFailure));
   }
-  did_swap_buffer_complete_callback_.Run(
-      *params_, gfx::Size(draw_surface_->width(), draw_surface_->height()));
 
   feedback_.reset();
   auto response = params_->swap_response;
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc
index 34d0877..e9540cfc 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -573,7 +573,7 @@
     client_->DidReceiveTextureInUseResponses(params.texture_in_use_responses);
   if (!params.ca_layer_params.is_empty)
     client_->DidReceiveCALayerParams(params.ca_layer_params);
-  client_->DidReceiveSwapBuffersAck();
+  client_->DidReceiveSwapBuffersAck(params.swap_response.timings);
   if (needs_swap_size_notifications_)
     client_->DidSwapWithSize(pixel_size);
 }
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_non_ddl.cc b/components/viz/service/display_embedder/skia_output_surface_impl_non_ddl.cc
index dc22ef2..770ba59 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_non_ddl.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_non_ddl.cc
@@ -252,11 +252,14 @@
 
 void SkiaOutputSurfaceImplNonDDL::SkiaSwapBuffers(OutputSurfaceFrame frame) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  gfx::SwapTimings swap_timings;
+  swap_timings.swap_start = base::TimeTicks::Now();
   gl_surface_->SwapBuffers(
       base::BindOnce(&SkiaOutputSurfaceImplNonDDL::BufferPresented,
                      weak_ptr_factory_.GetWeakPtr()));
+  swap_timings.swap_end = base::TimeTicks::Now();
   if (need_swapbuffers_ack_)
-    client_->DidReceiveSwapBuffersAck();
+    client_->DidReceiveSwapBuffersAck(swap_timings);
 }
 
 SkCanvas* SkiaOutputSurfaceImplNonDDL::BeginPaintRenderPass(
diff --git a/components/viz/service/display_embedder/software_output_surface.cc b/components/viz/service/display_embedder/software_output_surface.cc
index 31f360b..e2d4cdb 100644
--- a/components/viz/service/display_embedder/software_output_surface.cc
+++ b/components/viz/service/display_embedder/software_output_surface.cc
@@ -16,6 +16,7 @@
 #include "components/viz/service/display/output_surface_frame.h"
 #include "components/viz/service/display/software_output_device.h"
 #include "ui/gfx/presentation_feedback.h"
+#include "ui/gfx/swap_result.h"
 #include "ui/gfx/vsync_provider.h"
 #include "ui/latency/latency_info.h"
 
@@ -71,8 +72,9 @@
       << "arrive before the previous latency info is processed.";
   stored_latency_info_ = std::move(frame.latency_info);
 
-  software_device()->OnSwapBuffers(base::BindOnce(
-      &SoftwareOutputSurface::SwapBuffersCallback, weak_factory_.GetWeakPtr()));
+  software_device()->OnSwapBuffers(
+      base::BindOnce(&SoftwareOutputSurface::SwapBuffersCallback,
+                     weak_factory_.GetWeakPtr(), swap_time));
 
   gfx::VSyncProvider* vsync_provider = software_device()->GetVSyncProvider();
   if (vsync_provider && update_vsync_parameters_callback_) {
@@ -106,11 +108,12 @@
   return 0;
 }
 
-void SoftwareOutputSurface::SwapBuffersCallback(const gfx::Size& pixel_size) {
+void SoftwareOutputSurface::SwapBuffersCallback(base::TimeTicks swap_time,
+                                                const gfx::Size& pixel_size) {
   latency_tracker_.OnGpuSwapBuffersCompleted(stored_latency_info_);
   client_->DidFinishLatencyInfo(stored_latency_info_);
   std::vector<ui::LatencyInfo>().swap(stored_latency_info_);
-  client_->DidReceiveSwapBuffersAck();
+  client_->DidReceiveSwapBuffersAck({swap_time, swap_time});
 
   base::TimeTicks now = base::TimeTicks::Now();
   base::TimeDelta interval_to_next_refresh =
diff --git a/components/viz/service/display_embedder/software_output_surface.h b/components/viz/service/display_embedder/software_output_surface.h
index 2fec3a2..df55a34 100644
--- a/components/viz/service/display_embedder/software_output_surface.h
+++ b/components/viz/service/display_embedder/software_output_surface.h
@@ -53,7 +53,8 @@
 #endif
 
  private:
-  void SwapBuffersCallback(const gfx::Size& pixel_size);
+  void SwapBuffersCallback(base::TimeTicks swap_time,
+                           const gfx::Size& pixel_size);
   void UpdateVSyncParameters(base::TimeTicks timebase,
                              base::TimeDelta interval);
 
diff --git a/components/viz/test/fake_output_surface.cc b/components/viz/test/fake_output_surface.cc
index c924f0a..95fc63e 100644
--- a/components/viz/test/fake_output_surface.cc
+++ b/components/viz/test/fake_output_surface.cc
@@ -54,9 +54,9 @@
 }
 
 void FakeOutputSurface::SwapBuffersAck() {
-  client_->DidReceiveSwapBuffersAck();
-  client_->DidReceivePresentationFeedback(
-      {base::TimeTicks::Now(), base::TimeDelta(), 0});
+  base::TimeTicks now = base::TimeTicks::Now();
+  client_->DidReceiveSwapBuffersAck({now, now});
+  client_->DidReceivePresentationFeedback({now, base::TimeDelta(), 0});
 }
 
 void FakeOutputSurface::BindFramebuffer() {
diff --git a/components/viz/test/fake_skia_output_surface.cc b/components/viz/test/fake_skia_output_surface.cc
index 29a18da..52fdabcc 100644
--- a/components/viz/test/fake_skia_output_surface.cc
+++ b/components/viz/test/fake_skia_output_surface.cc
@@ -21,6 +21,7 @@
 #include "third_party/skia/include/core/SkPixelRef.h"
 #include "third_party/skia/include/gpu/GrBackendSurface.h"
 #include "third_party/skia/include/gpu/gl/GrGLTypes.h"
+#include "ui/gfx/swap_result.h"
 #include "ui/gl/gl_utils.h"
 
 namespace viz {
@@ -330,9 +331,9 @@
 }
 
 void FakeSkiaOutputSurface::SwapBuffersAck() {
-  client_->DidReceiveSwapBuffersAck();
-  client_->DidReceivePresentationFeedback(
-      {base::TimeTicks::Now(), base::TimeDelta(), 0});
+  base::TimeTicks now = base::TimeTicks::Now();
+  client_->DidReceiveSwapBuffersAck({now, now});
+  client_->DidReceivePresentationFeedback({now, base::TimeDelta(), 0});
 }
 
 }  // namespace viz
diff --git a/content/app_shim_remote_cocoa/render_widget_host_ns_view_bridge.h b/content/app_shim_remote_cocoa/render_widget_host_ns_view_bridge.h
index 0ac0181..772b60e1 100644
--- a/content/app_shim_remote_cocoa/render_widget_host_ns_view_bridge.h
+++ b/content/app_shim_remote_cocoa/render_widget_host_ns_view_bridge.h
@@ -48,7 +48,8 @@
   void SetBackgroundColor(SkColor color) override;
   void SetVisible(bool visible) override;
   void SetTooltipText(const base::string16& display_text) override;
-  void SetTextInputType(ui::TextInputType text_input_type) override;
+  void SetTextInputState(ui::TextInputType text_input_type,
+                         uint32_t flags) override;
   void SetTextSelection(const base::string16& text,
                         uint64_t offset,
                         const gfx::Range& range) override;
diff --git a/content/app_shim_remote_cocoa/render_widget_host_ns_view_bridge.mm b/content/app_shim_remote_cocoa/render_widget_host_ns_view_bridge.mm
index 758ed69e..e4ebe13 100644
--- a/content/app_shim_remote_cocoa/render_widget_host_ns_view_bridge.mm
+++ b/content/app_shim_remote_cocoa/render_widget_host_ns_view_bridge.mm
@@ -183,9 +183,11 @@
   [cocoa_view_ cancelComposition];
 }
 
-void RenderWidgetHostNSViewBridge::SetTextInputType(
-    ui::TextInputType text_input_type) {
+void RenderWidgetHostNSViewBridge::SetTextInputState(
+    ui::TextInputType text_input_type,
+    uint32_t flags) {
   [cocoa_view_ setTextInputType:text_input_type];
+  [cocoa_view_ setTextInputFlags:flags];
 }
 
 void RenderWidgetHostNSViewBridge::SetTextSelection(const base::string16& text,
diff --git a/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.h b/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.h
index 0013b7c..6f73679 100644
--- a/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.h
+++ b/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.h
@@ -134,8 +134,6 @@
   // the whole content yet.
   NSRange markedRange_;
 
-  ui::TextInputType textInputType_;
-
   // The text selection, cached from the RenderWidgetHostView. This is only ever
   // updated from the renderer.
   base::string16 textSelectionText_;
@@ -208,6 +206,7 @@
 
 @property(nonatomic, assign) NSRange markedRange;
 @property(nonatomic, assign) ui::TextInputType textInputType;
+@property(nonatomic, assign) int textInputFlags;
 
 @property(nonatomic, assign) NSSpellChecker* spellCheckerForTesting;
 
diff --git a/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm b/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm
index f70ed3d..cf9ef06 100644
--- a/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm
+++ b/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm
@@ -22,6 +22,7 @@
 #import "content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.h"
 #import "content/public/browser/render_widget_host_view_mac_delegate.h"
 #include "content/public/common/content_features.h"
+#include "third_party/blink/public/platform/web_text_input_type.h"
 #include "ui/accessibility/platform/ax_platform_node.h"
 #import "ui/base/clipboard/clipboard_util_mac.h"
 #import "ui/base/cocoa/appkit_utils.h"
@@ -159,7 +160,16 @@
   API_AVAILABLE(macos(10.12.2))
   base::scoped_nsobject<NSCandidateListTouchBarItem> candidateListTouchBarItem_;
   NSInteger textSuggestionsSequenceNumber_;
+  BOOL shouldRequestTextSubstitutions_;
+  BOOL substitutionWasApplied_;
+
+  NSTextCheckingTypes userEnabledTextCheckingTypes_;
+  NSTextCheckingTypes userDisabledTextCheckingTypes_;
 }
+@property(readonly) NSTextCheckingType enabledTextCheckingTypes;
+@property(readonly) BOOL inputAllowsTextSubstitution;
+@property(readonly) NSSpellChecker* spellChecker;
+
 - (void)processedWheelEvent:(const blink::WebMouseWheelEvent&)event
                    consumed:(BOOL)consumed;
 - (void)keyEvent:(NSEvent*)theEvent wasKeyEquivalent:(BOOL)equiv;
@@ -168,6 +178,7 @@
 - (void)windowDidBecomeKey:(NSNotification*)notification;
 - (void)windowDidResignKey:(NSNotification*)notification;
 - (void)sendViewBoundsInWindowToHost;
+- (void)requestTextSubstitutions;
 - (void)requestTextSuggestions API_AVAILABLE(macos(10.12.2));
 - (void)sendWindowFrameInScreenToHost;
 - (bool)hostIsDisconnected;
@@ -185,6 +196,7 @@
 @implementation RenderWidgetHostViewCocoa
 @synthesize markedRange = markedRange_;
 @synthesize textInputType = textInputType_;
+@synthesize textInputFlags = textInputFlags_;
 @synthesize spellCheckerForTesting = spellCheckerForTesting_;
 
 - (id)initWithHost:(RenderWidgetHostNSViewHost*)host
@@ -242,6 +254,128 @@
   host_->OnBoundsInWindowChanged(gfxViewBoundsInWindow, true);
 }
 
+- (BOOL)inputAllowsTextSubstitution {
+  if (textInputType_ == ui::TEXT_INPUT_TYPE_NONE)
+    return NO;
+  if (textInputType_ == ui::TEXT_INPUT_TYPE_PASSWORD)
+    return NO;
+  if (textInputFlags_ & blink::kWebTextInputFlagSpellcheckOff)
+    return NO;
+  return YES;
+}
+
+- (NSSpellChecker*)spellChecker {
+  if (spellCheckerForTesting_)
+    return spellCheckerForTesting_;
+  return NSSpellChecker.sharedSpellChecker;
+}
+
+- (void)requestTextSubstitutions {
+  if (!self.inputAllowsTextSubstitution)
+    return;
+
+  NSTextCheckingType enabledTextCheckingTypes = self.enabledTextCheckingTypes;
+  if (!enabledTextCheckingTypes)
+    return;
+
+  NSString* availableText = base::SysUTF16ToNSString(textSelectionText_);
+
+  if (!availableText)
+    return;
+
+  auto* textCheckingResults =
+      [self.spellChecker checkString:availableText
+                               range:NSMakeRange(0, availableText.length)
+                               types:enabledTextCheckingTypes
+                             options:nil
+              inSpellDocumentWithTag:0
+                         orthography:nullptr
+                           wordCount:nullptr];
+
+  NSUInteger cursorLocation = textSelectionRange_.start();
+  base::scoped_nsobject<NSTextCheckingResult> scopedCandidateResult;
+  for (NSTextCheckingResult* result in textCheckingResults) {
+    NSTextCheckingResult* adjustedResult =
+        [result resultByAdjustingRangesWithOffset:textSelectionOffset_];
+    if (!NSLocationInRange(cursorLocation,
+                           NSMakeRange(adjustedResult.range.location,
+                                       adjustedResult.range.length + 1)))
+      continue;
+    constexpr NSTextCheckingType textCheckingTypesToReplaceImmediately =
+        NSTextCheckingTypeQuote | NSTextCheckingTypeDash;
+    if (adjustedResult.resultType & textCheckingTypesToReplaceImmediately) {
+      [self insertText:adjustedResult.replacementString
+          replacementRange:adjustedResult.range];
+      continue;
+    }
+    scopedCandidateResult.reset([adjustedResult retain]);
+  }
+  NSTextCheckingResult* candidateResult = scopedCandidateResult.get();
+  if (!candidateResult)
+    return;
+
+  NSRect textRectInScreenCoordinates =
+      [self firstRectForCharacterRange:candidateResult.range
+                           actualRange:nullptr];
+  NSRect textRectInWindowCoordinates =
+      [self.window convertRectFromScreen:textRectInScreenCoordinates];
+  NSRect textRectInViewCoordinates =
+      [self convertRect:textRectInWindowCoordinates fromView:nil];
+
+  [self.spellChecker
+      showCorrectionIndicatorOfType:NSCorrectionIndicatorTypeDefault
+                      primaryString:candidateResult.replacementString
+                 alternativeStrings:candidateResult.alternativeStrings
+                    forStringInRect:textRectInViewCoordinates
+                               view:self
+                  completionHandler:^(NSString* acceptedString) {
+                    [self didAcceptReplacementString:acceptedString
+                               forTextCheckingResult:candidateResult];
+                  }];
+}
+
+- (void)didAcceptReplacementString:(NSString*)acceptedString
+             forTextCheckingResult:(NSTextCheckingResult*)correction {
+  // TODO: Keep NSSpellChecker up to date on the user's response via
+  // -recordResponse:toCorrection:forWord:language:inSpellDocumentWithTag:.
+  // Call it to report whether they initially accepted or rejected the
+  // suggestion, but also if they edit, revert, etc. later.
+
+  if (acceptedString == nil)
+    return;
+
+  NSRange availableTextRange =
+      NSMakeRange(textSelectionOffset_, textSelectionText_.length());
+
+  if (NSMaxRange(correction.range) > NSMaxRange(availableTextRange))
+    return;
+
+  NSAttributedString* attString = [[[NSAttributedString alloc]
+      initWithString:base::SysUTF16ToNSString(textSelectionText_)] autorelease];
+  NSRange trailingRange = NSMakeRange(
+      NSMaxRange(correction.range),
+      NSMaxRange(availableTextRange) - NSMaxRange(correction.range));
+
+  if (trailingRange.length > 0 &&
+      trailingRange.location < NSMaxRange(availableTextRange)) {
+    NSRange trailingRangeInAvailableText = NSMakeRange(
+        trailingRange.location - textSelectionOffset_, trailingRange.length);
+    if (@available(macOS 10.12, *)) {
+      NSString* trailingString =
+          [attString.string substringWithRange:trailingRangeInAvailableText];
+      if ([self.spellChecker preventsAutocorrectionBeforeString:trailingString
+                                                       language:nil])
+        return;
+    }
+    if ([attString doubleClickAtIndex:trailingRangeInAvailableText.location]
+            .location < trailingRangeInAvailableText.location)
+      return;
+  }
+
+  substitutionWasApplied_ = YES;
+  [self insertText:acceptedString replacementRange:correction.range];
+}
+
 - (void)requestTextSuggestions {
   auto* touchBarItem = candidateListTouchBarItem_.get();
   if (!touchBarItem)
@@ -259,10 +393,9 @@
   selectionRange.location -= textSelectionOffset_;
   if (NSMaxRange(selectionRange) > selectionText.length)
     return;
-  NSSpellChecker* spell_checker = spellCheckerForTesting_
-                                      ? spellCheckerForTesting_
-                                      : [NSSpellChecker sharedSpellChecker];
-  textSuggestionsSequenceNumber_ = [spell_checker
+
+  // TODO: Fetch the spell document tag from the renderer (or equivalent).
+  textSuggestionsSequenceNumber_ = [self.spellChecker
       requestCandidatesForSelectedRange:selectionRange
                                inString:selectionText
                                   types:NSTextCheckingAllSystemTypes
@@ -281,12 +414,36 @@
                       }];
 }
 
+- (NSTextCheckingType)enabledTextCheckingTypes {
+  NSTextCheckingType checkingTypes = 0;
+  if (NSSpellChecker.automaticQuoteSubstitutionEnabled)
+    checkingTypes |= NSTextCheckingTypeQuote;
+  if (NSSpellChecker.automaticDashSubstitutionEnabled)
+    checkingTypes |= NSTextCheckingTypeDash;
+  if (NSSpellChecker.automaticTextReplacementEnabled)
+    checkingTypes |= NSTextCheckingTypeReplacement;
+  checkingTypes |= userEnabledTextCheckingTypes_;
+  checkingTypes &= ~userDisabledTextCheckingTypes_;
+  return checkingTypes;
+}
+
+- (void)orderFrontSubstitutionsPanel:(id)sender {
+  [NSSpellChecker.sharedSpellChecker.substitutionsPanel orderFront:sender];
+}
+
 - (void)setTextSelectionText:(base::string16)text
                       offset:(size_t)offset
                        range:(gfx::Range)range {
   textSelectionText_ = text;
   textSelectionOffset_ = offset;
   textSelectionRange_ = range;
+  substitutionWasApplied_ = NO;
+  [NSSpellChecker.sharedSpellChecker dismissCorrectionIndicatorForView:self];
+  if (shouldRequestTextSubstitutions_ && !substitutionWasApplied_ &&
+      textSelectionRange_.is_empty()) {
+    shouldRequestTextSubstitutions_ = NO;
+    [self requestTextSubstitutions];
+  }
   if (@available(macOS 10.12.2, *))
     [self requestTextSuggestions];
 }
@@ -1365,7 +1522,49 @@
   return YES;
 }
 
+- (void)toggleTextCheckingType:(NSTextCheckingType)type {
+  if (self.enabledTextCheckingTypes & type) {
+    userEnabledTextCheckingTypes_ &= ~type;
+    userDisabledTextCheckingTypes_ |= type;
+  } else {
+    userEnabledTextCheckingTypes_ |= type;
+    userDisabledTextCheckingTypes_ &= ~type;
+  }
+}
+
+- (void)toggleAutomaticQuoteSubstitution:(id)sender {
+  [self toggleTextCheckingType:NSTextCheckingTypeQuote];
+}
+
+- (void)toggleAutomaticDashSubstitution:(id)sender {
+  [self toggleTextCheckingType:NSTextCheckingTypeDash];
+}
+
+- (void)toggleAutomaticTextReplacement:(id)sender {
+  [self toggleTextCheckingType:NSTextCheckingTypeReplacement];
+}
+
 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item {
+  if (NSMenuItem* menuItem = base::mac::ObjCCast<NSMenuItem>(item)) {
+    NSTextCheckingType representedTextCheckingType = 0;
+    if (item.action == @selector(orderFrontSubstitutionsPanel:)) {
+      return YES;
+    } else if (item.action == @selector(toggleAutomaticQuoteSubstitution:)) {
+      representedTextCheckingType = NSTextCheckingTypeQuote;
+    } else if (item.action == @selector(toggleAutomaticDashSubstitution:)) {
+      representedTextCheckingType = NSTextCheckingTypeDash;
+    } else if (item.action == @selector(toggleAutomaticTextReplacement:)) {
+      representedTextCheckingType = NSTextCheckingTypeReplacement;
+    }
+    if (representedTextCheckingType) {
+      menuItem.state =
+          (self.enabledTextCheckingTypes & representedTextCheckingType)
+              ? NSControlStateValueOn
+              : NSControlStateValueOff;
+      return self.inputAllowsTextSubstitution;
+    }
+  }
+
   if (responderDelegate_ &&
       [responderDelegate_ respondsToSelector:@selector
                           (validateUserInterfaceItem:isValidItem:)]) {
@@ -1767,6 +1966,7 @@
   NSString* im_text = isAttributedString ? [string string] : string;
   if (handlingKeyDown_) {
     textToBeInserted_.append(base::SysNSStringToUTF16(im_text));
+    shouldRequestTextSubstitutions_ = YES;
   } else {
     gfx::Range replacement_range(replacementRange);
     host_->ImeCommitText(base::SysNSStringToUTF16(im_text), replacement_range);
@@ -1848,6 +2048,8 @@
 }
 
 - (void)cancelComposition {
+  [NSSpellChecker.sharedSpellChecker dismissCorrectionIndicatorForView:self];
+
   if (!hasMarkedText_)
     return;
 
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 54df002..0cb96497 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -1554,6 +1554,8 @@
     "renderer_host/input_event_shim.h",
     "renderer_host/legacy_render_widget_host_win.cc",
     "renderer_host/legacy_render_widget_host_win.h",
+    "renderer_host/media/aec_dump_manager_impl.cc",
+    "renderer_host/media/aec_dump_manager_impl.h",
     "renderer_host/media/audio_input_delegate_impl.cc",
     "renderer_host/media/audio_input_delegate_impl.h",
     "renderer_host/media/audio_input_device_manager.cc",
diff --git a/content/browser/accessibility/fullscreen_browsertest.cc b/content/browser/accessibility/fullscreen_browsertest.cc
index aff774b..214e764 100644
--- a/content/browser/accessibility/fullscreen_browsertest.cc
+++ b/content/browser/accessibility/fullscreen_browsertest.cc
@@ -61,7 +61,7 @@
     is_fullscreen_ = false;
   }
 
-  bool IsFullscreenForTabOrPending(const WebContents*) const override {
+  bool IsFullscreenForTabOrPending(const WebContents*) override {
     return is_fullscreen_;
   }
 
diff --git a/content/browser/appcache/appcache_group.h b/content/browser/appcache/appcache_group.h
index 5229a54..a058f600 100644
--- a/content/browser/appcache/appcache_group.h
+++ b/content/browser/appcache/appcache_group.h
@@ -47,9 +47,17 @@
 
   class CONTENT_EXPORT UpdateObserver {
    public:
+    UpdateObserver(const UpdateObserver&) = delete;
+    UpdateObserver& operator=(const UpdateObserver&) = delete;
+
     // Called just after an appcache update has completed.
     virtual void OnUpdateComplete(AppCacheGroup* group) = 0;
-    virtual ~UpdateObserver() {}
+
+   protected:
+    // The constructor and destructor exist to facilitate subclassing, and
+    // should not be called directly.
+    UpdateObserver() noexcept = default;
+    virtual ~UpdateObserver() = default;
   };
 
   enum UpdateAppCacheStatus {
diff --git a/content/browser/appcache/appcache_host.h b/content/browser/appcache/appcache_host.h
index d71c73e..8d01646 100644
--- a/content/browser/appcache/appcache_host.h
+++ b/content/browser/appcache/appcache_host.h
@@ -61,13 +61,20 @@
  public:
   class CONTENT_EXPORT Observer {
    public:
+    Observer(const Observer&) = delete;
+    Observer& operator=(const Observer&) = delete;
+
     // Called just after the cache selection algorithm completes.
     virtual void OnCacheSelectionComplete(AppCacheHost* host) = 0;
 
     // Called just prior to the instance being deleted.
     virtual void OnDestructionImminent(AppCacheHost* host) = 0;
 
-    virtual ~Observer() {}
+   protected:
+    // The constructor and destructor exist to facilitate subclassing, and
+    // should not be called directly.
+    Observer() noexcept = default;
+    virtual ~Observer() = default;
   };
 
   AppCacheHost(const base::UnguessableToken& host_id,
diff --git a/content/browser/appcache/appcache_quota_client_unittest.cc b/content/browser/appcache/appcache_quota_client_unittest.cc
index 7c1f72d..2eef1c61 100644
--- a/content/browser/appcache/appcache_quota_client_unittest.cc
+++ b/content/browser/appcache/appcache_quota_client_unittest.cc
@@ -114,6 +114,8 @@
   }
 
   AppCacheQuotaClient* CreateClient() {
+    // The bare operator new is used here because AppCacheQuotaClient deletes
+    // itself when the QuotaManager goes out of scope.
     return new AppCacheQuotaClient(&mock_service_);
   }
 
diff --git a/content/browser/appcache/appcache_service_impl.h b/content/browser/appcache/appcache_service_impl.h
index 55c05ddc..8d1629d 100644
--- a/content/browser/appcache/appcache_service_impl.h
+++ b/content/browser/appcache/appcache_service_impl.h
@@ -73,6 +73,9 @@
 
   class CONTENT_EXPORT Observer {
    public:
+    Observer(const Observer&) = delete;
+    Observer& operator=(const Observer&) = delete;
+
     // Called just prior to the instance being deleted.
     virtual void OnServiceDestructionImminent(AppCacheServiceImpl* service) {}
 
@@ -82,7 +85,12 @@
     // ref provided.
     virtual void OnServiceReinitialized(
         AppCacheStorageReference* old_storage_ref) {}
-    virtual ~Observer() {}
+
+   protected:
+    // The constructor and destructor exist to facilitate subclassing, and
+    // should not be called directly.
+    Observer() noexcept = default;
+    virtual ~Observer() = default;
   };
 
   // If not using quota management, the proxy may be NULL.
diff --git a/content/browser/appcache/appcache_storage.h b/content/browser/appcache/appcache_storage.h
index cd45806..296aa93 100644
--- a/content/browser/appcache/appcache_storage.h
+++ b/content/browser/appcache/appcache_storage.h
@@ -48,6 +48,9 @@
 
   class CONTENT_EXPORT Delegate {
    public:
+    Delegate(const Delegate&) = delete;
+    Delegate& operator=(const Delegate&) = delete;
+
     // If retrieval fails, 'collection' will be NULL.
     virtual void OnAllInfo(AppCacheInfoCollection* collection) {}
 
@@ -87,7 +90,10 @@
                                      const GURL& mainfest_url) {}
 
    protected:
-    virtual ~Delegate() {}
+    // The constructor and destructor exist to facilitate subclassing, and
+    // should not be called directly.
+    Delegate() noexcept = default;
+    virtual ~Delegate() = default;
   };
 
   explicit AppCacheStorage(AppCacheServiceImpl* service);
diff --git a/content/browser/appcache/appcache_update_job.cc b/content/browser/appcache/appcache_update_job.cc
index e25839d..dcc1c51 100644
--- a/content/browser/appcache/appcache_update_job.cc
+++ b/content/browser/appcache/appcache_update_job.cc
@@ -253,7 +253,7 @@
   DCHECK(!inprogress_cache_.get());
   DCHECK(pending_master_entries_.empty());
 
-  // The job must not outlive any of its fetchers.
+  // No fetcher may outlive the job.
   CHECK(!manifest_fetcher_);
   CHECK(pending_url_fetches_.empty());
   CHECK(master_entry_fetches_.empty());
@@ -282,11 +282,10 @@
       return;
     }
 
-    std::pair<PendingMasters::iterator, bool> ret =
-        pending_master_entries_.insert(
-            PendingMasters::value_type(new_master_resource, PendingHosts()));
-    is_new_pending_master_entry = ret.second;
-    ret.first->second.push_back(host);
+    auto emplace_result = pending_master_entries_.emplace(
+        new_master_resource, std::vector<AppCacheHost*>());
+    is_new_pending_master_entry = emplace_result.second;
+    emplace_result.first->second.push_back(host);
     host->AddObserver(this);
   }
 
@@ -395,11 +394,11 @@
 
 void AppCacheUpdateJob::FetchManifest(bool is_first_fetch) {
   DCHECK(!manifest_fetcher_);
-  manifest_fetcher_ =
-      new URLFetcher(manifest_url_,
-                     is_first_fetch ? URLFetcher::MANIFEST_FETCH
-                                    : URLFetcher::MANIFEST_REFETCH,
-                     this, kAppCacheFetchBufferSize);
+  manifest_fetcher_ = std::make_unique<URLFetcher>(
+      manifest_url_,
+      is_first_fetch ? URLFetcher::FetchType::kManifest
+                     : URLFetcher::FetchType::kManifestRefetch,
+      this, kAppCacheFetchBufferSize);
 
   if (is_first_fetch) {
     // Maybe load the cached headers to make a condiditional request.
@@ -423,14 +422,13 @@
   manifest_fetcher_->Start();
 }
 
-void AppCacheUpdateJob::HandleManifestFetchCompleted(URLFetcher* fetcher,
+void AppCacheUpdateJob::HandleManifestFetchCompleted(URLFetcher* url_fetcher,
                                                      int net_error) {
   DCHECK_EQ(internal_state_, FETCH_MANIFEST);
-  DCHECK_EQ(manifest_fetcher_, fetcher);
+  DCHECK_EQ(manifest_fetcher_.get(), url_fetcher);
+  std::unique_ptr<URLFetcher> manifest_fetcher = std::move(manifest_fetcher_);
 
-  manifest_fetcher_ = nullptr;
-
-  UpdateURLLoaderRequest* request = fetcher->request();
+  UpdateURLLoaderRequest* request = manifest_fetcher->request();
   int response_code = -1;
   bool is_valid_response_code = false;
   if (net_error == net::OK) {
@@ -442,7 +440,7 @@
   }
 
   if (is_valid_response_code) {
-    manifest_data_ = fetcher->manifest_data();
+    manifest_data_ = manifest_fetcher->manifest_data();
     manifest_response_info_ =
         std::make_unique<net::HttpResponseInfo>(request->GetResponseInfo());
     if (update_type_ == UPGRADE_ATTEMPT)
@@ -456,13 +454,14 @@
     storage_->MakeGroupObsolete(group_, this, response_code);  // async
   } else {
     const char kFormatString[] = "Manifest fetch failed (%d) %s";
-    std::string message = FormatUrlErrorMessage(
-        kFormatString, manifest_url_, fetcher->result(), response_code);
+    std::string message =
+        FormatUrlErrorMessage(kFormatString, manifest_url_,
+                              manifest_fetcher->result(), response_code);
     HandleCacheFailure(
         blink::mojom::AppCacheErrorDetails(
             message, blink::mojom::AppCacheErrorReason::APPCACHE_MANIFEST_ERROR,
             manifest_url_, response_code, false /*is_cross_origin*/),
-        fetcher->result(), GURL());
+        manifest_fetcher->result(), GURL());
   }
 }
 
@@ -534,7 +533,7 @@
 
   // Associate all pending master hosts with the newly created cache.
   for (const auto& pair : pending_master_entries_) {
-    const PendingHosts& hosts = pair.second;
+    const std::vector<AppCacheHost*>& hosts = pair.second;
     for (AppCacheHost* host : hosts) {
       host->AssociateIncompleteCache(inprogress_cache_.get(), manifest_url_);
     }
@@ -563,27 +562,37 @@
   MaybeCompleteUpdate();  // if not done, continues when async fetches complete
 }
 
-void AppCacheUpdateJob::HandleUrlFetchCompleted(URLFetcher* fetcher,
-                                                int net_error) {
+void AppCacheUpdateJob::HandleResourceFetchCompleted(URLFetcher* url_fetcher,
+                                                     int net_error) {
   DCHECK(internal_state_ == DOWNLOADING);
 
-  UpdateURLLoaderRequest* request = fetcher->request();
+  UpdateURLLoaderRequest* request = url_fetcher->request();
   const GURL& url = request->GetURL();
-  pending_url_fetches_.erase(url);
+
+  auto it = pending_url_fetches_.find(url);
+  if (it == pending_url_fetches_.end()) {
+    NOTREACHED() << "Entry URL not found in pending_url_fetches_";
+    return;
+  }
+  DCHECK_EQ(it->second.get(), url_fetcher);
+  std::unique_ptr<URLFetcher> entry_fetcher = std::move(it->second);
+  pending_url_fetches_.erase(it);
+
   NotifyAllProgress(url);
   ++url_fetches_completed_;
 
-  int response_code = net_error == net::OK ? request->GetResponseCode()
-                                           : fetcher->redirect_response_code();
+  int response_code = net_error == net::OK
+                          ? request->GetResponseCode()
+                          : entry_fetcher->redirect_response_code();
 
   AppCacheEntry& entry = url_file_list_.find(url)->second;
 
   if (response_code / 100 == 2) {
     // Associate storage with the new entry.
-    DCHECK(fetcher->response_writer());
-    entry.set_response_id(fetcher->response_writer()->response_id());
+    DCHECK(entry_fetcher->response_writer());
+    entry.set_response_id(entry_fetcher->response_writer()->response_id());
     entry.SetResponseAndPaddingSizes(
-        fetcher->response_writer()->amount_written(),
+        entry_fetcher->response_writer()->amount_written(),
         ComputeAppCacheResponsePadding(url, manifest_url_));
     if (!inprogress_cache_->AddOrModifyEntry(url, entry))
       duplicate_response_ids_.push_back(entry.response_id());
@@ -602,18 +611,19 @@
     VLOG(1) << "Request error: " << net_error
             << " response code: " << response_code;
     if (entry.IsExplicit() || entry.IsFallback() || entry.IsIntercept()) {
-      if (response_code == 304 && fetcher->existing_entry().has_response_id()) {
+      if (response_code == 304 &&
+          entry_fetcher->existing_entry().has_response_id()) {
         // Keep the existing response.
-        entry.set_response_id(fetcher->existing_entry().response_id());
+        entry.set_response_id(entry_fetcher->existing_entry().response_id());
         entry.SetResponseAndPaddingSizes(
-            fetcher->existing_entry().response_size(),
-            fetcher->existing_entry().padding_size());
+            entry_fetcher->existing_entry().response_size(),
+            entry_fetcher->existing_entry().padding_size());
         inprogress_cache_->AddOrModifyEntry(url, entry);
       } else {
         const char kFormatString[] = "Resource fetch failed (%d) %s";
         std::string message = FormatUrlErrorMessage(
-            kFormatString, url, fetcher->result(), response_code);
-        ResultType result = fetcher->result();
+            kFormatString, url, entry_fetcher->result(), response_code);
+        ResultType result = entry_fetcher->result();
         bool is_cross_origin = url.GetOrigin() != manifest_url_.GetOrigin();
         switch (result) {
           case DISKCACHE_ERROR:
@@ -646,15 +656,15 @@
     } else if (response_code == 404 || response_code == 410) {
       // Entry is skipped.  They are dropped from the cache.
     } else if (update_type_ == UPGRADE_ATTEMPT &&
-               fetcher->existing_entry().has_response_id()) {
+               entry_fetcher->existing_entry().has_response_id()) {
       // Keep the existing response.
       // TODO(michaeln): Not sure this is a good idea. This is spec compliant
       // but the old resource may or may not be compatible with the new contents
       // of the cache. Impossible to know one way or the other.
-      entry.set_response_id(fetcher->existing_entry().response_id());
+      entry.set_response_id(entry_fetcher->existing_entry().response_id());
       entry.SetResponseAndPaddingSizes(
-          fetcher->existing_entry().response_size(),
-          fetcher->existing_entry().padding_size());
+          entry_fetcher->existing_entry().response_size(),
+          entry_fetcher->existing_entry().padding_size());
       inprogress_cache_->AddOrModifyEntry(url, entry);
     }
   }
@@ -665,8 +675,9 @@
   MaybeCompleteUpdate();
 }
 
-void AppCacheUpdateJob::HandleMasterEntryFetchCompleted(URLFetcher* fetcher,
-                                                        int net_error) {
+void AppCacheUpdateJob::HandleNewMasterEntryFetchCompleted(
+    URLFetcher* url_fetcher,
+    int net_error) {
   DCHECK(internal_state_ == NO_UPDATE || internal_state_ == DOWNLOADING);
 
   // TODO(jennb): Handle downloads completing during cache failure when update
@@ -674,28 +685,37 @@
   // master entry fetches when entering cache failure state so this will never
   // be called in CACHE_FAILURE state.
 
-  UpdateURLLoaderRequest* request = fetcher->request();
+  UpdateURLLoaderRequest* request = url_fetcher->request();
   const GURL& url = request->GetURL();
-  master_entry_fetches_.erase(url);
+
+  auto it = master_entry_fetches_.find(url);
+  if (it == master_entry_fetches_.end()) {
+    NOTREACHED() << "Entry URL not found in master_entry_fetches_";
+    return;
+  }
+  DCHECK_EQ(it->second.get(), url_fetcher);
+  std::unique_ptr<URLFetcher> entry_fetcher = std::move(it->second);
+  master_entry_fetches_.erase(it);
+
   ++master_entries_completed_;
 
   int response_code = net_error == net::OK ? request->GetResponseCode() : -1;
 
   auto found = pending_master_entries_.find(url);
   DCHECK(found != pending_master_entries_.end());
-  PendingHosts& hosts = found->second;
+  std::vector<AppCacheHost*>& hosts = found->second;
 
   // Section 6.9.4. No update case: step 7.3, else step 22.
   if (response_code / 100 == 2) {
     // Add fetched master entry to the appropriate cache.
     AppCache* cache = inprogress_cache_.get() ? inprogress_cache_.get()
                                               : group_->newest_complete_cache();
-    DCHECK(fetcher->response_writer());
+    DCHECK(entry_fetcher->response_writer());
     // Master entries cannot be cross-origin by definition, so they do not
     // require padding.
     AppCacheEntry master_entry(
-        AppCacheEntry::MASTER, fetcher->response_writer()->response_id(),
-        fetcher->response_writer()->amount_written(), /*padding_size=*/0);
+        AppCacheEntry::MASTER, entry_fetcher->response_writer()->response_id(),
+        entry_fetcher->response_writer()->amount_written(), /*padding_size=*/0);
     if (cache->AddOrModifyEntry(url, master_entry))
       added_master_entries_.push_back(url);
     else
@@ -724,8 +744,9 @@
     failed_master_entries_.insert(url);
 
     const char kFormatString[] = "Manifest fetch failed (%d) %s";
-    std::string message = FormatUrlErrorMessage(
-        kFormatString, request->GetURL(), fetcher->result(), response_code);
+    std::string message =
+        FormatUrlErrorMessage(kFormatString, request->GetURL(),
+                              entry_fetcher->result(), response_code);
     host_notifier.SendErrorNotifications(blink::mojom::AppCacheErrorDetails(
         message, blink::mojom::AppCacheErrorReason::APPCACHE_MANIFEST_ERROR,
         request->GetURL(), response_code, false /*is_cross_origin*/));
@@ -744,7 +765,7 @@
                 message,
                 blink::mojom::AppCacheErrorReason::APPCACHE_MANIFEST_ERROR,
                 request->GetURL(), response_code, false /*is_cross_origin*/),
-            fetcher->result(), GURL());
+            entry_fetcher->result(), GURL());
         return;
       }
     }
@@ -755,15 +776,17 @@
   MaybeCompleteUpdate();
 }
 
-void AppCacheUpdateJob::HandleManifestRefetchCompleted(URLFetcher* fetcher,
+void AppCacheUpdateJob::HandleManifestRefetchCompleted(URLFetcher* url_fetcher,
                                                        int net_error) {
-  DCHECK(internal_state_ == REFETCH_MANIFEST);
-  DCHECK(manifest_fetcher_ == fetcher);
-  manifest_fetcher_ = nullptr;
+  DCHECK_EQ(internal_state_, REFETCH_MANIFEST);
+  DCHECK_EQ(manifest_fetcher_.get(), url_fetcher);
+  std::unique_ptr<URLFetcher> manifest_fetcher = std::move(manifest_fetcher_);
 
-  int response_code =
-      net_error == net::OK ? fetcher->request()->GetResponseCode() : -1;
-  if (response_code == 304 || manifest_data_ == fetcher->manifest_data()) {
+  int response_code = net_error == net::OK
+                          ? manifest_fetcher->request()->GetResponseCode()
+                          : -1;
+  if (response_code == 304 ||
+      manifest_data_ == manifest_fetcher->manifest_data()) {
     // Only need to store response in storage if manifest is not already
     // an entry in the cache.
     AppCacheEntry* entry = nullptr;
@@ -795,9 +818,10 @@
           MANIFEST_ERROR, GURL());
     } else {
       const char kFormatString[] = "Manifest re-fetch failed (%d) %s";
-      std::string message = FormatUrlErrorMessage(
-          kFormatString, manifest_url_, fetcher->result(), response_code);
-      ResultType result = fetcher->result();
+      std::string message =
+          FormatUrlErrorMessage(kFormatString, manifest_url_,
+                                manifest_fetcher->result(), response_code);
+      ResultType result = manifest_fetcher->result();
       if (result == UPDATE_OK) {
         // URLFetcher considers any 2xx response a success, however in this
         // particular case we want to treat any non 200 responses as failures.
@@ -962,7 +986,7 @@
   // The host is about to be deleted; remove from our collection.
   auto found = pending_master_entries_.find(host->pending_master_entry_url());
   CHECK(found != pending_master_entries_.end());
-  PendingHosts& hosts = found->second;
+  std::vector<AppCacheHost*>& hosts = found->second;
   auto it = std::find(hosts.begin(), hosts.end(), host);
   CHECK(it != hosts.end());
   hosts.erase(it);
@@ -1047,13 +1071,14 @@
 }
 
 void AppCacheUpdateJob::AddUrlToFileList(const GURL& url, int type) {
-  std::pair<AppCache::EntryMap::iterator, bool> ret = url_file_list_.insert(
-      AppCache::EntryMap::value_type(url, AppCacheEntry(type)));
+  auto emplace_result = url_file_list_.emplace(url, AppCacheEntry(type));
 
-  if (ret.second)
-    urls_to_fetch_.push_back(UrlToFetch(url, false, nullptr));
-  else
-    ret.first->second.add_types(type);  // URL already exists. Merge types.
+  if (emplace_result.second) {
+    urls_to_fetch_.emplace_back(url, false, nullptr);
+  } else {
+    // URL already exists. Merge types.
+    emplace_result.first->second.add_types(type);
+  }
 }
 
 void AppCacheUpdateJob::FetchUrls() {
@@ -1080,9 +1105,9 @@
                MaybeLoadFromNewestCache(url_to_fetch.url, entry)) {
       // Continues asynchronously after data is loaded from newest cache.
     } else {
-      URLFetcher* fetcher =
-          new URLFetcher(url_to_fetch.url, URLFetcher::URL_FETCH, this,
-                         kAppCacheFetchBufferSize);
+      auto fetcher = std::make_unique<URLFetcher>(
+          url_to_fetch.url, URLFetcher::FetchType::kResource, this,
+          kAppCacheFetchBufferSize);
       if (url_to_fetch.existing_response_info.get() &&
           group_->newest_complete_cache()) {
         AppCacheEntry* existing_entry =
@@ -1096,17 +1121,13 @@
         fetcher->set_existing_entry(*existing_entry);
       }
       fetcher->Start();
-      pending_url_fetches_.insert(
-          PendingUrlFetches::value_type(url_to_fetch.url, fetcher));
+      pending_url_fetches_.emplace(url_to_fetch.url, std::move(fetcher));
     }
   }
 }
 
 void AppCacheUpdateJob::CancelAllUrlFetches() {
   // Cancel any pending URL requests.
-  for (auto& pair : pending_url_fetches_)
-    delete pair.second;
-
   url_fetches_completed_ +=
       pending_url_fetches_.size() + urls_to_fetch_.size();
   pending_url_fetches_.clear();
@@ -1195,15 +1216,16 @@
         AppCache* cache = group_->newest_complete_cache();
         auto found = pending_master_entries_.find(url);
         DCHECK(found != pending_master_entries_.end());
-        PendingHosts& hosts = found->second;
+        std::vector<AppCacheHost*>& hosts = found->second;
         for (AppCacheHost* host : hosts)
           host->AssociateCompleteCache(cache);
       }
     } else {
-      URLFetcher* fetcher = new URLFetcher(url, URLFetcher::MASTER_ENTRY_FETCH,
-                                           this, kAppCacheFetchBufferSize);
+      auto fetcher = std::make_unique<URLFetcher>(
+          url, URLFetcher::FetchType::kNewMasterEntry, this,
+          kAppCacheFetchBufferSize);
       fetcher->Start();
-      master_entry_fetches_.insert(PendingUrlFetches::value_type(url, fetcher));
+      master_entry_fetches_.emplace(url, std::move(fetcher));
     }
 
     master_entries_to_fetch_.erase(master_entries_to_fetch_.begin());
@@ -1219,8 +1241,8 @@
 
   // Cancel all in-progress fetches.
   for (auto& pair : master_entry_fetches_) {
-    delete pair.second;
-    master_entries_to_fetch_.insert(pair.first);  // back in unfetched list
+    // Move URLs back to the unfetched list.
+    master_entries_to_fetch_.emplace(std::move(pair.first));
   }
   master_entry_fetches_.clear();
 
@@ -1234,7 +1256,7 @@
     const GURL& url = *master_entries_to_fetch_.begin();
     auto found = pending_master_entries_.find(url);
     DCHECK(found != pending_master_entries_.end());
-    PendingHosts& hosts = found->second;
+    std::vector<AppCacheHost*>& hosts = found->second;
     for (AppCacheHost* host : hosts) {
       host->AssociateNoCache(GURL());
       host_notifier.AddHost(host);
@@ -1258,8 +1280,7 @@
     return false;
 
   // Load HTTP headers for entry from newest cache.
-  loading_responses_.insert(
-      LoadingResponses::value_type(copy_me->response_id(), url));
+  loading_responses_.emplace(copy_me->response_id(), url);
   storage_->LoadResponseInfo(manifest_url_, copy_me->response_id(), this);
   // Async: wait for OnResponseInfoLoaded to complete.
   return true;
@@ -1400,17 +1421,8 @@
 void AppCacheUpdateJob::Cancel() {
   internal_state_ = CANCELLED;
 
-  if (manifest_fetcher_) {
-    delete manifest_fetcher_;
-    manifest_fetcher_ = nullptr;
-  }
-
-  for (auto& pair : pending_url_fetches_)
-    delete pair.second;
+  manifest_fetcher_.reset();
   pending_url_fetches_.clear();
-
-  for (auto& pair : master_entry_fetches_)
-    delete pair.second;
   master_entry_fetches_.clear();
 
   ClearPendingMasterEntries();
@@ -1425,7 +1437,7 @@
 
 void AppCacheUpdateJob::ClearPendingMasterEntries() {
   for (auto& pair : pending_master_entries_) {
-    PendingHosts& hosts = pair.second;
+    std::vector<AppCacheHost*>& hosts = pair.second;
     for (AppCacheHost* host : hosts)
       host->RemoveObserver(this);
   }
diff --git a/content/browser/appcache/appcache_update_job.h b/content/browser/appcache/appcache_update_job.h
index 082965d..555af60 100644
--- a/content/browser/appcache/appcache_update_job.h
+++ b/content/browser/appcache/appcache_update_job.h
@@ -71,13 +71,6 @@
   class UpdateURLLoaderRequest;
   class UpdateURLRequest;
 
-  // Master entries have multiple hosts, for example, the same page is opened
-  // in different tabs.
-  using PendingHosts = std::vector<AppCacheHost*>;
-  using PendingMasters = std::map<GURL, PendingHosts>;
-  using PendingUrlFetches = std::map<GURL, URLFetcher*>;
-  using LoadingResponses = std::map<int64_t, GURL>;
-
   static const int kRerunDelayMs = 1000;
 
   // TODO(michaeln): Rework the set of states vs update types vs stored states.
@@ -114,7 +107,12 @@
     ~UrlToFetch();
 
     GURL url;
+
+    // If true, we attempted fetching the URL from storage. The fetch failed,
+    // because this instance indicates the URL still needs to be fetched.
     bool storage_checked;
+    // Cached entry with a matching URL. The entry is expired or uncacheable,
+    // but it can serve as the basis for a conditional HTTP request.
     scoped_refptr<AppCacheResponseInfo> existing_response_info;
   };
 
@@ -143,13 +141,14 @@
                           const GURL& failed_resource_url);
 
   void FetchManifest(bool is_first_fetch);
-  void HandleManifestFetchCompleted(URLFetcher* fetcher, int net_error);
+  void HandleManifestFetchCompleted(URLFetcher* url_fetcher, int net_error);
   void ContinueHandleManifestFetchCompleted(bool changed);
 
-  void HandleUrlFetchCompleted(URLFetcher* fetcher, int net_error);
-  void HandleMasterEntryFetchCompleted(URLFetcher* fetcher, int net_error);
+  void HandleResourceFetchCompleted(URLFetcher* url_fetcher, int net_error);
+  void HandleNewMasterEntryFetchCompleted(URLFetcher* url_fetcher,
+                                          int net_error);
 
-  void HandleManifestRefetchCompleted(URLFetcher* fetcher, int net_error);
+  void HandleManifestRefetchCompleted(URLFetcher* url_fetcher, int net_error);
   void OnManifestInfoWriteComplete(int result);
   void OnManifestDataWriteComplete(int result);
 
@@ -238,7 +237,10 @@
   base::Time last_progress_time_;
   bool doing_full_update_check_;
 
-  PendingMasters pending_master_entries_;
+  // Master entries have multiple hosts, for example, the same page is opened
+  // in different tabs.
+  std::map<GURL, std::vector<AppCacheHost*>> pending_master_entries_;
+
   size_t master_entries_completed_;
   std::set<GURL> failed_master_entries_;
 
@@ -248,24 +250,24 @@
   // are listed in the manifest may be fetched as a regular URL instead of
   // as a separate master entry fetch to optimize against duplicate fetches.
   std::set<GURL> master_entries_to_fetch_;
-  PendingUrlFetches master_entry_fetches_;
+  std::map<GURL, std::unique_ptr<URLFetcher>> master_entry_fetches_;
 
   // URLs of files to fetch along with their flags.
-  AppCache::EntryMap url_file_list_;
+  std::map<GURL, AppCacheEntry> url_file_list_;
   size_t url_fetches_completed_;
 
-  // Helper container to track which urls have not been fetched yet. URLs are
-  // removed when the fetch is initiated. Flag indicates whether an attempt
-  // to load the URL from storage has already been tried and failed.
+  // URLs that have not been fetched yet.
+  //
+  // URLs are removed from this set right as they are about to be fetched.
   base::circular_deque<UrlToFetch> urls_to_fetch_;
 
   // Helper container to track which urls are being loaded from response
   // storage.
-  LoadingResponses loading_responses_;
+  std::map<int64_t, GURL> loading_responses_;
 
   // Keep track of pending URL requests so we can cancel them if necessary.
-  URLFetcher* manifest_fetcher_;
-  PendingUrlFetches pending_url_fetches_;
+  std::unique_ptr<URLFetcher> manifest_fetcher_;
+  std::map<GURL, std::unique_ptr<URLFetcher>> pending_url_fetches_;
 
   // Temporary storage of manifest response data for parsing and comparison.
   std::string manifest_data_;
diff --git a/content/browser/appcache/appcache_update_url_fetcher.cc b/content/browser/appcache/appcache_update_url_fetcher.cc
index 59af1a1..d246f58 100644
--- a/content/browser/appcache/appcache_update_url_fetcher.cc
+++ b/content/browser/appcache/appcache_update_url_fetcher.cc
@@ -19,13 +19,10 @@
 
 namespace {
 
-const int kMax503Retries = 3;
+const int kMaxRetryCount = 3;
 
 }  // namespace
 
-// Helper class to fetch resources. Depending on the fetch type,
-// can either fetch to an in-memory string or write the response
-// data out to the disk cache.
 AppCacheUpdateJob::URLFetcher::URLFetcher(const GURL& url,
                                           FetchType fetch_type,
                                           AppCacheUpdateJob* job,
@@ -33,25 +30,25 @@
     : url_(url),
       job_(job),
       fetch_type_(fetch_type),
-      retry_503_attempts_(0),
+      buffer_size_(buffer_size),
       request_(std::make_unique<UpdateURLLoaderRequest>(
           job->service_->url_loader_factory_getter(),
           url,
           buffer_size,
-          this)),
-      result_(AppCacheUpdateJob::UPDATE_OK),
-      redirect_response_code_(-1),
-      buffer_size_(buffer_size) {}
+          this)) {
+  DCHECK(job != nullptr);
+}
 
-AppCacheUpdateJob::URLFetcher::~URLFetcher() {}
+AppCacheUpdateJob::URLFetcher::~URLFetcher() = default;
 
 void AppCacheUpdateJob::URLFetcher::Start() {
   request_->SetSiteForCookies(job_->manifest_url_);
   request_->SetInitiator(url::Origin::Create(job_->manifest_url_));
-  if (fetch_type_ == MANIFEST_FETCH && job_->doing_full_update_check_)
+  if (fetch_type_ == FetchType::kManifest && job_->doing_full_update_check_) {
     request_->SetLoadFlags(request_->GetLoadFlags() | net::LOAD_BYPASS_CACHE);
-  else if (existing_response_headers_.get())
+  } else if (existing_response_headers_.get()) {
     AddConditionalHeaders(existing_response_headers_.get());
+  }
   request_->Start();
 }
 
@@ -109,20 +106,23 @@
     }
   }
 
-  // Write response info to storage for URL fetches. Wait for async write
-  // completion before reading any response data.
-  if (fetch_type_ == URL_FETCH || fetch_type_ == MASTER_ENTRY_FETCH) {
-    response_writer_ = job_->CreateResponseWriter();
-    scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
-        base::MakeRefCounted<HttpResponseInfoIOBuffer>(
-            std::make_unique<net::HttpResponseInfo>(
-                request_->GetResponseInfo()));
-    response_writer_->WriteInfo(
-        io_buffer.get(),
-        base::BindOnce(&URLFetcher::OnWriteComplete, base::Unretained(this)));
-  } else {
+  if (fetch_type_ == FetchType::kManifest ||
+      fetch_type_ == FetchType::kManifestRefetch) {
     ReadResponseData();
+    return;
   }
+
+  // Write response info to storage for non-manifest fetches. Wait for async
+  // write completion before reading any response data.
+  DCHECK(fetch_type_ == FetchType::kResource ||
+         fetch_type_ == FetchType::kNewMasterEntry);
+  response_writer_ = job_->CreateResponseWriter();
+  scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
+      base::MakeRefCounted<HttpResponseInfoIOBuffer>(
+          std::make_unique<net::HttpResponseInfo>(request_->GetResponseInfo()));
+  response_writer_->WriteInfo(
+      io_buffer.get(),
+      base::BindOnce(&URLFetcher::OnWriteComplete, base::Unretained(this)));
 }
 
 void AppCacheUpdateJob::URLFetcher::OnReadCompleted(net::IOBuffer* buffer,
@@ -192,22 +192,21 @@
 bool AppCacheUpdateJob::URLFetcher::ConsumeResponseData(net::IOBuffer* buffer,
                                                         int bytes_read) {
   DCHECK_GT(bytes_read, 0);
-  switch (fetch_type_) {
-    case MANIFEST_FETCH:
-    case MANIFEST_REFETCH:
-      manifest_data_.append(buffer->data(), bytes_read);
-      break;
-    case URL_FETCH:
-    case MASTER_ENTRY_FETCH:
-      DCHECK(response_writer_.get());
-      response_writer_->WriteData(
-          buffer, bytes_read,
-          base::BindOnce(&URLFetcher::OnWriteComplete, base::Unretained(this)));
-      return false;  // wait for async write completion to continue reading
-    default:
-      NOTREACHED();
+
+  if (fetch_type_ == FetchType::kManifest ||
+      fetch_type_ == FetchType::kManifestRefetch) {
+    manifest_data_.append(buffer->data(), bytes_read);
+    return true;
   }
-  return true;
+
+  DCHECK(fetch_type_ == FetchType::kResource ||
+         fetch_type_ == FetchType::kNewMasterEntry);
+
+  DCHECK(response_writer_.get());
+  response_writer_->WriteData(
+      buffer, bytes_read,
+      base::BindOnce(&URLFetcher::OnWriteComplete, base::Unretained(this)));
+  return false;  // wait for async write completion to continue reading
 }
 
 void AppCacheUpdateJob::URLFetcher::OnResponseCompleted(int net_error) {
@@ -224,31 +223,30 @@
   }
 
   switch (fetch_type_) {
-    case MANIFEST_FETCH:
+    case FetchType::kResource:
+      job_->HandleResourceFetchCompleted(this, net_error);
+      break;
+    case FetchType::kNewMasterEntry:
+      job_->HandleNewMasterEntryFetchCompleted(this, net_error);
+      break;
+    case FetchType::kManifest:
       job_->HandleManifestFetchCompleted(this, net_error);
       break;
-    case URL_FETCH:
-      job_->HandleUrlFetchCompleted(this, net_error);
-      break;
-    case MASTER_ENTRY_FETCH:
-      job_->HandleMasterEntryFetchCompleted(this, net_error);
-      break;
-    case MANIFEST_REFETCH:
+    case FetchType::kManifestRefetch:
       job_->HandleManifestRefetchCompleted(this, net_error);
       break;
     default:
       NOTREACHED();
   }
-
-  delete this;
 }
 
 bool AppCacheUpdateJob::URLFetcher::MaybeRetryRequest() {
-  if (retry_503_attempts_ >= kMax503Retries ||
+  if (retry_count_ >= kMaxRetryCount ||
       !request_->GetResponseHeaders()->HasHeaderValue("retry-after", "0")) {
     return false;
   }
-  ++retry_503_attempts_;
+  ++retry_count_;
+
   result_ = AppCacheUpdateJob::UPDATE_OK;
   request_ = std::make_unique<UpdateURLLoaderRequest>(
       job_->service_->url_loader_factory_getter(), url_, buffer_size_, this);
diff --git a/content/browser/appcache/appcache_update_url_fetcher.h b/content/browser/appcache/appcache_update_url_fetcher.h
index 3368e36..09487326 100644
--- a/content/browser/appcache/appcache_update_url_fetcher.h
+++ b/content/browser/appcache/appcache_update_url_fetcher.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include "base/logging.h"
 #include "content/browser/appcache/appcache_response.h"
 #include "content/browser/appcache/appcache_update_job.h"
 #include "net/base/io_buffer.h"
@@ -15,36 +16,60 @@
 
 namespace content {
 
-// Helper class to fetch resources. Depending on the fetch type,
-// can either fetch to an in-memory string or write the response
-// data out to the disk cache.
+// Fetches a manifest or a referenced resource.
+//
+// The manifest is fetched into an in-memory string, and can be read using
+// manifest_data(). Other resources are stored in net::disk_cache entries.
 class AppCacheUpdateJob::URLFetcher {
  public:
-  enum FetchType {
-    MANIFEST_FETCH,
-    URL_FETCH,
-    MASTER_ENTRY_FETCH,
-    MANIFEST_REFETCH,
+  enum class FetchType {
+    // Fetching an URL that is explicitly called out in the manifest. When
+    // updating a manifest, this type is also used for HTML pages (master
+    // entries) that have already been found to point to the manifest.
+    kResource,
+    // Fetching a HTML page pointing to a manifest that is already cached. The
+    // page will be added as a master entry to the existing cache.
+    kNewMasterEntry,
+    kManifest,
+    kManifestRefetch,
   };
+
+  // The caller must ensure that |job| outlives this instance.
   URLFetcher(const GURL& url,
              FetchType fetch_type,
              AppCacheUpdateJob* job,
              int buffer_size);
   ~URLFetcher();
+
   void Start();
+
   FetchType fetch_type() const { return fetch_type_; }
-  UpdateURLLoaderRequest* request() const { return request_.get(); }
+
   const AppCacheEntry& existing_entry() const { return existing_entry_; }
-  const std::string& manifest_data() const { return manifest_data_; }
-  AppCacheResponseWriter* response_writer() const {
-    return response_writer_.get();
-  }
-  void set_existing_response_headers(net::HttpResponseHeaders* headers) {
-    existing_response_headers_ = headers;
-  }
   void set_existing_entry(const AppCacheEntry& entry) {
     existing_entry_ = entry;
   }
+  void set_existing_response_headers(
+      scoped_refptr<net::HttpResponseHeaders> headers) {
+    existing_response_headers_ = std::move(headers);
+  }
+
+  UpdateURLLoaderRequest* request() const { return request_.get(); }
+
+  // Only valid when fetching a manifest.
+  const std::string& manifest_data() const {
+    DCHECK(fetch_type_ == FetchType::kManifest ||
+           fetch_type_ == FetchType::kManifestRefetch);
+    return manifest_data_;
+  }
+
+  // Only valid when fetching a resource or a new master entry.
+  AppCacheResponseWriter* response_writer() const {
+    DCHECK(fetch_type_ == FetchType::kResource ||
+           fetch_type_ == FetchType::kNewMasterEntry);
+    return response_writer_.get();
+  }
+
   AppCacheUpdateJob::ResultType result() const { return result_; }
   int redirect_response_code() const { return redirect_response_code_; }
 
@@ -62,18 +87,30 @@
 
   friend class UpdateURLLoaderRequest;
 
-  GURL url_;
-  AppCacheUpdateJob* job_;
-  FetchType fetch_type_;
-  int retry_503_attempts_;
-  std::unique_ptr<UpdateURLLoaderRequest> request_;
+  const GURL url_;
+  AppCacheUpdateJob* const job_;
+  const FetchType fetch_type_;
+  const int buffer_size_;
+
   AppCacheEntry existing_entry_;
   scoped_refptr<net::HttpResponseHeaders> existing_response_headers_;
-  std::string manifest_data_;
-  AppCacheUpdateJob::ResultType result_;
-  int redirect_response_code_;
+
   std::unique_ptr<AppCacheResponseWriter> response_writer_;
-  int buffer_size_;
+  AppCacheUpdateJob::ResultType result_ = AppCacheUpdateJob::UPDATE_OK;
+
+  // Populated after successfully fetching a manifest.
+  std::string manifest_data_;
+
+  // Never null. Only modified when the fetch is retried.
+  std::unique_ptr<UpdateURLLoaderRequest> request_;
+
+  // Number of times the fetch has been retried.
+  //
+  // When receiving a 503 response, we re-attempt fetching the resource for a
+  // few times.
+  int retry_count_ = 0;
+
+  int redirect_response_code_ = -1;
 };  // class URLFetcher
 
 }  // namespace content.
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.h b/content/browser/bluetooth/web_bluetooth_service_impl.h
index 4107585..5291874 100644
--- a/content/browser/bluetooth/web_bluetooth_service_impl.h
+++ b/content/browser/bluetooth/web_bluetooth_service_impl.h
@@ -82,6 +82,9 @@
       BluetoothDeviceScanningPromptController* prompt_controller);
 
  private:
+  FRIEND_TEST_ALL_PREFIXES(WebBluetoothServiceImplTest, PermissionAllowed);
+  FRIEND_TEST_ALL_PREFIXES(WebBluetoothServiceImplTest,
+                           PermissionPromptCanceled);
   FRIEND_TEST_ALL_PREFIXES(WebBluetoothServiceImplTest,
                            BluetoothScanningPermissionRevokedWhenTabHidden);
   FRIEND_TEST_ALL_PREFIXES(WebBluetoothServiceImplTest,
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl_unittest.cc b/content/browser/bluetooth/web_bluetooth_service_impl_unittest.cc
index c968fc7c..cafe63f 100644
--- a/content/browser/bluetooth/web_bluetooth_service_impl_unittest.cc
+++ b/content/browser/bluetooth/web_bluetooth_service_impl_unittest.cc
@@ -24,11 +24,9 @@
 
 class FakeBluetoothScanningPrompt : public BluetoothScanningPrompt {
  public:
-  FakeBluetoothScanningPrompt(const EventHandler& event_handler, bool allow) {
-    if (allow)
-      event_handler.Run(content::BluetoothScanningPrompt::Event::kAllow);
-    else
-      event_handler.Run(content::BluetoothScanningPrompt::Event::kBlock);
+  FakeBluetoothScanningPrompt(const EventHandler& event_handler,
+                              content::BluetoothScanningPrompt::Event event) {
+    event_handler.Run(event);
   }
 
   ~FakeBluetoothScanningPrompt() override = default;
@@ -65,13 +63,16 @@
   std::unique_ptr<BluetoothScanningPrompt> ShowBluetoothScanningPrompt(
       RenderFrameHost* frame,
       const BluetoothScanningPrompt::EventHandler& event_handler) override {
-    return std::make_unique<FakeBluetoothScanningPrompt>(event_handler, allow_);
+    return std::make_unique<FakeBluetoothScanningPrompt>(event_handler, event_);
   }
 
-  void set_allow(bool allow) { allow_ = allow; }
+  void set_event(content::BluetoothScanningPrompt::Event event) {
+    event_ = event;
+  }
 
  private:
-  bool allow_ = true;
+  content::BluetoothScanningPrompt::Event event_ =
+      content::BluetoothScanningPrompt::Event::kAllow;
 
   DISALLOW_COPY_AND_ASSIGN(FakeWebContentsDelegate);
 };
@@ -169,6 +170,37 @@
   DISALLOW_COPY_AND_ASSIGN(WebBluetoothServiceImplTest);
 };
 
+TEST_F(WebBluetoothServiceImplTest, PermissionAllowed) {
+  blink::mojom::WebBluetoothLeScanFilterPtr filter = CreateScanFilter("a", "b");
+  base::Optional<WebBluetoothServiceImpl::ScanFilters> filters;
+  filters.emplace();
+  filters->push_back(filter.Clone());
+  EXPECT_FALSE(service_->AreScanFiltersAllowed(filters));
+
+  FakeWebBluetoothScanClientImpl client_impl;
+  RequestScanningStart(*filter, &client_impl);
+  // |filters| should be allowed.
+  EXPECT_TRUE(service_->AreScanFiltersAllowed(filters));
+}
+
+TEST_F(WebBluetoothServiceImplTest, PermissionPromptCanceled) {
+  blink::mojom::WebBluetoothLeScanFilterPtr filter = CreateScanFilter("a", "b");
+  base::Optional<WebBluetoothServiceImpl::ScanFilters> filters;
+  filters.emplace();
+  filters->push_back(filter.Clone());
+  EXPECT_FALSE(service_->AreScanFiltersAllowed(filters));
+
+  // Set |event_| to kCanceled in the FakeWebContentsDelegate so that the call
+  // to WebBluetoothServiceImpl::RequestScanningStart() will not grant the
+  // permission.
+  delegate_.set_event(content::BluetoothScanningPrompt::Event::kCanceled);
+
+  FakeWebBluetoothScanClientImpl client_impl;
+  RequestScanningStart(*filter, &client_impl);
+  // |filters| should still not be allowed.
+  EXPECT_FALSE(service_->AreScanFiltersAllowed(filters));
+}
+
 TEST_F(WebBluetoothServiceImplTest,
        BluetoothScanningPermissionRevokedWhenTabHidden) {
   blink::mojom::WebBluetoothLeScanFilterPtr filter = CreateScanFilter("a", "b");
@@ -223,10 +255,10 @@
   EXPECT_TRUE(service_->AreScanFiltersAllowed(filters_2));
   EXPECT_FALSE(client_impl_2.on_connection_error_called());
 
-  // Set |allow_| to false in the FakeWebContentsDelegate so that the next call
+  // Set |event_| to kBlock in the FakeWebContentsDelegate so that the next call
   // to WebBluetoothServiceImpl::RequestScanningStart() will block the
   // permission.
-  delegate_.set_allow(false);
+  delegate_.set_event(content::BluetoothScanningPrompt::Event::kBlock);
 
   blink::mojom::WebBluetoothLeScanFilterPtr filter_3 =
       CreateScanFilter("e", "f");
diff --git a/content/browser/compositor/gpu_browser_compositor_output_surface.cc b/content/browser/compositor/gpu_browser_compositor_output_surface.cc
index 53ca7c36..a25b060 100644
--- a/content/browser/compositor/gpu_browser_compositor_output_surface.cc
+++ b/content/browser/compositor/gpu_browser_compositor_output_surface.cc
@@ -50,7 +50,7 @@
     client_->DidReceiveCALayerParams(params.ca_layer_params);
   if (!params.texture_in_use_responses.empty())
     client_->DidReceiveTextureInUseResponses(params.texture_in_use_responses);
-  client_->DidReceiveSwapBuffersAck();
+  client_->DidReceiveSwapBuffersAck(params.swap_response.timings);
   UpdateLatencyInfoOnSwap(params.swap_response, &latency_info);
   latency_tracker_.OnGpuSwapBuffersCompleted(latency_info);
 }
diff --git a/content/browser/compositor/offscreen_browser_compositor_output_surface.cc b/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
index 84e6d6f..0eae968 100644
--- a/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
+++ b/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
@@ -186,7 +186,9 @@
 void OffscreenBrowserCompositorOutputSurface::OnSwapBuffersComplete(
     const std::vector<ui::LatencyInfo>& latency_info) {
   latency_tracker_.OnGpuSwapBuffersCompleted(latency_info);
-  client_->DidReceiveSwapBuffersAck();
+  // Swap timings are not available since for offscreen there is no Swap, just
+  // a SignalSyncToken.
+  client_->DidReceiveSwapBuffersAck(gfx::SwapTimings());
   client_->DidReceivePresentationFeedback(gfx::PresentationFeedback());
 }
 
diff --git a/content/browser/compositor/software_browser_compositor_output_surface.cc b/content/browser/compositor/software_browser_compositor_output_surface.cc
index d48e93f..e9d4785 100644
--- a/content/browser/compositor/software_browser_compositor_output_surface.cc
+++ b/content/browser/compositor/software_browser_compositor_output_surface.cc
@@ -81,14 +81,15 @@
 
   software_device()->OnSwapBuffers(base::BindOnce(
       &SoftwareBrowserCompositorOutputSurface::SwapBuffersCallback,
-      weak_factory_.GetWeakPtr(), frame.latency_info));
+      weak_factory_.GetWeakPtr(), frame.latency_info, swap_time));
 }
 
 void SoftwareBrowserCompositorOutputSurface::SwapBuffersCallback(
     const std::vector<ui::LatencyInfo>& latency_info,
+    const base::TimeTicks& swap_time,
     const gfx::Size& pixel_size) {
   latency_tracker_.OnGpuSwapBuffersCompleted(latency_info);
-  client_->DidReceiveSwapBuffersAck();
+  client_->DidReceiveSwapBuffersAck({swap_time, swap_time});
 #if defined(USE_X11)
   if (needs_swap_size_notifications_)
     client_->DidSwapWithSize(pixel_size);
diff --git a/content/browser/compositor/software_browser_compositor_output_surface.h b/content/browser/compositor/software_browser_compositor_output_surface.h
index 9a838454..d4550f6 100644
--- a/content/browser/compositor/software_browser_compositor_output_surface.h
+++ b/content/browser/compositor/software_browser_compositor_output_surface.h
@@ -46,6 +46,7 @@
 
  private:
   void SwapBuffersCallback(const std::vector<ui::LatencyInfo>& latency_info,
+                           const base::TimeTicks& swap_time,
                            const gfx::Size& pixel_size);
   void UpdateVSyncCallback(const base::TimeTicks timebase,
                            const base::TimeDelta interval);
diff --git a/content/browser/devtools/protocol/webauthn_handler.cc b/content/browser/devtools/protocol/webauthn_handler.cc
index 71ddde2..708fdfd 100644
--- a/content/browser/devtools/protocol/webauthn_handler.cc
+++ b/content/browser/devtools/protocol/webauthn_handler.cc
@@ -129,13 +129,10 @@
 Response WebAuthnHandler::AddCredential(
     const String& authenticator_id,
     std::unique_ptr<WebAuthn::Credential> credential) {
-  if (!virtual_discovery_factory_)
-    return Response::Error(kVirtualEnvironmentNotEnabled);
-
-  auto* authenticator =
-      virtual_discovery_factory_->GetAuthenticator(authenticator_id);
-  if (!authenticator)
-    return Response::InvalidParams(kAuthenticatorNotFound);
+  VirtualAuthenticator* authenticator;
+  Response response = FindAuthenticator(authenticator_id, &authenticator);
+  if (!response.isSuccess())
+    return response;
 
   if (credential->GetRpIdHash().size() != device::kRpIdHashLength) {
     return Response::InvalidParams(
@@ -156,13 +153,10 @@
 Response WebAuthnHandler::GetCredentials(
     const String& authenticator_id,
     std::unique_ptr<Array<WebAuthn::Credential>>* out_credentials) {
-  if (!virtual_discovery_factory_)
-    return Response::Error(kVirtualEnvironmentNotEnabled);
-
-  auto* authenticator =
-      virtual_discovery_factory_->GetAuthenticator(authenticator_id);
-  if (!authenticator)
-    return Response::InvalidParams(kAuthenticatorNotFound);
+  VirtualAuthenticator* authenticator;
+  Response response = FindAuthenticator(authenticator_id, &authenticator);
+  if (!response.isSuccess())
+    return response;
 
   *out_credentials = Array<WebAuthn::Credential>::create();
   for (const auto& credential : authenticator->registrations()) {
@@ -182,15 +176,37 @@
 }
 
 Response WebAuthnHandler::ClearCredentials(const String& authenticator_id) {
+  VirtualAuthenticator* authenticator;
+  Response response = FindAuthenticator(authenticator_id, &authenticator);
+  if (!response.isSuccess())
+    return response;
+
+  authenticator->ClearRegistrations();
+  return Response::OK();
+}
+
+Response WebAuthnHandler::SetUserVerified(const String& authenticator_id,
+                                          bool is_user_verified) {
+  VirtualAuthenticator* authenticator;
+  Response response = FindAuthenticator(authenticator_id, &authenticator);
+  if (!response.isSuccess())
+    return response;
+
+  authenticator->set_user_verified(is_user_verified);
+  return Response::OK();
+}
+
+Response WebAuthnHandler::FindAuthenticator(
+    const String& id,
+    VirtualAuthenticator** out_authenticator) {
+  *out_authenticator = nullptr;
   if (!virtual_discovery_factory_)
     return Response::Error(kVirtualEnvironmentNotEnabled);
 
-  auto* authenticator =
-      virtual_discovery_factory_->GetAuthenticator(authenticator_id);
-  if (!authenticator)
+  *out_authenticator = virtual_discovery_factory_->GetAuthenticator(id);
+  if (!*out_authenticator)
     return Response::InvalidParams(kAuthenticatorNotFound);
 
-  authenticator->ClearRegistrations();
   return Response::OK();
 }
 
diff --git a/content/browser/devtools/protocol/webauthn_handler.h b/content/browser/devtools/protocol/webauthn_handler.h
index 28683ab..1985567 100644
--- a/content/browser/devtools/protocol/webauthn_handler.h
+++ b/content/browser/devtools/protocol/webauthn_handler.h
@@ -13,6 +13,7 @@
 #include "content/common/content_export.h"
 
 namespace content {
+class VirtualAuthenticator;
 class VirtualFidoDiscoveryFactory;
 namespace protocol {
 
@@ -41,8 +42,14 @@
       std::unique_ptr<protocol::Array<protocol::WebAuthn::Credential>>*
           out_credentials) override;
   Response ClearCredentials(const String& in_authenticator_id) override;
+  Response SetUserVerified(const String& authenticator_id,
+                           bool is_user_verified) override;
 
  private:
+  // Finds the authenticator with the given |id|. Returns Response::OK() if
+  // successful, an error otherwise.
+  Response FindAuthenticator(const String& id,
+                             VirtualAuthenticator** out_authenticator);
   RenderFrameHostImpl* frame_host_ = nullptr;
   VirtualFidoDiscoveryFactory* virtual_discovery_factory_ = nullptr;
   DISALLOW_COPY_AND_ASSIGN(WebAuthnHandler);
diff --git a/content/browser/devtools/protocol_config.json b/content/browser/devtools/protocol_config.json
index 814d0d5..4f57e10 100644
--- a/content/browser/devtools/protocol_config.json
+++ b/content/browser/devtools/protocol_config.json
@@ -102,7 +102,7 @@
             },
             {
                 "domain": "WebAuthn",
-                "include": ["enable", "disable", "addVirtualAuthenticator", "removeVirtualAuthenticator", "addCredential", "clearCredentials", "getCredentials"]
+                "include": ["enable", "disable", "addVirtualAuthenticator", "removeVirtualAuthenticator", "addCredential", "clearCredentials", "getCredentials", "setUserVerified"]
             }
         ]
     },
diff --git a/content/browser/display_cutout/display_cutout_browsertest.cc b/content/browser/display_cutout/display_cutout_browsertest.cc
index 0ccf0874..3a2b94a4 100644
--- a/content/browser/display_cutout/display_cutout_browsertest.cc
+++ b/content/browser/display_cutout/display_cutout_browsertest.cc
@@ -87,7 +87,7 @@
 class DisplayCutoutWebContentsDelegate : public WebContentsDelegate {
  public:
   blink::WebDisplayMode GetDisplayMode(
-      const WebContents* web_contents) const override {
+      const WebContents* web_contents) override {
     return display_mode_;
   }
 
diff --git a/content/browser/download/download_manager_impl_unittest.cc b/content/browser/download/download_manager_impl_unittest.cc
index 78f18bcc..add7114 100644
--- a/content/browser/download/download_manager_impl_unittest.cc
+++ b/content/browser/download/download_manager_impl_unittest.cc
@@ -95,7 +95,7 @@
   MOCK_METHOD5(ChooseSavePath, void(
       WebContents*, const base::FilePath&, const base::FilePath::StringType&,
       bool, const SavePackagePathPickedCallback&));
-  MOCK_CONST_METHOD0(ApplicationClientIdForFileScanning, std::string());
+  MOCK_METHOD0(ApplicationClientIdForFileScanning, std::string());
 };
 
 MockDownloadManagerDelegate::MockDownloadManagerDelegate() {}
diff --git a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
index 2d89cac..2bbbe2ef 100644
--- a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
@@ -191,7 +191,7 @@
     idb_factory_ = std::make_unique<TestIDBFactory>(idb_context_.get());
 
     leveldb::Status s;
-    std::tie(origin_state_handle_, s, std::ignore, std::ignore) =
+    std::tie(origin_state_handle_, s, std::ignore, std::ignore, std::ignore) =
         idb_factory_->GetOrOpenOriginFactory(origin, idb_context_->data_path());
     if (!origin_state_handle_.IsHeld()) {
       backing_store_ = nullptr;
diff --git a/content/browser/indexed_db/indexed_db_database.cc b/content/browser/indexed_db/indexed_db_database.cc
index d8ca38083..fcf6018 100644
--- a/content/browser/indexed_db/indexed_db_database.cc
+++ b/content/browser/indexed_db/indexed_db_database.cc
@@ -159,7 +159,9 @@
               std::unique_ptr<IndexedDBPendingConnection> pending_connection)
       : ConnectionRequest(std::move(origin_state_handle), db),
         pending_(std::move(pending_connection)),
-        weak_factory_(this) {}
+        weak_factory_(this) {
+    db_->metadata_.was_cold_open = pending_->was_cold_open;
+  }
 
   void Perform() override {
     if (db_->metadata_.id == kInvalidId) {
diff --git a/content/browser/indexed_db/indexed_db_factory_impl.cc b/content/browser/indexed_db/indexed_db_factory_impl.cc
index ef9c3bc..9e47840 100644
--- a/content/browser/indexed_db/indexed_db_factory_impl.cc
+++ b/content/browser/indexed_db/indexed_db_factory_impl.cc
@@ -106,7 +106,7 @@
   IndexedDBDatabaseError error;
   // Note: Any data loss information here is not piped up to the renderer, and
   // will be lost.
-  std::tie(origin_state_handle, s, error, std::ignore) =
+  std::tie(origin_state_handle, s, error, std::ignore, std::ignore) =
       GetOrOpenOriginFactory(origin, data_directory);
   if (!origin_state_handle.IsHeld() || !origin_state_handle.origin_state()) {
     callbacks->OnError(error);
@@ -144,7 +144,7 @@
   IndexedDBDatabaseError error;
   // Note: Any data loss information here is not piped up to the renderer, and
   // will be lost.
-  std::tie(origin_state_handle, s, error, std::ignore) =
+  std::tie(origin_state_handle, s, error, std::ignore, std::ignore) =
       GetOrOpenOriginFactory(origin, data_directory);
   if (!origin_state_handle.IsHeld() || !origin_state_handle.origin_state()) {
     callbacks->OnError(error);
@@ -182,7 +182,8 @@
   IndexedDBOriginStateHandle origin_state_handle;
   leveldb::Status s;
   IndexedDBDatabaseError error;
-  std::tie(origin_state_handle, s, error, connection->data_loss_info) =
+  std::tie(origin_state_handle, s, error, connection->data_loss_info,
+           connection->was_cold_open) =
       GetOrOpenOriginFactory(origin, data_directory);
   if (!origin_state_handle.IsHeld() || !origin_state_handle.origin_state()) {
     connection->callbacks->OnError(error);
@@ -238,7 +239,7 @@
   IndexedDBDatabaseError error;
   // Note: Any data loss information here is not piped up to the renderer, and
   // will be lost.
-  std::tie(origin_state_handle, s, error, std::ignore) =
+  std::tie(origin_state_handle, s, error, std::ignore, std::ignore) =
       GetOrOpenOriginFactory(origin, data_directory);
   if (!origin_state_handle.IsHeld() || !origin_state_handle.origin_state()) {
     callbacks->OnError(error);
@@ -535,7 +536,8 @@
 std::tuple<IndexedDBOriginStateHandle,
            leveldb::Status,
            IndexedDBDatabaseError,
-           IndexedDBDataLossInfo>
+           IndexedDBDataLossInfo,
+           bool>
 IndexedDBFactoryImpl::GetOrOpenOriginFactory(
     const Origin& origin,
     const base::FilePath& data_directory) {
@@ -543,7 +545,8 @@
   auto it = factories_per_origin_.find(origin);
   if (it != factories_per_origin_.end()) {
     return {it->second->CreateHandle(), leveldb::Status::OK(),
-            IndexedDBDatabaseError(), IndexedDBDataLossInfo()};
+            IndexedDBDatabaseError(), IndexedDBDataLossInfo(),
+            /*was_cold_open=*/false};
   }
 
   base::FilePath blob_path;
@@ -555,7 +558,7 @@
         indexed_db::CreateDatabaseDirectories(data_directory, origin);
     if (!s.ok())
       return {IndexedDBOriginStateHandle(), s, CreateDefaultError(),
-              IndexedDBDataLossInfo()};
+              IndexedDBDataLossInfo(), /*was_cold_open=*/true};
   }
   std::unique_ptr<LevelDBDatabase> database;
   IndexedDBDataLossInfo data_loss_info;
@@ -571,11 +574,11 @@
                   blink::kWebIDBDatabaseExceptionQuotaError,
                   ASCIIToUTF16("Encountered full disk while opening "
                                "backing store for indexedDB.open.")),
-              data_loss_info};
+              data_loss_info, /*was_cold_open=*/true};
 
     } else {
       return {IndexedDBOriginStateHandle(), s, CreateDefaultError(),
-              data_loss_info};
+              data_loss_info, /*was_cold_open=*/true};
     }
   }
   bool is_in_memory = data_directory.empty();
@@ -594,7 +597,7 @@
 
   if (!s.ok())
     return {IndexedDBOriginStateHandle(), s, CreateDefaultError(),
-            data_loss_info};
+            data_loss_info, /*was_cold_open=*/true};
 
   it =
       factories_per_origin_
@@ -609,7 +612,7 @@
           .first;
   context_->FactoryOpened(origin);
   return {it->second->CreateHandle(), s, IndexedDBDatabaseError(),
-          data_loss_info};
+          data_loss_info, /*was_cold_open=*/true};
 }
 
 std::unique_ptr<IndexedDBBackingStore> IndexedDBFactoryImpl::CreateBackingStore(
diff --git a/content/browser/indexed_db/indexed_db_factory_impl.h b/content/browser/indexed_db/indexed_db_factory_impl.h
index 88a4dcf..08bcac8 100644
--- a/content/browser/indexed_db/indexed_db_factory_impl.h
+++ b/content/browser/indexed_db/indexed_db_factory_impl.h
@@ -125,7 +125,8 @@
   std::tuple<IndexedDBOriginStateHandle,
              leveldb::Status,
              IndexedDBDatabaseError,
-             IndexedDBDataLossInfo>
+             IndexedDBDataLossInfo,
+             /*was_cold_open=*/bool>
   GetOrOpenOriginFactory(const url::Origin& origin,
                          const base::FilePath& data_directory);
 
diff --git a/content/browser/indexed_db/indexed_db_factory_unittest.cc b/content/browser/indexed_db/indexed_db_factory_unittest.cc
index a393243..f8de8fb 100644
--- a/content/browser/indexed_db/indexed_db_factory_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -221,11 +221,11 @@
   IndexedDBOriginStateHandle origin_state2_handle;
   leveldb::Status s;
 
-  std::tie(origin_state1_handle, s, std::ignore, std::ignore) =
+  std::tie(origin_state1_handle, s, std::ignore, std::ignore, std::ignore) =
       factory()->GetOrOpenOriginFactory(origin1, context()->data_path());
   EXPECT_TRUE(origin_state1_handle.IsHeld()) << s.ToString();
 
-  std::tie(origin_state2_handle, s, std::ignore, std::ignore) =
+  std::tie(origin_state2_handle, s, std::ignore, std::ignore, std::ignore) =
       factory()->GetOrOpenOriginFactory(origin2, context()->data_path());
   EXPECT_TRUE(origin_state2_handle.IsHeld()) << s.ToString();
 
@@ -242,7 +242,7 @@
   IndexedDBOriginStateHandle origin_state_handle;
   leveldb::Status s;
 
-  std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+  std::tie(origin_state_handle, s, std::ignore, std::ignore, std::ignore) =
       factory()->GetOrOpenOriginFactory(origin, context()->data_path());
   EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString();
   origin_state_handle.Release();
@@ -264,7 +264,7 @@
   IndexedDBOriginStateHandle origin_state_handle;
   leveldb::Status s;
 
-  std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+  std::tie(origin_state_handle, s, std::ignore, std::ignore, std::ignore) =
       factory()->GetOrOpenOriginFactory(origin, context()->data_path());
   EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString();
   origin_state_handle.Release();
@@ -284,7 +284,7 @@
   IndexedDBOriginStateHandle origin_state_handle;
   leveldb::Status s;
 
-  std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+  std::tie(origin_state_handle, s, std::ignore, std::ignore, std::ignore) =
       factory()->GetOrOpenOriginFactory(origin, context()->data_path());
   EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString();
   origin_state_handle.Release();
@@ -312,7 +312,7 @@
 
   // Open a connection & immediately release it to cause the closing sequence to
   // start.
-  std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+  std::tie(origin_state_handle, s, std::ignore, std::ignore, std::ignore) =
       factory()->GetOrOpenOriginFactory(origin, context()->data_path());
   EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString();
   origin_state_handle.Release();
@@ -333,7 +333,7 @@
 
   // Open a connection & immediately release it to cause the closing sequence to
   // start again.
-  std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+  std::tie(origin_state_handle, s, std::ignore, std::ignore, std::ignore) =
       factory()->GetOrOpenOriginFactory(origin, context()->data_path());
   EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString();
   origin_state_handle.Release();
@@ -351,7 +351,7 @@
       factory()->GetOriginFactory(origin)->pre_close_task_queue()->started());
 
   // Stop sweep by opening a connection.
-  std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+  std::tie(origin_state_handle, s, std::ignore, std::ignore, std::ignore) =
       factory()->GetOrOpenOriginFactory(origin, context()->data_path());
   EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString();
   EXPECT_FALSE(
@@ -375,7 +375,7 @@
 
   //  Finally, move the clock forward so the origin should allow a sweep.
   clock.Advance(IndexedDBOriginState::kMaxEarliestOriginSweepFromNow);
-  std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+  std::tie(origin_state_handle, s, std::ignore, std::ignore, std::ignore) =
       factory()->GetOrOpenOriginFactory(origin, context()->data_path());
   origin_state_handle.Release();
   factory()->GetOriginFactory(origin)->close_timer()->FireNow();
@@ -397,7 +397,7 @@
   IndexedDBOriginStateHandle origin_state_handle;
   leveldb::Status s;
 
-  std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+  std::tie(origin_state_handle, s, std::ignore, std::ignore, std::ignore) =
       factory()->GetOrOpenOriginFactory(origin, context()->data_path());
   EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString();
   EXPECT_TRUE(OriginStateFromHandle(origin_state_handle)
@@ -428,7 +428,7 @@
   IndexedDBOriginStateHandle origin_state_handle;
   leveldb::Status s;
 
-  std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+  std::tie(origin_state_handle, s, std::ignore, std::ignore, std::ignore) =
       factory()->GetOrOpenOriginFactory(too_long_origin,
                                         context()->data_path());
   EXPECT_FALSE(origin_state_handle.IsHeld());
@@ -464,7 +464,7 @@
   IndexedDBOriginStateHandle origin_state_handle;
   leveldb::Status s;
 
-  std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+  std::tie(origin_state_handle, s, std::ignore, std::ignore, std::ignore) =
       factory()->GetOrOpenOriginFactory(origin, context()->data_path());
   EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString();
 
@@ -481,7 +481,7 @@
   IndexedDBOriginStateHandle origin_state_handle;
   leveldb::Status s;
 
-  std::tie(origin_state_handle, s, std::ignore, std::ignore) =
+  std::tie(origin_state_handle, s, std::ignore, std::ignore, std::ignore) =
       factory()->GetOrOpenOriginFactory(origin, context()->data_path());
   EXPECT_TRUE(origin_state_handle.IsHeld()) << s.ToString();
 
diff --git a/content/browser/indexed_db/indexed_db_pending_connection.h b/content/browser/indexed_db/indexed_db_pending_connection.h
index fd61559..ebe7d79 100644
--- a/content/browser/indexed_db/indexed_db_pending_connection.h
+++ b/content/browser/indexed_db/indexed_db_pending_connection.h
@@ -39,6 +39,7 @@
   base::OnceCallback<void(base::WeakPtr<IndexedDBTransaction>)>
       create_transaction_callback;
   base::WeakPtr<IndexedDBTransaction> transaction;
+  bool was_cold_open = false;
 };
 
 }  // namespace content
diff --git a/content/browser/keyboard_lock_browsertest.cc b/content/browser/keyboard_lock_browsertest.cc
index e7545cc..05a707e5 100644
--- a/content/browser/keyboard_lock_browsertest.cc
+++ b/content/browser/keyboard_lock_browsertest.cc
@@ -151,8 +151,7 @@
       const GURL& origin,
       const blink::WebFullscreenOptions& options) override;
   void ExitFullscreenModeForTab(WebContents* web_contents) override;
-  bool IsFullscreenForTabOrPending(
-      const WebContents* web_contents) const override;
+  bool IsFullscreenForTabOrPending(const WebContents* web_contents) override;
   void RequestKeyboardLock(WebContents* web_contents,
                            bool esc_key_locked) override;
   void CancelKeyboardLockRequest(WebContents* web_contents) override;
@@ -181,7 +180,7 @@
 }
 
 bool FakeKeyboardLockWebContentsDelegate::IsFullscreenForTabOrPending(
-    const WebContents* web_contents) const {
+    const WebContents* web_contents) {
   return is_fullscreen_;
 }
 
diff --git a/content/browser/notifications/platform_notification_context_trigger_unittest.cc b/content/browser/notifications/platform_notification_context_trigger_unittest.cc
index 4fcd8d7..ad01c2d 100644
--- a/content/browser/notifications/platform_notification_context_trigger_unittest.cc
+++ b/content/browser/notifications/platform_notification_context_trigger_unittest.cc
@@ -53,12 +53,9 @@
  public:
   PlatformNotificationContextTriggerTest()
       : thread_bundle_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
-            base::test::ScopedTaskEnvironment::NowSource::MAIN_THREAD_MOCK_TIME,
-            // TODO(crbug.com/974365): The IO thread is only needed so
-            // MessagePumpFuchsia will create an async::Loop, which is needed
-            // for fidl.
-            content::TestBrowserThreadBundle::REAL_IO_THREAD),
+            base::test::ScopedTaskEnvironment::MainThreadType::UI_MOCK_TIME,
+            base::test::ScopedTaskEnvironment::NowSource::
+                MAIN_THREAD_MOCK_TIME),
         notification_browser_client_(&browser_context_),
         success_(false) {
     SetBrowserClientForTesting(&notification_browser_client_);
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index 28294e34..9115c15 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -315,7 +315,7 @@
   void OnSwapBuffersCompleted(std::vector<ui::LatencyInfo> latency_info,
                               gfx::Size swap_size,
                               const gpu::SwapBuffersCompleteParams& params) {
-    client_->DidReceiveSwapBuffersAck();
+    client_->DidReceiveSwapBuffersAck(params.swap_response.timings);
     swap_buffers_callback_.Run(swap_size);
     UpdateLatencyInfoOnSwap(params.swap_response, &latency_info);
     latency_tracker_.OnGpuSwapBuffersCompleted(latency_info);
diff --git a/content/browser/renderer_host/input/fling_controller.cc b/content/browser/renderer_host/input/fling_controller.cc
index 0d6fda58..4131a5f 100644
--- a/content/browser/renderer_host/input/fling_controller.cc
+++ b/content/browser/renderer_host/input/fling_controller.cc
@@ -10,7 +10,6 @@
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/common/content_client.h"
 #include "ui/events/base_event_utils.h"
-#include "ui/events/blink/fling_booster.h"
 #include "ui/events/gestures/blink/web_gesture_curve_impl.h"
 
 using blink::WebInputEvent;
@@ -52,7 +51,6 @@
           config.touchpad_tap_suppression_config),
       touchscreen_tap_suppression_controller_(
           config.touchscreen_tap_suppression_config),
-      fling_in_progress_(false),
       clock_(base::DefaultTickClock::GetInstance()),
       weak_ptr_factory_(this) {
   DCHECK(event_sender_client);
@@ -61,21 +59,13 @@
 
 FlingController::~FlingController() = default;
 
-bool FlingController::ShouldForwardForGFCFiltering(
-    const GestureEventWithLatencyInfo& gesture_event) const {
-  if (gesture_event.event.GetType() != WebInputEvent::kGestureFlingCancel)
-    return true;
-
-  if (fling_in_progress_)
-    return !fling_booster_->fling_cancellation_is_deferred();
-
-  return false;
-}
-
-bool FlingController::ShouldForwardForTapSuppression(
+bool FlingController::ObserveAndFilterForTapSuppression(
     const GestureEventWithLatencyInfo& gesture_event) {
   switch (gesture_event.event.GetType()) {
     case WebInputEvent::kGestureFlingCancel:
+      // The controllers' state is affected by the cancel event and assumes
+      // it's actually stopping an ongoing fling.
+      DCHECK(fling_curve_);
       if (gesture_event.event.SourceDevice() ==
           blink::WebGestureDevice::kTouchscreen) {
         touchscreen_tap_suppression_controller_
@@ -84,7 +74,7 @@
                  blink::WebGestureDevice::kTouchpad) {
         touchpad_tap_suppression_controller_.GestureFlingCancelStoppedFling();
       }
-      return true;
+      return false;
     case WebInputEvent::kGestureTapDown:
     case WebInputEvent::kGestureShowPress:
     case WebInputEvent::kGestureTapUnconfirmed:
@@ -96,61 +86,27 @@
     case WebInputEvent::kGestureTwoFingerTap:
       if (gesture_event.event.SourceDevice() ==
           blink::WebGestureDevice::kTouchscreen) {
-        return !touchscreen_tap_suppression_controller_.FilterTapEvent(
+        return touchscreen_tap_suppression_controller_.FilterTapEvent(
             gesture_event);
       }
-      return true;
+      return false;
     default:
-      return true;
+      return false;
   }
 }
 
-bool FlingController::FilterGestureEventForFlingBoosting(
-    const GestureEventWithLatencyInfo& gesture_event) {
-  if (!fling_booster_)
-    return false;
-
-  bool cancel_current_fling;
-  bool should_filter_event = fling_booster_->FilterGestureEventForFlingBoosting(
-      gesture_event.event, &cancel_current_fling);
-  if (cancel_current_fling) {
-    CancelCurrentFling();
-  }
-
-  if (should_filter_event) {
-    if (gesture_event.event.GetType() == WebInputEvent::kGestureFlingStart) {
-      UpdateCurrentFlingState(gesture_event.event,
-                              fling_booster_->current_fling_velocity());
-      TRACE_EVENT_INSTANT2("input",
-                           fling_booster_->fling_boosted()
-                               ? "FlingController::FlingBoosted"
-                               : "FlingController::FlingReplaced",
-                           TRACE_EVENT_SCOPE_THREAD, "vx",
-                           fling_booster_->current_fling_velocity().x(), "vy",
-                           fling_booster_->current_fling_velocity().y());
-    } else if (gesture_event.event.GetType() ==
-               WebInputEvent::kGestureFlingCancel) {
-      DCHECK(fling_booster_->fling_cancellation_is_deferred());
-      TRACE_EVENT_INSTANT0("input", "FlingController::FlingBoostStart",
-                           TRACE_EVENT_SCOPE_THREAD);
-    } else if (gesture_event.event.GetType() ==
-                   WebInputEvent::kGestureScrollBegin ||
-               gesture_event.event.GetType() ==
-                   WebInputEvent::kGestureScrollUpdate) {
-      TRACE_EVENT_INSTANT0("input",
-                           "FlingController::ExtendBoostedFlingTimeout",
-                           TRACE_EVENT_SCOPE_THREAD);
-    }
-  }
-
-  return should_filter_event;
-}
-
 bool FlingController::ObserveAndMaybeConsumeGestureEvent(
     const GestureEventWithLatencyInfo& gesture_event) {
-  if (!ShouldForwardForGFCFiltering(gesture_event) ||
-      !ShouldForwardForTapSuppression(gesture_event) ||
-      FilterGestureEventForFlingBoosting(gesture_event))
+  // FlingCancel events arrive when a finger is touched down regardless of
+  // whether there is an ongoing fling. These can affect state so if there's no
+  // on-going fling we should just discard these without letting the rest of
+  // the fling system see it.
+  if (gesture_event.event.GetType() == WebInputEvent::kGestureFlingCancel &&
+      !fling_curve_) {
+    return true;
+  }
+
+  if (ObserveAndFilterForTapSuppression(gesture_event))
     return true;
 
   if (gesture_event.event.GetType() == WebInputEvent::kGestureScrollUpdate) {
@@ -165,6 +121,8 @@
     last_seen_scroll_update_ = base::TimeTicks();
   }
 
+  fling_booster_.ObserveGestureEvent(gesture_event.event);
+
   // fling_controller_ is in charge of handling GFS events and the events are
   // not sent to the renderer, the controller processes the fling and generates
   // fling progress events (wheel events for touchpad and GSU events for
@@ -186,20 +144,15 @@
 
 void FlingController::ProcessGestureFlingStart(
     const GestureEventWithLatencyInfo& gesture_event) {
-  const float vx = gesture_event.event.data.fling_start.velocity_x;
-  const float vy = gesture_event.event.data.fling_start.velocity_y;
-  if (!UpdateCurrentFlingState(gesture_event.event, gfx::Vector2dF(vx, vy)))
+  if (!UpdateCurrentFlingState(gesture_event.event))
     return;
 
-  TRACE_EVENT_ASYNC_BEGIN2("input", kFlingTraceName, this, "vx", vx, "vy", vy);
+  TRACE_EVENT_ASYNC_BEGIN2("input", kFlingTraceName, this, "vx",
+                           current_fling_parameters_.velocity.x(), "vy",
+                           current_fling_parameters_.velocity.y());
 
-  has_fling_animation_started_ = false;
   last_progress_time_ = base::TimeTicks();
-  fling_in_progress_ = true;
-  fling_booster_ = std::make_unique<ui::FlingBooster>(
-      current_fling_parameters_.velocity,
-      current_fling_parameters_.source_device,
-      current_fling_parameters_.modifiers);
+
   // Wait for BeginFrame to call ProgressFling when
   // SetNeedsBeginFrameForFlingProgress is used to progress flings instead of
   // compositor animation observer (happens on Android WebView).
@@ -215,10 +168,8 @@
 
 void FlingController::ProcessGestureFlingCancel(
     const GestureEventWithLatencyInfo& gesture_event) {
-  fling_in_progress_ = false;
-
-  if (fling_curve_)
-    CancelCurrentFling();
+  DCHECK(fling_curve_);
+  EndCurrentFling();
 }
 
 void FlingController::ProgressFling(base::TimeTicks current_time) {
@@ -226,15 +177,8 @@
     return;
 
   TRACE_EVENT_ASYNC_STEP_INTO0("input", kFlingTraceName, this, "ProgressFling");
-  DCHECK(fling_booster_);
-  fling_booster_->set_last_fling_animation_time(
-      (current_time - base::TimeTicks()).InSecondsF());
-  if (fling_booster_->MustCancelDeferredFling()) {
-    CancelCurrentFling();
-    return;
-  }
 
-  if (!has_fling_animation_started_) {
+  if (!first_fling_update_sent()) {
     // Guard against invalid as there are no guarantees fling event and progress
     // timestamps are compatible.
     if (current_fling_parameters_.start_time.is_null()) {
@@ -270,30 +214,27 @@
   bool fling_is_active = fling_curve_->Advance(
       (current_time - current_fling_parameters_.start_time).InSecondsF(),
       current_fling_parameters_.velocity, delta_to_scroll);
-  if (fling_is_active) {
-    if (std::abs(delta_to_scroll.x()) > kMinInertialScrollDelta ||
-        std::abs(delta_to_scroll.y()) > kMinInertialScrollDelta) {
-      GenerateAndSendFlingProgressEvents(delta_to_scroll);
-      has_fling_animation_started_ = true;
-      last_progress_time_ = current_time;
-    }
-    // As long as the fling curve is active, the fling progress must get
-    // scheduled even when the last delta to scroll was zero.
-    ScheduleFlingProgress();
+
+  if (!fling_is_active && current_fling_parameters_.source_device !=
+                              blink::WebGestureDevice::kSyntheticAutoscroll) {
+    EndCurrentFling();
     return;
   }
 
-  if (current_fling_parameters_.source_device !=
-      blink::WebGestureDevice::kSyntheticAutoscroll) {
-    CancelCurrentFling();
+  if (std::abs(delta_to_scroll.x()) > kMinInertialScrollDelta ||
+      std::abs(delta_to_scroll.y()) > kMinInertialScrollDelta) {
+    GenerateAndSendFlingProgressEvents(delta_to_scroll);
+    last_progress_time_ = current_time;
   }
+
+  // As long as the fling curve is active, the fling progress must get
+  // scheduled even when the last delta to scroll was zero.
+  ScheduleFlingProgress();
 }
 
 void FlingController::StopFling() {
-  if (!fling_curve_)
-    return;
-
-  CancelCurrentFling();
+  if (fling_curve_)
+    EndCurrentFling();
 }
 
 void FlingController::GenerateAndSendWheelEvents(
@@ -349,9 +290,8 @@
   switch (current_fling_parameters_.source_device) {
     case blink::WebGestureDevice::kTouchpad: {
       blink::WebMouseWheelEvent::Phase phase =
-          has_fling_animation_started_
-              ? blink::WebMouseWheelEvent::kPhaseChanged
-              : blink::WebMouseWheelEvent::kPhaseBegan;
+          first_fling_update_sent() ? blink::WebMouseWheelEvent::kPhaseChanged
+                                    : blink::WebMouseWheelEvent::kPhaseBegan;
       GenerateAndSendWheelEvents(delta, phase);
       break;
     }
@@ -386,62 +326,27 @@
   }
 }
 
-void FlingController::CancelCurrentFling() {
-  bool had_active_fling = !!fling_curve_;
-  fling_curve_.reset();
-  has_fling_animation_started_ = false;
+void FlingController::EndCurrentFling() {
   last_progress_time_ = base::TimeTicks();
-  fling_in_progress_ = false;
 
-  // Extract the last event filtered by the fling booster if it exists.
-  bool fling_cancellation_is_deferred =
-      fling_booster_ && fling_booster_->fling_cancellation_is_deferred();
-  WebGestureEvent last_fling_boost_event;
-  if (fling_cancellation_is_deferred)
-    last_fling_boost_event = fling_booster_->last_boost_event();
-
-  // Reset the state of the fling.
-  fling_booster_.reset();
   GenerateAndSendFlingEndEvents();
   current_fling_parameters_ = ActiveFlingParameters();
 
-  // Synthesize a GestureScrollBegin, as the original event was suppressed. It
-  // is important to send the GSB after resetting the fling_booster_ otherwise
-  // it will get filtered by the booster again. This is necessary for
-  // touchscreen fling cancelation only, since autoscroll fling cancelation
-  // doesn't get deferred and when the touchpad fling cancelation gets deferred,
-  // the first wheel event after the cancelation will cause a GSB generation.
-  if (fling_cancellation_is_deferred &&
-      last_fling_boost_event.SourceDevice() ==
-          blink::WebGestureDevice::kTouchscreen &&
-      (last_fling_boost_event.GetType() == WebInputEvent::kGestureScrollBegin ||
-       last_fling_boost_event.GetType() ==
-           WebInputEvent::kGestureScrollUpdate)) {
-    WebGestureEvent scroll_begin_event;
-    if (last_fling_boost_event.GetType() ==
-        WebInputEvent::kGestureScrollUpdate) {
-      scroll_begin_event =
-          ui::ScrollBeginFromScrollUpdate(last_fling_boost_event);
-    } else {
-      scroll_begin_event = last_fling_boost_event;
-    }
-    event_sender_client_->SendGeneratedGestureScrollEvents(
-        GestureEventWithLatencyInfo(
-            scroll_begin_event,
-            ui::LatencyInfo(ui::SourceEventType::INERTIAL)));
-  }
-
-  if (had_active_fling) {
+  if (fling_curve_) {
     scheduler_client_->DidStopFlingingOnBrowser(weak_ptr_factory_.GetWeakPtr());
     TRACE_EVENT_ASYNC_END0("input", kFlingTraceName, this);
   }
+
+  fling_curve_.reset();
 }
 
 bool FlingController::UpdateCurrentFlingState(
-    const WebGestureEvent& fling_start_event,
-    const gfx::Vector2dF& velocity) {
+    const WebGestureEvent& fling_start_event) {
   DCHECK_EQ(WebInputEvent::kGestureFlingStart, fling_start_event.GetType());
 
+  const gfx::Vector2dF velocity =
+      fling_booster_.GetVelocityForFlingStart(fling_start_event);
+
   current_fling_parameters_.velocity = velocity;
   current_fling_parameters_.point = fling_start_event.PositionInWidget();
   current_fling_parameters_.global_point = fling_start_event.PositionInScreen();
@@ -460,7 +365,7 @@
 
   if (velocity.IsZero() && fling_start_event.SourceDevice() !=
                                blink::WebGestureDevice::kSyntheticAutoscroll) {
-    CancelCurrentFling();
+    EndCurrentFling();
     return false;
   }
 
@@ -473,10 +378,6 @@
   return true;
 }
 
-bool FlingController::FlingCancellationIsDeferred() const {
-  return fling_booster_ && fling_booster_->fling_cancellation_is_deferred();
-}
-
 gfx::Vector2dF FlingController::CurrentFlingVelocity() const {
   return current_fling_parameters_.velocity;
 }
diff --git a/content/browser/renderer_host/input/fling_controller.h b/content/browser/renderer_host/input/fling_controller.h
index bcb5aec..a71152d 100644
--- a/content/browser/renderer_host/input/fling_controller.h
+++ b/content/browser/renderer_host/input/fling_controller.h
@@ -8,15 +8,12 @@
 #include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
 #include "content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h"
 #include "content/public/common/input_event_ack_state.h"
+#include "ui/events/blink/fling_booster.h"
 
 namespace blink {
 class WebGestureCurve;
 }
 
-namespace ui {
-class FlingBooster;
-}
-
 namespace content {
 
 class FlingController;
@@ -95,9 +92,7 @@
   void ProcessGestureFlingCancel(
       const GestureEventWithLatencyInfo& gesture_event);
 
-  bool fling_in_progress() const { return fling_in_progress_; }
-
-  bool FlingCancellationIsDeferred() const;
+  bool fling_in_progress() const { return fling_curve_.get(); }
 
   gfx::Vector2dF CurrentFlingVelocity() const;
 
@@ -107,20 +102,11 @@
   void set_clock_for_testing(const base::TickClock* clock) { clock_ = clock; }
 
  protected:
-  std::unique_ptr<ui::FlingBooster> fling_booster_;
+  ui::FlingBooster fling_booster_;
 
  private:
-  // Sub-filter for removing unnecessary GestureFlingCancels.
-  bool ShouldForwardForGFCFiltering(
-      const GestureEventWithLatencyInfo& gesture_event) const;
-
   // Sub-filter for suppressing taps immediately after a GestureFlingCancel.
-  bool ShouldForwardForTapSuppression(
-      const GestureEventWithLatencyInfo& gesture_event);
-
-  // Sub-filter for suppressing gesture events to boost an active fling whenever
-  // possible.
-  bool FilterGestureEventForFlingBoosting(
+  bool ObserveAndFilterForTapSuppression(
       const GestureEventWithLatencyInfo& gesture_event);
 
   void ScheduleFlingProgress();
@@ -145,10 +131,17 @@
 
   void GenerateAndSendFlingEndEvents();
 
-  void CancelCurrentFling();
+  void EndCurrentFling();
 
-  bool UpdateCurrentFlingState(const blink::WebGestureEvent& fling_start_event,
-                               const gfx::Vector2dF& velocity);
+  // Used to update the fling_curve_ state based on the parameters of the fling
+  // start event. Returns true if the fling curve was updated for a valid
+  // fling. Returns false if the parameters should not cause a fling and the
+  // fling_curve_ is not updated.
+  bool UpdateCurrentFlingState(const blink::WebGestureEvent& fling_start_event);
+
+  bool first_fling_update_sent() const {
+    return !last_progress_time_.is_null();
+  }
 
   FlingControllerEventSenderClient* event_sender_client_;
 
@@ -164,18 +157,12 @@
   // canceling tap.
   TouchscreenTapSuppressionController touchscreen_tap_suppression_controller_;
 
-  // Gesture curve of the current active fling.
+  // Gesture curve of the current active fling. nullptr while a fling is not
+  // active.
   std::unique_ptr<blink::WebGestureCurve> fling_curve_;
 
   ActiveFlingParameters current_fling_parameters_;
 
-  // True when a fling is active.
-  bool fling_in_progress_;
-
-  // Whether an active fling has seen a |ProgressFling()| call. This is useful
-  // for determining if the fling start time should be re-initialized.
-  bool has_fling_animation_started_;
-
   // The last time fling progress events were sent.
   base::TimeTicks last_progress_time_;
 
diff --git a/content/browser/renderer_host/input/fling_controller_unittest.cc b/content/browser/renderer_host/input/fling_controller_unittest.cc
index 1405a5ad..c9f2f2d0 100644
--- a/content/browser/renderer_host/input/fling_controller_unittest.cc
+++ b/content/browser/renderer_host/input/fling_controller_unittest.cc
@@ -30,8 +30,6 @@
                       FlingControllerSchedulerClient* scheduler_client,
                       const Config& config)
       : FlingController(event_sender_client, scheduler_client, config) {}
-
-  bool FlingBoosted() const { return fling_booster_->fling_boosted(); }
 };
 
 class FlingControllerTest : public FlingControllerEventSenderClient,
@@ -138,7 +136,6 @@
   }
 
   bool FlingInProgress() { return fling_controller_->fling_in_progress(); }
-  bool FlingBoosted() { return fling_controller_->FlingBoosted(); }
 
   void AdvanceTime(double time_delta_ms = kFrameDelta) {
     mock_clock_.Advance(base::TimeDelta::FromMillisecondsD(time_delta_ms));
@@ -211,17 +208,9 @@
   EXPECT_EQ(WebMouseWheelEvent::kPhaseChanged, last_sent_wheel_.momentum_phase);
   EXPECT_GT(last_sent_wheel_.delta_x, 0.f);
 
-  // Now cancel the fling. The GFC will get suppressed by fling booster.
+  // Now cancel the fling.
   SimulateFlingCancel(blink::WebGestureDevice::kTouchpad);
-  EXPECT_TRUE(FlingInProgress());
-
-  // Wait for the boosting timer to expire. The delayed cancelation must work.
-  AdvanceTime(500);
-  ProgressFling(NowTicks());
   EXPECT_FALSE(FlingInProgress());
-  EXPECT_EQ(WebMouseWheelEvent::kPhaseEnded, last_sent_wheel_.momentum_phase);
-  EXPECT_EQ(0.f, last_sent_wheel_.delta_x);
-  EXPECT_EQ(0.f, last_sent_wheel_.delta_y);
 }
 
 // Ensure that the start time of a fling is measured from the last received
@@ -261,13 +250,11 @@
             last_sent_gesture_.data.scroll_update.inertial_phase);
   EXPECT_GT(last_sent_gesture_.data.scroll_update.delta_x, 0.f);
 
-  // Now cancel the fling. The GFC will get suppressed by fling booster.
+  // Now cancel the fling.
   SimulateFlingCancel(blink::WebGestureDevice::kTouchscreen);
-  EXPECT_TRUE(FlingInProgress());
+  EXPECT_FALSE(FlingInProgress());
 
-  // Wait for the boosting timer to expire. The delayed cancelation must work.
-  AdvanceTime(500);
-  ProgressFling(NowTicks());
+  // Cancellation should send a GSE.
   EXPECT_FALSE(FlingInProgress());
   EXPECT_EQ(WebInputEvent::kGestureScrollEnd, last_sent_gesture_.GetType());
 }
@@ -370,21 +357,27 @@
   EXPECT_EQ(WebInputEvent::kGestureScrollEnd, last_sent_gesture_.GetType());
 }
 
-TEST_P(FlingControllerTest, GestureFlingCancelsFiltered) {
-  // GFC without previous GFS is dropped.
-  SimulateFlingCancel(blink::WebGestureDevice::kTouchscreen);
-  EXPECT_FALSE(FlingInProgress());
+TEST_P(FlingControllerTest, GestureFlingCancelOutsideFling) {
+  // FlingCancel without a FlingStart doesn't cause issues, doesn't send any
+  // events.
+  {
+    int current_sent_scroll_gesture_count = sent_scroll_gesture_count_;
+    SimulateFlingCancel(blink::WebGestureDevice::kTouchscreen);
+    EXPECT_FALSE(FlingInProgress());
+    EXPECT_EQ(current_sent_scroll_gesture_count, sent_scroll_gesture_count_);
+  }
 
-  // GFC after previous GFS is filtered by fling booster.
-  SimulateFlingStart(blink::WebGestureDevice::kTouchscreen,
-                     gfx::Vector2dF(1000, 0));
-  EXPECT_TRUE(FlingInProgress());
-  SimulateFlingCancel(blink::WebGestureDevice::kTouchscreen);
-  EXPECT_TRUE(FlingInProgress());
-
-  // Any other GFC while the fling cancelation is deferred gets filtered.
-  SimulateFlingCancel(blink::WebGestureDevice::kTouchscreen);
-  EXPECT_TRUE(FlingInProgress());
+  // Do a fling and cancel it. Make sure another cancel is also a no-op.
+  {
+    SimulateFlingStart(blink::WebGestureDevice::kTouchscreen,
+                       gfx::Vector2dF(1000, 0));
+    AdvanceTime();
+    ProgressFling(NowTicks());
+    SimulateFlingCancel(blink::WebGestureDevice::kTouchscreen);
+    int current_sent_scroll_gesture_count = sent_scroll_gesture_count_;
+    SimulateFlingCancel(blink::WebGestureDevice::kTouchscreen);
+    EXPECT_EQ(current_sent_scroll_gesture_count, sent_scroll_gesture_count_);
+  }
 }
 
 TEST_P(FlingControllerTest, GestureFlingNotCancelledBySmallTimeDelta) {
@@ -479,13 +472,7 @@
   EXPECT_GT(wheel_event_count_, 0);
 }
 
-#if defined(OS_LINUX)
-#define MAYBE_ControllerBoostsTouchpadFling \
-  DISABLED_ControllerBoostsTouchpadFling
-#else
-#define MAYBE_ControllerBoostsTouchpadFling ControllerBoostsTouchpadFling
-#endif
-TEST_P(FlingControllerTest, MAYBE_ControllerBoostsTouchpadFling) {
+TEST_P(FlingControllerTest, ControllerBoostsTouchpadFling) {
   SimulateFlingStart(blink::WebGestureDevice::kTouchpad,
                      gfx::Vector2dF(1000, 0));
   EXPECT_TRUE(FlingInProgress());
@@ -510,15 +497,14 @@
   EXPECT_EQ(WebMouseWheelEvent::kPhaseChanged, last_sent_wheel_.momentum_phase);
   EXPECT_GT(last_sent_wheel_.delta_x, 0.f);
 
-  // Now cancel the fling. The GFC will get suppressed by fling booster.
+  // Now cancel the fling.
   SimulateFlingCancel(blink::WebGestureDevice::kTouchpad);
-  EXPECT_TRUE(FlingInProgress());
+  EXPECT_FALSE(FlingInProgress());
 
   // The second GFS will boost the current active fling.
   SimulateFlingStart(blink::WebGestureDevice::kTouchpad,
                      gfx::Vector2dF(1000, 0));
   EXPECT_TRUE(FlingInProgress());
-  EXPECT_TRUE(FlingBoosted());
 }
 
 TEST_P(FlingControllerTest, ControllerBoostsTouchscreenFling) {
@@ -533,15 +519,16 @@
             last_sent_gesture_.data.scroll_update.inertial_phase);
   EXPECT_GT(last_sent_gesture_.data.scroll_update.delta_x, 0.f);
 
-  // Now cancel the fling. The GFC will get suppressed by fling booster.
+  // Now cancel the fling.
   SimulateFlingCancel(blink::WebGestureDevice::kTouchscreen);
-  EXPECT_TRUE(FlingInProgress());
+  EXPECT_FALSE(FlingInProgress());
 
-  // The second GFS will boost the current active fling.
+  // The second GFS can be boosted so it should boost the just deactivated
+  // fling.
   SimulateFlingStart(blink::WebGestureDevice::kTouchscreen,
                      gfx::Vector2dF(1000, 0));
   EXPECT_TRUE(FlingInProgress());
-  EXPECT_TRUE(FlingBoosted());
+  EXPECT_GT(fling_controller_->CurrentFlingVelocity().x(), 1000);
 }
 
 TEST_P(FlingControllerTest, ControllerNotifiesTheClientAfterFlingStart) {
@@ -549,16 +536,9 @@
                      gfx::Vector2dF(1000, 0));
   EXPECT_TRUE(FlingInProgress());
 
-  // Now cancel the fling. The GFC will get suppressed by fling booster.
+  // Now cancel the fling.
   SimulateFlingCancel(blink::WebGestureDevice::kTouchscreen);
-  EXPECT_TRUE(FlingInProgress());
-
-  // Wait for the boosting timer to expire. The delayed cancelation must work
-  // and the client must be notified after fling cancelation.
-  AdvanceTime(500);
-  ProgressFling(NowTicks());
   EXPECT_FALSE(FlingInProgress());
-  EXPECT_EQ(WebInputEvent::kGestureScrollEnd, last_sent_gesture_.GetType());
   EXPECT_TRUE(notified_client_after_fling_stop_);
 }
 
@@ -580,7 +560,7 @@
   SimulateFlingStart(blink::WebGestureDevice::kSyntheticAutoscroll,
                      gfx::Vector2dF(2000, 0));
   EXPECT_TRUE(FlingInProgress());
-  EXPECT_FALSE(FlingBoosted());
+  EXPECT_EQ(fling_controller_->CurrentFlingVelocity().x(), 2000);
 
   // Now cancel the fling. The GFC won't get suppressed by fling booster since
   // autoscroll fling doesn't have boosting.
diff --git a/content/browser/renderer_host/input/gesture_event_queue.cc b/content/browser/renderer_host/input/gesture_event_queue.cc
index d266c05..c925ba5 100644
--- a/content/browser/renderer_host/input/gesture_event_queue.cc
+++ b/content/browser/renderer_host/input/gesture_event_queue.cc
@@ -75,10 +75,6 @@
   fling_controller_.StopFling();
 }
 
-bool GestureEventQueue::FlingCancellationIsDeferred() const {
-  return fling_controller_.FlingCancellationIsDeferred();
-}
-
 gfx::Vector2dF GestureEventQueue::CurrentFlingVelocity() const {
   return fling_controller_.CurrentFlingVelocity();
 }
diff --git a/content/browser/renderer_host/input/gesture_event_queue.h b/content/browser/renderer_host/input/gesture_event_queue.h
index 48976bcf..c279724 100644
--- a/content/browser/renderer_host/input/gesture_event_queue.h
+++ b/content/browser/renderer_host/input/gesture_event_queue.h
@@ -118,8 +118,6 @@
   // Calls |fling_controller_.StopFling| to halt an active fling if such exists.
   void StopFling();
 
-  bool FlingCancellationIsDeferred() const;
-
   gfx::Vector2dF CurrentFlingVelocity() const;
 
   void set_debounce_interval_time_ms_for_testing(int interval_ms) {
diff --git a/content/browser/renderer_host/input/gesture_event_queue_unittest.cc b/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
index 496beb3a..ff22573 100644
--- a/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
+++ b/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
@@ -215,9 +215,6 @@
   }
 
   bool FlingInProgress() { return queue()->FlingInProgressForTest(); }
-  bool FlingCancellationIsDeferred() {
-    return queue()->FlingCancellationIsDeferred();
-  }
 
   GestureEventQueue* queue() const {
     return queue_.get();
@@ -476,7 +473,7 @@
 
 // Test that the fling cancelling tap down event and its following tap get
 // suppressed when tap suppression is enabled.
-TEST_F(GestureEventQueueTest, TapGetsSuppressedAfterTapDownCancellsFling) {
+TEST_F(GestureEventQueueTest, TapGetsSuppressedAfterTapDownCancelsFling) {
   SetUpForTapSuppression(400);
   // The velocity of the event must be large enough to make sure that the fling
   // is still active when the tap down happens.
@@ -492,7 +489,6 @@
   // fling cancel event is not sent to the renderer.
   SimulateGestureEvent(WebInputEvent::kGestureFlingCancel,
                        blink::WebGestureDevice::kTouchscreen);
-  EXPECT_TRUE(FlingCancellationIsDeferred());
   EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
   EXPECT_EQ(0U, GestureEventQueueSize());
   RunUntilIdle();
diff --git a/content/browser/renderer_host/input/input_router.h b/content/browser/renderer_host/input/input_router.h
index 3a32def..ed482871 100644
--- a/content/browser/renderer_host/input/input_router.h
+++ b/content/browser/renderer_host/input/input_router.h
@@ -91,9 +91,6 @@
   // Used to stop an active fling if such exists.
   virtual void StopFling() = 0;
 
-  // Used to check if a fling cancellation is deferred due to boosting or not.
-  virtual bool FlingCancellationIsDeferred() = 0;
-
   // Called when a set-touch-action message is received from the renderer
   // for a touch start event that is currently in flight.
   virtual void OnSetTouchAction(cc::TouchAction touch_action) = 0;
diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc
index 0eaa9de..b0b6cde 100644
--- a/content/browser/renderer_host/input/input_router_impl.cc
+++ b/content/browser/renderer_host/input/input_router_impl.cc
@@ -140,8 +140,7 @@
 
 void InputRouterImpl::SendGestureEvent(
     const GestureEventWithLatencyInfo& original_gesture_event) {
-  input_stream_validator_.Validate(original_gesture_event.event,
-                                   FlingCancellationIsDeferred());
+  input_stream_validator_.Validate(original_gesture_event.event);
 
   GestureEventWithLatencyInfo gesture_event(original_gesture_event);
 
@@ -261,10 +260,6 @@
   gesture_event_queue_.StopFling();
 }
 
-bool InputRouterImpl::FlingCancellationIsDeferred() {
-  return gesture_event_queue_.FlingCancellationIsDeferred();
-}
-
 void InputRouterImpl::ProcessDeferredGestureEventQueue() {
   GestureEventQueue::GestureQueue deferred_gesture_events =
       gesture_event_queue_.TakeDeferredEvents();
diff --git a/content/browser/renderer_host/input/input_router_impl.h b/content/browser/renderer_host/input/input_router_impl.h
index 745bac2..b4b8f4da 100644
--- a/content/browser/renderer_host/input/input_router_impl.h
+++ b/content/browser/renderer_host/input/input_router_impl.h
@@ -86,7 +86,6 @@
   void BindHost(mojom::WidgetInputHandlerHostRequest request,
                 bool frame_handler) override;
   void StopFling() override;
-  bool FlingCancellationIsDeferred() override;
   void OnSetTouchAction(cc::TouchAction touch_action) override;
   void ForceSetTouchActionAuto() override;
 
diff --git a/content/browser/renderer_host/input/mock_input_router.cc b/content/browser/renderer_host/input/mock_input_router.cc
index 142067c..d2890cbe 100644
--- a/content/browser/renderer_host/input/mock_input_router.cc
+++ b/content/browser/renderer_host/input/mock_input_router.cc
@@ -45,10 +45,6 @@
   return cc::kTouchActionAuto;
 }
 
-bool MockInputRouter::FlingCancellationIsDeferred() {
-  return false;
-}
-
 void MockInputRouter::OnHasTouchEventHandlers(bool has_handlers) {
   has_handlers_ = has_handlers;
 }
diff --git a/content/browser/renderer_host/input/mock_input_router.h b/content/browser/renderer_host/input/mock_input_router.h
index 31ca101..9bc5dab 100644
--- a/content/browser/renderer_host/input/mock_input_router.h
+++ b/content/browser/renderer_host/input/mock_input_router.h
@@ -47,7 +47,6 @@
   void BindHost(mojom::WidgetInputHandlerHostRequest request,
                 bool frame_handler) override {}
   void StopFling() override {}
-  bool FlingCancellationIsDeferred() override;
   void OnSetTouchAction(cc::TouchAction touch_action) override {}
   void ForceSetTouchActionAuto() override {}
   void OnHasTouchEventHandlers(bool has_handlers) override;
diff --git a/content/browser/renderer_host/media/aec_dump_manager_impl.cc b/content/browser/renderer_host/media/aec_dump_manager_impl.cc
new file mode 100644
index 0000000..1911a66
--- /dev/null
+++ b/content/browser/renderer_host/media/aec_dump_manager_impl.cc
@@ -0,0 +1,104 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/media/aec_dump_manager_impl.h"
+
+#include "base/files/file.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/task/post_task.h"
+#include "content/browser/webrtc/webrtc_internals.h"
+#include "mojo/public/cpp/base/file_mojom_traits.h"
+
+namespace content {
+namespace {
+
+constexpr char kAecDumpFileNameAddition[] = "aec_dump";
+
+base::File CreateDumpFile(const base::FilePath& file_path) {
+  return base::File(file_path,
+                    base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_APPEND);
+}
+
+}  // namespace
+
+AecDumpManagerImpl::AecDumpManagerImpl() = default;
+
+AecDumpManagerImpl::~AecDumpManagerImpl() = default;
+
+void AecDumpManagerImpl::AddRequest(
+    mojo::InterfaceRequest<mojom::AecDumpManager> request) {
+  receiver_set_.Add(this, std::move(request));
+}
+
+void AecDumpManagerImpl::AutoStart() {
+  WebRTCInternals* webrtc_internals = WebRTCInternals::GetInstance();
+  if (webrtc_internals->IsAudioDebugRecordingsEnabled())
+    Start(webrtc_internals->GetAudioDebugRecordingsFilePath());
+}
+
+void AecDumpManagerImpl::Start(const base::FilePath& file_path) {
+  for (auto& it : agents_)
+    CreateFileAndStartDump(file_path, it.first);
+}
+
+void AecDumpManagerImpl::Stop() {
+  for (auto& it : agents_)
+    it.second->Stop();
+}
+
+void AecDumpManagerImpl::Add(mojo::PendingRemote<mojom::AecDumpAgent> agent) {
+  int id = ++id_counter_;
+
+  agents_.emplace(std::make_pair(id, std::move(agent)));
+
+  agents_[id].set_disconnect_handler(
+      base::BindOnce(&AecDumpManagerImpl::OnAgentDisconnected,
+                     weak_factory_.GetWeakPtr(), id));
+
+  WebRTCInternals* webrtc_internals = WebRTCInternals::GetInstance();
+  if (webrtc_internals->IsAudioDebugRecordingsEnabled()) {
+    CreateFileAndStartDump(webrtc_internals->GetAudioDebugRecordingsFilePath(),
+                           id);
+  }
+}
+
+void AecDumpManagerImpl::CreateFileAndStartDump(const base::FilePath& file_path,
+                                                int id) {
+  base::FilePath file_path_extended =
+      file_path.AddExtensionASCII(base::NumberToString(pid_))
+          .AddExtensionASCII(kAecDumpFileNameAddition)
+          .AddExtensionASCII(base::NumberToString(id));
+
+  base::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
+       base::TaskPriority::USER_BLOCKING},
+      base::BindOnce(&CreateDumpFile, file_path_extended),
+      base::BindOnce(&AecDumpManagerImpl::StartDump, weak_factory_.GetWeakPtr(),
+                     id));
+}
+
+void AecDumpManagerImpl::StartDump(int id, base::File file) {
+  if (!file.IsValid()) {
+    VLOG(1) << "Could not open AEC dump file, error=" << file.error_details();
+    return;
+  }
+
+  auto it = agents_.find(id);
+  if (it == agents_.end()) {
+    // Post the file close to avoid blocking the current thread.
+    base::PostTaskWithTraits(
+        FROM_HERE, {base::TaskPriority::LOWEST, base::MayBlock()},
+        base::BindOnce([](base::File) {}, std::move(file)));
+    return;
+  }
+
+  it->second->Start(std::move(file));
+}
+
+void AecDumpManagerImpl::OnAgentDisconnected(int id) {
+  agents_.erase(id);
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/media/aec_dump_manager_impl.h b/content/browser/renderer_host/media/aec_dump_manager_impl.h
new file mode 100644
index 0000000..fd49092
--- /dev/null
+++ b/content/browser/renderer_host/media/aec_dump_manager_impl.h
@@ -0,0 +1,60 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_AEC_DUMP_MANAGER_IMPL_H_
+#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_AEC_DUMP_MANAGER_IMPL_H_
+
+#include <map>
+#include <memory>
+
+#include "base/process/process_handle.h"
+#include "content/common/media/aec_dump.mojom.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+
+namespace base {
+class File;
+class FilePath;
+}  // namespace base
+
+namespace content {
+
+class AecDumpManagerImpl : public mojom::AecDumpManager {
+ public:
+  AecDumpManagerImpl();
+  ~AecDumpManagerImpl() override;
+
+  void AddRequest(mojo::InterfaceRequest<mojom::AecDumpManager> request);
+
+  // Start generating AEC dumps using default settings.
+  void AutoStart();
+
+  // Start generating AEC dumps using a specific file path prefix.
+  void Start(const base::FilePath& file_path);
+
+  // Stop generating AEC dumps.
+  void Stop();
+
+  // mojom::AecDumpManager methods:
+  void Add(mojo::PendingRemote<mojom::AecDumpAgent> agent) override;
+
+  void set_pid(base::ProcessId pid) { pid_ = pid; }
+
+ private:
+  void CreateFileAndStartDump(const base::FilePath& file_path, int id);
+  void StartDump(int id, base::File file);
+  void OnAgentDisconnected(int id);
+
+  base::ProcessId pid_ = 0;
+  std::map<int /* id */, mojo::Remote<mojom::AecDumpAgent>> agents_;
+  int id_counter_ = 0;
+  mojo::ReceiverSet<mojom::AecDumpManager> receiver_set_;
+
+  base::WeakPtrFactory<AecDumpManagerImpl> weak_factory_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(AecDumpManagerImpl);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_RENDERER_HOST_MEDIA_AEC_DUMP_MANAGER_IMPL_H_
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index b69a84e..b50b565 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -135,14 +135,12 @@
 #include "content/browser/site_instance_impl.h"
 #include "content/browser/storage_partition_impl.h"
 #include "content/browser/tracing/background_tracing_manager_impl.h"
-#include "content/browser/webrtc/webrtc_internals.h"
 #include "content/browser/websockets/websocket_manager.h"
 #include "content/browser/webui/web_ui_controller_factory_registry.h"
 #include "content/common/child_process_host_impl.h"
 #include "content/common/content_switches_internal.h"
 #include "content/common/frame_messages.h"
 #include "content/common/in_process_child_thread_params.h"
-#include "content/common/media/aec_dump_messages.h"
 #include "content/common/media/peer_connection_tracker_messages.h"
 #include "content/common/resource_messages.h"
 #include "content/common/service_manager/child_connection.h"
@@ -269,12 +267,6 @@
 #include "services/service_manager/zygote/common/zygote_handle.h"  // nogncheck
 #endif
 
-#if defined(OS_WIN)
-#define NumberToStringType base::NumberToString16
-#else
-#define NumberToStringType base::NumberToString
-#endif
-
 namespace content {
 
 namespace {
@@ -295,9 +287,6 @@
 RenderProcessHost::AnalyzeHungRendererFunction g_analyze_hung_renderer =
     nullptr;
 
-const base::FilePath::CharType kAecDumpFileNameAddition[] =
-    FILE_PATH_LITERAL("aec_dump");
-
 void CacheShaderInfo(int32_t id, base::FilePath path) {
   if (GetShaderCacheFactorySingleton())
     GetShaderCacheFactorySingleton()->SetCacheInfo(id, path);
@@ -332,18 +321,6 @@
       GetRequestContext(request_context, media_request_context, resource_type);
 }
 
-// Creates a file used for handing over to the renderer.
-IPC::PlatformFileForTransit CreateFileForProcess(base::FilePath file_path) {
-  base::File dump_file(file_path,
-                       base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_APPEND);
-  if (!dump_file.IsValid()) {
-    VLOG(1) << "Could not open AEC dump file, error="
-            << dump_file.error_details();
-    return IPC::InvalidPlatformFileForTransit();
-  }
-  return IPC::TakePlatformFileForTransit(std::move(dump_file));
-}
-
 // Allow us to only run the trial in the first renderer.
 bool has_done_stun_trials = false;
 
@@ -2196,6 +2173,11 @@
       base::BindRepeating(&RenderProcessHostImpl::BindVideoDecoderService,
                           base::Unretained(this)));
 
+  AddUIThreadInterface(
+      registry.get(),
+      base::BindRepeating(&AecDumpManagerImpl::AddRequest,
+                          base::Unretained(&aec_dump_manager_)));
+
   // ---- Please do not register interfaces below this line ------
   //
   // This call should be done after registering all interfaces above, so that
@@ -3279,10 +3261,6 @@
       IPC_MESSAGE_HANDLER(ViewHostMsg_UserMetricsRecordAction,
                           OnUserMetricsRecordAction)
       IPC_MESSAGE_HANDLER(WidgetHostMsg_Close_ACK, OnCloseACK)
-      IPC_MESSAGE_HANDLER(AecDumpMsg_RegisterAecDumpConsumer,
-                          OnRegisterAecDumpConsumer)
-      IPC_MESSAGE_HANDLER(AecDumpMsg_UnregisterAecDumpConsumer,
-                          OnUnregisterAecDumpConsumer)
     // Adding single handlers for your service here is fine, but once your
     // service needs more than one handler, please extract them into a new
     // message filter and add that filter to CreateMessageFilters().
@@ -3549,26 +3527,16 @@
 }
 
 void RenderProcessHostImpl::EnableAudioDebugRecordings(
-    const base::FilePath& file) {
+    const base::FilePath& file_path) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  // Enable AEC dump for each registered consumer.
-  base::FilePath file_with_extensions = GetAecDumpFilePathWithExtensions(file);
-  for (int id : aec_dump_consumers_) {
-    EnableAecDumpForId(file_with_extensions, id);
-  }
+  aec_dump_manager_.Start(file_path);
 }
 
 void RenderProcessHostImpl::DisableAudioDebugRecordings() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  // Posting on the sequence and then replying back on the UI thread is only
-  // for avoiding races between enable and disable. Nothing is done on the
-  // sequence.
-  GetAecDumpFileTaskRunner().PostTaskAndReply(
-      FROM_HERE, base::DoNothing(),
-      base::BindOnce(&RenderProcessHostImpl::SendDisableAecDumpToRenderer,
-                     weak_factory_.GetWeakPtr()));
+  aec_dump_manager_.Stop();
 }
 
 RenderProcessHostImpl::WebRtcStopRtpDumpCallback
@@ -4474,11 +4442,8 @@
       observer.RenderProcessReady(this);
   }
 
-  WebRTCInternals* webrtc_internals = WebRTCInternals::GetInstance();
-  if (webrtc_internals->IsAudioDebugRecordingsEnabled()) {
-    EnableAudioDebugRecordings(
-        webrtc_internals->GetAudioDebugRecordingsFilePath());
-  }
+  aec_dump_manager_.set_pid(GetProcess().Pid());
+  aec_dump_manager_.AutoStart();
 }
 
 void RenderProcessHostImpl::OnProcessLaunchFailed(int error_code) {
@@ -4578,80 +4543,6 @@
 }
 #endif  // BUILDFLAG(ENABLE_MDNS)
 
-void RenderProcessHostImpl::OnRegisterAecDumpConsumer(int id) {
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::UI},
-      base::BindOnce(&RenderProcessHostImpl::RegisterAecDumpConsumerOnUIThread,
-                     weak_factory_.GetWeakPtr(), id));
-}
-
-void RenderProcessHostImpl::OnUnregisterAecDumpConsumer(int id) {
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::UI},
-      base::BindOnce(
-          &RenderProcessHostImpl::UnregisterAecDumpConsumerOnUIThread,
-          weak_factory_.GetWeakPtr(), id));
-}
-
-void RenderProcessHostImpl::RegisterAecDumpConsumerOnUIThread(int id) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  aec_dump_consumers_.push_back(id);
-
-  WebRTCInternals* webrtc_internals = WebRTCInternals::GetInstance();
-  if (webrtc_internals->IsAudioDebugRecordingsEnabled()) {
-    base::FilePath file_with_extensions = GetAecDumpFilePathWithExtensions(
-        webrtc_internals->GetAudioDebugRecordingsFilePath());
-    EnableAecDumpForId(file_with_extensions, id);
-  }
-}
-
-void RenderProcessHostImpl::UnregisterAecDumpConsumerOnUIThread(int id) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  auto it =
-      std::find(aec_dump_consumers_.begin(), aec_dump_consumers_.end(), id);
-  if (it != aec_dump_consumers_.end())
-    aec_dump_consumers_.erase(it);
-}
-
-void RenderProcessHostImpl::EnableAecDumpForId(const base::FilePath& file,
-                                               int id) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  base::PostTaskAndReplyWithResult(
-      &GetAecDumpFileTaskRunner(), FROM_HERE,
-      base::Bind(&CreateFileForProcess,
-                 file.AddExtension(NumberToStringType(id))),
-      base::Bind(&RenderProcessHostImpl::SendAecDumpFileToRenderer,
-                 weak_factory_.GetWeakPtr(), id));
-}
-
-void RenderProcessHostImpl::SendAecDumpFileToRenderer(
-    int id,
-    IPC::PlatformFileForTransit file_for_transit) {
-  if (file_for_transit == IPC::InvalidPlatformFileForTransit())
-    return;
-  Send(new AecDumpMsg_EnableAecDump(id, file_for_transit));
-}
-
-void RenderProcessHostImpl::SendDisableAecDumpToRenderer() {
-  Send(new AecDumpMsg_DisableAecDump());
-}
-
-base::FilePath RenderProcessHostImpl::GetAecDumpFilePathWithExtensions(
-    const base::FilePath& file) {
-  return file.AddExtension(NumberToStringType(GetProcess().Pid()))
-      .AddExtension(kAecDumpFileNameAddition);
-}
-
-base::SequencedTaskRunner& RenderProcessHostImpl::GetAecDumpFileTaskRunner() {
-  if (!audio_debug_recordings_file_task_runner_) {
-    audio_debug_recordings_file_task_runner_ =
-        base::CreateSequencedTaskRunnerWithTraits(
-            {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
-             base::TaskPriority::USER_BLOCKING});
-  }
-  return *audio_debug_recordings_file_task_runner_;
-}
-
 // static
 void RenderProcessHostImpl::OnMojoError(int render_process_id,
                                         const std::string& error) {
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index a949f32..da7d3ca 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -33,6 +33,7 @@
 #include "content/browser/media/video_decoder_proxy.h"
 #include "content/browser/renderer_host/embedded_frame_sink_provider_impl.h"
 #include "content/browser/renderer_host/frame_sink_provider_impl.h"
+#include "content/browser/renderer_host/media/aec_dump_manager_impl.h"
 #include "content/browser/renderer_host/media/renderer_audio_output_stream_factory_context_impl.h"
 #include "content/common/associated_interfaces.mojom.h"
 #include "content/common/child_control.mojom.h"
@@ -636,17 +637,6 @@
   void CreateMdnsResponder(network::mojom::MdnsResponderRequest request);
 #endif  // BUILDFLAG(ENABLE_MDNS)
 
-  void OnRegisterAecDumpConsumer(int id);
-  void OnUnregisterAecDumpConsumer(int id);
-  void RegisterAecDumpConsumerOnUIThread(int id);
-  void UnregisterAecDumpConsumerOnUIThread(int id);
-  void EnableAecDumpForId(const base::FilePath& file, int id);
-  // Sends |file_for_transit| to the render process.
-  void SendAecDumpFileToRenderer(int id,
-                                 IPC::PlatformFileForTransit file_for_transit);
-  void SendDisableAecDumpToRenderer();
-  base::FilePath GetAecDumpFilePathWithExtensions(const base::FilePath& file);
-  base::SequencedTaskRunner& GetAecDumpFileTaskRunner();
   void NotifyRendererIfLockedToSite();
   void PopulateTerminationInfoRendererFields(ChildProcessTerminationInfo* info);
 
@@ -839,13 +829,10 @@
   std::unique_ptr<P2PSocketDispatcherHost> p2p_socket_dispatcher_host_;
 
   // Must be accessed on UI thread.
-  std::vector<int> aec_dump_consumers_;
+  AecDumpManagerImpl aec_dump_manager_;
 
   WebRtcStopRtpDumpCallback stop_rtp_dump_callback_;
 
-  scoped_refptr<base::SequencedTaskRunner>
-      audio_debug_recordings_file_task_runner_;
-
   std::unique_ptr<MediaStreamTrackMetricsHost, BrowserThread::DeleteOnIOThread>
       media_stream_track_metrics_host_;
 
diff --git a/content/browser/renderer_host/render_widget_host_delegate.h b/content/browser/renderer_host/render_widget_host_delegate.h
index 00a6998..1990066 100644
--- a/content/browser/renderer_host/render_widget_host_delegate.h
+++ b/content/browser/renderer_host/render_widget_host_delegate.h
@@ -324,6 +324,11 @@
   // Lock events from the renderer.
   virtual InputEventShim* GetInputEventShim() const;
 
+  // Notifies all renderers in a page about changes to the size of the visible
+  // viewport.
+  virtual void NotifyVisibleViewportSizeChanged(
+      const gfx::Size& visible_viewport_size) {}
+
  protected:
   virtual ~RenderWidgetHostDelegate() {}
 };
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index b83a6a6..2bd19c8 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -954,6 +954,10 @@
   bool width_changed =
       !old_visual_properties_ || old_visual_properties_->new_size.width() !=
                                      visual_properties->new_size.width();
+  bool visible_viewport_size_changed =
+      !old_visual_properties_ ||
+      old_visual_properties_->visible_viewport_size !=
+          visual_properties->visible_viewport_size;
 
   // TODO(jonross): Enable on ChromeOS once blocking mus bugs are fixed:
   // https://crbug.com/920642 https://crbug.com/920006
@@ -995,6 +999,10 @@
         visual_properties->local_surface_id_allocation->local_surface_id()
             .ToString());
     visual_properties_ack_pending_ = needs_ack;
+    if (delegate() && visible_viewport_size_changed) {
+      delegate()->NotifyVisibleViewportSizeChanged(
+          visual_properties->visible_viewport_size);
+    }
     old_visual_properties_.swap(visual_properties);
     sent_visual_properties = true;
   }
@@ -1296,18 +1304,8 @@
 
   bool scroll_update_needs_wrapping = false;
   if (gesture_event.GetType() == blink::WebInputEvent::kGestureScrollBegin) {
-    // When a user starts scrolling while a fling is active, the GSB will arrive
-    // when is_in_gesture_scroll_[gesture_event.SourceDevice()] is still true.
-    // This is because the fling controller defers handling the GFC event
-    // arrived before the GSB and doesn't send a GSE to end the fling; Instead,
-    // it waits for a second GFS to arrive and boost the current active fling if
-    // possible. While GFC handling is deferred the controller suppresses the
-    // GSB and GSU events instead of sending them to the renderer and continues
-    // to progress the fling. So, the renderer doesn't receive two GSB events
-    // without any GSE in between.
-    DCHECK(!is_in_gesture_scroll_[static_cast<int>(
-               gesture_event.SourceDevice())] ||
-           FlingCancellationIsDeferred());
+    DCHECK(
+        !is_in_gesture_scroll_[static_cast<int>(gesture_event.SourceDevice())]);
     is_in_gesture_scroll_[static_cast<int>(gesture_event.SourceDevice())] =
         true;
   } else if (gesture_event.GetType() ==
@@ -3081,10 +3079,6 @@
   input_router_->StopFling();
 }
 
-bool RenderWidgetHostImpl::FlingCancellationIsDeferred() const {
-  return input_router_->FlingCancellationIsDeferred();
-}
-
 void RenderWidgetHostImpl::SetScreenOrientationForTesting(
     uint16_t angle,
     ScreenOrientationValues type) {
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index 77ec094..30f9aee 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -699,7 +699,6 @@
 
   void ProgressFlingIfNeeded(base::TimeTicks current_time);
   void StopFling();
-  bool FlingCancellationIsDeferred() const;
   void SetNeedsBeginFrameForFlingProgress();
 
   // The RenderWidgetHostImpl will keep showing the old page (for a while) after
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index d665ce6..0023fe4 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -2209,11 +2209,13 @@
   view_->OnScrollEvent(&scroll2);
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_TRUE(widget_host_->FlingCancellationIsDeferred());
   events = GetAndResetDispatchedMessages();
-  EXPECT_EQ("MouseWheel", GetMessageNames(events));
+  EXPECT_EQ("MouseWheel GestureScrollEnd MouseWheel", GetMessageNames(events));
   wheel_event = static_cast<const WebMouseWheelEvent*>(
       events[0]->ToEvent()->Event()->web_event.get());
+  EXPECT_EQ(WebMouseWheelEvent::kPhaseEnded, wheel_event->momentum_phase);
+  wheel_event = static_cast<const WebMouseWheelEvent*>(
+      events[2]->ToEvent()->Event()->web_event.get());
   EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, wheel_event->phase);
 }
 
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index 2edb742..6845707 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -560,7 +560,11 @@
   if (!did_update_state)
     return;
 
-  ns_view_->SetTextInputType(GetTextInputType());
+  const TextInputState* state = text_input_manager->GetTextInputState();
+  if (state)
+    ns_view_->SetTextInputState(state->type, state->flags);
+  else
+    ns_view_->SetTextInputState(ui::TEXT_INPUT_TYPE_NONE, 0);
 
   // |updated_view| is the last view to change its TextInputState which can be
   // used to start/stop monitoring composition info when it has a focused
@@ -576,7 +580,6 @@
 
   // Set the monitor state based on the text input focus state.
   const bool has_focus = HasFocus();
-  const TextInputState* state = text_input_manager->GetTextInputState();
   bool need_monitor_composition =
       has_focus && state && state->type != ui::TEXT_INPUT_TYPE_NONE;
 
diff --git a/content/browser/screen_orientation/screen_orientation_provider_unittest.cc b/content/browser/screen_orientation/screen_orientation_provider_unittest.cc
index 2d778f6a6..a4b0c9a 100644
--- a/content/browser/screen_orientation/screen_orientation_provider_unittest.cc
+++ b/content/browser/screen_orientation/screen_orientation_provider_unittest.cc
@@ -71,8 +71,7 @@
     fullscreened_contents_ = nullptr;
   }
 
-  bool IsFullscreenForTabOrPending(
-      const WebContents* web_contents) const override {
+  bool IsFullscreenForTabOrPending(const WebContents* web_contents) override {
     return fullscreened_contents_ && web_contents == fullscreened_contents_;
   }
 
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index c622b33..e1f7339 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -189,15 +189,18 @@
 class BlobURLStoreInterceptor
     : public blink::mojom::BlobURLStoreInterceptorForTesting {
  public:
-  explicit BlobURLStoreInterceptor(GURL target_url) : target_url_(target_url) {}
-
-  void Intercept(
+  static void Intercept(
+      GURL target_url,
       mojo::StrongAssociatedBindingPtr<blink::mojom::BlobURLStore> binding) {
-    url_store_ = binding->SwapImplForTesting(this);
+    auto interceptor =
+        base::WrapUnique(new BlobURLStoreInterceptor(target_url));
+    auto* raw_interceptor = interceptor.get();
+    auto impl = binding->SwapImplForTesting(std::move(interceptor));
+    raw_interceptor->url_store_ = std::move(impl);
   }
 
   blink::mojom::BlobURLStore* GetForwardingInterface() override {
-    return url_store_;
+    return url_store_.get();
   }
 
   void Register(blink::mojom::BlobPtr blob,
@@ -208,7 +211,9 @@
   }
 
  private:
-  blink::mojom::BlobURLStore* url_store_;
+  explicit BlobURLStoreInterceptor(GURL target_url) : target_url_(target_url) {}
+
+  std::unique_ptr<blink::mojom::BlobURLStore> url_store_;
   GURL target_url_;
 };
 
@@ -981,10 +986,9 @@
   // with b.com.
   std::string target_origin = "http://b.com";
   std::string blob_path = "5881f76e-10d2-410d-8c61-ef210502acfd";
-  BlobURLStoreInterceptor interceptor(
-      GURL("blob:" + target_origin + "/" + blob_path));
-  auto intercept_hook = base::BindRepeating(&BlobURLStoreInterceptor::Intercept,
-                                            base::Unretained(&interceptor));
+  auto intercept_hook =
+      base::BindRepeating(&BlobURLStoreInterceptor::Intercept,
+                          GURL("blob:" + target_origin + "/" + blob_path));
   storage::BlobRegistryImpl::SetURLStoreCreationHookForTesting(&intercept_hook);
 
   // Register a blob URL from the a.com main frame, which will go through the
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index b9cb568..8713403 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -1630,6 +1630,12 @@
     GetOuterWebContents()->NotifyNavigationStateChanged(changed_flags);
 }
 
+void WebContentsImpl::NotifyVisibleViewportSizeChanged(
+    const gfx::Size& visible_viewport_size) {
+  SendPageMessage(new PageMsg_UpdatePageVisualProperties(
+      MSG_ROUTING_NONE, visible_viewport_size));
+}
+
 void WebContentsImpl::OnAudioStateChanged() {
   // This notification can come from any embedded contents or from this
   // WebContents' stream monitor. Aggregate these signals to get the actual
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 21b1a8c5..7171fb4a 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -726,6 +726,8 @@
   gfx::Size GetAutoResizeSize() override;
   void ResetAutoResizeSize() override;
   InputEventShim* GetInputEventShim() const override;
+  void NotifyVisibleViewportSizeChanged(
+      const gfx::Size& visible_viewport_size) override;
 
 #if !defined(OS_ANDROID)
   double GetPendingPageZoomLevel() override;
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index 84c80a7f..eba8bdb 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -207,7 +207,7 @@
   }
 
   // WebContentsDelegate:
-  gfx::Size GetSizeForNewRenderView(WebContents* web_contents) const override {
+  gfx::Size GetSizeForNewRenderView(WebContents* web_contents) override {
     gfx::Size size(web_contents->GetContainerBounds().size());
     size.Enlarge(size_insets_.width(), size_insets_.height());
     return size;
@@ -1565,8 +1565,9 @@
   explicit WebDisplayModeDelegate(blink::WebDisplayMode mode) : mode_(mode) { }
   ~WebDisplayModeDelegate() override { }
 
-  blink::WebDisplayMode GetDisplayMode(
-      const WebContents* source) const override { return mode_; }
+  blink::WebDisplayMode GetDisplayMode(const WebContents* source) override {
+    return mode_;
+  }
   void set_mode(blink::WebDisplayMode mode) { mode_ = mode; }
  private:
   blink::WebDisplayMode mode_;
@@ -1964,8 +1965,7 @@
     }
   }
 
-  bool IsFullscreenForTabOrPending(
-      const WebContents* web_contents) const override {
+  bool IsFullscreenForTabOrPending(const WebContents* web_contents) override {
     return is_fullscreen_;
   }
 
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc
index 227e15df..a17f373 100644
--- a/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -332,8 +332,7 @@
     fullscreened_contents_ = nullptr;
   }
 
-  bool IsFullscreenForTabOrPending(
-      const WebContents* web_contents) const override {
+  bool IsFullscreenForTabOrPending(const WebContents* web_contents) override {
     return fullscreened_contents_ && web_contents == fullscreened_contents_;
   }
 
diff --git a/content/browser/webauth/virtual_authenticator.cc b/content/browser/webauth/virtual_authenticator.cc
index 161c25a..67f2e9fe 100644
--- a/content/browser/webauth/virtual_authenticator.cc
+++ b/content/browser/webauth/virtual_authenticator.cc
@@ -28,6 +28,9 @@
       unique_id_(base::GenerateGUID()),
       state_(base::MakeRefCounted<::device::VirtualFidoDevice::State>()) {
   state_->transport = transport;
+  // If the authenticator has user verification, simulate having set it up
+  // already.
+  state_->fingerprints_enrolled = has_user_verification_;
   SetUserPresence(true);
 }
 
@@ -83,6 +86,7 @@
       config.internal_uv_support = has_user_verification_;
       config.is_platform_authenticator =
           attachment_ == ::device::AuthenticatorAttachment::kPlatform;
+      config.user_verification_succeeds = is_user_verified_;
       return std::make_unique<::device::VirtualCtap2Device>(state_, config);
     }
     default:
diff --git a/content/browser/webauth/virtual_authenticator.h b/content/browser/webauth/virtual_authenticator.h
index 3fb8f1f..37668b96 100644
--- a/content/browser/webauth/virtual_authenticator.h
+++ b/content/browser/webauth/virtual_authenticator.h
@@ -55,6 +55,12 @@
   // this authenticator. The default is true.
   void SetUserPresence(bool is_user_present);
 
+  // Sets whether user verification should succeed or not for new requests sent
+  // to this authenticator. Defaults to true.
+  void set_user_verified(bool is_user_verified) {
+    is_user_verified_ = is_user_verified;
+  }
+
   ::device::FidoTransportProtocol transport() const {
     return state_->transport;
   }
@@ -85,6 +91,7 @@
   const ::device::AuthenticatorAttachment attachment_;
   const bool has_resident_key_;
   const bool has_user_verification_;
+  bool is_user_verified_ = true;
   const std::string unique_id_;
   bool is_user_present_;
   scoped_refptr<::device::VirtualFidoDevice::State> state_;
diff --git a/content/browser/webrtc/webrtc_audio_debug_recordings_browsertest.cc b/content/browser/webrtc/webrtc_audio_debug_recordings_browsertest.cc
index 1634e0e3..8ebd2f5 100644
--- a/content/browser/webrtc/webrtc_audio_debug_recordings_browsertest.cc
+++ b/content/browser/webrtc/webrtc_audio_debug_recordings_browsertest.cc
@@ -19,29 +19,20 @@
 #include "media/base/media_switches.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 
-#if defined(OS_WIN)
-#define NumberToStringType base::NumberToString16
-#else
-#define NumberToStringType base::NumberToString
-#endif
-
 namespace {
 
-const int kExpectedConsumerId = 1;
-
-const int kWaveHeaderSizeBytes = 44;
-
-const base::FilePath::CharType kBaseFilename[] =
-    FILE_PATH_LITERAL("audio_debug");
+constexpr int kExpectedConsumerId = 1;
+constexpr int kWaveHeaderSizeBytes = 44;
+constexpr char kBaseFilename[] = "audio_debug";
 
 // Get the expected AEC dump file name. The name will be
 // <temporary path>.<render process id>.aec_dump.<consumer id>, for example
 // "/tmp/.com.google.Chrome.Z6UC3P.12345.aec_dump.1".
 base::FilePath GetExpectedAecDumpFileName(const base::FilePath& base_file_path,
-                                          int render_process_id) {
-  return base_file_path.AddExtension(NumberToStringType(render_process_id))
-      .AddExtension(FILE_PATH_LITERAL("aec_dump"))
-      .AddExtension(NumberToStringType(kExpectedConsumerId));
+                                          int renderer_pid) {
+  return base_file_path.AddExtensionASCII(base::NumberToString(renderer_pid))
+      .AddExtensionASCII("aec_dump")
+      .AddExtensionASCII(base::NumberToString(kExpectedConsumerId));
 }
 
 // Get the file names of the recordings. The name will be
@@ -134,7 +125,7 @@
   base::FilePath temp_dir_path;
   ASSERT_TRUE(
       CreateNewTempDirectory(base::FilePath::StringType(), &temp_dir_path));
-  base::FilePath base_file_path = temp_dir_path.Append(kBaseFilename);
+  base::FilePath base_file_path = temp_dir_path.AppendASCII(kBaseFilename);
 
   // This fakes the behavior of another open tab with webrtc-internals, and
   // enabling audio debug recordings in that tab.
@@ -220,7 +211,7 @@
   base::FilePath temp_dir_path;
   ASSERT_TRUE(
       CreateNewTempDirectory(base::FilePath::StringType(), &temp_dir_path));
-  base::FilePath base_file_path = temp_dir_path.Append(kBaseFilename);
+  base::FilePath base_file_path = temp_dir_path.AppendASCII(kBaseFilename);
 
   // This fakes the behavior of another open tab with webrtc-internals, and
   // enabling audio debug recordings in that tab, then disabling it.
@@ -273,7 +264,7 @@
   base::FilePath temp_dir_path;
   ASSERT_TRUE(
       CreateNewTempDirectory(base::FilePath::StringType(), &temp_dir_path));
-  base::FilePath base_file_path = temp_dir_path.Append(kBaseFilename);
+  base::FilePath base_file_path = temp_dir_path.AppendASCII(kBaseFilename);
 
   // This fakes the behavior of another open tab with webrtc-internals, and
   // enabling audio debug recordings in that tab.
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index dde9fcb..462d40d03 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -177,7 +177,6 @@
     "mac/attributed_string_coder.mm",
     "mac/font_loader.h",
     "mac/font_loader.mm",
-    "media/aec_dump_messages.h",
     "media/cdm_info.cc",
     "media/media_player_delegate_messages.h",
     "media/peer_connection_tracker_messages.h",
@@ -480,6 +479,7 @@
     "input/input_handler.mojom",
     "input/input_injector.mojom",
     "input/synchronous_compositor.mojom",
+    "media/aec_dump.mojom",
     "media/peer_connection_tracker.mojom",
     "media/renderer_audio_input_stream_factory.mojom",
     "media/renderer_audio_output_stream_factory.mojom",
diff --git a/content/common/content_message_generator.h b/content/common/content_message_generator.h
index 7f555c0..27534ba 100644
--- a/content/common/content_message_generator.h
+++ b/content/common/content_message_generator.h
@@ -41,11 +41,6 @@
 #ifndef CONTENT_COMMON_INPUT_MESSAGES_H_
 #error "Failed to include content/common/input_messages.h"
 #endif
-#undef CONTENT_COMMON_MEDIA_AEC_DUMP_MESSAGES_H_
-#include "content/common/media/aec_dump_messages.h"
-#ifndef CONTENT_COMMON_MEDIA_AEC_DUMP_MESSAGES_H_
-#error "Failed to include content/common/media/aec_dump_messages.h"
-#endif
 #undef CONTENT_COMMON_MEDIA_MEDIA_PLAYER_DELEGATE_MESSAGES_H_
 #include "content/common/media/media_player_delegate_messages.h"
 #ifndef CONTENT_COMMON_MEDIA_MEDIA_PLAYER_DELEGATE_MESSAGES_H_
diff --git a/content/common/input/gesture_event_stream_validator.cc b/content/common/input/gesture_event_stream_validator.cc
index 52b6082..00748c2 100644
--- a/content/common/input/gesture_event_stream_validator.cc
+++ b/content/common/input/gesture_event_stream_validator.cc
@@ -23,7 +23,6 @@
 
 bool GestureEventStreamValidator::Validate(
     const blink::WebGestureEvent& event,
-    const bool fling_cancellation_is_deferred,
     std::string* error_msg) {
   DCHECK(error_msg);
   error_msg->clear();
@@ -33,7 +32,7 @@
   }
   switch (event.GetType()) {
     case WebInputEvent::kGestureScrollBegin:
-      if (scrolling_ && !fling_cancellation_is_deferred)
+      if (scrolling_)
         error_msg->append("Scroll begin during scroll\n");
       if (pinching_)
         error_msg->append("Scroll begin during pinch\n");
@@ -114,10 +113,4 @@
   return error_msg->empty();
 }
 
-bool GestureEventStreamValidator::Validate(const blink::WebGestureEvent& event,
-                                           std::string* error_msg) {
-  return Validate(event, /* fling_cancellation_is_deferred = */ false,
-                  error_msg);
-}
-
 }  // namespace content
diff --git a/content/common/input/gesture_event_stream_validator.h b/content/common/input/gesture_event_stream_validator.h
index 49303e1..5d8ae8f3 100644
--- a/content/common/input/gesture_event_stream_validator.h
+++ b/content/common/input/gesture_event_stream_validator.h
@@ -24,9 +24,6 @@
 
   // If |event| is valid for the current stream, returns true.
   // Otherwise, returns false with a corresponding error message.
-  bool Validate(const blink::WebGestureEvent& event,
-                const bool fling_cancellation_is_deferred,
-                std::string* error_msg);
   bool Validate(const blink::WebGestureEvent& event, std::string* error_msg);
 
  private:
diff --git a/content/common/input/input_event_stream_validator.cc b/content/common/input/input_event_stream_validator.cc
index 237a333..731aa1f4 100644
--- a/content/common/input/input_event_stream_validator.cc
+++ b/content/common/input/input_event_stream_validator.cc
@@ -25,28 +25,24 @@
 InputEventStreamValidator::~InputEventStreamValidator() {
 }
 
-void InputEventStreamValidator::Validate(
-    const WebInputEvent& event,
-    const bool fling_cancellation_is_deferred /* = false */) {
+void InputEventStreamValidator::Validate(const WebInputEvent& event) {
   if (!enabled_)
     return;
 
-  DCHECK(ValidateImpl(event, fling_cancellation_is_deferred, &error_msg_))
+  DCHECK(ValidateImpl(event, &error_msg_))
       << error_msg_
       << "\nInvalid Event: " << ui::WebInputEventTraits::ToString(event);
 }
 
 bool InputEventStreamValidator::ValidateImpl(
     const blink::WebInputEvent& event,
-    const bool fling_cancellation_is_deferred,
     std::string* error_msg) {
   DCHECK(error_msg);
   if (WebInputEvent::IsGestureEventType(event.GetType())) {
     const WebGestureEvent& gesture = static_cast<const WebGestureEvent&>(event);
     // TODO(jdduke): Validate touchpad gesture streams.
     if (gesture.SourceDevice() == blink::WebGestureDevice::kTouchscreen)
-      return gesture_validator_.Validate(
-          gesture, fling_cancellation_is_deferred, error_msg);
+      return gesture_validator_.Validate(gesture, error_msg);
   } else if (WebInputEvent::IsTouchEventType(event.GetType())) {
     const WebTouchEvent& touch = static_cast<const WebTouchEvent&>(event);
     return touch_validator_.Validate(touch, error_msg);
diff --git a/content/common/input/input_event_stream_validator.h b/content/common/input/input_event_stream_validator.h
index 7bf2238e..6bf8625 100644
--- a/content/common/input/input_event_stream_validator.h
+++ b/content/common/input/input_event_stream_validator.h
@@ -24,12 +24,10 @@
   InputEventStreamValidator();
   ~InputEventStreamValidator();
 
-  void Validate(const blink::WebInputEvent&,
-                const bool fling_cancellation_is_deferred = false);
+  void Validate(const blink::WebInputEvent&);
 
  private:
   bool ValidateImpl(const blink::WebInputEvent&,
-                    const bool fling_cancellation_is_deferred,
                     std::string* error_msg);
 
   GestureEventStreamValidator gesture_validator_;
diff --git a/content/common/media/aec_dump.mojom b/content/common/media/aec_dump.mojom
new file mode 100644
index 0000000..24fe459
--- /dev/null
+++ b/content/common/media/aec_dump.mojom
@@ -0,0 +1,19 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module content.mojom;
+
+import "mojo/public/mojom/base/file.mojom";
+
+// Interface used to start / stop writing out an AEC dump from a child process.
+interface AecDumpAgent {
+  Start(mojo_base.mojom.File file);
+  Stop();
+};
+
+// Interface used to register child processes that can generate AEC dump files.
+interface AecDumpManager {
+  // Register the provided |agent| until disconnected.
+  Add(pending_remote<AecDumpAgent> agent);
+};
diff --git a/content/common/media/aec_dump_messages.h b/content/common/media/aec_dump_messages.h
deleted file mode 100644
index fc84743..0000000
--- a/content/common/media/aec_dump_messages.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_MEDIA_AEC_DUMP_MESSAGES_H_
-#define CONTENT_COMMON_MEDIA_AEC_DUMP_MESSAGES_H_
-
-// IPC messages for the AEC dump.
-
-#include "content/common/content_export.h"
-#include "ipc/ipc_message_macros.h"
-#include "ipc/ipc_platform_file.h"
-
-#undef IPC_MESSAGE_EXPORT
-#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
-#define IPC_MESSAGE_START AecDumpMsgStart
-
-// Messages sent from the browser to the renderer.
-
-// The browser hands over a file handle to the consumer in the renderer
-// identified by |id| to use for AEC dump.
-IPC_MESSAGE_CONTROL2(AecDumpMsg_EnableAecDump,
-                     int /* id */,
-                     IPC::PlatformFileForTransit /* file_handle */)
-
-// Tell the renderer to disable AEC dump in all consumers.
-IPC_MESSAGE_CONTROL0(AecDumpMsg_DisableAecDump)
-
-// Messages sent from the renderer to the browser.
-
-// Registers a consumer with the browser. The consumer will then get a file
-// handle when the dump is enabled.
-IPC_MESSAGE_CONTROL1(AecDumpMsg_RegisterAecDumpConsumer,
-                     int /* id */)
-
-// Unregisters a consumer with the browser.
-IPC_MESSAGE_CONTROL1(AecDumpMsg_UnregisterAecDumpConsumer,
-                     int /* id */)
-
-#endif  // CONTENT_COMMON_MEDIA_AEC_DUMP_MESSAGES_H_
diff --git a/content/common/page_messages.h b/content/common/page_messages.h
index 164b769..1693ebc 100644
--- a/content/common/page_messages.h
+++ b/content/common/page_messages.h
@@ -40,6 +40,11 @@
 IPC_MESSAGE_ROUTED1(PageMsg_UpdateScreenInfo,
                     content::ScreenInfo /* screen_info */)
 
+// Sent to renderers with remote main frames when page-related visual properties
+// change.
+IPC_MESSAGE_ROUTED1(PageMsg_UpdatePageVisualProperties,
+                    gfx::Size /* VisualViewport size */)
+
 // Sent to all renderers, instructing them to freeze or unfreeze all frames that
 // belongs to this page.
 IPC_MESSAGE_ROUTED1(PageMsg_SetPageFrozen, bool /* frozen */)
diff --git a/content/common/render_widget_host_ns_view.mojom b/content/common/render_widget_host_ns_view.mojom
index 2c70decc..1a11dd4 100644
--- a/content/common/render_widget_host_ns_view.mojom
+++ b/content/common/render_widget_host_ns_view.mojom
@@ -50,8 +50,8 @@
   // Call the -[NSView setToolTipAtMousePoint] method.
   SetTooltipText(mojo_base.mojom.String16 display_text);
 
-  // Forward changes in ui::TextInputType.
-  SetTextInputType(ui.mojom.TextInputType text_input_type);
+  // Forward changes in content::TextInputState.
+  SetTextInputState(ui.mojom.TextInputType text_input_type, uint32 flags);
 
   // Forward the TextInputManager::TextSelection from the renderer.
   SetTextSelection(mojo_base.mojom.String16 text,
diff --git a/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java b/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
index 7c5eb8f..6bc5ba2 100644
--- a/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/selection/SelectionPopupControllerImpl.java
@@ -18,7 +18,6 @@
 import android.graphics.Rect;
 import android.os.Build;
 import android.provider.Browser;
-import android.provider.Settings;
 import android.support.annotation.Nullable;
 import android.text.Spanned;
 import android.text.TextUtils;
@@ -363,13 +362,7 @@
         mUnselectAllOnDismiss = true;
 
         if (hasSelection()) {
-            // Device is not provisioned, don't trigger SelectionClient logic at all.
-            boolean blockSelectionClient = !isDeviceProvisioned();
-
-            // Disable SelectionClient logic if it's incognito.
-            blockSelectionClient |= isIncognito();
-
-            if (!blockSelectionClient && mSelectionMetricsLogger != null) {
+            if (mSelectionMetricsLogger != null) {
                 switch (sourceType) {
                     case MenuSourceType.MENU_SOURCE_ADJUST_SELECTION:
                         mSelectionMetricsLogger.logSelectionModified(
@@ -389,15 +382,14 @@
             }
 
             // From selection adjustment, show menu directly.
-            if (!blockSelectionClient
-                    && sourceType == MenuSourceType.MENU_SOURCE_ADJUST_SELECTION) {
+            // Note that this won't happen if it is incognito mode or device is not provisioned.
+            if (sourceType == MenuSourceType.MENU_SOURCE_ADJUST_SELECTION) {
                 showActionModeOrClearOnFailure();
                 return;
             }
 
-            // Show menu if we need to block SelectionClient or there is no updates from
-            // SelectionClient.
-            if (blockSelectionClient || mSelectionClient == null
+            // Show menu there is no updates from SelectionClient.
+            if (mSelectionClient == null
                     || !mSelectionClient.requestSelectionPopupUpdates(shouldSuggest)) {
                 showActionModeOrClearOnFailure();
             }
@@ -1567,14 +1559,6 @@
         return client == null ? null : client.getCustomTextClassifier();
     }
 
-    @VisibleForTesting
-    public boolean isDeviceProvisioned() {
-        if (mContext == null || mContext.getContentResolver() == null) return true;
-        return Settings.Global.getInt(
-                       mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0)
-                != 0;
-    }
-
     @CalledByNative
     private void nativeSelectionPopupControllerDestroyed() {
         mNativeSelectionPopupController = 0;
diff --git a/content/public/android/java/src/org/chromium/content/browser/selection/SmartSelectionClient.java b/content/public/android/java/src/org/chromium/content/browser/selection/SmartSelectionClient.java
index 5bfa07e..b9cff45 100644
--- a/content/public/android/java/src/org/chromium/content/browser/selection/SmartSelectionClient.java
+++ b/content/public/android/java/src/org/chromium/content/browser/selection/SmartSelectionClient.java
@@ -4,7 +4,9 @@
 
 package org.chromium.content.browser.selection;
 
+import android.content.Context;
 import android.os.Build;
+import android.provider.Settings;
 import android.support.annotation.IntDef;
 import android.text.TextUtils;
 import android.view.textclassifier.TextClassifier;
@@ -56,6 +58,10 @@
         WindowAndroid windowAndroid = webContents.getTopLevelNativeWindow();
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O || windowAndroid == null) return null;
 
+        // Don't do Smart Selection when device is not provisioned or in incognito mode.
+        if (!isDeviceProvisioned(windowAndroid.getContext().get()) || webContents.isIncognito())
+            return null;
+
         return new SmartSelectionClient(callback, webContents, windowAndroid);
     }
 
@@ -154,6 +160,15 @@
         }
     }
 
+    private static boolean isDeviceProvisioned(Context context) {
+        if (context == null || context.getContentResolver() == null) return true;
+        // Returns false when device is not provisioned, i.e. before a new device went through
+        // signup process.
+        return Settings.Global.getInt(
+                       context.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0)
+                != 0;
+    }
+
     private boolean textHasValidSelection(String text, int start, int end) {
         return !TextUtils.isEmpty(text) && 0 <= start && start < end && end <= text.length();
     }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentTextSelectionTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentTextSelectionTest.java
index c1d0ce4..8d3500b 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/ContentTextSelectionTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/ContentTextSelectionTest.java
@@ -20,7 +20,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import org.chromium.base.Log;
 import org.chromium.base.task.PostTask;
 import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.DisabledTest;
@@ -46,8 +45,6 @@
  */
 @RunWith(ContentJUnit4ClassRunner.class)
 public class ContentTextSelectionTest {
-    private static final String TAG = "ContentTextSelTest";
-
     @Rule
     public ContentShellActivityTestRule mActivityTestRule = new ContentShellActivityTestRule();
     private static final String DATA_URL = UrlUtils.encodeHtmlDataUri(
@@ -378,9 +375,6 @@
 
         mSelectionPopupController.setSelectionClient(client);
 
-        // TODO(crbug.com/967811): Remove logs once we confirmed the assumpution.
-        Log.d(TAG, "isIncognito = " + mWebContents.isIncognito());
-        Log.d(TAG, "isDeviceProvisioned = " + mSelectionPopupController.isDeviceProvisioned());
         DOMUtils.longPressNode(mWebContents, "smart_selection");
         waitForSelectActionBarVisible(true);
 
@@ -396,7 +390,6 @@
     @Test
     @MediumTest
     @Feature({"TextInput", "SmartSelection"})
-    @DisabledTest(message = "https://crbug.com/973865")
     public void testSmartSelectionReset() throws Throwable {
         SelectionClient.Result result = new SelectionClient.Result();
         result.startAdjust = -5;
@@ -409,9 +402,6 @@
 
         mSelectionPopupController.setSelectionClient(client);
 
-        // TODO(crbug.com/967811): Remove logs once we confirmed the assumpution.
-        Log.d(TAG, "isIncognito = " + mWebContents.isIncognito());
-        Log.d(TAG, "isDeviceProvisioned = " + mSelectionPopupController.isDeviceProvisioned());
         DOMUtils.longPressNode(mWebContents, "smart_selection");
         waitForSelectActionBarVisible(true);
 
diff --git a/content/public/android/junit/src/org/chromium/content/browser/selection/SelectionPopupControllerTest.java b/content/public/android/junit/src/org/chromium/content/browser/selection/SelectionPopupControllerTest.java
index 03aab70..ee65947 100644
--- a/content/public/android/junit/src/org/chromium/content/browser/selection/SelectionPopupControllerTest.java
+++ b/content/public/android/junit/src/org/chromium/content/browser/selection/SelectionPopupControllerTest.java
@@ -6,9 +6,9 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
@@ -21,6 +21,7 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.os.Build;
 import android.provider.Settings;
 import android.view.ActionMode;
 import android.view.ViewGroup;
@@ -51,6 +52,8 @@
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.ui.touch_selection.SelectionEventType;
 
+import java.lang.ref.WeakReference;
+
 /**
  * Unit tests for {@link SelectionPopupController}.
  */
@@ -59,6 +62,7 @@
 public class SelectionPopupControllerTest {
     private SelectionPopupControllerImpl mController;
     private Context mContext;
+    private WeakReference<Context> mWeakContext;
     private WindowAndroid mWindowAndroid;
     private WebContentsImpl mWebContents;
     private ViewGroup mView;
@@ -131,6 +135,7 @@
         ShadowLog.stream = System.out;
 
         mContext = Mockito.mock(Context.class);
+        mWeakContext = new WeakReference<Context>(mContext);
         mWindowAndroid = Mockito.mock(WindowAndroid.class);
         mWebContents = Mockito.mock(WebContentsImpl.class);
         mView = Mockito.mock(ViewGroup.class);
@@ -161,6 +166,7 @@
         when(mWebContents.getContext()).thenReturn(mContext);
         when(mWebContents.getTopLevelNativeWindow()).thenReturn(mWindowAndroid);
         when(mGestureStateListenerManager.isScrollInProgress()).thenReturn(false);
+        when(mWindowAndroid.getContext()).thenReturn(mWeakContext);
 
         mController = SelectionPopupControllerImpl.createForTesting(mWebContents, mPopupController);
         when(mController.getGestureListenerManager()).thenReturn(mGestureStateListenerManager);
@@ -443,43 +449,23 @@
     }
 
     @Test
+    @Config(sdk = Build.VERSION_CODES.O)
     @Feature({"TextInput", "SmartSelection"})
     public void testBlockSelectionClientWhenUnprovisioned() {
         // Device is not provisioned.
         Settings.Global.putInt(mContentResolver, Settings.Global.DEVICE_PROVISIONED, 0);
 
-        TestSelectionClient client = Mockito.mock(TestSelectionClient.class);
-        InOrder order = inOrder(mLogger, client);
-        mController.setSelectionClient(client);
-
-        // Long press triggered showSelectionMenu() call.
-        mController.showSelectionMenu(0, 0, 0, 0, 0, /* isEditable = */ true,
-                /* isPasswordType = */ false, AMPHITHEATRE, /* selectionOffset = */ 5,
-                /* canSelectAll = */ true,
-                /* canRichlyEdit = */ true, /* shouldSuggest = */ true,
-                MenuSourceType.MENU_SOURCE_LONG_PRESS);
-        order.verify(mLogger, never()).logSelectionStarted(anyString(), anyInt(), anyBoolean());
-        order.verify(client, never()).requestSelectionPopupUpdates(anyBoolean());
+        assertNull(SmartSelectionClient.create(mController.getResultCallback(), mWebContents));
     }
 
     @Test
+    @Config(sdk = Build.VERSION_CODES.O)
     @Feature({"TextInput", "SmartSelection"})
     public void testBlockSelectionClientWhenIncognito() {
         // Incognito.
         when(mWebContents.isIncognito()).thenReturn(true);
 
-        TestSelectionClient client = Mockito.mock(TestSelectionClient.class);
-        InOrder order = inOrder(mLogger, client);
-        mController.setSelectionClient(client);
-
-        // Long press triggered showSelectionMenu() call.
-        mController.showSelectionMenu(0, 0, 0, 0, 0, /* isEditable = */ true,
-                /* isPasswordType = */ false, AMPHITHEATRE, /* selectionOffset = */ 5,
-                /* canSelectAll = */ true,
-                /* canRichlyEdit = */ true, /* shouldSuggest = */ true,
-                MenuSourceType.MENU_SOURCE_LONG_PRESS);
-        order.verify(mLogger, never()).logSelectionStarted(anyString(), anyInt(), anyBoolean());
-        order.verify(client, never()).requestSelectionPopupUpdates(anyBoolean());
+        assertNull(SmartSelectionClient.create(mController.getResultCallback(), mWebContents));
     }
 
     @Test
diff --git a/content/public/app/content_browser_manifest.cc b/content/public/app/content_browser_manifest.cc
index f53c440..c36f884c 100644
--- a/content/public/app/content_browser_manifest.cc
+++ b/content/public/app/content_browser_manifest.cc
@@ -71,6 +71,7 @@
                   "blink.mojom.ReportingServiceProxy",
                   "blink.mojom.StoragePartitionService",
                   "blink.mojom.WebDatabaseHost",
+                  "content.mojom.AecDumpManager",
                   "content.mojom.ClipboardHost",
                   "content.mojom.FieldTrialRecorder",
                   "content.mojom.FrameSinkProvider",
diff --git a/content/public/browser/browser_plugin_guest_delegate.cc b/content/public/browser/browser_plugin_guest_delegate.cc
index b7ff8c5..28a429f 100644
--- a/content/public/browser/browser_plugin_guest_delegate.cc
+++ b/content/public/browser/browser_plugin_guest_delegate.cc
@@ -12,7 +12,7 @@
   return nullptr;
 }
 
-WebContents* BrowserPluginGuestDelegate::GetOwnerWebContents() const {
+WebContents* BrowserPluginGuestDelegate::GetOwnerWebContents() {
   return nullptr;
 }
 
@@ -32,7 +32,7 @@
   return nullptr;
 }
 
-RenderFrameHost* BrowserPluginGuestDelegate::GetEmbedderFrame() const {
+RenderFrameHost* BrowserPluginGuestDelegate::GetEmbedderFrame() {
   NOTREACHED();
   return nullptr;
 }
diff --git a/content/public/browser/browser_plugin_guest_delegate.h b/content/public/browser/browser_plugin_guest_delegate.h
index b7db83c..ea12af6b 100644
--- a/content/public/browser/browser_plugin_guest_delegate.h
+++ b/content/public/browser/browser_plugin_guest_delegate.h
@@ -55,7 +55,7 @@
   virtual void ElementSizeChanged(const gfx::Size& size) {}
 
   // Returns the WebContents that currently owns this guest.
-  virtual WebContents* GetOwnerWebContents() const;
+  virtual WebContents* GetOwnerWebContents();
 
   // Asks the delegate if the given guest can lock the pointer.
   // Invoking the |callback| synchronously is OK.
@@ -84,7 +84,7 @@
   virtual bool CanBeEmbeddedInsideCrossProcessFrames();
 
   // Returns the embedder frame for this guest.
-  virtual RenderFrameHost* GetEmbedderFrame() const;
+  virtual RenderFrameHost* GetEmbedderFrame();
 };
 
 }  // namespace content
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index 04faf010..514fddc 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -99,7 +99,7 @@
   return true;
 }
 
-bool ContentBrowserClient::ShouldUseMobileFlingCurve() const {
+bool ContentBrowserClient::ShouldUseMobileFlingCurve() {
   return false;
 }
 
@@ -152,7 +152,7 @@
   GetAdditionalWebUISchemes(additional_schemes);
 }
 
-bool ContentBrowserClient::LogWebUIUrl(const GURL& web_ui_url) const {
+bool ContentBrowserClient::LogWebUIUrl(const GURL& web_ui_url) {
   return false;
 }
 
@@ -678,7 +678,7 @@
 }
 
 base::string16 ContentBrowserClient::GetAppContainerSidForSandboxType(
-    int sandbox_type) const {
+    int sandbox_type) {
   // Embedders should override this method and return different SIDs for each
   // sandbox type. Note: All content level tests will run child processes in the
   // same AppContainer.
@@ -942,19 +942,19 @@
   return content::PREVIEWS_OFF;
 }
 
-std::string ContentBrowserClient::GetProduct() const {
+std::string ContentBrowserClient::GetProduct() {
   return std::string();
 }
 
-std::string ContentBrowserClient::GetUserAgent() const {
+std::string ContentBrowserClient::GetUserAgent() {
   return std::string();
 }
 
-blink::UserAgentMetadata ContentBrowserClient::GetUserAgentMetadata() const {
+blink::UserAgentMetadata ContentBrowserClient::GetUserAgentMetadata() {
   return blink::UserAgentMetadata();
 }
 
-base::Optional<gfx::ImageSkia> ContentBrowserClient::GetProductLogo() const {
+base::Optional<gfx::ImageSkia> ContentBrowserClient::GetProductLogo() {
   return base::nullopt;
 }
 
@@ -976,7 +976,7 @@
 
 #if defined(OS_ANDROID)
 ContentBrowserClient::WideColorGamutHeuristic
-ContentBrowserClient::GetWideColorGamutHeuristic() const {
+ContentBrowserClient::GetWideColorGamutHeuristic() {
   return WideColorGamutHeuristic::kNone;
 }
 #endif
@@ -991,18 +991,18 @@
     const WebContents* web_contents,
     const RenderFrameHost* frame_host,
     bool user_gesture,
-    NavigationDownloadPolicy* download_policy) const {}
+    NavigationDownloadPolicy* download_policy) {}
 
 bool ContentBrowserClient::IsBluetoothScanningBlocked(
     content::BrowserContext* browser_context,
     const url::Origin& requesting_origin,
-    const url::Origin& embedding_origin) const {
+    const url::Origin& embedding_origin) {
   return false;
 }
 
 void ContentBrowserClient::BlockBluetoothScanning(
     content::BrowserContext* browser_context,
     const url::Origin& requesting_origin,
-    const url::Origin& embedding_origin) const {}
+    const url::Origin& embedding_origin) {}
 
 }  // namespace content
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index 34b4fd3..b4fa038 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -284,7 +284,7 @@
 
   // Returns whether gesture fling events should use the mobile-behavior gesture
   // curve for scrolling.
-  virtual bool ShouldUseMobileFlingCurve() const;
+  virtual bool ShouldUseMobileFlingCurve();
 
   // Returns whether all instances of the specified effective URL should be
   // rendered by the same process, rather than using process-per-site-instance.
@@ -376,7 +376,7 @@
   // Called when WebUI objects are created to get aggregate usage data (i.e. is
   // chrome://downloads used more than chrome://bookmarks?). Only internal (e.g.
   // chrome://) URLs are logged. Returns whether the URL was actually logged.
-  virtual bool LogWebUIUrl(const GURL& web_ui_url) const;
+  virtual bool LogWebUIUrl(const GURL& web_ui_url);
 
   // http://crbug.com/829412
   // Renderers with WebUI bindings shouldn't make http(s) requests for security
@@ -1146,8 +1146,7 @@
   // Returns the AppContainer SID for the specified sandboxed process type, or
   // empty string if this sandboxed process type does not support living inside
   // an AppContainer.
-  virtual base::string16 GetAppContainerSidForSandboxType(
-      int sandbox_type) const;
+  virtual base::string16 GetAppContainerSidForSandboxType(int sandbox_type);
 #endif
 
   // Binds a new media remoter service to |request|, if supported by the
@@ -1530,17 +1529,17 @@
   // Returns a string describing the embedder product name and version,
   // of the form "productname/version", with no other slashes.
   // Used as part of the user agent string.
-  virtual std::string GetProduct() const;
+  virtual std::string GetProduct();
 
   // Returns the user agent.  Content may cache this value.
-  virtual std::string GetUserAgent() const;
+  virtual std::string GetUserAgent();
 
   // Returns user agent metadata. Content may cache this value.
-  virtual blink::UserAgentMetadata GetUserAgentMetadata() const;
+  virtual blink::UserAgentMetadata GetUserAgentMetadata();
 
   // Returns a 256x256 transparent background image of the product logo, i.e.
   // the browser icon, if available.
-  virtual base::Optional<gfx::ImageSkia> GetProductLogo() const;
+  virtual base::Optional<gfx::ImageSkia> GetProductLogo();
 
   // Returns whether |origin| should be considered a integral component similar
   // to native code, and as such whether its log messages should be recorded.
@@ -1566,7 +1565,7 @@
   };
 
   // Returns kNone by default.
-  virtual WideColorGamutHeuristic GetWideColorGamutHeuristic() const;
+  virtual WideColorGamutHeuristic GetWideColorGamutHeuristic();
 #endif
 
   // Obtains the list of MIME types that are for plugins with external handlers.
@@ -1579,19 +1578,18 @@
       const WebContents* web_contents,
       const RenderFrameHost* frame_host,
       bool user_gesture,
-      NavigationDownloadPolicy* download_policy) const;
+      NavigationDownloadPolicy* download_policy);
 
   // Returns whether a site is blocked to use Bluetooth scanning API.
   virtual bool IsBluetoothScanningBlocked(
       content::BrowserContext* browser_context,
       const url::Origin& requesting_origin,
-      const url::Origin& embedding_origin) const;
+      const url::Origin& embedding_origin);
 
   // Blocks a site to use Bluetooth scanning API.
-  virtual void BlockBluetoothScanning(
-      content::BrowserContext* browser_context,
-      const url::Origin& requesting_origin,
-      const url::Origin& embedding_origin) const;
+  virtual void BlockBluetoothScanning(content::BrowserContext* browser_context,
+                                      const url::Origin& requesting_origin,
+                                      const url::Origin& embedding_origin);
 };
 
 }  // namespace content
diff --git a/content/public/browser/download_manager_delegate.cc b/content/public/browser/download_manager_delegate.cc
index 5c85ac4..17a484b5 100644
--- a/content/public/browser/download_manager_delegate.cc
+++ b/content/public/browser/download_manager_delegate.cc
@@ -53,8 +53,7 @@
   return true;
 }
 
-std::string
-DownloadManagerDelegate::ApplicationClientIdForFileScanning() const {
+std::string DownloadManagerDelegate::ApplicationClientIdForFileScanning() {
   return std::string();
 }
 
diff --git a/content/public/browser/download_manager_delegate.h b/content/public/browser/download_manager_delegate.h
index 3db1c15..fb283bb 100644
--- a/content/public/browser/download_manager_delegate.h
+++ b/content/public/browser/download_manager_delegate.h
@@ -181,7 +181,7 @@
   // performed manually without passing the download to the system AV function.
   //
   // This GUID is only used on Windows.
-  virtual std::string ApplicationClientIdForFileScanning() const;
+  virtual std::string ApplicationClientIdForFileScanning();
 
   // Checks whether download is allowed to continue. |check_download_allowed_cb|
   // is called with the decision on completion.
diff --git a/content/public/browser/interstitial_page_delegate.cc b/content/public/browser/interstitial_page_delegate.cc
index 60a4418..b61905a 100644
--- a/content/public/browser/interstitial_page_delegate.cc
+++ b/content/public/browser/interstitial_page_delegate.cc
@@ -5,8 +5,7 @@
 #include "content/public/browser/interstitial_page_delegate.h"
 
 namespace content {
-InterstitialPageDelegate::TypeID InterstitialPageDelegate::GetTypeForTesting()
-    const {
+InterstitialPageDelegate::TypeID InterstitialPageDelegate::GetTypeForTesting() {
   return nullptr;
 }
 
diff --git a/content/public/browser/interstitial_page_delegate.h b/content/public/browser/interstitial_page_delegate.h
index 346fa1f..3b3a3b7c 100644
--- a/content/public/browser/interstitial_page_delegate.h
+++ b/content/public/browser/interstitial_page_delegate.h
@@ -53,7 +53,7 @@
   }
 
   // Return the interstitial type for testing.
-  virtual TypeID GetTypeForTesting() const;
+  virtual TypeID GetTypeForTesting();
 };
 
 }  // namespace content
diff --git a/content/public/browser/web_contents_delegate.cc b/content/public/browser/web_contents_delegate.cc
index 1f20105..9f74a1a 100644
--- a/content/public/browser/web_contents_delegate.cc
+++ b/content/public/browser/web_contents_delegate.cc
@@ -36,7 +36,9 @@
   return true;
 }
 
-bool WebContentsDelegate::CanOverscrollContent() const { return false; }
+bool WebContentsDelegate::CanOverscrollContent() {
+  return false;
+}
 
 bool WebContentsDelegate::ShouldSuppressDialogs(WebContents* source) {
   return false;
@@ -151,17 +153,17 @@
   return nullptr;
 }
 
-bool WebContentsDelegate::EmbedsFullscreenWidget() const {
+bool WebContentsDelegate::EmbedsFullscreenWidget() {
   return false;
 }
 
 bool WebContentsDelegate::IsFullscreenForTabOrPending(
-    const WebContents* web_contents) const {
+    const WebContents* web_contents) {
   return false;
 }
 
 blink::WebDisplayMode WebContentsDelegate::GetDisplayMode(
-    const WebContents* web_contents) const {
+    const WebContents* web_contents) {
   return blink::kWebDisplayModeBrowser;
 }
 
@@ -245,7 +247,7 @@
 }
 
 gfx::Size WebContentsDelegate::GetSizeForNewRenderView(
-    WebContents* web_contents) const {
+    WebContents* web_contents) {
   return gfx::Size();
 }
 
@@ -275,16 +277,16 @@
   return allowed_per_prefs;
 }
 
-int WebContentsDelegate::GetTopControlsHeight() const {
+int WebContentsDelegate::GetTopControlsHeight() {
   return 0;
 }
 
-int WebContentsDelegate::GetBottomControlsHeight() const {
+int WebContentsDelegate::GetBottomControlsHeight() {
   return 0;
 }
 
 bool WebContentsDelegate::DoBrowserControlsShrinkRendererSize(
-    const WebContents* web_contents) const {
+    const WebContents* web_contents) {
   return false;
 }
 
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h
index 1a9bc7c..ec0252d 100644
--- a/content/public/browser/web_contents_delegate.h
+++ b/content/public/browser/web_contents_delegate.h
@@ -188,7 +188,7 @@
 
   // Called to determine if the WebContents can be overscrolled with touch/wheel
   // gestures.
-  virtual bool CanOverscrollContent() const;
+  virtual bool CanOverscrollContent();
 
   // Invoked prior to showing before unload handler confirmation dialog.
   virtual void WillRunBeforeUnloadConfirm() {}
@@ -417,7 +417,7 @@
   // render widget.  In this case, the delegate may access the widget by calling
   // WebContents::GetFullscreenRenderWidgetHostView().  If false is returned,
   // WebContents will be responsible for showing the fullscreen widget.
-  virtual bool EmbedsFullscreenWidget() const;
+  virtual bool EmbedsFullscreenWidget();
 
   // Called when the renderer puts a tab into fullscreen mode.
   // |origin| is the origin of the initiating frame inside the |web_contents|.
@@ -431,16 +431,14 @@
   // Called when the renderer puts a tab out of fullscreen mode.
   virtual void ExitFullscreenModeForTab(WebContents*) {}
 
-  virtual bool IsFullscreenForTabOrPending(
-      const WebContents* web_contents) const;
+  virtual bool IsFullscreenForTabOrPending(const WebContents* web_contents);
 
   // Returns the actual display mode of the top-level browsing context.
   // For example, it should return 'blink::WebDisplayModeFullscreen' whenever
   // the browser window is put to fullscreen mode (either by the end user,
   // or HTML API or from a web manifest setting).
   // See http://w3c.github.io/manifest/#dfn-display-mode
-  virtual blink::WebDisplayMode GetDisplayMode(
-      const WebContents* web_contents) const;
+  virtual blink::WebDisplayMode GetDisplayMode(const WebContents* web_contents);
 
   // Register a new handler for URL requests with the given scheme.
   // |user_gesture| is true if the registration is made in the context of a user
@@ -552,7 +550,7 @@
   // This is optional for implementations of WebContentsDelegate; if the
   // delegate doesn't provide a size, the current WebContentsView's size will be
   // used.
-  virtual gfx::Size GetSizeForNewRenderView(WebContents* web_contents) const;
+  virtual gfx::Size GetSizeForNewRenderView(WebContents* web_contents);
 
   // Returns true if the WebContents is never visible.
   virtual bool IsNeverVisible(WebContents* web_contents);
@@ -598,10 +596,10 @@
   // Note that they are not complete in the sense that there is no API to tell
   // content to poll these values again, except part of resize. But this is not
   // needed by embedder because it's always accompanied by view size change.
-  virtual int GetTopControlsHeight() const;
-  virtual int GetBottomControlsHeight() const;
+  virtual int GetTopControlsHeight();
+  virtual int GetBottomControlsHeight();
   virtual bool DoBrowserControlsShrinkRendererSize(
-      const WebContents* web_contents) const;
+      const WebContents* web_contents);
 
   // Propagates to the browser that gesture scrolling has changed state. This is
   // used by the browser to assist in controlling the behavior of sliding the
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
index 6e77b42b..f691411 100644
--- a/content/renderer/BUILD.gn
+++ b/content/renderer/BUILD.gn
@@ -200,8 +200,8 @@
     "media/renderer_webaudiodevice_impl.h",
     "media/renderer_webmediaplayer_delegate.cc",
     "media/renderer_webmediaplayer_delegate.h",
-    "media/stream/aec_dump_message_filter.cc",
-    "media/stream/aec_dump_message_filter.h",
+    "media/stream/aec_dump_agent_impl.cc",
+    "media/stream/aec_dump_agent_impl.h",
     "media/stream/apply_constraints_processor.cc",
     "media/stream/apply_constraints_processor.h",
     "media/stream/audio_service_audio_processor_proxy.cc",
diff --git a/content/renderer/media/stream/aec_dump_agent_impl.cc b/content/renderer/media/stream/aec_dump_agent_impl.cc
new file mode 100644
index 0000000..5b80a8e
--- /dev/null
+++ b/content/renderer/media/stream/aec_dump_agent_impl.cc
@@ -0,0 +1,46 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/stream/aec_dump_agent_impl.h"
+
+#include "content/public/child/child_thread.h"
+#include "content/public/common/service_names.mojom.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "services/service_manager/public/cpp/connector.h"
+
+namespace content {
+
+// static
+std::unique_ptr<AecDumpAgentImpl> AecDumpAgentImpl::Create(Delegate* delegate) {
+  if (!ChildThread::Get())  // Can be true in unit tests.
+    return nullptr;
+
+  mojo::Remote<mojom::AecDumpManager> manager;
+  ChildThread::Get()->GetConnector()->Connect(
+      mojom::kBrowserServiceName, manager.BindNewPipeAndPassReceiver());
+
+  mojo::PendingRemote<AecDumpAgent> remote;
+  auto receiver = remote.InitWithNewPipeAndPassReceiver();
+
+  manager->Add(std::move(remote));
+
+  return base::WrapUnique(new AecDumpAgentImpl(delegate, std::move(receiver)));
+}
+
+AecDumpAgentImpl::AecDumpAgentImpl(
+    Delegate* delegate,
+    mojo::PendingReceiver<mojom::AecDumpAgent> receiver)
+    : delegate_(delegate), receiver_(this, std::move(receiver)) {}
+
+AecDumpAgentImpl::~AecDumpAgentImpl() = default;
+
+void AecDumpAgentImpl::Start(base::File dump_file) {
+  delegate_->OnStartDump(std::move(dump_file));
+}
+
+void AecDumpAgentImpl::Stop() {
+  delegate_->OnStopDump();
+}
+
+}  // namespace content
diff --git a/content/renderer/media/stream/aec_dump_agent_impl.h b/content/renderer/media/stream/aec_dump_agent_impl.h
new file mode 100644
index 0000000..fd04eab
--- /dev/null
+++ b/content/renderer/media/stream/aec_dump_agent_impl.h
@@ -0,0 +1,46 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_STREAM_AEC_DUMP_AGENT_IMPL_H_
+#define CONTENT_RENDERER_MEDIA_STREAM_AEC_DUMP_AGENT_IMPL_H_
+
+#include "base/macros.h"
+#include "content/common/media/aec_dump.mojom.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+
+namespace content {
+
+// An instance of this class connects to the browser process to register for
+// notifications to start / stop writing to a dump file.
+class AecDumpAgentImpl : public mojom::AecDumpAgent {
+ public:
+  class Delegate {
+   public:
+    virtual void OnStartDump(base::File file) = 0;
+    virtual void OnStopDump() = 0;
+  };
+
+  // This may fail in unit tests, in which case a null object is returned.
+  static std::unique_ptr<AecDumpAgentImpl> Create(Delegate* delegate);
+
+  ~AecDumpAgentImpl() override;
+
+  // AecDumpAgent methods:
+  void Start(base::File dump_file) override;
+  void Stop() override;
+
+ private:
+  explicit AecDumpAgentImpl(
+      Delegate* delegate,
+      mojo::PendingReceiver<mojom::AecDumpAgent> receiver);
+
+  Delegate* delegate_;
+  mojo::Receiver<mojom::AecDumpAgent> receiver_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(AecDumpAgentImpl);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_MEDIA_STREAM_AEC_DUMP_AGENT_IMPL_H_
diff --git a/content/renderer/media/stream/aec_dump_message_filter.cc b/content/renderer/media/stream/aec_dump_message_filter.cc
deleted file mode 100644
index 469cb91..0000000
--- a/content/renderer/media/stream/aec_dump_message_filter.cc
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/stream/aec_dump_message_filter.h"
-
-#include "base/bind.h"
-#include "base/single_thread_task_runner.h"
-#include "content/common/media/aec_dump_messages.h"
-#include "content/renderer/media/webrtc_logging.h"
-#include "ipc/ipc_logging.h"
-#include "ipc/ipc_sender.h"
-
-namespace {
-const int kInvalidDelegateId = -1;
-}
-
-namespace content {
-
-AecDumpMessageFilter* AecDumpMessageFilter::g_filter = nullptr;
-
-AecDumpMessageFilter::AecDumpMessageFilter(
-    const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
-    const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner)
-    : sender_(nullptr),
-      delegate_id_counter_(1),
-      io_task_runner_(io_task_runner),
-      main_task_runner_(main_task_runner) {
-  DCHECK(!g_filter);
-  g_filter = this;
-}
-
-AecDumpMessageFilter::~AecDumpMessageFilter() {
-  DCHECK_EQ(g_filter, this);
-  g_filter = nullptr;
-}
-
-// static
-scoped_refptr<AecDumpMessageFilter> AecDumpMessageFilter::Get() {
-  return g_filter;
-}
-
-void AecDumpMessageFilter::AddDelegate(
-    AecDumpMessageFilter::AecDumpDelegate* delegate) {
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-  DCHECK(delegate);
-  DCHECK_EQ(kInvalidDelegateId, GetIdForDelegate(delegate));
-
-  int id = delegate_id_counter_++;
-  delegates_[id] = delegate;
-
-  io_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&AecDumpMessageFilter::RegisterAecDumpConsumer, this, id));
-}
-
-void AecDumpMessageFilter::RemoveDelegate(
-    AecDumpMessageFilter::AecDumpDelegate* delegate) {
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-  DCHECK(delegate);
-
-  int id = GetIdForDelegate(delegate);
-  DCHECK_NE(kInvalidDelegateId, id);
-  delegates_.erase(id);
-
-  io_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&AecDumpMessageFilter::UnregisterAecDumpConsumer, this,
-                     id));
-}
-
-void AecDumpMessageFilter::Send(IPC::Message* message) {
-  DCHECK(io_task_runner_->BelongsToCurrentThread());
-  if (sender_)
-    sender_->Send(message);
-  else
-    delete message;
-}
-
-void AecDumpMessageFilter::RegisterAecDumpConsumer(int id) {
-  Send(new AecDumpMsg_RegisterAecDumpConsumer(id));
-}
-
-void AecDumpMessageFilter::UnregisterAecDumpConsumer(int id) {
-  Send(new AecDumpMsg_UnregisterAecDumpConsumer(id));
-}
-
-bool AecDumpMessageFilter::OnMessageReceived(const IPC::Message& message) {
-  DCHECK(io_task_runner_->BelongsToCurrentThread());
-  bool handled = true;
-  IPC_BEGIN_MESSAGE_MAP(AecDumpMessageFilter, message)
-    IPC_MESSAGE_HANDLER(AecDumpMsg_EnableAecDump, OnEnableAecDump)
-    IPC_MESSAGE_HANDLER(AecDumpMsg_DisableAecDump, OnDisableAecDump)
-    IPC_MESSAGE_UNHANDLED(handled = false)
-  IPC_END_MESSAGE_MAP()
-  return handled;
-}
-
-void AecDumpMessageFilter::OnFilterAdded(IPC::Channel* channel) {
-  DCHECK(io_task_runner_->BelongsToCurrentThread());
-  sender_ = channel;
-}
-
-void AecDumpMessageFilter::OnFilterRemoved() {
-  DCHECK(io_task_runner_->BelongsToCurrentThread());
-
-  // Once removed, a filter will not be used again.  At this time the
-  // observer must be notified so it releases its reference.
-  OnChannelClosing();
-}
-
-void AecDumpMessageFilter::OnChannelClosing() {
-  DCHECK(io_task_runner_->BelongsToCurrentThread());
-  sender_ = nullptr;
-  main_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&AecDumpMessageFilter::DoChannelClosingOnDelegates, this));
-}
-
-void AecDumpMessageFilter::OnEnableAecDump(
-    int id,
-    IPC::PlatformFileForTransit file_handle) {
-  DCHECK(io_task_runner_->BelongsToCurrentThread());
-  main_task_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&AecDumpMessageFilter::DoEnableAecDump, this,
-                                id, file_handle));
-}
-
-void AecDumpMessageFilter::OnDisableAecDump() {
-  DCHECK(io_task_runner_->BelongsToCurrentThread());
-  main_task_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&AecDumpMessageFilter::DoDisableAecDump, this));
-}
-
-void AecDumpMessageFilter::DoEnableAecDump(
-    int id,
-    IPC::PlatformFileForTransit file_handle) {
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-  auto it = delegates_.find(id);
-  if (it != delegates_.end()) {
-    it->second->OnAecDumpFile(file_handle);
-  } else {
-    // Delegate has been removed, we must close the file.
-    base::File file = IPC::PlatformFileForTransitToFile(file_handle);
-    DCHECK(file.IsValid());
-    file.Close();
-  }
-}
-
-void AecDumpMessageFilter::DoDisableAecDump() {
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-  for (auto it = delegates_.begin(); it != delegates_.end(); ++it) {
-    it->second->OnDisableAecDump();
-  }
-}
-
-void AecDumpMessageFilter::DoChannelClosingOnDelegates() {
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-  for (auto it = delegates_.begin(); it != delegates_.end(); ++it) {
-    it->second->OnIpcClosing();
-  }
-  delegates_.clear();
-}
-
-int AecDumpMessageFilter::GetIdForDelegate(
-    AecDumpMessageFilter::AecDumpDelegate* delegate) {
-  DCHECK(main_task_runner_->BelongsToCurrentThread());
-  for (auto it = delegates_.begin(); it != delegates_.end(); ++it) {
-    if (it->second == delegate)
-      return it->first;
-  }
-  return kInvalidDelegateId;
-}
-
-}  // namespace content
diff --git a/content/renderer/media/stream/aec_dump_message_filter.h b/content/renderer/media/stream/aec_dump_message_filter.h
deleted file mode 100644
index 4c340d0..0000000
--- a/content/renderer/media/stream/aec_dump_message_filter.h
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_MEDIA_STREAM_AEC_DUMP_MESSAGE_FILTER_H_
-#define CONTENT_RENDERER_MEDIA_STREAM_AEC_DUMP_MESSAGE_FILTER_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/optional.h"
-#include "content/common/content_export.h"
-#include "content/renderer/render_thread_impl.h"
-#include "ipc/ipc_platform_file.h"
-#include "ipc/message_filter.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace content {
-
-// MessageFilter that handles AEC dump messages and forwards them to an
-// observer.
-class CONTENT_EXPORT AecDumpMessageFilter : public IPC::MessageFilter {
- public:
-  class AecDumpDelegate {
-   public:
-    virtual void OnAecDumpFile(
-        const IPC::PlatformFileForTransit& file_handle) = 0;
-    virtual void OnDisableAecDump() = 0;
-    virtual void OnIpcClosing() = 0;
-  };
-
-  AecDumpMessageFilter(
-      const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
-      const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner);
-
-  // Getter for the one AecDumpMessageFilter object.
-  static scoped_refptr<AecDumpMessageFilter> Get();
-
-  // Adds a delegate that receives the enable and disable notifications. Must be
-  // called on the main task runner (|main_task_runner| in constructor). All
-  // calls on |delegate| are done on the main task runner.
-  void AddDelegate(AecDumpMessageFilter::AecDumpDelegate* delegate);
-
-  // Removes a delegate. Must be called on the main task runner
-  // (|main_task_runner| in constructor).
-  void RemoveDelegate(AecDumpMessageFilter::AecDumpDelegate* delegate);
-
-  // IO task runner associated with this message filter.
-  scoped_refptr<base::SingleThreadTaskRunner> io_task_runner() const {
-    return io_task_runner_;
-  }
-
- protected:
-  ~AecDumpMessageFilter() override;
-
- private:
-  // Sends an IPC message using |sender_|.
-  void Send(IPC::Message* message);
-
-  // Registers a consumer of AEC dump in the browser process. This consumer will
-  // get a file handle when the AEC dump is enabled and a notification when it
-  // is disabled.
-  void RegisterAecDumpConsumer(int id);
-
-  // Unregisters a consumer of AEC dump in the browser process.
-  void UnregisterAecDumpConsumer(int id);
-
-  // IPC::MessageFilter override. Called on |io_task_runner|.
-  bool OnMessageReceived(const IPC::Message& message) override;
-  void OnFilterAdded(IPC::Channel* channel) override;
-  void OnFilterRemoved() override;
-  void OnChannelClosing() override;
-
-  // Accessed on |io_task_runner_|.
-  void OnEnableAecDump(int id, IPC::PlatformFileForTransit file_handle);
-  void OnDisableAecDump();
-
-  // Accessed on |main_task_runner_|.
-  void DoEnableAecDump(int id, IPC::PlatformFileForTransit file_handle);
-  void DoDisableAecDump();
-  void DoChannelClosingOnDelegates();
-  int GetIdForDelegate(AecDumpMessageFilter::AecDumpDelegate* delegate);
-
-  // Accessed on |io_task_runner_|.
-  IPC::Sender* sender_;
-
-  // The delgates for this filter. Must only be accessed on
-  // |main_task_runner_|.
-  using DelegateMap = std::map<int, AecDumpMessageFilter::AecDumpDelegate*>;
-  DelegateMap delegates_;
-
-  // Counter for generating unique IDs to delegates. Accessed on
-  // |main_task_runner_|.
-  int delegate_id_counter_;
-
-  // Task runner which IPC calls are executed.
-  const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
-
-  // Main task runner.
-  const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
-
-  // The singleton instance for this filter.
-  static AecDumpMessageFilter* g_filter;
-
-  DISALLOW_COPY_AND_ASSIGN(AecDumpMessageFilter);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_RENDERER_MEDIA_STREAM_AEC_DUMP_MESSAGE_FILTER_H_
diff --git a/content/renderer/media/stream/audio_service_audio_processor_proxy.cc b/content/renderer/media/stream/audio_service_audio_processor_proxy.cc
index dd66e79..a17ed83 100644
--- a/content/renderer/media/stream/audio_service_audio_processor_proxy.cc
+++ b/content/renderer/media/stream/audio_service_audio_processor_proxy.cc
@@ -31,7 +31,6 @@
     scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner)
     : main_thread_runner_(std::move(main_thread_task_runner)),
       target_stats_interval_(kMaxStatsInterval),
-      aec_dump_message_filter_(AecDumpMessageFilter::Get()),
       weak_ptr_factory_(this) {
   DCHECK(main_thread_runner_->BelongsToCurrentThread());
 }
@@ -44,10 +43,7 @@
 void AudioServiceAudioProcessorProxy::Stop() {
   DCHECK(main_thread_runner_->BelongsToCurrentThread());
 
-  if (aec_dump_message_filter_.get()) {
-    aec_dump_message_filter_->RemoveDelegate(this);
-    aec_dump_message_filter_ = nullptr;
-  }
+  aec_dump_agent_impl_.reset();
 
   if (processor_controls_) {
     processor_controls_->StopEchoCancellationDump();
@@ -57,33 +53,25 @@
   stats_update_timer_.Stop();
 }
 
-void AudioServiceAudioProcessorProxy::OnAecDumpFile(
-    const IPC::PlatformFileForTransit& file_handle) {
+void AudioServiceAudioProcessorProxy::OnStartDump(base::File dump_file) {
   DCHECK(main_thread_runner_->BelongsToCurrentThread());
-  base::File file = IPC::PlatformFileForTransitToFile(file_handle);
-  DCHECK(file.IsValid());
+  DCHECK(dump_file.IsValid());
   if (processor_controls_) {
-    processor_controls_->StartEchoCancellationDump(std::move(file));
+    processor_controls_->StartEchoCancellationDump(std::move(dump_file));
   } else {
     // Post the file close to avoid blocking the main thread.
     base::PostTaskWithTraits(
         FROM_HERE, {base::TaskPriority::LOWEST, base::MayBlock()},
-        base::BindOnce([](base::File) {}, std::move(file)));
+        base::BindOnce([](base::File) {}, std::move(dump_file)));
   }
 }
 
-void AudioServiceAudioProcessorProxy::OnDisableAecDump() {
+void AudioServiceAudioProcessorProxy::OnStopDump() {
   DCHECK(main_thread_runner_->BelongsToCurrentThread());
   if (processor_controls_)
     processor_controls_->StopEchoCancellationDump();
 }
 
-void AudioServiceAudioProcessorProxy::OnIpcClosing() {
-  DCHECK(main_thread_runner_->BelongsToCurrentThread());
-  aec_dump_message_filter_->RemoveDelegate(this);
-  aec_dump_message_filter_ = nullptr;
-}
-
 void AudioServiceAudioProcessorProxy::SetControls(
     media::AudioProcessorControls* controls) {
   DCHECK(main_thread_runner_->BelongsToCurrentThread());
@@ -96,11 +84,9 @@
   last_stats_request_time_ = base::TimeTicks::Now();
   stats_update_timer_.SetTaskRunner(main_thread_runner_);
   RescheduleStatsUpdateTimer(target_stats_interval_);
-  // In unit tests not creating a message filter, |aec_dump_message_filter_|
-  // will be null. We can just ignore that. Other unit tests and browser tests
-  // ensure that we do get the filter when we should.
-  if (aec_dump_message_filter_)
-    aec_dump_message_filter_->AddDelegate(this);
+
+  // Can be null in unit tests. That's okay.
+  aec_dump_agent_impl_ = AecDumpAgentImpl::Create(this);
 }
 
 webrtc::AudioProcessorInterface::AudioProcessorStatistics
diff --git a/content/renderer/media/stream/audio_service_audio_processor_proxy.h b/content/renderer/media/stream/audio_service_audio_processor_proxy.h
index 4fed003..2e2b5ac 100644
--- a/content/renderer/media/stream/audio_service_audio_processor_proxy.h
+++ b/content/renderer/media/stream/audio_service_audio_processor_proxy.h
@@ -14,7 +14,7 @@
 #include "base/threading/thread_checker.h"
 #include "base/timer/timer.h"
 #include "content/common/content_export.h"
-#include "content/renderer/media/stream/aec_dump_message_filter.h"
+#include "content/renderer/media/stream/aec_dump_agent_impl.h"
 #include "media/base/audio_processing.h"
 #include "media/webrtc/audio_processor_controls.h"
 #include "third_party/webrtc/api/media_stream_interface.h"
@@ -31,7 +31,7 @@
 // calculation code should be encapsulated in a class.
 class CONTENT_EXPORT AudioServiceAudioProcessorProxy
     : public webrtc::AudioProcessorInterface,
-      public AecDumpMessageFilter::AecDumpDelegate {
+      public AecDumpAgentImpl::Delegate {
  public:
   // All methods (including constructor and destructor) must be called on the
   // main thread except for GetStats.
@@ -45,11 +45,10 @@
   // This method is called on the libjingle thread.
   AudioProcessorStatistics GetStats(bool has_remote_tracks) override;
 
-  // AecDumpMessageFilter::AecDumpDelegate implementation.
+  // AecDumpAgentImpl::Delegate implementation.
   // Called on the main render thread.
-  void OnAecDumpFile(const IPC::PlatformFileForTransit& file_handle) override;
-  void OnDisableAecDump() override;
-  void OnIpcClosing() override;
+  void OnStartDump(base::File file) override;
+  void OnStopDump() override;
 
   // Set the AudioProcessorControls which to proxy to. Must only be called once
   // and |controls| cannot be nullptr.
@@ -78,7 +77,7 @@
   AudioProcessorStatistics latest_stats_ = {};
 
   // Communication with browser for AEC dump.
-  scoped_refptr<AecDumpMessageFilter> aec_dump_message_filter_;
+  std::unique_ptr<AecDumpAgentImpl> aec_dump_agent_impl_;
 
   base::WeakPtrFactory<AudioServiceAudioProcessorProxy> weak_ptr_factory_;
 
diff --git a/content/renderer/media/stream/media_stream_audio_processor.cc b/content/renderer/media/stream/media_stream_audio_processor.cc
index 4f99d26b..05603d0 100644
--- a/content/renderer/media/stream/media_stream_audio_processor.cc
+++ b/content/renderer/media/stream/media_stream_audio_processor.cc
@@ -21,6 +21,8 @@
 #include "base/optional.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
@@ -276,19 +278,13 @@
       main_thread_runner_(base::ThreadTaskRunnerHandle::Get()),
       audio_mirroring_(false),
       typing_detected_(false),
-      aec_dump_message_filter_(AecDumpMessageFilter::Get()),
+      aec_dump_agent_impl_(AecDumpAgentImpl::Create(this)),
       stopped_(false) {
   DCHECK(main_thread_runner_);
   DETACH_FROM_THREAD(capture_thread_checker_);
   DETACH_FROM_THREAD(render_thread_checker_);
 
   InitializeAudioProcessingModule(properties);
-
-  // In unit tests not creating a message filter, |aec_dump_message_filter_|
-  // will be null. We can just ignore that. Other unit tests and browser tests
-  // ensure that we do get the filter when we should.
-  if (aec_dump_message_filter_.get())
-    aec_dump_message_filter_->AddDelegate(this);
 }
 
 MediaStreamAudioProcessor::~MediaStreamAudioProcessor() {
@@ -369,10 +365,7 @@
 
   stopped_ = true;
 
-  if (aec_dump_message_filter_.get()) {
-    aec_dump_message_filter_->RemoveDelegate(this);
-    aec_dump_message_filter_ = nullptr;
-  }
+  aec_dump_agent_impl_.reset();
 
   if (!audio_processing_.get())
     return;
@@ -394,12 +387,10 @@
   return output_format_;
 }
 
-void MediaStreamAudioProcessor::OnAecDumpFile(
-    const IPC::PlatformFileForTransit& file_handle) {
+void MediaStreamAudioProcessor::OnStartDump(base::File dump_file) {
   DCHECK(main_thread_runner_->BelongsToCurrentThread());
 
-  base::File file = IPC::PlatformFileForTransitToFile(file_handle);
-  DCHECK(file.IsValid());
+  DCHECK(dump_file.IsValid());
 
   if (audio_processing_) {
     if (!worker_queue_) {
@@ -409,14 +400,17 @@
     // Here tasks will be posted on the |worker_queue_|. It must be
     // kept alive until StopEchoCancellationDump is called or the
     // webrtc::AudioProcessing instance is destroyed.
-    blink::StartEchoCancellationDump(audio_processing_.get(), std::move(file),
-                                     worker_queue_.get());
+    blink::StartEchoCancellationDump(audio_processing_.get(),
+                                     std::move(dump_file), worker_queue_.get());
   } else {
-    file.Close();
+    // Post the file close to avoid blocking the main thread.
+    base::PostTaskWithTraits(
+        FROM_HERE, {base::TaskPriority::LOWEST, base::MayBlock()},
+        base::BindOnce([](base::File) {}, std::move(dump_file)));
   }
 }
 
-void MediaStreamAudioProcessor::OnDisableAecDump() {
+void MediaStreamAudioProcessor::OnStopDump() {
   DCHECK(main_thread_runner_->BelongsToCurrentThread());
   if (audio_processing_)
     blink::StopEchoCancellationDump(audio_processing_.get());
@@ -426,11 +420,6 @@
   worker_queue_.reset(nullptr);
 }
 
-void MediaStreamAudioProcessor::OnIpcClosing() {
-  DCHECK(main_thread_runner_->BelongsToCurrentThread());
-  aec_dump_message_filter_ = nullptr;
-}
-
 // static
 bool MediaStreamAudioProcessor::WouldModifyAudio(
     const blink::AudioProcessingProperties& properties) {
diff --git a/content/renderer/media/stream/media_stream_audio_processor.h b/content/renderer/media/stream/media_stream_audio_processor.h
index dc200497..04da8552 100644
--- a/content/renderer/media/stream/media_stream_audio_processor.h
+++ b/content/renderer/media/stream/media_stream_audio_processor.h
@@ -18,7 +18,7 @@
 #include "base/threading/thread_checker.h"
 #include "base/time/time.h"
 #include "content/common/content_export.h"
-#include "content/renderer/media/stream/aec_dump_message_filter.h"
+#include "content/renderer/media/stream/aec_dump_agent_impl.h"
 #include "content/renderer/media/webrtc/webrtc_audio_device_impl.h"
 #include "media/base/audio_converter.h"
 #include "media/webrtc/audio_delay_stats_reporter.h"
@@ -51,7 +51,7 @@
 class CONTENT_EXPORT MediaStreamAudioProcessor
     : public WebRtcPlayoutDataSource::Sink,
       public AudioProcessorInterface,
-      public AecDumpMessageFilter::AecDumpDelegate {
+      public AecDumpAgentImpl::Delegate {
  public:
   // |playout_data_source| is used to register this class as a sink to the
   // WebRtc playout data for processing AEC. If clients do not enable AEC,
@@ -105,11 +105,10 @@
   // Accessor to check if the audio processing is enabled or not.
   bool has_audio_processing() const { return audio_processing_ != NULL; }
 
-  // AecDumpMessageFilter::AecDumpDelegate implementation.
+  // AecDumpAgentImpl::Delegate implementation.
   // Called on the main render thread.
-  void OnAecDumpFile(const IPC::PlatformFileForTransit& file_handle) override;
-  void OnDisableAecDump() override;
-  void OnIpcClosing() override;
+  void OnStartDump(base::File dump_file) override;
+  void OnStopDump() override;
 
   // Returns true if MediaStreamAudioProcessor would modify the audio signal,
   // based on |properties|. If the audio signal would not be modified, there is
@@ -205,7 +204,7 @@
   base::subtle::Atomic32 typing_detected_;
 
   // Communication with browser for AEC dump.
-  scoped_refptr<AecDumpMessageFilter> aec_dump_message_filter_;
+  std::unique_ptr<AecDumpAgentImpl> aec_dump_agent_impl_;
 
   // Flag to avoid executing Stop() more than once.
   bool stopped_;
diff --git a/content/renderer/media/stream/media_stream_audio_processor_unittest.cc b/content/renderer/media/stream/media_stream_audio_processor_unittest.cc
index 2e3e8d6a..5d878dc1 100644
--- a/content/renderer/media/stream/media_stream_audio_processor_unittest.cc
+++ b/content/renderer/media/stream/media_stream_audio_processor_unittest.cc
@@ -276,29 +276,6 @@
   audio_processor->Stop();
 }
 
-// Test that if we have an AEC dump message filter created, we are getting it
-// correctly in MSAP. Any IPC messages will be deleted since no sender in the
-// filter will be created.
-TEST_F(MediaStreamAudioProcessorTest, GetAecDumpMessageFilter) {
-  scoped_refptr<AecDumpMessageFilter> aec_dump_message_filter_(
-      new AecDumpMessageFilter(
-          blink::scheduler::GetSingleThreadTaskRunnerForTesting(),
-          blink::scheduler::GetSingleThreadTaskRunnerForTesting()));
-
-  scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
-      new rtc::RefCountedObject<WebRtcAudioDeviceImpl>());
-  blink::AudioProcessingProperties properties;
-  scoped_refptr<MediaStreamAudioProcessor> audio_processor(
-      new rtc::RefCountedObject<MediaStreamAudioProcessor>(
-          properties, webrtc_audio_device.get()));
-
-  EXPECT_TRUE(audio_processor->aec_dump_message_filter_.get());
-
-  // Stop |audio_processor| so that it removes itself from
-  // |webrtc_audio_device| and clears its pointer to it.
-  audio_processor->Stop();
-}
-
 TEST_F(MediaStreamAudioProcessorTest, StartStopAecDump) {
   scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
       new rtc::RefCountedObject<WebRtcAudioDeviceImpl>());
@@ -315,13 +292,13 @@
             properties, webrtc_audio_device.get()));
 
     // Start and stop recording.
-    audio_processor->OnAecDumpFile(IPC::TakePlatformFileForTransit(base::File(
-        temp_file_path, base::File::FLAG_WRITE | base::File::FLAG_OPEN)));
-    audio_processor->OnDisableAecDump();
+    audio_processor->OnStartDump(base::File(
+        temp_file_path, base::File::FLAG_WRITE | base::File::FLAG_OPEN));
+    audio_processor->OnStopDump();
 
     // Start and wait for d-tor.
-    audio_processor->OnAecDumpFile(IPC::TakePlatformFileForTransit(base::File(
-        temp_file_path, base::File::FLAG_WRITE | base::File::FLAG_OPEN)));
+    audio_processor->OnStartDump(base::File(
+        temp_file_path, base::File::FLAG_WRITE | base::File::FLAG_OPEN));
   }
 
   // Check that dump file is non-empty after audio processor has been
diff --git a/content/renderer/render_frame_impl_browsertest.cc b/content/renderer/render_frame_impl_browsertest.cc
index 872e21a..88f1661b 100644
--- a/content/renderer/render_frame_impl_browsertest.cc
+++ b/content/renderer/render_frame_impl_browsertest.cc
@@ -218,11 +218,19 @@
   visual_properties.is_fullscreen_granted = false;
 
   WidgetMsg_SynchronizeVisualProperties resize_message(0, visual_properties);
-  frame_widget()->OnMessageReceived(resize_message);
 
-  EXPECT_EQ(frame_widget()->GetWebWidget()->Size(), blink::WebSize(size));
+  // The main frame's widget will receive the resize message before the
+  // subframe's widget, and it will set the size for the WebView.
+  RenderWidget* main_frame_widget =
+      GetMainRenderFrame()->GetLocalRootRenderWidget();
+  main_frame_widget->OnMessageReceived(resize_message);
   EXPECT_EQ(view_->GetWebView()->MainFrameWidget()->Size(),
             blink::WebSize(size));
+  EXPECT_NE(frame_widget()->GetWebWidget()->Size(), blink::WebSize(size));
+
+  // The subframe sets the size only for itself.
+  frame_widget()->OnMessageReceived(resize_message);
+  EXPECT_EQ(frame_widget()->GetWebWidget()->Size(), blink::WebSize(size));
 }
 
 // Verify a subframe RenderWidget properly processes a WasShown message.
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 476c27d..a1ceab0 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -89,7 +89,6 @@
 #include "content/renderer/media/audio/audio_renderer_mixer_manager.h"
 #include "content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h"
 #include "content/renderer/media/render_media_client.h"
-#include "content/renderer/media/stream/aec_dump_message_filter.h"
 #include "content/renderer/media/stream/media_stream_center.h"
 #include "content/renderer/media/video_capture/video_capture_impl_manager.h"
 #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
@@ -756,11 +755,6 @@
   peer_connection_factory_.reset(
       new PeerConnectionDependencyFactory(p2p_socket_dispatcher_.get()));
 
-  aec_dump_message_filter_ =
-      new AecDumpMessageFilter(GetIOTaskRunner(), main_thread_runner());
-
-  AddFilter(aec_dump_message_filter_.get());
-
   unfreezable_message_filter_ = new UnfreezableMessageFilter(this);
   AddFilter(unfreezable_message_filter_.get());
 
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 90c62a7..649f7a6 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -112,7 +112,6 @@
 }  // namespace viz
 
 namespace content {
-class AecDumpMessageFilter;
 class AudioRendererMixerManager;
 class BrowserPluginManager;
 class CategorizedWorkerPool;
@@ -593,12 +592,6 @@
   // Dispatches all P2P sockets.
   scoped_refptr<P2PSocketDispatcher> p2p_socket_dispatcher_;
 
-  // Used for communicating registering AEC dump consumers with the browser and
-  // receving AEC dump file handles when AEC dump is enabled. An AEC dump is
-  // diagnostic audio data for WebRTC stored locally when enabled by the user in
-  // chrome://webrtc-internals.
-  scoped_refptr<AecDumpMessageFilter> aec_dump_message_filter_;
-
   // Filter out unfreezable messages and pass it to unfreezable task runners.
   scoped_refptr<UnfreezableMessageFilter> unfreezable_message_filter_;
 
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 2c5b3cc..dae2f5a0 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -1291,6 +1291,8 @@
                         OnSetHistoryOffsetAndLength)
     IPC_MESSAGE_HANDLER(PageMsg_AudioStateChanged, OnAudioStateChanged)
     IPC_MESSAGE_HANDLER(PageMsg_UpdateScreenInfo, OnUpdateScreenInfo)
+    IPC_MESSAGE_HANDLER(PageMsg_UpdatePageVisualProperties,
+                        OnUpdatePageVisualProperties)
     IPC_MESSAGE_HANDLER(PageMsg_SetPageFrozen, SetPageFrozen)
     IPC_MESSAGE_HANDLER(PageMsg_UpdateTextAutosizerPageInfoForRemoteMainFrames,
                         OnTextAutosizerPageInfoChanged)
@@ -2038,6 +2040,45 @@
     GetWidget()->set_screen_info(screen_info);
 }
 
+void RenderViewImpl::OnUpdatePageVisualProperties(
+    const gfx::Size& viewport_size) {
+  // Using this pathway to update the visual viewport should only happen for
+  // remote main frames. Local main frames will update the viewport size by
+  // RenderWidget calling RenderViewImpl::ResizeVisualViewport() directly.
+  if (!main_render_frame_) {
+    // Since the viewport size comes directly from the browser, we may
+    // need to adjust it for device scale factor.
+    // TODO(wjmaclean): we should look into having the browser apply this scale
+    // before sending the viewport size.
+    gfx::Size device_scale_factor_scaled_visual_viewport_size = viewport_size;
+    if (RenderThreadImpl::current()->IsUseZoomForDSFEnabled()) {
+      device_scale_factor_scaled_visual_viewport_size = gfx::ScaleToCeiledSize(
+          viewport_size, GetScreenInfo().device_scale_factor);
+    }
+    // TODO(wjmaclean): At present this makes use of the WebWidget part of
+    // WebViewImpl in order to be able to re-size the view
+    // without having to plumb through the browser-controls state. When
+    // WebViewImpl is no longer a WebWidget, then we'll need to plumb these
+    // values as well. At that time, presumably WebViewImpl::Resize() will
+    // also have migrated to the WebView API. https://crbug.com/419087
+    // Note: If WebViewImpl stops having any widget association when the
+    // main frame is remote, then this should be replaced with a direct call to
+    // webview()->ResizeVisualViewport().
+    webview()->MainFrameWidget()->Resize(
+        device_scale_factor_scaled_visual_viewport_size);
+  }
+}
+
+void RenderViewImpl::ResizeVisualViewportForWidget(
+    const gfx::Size& scaled_viewport_size) {
+  // This function is currently only called for local main frames. Once remote
+  // main frames no longer have a RenderWidget, they may also route through
+  // here via RenderViewImpl::OnUpdatePageVisualProperties(). In that case,
+  // WebViewImpl will need to implement its Size() function based on something
+  // other than the widget size.
+  webview()->ResizeVisualViewport(scaled_viewport_size);
+}
+
 void RenderViewImpl::SetPageFrozen(bool frozen) {
   if (webview())
     webview()->SetPageFrozen(frozen);
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index c8828c1..62c511d 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -405,6 +405,8 @@
   void SetScreenMetricsEmulationParametersForWidget(
       bool enabled,
       const blink::WebDeviceEmulationParams& params) override;
+  void ResizeVisualViewportForWidget(
+      const gfx::Size& scaled_viewport_size) override;
 
   // Old WebLocalFrameClient implementations
   // ----------------------------------------
@@ -458,6 +460,7 @@
   void OnPageWasHidden();
   void OnPageWasShown();
   void OnUpdateScreenInfo(const ScreenInfo& screen_info);
+  void OnUpdatePageVisualProperties(const gfx::Size& visible_viewport_size);
   void SetPageFrozen(bool frozen);
   void OnTextAutosizerPageInfoChanged(
       const blink::WebTextAutosizerPageInfo& page_info);
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 32e2502..f34ae97 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -1643,7 +1643,12 @@
       visual_viewport_size = gfx::ScaleToCeiledSize(
           visual_viewport_size, GetOriginalScreenInfo().device_scale_factor);
     }
-    GetWebWidget()->ResizeVisualViewport(visual_viewport_size);
+    // When this function is invoked for a main frame widget, it is only if
+    // (i) we are initializing the widget, or (ii) the widget supports a local
+    // mainframe. For widgets supporting a remote main frame, the visual
+    // viewport is updated through the RenderView.
+    if (delegate())
+      delegate()->ResizeVisualViewportForWidget(visual_viewport_size);
 
     // NOTE: We may have entered fullscreen mode without changing our size.
     SetIsFullscreen(params.is_fullscreen_granted);
@@ -3698,7 +3703,10 @@
     visible_viewport_size =
         gfx::ScaleToCeiledSize(visible_viewport_size, factor);
   }
-  GetWebWidget()->ResizeVisualViewport(visible_viewport_size);
+
+  DCHECK(delegate()) << "Resizing the viewport for a cross-process subframe "
+                        "must be done via the RenderView.";
+  delegate()->ResizeVisualViewportForWidget(visible_viewport_size);
 
   // Make sure the DSF override stays for future VisualProperties updates, and
   // that includes overriding the VisualProperties'
diff --git a/content/renderer/render_widget_delegate.h b/content/renderer/render_widget_delegate.h
index 1252e15..ced4581 100644
--- a/content/renderer/render_widget_delegate.h
+++ b/content/renderer/render_widget_delegate.h
@@ -109,6 +109,11 @@
   virtual void SetScreenMetricsEmulationParametersForWidget(
       bool enabled,
       const blink::WebDeviceEmulationParams& params) = 0;
+
+  // Called when the VisualViewport needs to be updated. Expects coordinates
+  // scaled to account for DeviceScaleFactor.
+  virtual void ResizeVisualViewportForWidget(
+      const gfx::Size& scaled_viewport_size) = 0;
 };
 
 }  // namespace content
diff --git a/content/renderer/render_widget_unittest.cc b/content/renderer/render_widget_unittest.cc
index ff458c4..2736f85 100644
--- a/content/renderer/render_widget_unittest.cc
+++ b/content/renderer/render_widget_unittest.cc
@@ -552,6 +552,7 @@
   void SetScreenMetricsEmulationParametersForWidget(
       bool enabled,
       const blink::WebDeviceEmulationParams& params) override {}
+  void ResizeVisualViewportForWidget(const gfx::Size& viewport_size) override {}
 };
 
 // Tests that the value of VisualProperties::is_pinch_gesture_active is
diff --git a/content/shell/browser/shell.cc b/content/shell/browser/shell.cc
index 92ec8d4e..15499f4 100644
--- a/content/shell/browser/shell.cc
+++ b/content/shell/browser/shell.cc
@@ -497,7 +497,7 @@
   }
 }
 
-bool Shell::IsFullscreenForTabOrPending(const WebContents* web_contents) const {
+bool Shell::IsFullscreenForTabOrPending(const WebContents* web_contents) {
 #if defined(OS_ANDROID)
   return PlatformIsFullscreenForTabOrPending(web_contents);
 #else
@@ -505,8 +505,7 @@
 #endif
 }
 
-blink::WebDisplayMode Shell::GetDisplayMode(
-    const WebContents* web_contents) const {
+blink::WebDisplayMode Shell::GetDisplayMode(const WebContents* web_contents) {
   // TODO: should return blink::WebDisplayModeFullscreen wherever user puts
   // a browser window into fullscreen (not only in case of renderer-initiated
   // fullscreen mode): crbug.com/476874.
@@ -525,7 +524,7 @@
   Close();
 }
 
-bool Shell::CanOverscrollContent() const {
+bool Shell::CanOverscrollContent() {
 #if defined(USE_AURA)
   return true;
 #else
diff --git a/content/shell/browser/shell.h b/content/shell/browser/shell.h
index 4499fbe..4f982132 100644
--- a/content/shell/browser/shell.h
+++ b/content/shell/browser/shell.h
@@ -155,15 +155,14 @@
       const GURL& origin,
       const blink::WebFullscreenOptions& options) override;
   void ExitFullscreenModeForTab(WebContents* web_contents) override;
-  bool IsFullscreenForTabOrPending(
-      const WebContents* web_contents) const override;
+  bool IsFullscreenForTabOrPending(const WebContents* web_contents) override;
   blink::WebDisplayMode GetDisplayMode(
-     const WebContents* web_contents) const override;
+      const WebContents* web_contents) override;
   void RequestToLockMouse(WebContents* web_contents,
                           bool user_gesture,
                           bool last_unlocked_by_target) override;
   void CloseContents(WebContents* source) override;
-  bool CanOverscrollContent() const override;
+  bool CanOverscrollContent() override;
   void DidNavigateMainFramePostCommit(WebContents* web_contents) override;
   JavaScriptDialogManager* GetJavaScriptDialogManager(
       WebContents* source) override;
diff --git a/content/shell/browser/shell_content_browser_client.cc b/content/shell/browser/shell_content_browser_client.cc
index 854c4d3..2099862 100644
--- a/content/shell/browser/shell_content_browser_client.cc
+++ b/content/shell/browser/shell_content_browser_client.cc
@@ -469,12 +469,11 @@
   return nullptr;
 }
 
-std::string ShellContentBrowserClient::GetUserAgent() const {
+std::string ShellContentBrowserClient::GetUserAgent() {
   return GetShellUserAgent();
 }
 
-blink::UserAgentMetadata ShellContentBrowserClient::GetUserAgentMetadata()
-    const {
+blink::UserAgentMetadata ShellContentBrowserClient::GetUserAgentMetadata() {
   return GetShellUserAgentMetadata();
 }
 
diff --git a/content/shell/browser/shell_content_browser_client.h b/content/shell/browser/shell_content_browser_client.h
index 5b2c0b0..ad711ae 100644
--- a/content/shell/browser/shell_content_browser_client.h
+++ b/content/shell/browser/shell_content_browser_client.h
@@ -89,8 +89,8 @@
       bool first_auth_attempt,
       LoginAuthRequiredCallback auth_required_callback) override;
 
-  std::string GetUserAgent() const override;
-  blink::UserAgentMetadata GetUserAgentMetadata() const override;
+  std::string GetUserAgent() override;
+  blink::UserAgentMetadata GetUserAgentMetadata() override;
 
 #if defined(OS_LINUX) || defined(OS_ANDROID)
   void GetAdditionalMappedFilesForChildProcess(
diff --git a/content/test/test_content_browser_client.cc b/content/test/test_content_browser_client.cc
index 1a5b015..fc70a57d 100644
--- a/content/test/test_content_browser_client.cc
+++ b/content/test/test_content_browser_client.cc
@@ -45,7 +45,7 @@
   std::move(callback).Run(storage::GetHardCodedSettings(100 * 1024 * 1024));
 }
 
-std::string TestContentBrowserClient::GetUserAgent() const {
+std::string TestContentBrowserClient::GetUserAgent() {
   return std::string("TestContentClient");
 }
 
diff --git a/content/test/test_content_browser_client.h b/content/test/test_content_browser_client.h
index 2c9d780a..80accc3e 100644
--- a/content/test/test_content_browser_client.h
+++ b/content/test/test_content_browser_client.h
@@ -27,7 +27,7 @@
       content::BrowserContext* context,
       content::StoragePartition* partition,
       storage::OptionalQuotaSettingsCallback callback) override;
-  std::string GetUserAgent() const override;
+  std::string GetUserAgent() override;
 #if defined(OS_ANDROID)
   void GetAdditionalMappedFilesForChildProcess(
       const base::CommandLine& command_line,
diff --git a/device/fido/bio/enrollment.cc b/device/fido/bio/enrollment.cc
index 6608817..1af1213 100644
--- a/device/fido/bio/enrollment.cc
+++ b/device/fido/bio/enrollment.cc
@@ -97,6 +97,20 @@
   return request;
 }
 
+// static
+BioEnrollmentRequest BioEnrollmentRequest::ForDelete(
+    const pin::TokenResponse& token,
+    std::vector<uint8_t> id) {
+  BioEnrollmentRequest request;
+  request.subcommand = BioEnrollmentSubCommand::kRemoveEnrollment;
+  request.params = cbor::Value::MapValue();
+  request.params->emplace(
+      static_cast<int>(BioEnrollmentSubCommandParam::kTemplateId),
+      std::move(id));
+  SetPinAuth(&request, token);
+  return request;
+}
+
 BioEnrollmentRequest::BioEnrollmentRequest(BioEnrollmentRequest&&) = default;
 BioEnrollmentRequest& BioEnrollmentRequest::operator=(BioEnrollmentRequest&&) =
     default;
diff --git a/device/fido/bio/enrollment.h b/device/fido/bio/enrollment.h
index 19804c0e..f58dcf3 100644
--- a/device/fido/bio/enrollment.h
+++ b/device/fido/bio/enrollment.h
@@ -112,6 +112,8 @@
   static BioEnrollmentRequest ForRename(const pin::TokenResponse& token,
                                         std::vector<uint8_t> id,
                                         std::string name);
+  static BioEnrollmentRequest ForDelete(const pin::TokenResponse& token,
+                                        std::vector<uint8_t> id);
 
   base::Optional<BioEnrollmentModality> modality;
   base::Optional<BioEnrollmentSubCommand> subcommand;
diff --git a/device/fido/bio/enrollment_handler.cc b/device/fido/bio/enrollment_handler.cc
index b7c77fdb..78c3519 100644
--- a/device/fido/bio/enrollment_handler.cc
+++ b/device/fido/bio/enrollment_handler.cc
@@ -60,8 +60,9 @@
 
 void BioEnrollmentHandler::EnrollTemplate(ResponseCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker);
+  DCHECK(!enroll_callback_);
 
-  response_callback_ = std::move(callback);
+  enroll_callback_ = std::move(callback);
   authenticator_->BioEnrollFingerprint(
       *pin_token_response_,
       base::BindRepeating(&BioEnrollmentHandler::OnEnrollTemplate,
@@ -71,19 +72,18 @@
 void BioEnrollmentHandler::Cancel(StatusCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker);
 
-  status_callback_ = std::move(callback);
-  authenticator_->BioEnrollCancel(base::BindOnce(
-      &BioEnrollmentHandler::OnCancel, weak_factory_.GetWeakPtr()));
+  authenticator_->BioEnrollCancel(
+      base::BindOnce(&BioEnrollmentHandler::OnCancel,
+                     weak_factory_.GetWeakPtr(), std::move(callback)));
 }
 
 void BioEnrollmentHandler::EnumerateTemplates(ResponseCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker);
 
-  response_callback_ = std::move(callback);
   authenticator_->BioEnrollEnumerate(
       *pin_token_response_,
       base::BindOnce(&BioEnrollmentHandler::OnEnumerateTemplates,
-                     weak_factory_.GetWeakPtr()));
+                     weak_factory_.GetWeakPtr(), std::move(callback)));
 }
 
 void BioEnrollmentHandler::RenameTemplate(std::vector<uint8_t> id,
@@ -91,11 +91,20 @@
                                           StatusCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker);
 
-  status_callback_ = std::move(callback);
   authenticator_->BioEnrollRename(
       *pin_token_response_, std::move(id), std::move(name),
       base::BindOnce(&BioEnrollmentHandler::OnRenameTemplate,
-                     weak_factory_.GetWeakPtr()));
+                     weak_factory_.GetWeakPtr(), std::move(callback)));
+}
+
+void BioEnrollmentHandler::DeleteTemplate(std::vector<uint8_t> id,
+                                          StatusCallback callback) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker);
+
+  authenticator_->BioEnrollDelete(
+      *pin_token_response_, std::move(id),
+      base::BindOnce(&BioEnrollmentHandler::OnDeleteTemplate,
+                     weak_factory_.GetWeakPtr(), std::move(callback)));
 }
 
 void BioEnrollmentHandler::DispatchRequest(FidoAuthenticator* authenticator) {
@@ -219,46 +228,57 @@
     base::Optional<BioEnrollmentResponse> response) {
   if (code != CtapDeviceResponseCode::kSuccess) {
     // Response is not valid if operation was not successful.
-    std::move(response_callback_).Run(code, base::nullopt);
+    std::move(enroll_callback_).Run(code, base::nullopt);
     return;
   }
   if (!response || !response->last_status || !response->remaining_samples) {
-    std::move(response_callback_)
+    std::move(enroll_callback_)
         .Run(CtapDeviceResponseCode::kCtap2ErrOther, base::nullopt);
     return;
   }
   FIDO_LOG(DEBUG) << "Finished bio enrollment with code "
                   << static_cast<int>(code);
-  std::move(response_callback_).Run(code, std::move(response));
+  std::move(enroll_callback_).Run(code, std::move(response));
+  // TODO(noviv): Test calling OnEnrollTemplate multiple times.
 }
 
-void BioEnrollmentHandler::OnCancel(CtapDeviceResponseCode code,
+void BioEnrollmentHandler::OnCancel(StatusCallback callback,
+                                    CtapDeviceResponseCode code,
                                     base::Optional<BioEnrollmentResponse>) {
-  std::move(status_callback_).Run(code);
+  std::move(callback).Run(code);
 }
 
 void BioEnrollmentHandler::OnEnumerateTemplates(
+    ResponseCallback callback,
     CtapDeviceResponseCode code,
     base::Optional<BioEnrollmentResponse> response) {
   if (code != CtapDeviceResponseCode::kSuccess) {
     // Response is not valid if operation was not successful.
     // Note that an empty enumeration returns kCtap2ErrInvalidOption.
-    std::move(response_callback_).Run(code, base::nullopt);
+    std::move(callback).Run(code, base::nullopt);
     return;
   }
   if (!response || !response->enumerated_ids) {
     // Response must have enumerated_ids.
-    std::move(response_callback_)
-        .Run(CtapDeviceResponseCode::kCtap2ErrOther, base::nullopt);
+    std::move(callback).Run(CtapDeviceResponseCode::kCtap2ErrOther,
+                            base::nullopt);
     return;
   }
-  std::move(response_callback_).Run(code, std::move(response));
+  std::move(callback).Run(code, std::move(response));
 }
 
 void BioEnrollmentHandler::OnRenameTemplate(
+    StatusCallback callback,
     CtapDeviceResponseCode code,
     base::Optional<BioEnrollmentResponse> response) {
-  std::move(status_callback_).Run(code);
+  std::move(callback).Run(code);
+}
+
+void BioEnrollmentHandler::OnDeleteTemplate(
+    StatusCallback callback,
+    CtapDeviceResponseCode code,
+    base::Optional<BioEnrollmentResponse> response) {
+  std::move(callback).Run(code);
 }
 
 }  // namespace device
diff --git a/device/fido/bio/enrollment_handler.h b/device/fido/bio/enrollment_handler.h
index c7b838b8..cec194c 100644
--- a/device/fido/bio/enrollment_handler.h
+++ b/device/fido/bio/enrollment_handler.h
@@ -49,6 +49,7 @@
   void RenameTemplate(std::vector<uint8_t> id,
                       std::string name,
                       StatusCallback);
+  void DeleteTemplate(std::vector<uint8_t> id, StatusCallback);
 
  private:
   // FidoRequestHandlerBase:
@@ -66,10 +67,17 @@
                       base::Optional<pin::TokenResponse>);
   void OnEnrollTemplate(CtapDeviceResponseCode,
                         base::Optional<BioEnrollmentResponse>);
-  void OnCancel(CtapDeviceResponseCode, base::Optional<BioEnrollmentResponse>);
-  void OnEnumerateTemplates(CtapDeviceResponseCode,
+  void OnCancel(StatusCallback,
+                CtapDeviceResponseCode,
+                base::Optional<BioEnrollmentResponse>);
+  void OnEnumerateTemplates(ResponseCallback,
+                            CtapDeviceResponseCode,
                             base::Optional<BioEnrollmentResponse>);
-  void OnRenameTemplate(CtapDeviceResponseCode,
+  void OnRenameTemplate(StatusCallback,
+                        CtapDeviceResponseCode,
+                        base::Optional<BioEnrollmentResponse>);
+  void OnDeleteTemplate(StatusCallback,
+                        CtapDeviceResponseCode,
                         base::Optional<BioEnrollmentResponse>);
 
   SEQUENCE_CHECKER(sequence_checker);
@@ -78,8 +86,7 @@
   base::OnceClosure ready_callback_;
   ErrorCallback error_callback_;
   GetPINCallback get_pin_callback_;
-  ResponseCallback response_callback_;
-  StatusCallback status_callback_;
+  ResponseCallback enroll_callback_;
   base::Optional<pin::TokenResponse> pin_token_response_;
   base::WeakPtrFactory<BioEnrollmentHandler> weak_factory_;
 
diff --git a/device/fido/bio/enrollment_handler_unittest.cc b/device/fido/bio/enrollment_handler_unittest.cc
index 4884e33e..32a2ef4 100644
--- a/device/fido/bio/enrollment_handler_unittest.cc
+++ b/device/fido/bio/enrollment_handler_unittest.cc
@@ -245,5 +245,31 @@
   EXPECT_EQ(cb1.value(), CtapDeviceResponseCode::kCtap2ErrInvalidOption);
 }
 
+// Tests deleting an enrollment (success and failure).
+TEST_F(BioEnrollmentHandlerTest, Delete) {
+  VirtualCtap2Device::Config config;
+  config.pin_support = true;
+  config.bio_enrollment_support = true;
+
+  virtual_device_factory_.SetCtap2Config(config);
+
+  auto handler = MakeHandler();
+  ready_callback_.WaitForCallback();
+
+  // Delete existing enrollment.
+  test::ValueCallbackReceiver<CtapDeviceResponseCode> cb0;
+  handler->DeleteTemplate({0, 0, 0, 1}, cb0.callback());
+
+  cb0.WaitForCallback();
+  EXPECT_EQ(cb0.value(), CtapDeviceResponseCode::kSuccess);
+
+  // Delete non-existent enrollment.
+  test::ValueCallbackReceiver<CtapDeviceResponseCode> cb1;
+  handler->DeleteTemplate({0, 0, 0, 2}, cb1.callback());
+
+  cb1.WaitForCallback();
+  EXPECT_EQ(cb1.value(), CtapDeviceResponseCode::kCtap2ErrInvalidOption);
+}
+
 }  // namespace
 }  // namespace device
diff --git a/device/fido/features.cc b/device/fido/features.cc
index 13ec84aa..e44eabb 100644
--- a/device/fido/features.cc
+++ b/device/fido/features.cc
@@ -22,4 +22,7 @@
 extern const base::Feature kWebAuthResidentKeys{
     "WebAuthenticationResidentKeys", base::FEATURE_ENABLED_BY_DEFAULT};
 
+extern const base::Feature kWebAuthBiometricEnrollment{
+    "WebAuthenticationBiometricEnrollment", base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace device
diff --git a/device/fido/features.h b/device/fido/features.h
index 0e94727..e564d42 100644
--- a/device/fido/features.h
+++ b/device/fido/features.h
@@ -24,6 +24,10 @@
 COMPONENT_EXPORT(DEVICE_FIDO)
 extern const base::Feature kWebAuthResidentKeys;
 
+// Enable biometric enrollment in the security keys settings UI.
+COMPONENT_EXPORT(DEVICE_FIDO)
+extern const base::Feature kWebAuthBiometricEnrollment;
+
 }  // namespace device
 
 #endif  // DEVICE_FIDO_FEATURES_H_
diff --git a/device/fido/fido_authenticator.cc b/device/fido/fido_authenticator.cc
index fc3679c..1f5acb8 100644
--- a/device/fido/fido_authenticator.cc
+++ b/device/fido/fido_authenticator.cc
@@ -112,6 +112,12 @@
   NOTREACHED();
 }
 
+void FidoAuthenticator::BioEnrollDelete(const pin::TokenResponse&,
+                                        std::vector<uint8_t>,
+                                        BioEnrollmentCallback) {
+  NOTREACHED();
+}
+
 void FidoAuthenticator::Reset(ResetCallback callback) {
   std::move(callback).Run(CtapDeviceResponseCode::kCtap1ErrInvalidCommand,
                           base::nullopt);
diff --git a/device/fido/fido_authenticator.h b/device/fido/fido_authenticator.h
index 54a96b9..446d779 100644
--- a/device/fido/fido_authenticator.h
+++ b/device/fido/fido_authenticator.h
@@ -177,8 +177,11 @@
   virtual void BioEnrollEnumerate(const pin::TokenResponse&,
                                   BioEnrollmentCallback);
   virtual void BioEnrollRename(const pin::TokenResponse&,
-                               std::vector<uint8_t>,
-                               std::string,
+                               std::vector<uint8_t> template_id,
+                               std::string name,
+                               BioEnrollmentCallback);
+  virtual void BioEnrollDelete(const pin::TokenResponse&,
+                               std::vector<uint8_t> template_id,
                                BioEnrollmentCallback);
 
   // Reset triggers a reset operation on the authenticator. This erases all
diff --git a/device/fido/fido_device_authenticator.cc b/device/fido/fido_device_authenticator.cc
index c8596387..339ed50e 100644
--- a/device/fido/fido_device_authenticator.cc
+++ b/device/fido/fido_device_authenticator.cc
@@ -513,30 +513,45 @@
 }
 
 void FidoDeviceAuthenticator::BioEnrollFingerprint(
-    const pin::TokenResponse& token,
+    const pin::TokenResponse& response,
     BioEnrollmentCallback callback) {
   DCHECK(
       Options()->bio_enrollment_availability_preview !=
       AuthenticatorSupportedOptions::BioEnrollmentAvailability::kNotSupported);
 
   RunOperation<BioEnrollmentRequest, BioEnrollmentResponse>(
-      BioEnrollmentRequest::ForEnrollBegin(token),
+      BioEnrollmentRequest::ForEnrollBegin(response),
       base::BindOnce(&FidoDeviceAuthenticator::OnBioEnroll,
-                     weak_factory_.GetWeakPtr(), std::move(token),
+                     weak_factory_.GetWeakPtr(), std::move(response),
                      std::move(callback)),
       base::BindOnce(&BioEnrollmentResponse::Parse));
 }
 
-void FidoDeviceAuthenticator::BioEnrollRename(const pin::TokenResponse& token,
-                                              std::vector<uint8_t> id,
-                                              std::string name,
-                                              BioEnrollmentCallback callback) {
+void FidoDeviceAuthenticator::BioEnrollRename(
+    const pin::TokenResponse& response,
+    std::vector<uint8_t> template_id,
+    std::string name,
+    BioEnrollmentCallback callback) {
   DCHECK(
       Options()->bio_enrollment_availability_preview !=
       AuthenticatorSupportedOptions::BioEnrollmentAvailability::kNotSupported);
 
   RunOperation<BioEnrollmentRequest, BioEnrollmentResponse>(
-      BioEnrollmentRequest::ForRename(token, std::move(id), std::move(name)),
+      BioEnrollmentRequest::ForRename(response, std::move(template_id),
+                                      std::move(name)),
+      std::move(callback), base::BindOnce(&BioEnrollmentResponse::Parse));
+}
+
+void FidoDeviceAuthenticator::BioEnrollDelete(
+    const pin::TokenResponse& response,
+    std::vector<uint8_t> template_id,
+    BioEnrollmentCallback callback) {
+  DCHECK(
+      Options()->bio_enrollment_availability_preview !=
+      AuthenticatorSupportedOptions::BioEnrollmentAvailability::kNotSupported);
+
+  RunOperation<BioEnrollmentRequest, BioEnrollmentResponse>(
+      BioEnrollmentRequest::ForDelete(response, std::move(template_id)),
       std::move(callback), base::BindOnce(&BioEnrollmentResponse::Parse));
 }
 
diff --git a/device/fido/fido_device_authenticator.h b/device/fido/fido_device_authenticator.h
index 111d02d..79a5187 100644
--- a/device/fido/fido_device_authenticator.h
+++ b/device/fido/fido_device_authenticator.h
@@ -87,8 +87,11 @@
   void BioEnrollEnumerate(const pin::TokenResponse&,
                           BioEnrollmentCallback) override;
   void BioEnrollRename(const pin::TokenResponse&,
-                       std::vector<uint8_t>,
-                       std::string,
+                       std::vector<uint8_t> template_id,
+                       std::string name,
+                       BioEnrollmentCallback) override;
+  void BioEnrollDelete(const pin::TokenResponse&,
+                       std::vector<uint8_t> template_id,
                        BioEnrollmentCallback) override;
 
   void Reset(ResetCallback callback) override;
diff --git a/device/fido/virtual_ctap2_device.cc b/device/fido/virtual_ctap2_device.cc
index af2c007..2745c301 100644
--- a/device/fido/virtual_ctap2_device.cc
+++ b/device/fido/virtual_ctap2_device.cc
@@ -93,6 +93,7 @@
     base::span<const uint8_t> client_data_hash,
     UserVerificationRequirement user_verification,
     base::RepeatingCallback<bool(void)> simulate_press_callback,
+    bool internal_user_verification_succeeds,
     bool* out_user_verified) {
   // The following quotes are from the CTAP2 spec:
 
@@ -148,10 +149,14 @@
       if (options.user_verification_availability ==
           AuthenticatorSupportedOptions::UserVerificationAvailability::
               kSupportedAndConfigured) {
-        // Internal UV is assumed to always succeed.
         if (simulate_press_callback && !simulate_press_callback.Run())
           return base::nullopt;
 
+        if (!internal_user_verification_succeeds) {
+          if (is_make_credential)
+            return CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid;
+          return CtapDeviceResponseCode::kCtap2ErrOperationDenied;
+        }
         uv = true;
       } else {
         // UV was requested, but either not supported or not configured.
@@ -636,7 +641,7 @@
           ? base::BindRepeating(mutable_state()->simulate_press_callback,
                                 base::Unretained(this))
           : base::RepeatingCallback<bool(void)>(),
-      &user_verified);
+      config_.user_verification_succeeds, &user_verified);
   if (uv_error != CtapDeviceResponseCode::kSuccess) {
     return uv_error;
   }
@@ -813,7 +818,7 @@
           ? base::BindRepeating(mutable_state()->simulate_press_callback,
                                 base::Unretained(this))
           : base::RepeatingCallback<bool(void)>(),
-      &user_verified);
+      config_.user_verification_succeeds, &user_verified);
   if (uv_error != CtapDeviceResponseCode::kSuccess) {
     return uv_error;
   }
@@ -1449,6 +1454,7 @@
           enumerated_ids);
       break;
     case static_cast<int>(SubCmd::kSetFriendlyName):
+    case static_cast<int>(SubCmd::kRemoveEnrollment):
       if (template_id && *template_id == std::vector<uint8_t>{0, 0, 0, 2}) {
         return CtapDeviceResponseCode::kCtap2ErrInvalidOption;
       }
diff --git a/device/fido/virtual_ctap2_device.h b/device/fido/virtual_ctap2_device.h
index b7853a718..6a7a5cc 100644
--- a/device/fido/virtual_ctap2_device.h
+++ b/device/fido/virtual_ctap2_device.h
@@ -65,6 +65,8 @@
     // reject_silent_authenticator_requests causes the authenticator to return
     // an error if a up=false assertion request is received.
     bool reject_silent_authentication_requests = false;
+    // Whether internal user verification should succeed or not.
+    bool user_verification_succeeds = true;
     bool is_platform_authenticator = false;
   };
 
diff --git a/docs/login/user_types.md b/docs/login/user_types.md
index d44fee1d..991334b3 100644
--- a/docs/login/user_types.md
+++ b/docs/login/user_types.md
@@ -38,7 +38,7 @@
 the user's policies have been refreshed (using the user's OAuth token). This
 might cause issues for tests that include child user login, as it may add
 unnecessary time to the test runtime. To avoid this, tests should:
-*   Set up `LocalTestServerMixin` to serve a policy for the test user.
+*   Set up `LocalPolicyTestServerMixin` to serve a policy for the test user.
     *   This should be done even if a cached policy is set up using
         `UserPolicyMixin`.
     *   Note that `UserPolicyMixin` propagates policy changes to
diff --git a/extensions/browser/app_window/app_window.cc b/extensions/browser/app_window/app_window.cc
index a05682fd..987621e 100644
--- a/extensions/browser/app_window/app_window.cc
+++ b/extensions/browser/app_window/app_window.cc
@@ -941,13 +941,13 @@
   SetFullscreen(FULLSCREEN_TYPE_HTML_API, enter_fullscreen);
 }
 
-bool AppWindow::IsFullscreenForTabOrPending(const content::WebContents* source)
-    const {
+bool AppWindow::IsFullscreenForTabOrPending(
+    const content::WebContents* source) {
   return IsHtmlApiFullscreen();
 }
 
 blink::WebDisplayMode AppWindow::GetDisplayMode(
-    const content::WebContents* source) const {
+    const content::WebContents* source) {
   return IsFullscreen() ? blink::kWebDisplayModeFullscreen
                         : blink::kWebDisplayModeStandalone;
 }
diff --git a/extensions/browser/app_window/app_window.h b/extensions/browser/app_window/app_window.h
index 1d63b77..87f05e5 100644
--- a/extensions/browser/app_window/app_window.h
+++ b/extensions/browser/app_window/app_window.h
@@ -412,10 +412,9 @@
       const GURL& origin,
       const blink::WebFullscreenOptions& options) override;
   void ExitFullscreenModeForTab(content::WebContents* source) override;
-  bool IsFullscreenForTabOrPending(
-      const content::WebContents* source) const override;
+  bool IsFullscreenForTabOrPending(const content::WebContents* source) override;
   blink::WebDisplayMode GetDisplayMode(
-      const content::WebContents* source) const override;
+      const content::WebContents* source) override;
   void RequestMediaAccessPermission(
       content::WebContents* web_contents,
       const content::MediaStreamRequest& request,
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
index 0bb8c44..859ac3d 100644
--- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
+++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
@@ -391,7 +391,7 @@
 }
 
 bool MimeHandlerViewGuest::IsFullscreenForTabOrPending(
-    const content::WebContents* web_contents) const {
+    const content::WebContents* web_contents) {
   return is_guest_fullscreen_;
 }
 
@@ -480,7 +480,7 @@
                       std::move(pending_before_unload_control_));
 }
 
-content::RenderFrameHost* MimeHandlerViewGuest::GetEmbedderFrame() const {
+content::RenderFrameHost* MimeHandlerViewGuest::GetEmbedderFrame() {
   return content::RenderFrameHost::FromID(embedder_frame_process_id_,
                                           embedder_frame_routing_id_);
 }
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h
index 0a4855e7..c690e25 100644
--- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h
+++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h
@@ -85,7 +85,7 @@
   bool CanBeEmbeddedInsideCrossProcessFrames() override;
   content::RenderWidgetHost* GetOwnerRenderWidgetHost() override;
   content::SiteInstance* GetOwnerSiteInstance() override;
-  content::RenderFrameHost* GetEmbedderFrame() const override;
+  content::RenderFrameHost* GetEmbedderFrame() override;
 
   void SetEmbedderFrame(int process_id, int routing_id);
 
@@ -149,7 +149,7 @@
       const blink::WebFullscreenOptions& options) override;
   void ExitFullscreenModeForTab(content::WebContents*) override;
   bool IsFullscreenForTabOrPending(
-      const content::WebContents* web_contents) const override;
+      const content::WebContents* web_contents) override;
   bool ShouldCreateWebContents(
       content::WebContents* web_contents,
       content::RenderFrameHost* opener,
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc
index 2446794a..9221c2c 100644
--- a/extensions/browser/guest_view/web_view/web_view_guest.cc
+++ b/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -1455,7 +1455,7 @@
 }
 
 bool WebViewGuest::IsFullscreenForTabOrPending(
-    const WebContents* web_contents) const {
+    const WebContents* web_contents) {
   return is_guest_fullscreen_;
 }
 
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.h b/extensions/browser/guest_view/web_view/web_view_guest.h
index 4321cc0..c98ce64 100644
--- a/extensions/browser/guest_view/web_view/web_view_guest.h
+++ b/extensions/browser/guest_view/web_view/web_view_guest.h
@@ -262,7 +262,7 @@
       const blink::WebFullscreenOptions& options) final;
   void ExitFullscreenModeForTab(content::WebContents* web_contents) final;
   bool IsFullscreenForTabOrPending(
-      const content::WebContents* web_contents) const final;
+      const content::WebContents* web_contents) final;
   void RequestToLockMouse(content::WebContents* web_contents,
                           bool user_gesture,
                           bool last_unlocked_by_target) override;
diff --git a/extensions/shell/browser/shell_content_browser_client.cc b/extensions/shell/browser/shell_content_browser_client.cc
index 44d5cb6..517d1e57 100644
--- a/extensions/shell/browser/shell_content_browser_client.cc
+++ b/extensions/shell/browser/shell_content_browser_client.cc
@@ -336,7 +336,7 @@
       process, network_context, header_client, request_initiator);
 }
 
-std::string ShellContentBrowserClient::GetUserAgent() const {
+std::string ShellContentBrowserClient::GetUserAgent() {
   // Must contain a user agent string for version sniffing. For example,
   // pluginless WebRTC Hangouts checks the Chrome version number.
   return content::BuildUserAgentFromProduct("Chrome/" PRODUCT_VERSION);
diff --git a/extensions/shell/browser/shell_content_browser_client.h b/extensions/shell/browser/shell_content_browser_client.h
index 673c8594..2f19874 100644
--- a/extensions/shell/browser/shell_content_browser_client.h
+++ b/extensions/shell/browser/shell_content_browser_client.h
@@ -101,7 +101,7 @@
       network::mojom::NetworkContext* network_context,
       network::mojom::TrustedURLLoaderHeaderClientPtrInfo* header_client,
       const url::Origin& request_initiator) override;
-  std::string GetUserAgent() const override;
+  std::string GetUserAgent() override;
 
  protected:
   // Subclasses may wish to provide their own ShellBrowserMainParts.
diff --git a/fuchsia/engine/browser/web_engine_content_browser_client.cc b/fuchsia/engine/browser/web_engine_content_browser_client.cc
index 50f8a9c..2b33e1a 100644
--- a/fuchsia/engine/browser/web_engine_content_browser_client.cc
+++ b/fuchsia/engine/browser/web_engine_content_browser_client.cc
@@ -38,11 +38,11 @@
   return new WebEngineDevToolsManagerDelegate(main_parts_->browser_context());
 }
 
-std::string WebEngineContentBrowserClient::GetProduct() const {
+std::string WebEngineContentBrowserClient::GetProduct() {
   return version_info::GetProductNameAndVersionForUserAgent();
 }
 
-std::string WebEngineContentBrowserClient::GetUserAgent() const {
+std::string WebEngineContentBrowserClient::GetUserAgent() {
   return content::BuildUserAgentFromProduct(
       version_info::GetProductNameAndVersionForUserAgent());
 }
diff --git a/fuchsia/engine/browser/web_engine_content_browser_client.h b/fuchsia/engine/browser/web_engine_content_browser_client.h
index eeb3a77..7309282 100644
--- a/fuchsia/engine/browser/web_engine_content_browser_client.h
+++ b/fuchsia/engine/browser/web_engine_content_browser_client.h
@@ -27,8 +27,8 @@
   std::unique_ptr<content::BrowserMainParts> CreateBrowserMainParts(
       const content::MainFunctionParams& parameters) override;
   content::DevToolsManagerDelegate* GetDevToolsManagerDelegate() override;
-  std::string GetProduct() const override;
-  std::string GetUserAgent() const override;
+  std::string GetProduct() override;
+  std::string GetUserAgent() override;
   void OverrideWebkitPrefs(content::RenderViewHost* rvh,
                            content::WebPreferences* web_prefs) override;
 
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn
index 3053b53b..de22b07 100644
--- a/gpu/BUILD.gn
+++ b/gpu/BUILD.gn
@@ -446,6 +446,9 @@
     "command_buffer/service/command_buffer_service_unittest.cc",
     "command_buffer/service/common_decoder_unittest.cc",
     "command_buffer/service/context_group_unittest.cc",
+    "command_buffer/service/context_state_test_helpers.cc",
+    "command_buffer/service/context_state_test_helpers.h",
+    "command_buffer/service/context_state_test_helpers_autogen.h",
     "command_buffer/service/context_state_unittest.cc",
     "command_buffer/service/feature_info_unittest.cc",
     "command_buffer/service/framebuffer_manager_unittest.cc",
@@ -458,7 +461,6 @@
     "command_buffer/service/gl_surface_mock.h",
     "command_buffer/service/gles2_cmd_decoder_unittest.cc",
     "command_buffer/service/gles2_cmd_decoder_unittest.h",
-    "command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h",
     "command_buffer/service/gles2_cmd_decoder_unittest_1.cc",
     "command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h",
     "command_buffer/service/gles2_cmd_decoder_unittest_2.cc",
diff --git a/gpu/OWNERS b/gpu/OWNERS
index 25d416b..4edd131 100644
--- a/gpu/OWNERS
+++ b/gpu/OWNERS
@@ -5,6 +5,7 @@
 vmiura@chromium.org
 zmo@chromium.org
 sunnyps@chromium.org
+penghuang@chromium.org
 
 # GPU memory buffer implementations.
 per-file *gpu_memory_buffer*=reveman@chromium.org
diff --git a/gpu/command_buffer/build_cmd_buffer_lib.py b/gpu/command_buffer/build_cmd_buffer_lib.py
index 9d66d12..6590b51 100644
--- a/gpu/command_buffer/build_cmd_buffer_lib.py
+++ b/gpu/command_buffer/build_cmd_buffer_lib.py
@@ -576,25 +576,23 @@
         'name': 'scissor_x',
         'type': 'GLint',
         'default': '0',
-        'expected': 'kViewportX',
       },
       {
         'name': 'scissor_y',
         'type': 'GLint',
         'default': '0',
-        'expected': 'kViewportY',
       },
       {
         'name': 'scissor_width',
         'type': 'GLsizei',
         'default': '1',
-        'expected': 'kViewportWidth',
+        'expected': 'initial_size.width()',
       },
       {
         'name': 'scissor_height',
         'type': 'GLsizei',
         'default': '1',
-        'expected': 'kViewportHeight',
+        'expected': 'initial_size.height()',
       },
     ],
   },
@@ -608,25 +606,23 @@
         'name': 'viewport_x',
         'type': 'GLint',
         'default': '0',
-        'expected': 'kViewportX',
       },
       {
         'name': 'viewport_y',
         'type': 'GLint',
         'default': '0',
-        'expected': 'kViewportY',
       },
       {
         'name': 'viewport_width',
         'type': 'GLsizei',
         'default': '1',
-        'expected': 'kViewportWidth',
+        'expected': 'initial_size.width()',
       },
       {
         'name': 'viewport_height',
         'type': 'GLsizei',
         'default': '1',
-        'expected': 'kViewportHeight',
+        'expected': 'initial_size.height()',
       },
     ],
   },
@@ -780,7 +776,7 @@
     return 'cached_' + item['name']
   return item['name']
 
-def GuardState(state, operation):
+def GuardState(state, operation, feature_info):
   if 'manual' in state:
     assert state['manual']
     return ""
@@ -789,11 +785,11 @@
   result_end = []
   if 'es3' in state:
     assert state['es3']
-    result.append("  if (feature_info_->IsES3Capable()) {\n");
+    result.append("  if (%s->IsES3Capable()) {\n" % feature_info);
     result_end.append("  }\n")
   if 'extension_flag' in state:
-    result.append("  if (feature_info_->feature_flags().%s) {\n  " %
-                     (state['extension_flag']))
+    result.append("  if (%s->feature_flags().%s) {\n  " %
+                     (feature_info, state['extension_flag']))
     result_end.append("  }\n")
   if 'gl_version_flag' in state:
     name = state['gl_version_flag']
@@ -801,8 +797,8 @@
     if name[0] == '!':
       inverted = '!'
       name = name[1:]
-    result.append("  if (%sfeature_info_->gl_version_info().%s) {\n" %
-                      (inverted, name))
+    result.append("  if (%s%s->gl_version_info().%s) {\n" %
+                      (inverted, feature_info, name))
     result_end.append("  }\n")
 
   result.append(operation)
@@ -1868,7 +1864,7 @@
       if not func.GetInfo("no_gl"):
         operation = "        %s(%s);\n" % \
                     (func.GetGLFunctionName(), func.MakeOriginalArgString(""))
-        f.write(GuardState(state, operation))
+        f.write(GuardState(state, operation, "feature_info_"))
       f.write("      }\n")
       f.write("      break;\n")
     f.write("    default:\n")
@@ -6800,7 +6796,8 @@
               if test_prev:
                 operation.append("  }")
 
-              guarded_operation = GuardState(item, ''.join(operation))
+              guarded_operation = GuardState(item, ''.join(operation),
+                                             "feature_info_")
               f.write(guarded_operation)
           else:
             if 'extension_flag' in state:
@@ -6998,14 +6995,16 @@
             })
       self.generated_cpp_filenames.append(filename)
 
-    comment = ("// It is included by %s_cmd_decoder_unittest_base.cc\n"
-               % _lower_prefix)
-    filename = filename_pattern % 0
+
+  def WriteServiceContextStateTestHelpers(self, filename):
+    comment = "// It is included by context_state_test_helpers.cc\n"
     with CHeaderWriter(filename, self.year, comment) as f:
       if self.capability_flags:
         f.write(
-"""void %sDecoderTestBase::SetupInitCapabilitiesExpectations(
-      bool es3_capable) {""" % _prefix)
+            """void ContextStateTestHelpers::SetupInitCapabilitiesExpectations(
+    MockGL* gl,
+    gles2::FeatureInfo* feature_info) {
+""")
         for capability in self.capability_flags:
           capability_no_init = 'no_init' in capability and \
               capability['no_init'] == True
@@ -7015,28 +7014,30 @@
           if capability_es3:
             continue
           if 'extension_flag' in capability:
-            f.write("  if (feature_info()->feature_flags().%s) {\n" %
+            f.write("  if (feature_info->feature_flags().%s) {\n" %
                      capability['extension_flag'])
             f.write("  ")
-          f.write("  ExpectEnableDisable(GL_%s, %s);\n" %
+          f.write("  ExpectEnableDisable(gl, GL_%s, %s);\n" %
                   (capability['name'].upper(),
                    ('false', 'true')['default' in capability]))
           if 'extension_flag' in capability:
             f.write("  }")
-        f.write("  if (es3_capable) {")
+        f.write("  if (feature_info->IsES3Capable()) {")
         for capability in self.capability_flags:
           capability_es3 = 'es3' in capability and capability['es3'] == True
           if capability_es3:
-            f.write("    ExpectEnableDisable(GL_%s, %s);\n" %
+            f.write("    ExpectEnableDisable(gl, GL_%s, %s);\n" %
                        (capability['name'].upper(),
                         ('false', 'true')['default' in capability]))
         f.write("""  }
 }
 """)
       f.write("""
-void %sDecoderTestBase::SetupInitStateExpectations(bool es3_capable) {
-  auto* feature_info_ = feature_info();
-""" % _prefix)
+void ContextStateTestHelpers::SetupInitStateExpectations(
+    MockGL* gl,
+    gles2::FeatureInfo* feature_info,
+    const gfx::Size& initial_size) {
+""")
       # We need to sort the keys so the expectations match
       for state_name in sorted(_STATE_INFO.keys()):
         state = _STATE_INFO[state_name]
@@ -7051,7 +7052,7 @@
               else:
                 args.append(item['default'])
             f.write(
-                "  EXPECT_CALL(*gl_, %s(%s, %s))\n" %
+                "  EXPECT_CALL(*gl, %s(%s, %s))\n" %
                 (state['func'], ('GL_FRONT', 'GL_BACK')[ndx],
                  ", ".join(args)))
             f.write("      .Times(1)\n")
@@ -7065,7 +7066,7 @@
 
             operation = []
             operation.append(
-                             "  EXPECT_CALL(*gl_, %s(%s, %s))\n" %
+                             "  EXPECT_CALL(*gl, %s(%s, %s))\n" %
                              (state['func'],
                               (item['enum_set']
                                   if 'enum_set' in item else item['enum']),
@@ -7073,11 +7074,12 @@
             operation.append("      .Times(1)\n")
             operation.append("      .RetiresOnSaturation();\n")
 
-            guarded_operation = GuardState(item, ''.join(operation))
+            guarded_operation = GuardState(item, ''.join(operation),
+                                           "feature_info")
             f.write(guarded_operation)
         elif 'no_init' not in state:
           if 'extension_flag' in state:
-            f.write("  if (feature_info()->feature_flags().%s) {\n" %
+            f.write("  if (feature_info->feature_flags().%s) {\n" %
                        state['extension_flag'])
             f.write("  ")
           args = []
@@ -7089,16 +7091,16 @@
           # TODO: Currently we do not check array values.
           args = ["_" if isinstance(arg, list) else arg for arg in args]
           if 'custom_function' in state:
-            f.write("  SetupInitStateManualExpectationsFor%s(%s);\n" %
+            f.write("  SetupInitStateManualExpectationsFor%s(gl, %s);\n" %
                        (state['func'], ", ".join(args)))
           else:
-            f.write("  EXPECT_CALL(*gl_, %s(%s))\n" %
+            f.write("  EXPECT_CALL(*gl, %s(%s))\n" %
                        (state['func'], ", ".join(args)))
             f.write("      .Times(1)\n")
             f.write("      .RetiresOnSaturation();\n")
           if 'extension_flag' in state:
             f.write("  }\n")
-      f.write("  SetupInitStateManualExpectations(es3_capable);\n")
+      f.write("  SetupInitStateManualExpectations(gl, feature_info);\n")
       f.write("}\n")
     self.generated_cpp_filenames.append(filename)
 
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 4a4fb94..38ffa4c 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -4414,6 +4414,8 @@
     "gpu/command_buffer/service/context_state_autogen.h")
   gen.WriteServiceContextStateImpl(
     "gpu/command_buffer/service/context_state_impl_autogen.h")
+  gen.WriteServiceContextStateTestHelpers(
+    "gpu/command_buffer/service/context_state_test_helpers_autogen.h")
   gen.WriteClientContextStateHeader(
     "gpu/command_buffer/client/client_context_state_autogen.h")
   gen.WriteClientContextStateImpl(
diff --git a/gpu/command_buffer/service/context_state_test_helpers.cc b/gpu/command_buffer/service/context_state_test_helpers.cc
new file mode 100644
index 0000000..70e7ac19
--- /dev/null
+++ b/gpu/command_buffer/service/context_state_test_helpers.cc
@@ -0,0 +1,63 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/command_buffer/service/context_state_test_helpers.h"
+
+#include "gpu/command_buffer/service/feature_info.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gl/gl_version_info.h"
+
+using ::testing::_;
+
+namespace gpu {
+// Include the auto-generated part of this file. We split this because it means
+// we can easily edit the non-auto generated parts right here in this file
+// instead of having to edit some template or the code generator.
+#include "gpu/command_buffer/service/context_state_test_helpers_autogen.h"
+
+void ContextStateTestHelpers::SetupInitState(MockGL* gl,
+                                             gles2::FeatureInfo* feature_info,
+                                             const gfx::Size& initial_size) {
+  SetupInitCapabilitiesExpectations(gl, feature_info);
+  SetupInitStateExpectations(gl, feature_info, initial_size);
+}
+
+void ContextStateTestHelpers::SetupInitStateManualExpectations(
+    MockGL* gl,
+    gles2::FeatureInfo* feature_info) {
+  if (feature_info->IsES3Capable()) {
+    EXPECT_CALL(*gl, PixelStorei(GL_PACK_ROW_LENGTH, 0))
+        .Times(1)
+        .RetiresOnSaturation();
+    EXPECT_CALL(*gl, PixelStorei(GL_UNPACK_ROW_LENGTH, 0))
+        .Times(1)
+        .RetiresOnSaturation();
+    EXPECT_CALL(*gl, PixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0))
+        .Times(1)
+        .RetiresOnSaturation();
+    if (feature_info->feature_flags().ext_window_rectangles) {
+      EXPECT_CALL(*gl, WindowRectanglesEXT(GL_EXCLUSIVE_EXT, 0, nullptr))
+          .Times(1)
+          .RetiresOnSaturation();
+    }
+  }
+}
+
+void ContextStateTestHelpers::SetupInitStateManualExpectationsForDoLineWidth(
+    MockGL* gl,
+    GLfloat width) {
+  EXPECT_CALL(*gl, LineWidth(width)).Times(1).RetiresOnSaturation();
+}
+
+void ContextStateTestHelpers::ExpectEnableDisable(MockGL* gl,
+                                                  GLenum cap,
+                                                  bool enable) {
+  if (enable) {
+    EXPECT_CALL(*gl, Enable(cap)).Times(1).RetiresOnSaturation();
+  } else {
+    EXPECT_CALL(*gl, Disable(cap)).Times(1).RetiresOnSaturation();
+  }
+}
+
+}  // namespace gpu
diff --git a/gpu/command_buffer/service/context_state_test_helpers.h b/gpu/command_buffer/service/context_state_test_helpers.h
new file mode 100644
index 0000000..4ee751c
--- /dev/null
+++ b/gpu/command_buffer/service/context_state_test_helpers.h
@@ -0,0 +1,44 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#ifndef GPU_COMMAND_BUFFER_SERVICE_CONTEXT_STATE_TEST_HELPERS_H_
+#define GPU_COMMAND_BUFFER_SERVICE_CONTEXT_STATE_TEST_HELPERS_H_
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gl/gl_mock.h"
+
+namespace gfx {
+class Size;
+}  // namespace gfx
+
+namespace gpu {
+namespace gles2 {
+class FeatureInfo;
+}  // namespace gles2
+
+class ContextStateTestHelpers {
+ public:
+  using MockGL = ::testing::StrictMock<::gl::MockGLInterface>;
+  static void SetupInitState(MockGL* gl,
+                             gles2::FeatureInfo* feature_info,
+                             const gfx::Size& initial_size);
+
+ private:
+  static void SetupInitCapabilitiesExpectations(
+      MockGL* gl,
+      gles2::FeatureInfo* feature_info);
+  static void SetupInitStateExpectations(MockGL* gl,
+                                         gles2::FeatureInfo* feature_info,
+                                         const gfx::Size& initial_size);
+  static void SetupInitStateManualExpectations(
+      MockGL* gl,
+      gles2::FeatureInfo* feature_info);
+  static void SetupInitStateManualExpectationsForDoLineWidth(MockGL* gl,
+                                                             GLfloat width);
+  static void ExpectEnableDisable(MockGL* gl, GLenum cap, bool enable);
+};
+
+}  // namespace gpu
+
+#endif  // GPU_COMMAND_BUFFER_SERVICE_CONTEXT_STATE_TEST_HELPERS_H_
diff --git a/gpu/command_buffer/service/context_state_test_helpers_autogen.h b/gpu/command_buffer/service/context_state_test_helpers_autogen.h
new file mode 100644
index 0000000..6fa1c493
--- /dev/null
+++ b/gpu/command_buffer/service/context_state_test_helpers_autogen.h
@@ -0,0 +1,135 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is auto-generated from
+// gpu/command_buffer/build_gles2_cmd_buffer.py
+// It's formatted by clang-format using chromium coding style:
+//    clang-format -i -style=chromium filename
+// DO NOT EDIT!
+
+// It is included by context_state_test_helpers.cc
+#ifndef GPU_COMMAND_BUFFER_SERVICE_CONTEXT_STATE_TEST_HELPERS_AUTOGEN_H_
+#define GPU_COMMAND_BUFFER_SERVICE_CONTEXT_STATE_TEST_HELPERS_AUTOGEN_H_
+
+void ContextStateTestHelpers::SetupInitCapabilitiesExpectations(
+    MockGL* gl,
+    gles2::FeatureInfo* feature_info) {
+  ExpectEnableDisable(gl, GL_BLEND, false);
+  ExpectEnableDisable(gl, GL_CULL_FACE, false);
+  ExpectEnableDisable(gl, GL_DEPTH_TEST, false);
+  ExpectEnableDisable(gl, GL_DITHER, true);
+  ExpectEnableDisable(gl, GL_POLYGON_OFFSET_FILL, false);
+  ExpectEnableDisable(gl, GL_SAMPLE_ALPHA_TO_COVERAGE, false);
+  ExpectEnableDisable(gl, GL_SAMPLE_COVERAGE, false);
+  ExpectEnableDisable(gl, GL_SCISSOR_TEST, false);
+  ExpectEnableDisable(gl, GL_STENCIL_TEST, false);
+  if (feature_info->feature_flags().ext_multisample_compatibility) {
+    ExpectEnableDisable(gl, GL_MULTISAMPLE_EXT, true);
+  }
+  if (feature_info->feature_flags().ext_multisample_compatibility) {
+    ExpectEnableDisable(gl, GL_SAMPLE_ALPHA_TO_ONE_EXT, false);
+  }
+  if (feature_info->IsES3Capable()) {
+    ExpectEnableDisable(gl, GL_RASTERIZER_DISCARD, false);
+    ExpectEnableDisable(gl, GL_PRIMITIVE_RESTART_FIXED_INDEX, false);
+  }
+}
+
+void ContextStateTestHelpers::SetupInitStateExpectations(
+    MockGL* gl,
+    gles2::FeatureInfo* feature_info,
+    const gfx::Size& initial_size) {
+  EXPECT_CALL(*gl, BlendColor(0.0f, 0.0f, 0.0f, 0.0f))
+      .Times(1)
+      .RetiresOnSaturation();
+  EXPECT_CALL(*gl, BlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD))
+      .Times(1)
+      .RetiresOnSaturation();
+  EXPECT_CALL(*gl, BlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO))
+      .Times(1)
+      .RetiresOnSaturation();
+  EXPECT_CALL(*gl, ClearColor(0.0f, 0.0f, 0.0f, 0.0f))
+      .Times(1)
+      .RetiresOnSaturation();
+  EXPECT_CALL(*gl, ClearDepth(1.0f)).Times(1).RetiresOnSaturation();
+  EXPECT_CALL(*gl, ClearStencil(0)).Times(1).RetiresOnSaturation();
+  EXPECT_CALL(*gl, ColorMask(true, true, true, true))
+      .Times(1)
+      .RetiresOnSaturation();
+  if (feature_info->feature_flags().chromium_framebuffer_mixed_samples) {
+    EXPECT_CALL(*gl, CoverageModulationNV(GL_NONE))
+        .Times(1)
+        .RetiresOnSaturation();
+  }
+  EXPECT_CALL(*gl, CullFace(GL_BACK)).Times(1).RetiresOnSaturation();
+  EXPECT_CALL(*gl, DepthFunc(GL_LESS)).Times(1).RetiresOnSaturation();
+  EXPECT_CALL(*gl, DepthMask(true)).Times(1).RetiresOnSaturation();
+  EXPECT_CALL(*gl, DepthRange(0.0f, 1.0f)).Times(1).RetiresOnSaturation();
+  EXPECT_CALL(*gl, FrontFace(GL_CCW)).Times(1).RetiresOnSaturation();
+  if (!feature_info->gl_version_info().is_desktop_core_profile) {
+    EXPECT_CALL(*gl, Hint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE))
+        .Times(1)
+        .RetiresOnSaturation();
+  }
+  if (feature_info->feature_flags().oes_standard_derivatives) {
+    EXPECT_CALL(*gl, Hint(GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES, GL_DONT_CARE))
+        .Times(1)
+        .RetiresOnSaturation();
+  }
+  if (feature_info->feature_flags().chromium_texture_filtering_hint) {
+    EXPECT_CALL(*gl, Hint(GL_TEXTURE_FILTERING_HINT_CHROMIUM, GL_NICEST))
+        .Times(1)
+        .RetiresOnSaturation();
+  }
+  SetupInitStateManualExpectationsForDoLineWidth(gl, 1.0f);
+  if (feature_info->feature_flags().chromium_path_rendering) {
+    EXPECT_CALL(*gl, MatrixLoadfEXT(GL_PATH_MODELVIEW_CHROMIUM, _))
+        .Times(1)
+        .RetiresOnSaturation();
+  }
+  if (feature_info->feature_flags().chromium_path_rendering) {
+    EXPECT_CALL(*gl, MatrixLoadfEXT(GL_PATH_PROJECTION_CHROMIUM, _))
+        .Times(1)
+        .RetiresOnSaturation();
+  }
+  if (feature_info->feature_flags().chromium_path_rendering) {
+    EXPECT_CALL(*gl, PathStencilFuncNV(GL_ALWAYS, 0, 0xFFFFFFFFU))
+        .Times(1)
+        .RetiresOnSaturation();
+  }
+  EXPECT_CALL(*gl, PixelStorei(GL_PACK_ALIGNMENT, 4))
+      .Times(1)
+      .RetiresOnSaturation();
+  EXPECT_CALL(*gl, PixelStorei(GL_UNPACK_ALIGNMENT, 4))
+      .Times(1)
+      .RetiresOnSaturation();
+  EXPECT_CALL(*gl, PolygonOffset(0.0f, 0.0f)).Times(1).RetiresOnSaturation();
+  EXPECT_CALL(*gl, SampleCoverage(1.0f, false)).Times(1).RetiresOnSaturation();
+  EXPECT_CALL(*gl, Scissor(0, 0, initial_size.width(), initial_size.height()))
+      .Times(1)
+      .RetiresOnSaturation();
+  EXPECT_CALL(*gl, StencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0, 0xFFFFFFFFU))
+      .Times(1)
+      .RetiresOnSaturation();
+  EXPECT_CALL(*gl, StencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 0xFFFFFFFFU))
+      .Times(1)
+      .RetiresOnSaturation();
+  EXPECT_CALL(*gl, StencilMaskSeparate(GL_FRONT, 0xFFFFFFFFU))
+      .Times(1)
+      .RetiresOnSaturation();
+  EXPECT_CALL(*gl, StencilMaskSeparate(GL_BACK, 0xFFFFFFFFU))
+      .Times(1)
+      .RetiresOnSaturation();
+  EXPECT_CALL(*gl, StencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_KEEP))
+      .Times(1)
+      .RetiresOnSaturation();
+  EXPECT_CALL(*gl, StencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP))
+      .Times(1)
+      .RetiresOnSaturation();
+  EXPECT_CALL(*gl, Viewport(0, 0, initial_size.width(), initial_size.height()))
+      .Times(1)
+      .RetiresOnSaturation();
+  SetupInitStateManualExpectations(gl, feature_info);
+}
+#endif  // GPU_COMMAND_BUFFER_SERVICE_CONTEXT_STATE_TEST_HELPERS_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/framebuffer_manager.cc b/gpu/command_buffer/service/framebuffer_manager.cc
index 30a62773a..96dea36 100644
--- a/gpu/command_buffer/service/framebuffer_manager.cc
+++ b/gpu/command_buffer/service/framebuffer_manager.cc
@@ -709,6 +709,8 @@
   GLsizei width = -1;
   GLsizei height = -1;
   GLsizei samples = -1;
+  uint32_t colorbufferSize = 0;
+  bool colorbufferSizeValid = false;
   const bool kSamplesMustMatch = feature_info->IsWebGLContext() ||
       !feature_info->feature_flags().chromium_framebuffer_mixed_samples;
 
@@ -751,10 +753,26 @@
       return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
     }
 
-    // Attaching an image to more than one color attachment point should return
-    // FRAMEBUFFER_UNSUPPORTED.
     if (it->first >= GL_COLOR_ATTACHMENT0 &&
         it->first < GL_COLOR_ATTACHMENT0 + manager_->max_color_attachments_) {
+      // in GLES 2.0, all color attachments attachments must have the same
+      // number of bitplanes.
+      // in GLES 3.0, there is no such restriction.
+      if (feature_info->context_type() == CONTEXT_TYPE_WEBGL1) {
+        if (colorbufferSizeValid) {
+          if (colorbufferSize !=
+              GLES2Util::GetGLTypeSizeForTextures(attachment->texture_type())) {
+            return GL_FRAMEBUFFER_UNSUPPORTED;
+          }
+        } else {
+          colorbufferSize =
+              GLES2Util::GetGLTypeSizeForTextures(attachment->texture_type());
+          colorbufferSizeValid = true;
+        }
+      }
+
+      // Attaching an image to more than one color attachment point should
+      // return FRAMEBUFFER_UNSUPPORTED.
       for (GLenum i = it->first + 1;
            i < GL_COLOR_ATTACHMENT0 + manager_->max_color_attachments_; i++) {
         const Attachment* other = GetAttachment(i);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 1534a9d..e40c171 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -12001,6 +12001,21 @@
     return;
   }
 
+  if (pname == GL_COMPILE_STATUS) {
+    if (shader->HasCompiled()) {
+      *params = compile_shader_always_succeeds_ ? true : shader->valid();
+      return;
+    }
+    // Lookup if there is compiled shader cache
+    if (program_manager()->HasCachedCompileStatus(shader)) {
+      // Only successful compile is cached
+      // Fail-to-compile shader is not cached as needs compiling
+      // to get log info
+      *params = true;
+      return;
+    }
+  }
+
   // Compile now for statuses that require it.
   switch (pname) {
     case GL_COMPILE_STATUS:
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h
deleted file mode 100644
index 09a217d1..0000000
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file is auto-generated from
-// gpu/command_buffer/build_gles2_cmd_buffer.py
-// It's formatted by clang-format using chromium coding style:
-//    clang-format -i -style=chromium filename
-// DO NOT EDIT!
-
-// It is included by gles2_cmd_decoder_unittest_base.cc
-#ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_0_AUTOGEN_H_
-#define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_0_AUTOGEN_H_
-
-void GLES2DecoderTestBase::SetupInitCapabilitiesExpectations(bool es3_capable) {
-  ExpectEnableDisable(GL_BLEND, false);
-  ExpectEnableDisable(GL_CULL_FACE, false);
-  ExpectEnableDisable(GL_DEPTH_TEST, false);
-  ExpectEnableDisable(GL_DITHER, true);
-  ExpectEnableDisable(GL_POLYGON_OFFSET_FILL, false);
-  ExpectEnableDisable(GL_SAMPLE_ALPHA_TO_COVERAGE, false);
-  ExpectEnableDisable(GL_SAMPLE_COVERAGE, false);
-  ExpectEnableDisable(GL_SCISSOR_TEST, false);
-  ExpectEnableDisable(GL_STENCIL_TEST, false);
-  if (feature_info()->feature_flags().ext_multisample_compatibility) {
-    ExpectEnableDisable(GL_MULTISAMPLE_EXT, true);
-  }
-  if (feature_info()->feature_flags().ext_multisample_compatibility) {
-    ExpectEnableDisable(GL_SAMPLE_ALPHA_TO_ONE_EXT, false);
-  }
-  if (es3_capable) {
-    ExpectEnableDisable(GL_RASTERIZER_DISCARD, false);
-    ExpectEnableDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX, false);
-  }
-}
-
-void GLES2DecoderTestBase::SetupInitStateExpectations(bool es3_capable) {
-  auto* feature_info_ = feature_info();
-  EXPECT_CALL(*gl_, BlendColor(0.0f, 0.0f, 0.0f, 0.0f))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, BlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, BlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, ClearColor(0.0f, 0.0f, 0.0f, 0.0f))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, ClearDepth(1.0f)).Times(1).RetiresOnSaturation();
-  EXPECT_CALL(*gl_, ClearStencil(0)).Times(1).RetiresOnSaturation();
-  EXPECT_CALL(*gl_, ColorMask(true, true, true, true))
-      .Times(1)
-      .RetiresOnSaturation();
-  if (feature_info()->feature_flags().chromium_framebuffer_mixed_samples) {
-    EXPECT_CALL(*gl_, CoverageModulationNV(GL_NONE))
-        .Times(1)
-        .RetiresOnSaturation();
-  }
-  EXPECT_CALL(*gl_, CullFace(GL_BACK)).Times(1).RetiresOnSaturation();
-  EXPECT_CALL(*gl_, DepthFunc(GL_LESS)).Times(1).RetiresOnSaturation();
-  EXPECT_CALL(*gl_, DepthMask(true)).Times(1).RetiresOnSaturation();
-  EXPECT_CALL(*gl_, DepthRange(0.0f, 1.0f)).Times(1).RetiresOnSaturation();
-  EXPECT_CALL(*gl_, FrontFace(GL_CCW)).Times(1).RetiresOnSaturation();
-  if (!feature_info_->gl_version_info().is_desktop_core_profile) {
-    EXPECT_CALL(*gl_, Hint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE))
-        .Times(1)
-        .RetiresOnSaturation();
-  }
-  if (feature_info_->feature_flags().oes_standard_derivatives) {
-    EXPECT_CALL(*gl_,
-                Hint(GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES, GL_DONT_CARE))
-        .Times(1)
-        .RetiresOnSaturation();
-  }
-  if (feature_info_->feature_flags().chromium_texture_filtering_hint) {
-    EXPECT_CALL(*gl_, Hint(GL_TEXTURE_FILTERING_HINT_CHROMIUM, GL_NICEST))
-        .Times(1)
-        .RetiresOnSaturation();
-  }
-  SetupInitStateManualExpectationsForDoLineWidth(1.0f);
-  if (feature_info_->feature_flags().chromium_path_rendering) {
-    EXPECT_CALL(*gl_, MatrixLoadfEXT(GL_PATH_MODELVIEW_CHROMIUM, _))
-        .Times(1)
-        .RetiresOnSaturation();
-  }
-  if (feature_info_->feature_flags().chromium_path_rendering) {
-    EXPECT_CALL(*gl_, MatrixLoadfEXT(GL_PATH_PROJECTION_CHROMIUM, _))
-        .Times(1)
-        .RetiresOnSaturation();
-  }
-  if (feature_info()->feature_flags().chromium_path_rendering) {
-    EXPECT_CALL(*gl_, PathStencilFuncNV(GL_ALWAYS, 0, 0xFFFFFFFFU))
-        .Times(1)
-        .RetiresOnSaturation();
-  }
-  EXPECT_CALL(*gl_, PixelStorei(GL_PACK_ALIGNMENT, 4))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, PixelStorei(GL_UNPACK_ALIGNMENT, 4))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, PolygonOffset(0.0f, 0.0f)).Times(1).RetiresOnSaturation();
-  EXPECT_CALL(*gl_, SampleCoverage(1.0f, false)).Times(1).RetiresOnSaturation();
-  EXPECT_CALL(*gl_,
-              Scissor(kViewportX, kViewportY, kViewportWidth, kViewportHeight))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, StencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0, 0xFFFFFFFFU))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, StencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 0xFFFFFFFFU))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, StencilMaskSeparate(GL_FRONT, 0xFFFFFFFFU))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, StencilMaskSeparate(GL_BACK, 0xFFFFFFFFU))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, StencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_KEEP))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, StencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_,
-              Viewport(kViewportX, kViewportY, kViewportWidth, kViewportHeight))
-      .Times(1)
-      .RetiresOnSaturation();
-  SetupInitStateManualExpectations(es3_capable);
-}
-#endif  // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_0_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
index 34bfa245..222b2d42 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -19,6 +19,7 @@
 #include "gpu/command_buffer/common/gles2_cmd_format.h"
 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
 #include "gpu/command_buffer/service/context_group.h"
+#include "gpu/command_buffer/service/context_state_test_helpers.h"
 #include "gpu/command_buffer/service/copy_texture_chromium_mock.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
 #include "gpu/command_buffer/service/logger.h"
@@ -438,8 +439,9 @@
         .RetiresOnSaturation();
   }
 
-  SetupInitCapabilitiesExpectations(group_->feature_info()->IsES3Capable());
-  SetupInitStateExpectations(group_->feature_info()->IsES3Capable());
+  ContextStateTestHelpers::SetupInitState(
+      gl_.get(), group_->feature_info(),
+      gfx::Size(kBackBufferWidth, kBackBufferHeight));
 
   EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0))
       .Times(1)
@@ -616,19 +618,6 @@
   ResetDecoder();
 }
 
-void GLES2DecoderTestBase::ExpectEnableDisable(GLenum cap, bool enable) {
-  if (enable) {
-    EXPECT_CALL(*gl_, Enable(cap))
-        .Times(1)
-        .RetiresOnSaturation();
-  } else {
-    EXPECT_CALL(*gl_, Disable(cap))
-        .Times(1)
-        .RetiresOnSaturation();
-  }
-}
-
-
 GLint GLES2DecoderTestBase::GetGLError() {
   EXPECT_CALL(*gl_, GetError())
       .WillOnce(Return(GL_NO_ERROR))
@@ -1799,11 +1788,6 @@
 const GLint GLES2DecoderTestBase::kMaxViewportWidth;
 const GLint GLES2DecoderTestBase::kMaxViewportHeight;
 
-const GLint GLES2DecoderTestBase::kViewportX;
-const GLint GLES2DecoderTestBase::kViewportY;
-const GLint GLES2DecoderTestBase::kViewportWidth;
-const GLint GLES2DecoderTestBase::kViewportHeight;
-
 const GLuint GLES2DecoderTestBase::kServiceAttrib0BufferId;
 const GLuint GLES2DecoderTestBase::kServiceFixedAttribBufferId;
 
@@ -2361,30 +2345,6 @@
           &GLES2DecoderTestBase::MockGLStates::OnVertexAttribNullPointer));
 }
 
-void GLES2DecoderTestBase::SetupInitStateManualExpectations(bool es3_capable) {
-  if (es3_capable) {
-    EXPECT_CALL(*gl_, PixelStorei(GL_PACK_ROW_LENGTH, 0))
-        .Times(1)
-        .RetiresOnSaturation();
-    EXPECT_CALL(*gl_, PixelStorei(GL_UNPACK_ROW_LENGTH, 0))
-        .Times(1)
-        .RetiresOnSaturation();
-    EXPECT_CALL(*gl_, PixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0))
-        .Times(1)
-        .RetiresOnSaturation();
-    if (group_->feature_info()->feature_flags().ext_window_rectangles) {
-      EXPECT_CALL(*gl_, WindowRectanglesEXT(GL_EXCLUSIVE_EXT, 0, nullptr))
-          .Times(1)
-          .RetiresOnSaturation();
-    }
-  }
-}
-
-void GLES2DecoderTestBase::SetupInitStateManualExpectationsForDoLineWidth(
-    GLfloat width) {
-  EXPECT_CALL(*gl_, LineWidth(width)).Times(1).RetiresOnSaturation();
-}
-
 void GLES2DecoderWithShaderTestBase::SetUp() {
   GLES2DecoderTestBase::SetUp();
   SetupDefaultProgram();
@@ -2414,11 +2374,6 @@
   EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
 }
 
-// Include the auto-generated part of this file. We split this because it means
-// we can easily edit the non-auto generated parts right here in this file
-// instead of having to edit some template or the code generator.
-#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h"
-
 namespace {
 
 GpuPreferences GenerateGpuPreferencesForPassthroughTests() {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
index 4b9e783..9bfb9e6 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
@@ -273,10 +273,6 @@
       GLuint vertex_shader_client_id, GLuint vertex_shader_service_id,
       GLuint fragment_shader_client_id, GLuint fragment_shader_service_id);
 
-  void SetupInitCapabilitiesExpectations(bool es3_capable);
-  void SetupInitStateExpectations(bool es3_capable);
-  void ExpectEnableDisable(GLenum cap, bool enable);
-
   // Setups up a shader for testing glUniform.
   void SetupShaderForUniform(GLenum uniform_type);
   void SetupDefaultProgram();
@@ -561,11 +557,6 @@
   static const GLint kMaxViewportWidth = 8192;
   static const GLint kMaxViewportHeight = 8192;
 
-  static const GLint kViewportX = 0;
-  static const GLint kViewportY = 0;
-  static const GLint kViewportWidth = kBackBufferWidth;
-  static const GLint kViewportHeight = kBackBufferHeight;
-
   static const GLuint kServiceAttrib0BufferId = 801;
   static const GLuint kServiceFixedAttribBufferId = 802;
 
@@ -799,11 +790,6 @@
   void AddExpectationsForVertexAttribManager();
   void SetupMockGLBehaviors();
 
-  void SetupInitStateManualExpectations(bool es3_capable);
-  void SetupInitStateManualExpectationsForWindowRectanglesEXT(GLenum mode,
-                                                              GLint count);
-  void SetupInitStateManualExpectationsForDoLineWidth(GLfloat width);
-
   GpuPreferences gpu_preferences_;
   MailboxManagerImpl mailbox_manager_;
   ShaderTranslatorCache shader_translator_cache_;
diff --git a/gpu/command_buffer/service/memory_program_cache.cc b/gpu/command_buffer/service/memory_program_cache.cc
index 13dc774..95b361c 100644
--- a/gpu/command_buffer/service/memory_program_cache.cc
+++ b/gpu/command_buffer/service/memory_program_cache.cc
@@ -620,12 +620,14 @@
       interface_block_map_1_(interface_block_map_1),
       program_cache_(program_cache) {
   program_cache_->curr_size_bytes_ += data_.size();
+  program_cache->CompiledShaderCacheSuccess(shader_0_hash_);
+  program_cache->CompiledShaderCacheSuccess(shader_1_hash_);
   program_cache_->LinkedProgramCacheSuccess(program_hash);
 }
 
 MemoryProgramCache::ProgramCacheValue::~ProgramCacheValue() {
   program_cache_->curr_size_bytes_ -= data_.size();
-  program_cache_->Evict(program_hash_);
+  program_cache_->Evict(program_hash_, shader_0_hash_, shader_1_hash_);
 }
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/program_cache.cc b/gpu/command_buffer/service/program_cache.cc
index 31bcca0e..7e76fda 100644
--- a/gpu/command_buffer/service/program_cache.cc
+++ b/gpu/command_buffer/service/program_cache.cc
@@ -33,6 +33,19 @@
 void ProgramCache::Clear() {
   ClearBackend();
   link_status_.clear();
+  compiled_shaders_.clear();
+}
+
+bool ProgramCache::HasSuccessfullyCompiledShader(
+    const std::string& shader_signature) const {
+  char sha[kHashLength];
+  ComputeShaderHash(shader_signature, sha);
+  const std::string sha_string(sha, kHashLength);
+
+  if (compiled_shaders_.find(sha_string) != compiled_shaders_.end()) {
+    return true;
+  }
+  return false;
 }
 
 ProgramCache::LinkedProgramStatus ProgramCache::GetLinkedProgramStatus(
@@ -80,8 +93,12 @@
                      transform_feedback_varyings,
                      transform_feedback_buffer_mode,
                      sha);
+  const std::string a_sha_string(a_sha, kHashLength);
+  const std::string b_sha_string(b_sha, kHashLength);
   const std::string sha_string(sha, kHashLength);
 
+  CompiledShaderCacheSuccess(a_sha_string);
+  CompiledShaderCacheSuccess(b_sha_string);
   LinkedProgramCacheSuccess(sha_string);
 }
 
@@ -89,6 +106,10 @@
   link_status_[program_hash] = LINK_SUCCEEDED;
 }
 
+void ProgramCache::CompiledShaderCacheSuccess(const std::string& shader_hash) {
+  compiled_shaders_.insert(shader_hash);
+}
+
 void ProgramCache::ComputeShaderHash(
     const std::string& str,
     char* result) const {
@@ -96,8 +117,12 @@
                       str.length(), reinterpret_cast<unsigned char*>(result));
 }
 
-void ProgramCache::Evict(const std::string& program_hash) {
+void ProgramCache::Evict(const std::string& program_hash,
+                         const std::string& shader_0_hash,
+                         const std::string& shader_1_hash) {
   link_status_.erase(program_hash);
+  compiled_shaders_.erase(shader_0_hash);
+  compiled_shaders_.erase(shader_1_hash);
 }
 
 namespace {
diff --git a/gpu/command_buffer/service/program_cache.h b/gpu/command_buffer/service/program_cache.h
index cdb6eba..cb8e48d03 100644
--- a/gpu/command_buffer/service/program_cache.h
+++ b/gpu/command_buffer/service/program_cache.h
@@ -10,6 +10,7 @@
 #include <map>
 #include <string>
 #include <unordered_map>
+#include <unordered_set>
 
 #include "base/hash/sha1.h"
 #include "base/macros.h"
@@ -59,6 +60,8 @@
   explicit ProgramCache(size_t max_cache_size_bytes);
   virtual ~ProgramCache();
 
+  bool HasSuccessfullyCompiledShader(const std::string& shader_signature) const;
+
   LinkedProgramStatus GetLinkedProgramStatus(
       const std::string& shader_signature_a,
       const std::string& shader_signature_b,
@@ -115,6 +118,8 @@
   // called by implementing class after a shader was successfully cached
   void LinkedProgramCacheSuccess(const std::string& program_hash);
 
+  void CompiledShaderCacheSuccess(const std::string& shader_hash);
+
   // result is not null terminated
   void ComputeShaderHash(const std::string& shader,
                          char* result) const;
@@ -129,7 +134,9 @@
       GLenum transform_feedback_buffer_mode,
       char* result) const;
 
-  void Evict(const std::string& program_hash);
+  void Evict(const std::string& program_hash,
+             const std::string& shader_0_hash,
+             const std::string& shader_1_hash);
 
   // Used by the passthrough program cache to notify when a new blob is
   // inserted.
@@ -137,12 +144,15 @@
 
  private:
   typedef std::unordered_map<std::string, LinkedProgramStatus> LinkStatusMap;
+  typedef std::unordered_set<std::string> CachedCompiledShaderSet;
 
   // called to clear the backend cache
   virtual void ClearBackend() = 0;
 
   const size_t max_size_bytes_;
   LinkStatusMap link_status_;
+  // only cache the hash of successfully compiled shaders
+  CachedCompiledShaderSet compiled_shaders_;
 
   DISALLOW_COPY_AND_ASSIGN(ProgramCache);
 };
diff --git a/gpu/command_buffer/service/program_cache_unittest.cc b/gpu/command_buffer/service/program_cache_unittest.cc
index e97f5ef5..9977398 100644
--- a/gpu/command_buffer/service/program_cache_unittest.cc
+++ b/gpu/command_buffer/service/program_cache_unittest.cc
@@ -59,8 +59,12 @@
                        varyings,
                        buffer_mode,
                        sha);
+    const std::string a_shaString(a_sha, kHashLength);
+    const std::string b_shaString(b_sha, kHashLength);
     const std::string shaString(sha, kHashLength);
 
+    CompiledShaderCacheSuccess(a_shaString);
+    CompiledShaderCacheSuccess(b_shaString);
     LinkedProgramCacheSuccess(shaString);
   }
 
@@ -84,8 +88,10 @@
                                      result);
   }
 
-  void Evict(const std::string& program_hash) {
-    ProgramCache::Evict(program_hash);
+  void Evict(const std::string& program_hash,
+             const std::string& shader_0_hash,
+             const std::string& shader_1_hash) {
+    ProgramCache::Evict(program_hash, shader_0_hash, shader_1_hash);
   }
 
   size_t Trim(size_t limit) override { return 0; }
@@ -155,7 +161,9 @@
 
   char sha[ProgramCache::kHashLength];
   cache_->ComputeProgramHash(a_sha, b_sha, nullptr, varyings_, GL_NONE, sha);
-  cache_->Evict(std::string(sha, ProgramCache::kHashLength));
+  cache_->Evict(std::string(sha, ProgramCache::kHashLength),
+                std::string(a_sha, ProgramCache::kHashLength),
+                std::string(b_sha, ProgramCache::kHashLength));
   EXPECT_EQ(ProgramCache::LINK_UNKNOWN,
             cache_->GetLinkedProgramStatus(shader1, shader2, nullptr, varyings_,
                                            GL_NONE));
@@ -177,7 +185,9 @@
 
   char sha[ProgramCache::kHashLength];
   cache_->ComputeProgramHash(a_sha, b_sha, nullptr, varyings_, GL_NONE, sha);
-  cache_->Evict(std::string(sha, ProgramCache::kHashLength));
+  cache_->Evict(std::string(sha, ProgramCache::kHashLength),
+                std::string(a_sha, ProgramCache::kHashLength),
+                std::string(b_sha, ProgramCache::kHashLength));
   EXPECT_EQ(ProgramCache::LINK_UNKNOWN,
             cache_->GetLinkedProgramStatus(shader1, shader2, nullptr, varyings_,
                                            GL_NONE));
@@ -186,7 +196,9 @@
                                            GL_NONE));
 
   cache_->ComputeProgramHash(a_sha, c_sha, nullptr, varyings_, GL_NONE, sha);
-  cache_->Evict(std::string(sha, ProgramCache::kHashLength));
+  cache_->Evict(std::string(sha, ProgramCache::kHashLength),
+                std::string(a_sha, ProgramCache::kHashLength),
+                std::string(c_sha, ProgramCache::kHashLength));
   EXPECT_EQ(ProgramCache::LINK_UNKNOWN,
             cache_->GetLinkedProgramStatus(shader1, shader2, nullptr, varyings_,
                                            GL_NONE));
@@ -227,5 +239,29 @@
                                            GL_INTERLEAVED_ATTRIBS));
 }
 
+TEST_F(ProgramCacheTest, ShaderCompileStatus) {
+  const std::string shader1 = "abcd1234";
+  const std::string shader2 = "abcda sda b1~#4 bbbbb1234";
+  {
+    std::string shader_a = shader1;
+    std::string shader_b = shader2;
+
+    EXPECT_EQ(cache_->HasSuccessfullyCompiledShader(shader1), false);
+    EXPECT_EQ(cache_->HasSuccessfullyCompiledShader(shader2), false);
+    cache_->SaySuccessfullyCached(shader_a, shader_b, nullptr, varyings_,
+                                  GL_NONE);
+
+    shader_a.clear();
+    shader_b.clear();
+  }
+  // make sure it was copied
+  EXPECT_EQ(ProgramCache::LINK_SUCCEEDED,
+            cache_->GetLinkedProgramStatus(shader1, shader2, nullptr, varyings_,
+                                           GL_NONE));
+
+  EXPECT_EQ(cache_->HasSuccessfullyCompiledShader(shader1), true);
+  EXPECT_EQ(cache_->HasSuccessfullyCompiledShader(shader2), true);
+}
+
 }  // namespace gles2
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc
index 12ba131..5d98b20 100644
--- a/gpu/command_buffer/service/program_manager.cc
+++ b/gpu/command_buffer/service/program_manager.cc
@@ -2702,6 +2702,14 @@
   return false;
 }
 
+bool ProgramManager::HasCachedCompileStatus(Shader* shader) const {
+  if (program_cache_) {
+    return program_cache_->HasSuccessfullyCompiledShader(
+        shader->last_compiled_signature());
+  }
+  return false;
+}
+
 void ProgramManager::RemoveProgramInfoIfUnused(
     ShaderManager* shader_manager, Program* program) {
   DCHECK(shader_manager);
diff --git a/gpu/command_buffer/service/program_manager.h b/gpu/command_buffer/service/program_manager.h
index f3452ea9..b4646ba0 100644
--- a/gpu/command_buffer/service/program_manager.h
+++ b/gpu/command_buffer/service/program_manager.h
@@ -700,6 +700,9 @@
   // Check if a Program is owned by this ProgramManager.
   bool IsOwned(Program* program) const;
 
+  // Return true if this shader has compiled status cached.
+  bool HasCachedCompileStatus(Shader* shader) const;
+
   static int32_t MakeFakeLocation(int32_t index, int32_t element);
 
   uint32_t max_varying_vectors() const { return max_varying_vectors_; }
diff --git a/gpu/command_buffer/service/raster_decoder_unittest_0_autogen.h b/gpu/command_buffer/service/raster_decoder_unittest_0_autogen.h
deleted file mode 100644
index 200cbb5..0000000
--- a/gpu/command_buffer/service/raster_decoder_unittest_0_autogen.h
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file is auto-generated from
-// gpu/command_buffer/build_raster_cmd_buffer.py
-// It's formatted by clang-format using chromium coding style:
-//    clang-format -i -style=chromium filename
-// DO NOT EDIT!
-
-// It is included by raster_cmd_decoder_unittest_base.cc
-#ifndef GPU_COMMAND_BUFFER_SERVICE_RASTER_DECODER_UNITTEST_0_AUTOGEN_H_
-#define GPU_COMMAND_BUFFER_SERVICE_RASTER_DECODER_UNITTEST_0_AUTOGEN_H_
-
-void RasterDecoderTestBase::SetupInitCapabilitiesExpectations(
-    bool es3_capable) {
-  ExpectEnableDisable(GL_BLEND, false);
-  ExpectEnableDisable(GL_CULL_FACE, false);
-  ExpectEnableDisable(GL_DEPTH_TEST, false);
-  ExpectEnableDisable(GL_DITHER, true);
-  ExpectEnableDisable(GL_POLYGON_OFFSET_FILL, false);
-  ExpectEnableDisable(GL_SAMPLE_ALPHA_TO_COVERAGE, false);
-  ExpectEnableDisable(GL_SAMPLE_COVERAGE, false);
-  ExpectEnableDisable(GL_SCISSOR_TEST, false);
-  ExpectEnableDisable(GL_STENCIL_TEST, false);
-  if (feature_info()->feature_flags().ext_multisample_compatibility) {
-    ExpectEnableDisable(GL_MULTISAMPLE_EXT, true);
-  }
-  if (feature_info()->feature_flags().ext_multisample_compatibility) {
-    ExpectEnableDisable(GL_SAMPLE_ALPHA_TO_ONE_EXT, false);
-  }
-  if (es3_capable) {
-    ExpectEnableDisable(GL_RASTERIZER_DISCARD, false);
-    ExpectEnableDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX, false);
-  }
-}
-
-void RasterDecoderTestBase::SetupInitStateExpectations(bool es3_capable) {
-  auto* feature_info_ = feature_info();
-  EXPECT_CALL(*gl_, BlendColor(0.0f, 0.0f, 0.0f, 0.0f))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, BlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, BlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, ClearColor(0.0f, 0.0f, 0.0f, 0.0f))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, ClearDepth(1.0f)).Times(1).RetiresOnSaturation();
-  EXPECT_CALL(*gl_, ClearStencil(0)).Times(1).RetiresOnSaturation();
-  EXPECT_CALL(*gl_, ColorMask(true, true, true, true))
-      .Times(1)
-      .RetiresOnSaturation();
-  if (feature_info()->feature_flags().chromium_framebuffer_mixed_samples) {
-    EXPECT_CALL(*gl_, CoverageModulationNV(GL_NONE))
-        .Times(1)
-        .RetiresOnSaturation();
-  }
-  EXPECT_CALL(*gl_, CullFace(GL_BACK)).Times(1).RetiresOnSaturation();
-  EXPECT_CALL(*gl_, DepthFunc(GL_LESS)).Times(1).RetiresOnSaturation();
-  EXPECT_CALL(*gl_, DepthMask(true)).Times(1).RetiresOnSaturation();
-  EXPECT_CALL(*gl_, DepthRange(0.0f, 1.0f)).Times(1).RetiresOnSaturation();
-  EXPECT_CALL(*gl_, FrontFace(GL_CCW)).Times(1).RetiresOnSaturation();
-  if (!feature_info_->gl_version_info().is_desktop_core_profile) {
-    EXPECT_CALL(*gl_, Hint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE))
-        .Times(1)
-        .RetiresOnSaturation();
-  }
-  if (feature_info_->feature_flags().oes_standard_derivatives) {
-    EXPECT_CALL(*gl_,
-                Hint(GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES, GL_DONT_CARE))
-        .Times(1)
-        .RetiresOnSaturation();
-  }
-  if (feature_info_->feature_flags().chromium_texture_filtering_hint) {
-    EXPECT_CALL(*gl_, Hint(GL_TEXTURE_FILTERING_HINT_CHROMIUM, GL_NICEST))
-        .Times(1)
-        .RetiresOnSaturation();
-  }
-  SetupInitStateManualExpectationsForDoLineWidth(1.0f);
-  if (feature_info_->feature_flags().chromium_path_rendering) {
-    EXPECT_CALL(*gl_, MatrixLoadfEXT(GL_PATH_MODELVIEW_CHROMIUM, _))
-        .Times(1)
-        .RetiresOnSaturation();
-  }
-  if (feature_info_->feature_flags().chromium_path_rendering) {
-    EXPECT_CALL(*gl_, MatrixLoadfEXT(GL_PATH_PROJECTION_CHROMIUM, _))
-        .Times(1)
-        .RetiresOnSaturation();
-  }
-  if (feature_info()->feature_flags().chromium_path_rendering) {
-    EXPECT_CALL(*gl_, PathStencilFuncNV(GL_ALWAYS, 0, 0xFFFFFFFFU))
-        .Times(1)
-        .RetiresOnSaturation();
-  }
-  EXPECT_CALL(*gl_, PixelStorei(GL_PACK_ALIGNMENT, 4))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, PixelStorei(GL_UNPACK_ALIGNMENT, 4))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, PolygonOffset(0.0f, 0.0f)).Times(1).RetiresOnSaturation();
-  EXPECT_CALL(*gl_, SampleCoverage(1.0f, false)).Times(1).RetiresOnSaturation();
-  EXPECT_CALL(*gl_,
-              Scissor(kViewportX, kViewportY, kViewportWidth, kViewportHeight))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, StencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0, 0xFFFFFFFFU))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, StencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 0xFFFFFFFFU))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, StencilMaskSeparate(GL_FRONT, 0xFFFFFFFFU))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, StencilMaskSeparate(GL_BACK, 0xFFFFFFFFU))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, StencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_KEEP))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_, StencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP))
-      .Times(1)
-      .RetiresOnSaturation();
-  EXPECT_CALL(*gl_,
-              Viewport(kViewportX, kViewportY, kViewportWidth, kViewportHeight))
-      .Times(1)
-      .RetiresOnSaturation();
-  SetupInitStateManualExpectations(es3_capable);
-}
-#endif  // GPU_COMMAND_BUFFER_SERVICE_RASTER_DECODER_UNITTEST_0_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/raster_decoder_unittest_base.cc b/gpu/command_buffer/service/raster_decoder_unittest_base.cc
index 323c851..572b163 100644
--- a/gpu/command_buffer/service/raster_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/raster_decoder_unittest_base.cc
@@ -22,6 +22,7 @@
 #include "gpu/command_buffer/common/raster_cmd_format.h"
 #include "gpu/command_buffer/common/shared_image_usage.h"
 #include "gpu/command_buffer/service/context_group.h"
+#include "gpu/command_buffer/service/context_state_test_helpers.h"
 #include "gpu/command_buffer/service/copy_texture_chromium_mock.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
 #include "gpu/command_buffer/service/logger.h"
@@ -113,38 +114,6 @@
   }
 }
 
-void RasterDecoderTestBase::SetupInitStateManualExpectations(bool es3_capable) {
-  if (es3_capable) {
-    EXPECT_CALL(*gl_, PixelStorei(GL_PACK_ROW_LENGTH, 0))
-        .Times(1)
-        .RetiresOnSaturation();
-    EXPECT_CALL(*gl_, PixelStorei(GL_UNPACK_ROW_LENGTH, 0))
-        .Times(1)
-        .RetiresOnSaturation();
-    EXPECT_CALL(*gl_, PixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0))
-        .Times(1)
-        .RetiresOnSaturation();
-    if (feature_info()->feature_flags().ext_window_rectangles) {
-      EXPECT_CALL(*gl_, WindowRectanglesEXT(GL_EXCLUSIVE_EXT, 0, nullptr))
-          .Times(1)
-          .RetiresOnSaturation();
-    }
-  }
-}
-
-void RasterDecoderTestBase::SetupInitStateManualExpectationsForDoLineWidth(
-    GLfloat width) {
-  EXPECT_CALL(*gl_, LineWidth(width)).Times(1).RetiresOnSaturation();
-}
-
-void RasterDecoderTestBase::ExpectEnableDisable(GLenum cap, bool enable) {
-  if (enable) {
-    EXPECT_CALL(*gl_, Enable(cap)).Times(1).RetiresOnSaturation();
-  } else {
-    EXPECT_CALL(*gl_, Disable(cap)).Times(1).RetiresOnSaturation();
-  }
-}
-
 gpu::Mailbox RasterDecoderTestBase::CreateFakeTexture(
     GLuint service_id,
     viz::ResourceFormat resource_format,
@@ -203,8 +172,8 @@
   EXPECT_CALL(*gl_, GetIntegerv(GL_MAX_VERTEX_ATTRIBS, _))
       .WillOnce(SetArgPointee<1>(8u))
       .RetiresOnSaturation();
-  SetupInitCapabilitiesExpectations(feature_info()->IsES3Capable());
-  SetupInitStateExpectations(feature_info()->IsES3Capable());
+  ContextStateTestHelpers::SetupInitState(gl_.get(), feature_info(),
+                                          gfx::Size(1, 1));
 
   shared_context_state_ = base::MakeRefCounted<SharedContextState>(
       new gl::GLShareGroup(), surface_, context_,
@@ -400,21 +369,11 @@
 #endif
 }
 
-// Include the auto-generated part of this file. We split this because it means
-// we can easily edit the non-auto generated parts right here in this file
-// instead of having to edit some template or the code generator.
-#include "gpu/command_buffer/service/raster_decoder_unittest_0_autogen.h"
-
 // GCC requires these declarations, but MSVC requires they not be present
 #ifndef COMPILER_MSVC
 const GLint RasterDecoderTestBase::kMaxTextureSize;
 const GLint RasterDecoderTestBase::kNumTextureUnits;
 
-const GLint RasterDecoderTestBase::kViewportX;
-const GLint RasterDecoderTestBase::kViewportY;
-const GLint RasterDecoderTestBase::kViewportWidth;
-const GLint RasterDecoderTestBase::kViewportHeight;
-
 const GLuint RasterDecoderTestBase::kServiceBufferId;
 const GLuint RasterDecoderTestBase::kServiceTextureId;
 const GLuint RasterDecoderTestBase::kServiceVertexArrayId;
diff --git a/gpu/command_buffer/service/raster_decoder_unittest_base.h b/gpu/command_buffer/service/raster_decoder_unittest_base.h
index 8b321db..042994e3 100644
--- a/gpu/command_buffer/service/raster_decoder_unittest_base.h
+++ b/gpu/command_buffer/service/raster_decoder_unittest_base.h
@@ -153,12 +153,6 @@
   typedef gles2::TestHelper::AttribInfo AttribInfo;
   typedef gles2::TestHelper::UniformInfo UniformInfo;
 
-  void SetupInitCapabilitiesExpectations(bool es3_capable);
-  void SetupInitStateExpectations(bool es3_capable);
-  void SetupInitStateManualExpectations(bool es3_capable);
-  void SetupInitStateManualExpectationsForDoLineWidth(GLfloat width);
-  void ExpectEnableDisable(GLenum cap, bool enable);
-
   gpu::Mailbox CreateFakeTexture(GLuint service_id,
                                  viz::ResourceFormat resource_format,
                                  GLsizei width,
@@ -198,11 +192,6 @@
   static const GLint kNumTextureUnits = 8;
   static const GLint kNumVertexAttribs = 16;
 
-  static const GLint kViewportX = 0;
-  static const GLint kViewportY = 0;
-  static const GLint kViewportWidth = 1;
-  static const GLint kViewportHeight = 1;
-
   static const GLuint kServiceBufferId = 301;
   static const GLuint kServiceTextureId = 304;
   static const GLuint kServiceVertexArrayId = 310;
diff --git a/gpu/command_buffer/service/shader_manager.h b/gpu/command_buffer/service/shader_manager.h
index 251311a..deb4a49 100644
--- a/gpu/command_buffer/service/shader_manager.h
+++ b/gpu/command_buffer/service/shader_manager.h
@@ -58,6 +58,7 @@
   // Returns true if we are ready to call DoCompile. If we have not yet called
   // RequestCompile or if we've already compiled, returns false.
   bool CanCompile() { return shader_state_ == kShaderStateCompileRequested; }
+  bool HasCompiled() { return shader_state_ == kShaderStateCompiled; }
   void DoCompile();
   void RefreshTranslatedShaderSource();
 
diff --git a/headless/lib/browser/headless_content_browser_client.cc b/headless/lib/browser/headless_content_browser_client.cc
index 426d586..6839764 100644
--- a/headless/lib/browser/headless_content_browser_client.cc
+++ b/headless/lib/browser/headless_content_browser_client.cc
@@ -322,11 +322,11 @@
       in_memory, relative_partition_path);
 }
 
-std::string HeadlessContentBrowserClient::GetProduct() const {
+std::string HeadlessContentBrowserClient::GetProduct() {
   return browser_->options()->product_name_and_version;
 }
 
-std::string HeadlessContentBrowserClient::GetUserAgent() const {
+std::string HeadlessContentBrowserClient::GetUserAgent() {
   return browser_->options()->user_agent;
 }
 
diff --git a/headless/lib/browser/headless_content_browser_client.h b/headless/lib/browser/headless_content_browser_client.h
index 1af66e1..4e0c3c2 100644
--- a/headless/lib/browser/headless_content_browser_client.h
+++ b/headless/lib/browser/headless_content_browser_client.h
@@ -68,8 +68,8 @@
       bool in_memory,
       const base::FilePath& relative_partition_path) override;
 
-  std::string GetProduct() const override;
-  std::string GetUserAgent() const override;
+  std::string GetProduct() override;
+  std::string GetUserAgent() override;
 
  private:
   std::unique_ptr<base::Value> GetBrowserServiceManifestOverlay();
diff --git a/infra/config/cr-buildbucket.cfg b/infra/config/cr-buildbucket.cfg
index 1bc2e70..5f79993d 100644
--- a/infra/config/cr-buildbucket.cfg
+++ b/infra/config/cr-buildbucket.cfg
@@ -786,6 +786,16 @@
   }
 }
 
+
+builder_mixins {
+  name: "xcode-11-caches"
+  caches: {
+    # Cache for Xcode 11 (build version 11m337n) needed for iOS FYI builds.
+    name: "xcode_ios_11m337n"
+    path: "xcode_ios_11m337n.app"
+  }
+}
+
 builder_mixins {
   name: "xcode-mac-9a235"
   caches: {
@@ -1995,7 +2005,7 @@
     builders { mixins: "ios-ci" mixins: "fyi-ci" name: "ios12-beta-simulator" }
     builders { mixins: "ios-ci" mixins: "fyi-ci" name: "ios13-beta-simulator" }
     builders { mixins: "ios-ci" mixins: "fyi-ci" name: "ios13-sdk-device" }
-    builders { mixins: "ios-ci" mixins: "fyi-ci" name: "ios13-sdk-simulator" }
+    builders { mixins: "ios-ci" mixins: "fyi-ci" mixins: "xcode-11-caches" name: "ios13-sdk-simulator" }
 
     # Win bots.
     builders {
@@ -4239,7 +4249,7 @@
     builders { mixins: "ios-try" name: "ios-uirefresh-simulator" }
     builders { mixins: "ios-try" name: "ios12-beta-simulator" }
     builders { mixins: "ios-try" name: "ios13-beta-simulator" }
-    builders { mixins: "ios-try" name: "ios13-sdk-simulator" }
+    builders { mixins: "ios-try" mixins: "xcode-11-caches" name: "ios13-sdk-simulator" }
     builders { mixins: "ios-try" name: "ios-simulator-full-configs" }
     builders { mixins: "ios-try" name: "ios-simulator-eg" }
     builders { mixins: "ios-try" name: "ios-simulator-xcode-clang" }
diff --git a/ios/chrome/browser/tabs/BUILD.gn b/ios/chrome/browser/tabs/BUILD.gn
index 872a462..d7d3462 100644
--- a/ios/chrome/browser/tabs/BUILD.gn
+++ b/ios/chrome/browser/tabs/BUILD.gn
@@ -19,15 +19,10 @@
     "//ios/web",
   ]
   deps = [
-    "//components/search_engines",
     "//components/sessions",
-    "//components/signin/ios/browser",
     "//components/sync_sessions",
     "//ios/chrome/browser/sessions:serialisation",
-    "//ios/chrome/browser/web:tab_helper_delegates",
     "//ios/chrome/browser/web_state_list",
-    "//ios/net",
-    "//ios/web/public",
     "//ui/base",
   ]
   libs = [ "UIKit.framework" ]
@@ -58,32 +53,18 @@
   deps = [
     ":tabs",
     "//base",
-    "//components/content_settings/core/browser",
-    "//components/favicon/core",
     "//components/favicon/ios",
-    "//components/google/core/browser",
     "//components/history/core/browser",
     "//components/history/ios/browser",
-    "//components/infobars/core",
-    "//components/keyed_service/core",
     "//components/language/ios/browser",
-    "//components/metrics_services_manager",
     "//components/navigation_metrics",
-    "//components/prefs",
-    "//components/reading_list/core",
-    "//components/search_engines",
     "//components/sessions",
     "//components/strings",
-    "//components/url_formatter",
     "//ios/chrome/app/strings",
     "//ios/chrome/browser",
-    "//ios/chrome/browser/app_launcher",
     "//ios/chrome/browser/autofill",
     "//ios/chrome/browser/autofill:autofill_internal",
-    "//ios/chrome/browser/bookmarks",
     "//ios/chrome/browser/browser_state",
-    "//ios/chrome/browser/content_settings",
-    "//ios/chrome/browser/crash_report:crash_report_internal",
     "//ios/chrome/browser/download",
     "//ios/chrome/browser/download:features",
     "//ios/chrome/browser/favicon",
@@ -94,7 +75,6 @@
     "//ios/chrome/browser/infobars",
     "//ios/chrome/browser/infobars:badge",
     "//ios/chrome/browser/itunes_urls",
-    "//ios/chrome/browser/language",
     "//ios/chrome/browser/metrics",
     "//ios/chrome/browser/metrics:metrics_internal",
     "//ios/chrome/browser/network_activity:tab_helper",
@@ -113,32 +93,20 @@
     "//ios/chrome/browser/translate",
     "//ios/chrome/browser/u2f",
     "//ios/chrome/browser/ui:feature_flags",
-    "//ios/chrome/browser/ui/alert_coordinator",
-    "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/infobars:feature_flags",
     "//ios/chrome/browser/ui/open_in",
-    "//ios/chrome/browser/ui/overscroll_actions",
-    "//ios/chrome/browser/ui/util",
     "//ios/chrome/browser/voice",
     "//ios/chrome/browser/web",
     "//ios/chrome/browser/web:feature_flags",
-    "//ios/chrome/browser/web:tab_helper_delegates",
     "//ios/chrome/browser/web:web_internal",
     "//ios/chrome/browser/web_state_list",
     "//ios/chrome/browser/web_state_list/web_usage_enabler",
-    "//ios/net",
     "//ios/public/provider/chrome/browser",
-    "//ios/web",
-    "//ios/web/public",
-    "//ios/web/public/deprecated",
     "//ios/web/public/security",
     "//ios/web/public/session",
-    "//net",
     "//ui/base",
-    "//url",
   ]
   libs = [
-    "CoreLocation.framework",
     "Foundation.framework",
     "UIKit.framework",
   ]
diff --git a/ios/chrome/browser/tabs/tab.h b/ios/chrome/browser/tabs/tab.h
index 13da8d44..70d6ccd 100644
--- a/ios/chrome/browser/tabs/tab.h
+++ b/ios/chrome/browser/tabs/tab.h
@@ -7,21 +7,9 @@
 
 #import <UIKit/UIKit.h>
 
-#include <memory>
-#include <vector>
-
 #include "ios/web/public/user_agent.h"
 #include "ui/base/page_transition_types.h"
 
-@class AutofillController;
-@class CastController;
-class GURL;
-@class OpenInController;
-@class PasswordController;
-@class SnapshotManager;
-@class FormSuggestionController;
-@class Tab;
-
 namespace web {
 class WebState;
 }
diff --git a/ios/chrome/browser/tabs/tab.mm b/ios/chrome/browser/tabs/tab.mm
index 1081e526..3e4f905 100644
--- a/ios/chrome/browser/tabs/tab.mm
+++ b/ios/chrome/browser/tabs/tab.mm
@@ -3,99 +3,18 @@
 // found in the LICENSE file.
 
 #import "ios/chrome/browser/tabs/tab.h"
-
-#import <CoreLocation/CoreLocation.h>
-#import <UIKit/UIKit.h>
-
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/feature_list.h"
-#include "base/ios/block_types.h"
-#include "base/json/string_escape.h"
-#include "base/logging.h"
-#include "base/mac/foundation_util.h"
-#include "base/memory/ptr_util.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/metrics/user_metrics.h"
-#include "base/metrics/user_metrics_action.h"
-#include "base/scoped_observer.h"
-#include "base/strings/string_split.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/time/time.h"
-#include "components/google/core/common/google_util.h"
-#include "components/history/core/browser/history_context.h"
-#include "components/history/core/browser/history_service.h"
-#include "components/history/core/browser/top_sites.h"
-#include "components/history/ios/browser/web_state_top_sites_observer.h"
-#include "components/infobars/core/infobar_manager.h"
-#include "components/keyed_service/core/service_access_type.h"
-#include "components/metrics_services_manager/metrics_services_manager.h"
-#include "components/prefs/pref_service.h"
-#include "components/reading_list/core/reading_list_model.h"
-#include "components/search_engines/template_url_service.h"
-#include "components/strings/grit/components_strings.h"
-#include "components/url_formatter/url_formatter.h"
-#include "ios/chrome/browser/application_context.h"
-#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
-#include "ios/chrome/browser/chrome_url_constants.h"
-#import "ios/chrome/browser/download/download_manager_tab_helper.h"
-#import "ios/chrome/browser/find_in_page/find_in_page_controller.h"
-#include "ios/chrome/browser/history/history_service_factory.h"
-#include "ios/chrome/browser/history/history_tab_helper.h"
-#include "ios/chrome/browser/history/top_sites_factory.h"
-#include "ios/chrome/browser/infobars/infobar_manager_impl.h"
-#import "ios/chrome/browser/metrics/tab_usage_recorder.h"
-#include "ios/chrome/browser/pref_names.h"
-#include "ios/chrome/browser/reading_list/reading_list_model_factory.h"
-#include "ios/chrome/browser/search_engines/template_url_service_factory.h"
-#import "ios/chrome/browser/snapshots/snapshot_cache.h"
-#import "ios/chrome/browser/snapshots/snapshot_cache_factory.h"
-#import "ios/chrome/browser/snapshots/snapshot_tab_helper.h"
-#include "ios/chrome/browser/system_flags.h"
-#import "ios/chrome/browser/tabs/legacy_tab_helper.h"
-#import "ios/chrome/browser/tabs/tab_helper_util.h"
 #import "ios/chrome/browser/tabs/tab_private.h"
-#include "ios/chrome/browser/translate/chrome_ios_translate_client.h"
-#import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
-#import "ios/chrome/browser/ui/commands/show_signin_command.h"
+
+#include "base/strings/sys_string_conversions.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #import "ios/chrome/browser/ui/open_in/open_in_controller.h"
-#include "ios/chrome/browser/ui/util/ui_util.h"
-#import "ios/chrome/browser/web/page_placeholder_tab_helper.h"
-#import "ios/chrome/browser/web/tab_id_tab_helper.h"
 #include "ios/chrome/grit/ios_strings.h"
-#import "ios/web/navigation/navigation_manager_impl.h"
-#import "ios/web/public/deprecated/crw_js_injection_receiver.h"
-#include "ios/web/public/favicon/favicon_status.h"
-#include "ios/web/public/favicon/favicon_url.h"
-#import "ios/web/public/navigation_item.h"
-#import "ios/web/public/navigation_manager.h"
-#include "ios/web/public/referrer.h"
-#include "ios/web/public/security/ssl_status.h"
-#include "ios/web/public/security/web_interstitial.h"
-#import "ios/web/public/session/serializable_user_data_manager.h"
-#include "ios/web/public/thread/web_thread.h"
-#include "ios/web/public/url_scheme_util.h"
-#include "ios/web/public/web_client.h"
-#import "ios/web/public/web_state/navigation_context.h"
-#import "ios/web/public/web_state/web_state.h"
 #import "ios/web/public/web_state/web_state_observer_bridge.h"
 #import "ios/web/web_state/ui/crw_web_controller.h"
 #import "ios/web/web_state/web_state_impl.h"
-#include "net/base/escape.h"
 #include "net/base/filename_util.h"
-#import "net/base/mac/url_conversions.h"
-#include "net/base/net_errors.h"
-#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
-#include "net/cert/x509_certificate.h"
-#include "net/http/http_response_headers.h"
-#include "net/url_request/url_fetcher.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/base/page_transition_types.h"
-#include "url/origin.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
diff --git a/ios/chrome/browser/tabs/tab_private.h b/ios/chrome/browser/tabs/tab_private.h
index 4abd1f6..8c9502f 100644
--- a/ios/chrome/browser/tabs/tab_private.h
+++ b/ios/chrome/browser/tabs/tab_private.h
@@ -6,6 +6,7 @@
 #define IOS_CHROME_BROWSER_TABS_TAB_PRIVATE_H_
 
 @class CRWWebController;
+@class OpenInController;
 
 // Exposed private methods for testing purpose.
 @interface Tab ()
diff --git a/ios/chrome/browser/tabs/tab_unittest.mm b/ios/chrome/browser/tabs/tab_unittest.mm
index b3dc40e9..2ceac7e 100644
--- a/ios/chrome/browser/tabs/tab_unittest.mm
+++ b/ios/chrome/browser/tabs/tab_unittest.mm
@@ -294,6 +294,7 @@
   }
 
   void CheckCurrentItem(const GURL& expectedUrl, NSString* expectedTitle) {
+    OCMStub([mock_web_view_ URL]).andReturn(net::NSURLWithGURL(expectedUrl));
     web::NavigationItem* item =
         web_state_impl_->GetNavigationManager()->GetVisibleItem();
     EXPECT_EQ(expectedUrl, item->GetURL());
@@ -301,6 +302,8 @@
   }
 
   void CheckCurrentItem(const history::URLResult& historyResult) {
+    OCMStub([mock_web_view_ URL])
+        .andReturn(net::NSURLWithGURL(historyResult.url()));
     web::NavigationItem* item =
         web_state_impl_->GetNavigationManager()->GetVisibleItem();
     CheckHistoryResult(historyResult, item->GetURL(),
diff --git a/ios/chrome/browser/ui/authentication/BUILD.gn b/ios/chrome/browser/ui/authentication/BUILD.gn
index c596be0..4ca622b 100644
--- a/ios/chrome/browser/ui/authentication/BUILD.gn
+++ b/ios/chrome/browser/ui/authentication/BUILD.gn
@@ -146,6 +146,7 @@
 }
 
 source_set("eg_test_support") {
+  defines = [ "CHROME_EARL_GREY_1" ]
   configs += [ "//build/config/compiler:enable_arc" ]
   testonly = true
   sources = [
@@ -153,6 +154,8 @@
     "signin_earl_grey_ui.mm",
     "signin_earlgrey_utils.h",
     "signin_earlgrey_utils.mm",
+    "signin_earlgrey_utils_app_interface.h",
+    "signin_earlgrey_utils_app_interface.mm",
   ]
   deps = [
     ":authentication",
@@ -171,6 +174,7 @@
     "//ios/chrome/test/earl_grey:test_support",
     "//ios/public/provider/chrome/browser/signin",
     "//ios/public/provider/chrome/browser/signin:test_support",
+    "//ios/testing/earl_grey:earl_grey_support",
     "//ios/third_party/earl_grey:earl_grey+link",
     "//services/identity/public/cpp",
   ]
diff --git a/ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h b/ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h
index 3c4bfdf..6c5d665 100644
--- a/ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h
+++ b/ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h
@@ -6,28 +6,34 @@
 #define IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_EARLGREY_UTILS_H_
 
 #import <Foundation/Foundation.h>
+
 #include "base/compiler_specific.h"
+#import "ios/testing/earl_grey/base_eg_test_helper_impl.h"
 
 @class ChromeIdentity;
 
+#define SigninEarlGreyUtils \
+  [SigninEarlGreyUtilsImpl invokedFromFile:@"" __FILE__ lineNumber:__LINE__]
+
 // Methods used for the EarlGrey tests.
-@interface SigninEarlGreyUtils : NSObject
+// TODO(crbug.com/974833): Consider moving these into ChromeEarlGrey.
+@interface SigninEarlGreyUtilsImpl : BaseEGTestHelperImpl
 
 // Returns a fake identity.
-+ (ChromeIdentity*)fakeIdentity1;
+- (ChromeIdentity*)fakeIdentity1;
 
 // Returns a second fake identity.
-+ (ChromeIdentity*)fakeIdentity2;
+- (ChromeIdentity*)fakeIdentity2;
 
 // Returns a fake managed identity.
-+ (ChromeIdentity*)fakeManagedIdentity;
+- (ChromeIdentity*)fakeManagedIdentity;
 
 // Checks that |identity| is actually signed in to the active profile.
-+ (NSError*)checkSignedInWithIdentity:(ChromeIdentity*)identity
+- (NSError*)checkSignedInWithIdentity:(ChromeIdentity*)identity
     WARN_UNUSED_RESULT;
 
 // Checks that no identity is signed in.
-+ (NSError*)checkSignedOut WARN_UNUSED_RESULT;
+- (NSError*)checkSignedOut WARN_UNUSED_RESULT;
 
 @end
 
diff --git a/ios/chrome/browser/ui/authentication/signin_earlgrey_utils.mm b/ios/chrome/browser/ui/authentication/signin_earlgrey_utils.mm
index bf5eb4272..302af9d9 100644
--- a/ios/chrome/browser/ui/authentication/signin_earlgrey_utils.mm
+++ b/ios/chrome/browser/ui/authentication/signin_earlgrey_utils.mm
@@ -6,82 +6,67 @@
 
 #import <EarlGrey/EarlGrey.h>
 
-#include "base/strings/sys_string_conversions.h"
-#include "components/signin/core/browser/account_info.h"
-#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
-#include "ios/chrome/browser/signin/identity_manager_factory.h"
-#import "ios/chrome/test/app/chrome_test_util.h"
+#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.h"
 #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity.h"
-#import "ios/testing/nserror_util.h"
-#include "services/identity/public/cpp/identity_manager.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
-@implementation SigninEarlGreyUtils
+#if defined(CHROME_EARL_GREY_2)
+GREY_STUB_CLASS_IN_APP_MAIN_QUEUE(SigninEarlGreyUtilsAppInterface)
+#endif  // defined(CHROME_EARL_GREY_2)
 
-+ (ChromeIdentity*)fakeIdentity1 {
+@implementation SigninEarlGreyUtilsImpl
+
+- (ChromeIdentity*)fakeIdentity1 {
   return [FakeChromeIdentity identityWithEmail:@"foo1@gmail.com"
                                         gaiaID:@"foo1ID"
                                           name:@"Fake Foo 1"];
 }
 
-+ (ChromeIdentity*)fakeIdentity2 {
+- (ChromeIdentity*)fakeIdentity2 {
   return [FakeChromeIdentity identityWithEmail:@"foo2@gmail.com"
                                         gaiaID:@"foo2ID"
                                           name:@"Fake Foo 2"];
 }
 
-+ (ChromeIdentity*)fakeManagedIdentity {
+- (ChromeIdentity*)fakeManagedIdentity {
   return [FakeChromeIdentity identityWithEmail:@"foo@managed.com"
                                         gaiaID:@"fooManagedID"
                                           name:@"Fake Managed"];
 }
 
-+ (NSError*)checkSignedInWithIdentity:(ChromeIdentity*)identity {
-  if (identity == nil) {
-    return testing::NSErrorWithLocalizedDescription(
-        @"Need to give an identity");
-  }
+- (NSError*)checkSignedInWithIdentity:(ChromeIdentity*)identity {
+  BOOL identityIsNonNil = identity != nil;
+  EG_TEST_HELPER_ASSERT_TRUE(identityIsNonNil, @"Need to give an identity");
 
   // Required to avoid any problem since the following test is not dependant
   // to UI, and the previous action has to be totally finished before going
   // through the assert.
   [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
 
-  ios::ChromeBrowserState* browser_state =
-      chrome_test_util::GetOriginalBrowserState();
-  CoreAccountInfo info =
-      IdentityManagerFactory::GetForBrowserState(browser_state)
-          ->GetPrimaryAccountInfo();
+  NSString* primaryAccountGaiaID =
+      [SignInEarlGreyUtilsAppInterface primaryAccountGaiaID];
 
-  if (base::SysNSStringToUTF8(identity.gaiaID) != info.gaia) {
-    NSString* errorStr =
-        [NSString stringWithFormat:
-                      @"Unexpected Gaia ID of the signed in user [expected = "
-                      @"\"%@\", actual = \"%s\"]",
-                      identity.gaiaID, info.gaia.c_str()];
-    return testing::NSErrorWithLocalizedDescription(errorStr);
-  }
+  NSString* errorStr = [NSString
+      stringWithFormat:@"Unexpected Gaia ID of the signed in user [expected = "
+                       @"\"%@\", actual = \"%@\"]",
+                       identity.gaiaID, primaryAccountGaiaID];
+  EG_TEST_HELPER_ASSERT_TRUE(
+      [identity.gaiaID isEqualToString:primaryAccountGaiaID], errorStr);
 
   return nil;
 }
 
-+ (NSError*)checkSignedOut {
+- (NSError*)checkSignedOut {
   // Required to avoid any problem since the following test is not dependant to
   // UI, and the previous action has to be totally finished before going through
   // the assert.
   [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
 
-  ios::ChromeBrowserState* browser_state =
-      chrome_test_util::GetOriginalBrowserState();
-
-  if (IdentityManagerFactory::GetForBrowserState(browser_state)
-          ->HasPrimaryAccount()) {
-    return testing::NSErrorWithLocalizedDescription(
-        @"Unexpected signed in user");
-  }
+  EG_TEST_HELPER_ASSERT_TRUE([SignInEarlGreyUtilsAppInterface isSignedOut],
+                             @"Unexpected signed in user");
 
   return nil;
 }
diff --git a/ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.h b/ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.h
new file mode 100644
index 0000000..186eadd
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.h
@@ -0,0 +1,25 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_EARLGREY_UTILS_APP_INTERFACE_H_
+#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_EARLGREY_UTILS_APP_INTERFACE_H_
+
+#import <Foundation/Foundation.h>
+
+@class ChromeIdentity;
+
+// SignInEarlGreyAppInterface contains the app-side implementation for helpers
+// that primarily work via direct model access. These helpers are compiled into
+// the app binary and can be called from either app or test code.
+@interface SignInEarlGreyUtilsAppInterface : NSObject
+
+// Returns the gaia ID of the signed-in account.
++ (NSString*)primaryAccountGaiaID;
+
+// Checks that no identity is signed in.
++ (BOOL)isSignedOut;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_EARLGREY_UTILS_APP_INTERFACE_H_
diff --git a/ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.mm b/ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.mm
new file mode 100644
index 0000000..a3a7538
--- /dev/null
+++ b/ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.mm
@@ -0,0 +1,39 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.h"
+
+#include "base/strings/sys_string_conversions.h"
+#include "components/signin/core/browser/account_info.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/chrome/browser/signin/identity_manager_factory.h"
+#import "ios/chrome/test/app/chrome_test_util.h"
+#import "ios/public/provider/chrome/browser/signin/fake_chrome_identity.h"
+#include "services/identity/public/cpp/identity_manager.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@implementation SignInEarlGreyUtilsAppInterface
+
++ (NSString*)primaryAccountGaiaID {
+  ios::ChromeBrowserState* browser_state =
+      chrome_test_util::GetOriginalBrowserState();
+  CoreAccountInfo info =
+      IdentityManagerFactory::GetForBrowserState(browser_state)
+          ->GetPrimaryAccountInfo();
+
+  return base::SysUTF8ToNSString(info.gaia);
+}
+
++ (BOOL)isSignedOut {
+  ios::ChromeBrowserState* browser_state =
+      chrome_test_util::GetOriginalBrowserState();
+
+  return !IdentityManagerFactory::GetForBrowserState(browser_state)
+              ->HasPrimaryAccount();
+}
+
+@end
diff --git a/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm
index 3717dfd..08155e8 100644
--- a/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm
+++ b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm
@@ -4,6 +4,8 @@
 
 #import "ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.h"
 
+#include "base/metrics/user_metrics.h"
+#include "base/metrics/user_metrics_action.h"
 #include "ios/chrome/browser/infobars/infobar_metrics_recorder.h"
 #import "ios/chrome/browser/ui/infobars/banners/infobar_banner_constants.h"
 #import "ios/chrome/browser/ui/infobars/banners/infobar_banner_delegate.h"
@@ -283,6 +285,8 @@
         (self.view.center.y - self.originalCenter.y >
          kChangeInPositionForTransition);
     if (dragDownExceededThreshold) {
+      base::RecordAction(
+          base::UserMetricsAction("MobileMessagesBannerDraggedDown"));
       [self.metricsRecorder
           recordBannerDismissType:MobileMessagesBannerDismissType::
                                       ExpandedToModal];
@@ -386,6 +390,7 @@
 }
 
 - (void)presentInfobarModalAfterTap {
+  base::RecordAction(base::UserMetricsAction("MobileMessagesBannerTapped"));
   [self.metricsRecorder
       recordBannerDismissType:MobileMessagesBannerDismissType::TappedToModal];
   [self.delegate presentInfobarModalFromBanner];
diff --git a/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.mm b/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.mm
index d2728cc..b86f08a 100644
--- a/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.mm
+++ b/ios/chrome/browser/ui/infobars/modals/infobar_password_table_view_controller.mm
@@ -6,6 +6,8 @@
 
 #include "base/logging.h"
 #include "base/mac/foundation_util.h"
+#include "base/metrics/user_metrics.h"
+#include "base/metrics/user_metrics_action.h"
 #include "ios/chrome/browser/infobars/infobar_metrics_recorder.h"
 #import "ios/chrome/browser/passwords/ios_chrome_password_infobar_metrics_recorder.h"
 #import "ios/chrome/browser/ui/infobars/modals/infobar_modal_constants.h"
@@ -300,6 +302,8 @@
 }
 
 - (void)dismissInfobarModal:(UIButton*)sender {
+  base::RecordAction(
+      base::UserMetricsAction("MobileMessagesModalCancelledTapped"));
   [self.metricsRecorder recordModalEvent:MobileMessagesModalEvent::Canceled];
   [self.infobarModalDelegate dismissInfobarModal:sender
                                         animated:YES
@@ -307,6 +311,8 @@
 }
 
 - (void)saveCredentialsButtonWasPressed:(UIButton*)sender {
+  base::RecordAction(
+      base::UserMetricsAction("MobileMessagesModalAcceptedTapped"));
   [self.metricsRecorder recordModalEvent:MobileMessagesModalEvent::Accepted];
   if ([self.saveCredentialsItem.buttonText
           isEqualToString:l10n_util::GetNSString(
@@ -325,12 +331,14 @@
 }
 
 - (void)presentPasswordSettings {
+  base::RecordAction(base::UserMetricsAction("MobileMessagesModalSettings"));
   [self.metricsRecorder
       recordModalEvent:MobileMessagesModalEvent::SettingsOpened];
   [self.infobarModalDelegate presentPasswordSettings];
 }
 
 - (void)neverSaveCredentialsForCurrentSite {
+  base::RecordAction(base::UserMetricsAction("MobileMessagesModalNever"));
   [self.passwordMetricsRecorder
       recordModalDismiss:MobileMessagesPasswordsModalDismiss::
                              TappedNeverForThisSite];
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm
index 3428cc38..2c95e045 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm
@@ -474,9 +474,16 @@
 }
 
 - (void)displayModalInfobar {
-  MobileMessagesBadgeState state = self.activeBadge
-                                       ? MobileMessagesBadgeState::Active
-                                       : MobileMessagesBadgeState::Inactive;
+  MobileMessagesBadgeState state;
+  if (self.activeBadge) {
+    state = MobileMessagesBadgeState::Active;
+    base::RecordAction(
+        base::UserMetricsAction("MobileMessagesBadgeAcceptedTapped"));
+  } else {
+    state = MobileMessagesBadgeState::Inactive;
+    base::RecordAction(
+        base::UserMetricsAction("MobileMessagesBadgeNonAcceptedTapped"));
+  }
   [self.infobarMetricsRecorder recordBadgeTappedInState:state];
   [self.dispatcher displayModalInfobar];
 }
diff --git a/ios/chrome/browser/ui/tabs/tab_view_delegate.h b/ios/chrome/browser/ui/tabs/tab_view_delegate.h
index 5da8f6c..ecc13449 100644
--- a/ios/chrome/browser/ui/tabs/tab_view_delegate.h
+++ b/ios/chrome/browser/ui/tabs/tab_view_delegate.h
@@ -5,6 +5,7 @@
 #ifndef IOS_CHROME_BROWSER_UI_TABS_TAB_VIEW_DELEGATE_H_
 #define IOS_CHROME_BROWSER_UI_TABS_TAB_VIEW_DELEGATE_H_
 
+class GURL;
 @class TabView;
 
 // Protocol to observe events occuring in the tab view.
diff --git a/ios/web/navigation/OWNERS b/ios/web/navigation/OWNERS
index e639d04..4488d78ab 100644
--- a/ios/web/navigation/OWNERS
+++ b/ios/web/navigation/OWNERS
@@ -1,6 +1,8 @@
+ajuma@chromium.org
 danyao@chromium.org
 eugenebut@chromium.org
 kkhorimoto@chromium.org
 
 # TEAM: ios-directory-owners@chromium.org
 # OS: iOS
+# COMPONENT: UI>Browser>Navigation
\ No newline at end of file
diff --git a/ios/web/navigation/crw_wk_navigation_handler.mm b/ios/web/navigation/crw_wk_navigation_handler.mm
index 4e9131d..bbcc665c 100644
--- a/ios/web/navigation/crw_wk_navigation_handler.mm
+++ b/ios/web/navigation/crw_wk_navigation_handler.mm
@@ -1860,7 +1860,18 @@
         handleCancelledErrorForContext:navigationContext];
 
     if (provisionalLoad) {
-      self.webStateImpl->OnNavigationFinished(navigationContext);
+      if (!navigationContext &&
+          web::RequiresProvisionalNavigationFailureWorkaround()) {
+        // It is likely that |navigationContext| is null because
+        // didStartProvisionalNavigation: was not called with this WKNavigation
+        // object. Log UMA to know when this workaround can be removed and
+        // do not call OnNavigationFinished() to avoid crash on null pointer
+        // dereferencing. See crbug.com/973653 for details.
+        UMA_HISTOGRAM_BOOLEAN(
+            "Navigation.IOSNullContextInDidFailProvisionalNavigation", true);
+      } else {
+        self.webStateImpl->OnNavigationFinished(navigationContext);
+      }
     }
   } else if (!provisionalLoad) {
     web::NavigationItemImpl* item =
diff --git a/ios/web/navigation/navigation_manager_impl_unittest.mm b/ios/web/navigation/navigation_manager_impl_unittest.mm
index 884d83b..2588ece 100644
--- a/ios/web/navigation/navigation_manager_impl_unittest.mm
+++ b/ios/web/navigation/navigation_manager_impl_unittest.mm
@@ -1854,6 +1854,8 @@
   navigation_manager()->GetPendingItem()->SetVirtualURL(virtual_url);
   [mock_wk_list_ setCurrentURL:@"http://www.1.com"];
   navigation_manager()->CommitPendingItem();
+  OCMExpect([mock_web_view_ URL])
+      .andReturn([[NSURL alloc] initWithString:@"http://www.1.com"]);
 
   EXPECT_CALL(navigation_manager_delegate(), WillChangeUserAgentType());
   EXPECT_CALL(navigation_manager_delegate(), RecordPageStateInNavigationItem());
@@ -2296,7 +2298,11 @@
   }
   ASSERT_EQ(0, navigation_manager()->GetPendingItemIndex());
 
+  OCMExpect([mock_web_view_ URL])
+      .andReturn([[NSURL alloc] initWithString:@"http://www.url.com/0"]);
   ASSERT_TRUE(navigation_manager()->GetVisibleItem());
+  OCMExpect([mock_web_view_ URL])
+      .andReturn([[NSURL alloc] initWithString:@"http://www.url.com/0"]);
   EXPECT_EQ("http://www.url.com/1",
             navigation_manager()->GetVisibleItem()->GetURL().spec());
 }
@@ -2315,7 +2321,11 @@
       web::NavigationInitiationType::RENDERER_INITIATED,
       web::NavigationManager::UserAgentOverrideOption::INHERIT);
 
+  OCMExpect([mock_web_view_ URL])
+      .andReturn([[NSURL alloc] initWithString:@"http://www.url.com/0"]);
   ASSERT_TRUE(navigation_manager()->GetVisibleItem());
+  OCMExpect([mock_web_view_ URL])
+      .andReturn([[NSURL alloc] initWithString:@"http://www.url.com/0"]);
   EXPECT_EQ("http://www.url.com/0",
             navigation_manager()->GetVisibleItem()->GetURL().spec());
 }
diff --git a/ios/web/navigation/wk_based_navigation_manager_impl.h b/ios/web/navigation/wk_based_navigation_manager_impl.h
index 0991390f..b791106 100644
--- a/ios/web/navigation/wk_based_navigation_manager_impl.h
+++ b/ios/web/navigation/wk_based_navigation_manager_impl.h
@@ -182,6 +182,10 @@
     // DetachFromWebView().
     int GetCurrentItemIndex() const;
 
+    // Returns the visible WKWebView URL. If navigation manager is detached,
+    // returns an empty GURL.
+    GURL GetVisibleWebViewURL() const;
+
     // Returns the NavigationItem associated with the WKBackForwardListItem at
     // |index|. If |create_if_missing| is true and the WKBackForwardListItem
     // does not have an associated NavigationItem, creates a new one and returns
@@ -231,6 +235,19 @@
   void UnsafeRestore(int last_committed_item_index,
                      std::vector<std::unique_ptr<NavigationItem>> items);
 
+  // Returns true if |last_committed_item| matches WKWebView.URL when expected.
+  // WKWebView is more aggressive than Chromium is in updating the visible URL,
+  // and there are cases where, even though WKWebView's URL has updated,
+  // Chromium still wants to display last committed.  Normally this is managed
+  // by WKBasedNavigationManagerImpl last committed, but there are short periods
+  // during fast navigations where WKWebView.URL has updated and ios/web can't
+  // validate what should be shown for the visible item.  More importantly,
+  // there are bugs in WkWebView where WKWebView's URL and
+  // backForwardList.currentItem can fall out of sync.  In these situations,
+  // return false as a safeguard so visible item is always trusted.
+  bool CanTrustLastCommittedItemForVisibleItem(
+      const NavigationItem* last_committed_item) const;
+
   // The pending main frame navigation item. This is nullptr if there is no
   // pending item or if the pending item is a back-forward navigation, in which
   // case the NavigationItemImpl is stored on the WKBackForwardListItem.
@@ -259,6 +276,11 @@
   // The transient item in main frame.
   std::unique_ptr<NavigationItemImpl> transient_item_;
 
+  // A placeholder item used when CanTrustLastCommittedItemForVisibleItem
+  // returns false.  The navigation item returned uses crw_web_controller's
+  // documentURL as the URL.
+  mutable std::unique_ptr<NavigationItemImpl> visible_web_view_item_;
+
   // Time smoother for navigation item timestamps. See comment in
   // navigation_controller_impl.h.
   // NOTE: This is mutable because GetNavigationItemImplAtIndex() needs to call
@@ -273,6 +295,11 @@
   // OnNavigationItemCommitted() callback.
   bool is_restore_session_in_progress_ = false;
 
+  // Set to true when delegate_->GoToBackForwardListItem is being called, which
+  // is useful to know when comparing the VisibleWebViewURL with the last
+  // committed item.
+  bool going_to_back_forward_list_item_ = false;
+
   // Non null during the session restoration. Created when session restoration
   // is started and reset when the restoration is finished. Used to log UMA
   // histogram that measures session restoration time.
diff --git a/ios/web/navigation/wk_based_navigation_manager_impl.mm b/ios/web/navigation/wk_based_navigation_manager_impl.mm
index 82fab52..dd8035bc 100644
--- a/ios/web/navigation/wk_based_navigation_manager_impl.mm
+++ b/ios/web/navigation/wk_based_navigation_manager_impl.mm
@@ -24,6 +24,7 @@
 #import "ios/web/navigation/wk_navigation_util.h"
 #import "ios/web/public/navigation_item.h"
 #import "ios/web/public/web_client.h"
+#import "ios/web/public/web_state/web_state.h"
 #import "ios/web/web_state/ui/crw_web_view_navigation_proxy.h"
 #import "net/base/mac/url_conversions.h"
 
@@ -397,6 +398,45 @@
   return delegate_->GetWebState();
 }
 
+bool WKBasedNavigationManagerImpl::CanTrustLastCommittedItemForVisibleItem(
+    const NavigationItem* last_committed_item) const {
+  DCHECK(last_committed_item);
+  if (!web_view_cache_.IsAttachedToWebView())
+    return true;
+
+  // Only compare origins, as any mismatch between |web_view_url| and
+  // |last_committed_url| with the same origin are safe to return as
+  // visible.
+  GURL web_view_url = web_view_cache_.GetVisibleWebViewURL();
+  GURL last_committed_url = last_committed_item->GetURL();
+  if (web_view_url.GetOrigin() == last_committed_url.GetOrigin())
+    return true;
+
+  // Fast back-forward navigations can be performed synchronously, with the
+  // WKWebView.URL updated before enough callbacks occur to update the
+  // last committed item.  As a result, any calls to
+  // -CanTrustLastCommittedItemForVisibleItem during a call to WKWebView
+  // -goToBackForwardListItem are wrapped in the
+  // |going_to_back_forward_list_item_| flag. This flag is set and immediately
+  // unset because the the mismatch between URL and last_committed_item is
+  // expected.
+  if (going_to_back_forward_list_item_)
+    return true;
+
+  // WKWebView.URL will update immediately when navigating to and from
+  // about, file or chrome scheme URLs.
+  if (web_view_url.SchemeIs(url::kAboutScheme) ||
+      last_committed_url.SchemeIs(url::kAboutScheme) ||
+      web_view_url.SchemeIs(url::kFileScheme) ||
+      last_committed_url.SchemeIs(url::kAboutScheme) ||
+      web::GetWebClient()->IsAppSpecificURL(web_view_url) ||
+      web::GetWebClient()->IsAppSpecificURL(last_committed_url)) {
+    return true;
+  }
+
+  return false;
+}
+
 NavigationItem* WKBasedNavigationManagerImpl::GetVisibleItem() const {
   if (is_restore_session_in_progress_ || restored_visible_item_)
     return restored_visible_item_.get();
@@ -417,9 +457,30 @@
       return pending_item;
     }
   }
+
   NavigationItem* last_committed_item = GetLastCommittedItem();
-  if (last_committed_item)
-    return last_committed_item;
+  if (last_committed_item) {
+    if (CanTrustLastCommittedItemForVisibleItem(last_committed_item)) {
+      return last_committed_item;
+    } else {
+      auto trust_level = web::URLVerificationTrustLevel::kNone;
+      // Don't check trust level here, as at this point it's expected
+      // the _documentURL and the last_commited_item URL have an origin
+      // mismatch.
+      GURL document_url = delegate_->GetWebState()->GetCurrentURL(&trust_level);
+      if (!visible_web_view_item_) {
+        visible_web_view_item_ = CreateNavigationItemWithRewriters(
+            GURL::EmptyGURL(), Referrer(),
+            ui::PageTransition::PAGE_TRANSITION_LINK,
+            NavigationInitiationType::RENDERER_INITIATED, GURL::EmptyGURL(),
+            nullptr /* use default rewriters only */);
+      }
+      visible_web_view_item_->SetURL(document_url);
+      visible_web_view_item_->SetTimestamp(
+          time_smoother_.GetSmoothedTime(base::Time::Now()));
+      return visible_web_view_item_.get();
+    }
+  }
 
   // While an -IsRestoreSessionUrl URL can not be a committed page, it is
   // OK to display it as a visible URL.  This prevents seeing about:blank while
@@ -774,7 +835,9 @@
       item->GetTransitionType() | ui::PAGE_TRANSITION_FORWARD_BACK));
   WKBackForwardListItem* wk_item = web_view_cache_.GetWKItemAtIndex(index);
   if (wk_item) {
+    going_to_back_forward_list_item_ = true;
     delegate_->GoToBackForwardListItem(wk_item, item, type, has_user_gesture);
+    going_to_back_forward_list_item_ = false;
   } else {
     DCHECK(index == 0 && empty_window_open_item_)
         << " wk_item should not be nullptr. index: " << index
@@ -887,6 +950,18 @@
   return 0;
 }
 
+GURL WKBasedNavigationManagerImpl::WKWebViewCache::GetVisibleWebViewURL()
+    const {
+  if (!IsAttachedToWebView())
+    return GURL();
+
+  id<CRWWebViewNavigationProxy> proxy =
+      navigation_manager_->delegate_->GetWebViewNavigationProxy();
+  if (proxy)
+    return net::GURLWithNSURL(proxy.URL);
+  return GURL();
+}
+
 int WKBasedNavigationManagerImpl::WKWebViewCache::GetCurrentItemIndex() const {
   if (!IsAttachedToWebView())
     return cached_current_item_index_;
diff --git a/ios/web/navigation/wk_based_navigation_manager_impl_unittest.mm b/ios/web/navigation/wk_based_navigation_manager_impl_unittest.mm
index 4eb36c0..ab59ad0 100644
--- a/ios/web/navigation/wk_based_navigation_manager_impl_unittest.mm
+++ b/ios/web/navigation/wk_based_navigation_manager_impl_unittest.mm
@@ -799,6 +799,8 @@
 
   [mock_wk_list_ setCurrentURL:@"http://www.2.com"];
   manager_->CommitPendingItem();
+  OCMExpect([mock_web_view_ URL])
+      .andReturn([[NSURL alloc] initWithString:@"http://www.2.com"]);
 
   const NavigationItem* last_committed_item_2 =
       manager_->GetLastCommittedItem();
diff --git a/ios/web/session/OWNERS b/ios/web/session/OWNERS
new file mode 100644
index 0000000..b57bf3f8
--- /dev/null
+++ b/ios/web/session/OWNERS
@@ -0,0 +1,6 @@
+eugenebut@chromium.org
+kkhorimoto@chromium.org
+
+# TEAM: ios-directory-owners@chromium.org
+# OS: iOS
+# COMPONENT: UI>Browser>Sessions
diff --git a/ios/web/web_state/web_state_impl.mm b/ios/web/web_state/web_state_impl.mm
index f258d2dab..1d03944 100644
--- a/ios/web/web_state/web_state_impl.mm
+++ b/ios/web/web_state/web_state_impl.mm
@@ -742,6 +742,9 @@
                        << " Last committed: " << lastCommittedURL.spec();
   UMA_HISTOGRAM_BOOLEAN("Web.CurrentOriginEqualsLastCommittedOrigin",
                         equalOrigins);
+  if (web::GetWebClient()->IsSlimNavigationManagerEnabled() && !equalOrigins) {
+    *trust_level = web::URLVerificationTrustLevel::kMixed;
+  }
   return result;
 }
 
diff --git a/ios/web/web_view/wk_web_view_util.h b/ios/web/web_view/wk_web_view_util.h
index edf3d11..6bce0a1 100644
--- a/ios/web/web_view/wk_web_view_util.h
+++ b/ios/web/web_view/wk_web_view_util.h
@@ -16,6 +16,11 @@
 // TODO(crbug.com/954332): Remove this workaround when
 // https://bugs.webkit.org/show_bug.cgi?id=196930 is fixed.
 bool RequiresContentFilterBlockingWorkaround();
+
+// Returns true if this iOS version is known to have
+// https://bugs.webkit.org/show_bug.cgi?id=198794 WebKit bug.
+// TODO(crbug.com/973653): Remove this workaround when WebKit bug is fixed.
+bool RequiresProvisionalNavigationFailureWorkaround();
 }  // namespace web
 
 #endif  // IOS_WEB_WEB_VIEW_WK_WEB_VIEW_UTIL_H_
diff --git a/ios/web/web_view/wk_web_view_util.mm b/ios/web/web_view/wk_web_view_util.mm
index d4fe111..446d57f5 100644
--- a/ios/web/web_view/wk_web_view_util.mm
+++ b/ios/web/web_view/wk_web_view_util.mm
@@ -43,4 +43,9 @@
   return false;
 }
 
+bool RequiresProvisionalNavigationFailureWorkaround() {
+  if (@available(iOS 12.2, *))
+    return true;
+  return false;
+}
 }  // namespace web
diff --git a/ipc/ipc_message_start.h b/ipc/ipc_message_start.h
index ec19b74..480ae36 100644
--- a/ipc/ipc_message_start.h
+++ b/ipc/ipc_message_start.h
@@ -51,7 +51,6 @@
   ChromeExtensionMsgStart,
   GinJavaBridgeMsgStart,
   ChromeUtilityPrintingMsgStart,
-  AecDumpMsgStart,
   OzoneGpuMsgStart,
   WebTestMsgStart,
   NetworkHintsMsgStart,
diff --git a/media/audio/audio_output_resampler.cc b/media/audio/audio_output_resampler.cc
index 7f50515..727c2ff 100644
--- a/media/audio/audio_output_resampler.cc
+++ b/media/audio/audio_output_resampler.cc
@@ -17,7 +17,6 @@
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_functions.h"
-#include "base/metrics/histogram_macros.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/trace_event/trace_event.h"
 #include "build/build_config.h"
@@ -94,43 +93,20 @@
 
 // Record UMA statistics for hardware output configuration.
 static void RecordStats(const AudioParameters& output_params) {
-  UMA_HISTOGRAM_ENUMERATION(
+  base::UmaHistogramEnumeration(
       "Media.HardwareAudioChannelLayout", output_params.channel_layout(),
-      CHANNEL_LAYOUT_MAX + 1);
-  UMA_HISTOGRAM_EXACT_LINEAR("Media.HardwareAudioChannelCount",
-                             output_params.channels(),
-                             static_cast<int>(limits::kMaxChannels));
+      static_cast<ChannelLayout>(CHANNEL_LAYOUT_MAX + 1));
+  base::UmaHistogramExactLinear("Media.HardwareAudioChannelCount",
+                                output_params.channels(),
+                                static_cast<int>(limits::kMaxChannels));
 
   AudioSampleRate asr;
-  if (ToAudioSampleRate(output_params.sample_rate(), &asr)) {
-    UMA_HISTOGRAM_ENUMERATION(
-        "Media.HardwareAudioSamplesPerSecond", asr, kAudioSampleRateMax + 1);
-  } else {
-    UMA_HISTOGRAM_COUNTS_1M("Media.HardwareAudioSamplesPerSecondUnexpected",
-                            output_params.sample_rate());
-  }
-}
+  if (!ToAudioSampleRate(output_params.sample_rate(), &asr))
+    return;
 
-// Record UMA statistics for hardware output configuration after fallback.
-static void RecordFallbackStats(const AudioParameters& output_params) {
-  UMA_HISTOGRAM_BOOLEAN("Media.FallbackToHighLatencyAudioPath", true);
-  UMA_HISTOGRAM_ENUMERATION(
-      "Media.FallbackHardwareAudioChannelLayout",
-      output_params.channel_layout(), CHANNEL_LAYOUT_MAX + 1);
-  UMA_HISTOGRAM_EXACT_LINEAR("Media.FallbackHardwareAudioChannelCount",
-                             output_params.channels(),
-                             static_cast<int>(limits::kMaxChannels));
-
-  AudioSampleRate asr;
-  if (ToAudioSampleRate(output_params.sample_rate(), &asr)) {
-    UMA_HISTOGRAM_ENUMERATION(
-        "Media.FallbackHardwareAudioSamplesPerSecond",
-        asr, kAudioSampleRateMax + 1);
-  } else {
-    UMA_HISTOGRAM_COUNTS_1M(
-        "Media.FallbackHardwareAudioSamplesPerSecondUnexpected",
-        output_params.sample_rate());
-  }
+  base::UmaHistogramEnumeration(
+      "Media.HardwareAudioSamplesPerSecond", asr,
+      static_cast<AudioSampleRate>(kAudioSampleRateMax + 1));
 }
 
 // Record UMA statistics for input/output rebuffering.
@@ -209,18 +185,18 @@
 // This enum must match the numbering for
 // AudioOutputResamplerOpenLowLatencyStreamResult in enums.xml. Do not reorder
 // or remove items, only add new items before OPEN_STREAM_MAX.
-enum OpenStreamResult {
-  OPEN_STREAM_FAIL = 0,
-  OPEN_STREAM_FALLBACK_TO_FAKE = 1,
-  OPEN_STREAM_FALLBACK_TO_LINEAR = 2,
-  OPEN_STREAM_SUCCESS = 3,
-  OPEN_STREAM_SUBSEQUENT_FALLBACK_TO_FAKE_FAIL = 4,
-  OPEN_STREAM_SUBSEQUENT_FALLBACK_TO_FAKE_SUCCESS = 5,
-  OPEN_STREAM_SUBSEQUENT_FALLBACK_TO_LINEAR_FAIL = 6,
-  OPEN_STREAM_SUBSEQUENT_FALLBACK_TO_LINEAR_SUCCESS = 7,
-  OPEN_STREAM_SUBSEQUENT_FAIL = 8,
-  OPEN_STREAM_SUBSEQUENT_SUCCESS = 9,
-  OPEN_STREAM_MAX = 9,
+enum class OpenStreamResult {
+  kFail = 0,
+  kFallbackToFake = 1,
+  kFallbackToLinear = 2,
+  kSuccess = 3,
+  kFallbackToFakeFail = 4,
+  kFallbackToFakeSuccess = 5,
+  kFallbackToLinearFail = 6,
+  kFallbackToLinearSuccess = 7,
+  kSubsequentFail = 8,
+  kSubsequentSuccess = 9,
+  kMaxValue = kSubsequentSuccess,
 };
 
 OpenStreamResult GetSubsequentStreamCreationResultBucket(
@@ -228,17 +204,17 @@
     bool success) {
   switch (current_params.format()) {
     case AudioParameters::AUDIO_PCM_LOW_LATENCY:
-      return success ? OPEN_STREAM_SUBSEQUENT_SUCCESS
-                     : OPEN_STREAM_SUBSEQUENT_FAIL;
+      return success ? OpenStreamResult::kSubsequentSuccess
+                     : OpenStreamResult::kSubsequentFail;
     case AudioParameters::AUDIO_PCM_LINEAR:
-      return success ? OPEN_STREAM_SUBSEQUENT_FALLBACK_TO_LINEAR_SUCCESS
-                     : OPEN_STREAM_SUBSEQUENT_FALLBACK_TO_LINEAR_FAIL;
+      return success ? OpenStreamResult::kFallbackToLinearSuccess
+                     : OpenStreamResult::kFallbackToLinearFail;
     case AudioParameters::AUDIO_FAKE:
-      return success ? OPEN_STREAM_SUBSEQUENT_FALLBACK_TO_FAKE_SUCCESS
-                     : OPEN_STREAM_SUBSEQUENT_FALLBACK_TO_FAKE_FAIL;
+      return success ? OpenStreamResult::kFallbackToFakeSuccess
+                     : OpenStreamResult::kFallbackToFakeFail;
     default:
       NOTREACHED();
-      return OPEN_STREAM_FAIL;
+      return OpenStreamResult::kFail;
   }
 }
 
@@ -327,20 +303,24 @@
     dispatcher_ = MakeDispatcher(device_id_, output_params_);
   }
 
+  constexpr char kFallbackHistogramName[] =
+      "Media.FallbackToHighLatencyAudioPath";
+  constexpr char kOpenLowLatencyHistogramName[] =
+      "Media.AudioOutputResampler.OpenLowLatencyStream";
+
   if (dispatcher_->OpenStream()) {
     // Only record the UMA statistic if we didn't fallback during construction
     // and only for the first stream we open.
     if (original_output_params_.format() ==
         AudioParameters::AUDIO_PCM_LOW_LATENCY) {
       if (first_stream)
-        UMA_HISTOGRAM_BOOLEAN("Media.FallbackToHighLatencyAudioPath", false);
+        base::UmaHistogramBoolean(kFallbackHistogramName, false);
 
-      UMA_HISTOGRAM_ENUMERATION(
-          "Media.AudioOutputResampler.OpenLowLatencyStream",
+      base::UmaHistogramEnumeration(
+          kOpenLowLatencyHistogramName,
           first_stream
-              ? OPEN_STREAM_SUCCESS
-              : GetSubsequentStreamCreationResultBucket(output_params_, true),
-          OPEN_STREAM_MAX + 1);
+              ? OpenStreamResult::kSuccess
+              : GetSubsequentStreamCreationResultBucket(output_params_, true));
     }
     return true;
   }
@@ -354,15 +334,13 @@
   // If we have successfully opened a stream previously, there's nothing more to
   // be done.
   if (!first_stream) {
-    UMA_HISTOGRAM_ENUMERATION(
-        "Media.AudioOutputResampler.OpenLowLatencyStream",
-        GetSubsequentStreamCreationResultBucket(output_params_, false),
-        OPEN_STREAM_MAX + 1);
+    base::UmaHistogramEnumeration(
+        kOpenLowLatencyHistogramName,
+        GetSubsequentStreamCreationResultBucket(output_params_, false));
     return false;
   }
-  // Record UMA statistics about the hardware which triggered the failure so
-  // we can debug and triage later.
-  RecordFallbackStats(original_output_params_);
+
+  base::UmaHistogramBoolean(kFallbackHistogramName, true);
 
   // Only Windows has a high latency output driver that is not the same as the
   // low latency path.
@@ -374,9 +352,8 @@
   const std::string fallback_device_id = "";
   dispatcher_ = MakeDispatcher(fallback_device_id, output_params_);
   if (dispatcher_->OpenStream()) {
-    UMA_HISTOGRAM_ENUMERATION("Media.AudioOutputResampler.OpenLowLatencyStream",
-                              OPEN_STREAM_FALLBACK_TO_LINEAR,
-                              OPEN_STREAM_MAX + 1);
+    base::UmaHistogramEnumeration(kOpenLowLatencyHistogramName,
+                                  OpenStreamResult::kFallbackToLinear);
     return true;
   }
 #endif
@@ -389,16 +366,16 @@
   output_params_.set_format(AudioParameters::AUDIO_FAKE);
   dispatcher_ = MakeDispatcher(device_id_, output_params_);
   if (dispatcher_->OpenStream()) {
-    UMA_HISTOGRAM_ENUMERATION("Media.AudioOutputResampler.OpenLowLatencyStream",
-                              OPEN_STREAM_FALLBACK_TO_FAKE,
-                              OPEN_STREAM_MAX + 1);
+    base::UmaHistogramEnumeration(kOpenLowLatencyHistogramName,
+                                  OpenStreamResult::kFallbackToFake);
     return true;
   }
 
   // Resetting the malfunctioning dispatcher.
   Reinitialize();
-  UMA_HISTOGRAM_ENUMERATION("Media.AudioOutputResampler.OpenLowLatencyStream",
-                            OPEN_STREAM_FAIL, OPEN_STREAM_MAX + 1);
+
+  base::UmaHistogramEnumeration(kOpenLowLatencyHistogramName,
+                                OpenStreamResult::kFail);
   return false;
 }
 
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc
index bb001ab..fa9e64d 100644
--- a/media/filters/ffmpeg_demuxer.cc
+++ b/media/filters/ffmpeg_demuxer.cc
@@ -147,19 +147,6 @@
 static void RecordAudioCodecStats(const AudioDecoderConfig& audio_config) {
   UMA_HISTOGRAM_ENUMERATION("Media.AudioCodec", audio_config.codec(),
                             kAudioCodecMax + 1);
-  UMA_HISTOGRAM_ENUMERATION("Media.AudioSampleFormat",
-                            audio_config.sample_format(), kSampleFormatMax + 1);
-  UMA_HISTOGRAM_ENUMERATION("Media.AudioChannelLayout",
-                            audio_config.channel_layout(),
-                            CHANNEL_LAYOUT_MAX + 1);
-  AudioSampleRate asr;
-  if (ToAudioSampleRate(audio_config.samples_per_second(), &asr)) {
-    UMA_HISTOGRAM_ENUMERATION("Media.AudioSamplesPerSecond", asr,
-                              kAudioSampleRateMax + 1);
-  } else {
-    UMA_HISTOGRAM_COUNTS_1M("Media.AudioSamplesPerSecondUnexpected",
-                            audio_config.samples_per_second());
-  }
 }
 
 // Record video decoder config UMA stats corresponding to a src= playback.
diff --git a/mojo/public/cpp/bindings/strong_associated_binding.h b/mojo/public/cpp/bindings/strong_associated_binding.h
index dceb21f..f017956 100644
--- a/mojo/public/cpp/bindings/strong_associated_binding.h
+++ b/mojo/public/cpp/bindings/strong_associated_binding.h
@@ -43,9 +43,6 @@
 template <typename Interface>
 class StrongAssociatedBinding {
  public:
-  using ImplPointerType =
-      typename AssociatedBinding<Interface>::ImplPointerType;
-
   // Create a new StrongAssociatedBinding instance. The instance owns itself,
   // cleaning up only in the event of a pipe connection error. Returns a WeakPtr
   // to the new StrongAssociatedBinding instance.
@@ -87,8 +84,11 @@
   void FlushForTesting() { binding_.FlushForTesting(); }
 
   // Allows test code to swap the interface implementation.
-  ImplPointerType SwapImplForTesting(ImplPointerType new_impl) {
-    return binding_.SwapImplForTesting(new_impl);
+  std::unique_ptr<Interface> SwapImplForTesting(
+      std::unique_ptr<Interface> new_impl) {
+    binding_.SwapImplForTesting(new_impl.get());
+    impl_.swap(new_impl);
+    return new_impl;
   }
 
  private:
diff --git a/net/BUILD.gn b/net/BUILD.gn
index a7216ca..7a477c73f 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -7,7 +7,6 @@
 import("//build/config/compiler/compiler.gni")
 import("//build/config/crypto.gni")
 import("//build/config/features.gni")
-import("//build/config/ui.gni")
 import("//net/features.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
 import("//testing/test.gni")
diff --git a/net/cookies/parsed_cookie.cc b/net/cookies/parsed_cookie.cc
index 520f33e..910b48b 100644
--- a/net/cookies/parsed_cookie.cc
+++ b/net/cookies/parsed_cookie.cc
@@ -448,12 +448,28 @@
 
 bool ParsedCookie::SetString(size_t* index,
                              const std::string& key,
-                             const std::string& value) {
-  if (value.empty()) {
+                             const std::string& untrusted_value) {
+  // This function should do equivalent input validation to the
+  // constructor. Otherwise, the Set* functions can put this ParsedCookie in a
+  // state where parsing the output of ToCookieLine() produces a different
+  // ParsedCookie.
+  //
+  // Without input validation, invoking pc.SetPath(" baz ") would result in
+  // pc.ToCookieLine() == "path= baz ". Parsing the "path= baz " string would
+  // produce a cookie with "path" attribute equal to "baz" (no spaces). We
+  // should not produce cookie lines that parse to different key/value pairs!
+
+  // Inputs containing invalid characters should be ignored.
+  if (!IsValidCookieAttributeValue(untrusted_value))
+    return false;
+
+  // Use the same whitespace trimming code as the constructor.
+  const std::string parsed_value = ParseValueString(untrusted_value);
+  if (parsed_value.empty()) {
     ClearAttributePair(*index);
     return true;
   } else {
-    return SetAttributePair(index, key, value);
+    return SetAttributePair(index, key, parsed_value);
   }
 }
 
@@ -469,7 +485,7 @@
 bool ParsedCookie::SetAttributePair(size_t* index,
                                     const std::string& key,
                                     const std::string& value) {
-  if (!(HttpUtil::IsToken(key) && IsValidCookieAttributeValue(value)))
+  if (!HttpUtil::IsToken(key))
     return false;
   if (!IsValid())
     return false;
diff --git a/net/cookies/parsed_cookie_unittest.cc b/net/cookies/parsed_cookie_unittest.cc
index 535ae07..66beb9e 100644
--- a/net/cookies/parsed_cookie_unittest.cc
+++ b/net/cookies/parsed_cookie_unittest.cc
@@ -505,6 +505,29 @@
   EXPECT_TRUE(pc.IsValid());
 }
 
+TEST(ParsedCookieTest, SettersInputValidation) {
+  ParsedCookie pc("name=foobar");
+  EXPECT_TRUE(pc.SetPath("baz"));
+  EXPECT_EQ(pc.ToCookieLine(), "name=foobar; path=baz");
+
+  EXPECT_TRUE(pc.SetPath("  baz "));
+  EXPECT_EQ(pc.ToCookieLine(), "name=foobar; path=baz");
+
+  EXPECT_TRUE(pc.SetPath("     "));
+  EXPECT_EQ(pc.ToCookieLine(), "name=foobar");
+
+  EXPECT_TRUE(pc.SetDomain("  baz "));
+  EXPECT_EQ(pc.ToCookieLine(), "name=foobar; domain=baz");
+
+  // Invalid characters
+  EXPECT_FALSE(pc.SetPath("  baz\n "));
+  EXPECT_FALSE(pc.SetPath("f;oo"));
+  EXPECT_FALSE(pc.SetPath("\r"));
+  EXPECT_FALSE(pc.SetPath("\a"));
+  EXPECT_FALSE(pc.SetPath("\t"));
+  EXPECT_FALSE(pc.SetSameSite("\r"));
+}
+
 TEST(ParsedCookieTest, SameSiteValues) {
   struct TestCase {
     const char* cookie;
diff --git a/remoting/android/remoting_apk_tmpl.gni b/remoting/android/remoting_apk_tmpl.gni
index 0ebd46e..1921cec 100644
--- a/remoting/android/remoting_apk_tmpl.gni
+++ b/remoting/android/remoting_apk_tmpl.gni
@@ -16,5 +16,6 @@
     android_manifest_dep = "//remoting/android:remoting_apk_manifest"
     shared_libraries = [ "//remoting/client/jni:remoting_client_jni" ]
     version_name = chrome_version_name
+    version_code = chrome_version_code
   }
 }
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index f37ba02ee..c05ecf4 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -3639,6 +3639,21 @@
             ]
         }
     ],
+    "OfflinePreviewsFalsePositivePrevention": [
+        {
+            "platforms": [
+                "android"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "OfflinePreviewsFalsePositivePrevention"
+                    ]
+                }
+            ]
+        }
+    ],
     "OmniboxBundledExperimentV1": [
         {
             "platforms": [
diff --git a/third_party/blink/common/indexeddb/indexed_db_default_mojom_traits.cc b/third_party/blink/common/indexeddb/indexed_db_default_mojom_traits.cc
index 5198ac0..702edac 100644
--- a/third_party/blink/common/indexeddb/indexed_db_default_mojom_traits.cc
+++ b/third_party/blink/common/indexeddb/indexed_db_default_mojom_traits.cc
@@ -37,6 +37,7 @@
     DCHECK_EQ(out->object_stores.count(key), 0UL);
     out->object_stores[key] = object_store;
   }
+  out->was_cold_open = data.was_cold_open();
   return true;
 }
 
diff --git a/third_party/blink/public/common/indexeddb/indexed_db_default_mojom_traits.h b/third_party/blink/public/common/indexeddb/indexed_db_default_mojom_traits.h
index 5aed0ef..bc83906 100644
--- a/third_party/blink/public/common/indexeddb/indexed_db_default_mojom_traits.h
+++ b/third_party/blink/public/common/indexeddb/indexed_db_default_mojom_traits.h
@@ -34,6 +34,9 @@
       const blink::IndexedDBDatabaseMetadata& metadata) {
     return metadata.object_stores;
   }
+  static bool was_cold_open(const blink::IndexedDBDatabaseMetadata& metadata) {
+    return metadata.was_cold_open;
+  }
   static bool Read(blink::mojom::IDBDatabaseMetadataDataView data,
                    blink::IndexedDBDatabaseMetadata* out);
 };
diff --git a/third_party/blink/public/common/indexeddb/indexeddb_metadata.h b/third_party/blink/public/common/indexeddb/indexeddb_metadata.h
index 3abdadf..7bb37c9e 100644
--- a/third_party/blink/public/common/indexeddb/indexeddb_metadata.h
+++ b/third_party/blink/public/common/indexeddb/indexeddb_metadata.h
@@ -88,6 +88,8 @@
   int64_t max_object_store_id;
 
   std::map<int64_t, IndexedDBObjectStoreMetadata> object_stores;
+
+  bool was_cold_open;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/mojom/indexeddb/indexeddb.mojom b/third_party/blink/public/mojom/indexeddb/indexeddb.mojom
index 1d0c3409..520f084 100644
--- a/third_party/blink/public/mojom/indexeddb/indexeddb.mojom
+++ b/third_party/blink/public/mojom/indexeddb/indexeddb.mojom
@@ -146,6 +146,7 @@
   int64 version;
   int64 max_object_store_id;
   map<int64, IDBObjectStoreMetadata> object_stores;
+  bool was_cold_open;
 };
 
 struct IDBNameAndVersion {
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom
index 9e2f1bd..37ed9c9 100644
--- a/third_party/blink/public/mojom/web_feature/web_feature.mojom
+++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -1260,10 +1260,8 @@
   kV8PromiseConstructorReturnedUndefined = 1766,
   kFormSubmittedWithUnclosedFormControl = 1767,
   kScrollbarUseVerticalScrollbarButton = 1777,
-  kScrollbarUseVerticalScrollbarThumb = 1778,
   kScrollbarUseVerticalScrollbarTrack = 1779,
   kScrollbarUseHorizontalScrollbarButton = 1780,
-  kScrollbarUseHorizontalScrollbarThumb = 1781,
   kScrollbarUseHorizontalScrollbarTrack = 1782,
   kHTMLTableCellElementColspan = 1783,
   kHTMLTableCellElementColspanGreaterThan1000 = 1784,
diff --git a/third_party/blink/public/web/web_view.h b/third_party/blink/public/web/web_view.h
index cb3dde9238..1545bab 100644
--- a/third_party/blink/public/web/web_view.h
+++ b/third_party/blink/public/web/web_view.h
@@ -240,17 +240,24 @@
   virtual float MaximumPageScaleFactor() const = 0;
 
   // Sets the offset of the visual viewport within the main frame, in
-  // partial CSS pixels. The offset will be clamped so the visual viewport
+  // fractional CSS pixels. The offset will be clamped so the visual viewport
   // stays within the frame's bounds.
   virtual void SetVisualViewportOffset(const WebFloatPoint&) = 0;
 
   // Gets the visual viewport's current offset within the page's main frame,
-  // in partial CSS pixels.
+  // in fractional CSS pixels.
   virtual WebFloatPoint VisualViewportOffset() const = 0;
 
   // Get the visual viewport's size in CSS pixels.
   virtual WebFloatSize VisualViewportSize() const = 0;
 
+  // Resizes the unscaled (page scale = 1.0) visual viewport. Normally the
+  // unscaled visual viewport is the same size as the main frame. The passed
+  // size becomes the size of the viewport when page scale = 1. This
+  // is used to shrink the visible viewport to allow things like the ChromeOS
+  // virtual keyboard to overlay over content but allow scrolling it into view.
+  virtual void ResizeVisualViewport(const WebSize&) = 0;
+
   // Sets the default minimum, and maximum page scale. These will be overridden
   // by the page or by the overrides below if they are set.
   virtual void SetDefaultPageScaleLimits(float min_scale, float max_scale) = 0;
diff --git a/third_party/blink/public/web/web_widget.h b/third_party/blink/public/web/web_widget.h
index f4c79b9..d803c13 100644
--- a/third_party/blink/public/web/web_widget.h
+++ b/third_party/blink/public/web/web_widget.h
@@ -78,13 +78,6 @@
   // Called to resize the WebWidget.
   virtual void Resize(const WebSize&) {}
 
-  // Resizes the unscaled visual viewport. Normally the unscaled visual
-  // viewport is the same size as the main frame. The passed size becomes the
-  // size of the viewport when unscaled (i.e. scale = 1). This is used to
-  // shrink the visible viewport to allow things like the ChromeOS virtual
-  // keyboard to overlay over content but allow scrolling it into view.
-  virtual void ResizeVisualViewport(const WebSize&) {}
-
   // Called to notify the WebWidget of entering/exiting fullscreen mode.
   virtual void DidEnterFullscreen() {}
   virtual void DidExitFullscreen() {}
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_properties.h.tmpl b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_properties.h.tmpl
index 78e2b8b..74e5f37 100644
--- a/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_properties.h.tmpl
+++ b/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_properties.h.tmpl
@@ -37,7 +37,8 @@
   (property.compositable and 'kCompositableProperty' or ''),
   (property.is_property and 'kProperty' or ''),
   (property.inherited and 'kInherited' or ''),
-  (property.visited and 'kVisited' or '')
+  (property.visited and 'kVisited' or ''),
+  (property.is_internal and 'kInternal' or '')
 ] | reject('==', '') | join(' | ') %}
 {% set ctor_args = (not is_alias and [property_id, flags, separator] or []) %}
 // {{property.name}}
diff --git a/third_party/blink/renderer/core/clipboard/data_transfer_item.cc b/third_party/blink/renderer/core/clipboard/data_transfer_item.cc
index ea4d935..76e02205 100644
--- a/third_party/blink/renderer/core/clipboard/data_transfer_item.cc
+++ b/third_party/blink/renderer/core/clipboard/data_transfer_item.cc
@@ -36,7 +36,6 @@
 #include "third_party/blink/renderer/core/clipboard/data_object_item.h"
 #include "third_party/blink/renderer/core/clipboard/data_transfer.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/core/probe/core_probes.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
@@ -74,15 +73,14 @@
 
   auto* v8persistent_callback = ToV8PersistentCallbackFunction(callback);
   ExecutionContext* context = ExecutionContext::From(script_state);
-  auto task_id = std::make_unique<probe::AsyncTaskId>();
   probe::AsyncTaskScheduled(context, "DataTransferItem.getAsString",
-                            task_id.get());
+                            v8persistent_callback);
   context->GetTaskRunner(TaskType::kUserInteraction)
       ->PostTask(FROM_HERE,
                  WTF::Bind(&DataTransferItem::RunGetAsStringTask,
                            WrapPersistent(this), WrapPersistent(context),
                            WrapPersistent(v8persistent_callback),
-                           item_->GetAsString(), std::move(task_id)));
+                           item_->GetAsString()));
 }
 
 File* DataTransferItem::getAsFile() const {
@@ -99,10 +97,9 @@
 void DataTransferItem::RunGetAsStringTask(
     ExecutionContext* context,
     V8PersistentCallbackFunction<V8FunctionStringCallback>* callback,
-    const String& data,
-    std::unique_ptr<probe::AsyncTaskId> task_id) {
+    const String& data) {
   DCHECK(callback);
-  probe::AsyncTask async_task(context, task_id.get());
+  probe::AsyncTask async_task(context, callback);
   if (context)
     callback->InvokeAndReportException(nullptr, data);
 }
diff --git a/third_party/blink/renderer/core/clipboard/data_transfer_item.h b/third_party/blink/renderer/core/clipboard/data_transfer_item.h
index faae65f..c930a457 100644
--- a/third_party/blink/renderer/core/clipboard/data_transfer_item.h
+++ b/third_party/blink/renderer/core/clipboard/data_transfer_item.h
@@ -46,10 +46,6 @@
 class File;
 class ScriptState;
 
-namespace probe {
-class AsyncTaskId;
-}
-
 class CORE_EXPORT DataTransferItem final : public ScriptWrappable {
   DEFINE_WRAPPERTYPEINFO();
 
@@ -71,8 +67,7 @@
   void RunGetAsStringTask(
       ExecutionContext*,
       V8PersistentCallbackFunction<V8FunctionStringCallback>*,
-      const String& data,
-      std::unique_ptr<probe::AsyncTaskId>);
+      const String& data);
 
   Member<DataTransfer> data_transfer_;
   Member<DataObjectItem> item_;
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5
index 9c6b458..26cdfe4 100644
--- a/third_party/blink/renderer/core/css/css_properties.json5
+++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -5362,6 +5362,8 @@
       type_name: "float",
       default_value: "1.0f",
       field_group: "*",
+      priority: "High",
+      style_builder_custom_functions: ["initial", "inherit", "value"],
     },
 
     // Aliases; these map to the same CSSPropertyID
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_impl.cc b/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
index c4325cd..80b44b40 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
+++ b/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
@@ -1026,7 +1026,7 @@
     AtRuleDescriptorParser::ParseAtRule(atrule_id, range, *context_,
                                         parsed_properties_);
   } else {
-    unresolved_property = lhs.ParseAsUnresolvedCSSPropertyID();
+    unresolved_property = lhs.ParseAsUnresolvedCSSPropertyID(context_->Mode());
   }
 
   // @rules other than FontFace still handled with legacy code.
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_token.cc b/third_party/blink/renderer/core/css/parser/css_parser_token.cc
index 75c472f..6b564ca 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_token.cc
+++ b/third_party/blink/renderer/core/css/parser/css_parser_token.cc
@@ -85,9 +85,10 @@
   return numeric_value_;
 }
 
-CSSPropertyID CSSParserToken::ParseAsUnresolvedCSSPropertyID() const {
+CSSPropertyID CSSParserToken::ParseAsUnresolvedCSSPropertyID(
+    CSSParserMode mode) const {
   DCHECK_EQ(type_, static_cast<unsigned>(kIdentToken));
-  return UnresolvedCSSPropertyID(Value());
+  return UnresolvedCSSPropertyID(Value(), mode);
 }
 
 AtRuleDescriptorID CSSParserToken::ParseAsAtRuleDescriptorID() const {
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_token.h b/third_party/blink/renderer/core/css/parser/css_parser_token.h
index 8bdf9467..3089edce 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_token.h
+++ b/third_party/blink/renderer/core/css/parser/css_parser_token.h
@@ -8,6 +8,7 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/css/css_primitive_value.h"
 #include "third_party/blink/renderer/core/css/parser/at_rule_descriptors.h"
+#include "third_party/blink/renderer/core/css/parser/css_parser_mode.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_view.h"
 
@@ -145,7 +146,8 @@
 
   bool HasStringBacking() const;
 
-  CSSPropertyID ParseAsUnresolvedCSSPropertyID() const;
+  CSSPropertyID ParseAsUnresolvedCSSPropertyID(
+      CSSParserMode mode = kHTMLStandardMode) const;
   AtRuleDescriptorID ParseAsAtRuleDescriptorID() const;
 
   void Serialize(StringBuilder&) const;
diff --git a/third_party/blink/renderer/core/css/parser/css_property_parser.cc b/third_party/blink/renderer/core/css/parser/css_property_parser.cc
index 1da570e..587d60b 100644
--- a/third_party/blink/renderer/core/css/parser/css_property_parser.cc
+++ b/third_party/blink/renderer/core/css/parser/css_property_parser.cc
@@ -170,7 +170,8 @@
 
 template <typename CharacterType>
 static CSSPropertyID UnresolvedCSSPropertyID(const CharacterType* property_name,
-                                             unsigned length) {
+                                             unsigned length,
+                                             CSSParserMode mode) {
   if (length == 0)
     return CSSPropertyID::kInvalid;
   if (length >= 2 && property_name[0] == '-' && property_name[1] == '-')
@@ -192,24 +193,27 @@
   const Property* hash_table_entry = FindProperty(name, length);
   if (!hash_table_entry)
     return CSSPropertyID::kInvalid;
-  CSSPropertyID property = static_cast<CSSPropertyID>(hash_table_entry->id);
-  if (!CSSProperty::Get(resolveCSSPropertyID(property)).IsEnabled())
-    return CSSPropertyID::kInvalid;
-  return property;
+  CSSPropertyID property_id = static_cast<CSSPropertyID>(hash_table_entry->id);
+  const CSSProperty& property =
+      CSSProperty::Get(resolveCSSPropertyID(property_id));
+  bool enabled =
+      property.IsEnabled() || (property.IsInternal() && mode == kUASheetMode);
+  return enabled ? property_id : CSSPropertyID::kInvalid;
 }
 
 CSSPropertyID unresolvedCSSPropertyID(const String& string) {
   unsigned length = string.length();
+  CSSParserMode mode = kHTMLStandardMode;
   return string.Is8Bit()
-             ? UnresolvedCSSPropertyID(string.Characters8(), length)
-             : UnresolvedCSSPropertyID(string.Characters16(), length);
+             ? UnresolvedCSSPropertyID(string.Characters8(), length, mode)
+             : UnresolvedCSSPropertyID(string.Characters16(), length, mode);
 }
 
-CSSPropertyID UnresolvedCSSPropertyID(StringView string) {
+CSSPropertyID UnresolvedCSSPropertyID(StringView string, CSSParserMode mode) {
   unsigned length = string.length();
   return string.Is8Bit()
-             ? UnresolvedCSSPropertyID(string.Characters8(), length)
-             : UnresolvedCSSPropertyID(string.Characters16(), length);
+             ? UnresolvedCSSPropertyID(string.Characters8(), length, mode)
+             : UnresolvedCSSPropertyID(string.Characters16(), length, mode);
 }
 
 template <typename CharacterType>
diff --git a/third_party/blink/renderer/core/css/parser/css_property_parser.h b/third_party/blink/renderer/core/css/parser/css_property_parser.h
index 4fd0b1f..d4989ede 100644
--- a/third_party/blink/renderer/core/css/parser/css_property_parser.h
+++ b/third_party/blink/renderer/core/css/parser/css_property_parser.h
@@ -27,6 +27,7 @@
 
 #include "base/macros.h"
 #include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_parser_mode.h"
 #include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
 #include "third_party/blink/renderer/core/css/style_rule.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_view.h"
@@ -76,7 +77,8 @@
   DISALLOW_COPY_AND_ASSIGN(CSSPropertyParser);
 };
 
-CSSPropertyID UnresolvedCSSPropertyID(StringView);
+CSSPropertyID UnresolvedCSSPropertyID(StringView,
+                                      CSSParserMode mode = kHTMLStandardMode);
 CSSValueID CssValueKeywordID(StringView);
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/properties/css_property.h b/third_party/blink/renderer/core/css/properties/css_property.h
index 88b77f1..7254e3c 100644
--- a/third_party/blink/renderer/core/css/properties/css_property.h
+++ b/third_party/blink/renderer/core/css/properties/css_property.h
@@ -45,6 +45,7 @@
   bool IsLonghand() const { return flags_ & kLonghand; }
   bool IsInherited() const { return flags_ & kInherited; }
   bool IsVisited() const { return flags_ & kVisited; }
+  bool IsInternal() const { return flags_ & kInternal; }
 
   bool IsRepeated() const { return repetition_separator_ != '\0'; }
   char RepetitionSeparator() const { return repetition_separator_; }
@@ -98,6 +99,7 @@
     // computed value as seen by painting (as opposed to the computed value
     // seen by CSSOM, which is represented by the unvisited property).
     kVisited = 1 << 7,
+    kInternal = 1 << 8
   };
 
   constexpr CSSProperty(CSSPropertyID property_id,
diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
index 16679469..7047250 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -2868,6 +2868,20 @@
   return CSSIdentifierValue::Create(style.ForcedColorAdjust());
 }
 
+void InternalEffectiveZoom::ApplyInitial(StyleResolverState& state) const {
+  auto initial = ComputedStyleInitialValues::InitialInternalEffectiveZoom();
+  state.SetEffectiveZoom(initial);
+}
+
+void InternalEffectiveZoom::ApplyInherit(StyleResolverState& state) const {
+  state.SetEffectiveZoom(state.ParentStyle()->EffectiveZoom());
+}
+
+void InternalEffectiveZoom::ApplyValue(StyleResolverState& state,
+                                       const CSSValue& value) const {
+  state.SetEffectiveZoom(StyleBuilderConverter::ConvertZoom(state, value));
+}
+
 void InternalVisitedColor::ApplyValue(StyleResolverState& state,
                                       const CSSValue& value) const {
   auto* identifier_value = DynamicTo<CSSIdentifierValue>(value);
@@ -8052,26 +8066,7 @@
 }
 
 void Zoom::ApplyValue(StyleResolverState& state, const CSSValue& value) const {
-  SECURITY_DCHECK(value.IsPrimitiveValue() || value.IsIdentifierValue());
-
-  if (const auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) {
-    if (identifier_value->GetValueID() == CSSValueID::kNormal) {
-      state.SetZoom(ComputedStyleInitialValues::InitialZoom());
-    }
-  } else if (const auto* primitive_value =
-                 DynamicTo<CSSPrimitiveValue>(value)) {
-    if (primitive_value->IsPercentage()) {
-      if (float percent = primitive_value->GetFloatValue())
-        state.SetZoom(percent / 100.0f);
-      else
-        state.SetZoom(1.0f);
-    } else if (primitive_value->IsNumber()) {
-      if (float number = primitive_value->GetFloatValue())
-        state.SetZoom(number);
-      else
-        state.SetZoom(1.0f);
-    }
-  }
+  state.SetZoom(StyleBuilderConverter::ConvertZoom(state, value));
 }
 
 }  // namespace css_longhand
diff --git a/third_party/blink/renderer/core/css/resolver/css_property_priority.h b/third_party/blink/renderer/core/css/resolver/css_property_priority.h
index 4ebbd0b..9842a19 100644
--- a/third_party/blink/renderer/core/css/resolver/css_property_priority.h
+++ b/third_party/blink/renderer/core/css/resolver/css_property_priority.h
@@ -87,7 +87,7 @@
 template <>
 inline CSSPropertyID CSSPropertyPriorityData<kHighPropertyPriority>::Last() {
   static_assert(static_cast<int>(CSSPropertyID::kZoom) ==
-                    static_cast<int>(CSSPropertyID::kColor) + 24,
+                    static_cast<int>(CSSPropertyID::kColor) + 25,
                 "CSSPropertyID::kZoom should be the end of the high priority "
                 "property range");
   static_assert(static_cast<int>(CSSPropertyID::kWritingMode) ==
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
index d09a3d4..a6bd2be 100644
--- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
@@ -1007,6 +1007,28 @@
       state.UnzoomedLengthConversionData()));
 }
 
+float StyleBuilderConverter::ConvertZoom(const StyleResolverState& state,
+                                         const CSSValue& value) {
+  SECURITY_DCHECK(value.IsPrimitiveValue() || value.IsIdentifierValue());
+
+  if (const auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) {
+    if (identifier_value->GetValueID() == CSSValueID::kNormal)
+      return ComputedStyleInitialValues::InitialZoom();
+  } else if (const auto* primitive_value =
+                 DynamicTo<CSSPrimitiveValue>(value)) {
+    if (primitive_value->IsPercentage()) {
+      float percent = primitive_value->GetFloatValue();
+      return percent ? (percent / 100.0f) : 1.0f;
+    } else if (primitive_value->IsNumber()) {
+      float number = primitive_value->GetFloatValue();
+      return number ? number : 1.0f;
+    }
+  }
+
+  NOTREACHED();
+  return 1.0f;
+}
+
 Length StyleBuilderConverter::ConvertLengthOrAuto(
     const StyleResolverState& state,
     const CSSValue& value) {
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.h b/third_party/blink/renderer/core/css/resolver/style_builder_converter.h
index 60547c7..d1fe1b5 100644
--- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.h
+++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.h
@@ -164,6 +164,7 @@
   static Length ConvertLength(const StyleResolverState&, const CSSValue&);
   static UnzoomedLength ConvertUnzoomedLength(const StyleResolverState&,
                                               const CSSValue&);
+  static float ConvertZoom(const StyleResolverState&, const CSSValue&);
   static Length ConvertLengthOrAuto(const StyleResolverState&, const CSSValue&);
   static Length ConvertLengthSizing(StyleResolverState&, const CSSValue&);
   static Length ConvertLengthMaxSizing(StyleResolverState&, const CSSValue&);
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
index 65f30e4..1149fc5 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -1797,20 +1797,6 @@
       state, match_result.UaRules(), true, apply_inherited_only,
       needs_apply_pass);
 
-  if (UNLIKELY(IsSVGForeignObjectElement(state.GetElement()))) {
-    // LayoutSVGRoot handles zooming for the whole SVG subtree, so foreignObject
-    // content should not be scaled again.
-    //
-    // FIXME: The following hijacks the zoom property for foreignObject so that
-    // children of foreignObject get the correct font-size in case of zooming.
-    // 'zoom' has HighPropertyPriority, along with other font-related properties
-    // used as input to the FontBuilder, so resetting it here may cause the
-    // FontBuilder to recompute the font used as inheritable font for
-    // foreignObject content. If we want to support zoom on foreignObject we'll
-    // need to find another way of handling the SVG zoom model.
-    state.SetEffectiveZoom(ComputedStyleInitialValues::InitialZoom());
-  }
-
   if (cache_success.cached_matched_properties &&
       cache_success.cached_matched_properties->computed_style
               ->EffectiveZoom() != state.Style()->EffectiveZoom()) {
diff --git a/third_party/blink/renderer/core/css/svg.css b/third_party/blink/renderer/core/css/svg.css
index 091b6fe..ce01fef 100644
--- a/third_party/blink/renderer/core/css/svg.css
+++ b/third_party/blink/renderer/core/css/svg.css
@@ -84,3 +84,8 @@
 *:not(svg), *:not(foreignObject) > svg {
     transform-origin: 0 0;
 }
+
+/* TODO(crbug.com/976224): Support zoom on foreignObject */
+foreignObject {
+    -internal-effective-zoom: initial !important;
+}
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc b/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc
index 053b863..d9e810d 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc
@@ -611,19 +611,19 @@
   // phases, even though the budget allows it.
   EXPECT_FALSE(context->ShouldStyle(DisplayLockContext::kChildren));
   EXPECT_FALSE(context->ShouldLayout(DisplayLockContext::kChildren));
-  EXPECT_FALSE(context->ShouldPrePaint());
+  EXPECT_FALSE(context->ShouldPrePaint(DisplayLockContext::kChildren));
 
   GetDocument().GetFrame()->View()->SetInLifecycleUpdateForTest(true);
 
   EXPECT_TRUE(context->ShouldStyle(DisplayLockContext::kChildren));
   EXPECT_TRUE(context->ShouldLayout(DisplayLockContext::kChildren));
-  EXPECT_TRUE(context->ShouldPrePaint());
+  EXPECT_TRUE(context->ShouldPrePaint(DisplayLockContext::kChildren));
 
   GetDocument().GetFrame()->View()->SetInLifecycleUpdateForTest(false);
 
   EXPECT_FALSE(context->ShouldStyle(DisplayLockContext::kChildren));
   EXPECT_FALSE(context->ShouldLayout(DisplayLockContext::kChildren));
-  EXPECT_FALSE(context->ShouldPrePaint());
+  EXPECT_FALSE(context->ShouldPrePaint(DisplayLockContext::kChildren));
 
   // Ensure to flush any tasks scheduled by context calls.
   test::RunPendingTasks();
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
index c1060c6..c15153b 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -453,12 +453,15 @@
     update_budget_->DidPerformPhase(DisplayLockBudget::Phase::kLayout);
 }
 
-bool DisplayLockContext::ShouldPrePaint() const {
-  return update_forced_ || state_ > kUpdating ||
+bool DisplayLockContext::ShouldPrePaint(LifecycleTarget target) const {
+  return target == kSelf || update_forced_ || state_ > kUpdating ||
          ShouldPerformUpdatePhase(DisplayLockBudget::Phase::kPrePaint);
 }
 
-void DisplayLockContext::DidPrePaint() {
+void DisplayLockContext::DidPrePaint(LifecycleTarget target) {
+  if (target == kSelf)
+    return;
+
   if (state_ == kUpdating)
     update_budget_->DidPerformPhase(DisplayLockBudget::Phase::kPrePaint);
 
@@ -665,6 +668,9 @@
     if (needs_effective_allowed_touch_action_update_ ||
         layout_object->EffectiveAllowedTouchActionChanged() ||
         layout_object->DescendantEffectiveAllowedTouchActionChanged()) {
+      // Note that although the object itself should have up to date value, in
+      // order to force recalc of the whole subtree, we mark it as needing an
+      // update.
       layout_object->MarkEffectiveAllowedTouchActionChanged();
     }
     return true;
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.h b/third_party/blink/renderer/core/display_lock/display_lock_context.h
index 3fcb1b66..17264c17 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context.h
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context.h
@@ -110,8 +110,8 @@
   void DidStyle(LifecycleTarget);
   bool ShouldLayout(LifecycleTarget) const;
   void DidLayout(LifecycleTarget);
-  bool ShouldPrePaint() const;
-  void DidPrePaint();
+  bool ShouldPrePaint(LifecycleTarget) const;
+  void DidPrePaint(LifecycleTarget);
   bool ShouldPaint() const;
   void DidPaint();
 
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc b/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
index 5acc5ee..cbd62f6 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
@@ -1201,7 +1201,7 @@
   EXPECT_FALSE(ancestor_object->InsideBlockingTouchEventHandler());
   EXPECT_TRUE(handler_object->InsideBlockingTouchEventHandler());
   EXPECT_TRUE(descendant_object->InsideBlockingTouchEventHandler());
-  EXPECT_FALSE(locked_object->InsideBlockingTouchEventHandler());
+  EXPECT_TRUE(locked_object->InsideBlockingTouchEventHandler());
   EXPECT_FALSE(lockedchild_object->InsideBlockingTouchEventHandler());
 
   {
@@ -1226,7 +1226,7 @@
   EXPECT_FALSE(ancestor_object->InsideBlockingTouchEventHandler());
   EXPECT_TRUE(handler_object->InsideBlockingTouchEventHandler());
   EXPECT_TRUE(descendant_object->InsideBlockingTouchEventHandler());
-  EXPECT_FALSE(locked_object->InsideBlockingTouchEventHandler());
+  EXPECT_TRUE(locked_object->InsideBlockingTouchEventHandler());
   EXPECT_FALSE(lockedchild_object->InsideBlockingTouchEventHandler());
 
   UpdateAllLifecyclePhasesForTest();
@@ -1433,4 +1433,115 @@
       GraphicsLayerNeedsCollection(container->GetDisplayLockContext()));
 }
 
+TEST_F(DisplayLockContextTest, DescendantNeedsPaintPropertyUpdateBlocked) {
+  SetHtmlInnerHTML(R"HTML(
+    <style>
+    #locked {
+      width: 100px;
+      height: 100px;
+      contain: style layout paint;
+    }
+    </style>
+    <div id="ancestor">
+      <div id="descendant">
+        <div id="locked">
+          <div id="handler"></div>
+        </div>
+      </div>
+    </div>
+  )HTML");
+
+  auto* ancestor_element = GetDocument().getElementById("ancestor");
+  auto* descendant_element = GetDocument().getElementById("descendant");
+  auto* locked_element = GetDocument().getElementById("locked");
+  auto* handler_element = GetDocument().getElementById("handler");
+
+  auto* script_state = ToScriptStateForMainWorld(GetDocument().GetFrame());
+  {
+    ScriptState::Scope scope(script_state);
+    locked_element->getDisplayLockForBindings()->acquire(script_state, nullptr);
+  }
+
+  UpdateAllLifecyclePhasesForTest();
+  EXPECT_TRUE(locked_element->GetDisplayLockContext()->IsLocked());
+
+  auto* ancestor_object = ancestor_element->GetLayoutObject();
+  auto* descendant_object = descendant_element->GetLayoutObject();
+  auto* locked_object = locked_element->GetLayoutObject();
+  auto* handler_object = handler_element->GetLayoutObject();
+
+  EXPECT_FALSE(ancestor_object->NeedsPaintPropertyUpdate());
+  EXPECT_FALSE(descendant_object->NeedsPaintPropertyUpdate());
+  EXPECT_FALSE(locked_object->NeedsPaintPropertyUpdate());
+  EXPECT_FALSE(handler_object->NeedsPaintPropertyUpdate());
+
+  EXPECT_FALSE(ancestor_object->DescendantNeedsPaintPropertyUpdate());
+  EXPECT_FALSE(descendant_object->DescendantNeedsPaintPropertyUpdate());
+  EXPECT_FALSE(locked_object->DescendantNeedsPaintPropertyUpdate());
+  EXPECT_FALSE(handler_object->DescendantNeedsPaintPropertyUpdate());
+
+  handler_object->SetNeedsPaintPropertyUpdate();
+
+  EXPECT_FALSE(ancestor_object->NeedsPaintPropertyUpdate());
+  EXPECT_FALSE(descendant_object->NeedsPaintPropertyUpdate());
+  EXPECT_FALSE(locked_object->NeedsPaintPropertyUpdate());
+  EXPECT_TRUE(handler_object->NeedsPaintPropertyUpdate());
+
+  EXPECT_TRUE(ancestor_object->DescendantNeedsPaintPropertyUpdate());
+  EXPECT_TRUE(descendant_object->DescendantNeedsPaintPropertyUpdate());
+  EXPECT_TRUE(locked_object->DescendantNeedsPaintPropertyUpdate());
+  EXPECT_FALSE(handler_object->DescendantNeedsPaintPropertyUpdate());
+
+  UpdateAllLifecyclePhasesForTest();
+
+  EXPECT_FALSE(ancestor_object->NeedsPaintPropertyUpdate());
+  EXPECT_FALSE(descendant_object->NeedsPaintPropertyUpdate());
+  EXPECT_FALSE(locked_object->NeedsPaintPropertyUpdate());
+  EXPECT_TRUE(handler_object->NeedsPaintPropertyUpdate());
+
+  EXPECT_FALSE(ancestor_object->DescendantNeedsPaintPropertyUpdate());
+  EXPECT_FALSE(descendant_object->DescendantNeedsPaintPropertyUpdate());
+  EXPECT_TRUE(locked_object->DescendantNeedsPaintPropertyUpdate());
+  EXPECT_FALSE(handler_object->DescendantNeedsPaintPropertyUpdate());
+
+  locked_object->SetShouldCheckForPaintInvalidationWithoutGeometryChange();
+  UpdateAllLifecyclePhasesForTest();
+
+  EXPECT_FALSE(ancestor_object->NeedsPaintPropertyUpdate());
+  EXPECT_FALSE(descendant_object->NeedsPaintPropertyUpdate());
+  EXPECT_FALSE(locked_object->NeedsPaintPropertyUpdate());
+  EXPECT_TRUE(handler_object->NeedsPaintPropertyUpdate());
+
+  EXPECT_FALSE(ancestor_object->DescendantNeedsPaintPropertyUpdate());
+  EXPECT_FALSE(descendant_object->DescendantNeedsPaintPropertyUpdate());
+  EXPECT_TRUE(locked_object->DescendantNeedsPaintPropertyUpdate());
+  EXPECT_FALSE(handler_object->DescendantNeedsPaintPropertyUpdate());
+
+  {
+    ScriptState::Scope scope(script_state);
+    locked_element->GetDisplayLockContext()->commit(script_state);
+  }
+
+  EXPECT_FALSE(ancestor_object->NeedsPaintPropertyUpdate());
+  EXPECT_FALSE(descendant_object->NeedsPaintPropertyUpdate());
+  EXPECT_TRUE(locked_object->NeedsPaintPropertyUpdate());
+  EXPECT_TRUE(handler_object->NeedsPaintPropertyUpdate());
+
+  EXPECT_TRUE(ancestor_object->DescendantNeedsPaintPropertyUpdate());
+  EXPECT_TRUE(descendant_object->DescendantNeedsPaintPropertyUpdate());
+  EXPECT_TRUE(locked_object->DescendantNeedsPaintPropertyUpdate());
+  EXPECT_FALSE(handler_object->DescendantNeedsPaintPropertyUpdate());
+
+  UpdateAllLifecyclePhasesForTest();
+
+  EXPECT_FALSE(ancestor_object->NeedsPaintPropertyUpdate());
+  EXPECT_FALSE(descendant_object->NeedsPaintPropertyUpdate());
+  EXPECT_FALSE(locked_object->NeedsPaintPropertyUpdate());
+  EXPECT_FALSE(handler_object->NeedsPaintPropertyUpdate());
+
+  EXPECT_FALSE(ancestor_object->DescendantNeedsPaintPropertyUpdate());
+  EXPECT_FALSE(descendant_object->DescendantNeedsPaintPropertyUpdate());
+  EXPECT_FALSE(locked_object->DescendantNeedsPaintPropertyUpdate());
+  EXPECT_FALSE(handler_object->DescendantNeedsPaintPropertyUpdate());
+}
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/events/event.h b/third_party/blink/renderer/core/dom/events/event.h
index e9d27e5..caf9764 100644
--- a/third_party/blink/renderer/core/dom/events/event.h
+++ b/third_party/blink/renderer/core/dom/events/event.h
@@ -27,7 +27,6 @@
 
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/events/event_dispatch_result.h"
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -305,8 +304,6 @@
 
   virtual DispatchEventResult DispatchEvent(EventDispatcher&);
 
-  probe::AsyncTaskId* async_task_id() { return &async_task_id_; }
-
   void Trace(Visitor*) override;
 
  protected:
@@ -352,8 +349,6 @@
 
   PassiveMode handling_passive_;
   uint8_t event_phase_;
-  probe::AsyncTaskId async_task_id_;
-
   Member<EventTarget> current_target_;
   Member<EventTarget> target_;
   Member<Event> underlying_event_;
diff --git a/third_party/blink/renderer/core/dom/events/event_listener.h b/third_party/blink/renderer/core/dom/events/event_listener.h
index 0787c6f..3d7eb513 100644
--- a/third_party/blink/renderer/core/dom/events/event_listener.h
+++ b/third_party/blink/renderer/core/dom/events/event_listener.h
@@ -23,7 +23,6 @@
 
 #include "base/macros.h"
 #include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/platform/bindings/name_client.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -85,11 +84,8 @@
   virtual bool IsJSBasedEventListener() const { return false; }
   virtual bool IsNativeEventListener() const { return false; }
 
-  probe::AsyncTaskId* async_task_id() { return &async_task_id_; }
-
  private:
   EventListener() = default;
-  probe::AsyncTaskId async_task_id_;
 
   // Only these two classes are direct subclasses of EventListener.  Other
   // subclasses must inherit from either of them.
diff --git a/third_party/blink/renderer/core/dom/events/event_queue.cc b/third_party/blink/renderer/core/dom/events/event_queue.cc
index a0a24e1..89c80e0 100644
--- a/third_party/blink/renderer/core/dom/events/event_queue.cc
+++ b/third_party/blink/renderer/core/dom/events/event_queue.cc
@@ -57,8 +57,7 @@
   DCHECK(event.target());
   DCHECK(GetExecutionContext());
 
-  probe::AsyncTaskScheduled(GetExecutionContext(), event.type(),
-                            event.async_task_id());
+  probe::AsyncTaskScheduled(GetExecutionContext(), event.type(), &event);
 
   bool was_added = queued_events_.insert(&event).is_new_entry;
   DCHECK(was_added);  // It should not have already been in the list.
@@ -97,7 +96,7 @@
 
   DCHECK(GetExecutionContext());
 
-  probe::AsyncTask async_task(GetExecutionContext(), event->async_task_id());
+  probe::AsyncTask async_task(GetExecutionContext(), event);
   EventTarget* target = event->target();
   if (LocalDOMWindow* window = target->ToLocalDOMWindow())
     window->DispatchEvent(*event, nullptr);
@@ -116,7 +115,7 @@
 
 void EventQueue::DoCancelAllEvents(ExecutionContext* context) {
   for (const auto& queued_event : queued_events_)
-    probe::AsyncTaskCanceled(context, queued_event->async_task_id());
+    probe::AsyncTaskCanceled(context, queued_event);
   queued_events_.clear();
 }
 
diff --git a/third_party/blink/renderer/core/dom/events/event_target.cc b/third_party/blink/renderer/core/dom/events/event_target.cc
index 9c8c0ad..3dbe4ae 100644
--- a/third_party/blink/renderer/core/dom/events/event_target.cc
+++ b/third_party/blink/renderer/core/dom/events/event_target.cc
@@ -472,8 +472,7 @@
     AddedEventListener(event_type, registered_listener);
     if (IsA<JSBasedEventListener>(listener) &&
         IsInstrumentedForAsyncStack(event_type)) {
-      probe::AsyncTaskScheduled(GetExecutionContext(), event_type,
-                                listener->async_task_id());
+      probe::AsyncTaskScheduled(GetExecutionContext(), event_type, listener);
     }
   }
   return added;
@@ -622,8 +621,7 @@
   if (registered_listener) {
     if (IsA<JSBasedEventListener>(listener) &&
         IsInstrumentedForAsyncStack(event_type)) {
-      probe::AsyncTaskScheduled(GetExecutionContext(), event_type,
-                                listener->async_task_id());
+      probe::AsyncTaskScheduled(GetExecutionContext(), event_type, listener);
     }
     registered_listener->SetCallback(listener);
     return true;
@@ -911,7 +909,7 @@
     bool passive_forced = registered_listener.PassiveForcedForDocumentTarget();
 
     probe::UserCallback probe(context, nullptr, event.type(), false, this);
-    probe::AsyncTask async_task(context, listener->async_task_id(), "event",
+    probe::AsyncTask async_task(context, listener, "event",
                                 IsInstrumentedForAsyncStack(event.type()));
 
     // To match Mozilla, the AT_TARGET phase fires both capturing and bubbling
@@ -989,7 +987,7 @@
   ExecutionContext* context = GetExecutionContext();
   if (!context)
     return;
-  probe::AsyncTaskScheduled(context, event.type(), event.async_task_id());
+  probe::AsyncTaskScheduled(context, event.type(), &event);
   context->GetTaskRunner(task_type)->PostTask(
       FROM_HERE,
       WTF::Bind(&EventTarget::DispatchEnqueuedEvent, WrapPersistent(this),
@@ -999,10 +997,10 @@
 void EventTarget::DispatchEnqueuedEvent(Event* event,
                                         ExecutionContext* context) {
   if (!GetExecutionContext()) {
-    probe::AsyncTaskCanceled(context, event->async_task_id());
+    probe::AsyncTaskCanceled(context, event);
     return;
   }
-  probe::AsyncTask async_task(context, event->async_task_id());
+  probe::AsyncTask async_task(context, event);
   DispatchEvent(*event);
 }
 
diff --git a/third_party/blink/renderer/core/dom/frame_request_callback_collection.cc b/third_party/blink/renderer/core/dom/frame_request_callback_collection.cc
index 3a42dde..37faa19 100644
--- a/third_party/blink/renderer/core/dom/frame_request_callback_collection.cc
+++ b/third_party/blink/renderer/core/dom/frame_request_callback_collection.cc
@@ -25,7 +25,7 @@
                        TRACE_EVENT_SCOPE_THREAD, "data",
                        inspector_animation_frame_event::Data(context_, id));
   probe::AsyncTaskScheduledBreakable(context_, "requestAnimationFrame",
-                                     callback->async_task_id());
+                                     callback);
   return id;
 }
 
@@ -45,7 +45,7 @@
   for (wtf_size_t i = 0; i < frame_callbacks_.size(); ++i) {
     if (frame_callbacks_[i]->Id() == id) {
       probe::AsyncTaskCanceledBreakable(context_, probe_name,
-                                        frame_callbacks_[i]->async_task_id());
+                                        frame_callbacks_[i]);
       frame_callbacks_.EraseAt(i);
       TRACE_EVENT_INSTANT1("devtools.timeline", trace_event_name,
                            TRACE_EVENT_SCOPE_THREAD, "data",
@@ -55,8 +55,8 @@
   }
   for (wtf_size_t i = 0; i < post_frame_callbacks_.size(); ++i) {
     if (post_frame_callbacks_[i]->Id() == id) {
-      probe::AsyncTaskCanceledBreakable(
-          context_, probe_name, post_frame_callbacks_[i]->async_task_id());
+      probe::AsyncTaskCanceledBreakable(context_, probe_name,
+                                        post_frame_callbacks_[i]);
       post_frame_callbacks_.EraseAt(i);
       TRACE_EVENT_INSTANT1("devtools.timeline", trace_event_name,
                            TRACE_EVENT_SCOPE_THREAD, "data",
@@ -66,8 +66,7 @@
   }
   for (const auto& callback : callbacks_to_invoke_) {
     if (callback->Id() == id) {
-      probe::AsyncTaskCanceledBreakable(context_, probe_name,
-                                        callback->async_task_id());
+      probe::AsyncTaskCanceledBreakable(context_, probe_name, callback);
       TRACE_EVENT_INSTANT1("devtools.timeline", trace_event_name,
                            TRACE_EVENT_SCOPE_THREAD, "data",
                            inspector_animation_frame_event::Data(context_, id));
@@ -123,7 +122,7 @@
     TRACE_EVENT1(
         "devtools.timeline", trace_event_name, "data",
         inspector_animation_frame_event::Data(context_, callback->Id()));
-    probe::AsyncTask async_task(context_, callback->async_task_id());
+    probe::AsyncTask async_task(context_, callback);
     probe::UserCallback probe(context_, probe_name, AtomicString(), true);
     if (callback->GetUseLegacyTimeBase())
       callback->Invoke(high_res_now_ms_legacy);
@@ -146,7 +145,7 @@
                        TRACE_EVENT_SCOPE_THREAD, "data",
                        inspector_animation_frame_event::Data(context_, id));
   probe::AsyncTaskScheduledBreakable(context_, "requestPostAnimationFrame",
-                                     callback->async_task_id());
+                                     callback);
   return id;
 }
 
diff --git a/third_party/blink/renderer/core/dom/frame_request_callback_collection.h b/third_party/blink/renderer/core/dom/frame_request_callback_collection.h
index daf9d35..deafb2cf 100644
--- a/third_party/blink/renderer/core/dom/frame_request_callback_collection.h
+++ b/third_party/blink/renderer/core/dom/frame_request_callback_collection.h
@@ -8,7 +8,6 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_frame_request_callback.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/dom_high_res_time_stamp.h"
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/platform/bindings/name_client.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
@@ -45,8 +44,6 @@
       use_legacy_time_base_ = use_legacy_time_base;
     }
 
-    probe::AsyncTaskId* async_task_id() { return &async_task_id_; }
-
    protected:
     FrameCallback() = default;
 
@@ -54,7 +51,6 @@
     int id_ = 0;
     bool is_cancelled_ = false;
     bool use_legacy_time_base_ = false;
-    probe::AsyncTaskId async_task_id_;
   };
 
   // |V8FrameCallback| is an adapter class for the conversion from
diff --git a/third_party/blink/renderer/core/dom/mutation_observer.cc b/third_party/blink/renderer/core/dom/mutation_observer.cc
index 58f5bc8..3a6ad3f 100644
--- a/third_party/blink/renderer/core/dom/mutation_observer.cc
+++ b/third_party/blink/renderer/core/dom/mutation_observer.cc
@@ -240,7 +240,7 @@
   records_.push_back(mutation);
   Activate();
   probe::AsyncTaskScheduled(delegate_->GetExecutionContext(), mutation->type(),
-                            mutation->async_task_id());
+                            mutation);
 }
 
 void MutationObserver::SetHasTransientRegistration() {
@@ -261,10 +261,8 @@
 }
 
 void MutationObserver::CancelInspectorAsyncTasks() {
-  for (auto& record : records_) {
-    probe::AsyncTaskCanceled(delegate_->GetExecutionContext(),
-                             record->async_task_id());
-  }
+  for (auto& record : records_)
+    probe::AsyncTaskCanceled(delegate_->GetExecutionContext(), record);
 }
 
 void MutationObserver::Deliver() {
@@ -289,7 +287,7 @@
 
   // Report the first (earliest) stack as the async cause.
   probe::AsyncTask async_task(delegate_->GetExecutionContext(),
-                              records.front()->async_task_id());
+                              records.front());
   delegate_->Deliver(records, *this);
 }
 
diff --git a/third_party/blink/renderer/core/dom/mutation_record.h b/third_party/blink/renderer/core/dom/mutation_record.h
index c8e5cce..bc69247 100644
--- a/third_party/blink/renderer/core/dom/mutation_record.h
+++ b/third_party/blink/renderer/core/dom/mutation_record.h
@@ -32,7 +32,6 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_MUTATION_RECORD_H_
 
 #include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -77,11 +76,6 @@
   virtual const AtomicString& attributeNamespace() { return g_null_atom; }
 
   virtual String oldValue() { return String(); }
-
-  probe::AsyncTaskId* async_task_id() { return &async_task_id_; }
-
- private:
-  probe::AsyncTaskId async_task_id_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/dom/scripted_animation_controller.cc b/third_party/blink/renderer/core/dom/scripted_animation_controller.cc
index 35e7dc2..0f37c2b 100644
--- a/third_party/blink/renderer/core/dom/scripted_animation_controller.cc
+++ b/third_party/blink/renderer/core/dom/scripted_animation_controller.cc
@@ -132,8 +132,7 @@
     // avoid special casting window.
     // FIXME: We should not fire events for nodes that are no longer in the
     // tree.
-    probe::AsyncTask async_task(event_target->GetExecutionContext(),
-                                event->async_task_id());
+    probe::AsyncTask async_task(event_target->GetExecutionContext(), event);
     if (LocalDOMWindow* window = event_target->ToLocalDOMWindow())
       window->DispatchEvent(*event, nullptr);
     else
@@ -211,7 +210,7 @@
 
 void ScriptedAnimationController::EnqueueEvent(Event* event) {
   probe::AsyncTaskScheduled(event->target()->GetExecutionContext(),
-                            event->type(), event->async_task_id());
+                            event->type(), event);
   event_queue_.push_back(event);
   ScheduleAnimationIfNeeded();
 }
diff --git a/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc b/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc
index a9812c8..4d47f46 100644
--- a/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc
+++ b/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc
@@ -128,7 +128,7 @@
                           idle_task, queue_timestamp, timeout_millis));
 
   probe::AsyncTaskScheduled(GetExecutionContext(), "requestIdleCallback",
-                            idle_task->async_task_id());
+                            idle_task);
 
   scoped_refptr<internal::IdleRequestCallbackWrapper> callback_wrapper =
       internal::IdleRequestCallbackWrapper::Create(id, this);
@@ -208,8 +208,7 @@
   TimeTicks now = CurrentTimeTicks();
   TimeDelta allotted_time = std::max(deadline - now, TimeDelta());
 
-  probe::AsyncTask async_task(GetExecutionContext(),
-                              idle_task->async_task_id());
+  probe::AsyncTask async_task(GetExecutionContext(), idle_task);
   probe::UserCallback probe(GetExecutionContext(), "requestIdleCallback",
                             AtomicString(), true);
 
diff --git a/third_party/blink/renderer/core/dom/scripted_idle_task_controller.h b/third_party/blink/renderer/core/dom/scripted_idle_task_controller.h
index 80a68ee..b5803ff 100644
--- a/third_party/blink/renderer/core/dom/scripted_idle_task_controller.h
+++ b/third_party/blink/renderer/core/dom/scripted_idle_task_controller.h
@@ -8,7 +8,6 @@
 #include "third_party/blink/renderer/bindings/core/v8/v8_idle_request_callback.h"
 #include "third_party/blink/renderer/core/dom/idle_deadline.h"
 #include "third_party/blink/renderer/core/execution_context/context_lifecycle_state_observer.h"
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/platform/bindings/name_client.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/timer.h"
@@ -56,10 +55,6 @@
     const char* NameInHeapSnapshot() const override { return "IdleTask"; }
     virtual ~IdleTask() = default;
     virtual void invoke(IdleDeadline*) = 0;
-    probe::AsyncTaskId* async_task_id() { return &async_task_id_; }
-
-   private:
-    probe::AsyncTaskId async_task_id_;
   };
 
   // |V8IdleTask| is the adapter class for the conversion from
diff --git a/third_party/blink/renderer/core/dom/user_gesture_indicator.cc b/third_party/blink/renderer/core/dom/user_gesture_indicator.cc
index 477a3bbdb..6fb4483e 100644
--- a/third_party/blink/renderer/core/dom/user_gesture_indicator.cc
+++ b/third_party/blink/renderer/core/dom/user_gesture_indicator.cc
@@ -80,29 +80,13 @@
   kGestureMergeStateEnd = 1 << 2,
 };
 
-// Remove this when user gesture propagation is standardized. See
-// https://crbug.com/404161.
-static void RecordUserGestureMerge(const UserGestureToken& old_token,
-                                   const UserGestureToken& new_token) {
-  DEFINE_STATIC_LOCAL(EnumerationHistogram, gesture_merge_histogram,
-                      ("Blink.Gesture.Merged", kGestureMergeStateEnd));
-  int sample = 0;
-  if (old_token.HasGestures())
-    sample |= kOldTokenHasGesture;
-  if (new_token.HasGestures())
-    sample |= kNewTokenHasGesture;
-  gesture_merge_histogram.Count(sample);
-}
-
 UserGestureToken* UserGestureIndicator::root_token_ = nullptr;
 
 void UserGestureIndicator::UpdateRootToken() {
-  if (!root_token_) {
+  if (!root_token_)
     root_token_ = token_.get();
-  } else {
-    RecordUserGestureMerge(*root_token_, *token_);
+  else
     token_->TransferGestureTo(root_token_);
-  }
 }
 
 UserGestureIndicator::UserGestureIndicator(
diff --git a/third_party/blink/renderer/core/exported/web_frame_serializer.cc b/third_party/blink/renderer/core/exported/web_frame_serializer.cc
index 528f319..0f0dc6f 100644
--- a/third_party/blink/renderer/core/exported/web_frame_serializer.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_serializer.cc
@@ -235,8 +235,10 @@
   // images, as only the value of src is pulled into the archive. Discarding
   // srcset prevents the problem. Long term we should make sure to MHTML plays
   // nicely with srcset.
-  if (attribute.LocalName() == html_names::kSrcsetAttr)
+  if (IsHTMLImageElement(element) &&
+      attribute.LocalName() == html_names::kSrcsetAttr) {
     return true;
+  }
 
   // Do not save ping attribute since anyway the ping will be blocked from
   // MHTML.
diff --git a/third_party/blink/renderer/core/exported/web_frame_serializer_sanitization_test.cc b/third_party/blink/renderer/core/exported/web_frame_serializer_sanitization_test.cc
index 57bf39f..32780f8f 100644
--- a/third_party/blink/renderer/core/exported/web_frame_serializer_sanitization_test.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_serializer_sanitization_test.cc
@@ -413,4 +413,24 @@
   EXPECT_EQ(WTF::kNotFound, mhtml.Find("h1 { color: green; }"));
 }
 
+TEST_F(WebFrameSerializerSanitizationTest, PictureElement) {
+  RegisterMockedFileURLLoad(KURL("http://www.test.com/1x.png"),
+                            "frameserialization/1x.png");
+  RegisterMockedFileURLLoad(KURL("http://www.test.com/2x.png"),
+                            "frameserialization/2x.png");
+
+  WebView()->MainFrameWidget()->Resize(WebSize(500, 500));
+
+  String mhtml = GenerateMHTMLFromHtml("http://www.test.com", "picture.html");
+
+  // srcset attribute should be kept.
+  EXPECT_EQ(2, MatchSubstring(mhtml, "srcset=", 7));
+
+  // 2x.png resource should be added.
+  EXPECT_NE(WTF::kNotFound,
+            mhtml.Find("Content-Location: http://www.test.com/2x.png"));
+  EXPECT_EQ(WTF::kNotFound,
+            mhtml.Find("Content-Location: http://www.test.com/1x.png"));
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc
index 4a334ed..0bbd397 100644
--- a/third_party/blink/renderer/core/exported/web_frame_test.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -11541,7 +11541,7 @@
 
   // Now resize the visual viewport so that the input box is no longer in view
   // (e.g. a keyboard is overlayed).
-  WebView().MainFrameWidget()->ResizeVisualViewport(IntSize(200, 100));
+  WebView().ResizeVisualViewport(IntSize(200, 100));
   ASSERT_FALSE(frame_view->GetScrollableArea()->VisibleContentRect().Contains(
       inputRect));
 
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h
index ad0cef23..9e20f34 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.h
+++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -162,6 +162,7 @@
   void SetVisualViewportOffset(const WebFloatPoint&) override;
   WebFloatPoint VisualViewportOffset() const override;
   WebFloatSize VisualViewportSize() const override;
+  void ResizeVisualViewport(const WebSize&) override;
   void ResetScrollAndScaleState() override;
   void SetIgnoreViewportTagScaleLimits(bool) override;
   WebSize ContentsPreferredMinimumSize() override;
@@ -434,7 +435,6 @@
   void Close() override;
   WebSize Size() override;
   void Resize(const WebSize&) override;
-  void ResizeVisualViewport(const WebSize&) override;
   void DidEnterFullscreen() override;
   void DidExitFullscreen() override;
   void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) override;
diff --git a/third_party/blink/renderer/core/fileapi/file_reader.cc b/third_party/blink/renderer/core/fileapi/file_reader.cc
index 034b7063..5aeef60 100644
--- a/third_party/blink/renderer/core/fileapi/file_reader.cc
+++ b/third_party/blink/renderer/core/fileapi/file_reader.cc
@@ -95,7 +95,7 @@
     if (!controller)
       return;
 
-    probe::AsyncTaskScheduled(context, "FileReader", reader->async_task_id());
+    probe::AsyncTaskScheduled(context, "FileReader", reader);
     controller->PushReader(reader);
   }
 
@@ -116,7 +116,7 @@
       return;
 
     controller->FinishReader(reader, next_step);
-    probe::AsyncTaskCanceled(context, reader->async_task_id());
+    probe::AsyncTaskCanceled(context, reader);
   }
 
   explicit ThrottlingController(ExecutionContext& context)
@@ -459,7 +459,7 @@
 }
 
 void FileReader::FireEvent(const AtomicString& type) {
-  probe::AsyncTask async_task(GetExecutionContext(), async_task_id(), "event");
+  probe::AsyncTask async_task(GetExecutionContext(), this, "event");
   if (!loader_) {
     DispatchEvent(*ProgressEvent::Create(type, false, 0, 0));
     return;
diff --git a/third_party/blink/renderer/core/fileapi/file_reader.h b/third_party/blink/renderer/core/fileapi/file_reader.h
index 335c949..17ed1a4 100644
--- a/third_party/blink/renderer/core/fileapi/file_reader.h
+++ b/third_party/blink/renderer/core/fileapi/file_reader.h
@@ -38,7 +38,6 @@
 #include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
 #include "third_party/blink/renderer/core/fileapi/file_reader_loader.h"
 #include "third_party/blink/renderer/core/fileapi/file_reader_loader_client.h"
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 
@@ -75,7 +74,6 @@
   ReadyState getReadyState() const { return state_; }
   DOMException* error() { return error_; }
   void result(ScriptState*, StringOrArrayBuffer& result_attribute) const;
-  probe::AsyncTaskId* async_task_id() { return &async_task_id_; }
 
   // ContextLifecycleObserver
   void ContextDestroyed(ExecutionContext*) override;
@@ -130,7 +128,6 @@
   scoped_refptr<BlobDataHandle> blob_data_handle_;
   FileReaderLoader::ReadType read_type_;
   String encoding_;
-  probe::AsyncTaskId async_task_id_;
 
   std::unique_ptr<FileReaderLoader> loader_;
   Member<DOMException> error_;
diff --git a/third_party/blink/renderer/core/frame/ad_tracker.cc b/third_party/blink/renderer/core/frame/ad_tracker.cc
index 8970096..64ccaefa 100644
--- a/third_party/blink/renderer/core/frame/ad_tracker.cc
+++ b/third_party/blink/renderer/core/frame/ad_tracker.cc
@@ -6,7 +6,6 @@
 
 #include <memory>
 
-#include "base/feature_list.h"
 #include "third_party/blink/renderer/bindings/core/v8/source_location.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/core/core_probe_sink.h"
@@ -33,31 +32,7 @@
 
 }  // namespace
 
-namespace features {
-// Controls whether the AdTracker will look across async stacks to determine if
-// the currently running stack is ad related.
-const base::Feature kAsyncStackAdTagging{"AsyncStackAdTagging",
-                                         base::FEATURE_DISABLED_BY_DEFAULT};
-}  // namespace features
-
-// static
-AdTracker* AdTracker::FromExecutionContext(
-    ExecutionContext* execution_context) {
-  if (!execution_context)
-    return nullptr;
-  if (auto* document = DynamicTo<Document>(execution_context)) {
-    LocalFrame* frame = document->GetFrame();
-    if (frame) {
-      return frame->GetAdTracker();
-    }
-  }
-  return nullptr;
-}
-
-AdTracker::AdTracker(LocalFrame* local_root)
-    : local_root_(local_root),
-      async_stack_enabled_(
-          base::FeatureList::IsEnabled(features::kAsyncStackAdTagging)) {
+AdTracker::AdTracker(LocalFrame* local_root) : local_root_(local_root) {
   local_root_->GetProbeSink()->AddAdTracker(this);
 }
 
@@ -157,35 +132,8 @@
   return known_ad;
 }
 
-void AdTracker::DidCreateAsyncTask(probe::AsyncTaskId* task) {
-  DCHECK(task);
-  if (!async_stack_enabled_)
-    return;
-
-  if (IsAdScriptInStack())
-    task->SetAdTask();
-}
-
-void AdTracker::DidStartAsyncTask(probe::AsyncTaskId* task) {
-  DCHECK(task);
-  if (!async_stack_enabled_)
-    return;
-
-  if (task->IsAdTask())
-    running_ad_async_tasks_ += 1;
-}
-
-void AdTracker::DidFinishAsyncTask(probe::AsyncTaskId* task) {
-  DCHECK(task);
-  if (!async_stack_enabled_)
-    return;
-
-  if (task->IsAdTask())
-    running_ad_async_tasks_ -= 1;
-}
-
 bool AdTracker::IsAdScriptInStack() {
-  if (num_ads_in_stack_ > 0 || running_ad_async_tasks_ > 0)
+  if (num_ads_in_stack_ > 0)
     return true;
 
   ExecutionContext* execution_context = GetCurrentExecutionContext();
diff --git a/third_party/blink/renderer/core/frame/ad_tracker.h b/third_party/blink/renderer/core/frame/ad_tracker.h
index 001981e..b88ff12 100644
--- a/third_party/blink/renderer/core/frame/ad_tracker.h
+++ b/third_party/blink/renderer/core/frame/ad_tracker.h
@@ -7,7 +7,6 @@
 
 #include "base/macros.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/platform/heap/member.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
@@ -25,17 +24,10 @@
 class ExecuteScript;
 }  // namespace probe
 
-namespace features {
-CORE_EXPORT extern const base::Feature kAsyncStackAdTagging;
-}
-
 // Tracker for tagging resources as ads based on the call stack scripts.
 // The tracker is maintained per local root.
 class CORE_EXPORT AdTracker : public GarbageCollectedFinalized<AdTracker> {
  public:
-  // Finds an AdTracker for a given ExecutionContext.
-  static AdTracker* FromExecutionContext(ExecutionContext*);
-
   // Instrumenting methods.
   // Called when a script module or script gets executed from native code.
   void Will(const probe::ExecuteScript&);
@@ -56,16 +48,6 @@
                                         ResourceType resource_type,
                                         bool known_ad);
 
-  // Called when an async task is created. Check at this point for ad script on
-  // the stack and annotate the task if so.
-  void DidCreateAsyncTask(probe::AsyncTaskId* task);
-
-  // Called when an async task is eventually run.
-  void DidStartAsyncTask(probe::AsyncTaskId* task);
-
-  // Called when the task has finished running.
-  void DidFinishAsyncTask(probe::AsyncTaskId* task);
-
   // Returns true if any script in the pseudo call stack has previously been
   // identified as an ad resource.
   bool IsAdScriptInStack();
@@ -102,11 +84,6 @@
   // The set of ad scripts detected outside of ad-frame contexts.
   HeapHashMap<WeakMember<ExecutionContext>, HashSet<String>> known_ad_scripts_;
 
-  // The number of ad-related async tasks currently running in the stack.
-  uint32_t running_ad_async_tasks_ = 0;
-
-  const bool async_stack_enabled_;
-
   DISALLOW_COPY_AND_ASSIGN(AdTracker);
 };
 
diff --git a/third_party/blink/renderer/core/frame/ad_tracker_test.cc b/third_party/blink/renderer/core/frame/ad_tracker_test.cc
index b5f92e2..2a88349 100644
--- a/third_party/blink/renderer/core/frame/ad_tracker_test.cc
+++ b/third_party/blink/renderer/core/frame/ad_tracker_test.cc
@@ -6,11 +6,8 @@
 
 #include <memory>
 
-#include "base/test/scoped_feature_list.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/core/probe/core_probes.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_request.h"
@@ -91,13 +88,6 @@
     return page_holder_->GetDocument().GetFrame();
   }
 
-  void CreateAdTracker() {
-    if (ad_tracker_)
-      ad_tracker_->Shutdown();
-    ad_tracker_ = MakeGarbageCollected<TestAdTracker>(GetFrame());
-    ad_tracker_->SetExecutionContext(&page_holder_->GetDocument());
-  }
-
   void WillExecuteScript(const String& script_url) {
     ad_tracker_->WillExecuteScript(&page_holder_->GetDocument(),
                                    String(script_url));
@@ -120,7 +110,8 @@
 void AdTrackerTest::SetUp() {
   page_holder_ = std::make_unique<DummyPageHolder>(IntSize(800, 600));
   page_holder_->GetDocument().SetURL(KURL("https://example.com/foo"));
-  CreateAdTracker();
+  ad_tracker_ = MakeGarbageCollected<TestAdTracker>(GetFrame());
+  ad_tracker_->SetExecutionContext(&page_holder_->GetDocument());
 }
 
 void AdTrackerTest::TearDown() {
@@ -204,49 +195,6 @@
   EXPECT_TRUE(AnyExecutingScriptsTaggedAsAdResource());
 }
 
-TEST_F(AdTrackerTest, AsyncTagging) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(features::kAsyncStackAdTagging);
-  CreateAdTracker();
-
-  // Put an ad script on the stack.
-  AppendToKnownAdScripts("https://example.com/ad.js");
-  WillExecuteScript("https://example.com/ad.js");
-  EXPECT_TRUE(AnyExecutingScriptsTaggedAsAdResource());
-
-  // Create a fake task void*.
-  probe::AsyncTaskId async_task;
-
-  // Create an async task while ad script is running.
-  ad_tracker_->DidCreateAsyncTask(&async_task);
-
-  // Finish executing the ad script.
-  DidExecuteScript();
-  EXPECT_FALSE(AnyExecutingScriptsTaggedAsAdResource());
-
-  // Start and stop the async task created by the ad script.
-  ad_tracker_->DidStartAsyncTask(&async_task);
-  EXPECT_TRUE(AnyExecutingScriptsTaggedAsAdResource());
-  ad_tracker_->DidFinishAsyncTask(&async_task);
-  EXPECT_FALSE(AnyExecutingScriptsTaggedAsAdResource());
-
-  // Do it again.
-  ad_tracker_->DidStartAsyncTask(&async_task);
-  EXPECT_TRUE(AnyExecutingScriptsTaggedAsAdResource());
-  ad_tracker_->DidFinishAsyncTask(&async_task);
-  EXPECT_FALSE(AnyExecutingScriptsTaggedAsAdResource());
-
-  // Call the task recursively.
-  ad_tracker_->DidStartAsyncTask(&async_task);
-  EXPECT_TRUE(AnyExecutingScriptsTaggedAsAdResource());
-  ad_tracker_->DidStartAsyncTask(&async_task);
-  EXPECT_TRUE(AnyExecutingScriptsTaggedAsAdResource());
-  ad_tracker_->DidFinishAsyncTask(&async_task);
-  EXPECT_TRUE(AnyExecutingScriptsTaggedAsAdResource());
-  ad_tracker_->DidFinishAsyncTask(&async_task);
-  EXPECT_FALSE(AnyExecutingScriptsTaggedAsAdResource());
-}
-
 class AdTrackerSimTest : public SimTest {
  protected:
   void SetUp() override {
@@ -424,15 +372,7 @@
 }
 
 // Image loaded by ad script is tagged as ad.
-TEST_F(AdTrackerSimTest, ImageLoadedWhileExecutingAdScriptAsyncEnabled) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(features::kAsyncStackAdTagging);
-
-  // Reset the AdTracker so that it gets the latest base::Feature value on
-  // construction.
-  ad_tracker_ = MakeGarbageCollected<TestAdTracker>(GetDocument().GetFrame());
-  GetDocument().GetFrame()->SetAdTrackerForTesting(ad_tracker_);
-
+TEST_F(AdTrackerSimTest, ImageLoadedWhileExecutingAdScript) {
   const char kAdUrl[] = "https://example.com/ad_script.js";
   const char kVanillaUrl[] = "https://example.com/vanilla_image.jpg";
   SimSubresourceRequest ad_resource(kAdUrl, "text/javascript");
@@ -455,47 +395,7 @@
 
   EXPECT_TRUE(IsKnownAdScript(&GetDocument(), kAdUrl));
   EXPECT_TRUE(ad_tracker_->RequestWithUrlTaggedAsAd(kAdUrl));
-
-  // Image loading is async, so we should catch this when async stacks are
-  // monitored.
-  EXPECT_TRUE(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaUrl));
-}
-
-// Image loaded by ad script is tagged as ad.
-TEST_F(AdTrackerSimTest, ImageLoadedWhileExecutingAdScriptAsyncDisabled) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndDisableFeature(features::kAsyncStackAdTagging);
-
-  // Reset the AdTracker so that it gets the latest base::Feature value on
-  // construction.
-  ad_tracker_ = MakeGarbageCollected<TestAdTracker>(GetDocument().GetFrame());
-  GetDocument().GetFrame()->SetAdTrackerForTesting(ad_tracker_);
-
-  const char kAdUrl[] = "https://example.com/ad_script.js";
-  const char kVanillaUrl[] = "https://example.com/vanilla_image.jpg";
-  SimSubresourceRequest ad_resource(kAdUrl, "text/javascript");
-  SimSubresourceRequest vanilla_image(kVanillaUrl, "image/jpeg");
-
-  ad_tracker_->SetAdSuffix("ad_script.js");
-
-  main_resource_->Complete("<body></body><script src=ad_script.js></script>");
-
-  ad_resource.Complete(R"SCRIPT(
-    image = document.createElement("img");
-    image.src = "vanilla_image.jpg";
-    document.body.appendChild(image);
-    )SCRIPT");
-
-  // Wait for script to run.
-  base::RunLoop().RunUntilIdle();
-
-  vanilla_image.Complete("");
-
-  EXPECT_TRUE(IsKnownAdScript(&GetDocument(), kAdUrl));
-  EXPECT_TRUE(ad_tracker_->RequestWithUrlTaggedAsAd(kAdUrl));
-
-  // Image loading is async, so we won't catch this when async stacks aren't
-  // monitored.
+  // TODO(crbug.com/848916): Should be true.
   EXPECT_FALSE(ad_tracker_->RequestWithUrlTaggedAsAd(kVanillaUrl));
 }
 
diff --git a/third_party/blink/renderer/core/frame/dom_timer.cc b/third_party/blink/renderer/core/frame/dom_timer.cc
index 32ef55a..419c2da 100644
--- a/third_party/blink/renderer/core/frame/dom_timer.cc
+++ b/third_party/blink/renderer/core/frame/dom_timer.cc
@@ -108,7 +108,7 @@
                        inspector_timer_install_event::Data(
                            context, timeout_id, interval, single_shot));
   probe::AsyncTaskScheduledBreakable(
-      context, single_shot ? "setTimeout" : "setInterval", &async_task_id_);
+      context, single_shot ? "setTimeout" : "setInterval", this);
 }
 
 DOMTimer::~DOMTimer() {
@@ -120,7 +120,7 @@
   const bool is_interval = !RepeatInterval().is_zero();
   probe::AsyncTaskCanceledBreakable(
       GetExecutionContext(), is_interval ? "clearInterval" : "clearTimeout",
-      &async_task_id_);
+      this);
 
   user_gesture_token_ = nullptr;
   // Need to release JS objects potentially protected by ScheduledAction
@@ -150,8 +150,7 @@
   const bool is_interval = !RepeatInterval().is_zero();
   probe::UserCallback probe(context, is_interval ? "setInterval" : "setTimeout",
                             g_null_atom, true);
-  probe::AsyncTask async_task(context, &async_task_id_,
-                              is_interval ? "fired" : nullptr);
+  probe::AsyncTask async_task(context, this, is_interval ? "fired" : nullptr);
 
   // Simple case for non-one-shot timers.
   if (IsActive()) {
diff --git a/third_party/blink/renderer/core/frame/dom_timer.h b/third_party/blink/renderer/core/frame/dom_timer.h
index 517ebb9d..58da7f4 100644
--- a/third_party/blink/renderer/core/frame/dom_timer.h
+++ b/third_party/blink/renderer/core/frame/dom_timer.h
@@ -31,7 +31,6 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/user_gesture_indicator.h"
 #include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/platform/bindings/name_client.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/timer.h"
@@ -85,7 +84,6 @@
 
   int timeout_id_;
   int nesting_level_;
-  probe::AsyncTaskId async_task_id_;
   Member<ScheduledAction> action_;
   scoped_refptr<UserGestureToken> user_gesture_token_;
 };
diff --git a/third_party/blink/renderer/core/frame/frame_serializer.cc b/third_party/blink/renderer/core/frame/frame_serializer.cc
index 9c258b0..979d4c2 100644
--- a/third_party/blink/renderer/core/frame/frame_serializer.cc
+++ b/third_party/blink/renderer/core/frame/frame_serializer.cc
@@ -361,8 +361,11 @@
   }
 
   if (const auto* image = ToHTMLImageElementOrNull(element)) {
-    KURL image_url =
-        document.CompleteURL(image->getAttribute(html_names::kSrcAttr));
+    // ImageSourceURL() works for both scenarios:
+    // * parent element is <picture>: best fit image URL from sibling source
+    //   element
+    // * single <img> element: image url contained in href attribute
+    KURL image_url = document.CompleteURL(image->ImageSourceURL());
     ImageResourceContent* cached_image = image->CachedImage();
     AddImageToResources(cached_image, image_url);
   } else if (const auto* input = ToHTMLInputElementOrNull(element)) {
diff --git a/third_party/blink/renderer/core/frame/frame_test.cc b/third_party/blink/renderer/core/frame/frame_test.cc
index 0a126c3..949ffb6 100644
--- a/third_party/blink/renderer/core/frame/frame_test.cc
+++ b/third_party/blink/renderer/core/frame/frame_test.cc
@@ -4,7 +4,6 @@
 
 #include "third_party/blink/renderer/core/frame/frame.h"
 
-#include "base/test/metrics/histogram_tester.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/core/dom/user_gesture_indicator.h"
 #include "third_party/blink/renderer/core/loader/document_loader.h"
@@ -187,35 +186,6 @@
       LocalFrame::ConsumeTransientUserActivation(GetDocument().GetFrame()));
 }
 
-TEST_F(FrameTest, UserActivationHistograms) {
-  ScopedUserActivationV2ForTest scoped_feature(true);
-  base::HistogramTester histograms;
-
-  LocalFrame::HasTransientUserActivation(GetDocument().GetFrame());
-  histograms.ExpectBucketCount("UserActivation.AvailabilityCheck.FrameResult",
-                               0, 1);
-
-  LocalFrame::ConsumeTransientUserActivation(GetDocument().GetFrame());
-  histograms.ExpectBucketCount("UserActivation.Consumption.FrameResult", 0, 1);
-
-  LocalFrame::NotifyUserActivation(GetDocument().GetFrame());
-
-  LocalFrame::HasTransientUserActivation(GetDocument().GetFrame());
-  LocalFrame::HasTransientUserActivation(GetDocument().GetFrame());
-  histograms.ExpectBucketCount("UserActivation.AvailabilityCheck.FrameResult",
-                               3, 2);
-
-  LocalFrame::ConsumeTransientUserActivation(GetDocument().GetFrame());
-  histograms.ExpectBucketCount("UserActivation.Consumption.FrameResult", 3, 1);
-
-  LocalFrame::ConsumeTransientUserActivation(GetDocument().GetFrame());
-  histograms.ExpectBucketCount("UserActivation.Consumption.FrameResult", 0, 2);
-
-  histograms.ExpectTotalCount("UserActivation.AvailabilityCheck.FrameResult",
-                              3);
-  histograms.ExpectTotalCount("UserActivation.Consumption.FrameResult", 3);
-}
-
 TEST_F(FrameTest, TestDocumentInterfaceBrokerOverride) {
   mojom::blink::DocumentInterfaceBrokerPtr doc;
   FrameHostTestDocumentInterfaceBroker frame_interface_broker(
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index 45af36ae..ae0a6c2f 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -556,7 +556,7 @@
                            WrapPersistent(this), WrapPersistent(event),
                            WrapRefCounted(UserGestureIndicator::CurrentToken()),
                            std::move(target), std::move(location)));
-  probe::AsyncTaskScheduled(document(), "postMessage", event->async_task_id());
+  probe::AsyncTaskScheduled(document(), "postMessage", event);
 }
 
 void LocalDOMWindow::DispatchPostMessage(
@@ -564,7 +564,7 @@
     scoped_refptr<UserGestureToken> token,
     scoped_refptr<const SecurityOrigin> intended_target_origin,
     std::unique_ptr<SourceLocation> location) {
-  probe::AsyncTask async_task(document(), event->async_task_id());
+  probe::AsyncTask async_task(document(), event);
   if (!IsCurrentlyDisplayedInFrame())
     return;
 
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index 2aab679..75bb862 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -153,60 +153,6 @@
   return true;
 }
 
-WeakPersistent<LocalFrame>& UserActivationNotifierFrame() {
-  DEFINE_STATIC_LOCAL(WeakPersistent<LocalFrame>,
-                      user_activation_notifier_frame, (nullptr));
-  return user_activation_notifier_frame;
-}
-
-enum class UserActivationFrameResultEnum : int {
-  kNullFailure = 0,
-  kNullSuccess = 1,
-  kSelfFailure = 2,
-  kSelfSuccess = 3,
-  kAncestorFailure = 4,
-  kAncestorSuccess = 5,
-  kDescendantFailure = 6,
-  kDescendantSuccess = 7,
-  kOtherFailure = 8,
-  kOtherSuccess = 9,
-  kNonMainThreadFailure = 10,
-  kNonMainThreadSuccess = 11,
-  kMaxValue = kNonMainThreadSuccess
-};
-
-UserActivationFrameResultEnum DetermineActivationResultEnum(
-    const LocalFrame* const caller_frame,
-    const bool call_succeeded,
-    const bool off_main_thread) {
-  if (off_main_thread) {
-    return call_succeeded
-               ? UserActivationFrameResultEnum::kNonMainThreadSuccess
-               : UserActivationFrameResultEnum::kNonMainThreadFailure;
-  }
-
-  LocalFrame* user_activation_notifier_frame = UserActivationNotifierFrame();
-
-  if (!caller_frame || !user_activation_notifier_frame) {
-    return call_succeeded ? UserActivationFrameResultEnum::kNullSuccess
-                          : UserActivationFrameResultEnum::kNullFailure;
-  }
-  if (caller_frame == user_activation_notifier_frame) {
-    return call_succeeded ? UserActivationFrameResultEnum::kSelfSuccess
-                          : UserActivationFrameResultEnum::kSelfFailure;
-  }
-  if (user_activation_notifier_frame->Tree().IsDescendantOf(caller_frame)) {
-    return call_succeeded ? UserActivationFrameResultEnum::kAncestorSuccess
-                          : UserActivationFrameResultEnum::kAncestorFailure;
-  }
-  if (caller_frame->Tree().IsDescendantOf(user_activation_notifier_frame)) {
-    return call_succeeded ? UserActivationFrameResultEnum::kDescendantSuccess
-                          : UserActivationFrameResultEnum::kDescendantFailure;
-  }
-  return call_succeeded ? UserActivationFrameResultEnum::kOtherSuccess
-                        : UserActivationFrameResultEnum::kOtherFailure;
-}
-
 }  // namespace
 
 template class CORE_TEMPLATE_EXPORT Supplement<LocalFrame>;
@@ -337,9 +283,6 @@
   // Starting here, the code must be safe against re-entrancy. Dispatching
   // events, et cetera can run Javascript, which can reenter Detach().
   // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-  if (this == UserActivationNotifierFrame())
-    UserActivationNotifierFrame().Clear();
-
   frame_color_overlay_.reset();
 
   if (IsLocalRoot()) {
@@ -1538,10 +1481,8 @@
 std::unique_ptr<UserGestureIndicator> LocalFrame::NotifyUserActivation(
     LocalFrame* frame,
     UserGestureToken::Status status) {
-  if (frame) {
-    UserActivationNotifierFrame() = frame;
+  if (frame)
     frame->NotifyUserActivation();
-  }
   return std::make_unique<UserGestureIndicator>(status);
 }
 
@@ -1550,32 +1491,20 @@
     LocalFrame* frame,
     UserGestureToken* token) {
   DCHECK(!RuntimeEnabledFeatures::UserActivationV2Enabled());
-  if (frame) {
-    UserActivationNotifierFrame() = frame;
+  if (frame)
     frame->NotifyUserActivation();
-  }
   return std::make_unique<UserGestureIndicator>(token);
 }
 
 // static
 bool LocalFrame::HasTransientUserActivation(LocalFrame* frame,
                                             bool check_if_main_thread) {
-  bool available;
+  if (RuntimeEnabledFeatures::UserActivationV2Enabled())
+    return frame ? frame->HasTransientUserActivation() : false;
 
-  if (RuntimeEnabledFeatures::UserActivationV2Enabled()) {
-    available = frame ? frame->HasTransientUserActivation() : false;
-  } else {
-    available = check_if_main_thread
-                    ? UserGestureIndicator::ProcessingUserGestureThreadSafe()
-                    : UserGestureIndicator::ProcessingUserGesture();
-  }
-
-  const bool off_main_thread = check_if_main_thread && !IsMainThread();
-  UMA_HISTOGRAM_ENUMERATION(
-      "UserActivation.AvailabilityCheck.FrameResult",
-      DetermineActivationResultEnum(frame, available, off_main_thread));
-
-  return available;
+  return check_if_main_thread
+             ? UserGestureIndicator::ProcessingUserGestureThreadSafe()
+             : UserGestureIndicator::ProcessingUserGesture();
 }
 
 // static
@@ -1583,25 +1512,12 @@
     LocalFrame* frame,
     bool check_if_main_thread,
     UserActivationUpdateSource update_source) {
-  bool consumed;
+  if (RuntimeEnabledFeatures::UserActivationV2Enabled())
+    return frame ? frame->ConsumeTransientUserActivation(update_source) : false;
 
-  if (RuntimeEnabledFeatures::UserActivationV2Enabled()) {
-    consumed =
-        frame ? frame->ConsumeTransientUserActivation(update_source) : false;
-  } else {
-    consumed = check_if_main_thread
-                   ? UserGestureIndicator::ConsumeUserGestureThreadSafe()
-                   : UserGestureIndicator::ConsumeUserGesture();
-  }
-
-  const bool off_main_thread = check_if_main_thread && !IsMainThread();
-  UMA_HISTOGRAM_ENUMERATION(
-      "UserActivation.Consumption.FrameResult",
-      DetermineActivationResultEnum(frame, consumed, off_main_thread));
-  if (!off_main_thread)
-    UserActivationNotifierFrame().Clear();
-
-  return consumed;
+  return check_if_main_thread
+             ? UserGestureIndicator::ConsumeUserGestureThreadSafe()
+             : UserGestureIndicator::ConsumeUserGesture();
 }
 
 void LocalFrame::NotifyUserActivation() {
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc
index 5d2dae4..c4c392ba 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -1913,6 +1913,9 @@
 
     page->GlobalRootScrollerController().InitializeViewportScrollCallback(
         *root_frame_viewport, *frame_->GetDocument());
+
+    // Allow for commits to be deferred because this is a new document.
+    have_deferred_commits_ = false;
   }
 }
 
@@ -3321,6 +3324,10 @@
 void LocalFrameView::TrackObjectPaintInvalidation(
     const DisplayItemClient& client,
     PaintInvalidationReason reason) {
+  TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("blink.invalidation"),
+                       "InvalidateDisplayItemClient", TRACE_EVENT_SCOPE_GLOBAL,
+                       "client", client.DebugName().Utf8(), "reason",
+                       PaintInvalidationReasonToString(reason));
   if (!tracked_object_paint_invalidations_)
     return;
 
@@ -4146,8 +4153,17 @@
   if (document && base::FeatureList::IsEnabled(
                       blink::features::kAvoidFlashBetweenNavigation)) {
     if (document->DeferredCompositorCommitIsAllowed()) {
-      chrome_client.StartDeferringCommits(
-          GetCommitDelayForAvoidFlashBetweenNavigation());
+      // Only defer commits once. This method gets called multiple times,
+      // and we do not want to defer a second time if we have already done
+      // so once and resumed commits already.
+      if (!have_deferred_commits_) {
+        chrome_client.StartDeferringCommits(
+            GetCommitDelayForAvoidFlashBetweenNavigation());
+        have_deferred_commits_ = true;
+      }
+      // We do not StopDeferringCommits in cases where we have already started.
+      // A previously started deferral may not have completed yet, and we do
+      // not want to stop it prematurely.
     } else {
       chrome_client.StopDeferringCommits(
           cc::PaintHoldingCommitTrigger::kDisallowed);
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h
index ea77e3f..29af8150 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.h
+++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -957,6 +957,10 @@
   bool needs_focus_on_fragment_;
   bool in_lifecycle_update_;
 
+  // True if the frame has deferred commits at least once per document load.
+  // We won't defer again for the same document.
+  bool have_deferred_commits_ = false;
+
   LifecycleData lifecycle_data_;
 
   IntRect remote_viewport_intersection_;
diff --git a/third_party/blink/renderer/core/frame/visual_viewport_test.cc b/third_party/blink/renderer/core/frame/visual_viewport_test.cc
index e231aa2..4a48109 100644
--- a/third_party/blink/renderer/core/frame/visual_viewport_test.cc
+++ b/third_party/blink/renderer/core/frame/visual_viewport_test.cc
@@ -1703,14 +1703,14 @@
   NavigateTo("about:blank");
   UpdateAllLifecyclePhases();
 
-  WebView()->MainFrameWidget()->ResizeVisualViewport(IntSize(100, 100));
+  WebView()->ResizeVisualViewport(IntSize(100, 100));
 
   VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport();
   visual_viewport.Move(ScrollOffset(0, 100));
 
   EXPECT_EQ(100, visual_viewport.GetScrollOffset().Height());
 
-  WebView()->MainFrameWidget()->ResizeVisualViewport(IntSize(100, 200));
+  WebView()->ResizeVisualViewport(IntSize(100, 200));
 
   EXPECT_EQ(0, visual_viewport.GetScrollOffset().Height());
 }
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
index af01358..abe502c 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -235,23 +235,6 @@
   }
 }
 
-void WebFrameWidgetImpl::ResizeVisualViewport(const WebSize& new_size) {
-  if (!LocalRootImpl()) {
-    // We should figure out why we get here when there is no local root
-    // (https://crbug.com/792345).
-    return;
-  }
-
-  // TODO(alexmos, kenrb): resizing behavior such as this should be changed
-  // to use Page messages.  This uses the visual viewport size to set size on
-  // both the WebViewImpl size and the Page's VisualViewport. If there are
-  // multiple OOPIFs on a page, this will currently be set redundantly by
-  // each of them. See https://crbug.com/599688.
-  View()->MainFrameWidget()->Resize(new_size);
-
-  View()->DidUpdateFullscreenSize();
-}
-
 void WebFrameWidgetImpl::UpdateMainFrameLayoutSize() {
   if (!LocalRootImpl())
     return;
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
index d332bfd..aa10db3 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.h
@@ -76,7 +76,6 @@
   void Close() override;
   WebSize Size() override;
   void Resize(const WebSize&) override;
-  void ResizeVisualViewport(const WebSize&) override;
   void DidEnterFullscreen() override;
   void DidExitFullscreen() override;
   void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) final;
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
index 1ff606f..3941e27 100644
--- a/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
+++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.cc
@@ -35,10 +35,6 @@
   web_view_->Resize(size);
 }
 
-void WebViewFrameWidget::ResizeVisualViewport(const WebSize& size) {
-  web_view_->ResizeVisualViewport(size);
-}
-
 void WebViewFrameWidget::DidEnterFullscreen() {
   web_view_->DidEnterFullscreen();
 }
diff --git a/third_party/blink/renderer/core/frame/web_view_frame_widget.h b/third_party/blink/renderer/core/frame/web_view_frame_widget.h
index 406c0ef..a61b011 100644
--- a/third_party/blink/renderer/core/frame/web_view_frame_widget.h
+++ b/third_party/blink/renderer/core/frame/web_view_frame_widget.h
@@ -44,7 +44,6 @@
   void Close() override;
   WebSize Size() override;
   void Resize(const WebSize&) override;
-  void ResizeVisualViewport(const WebSize&) override;
   void DidEnterFullscreen() override;
   void DidExitFullscreen() override;
   void SetSuppressFrameRequestsWorkaroundFor704763Only(bool) final;
diff --git a/third_party/blink/renderer/core/html/portal/html_portal_element.cc b/third_party/blink/renderer/core/html/portal/html_portal_element.cc
index d37d420..efaae88 100644
--- a/third_party/blink/renderer/core/html/portal/html_portal_element.cc
+++ b/third_party/blink/renderer/core/html/portal/html_portal_element.cc
@@ -389,6 +389,11 @@
   return new LayoutIFrame(this);
 }
 
+void HTMLPortalElement::DisconnectContentFrame() {
+  HTMLFrameOwnerElement::DisconnectContentFrame();
+  ConsumePortal();
+}
+
 void HTMLPortalElement::AttachLayoutTree(AttachContext& context) {
   HTMLFrameOwnerElement::AttachLayoutTree(context);
 
diff --git a/third_party/blink/renderer/core/html/portal/html_portal_element.h b/third_party/blink/renderer/core/html/portal/html_portal_element.h
index 799ee1ec..f5de9c1 100644
--- a/third_party/blink/renderer/core/html/portal/html_portal_element.h
+++ b/third_party/blink/renderer/core/html/portal/html_portal_element.h
@@ -93,6 +93,7 @@
   LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override;
 
   // HTMLFrameOwnerElement overrides
+  void DisconnectContentFrame() override;
   ParsedFeaturePolicy ConstructContainerPolicy(Vector<String>*) const override {
     return ParsedFeaturePolicy();
   }
diff --git a/third_party/blink/renderer/core/inspector/browser_protocol.pdl b/third_party/blink/renderer/core/inspector/browser_protocol.pdl
index 70b2efbc..5e5d839 100644
--- a/third_party/blink/renderer/core/inspector/browser_protocol.pdl
+++ b/third_party/blink/renderer/core/inspector/browser_protocol.pdl
@@ -6978,3 +6978,10 @@
   command clearCredentials
     parameters
       AuthenticatorId authenticatorId
+
+  # Sets whether User Verification succeeds or fails for an authenticator.
+  # The default is true.
+  command setUserVerified
+    parameters
+      AuthenticatorId authenticatorId
+      boolean isUserVerified
diff --git a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
index 46561b3..9bdc8c0 100644
--- a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
@@ -51,6 +51,11 @@
 
 namespace {
 
+void* AsyncId(uint64_t identifier) {
+  // This value should be odd to avoid collisions with regular pointers.
+  return reinterpret_cast<void*>((identifier << 1) | 1);
+}
+
 std::unique_ptr<TracedValue> InspectorParseHtmlBeginData(Document* document,
                                                          unsigned start_line) {
   auto value = std::make_unique<TracedValue>();
@@ -145,6 +150,8 @@
                        TRACE_EVENT_SCOPE_THREAD, "data",
                        inspector_receive_data_event::Data(
                            loader, identifier, frame, encoded_data_length));
+  probe::AsyncTask async_task(frame ? frame->GetDocument() : nullptr,
+                              AsyncId(identifier), "data");
 }
 
 void InspectorTraceEvents::DidFinishLoading(uint64_t identifier,
@@ -153,11 +160,14 @@
                                             int64_t encoded_data_length,
                                             int64_t decoded_body_length,
                                             bool should_report_corb_blocking) {
+  LocalFrame* frame = loader ? loader->GetFrame() : nullptr;
   TRACE_EVENT_INSTANT1(
       "devtools.timeline", "ResourceFinish", TRACE_EVENT_SCOPE_THREAD, "data",
       inspector_resource_finish_event::Data(loader, identifier, finish_time,
                                             false, encoded_data_length,
                                             decoded_body_length));
+  probe::AsyncTask async_task(frame ? frame->GetDocument() : nullptr,
+                              AsyncId(identifier));
 }
 
 void InspectorTraceEvents::DidFailLoading(uint64_t identifier,
@@ -707,19 +717,6 @@
   return value;
 }
 
-std::unique_ptr<TracedValue> inspector_paint_invalidation_tracking_event::Data(
-    const LayoutObject& layout_object) {
-  auto value = std::make_unique<TracedValue>();
-  value->SetString("frame",
-                   IdentifiersFactory::FrameId(layout_object.GetFrame()));
-  const auto* paint_container =
-      layout_object.IsRooted() ? &layout_object.ContainerForPaintInvalidation()
-                               : nullptr;
-  SetGeneratingNodeInfo(value.get(), paint_container, "paintId");
-  SetGeneratingNodeInfo(value.get(), &layout_object, "nodeId", "nodeName");
-  return value;
-}
-
 std::unique_ptr<TracedValue> inspector_change_resource_priority_event::Data(
     DocumentLoader* loader,
     uint64_t identifier,
@@ -999,35 +996,6 @@
   quad->SetP4(LocalCoordToFloatPoint(view, absolute.P4()));
 }
 
-const char inspector_layer_invalidation_tracking_event::
-    kSquashingLayerGeometryWasUpdated[] =
-        "Squashing layer geometry was updated";
-const char
-    inspector_layer_invalidation_tracking_event::kAddedToSquashingLayer[] =
-        "The layer may have been added to an already-existing squashing layer";
-const char
-    inspector_layer_invalidation_tracking_event::kRemovedFromSquashingLayer[] =
-        "Removed the layer from a squashing layer";
-const char
-    inspector_layer_invalidation_tracking_event::kReflectionLayerChanged[] =
-        "Reflection layer change";
-const char inspector_layer_invalidation_tracking_event::kNewCompositedLayer[] =
-    "Assigned a new composited layer";
-
-std::unique_ptr<TracedValue> inspector_layer_invalidation_tracking_event::Data(
-    const PaintLayer* layer,
-    const char* reason) {
-  const LayoutObject& paint_invalidation_container =
-      layer->GetLayoutObject().ContainerForPaintInvalidation();
-
-  auto value = std::make_unique<TracedValue>();
-  value->SetString("frame", IdentifiersFactory::FrameId(
-                                paint_invalidation_container.GetFrame()));
-  SetGeneratingNodeInfo(value.get(), &paint_invalidation_container, "paintId");
-  value->SetString("reason", reason);
-  return value;
-}
-
 std::unique_ptr<TracedValue> inspector_paint_event::Data(
     LayoutObject* layout_object,
     const PhysicalRect& clip_rect,
diff --git a/third_party/blink/renderer/core/inspector/inspector_trace_events.h b/third_party/blink/renderer/core/inspector/inspector_trace_events.h
index a3ba589..938ed14 100644
--- a/third_party/blink/renderer/core/inspector/inspector_trace_events.h
+++ b/third_party/blink/renderer/core/inspector/inspector_trace_events.h
@@ -60,7 +60,6 @@
 class LocalFrame;
 class LocalFrameView;
 class Node;
-class PaintLayer;
 struct PhysicalRect;
 class QualifiedName;
 class Resource;
@@ -261,10 +260,6 @@
 Data(const LayoutObject*, LayoutInvalidationReasonForTracing);
 }
 
-namespace inspector_paint_invalidation_tracking_event {
-std::unique_ptr<TracedValue> Data(const LayoutObject&);
-}
-
 namespace inspector_change_resource_priority_event {
 std::unique_ptr<TracedValue> Data(DocumentLoader*,
                                   uint64_t identifier,
@@ -355,22 +350,6 @@
 std::unique_ptr<TracedValue> Data(ExecutionContext*, XMLHttpRequest*);
 }
 
-namespace inspector_layer_invalidation_tracking_event {
-extern const char kSquashingLayerGeometryWasUpdated[];
-extern const char kAddedToSquashingLayer[];
-extern const char kRemovedFromSquashingLayer[];
-extern const char kReflectionLayerChanged[];
-extern const char kNewCompositedLayer[];
-
-std::unique_ptr<TracedValue> Data(const PaintLayer*, const char* reason);
-}  // namespace inspector_layer_invalidation_tracking_event
-
-#define TRACE_LAYER_INVALIDATION(LAYER, REASON)                            \
-  TRACE_EVENT_INSTANT1(                                                    \
-      TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking"), \
-      "LayerInvalidationTracking", TRACE_EVENT_SCOPE_THREAD, "data",       \
-      inspector_layer_invalidation_tracking_event::Data((LAYER), (REASON)));
-
 namespace inspector_paint_event {
 std::unique_ptr<TracedValue> Data(LayoutObject*,
                                   const PhysicalRect& clip_rect,
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow_line.cc b/third_party/blink/renderer/core/layout/layout_block_flow_line.cc
index ffcf7628..8b719f5 100644
--- a/third_party/blink/renderer/core/layout/layout_block_flow_line.cc
+++ b/third_party/blink/renderer/core/layout/layout_block_flow_line.cc
@@ -2196,15 +2196,25 @@
                                            BidiStatus& clean_line_bidi_status) {
   DCHECK(!layout_state.EndLine());
   RootInlineBox* last = nullptr;
+  bool previous_was_clean = false;
   for (RootInlineBox* curr = start_line->NextRootBox(); curr;
        curr = curr->NextRootBox()) {
     if (!curr->IsDirty() && LineBoxHasBRWithClearance(curr))
       return;
 
-    if (curr->IsDirty())
+    // A line is considered clean when it's not marked dirty, AND it either
+    // doesn't contain floats, or follows another clean line. The legacy line
+    // layout engine has issues with handling floats at line boundaries,
+    // potentially resulting in a float belonging to two different lines,
+    // causing all kinds of misery.
+    if (curr->IsDirty() || (curr->FloatsPtr() && !previous_was_clean)) {
       last = nullptr;
-    else if (!last)
-      last = curr;
+      previous_was_clean = false;
+    } else {
+      if (!last)
+        last = curr;
+      previous_was_clean = true;
+    }
   }
 
   if (!last)
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index d3d6562..a0dab7e 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -3948,7 +3948,7 @@
   // If we're locked, mark our descendants as needing this change. This is used
   // a signal to ensure we mark the element as needing effective allowed
   // touch action recalculation when the element becomes unlocked.
-  if (PrePaintBlockedByDisplayLock()) {
+  if (PrePaintBlockedByDisplayLock(DisplayLockContext::kChildren)) {
     bitfields_.SetDescendantEffectiveAllowedTouchActionChanged(true);
     return;
   }
@@ -3956,7 +3956,7 @@
   LayoutObject* obj = ParentCrossingFrames();
   while (obj && !obj->DescendantEffectiveAllowedTouchActionChanged()) {
     obj->bitfields_.SetDescendantEffectiveAllowedTouchActionChanged(true);
-    if (obj->PrePaintBlockedByDisplayLock())
+    if (obj->PrePaintBlockedByDisplayLock(DisplayLockContext::kChildren))
       break;
 
     obj = obj->ParentCrossingFrames();
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index 608aa39..e89c2eb 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -420,7 +420,8 @@
   }
 
   void AssertClearedPaintInvalidationFlags() const {
-    if (PaintInvalidationStateIsDirty() && !PrePaintBlockedByDisplayLock()) {
+    if (PaintInvalidationStateIsDirty() &&
+        !PrePaintBlockedByDisplayLock(DisplayLockContext::kChildren)) {
       ShowLayoutTreeForThis();
       NOTREACHED();
     }
@@ -428,7 +429,8 @@
 
   void AssertSubtreeClearedPaintInvalidationFlags() const {
     for (const LayoutObject* layout_object = this; layout_object;
-         layout_object = layout_object->PrePaintBlockedByDisplayLock()
+         layout_object = layout_object->PrePaintBlockedByDisplayLock(
+                             DisplayLockContext::kChildren)
                              ? layout_object->NextInPreOrderAfterChildren()
                              : layout_object->NextInPreOrder()) {
       layout_object->AssertClearedPaintInvalidationFlags();
@@ -2185,11 +2187,15 @@
                 DocumentLifecycle::kInPrePaint);
       layout_object_.ClearPaintInvalidationFlags();
       layout_object_.bitfields_.SetNeedsPaintPropertyUpdate(false);
-      layout_object_.bitfields_.ResetSubtreePaintPropertyUpdateReasons();
-      layout_object_.bitfields_.SetDescendantNeedsPaintPropertyUpdate(false);
       layout_object_.bitfields_.SetEffectiveAllowedTouchActionChanged(false);
-      layout_object_.bitfields_.SetDescendantEffectiveAllowedTouchActionChanged(
-          false);
+
+      if (!layout_object_.PrePaintBlockedByDisplayLock(
+              DisplayLockContext::kChildren)) {
+        layout_object_.bitfields_.SetDescendantNeedsPaintPropertyUpdate(false);
+        layout_object_.bitfields_
+            .SetDescendantEffectiveAllowedTouchActionChanged(false);
+        layout_object_.bitfields_.ResetSubtreePaintPropertyUpdateReasons();
+      }
     }
     void SetShouldCheckForPaintInvalidation() {
       layout_object_.SetShouldCheckForPaintInvalidation();
@@ -2391,9 +2397,10 @@
     return context && context->IsLocked();
   }
 
-  bool PrePaintBlockedByDisplayLock() const {
+  bool PrePaintBlockedByDisplayLock(
+      DisplayLockContext::LifecycleTarget target) const {
     auto* context = GetDisplayLockContext();
-    return context && !context->ShouldPrePaint();
+    return context && !context->ShouldPrePaint(target);
   }
 
   bool PaintBlockedByDisplayLock() const {
@@ -2401,9 +2408,10 @@
     return context && !context->ShouldPaint();
   }
 
-  void NotifyDisplayLockDidPrePaint() const {
+  void NotifyDisplayLockDidPrePaint(
+      DisplayLockContext::LifecycleTarget target) const {
     if (auto* context = GetDisplayLockContext())
-      context->DidPrePaint();
+      context->DidPrePaint(target);
   }
 
   void NotifyDisplayLockDidPaint() const {
@@ -2568,7 +2576,10 @@
 #endif
 
   // Called before paint invalidation.
-  virtual void EnsureIsReadyForPaintInvalidation() { DCHECK(!NeedsLayout()); }
+  virtual void EnsureIsReadyForPaintInvalidation() {
+    DCHECK(!NeedsLayout() ||
+           LayoutBlockedByDisplayLock(DisplayLockContext::kChildren));
+  }
 
   void SetIsBackgroundAttachmentFixedObject(bool);
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h
index 53be162..d282938 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment.h
@@ -61,13 +61,6 @@
   TextDirection direction_;
 };
 
-template <>
-struct DowncastTraits<NGBoxFragment> {
-  static bool AllowFrom(const NGFragment& fragment) {
-    return fragment.Type() == NGPhysicalFragment::kFragmentBox;
-  }
-};
-
 }  // namespace blink
 
 #endif  // NGBoxFragment_h
diff --git a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
index 43a50cd1c..0c8bacd4 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
@@ -202,7 +202,7 @@
 }
 
 NGContainerFragmentBuilder& NGContainerFragmentBuilder::AddOutOfFlowDescendant(
-    NGOutOfFlowPositionedDescendant descendant) {
+    const NGOutOfFlowPositionedDescendant& descendant) {
   oof_positioned_descendants_.push_back(descendant);
   return *this;
 }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h
index 9b84c4e..e84c879 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h
@@ -136,7 +136,7 @@
       base::Optional<TextDirection> container_direction = base::nullopt);
 
   NGContainerFragmentBuilder& AddOutOfFlowDescendant(
-      NGOutOfFlowPositionedDescendant descendant);
+      const NGOutOfFlowPositionedDescendant& descendant);
 
   void GetAndClearOutOfFlowDescendantCandidates(
       Vector<NGOutOfFlowPositionedDescendant>* descendant_candidates,
@@ -217,8 +217,9 @@
     NGOutOfFlowPositionedDescendant descendant;
     LogicalOffset child_offset;  // Logical offset of child's top left vertex.
 
-    NGOutOfFlowPositionedCandidate(NGOutOfFlowPositionedDescendant descendant,
-                                   LogicalOffset child_offset)
+    NGOutOfFlowPositionedCandidate(
+        const NGOutOfFlowPositionedDescendant& descendant,
+        LogicalOffset child_offset)
         : descendant(descendant), child_offset(child_offset) {}
   };
 
diff --git a/third_party/blink/renderer/core/loader/image_loader.cc b/third_party/blink/renderer/core/loader/image_loader.cc
index a01337cf..7c248a84 100644
--- a/third_party/blink/renderer/core/loader/image_loader.cc
+++ b/third_party/blink/renderer/core/loader/image_loader.cc
@@ -51,7 +51,6 @@
 #include "third_party/blink/renderer/core/layout/layout_video.h"
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_image.h"
 #include "third_party/blink/renderer/core/loader/importance_attribute.h"
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/core/probe/core_probes.h"
 #include "third_party/blink/renderer/core/svg/graphics/svg_image.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
@@ -195,7 +194,7 @@
         request_url_(request_url),
         weak_factory_(this) {
     ExecutionContext& context = loader_->GetElement()->GetDocument();
-    probe::AsyncTaskScheduled(&context, "Image", &async_task_id_);
+    probe::AsyncTaskScheduled(&context, "Image", this);
     v8::Isolate* isolate = V8PerIsolateData::MainThreadIsolate();
     v8::HandleScope scope(isolate);
     // If we're invoked from C++ without a V8 context on the stack, we should
@@ -213,7 +212,7 @@
     if (!loader_)
       return;
     ExecutionContext& context = loader_->GetElement()->GetDocument();
-    probe::AsyncTask async_task(&context, &async_task_id_);
+    probe::AsyncTask async_task(&context, this);
     if (script_state_ && script_state_->ContextIsValid()) {
       ScriptState::Scope scope(script_state_);
       loader_->DoUpdateFromElement(should_bypass_main_world_csp_,
@@ -241,7 +240,6 @@
   WeakPersistent<ScriptState> script_state_;
   network::mojom::ReferrerPolicy referrer_policy_;
   KURL request_url_;
-  probe::AsyncTaskId async_task_id_;
   base::WeakPtrFactory<Task> weak_factory_;
 };
 
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
index fbbc2eb..d2baa952 100644
--- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
+++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
@@ -1118,10 +1118,6 @@
         layers[i].offset_from_layout_object != new_offset_from_layout_object) {
       ObjectPaintInvalidator(layers[i].paint_layer->GetLayoutObject())
           .InvalidatePaintIncludingNonCompositingDescendants();
-
-      TRACE_LAYER_INVALIDATION(layers[i].paint_layer,
-                               inspector_layer_invalidation_tracking_event::
-                                   kSquashingLayerGeometryWasUpdated);
       layers_needing_paint_invalidation.push_back(layers[i].paint_layer);
     }
     layers[i].offset_from_layout_object = new_offset_from_layout_object;
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc b/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc
index f936e11..0714fb3 100644
--- a/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc
+++ b/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc
@@ -28,7 +28,6 @@
 
 #include "third_party/blink/renderer/core/animation/scroll_timeline.h"
 #include "third_party/blink/renderer/core/animation/worklet_animation_controller.h"
-#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/page/page.h"
 #include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"
@@ -252,9 +251,6 @@
 
     // Issue a paint invalidation, since |layer| may have been added to an
     // already-existing squashing layer.
-    TRACE_LAYER_INVALIDATION(
-        layer,
-        inspector_layer_invalidation_tracking_event::kAddedToSquashingLayer);
     layers_needing_paint_invalidation.push_back(layer);
     layers_changed_ = true;
   } else if (composited_layer_update == kRemoveFromSquashingLayer) {
@@ -270,9 +266,6 @@
 
     // If we need to issue paint invalidations, do so now that we've removed it
     // from a squashed layer.
-    TRACE_LAYER_INVALIDATION(layer,
-                             inspector_layer_invalidation_tracking_event::
-                                 kRemovedFromSquashingLayer);
     layers_needing_paint_invalidation.push_back(layer);
     layers_changed_ = true;
 
@@ -303,9 +296,6 @@
 
     if (compositor_->AllocateOrClearCompositedLayerMapping(
             layer, composited_layer_update)) {
-      TRACE_LAYER_INVALIDATION(
-          layer,
-          inspector_layer_invalidation_tracking_event::kNewCompositedLayer);
       layers_needing_paint_invalidation.push_back(layer);
       layers_changed_ = true;
       if (ScrollingCoordinator* scrolling_coordinator =
diff --git a/third_party/blink/renderer/core/paint/compositing/graphics_layer_updater.cc b/third_party/blink/renderer/core/paint/compositing/graphics_layer_updater.cc
index 2537338f..330c0c9 100644
--- a/third_party/blink/renderer/core/paint/compositing/graphics_layer_updater.cc
+++ b/third_party/blink/renderer/core/paint/compositing/graphics_layer_updater.cc
@@ -27,7 +27,6 @@
 #include "third_party/blink/renderer/core/paint/compositing/graphics_layer_updater.h"
 
 #include "third_party/blink/renderer/core/html/media/html_media_element.h"
-#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
 #include "third_party/blink/renderer/core/layout/layout_block.h"
 #include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
 #include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
diff --git a/third_party/blink/renderer/core/paint/object_paint_invalidator.cc b/third_party/blink/renderer/core/paint/object_paint_invalidator.cc
index 777fbb5..476685c 100644
--- a/third_party/blink/renderer/core/paint/object_paint_invalidator.cc
+++ b/third_party/blink/renderer/core/paint/object_paint_invalidator.cc
@@ -172,18 +172,6 @@
   Helper::Traverse(object_);
 }
 
-namespace {
-bool IsClientNGPaintFragmentForObject(const DisplayItemClient& client,
-                                      const LayoutObject& object) {
-  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
-    return false;
-  // TODO(crbug.com/880519): This hack only makes current invalidation tracking
-  // web tests pass with LayoutNG. More work is needed if we want to launch
-  // the invalidation tracking feature.
-  return &client == object.PaintFragment();
-}
-}  // namespace
-
 void ObjectPaintInvalidator::InvalidateDisplayItemClient(
     const DisplayItemClient& client,
     PaintInvalidationReason reason) {
@@ -193,14 +181,6 @@
   // reduce the cost.
   DCHECK(!object_.PaintingLayer() || object_.PaintingLayer()->NeedsRepaint());
 
-  if (&client == &object_ ||
-      IsClientNGPaintFragmentForObject(client, object_)) {
-    TRACE_EVENT_INSTANT1(
-        TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking"),
-        "PaintInvalidationTracking", TRACE_EVENT_SCOPE_THREAD, "data",
-        inspector_paint_invalidation_tracking_event::Data(object_));
-  }
-
   client.Invalidate(reason);
 
   if (LocalFrameView* frame_view = object_.GetFrameView())
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
index 119d760..0417c27 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -2842,10 +2842,17 @@
                : WebFeature::kScrollbarUseHorizontalScrollbarButton);
       break;
     case kThumbPart:
-      scrollbar_use_uma =
-          (orientation == kVerticalScrollbar
-               ? WebFeature::kScrollbarUseVerticalScrollbarThumb
-               : WebFeature::kScrollbarUseHorizontalScrollbarThumb);
+      if (orientation == kVerticalScrollbar) {
+        scrollbar_use_uma =
+            (WebInputEvent::IsMouseEventType(type)
+                 ? WebFeature::kVerticalScrollbarThumbScrollingWithMouse
+                 : WebFeature::kVerticalScrollbarThumbScrollingWithTouch);
+      } else {
+        scrollbar_use_uma =
+            (WebInputEvent::IsMouseEventType(type)
+                 ? WebFeature::kHorizontalScrollbarThumbScrollingWithMouse
+                 : WebFeature::kHorizontalScrollbarThumbScrollingWithTouch);
+      }
       break;
     case kBackTrackPart:
     case kForwardTrackPart:
@@ -2860,24 +2867,7 @@
 
   Document& document = GetLayoutBox()->GetDocument();
 
-  // TODO(alpastew): Remove the UseCounters kScrollbarUseVerticalScrollbarThumb
-  // and kScrollbarUseHorizontalScrollbarThumb to avoid redundancy in metrics.
   UseCounter::Count(document, scrollbar_use_uma);
-
-  if (scrollbar_use_uma == WebFeature::kScrollbarUseVerticalScrollbarThumb) {
-    WebFeature input_specific_uma =
-        (WebInputEvent::IsMouseEventType(type)
-             ? WebFeature::kVerticalScrollbarThumbScrollingWithMouse
-             : WebFeature::kVerticalScrollbarThumbScrollingWithTouch);
-    UseCounter::Count(document, input_specific_uma);
-  } else if (scrollbar_use_uma ==
-             WebFeature::kScrollbarUseHorizontalScrollbarThumb) {
-    WebFeature input_specific_uma =
-        (WebInputEvent::IsMouseEventType(type)
-             ? WebFeature::kHorizontalScrollbarThumbScrollingWithMouse
-             : WebFeature::kHorizontalScrollbarThumbScrollingWithTouch);
-    UseCounter::Count(document, input_specific_uma);
-  }
 }
 
 CompositorElementId PaintLayerScrollableArea::GetCompositorElementId() const {
diff --git a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
index 884717d0..0fcfc3b 100644
--- a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
+++ b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
@@ -274,8 +274,9 @@
 bool PrePaintTreeWalk::ObjectRequiresTreeBuilderContext(
     const LayoutObject& object) {
   return object.NeedsPaintPropertyUpdate() ||
-         object.DescendantNeedsPaintPropertyUpdate() ||
-         object.DescendantNeedsPaintOffsetAndVisualRectUpdate();
+         (!object.PrePaintBlockedByDisplayLock(DisplayLockContext::kChildren) &&
+          (object.DescendantNeedsPaintPropertyUpdate() ||
+           object.DescendantNeedsPaintOffsetAndVisualRectUpdate()));
 }
 
 bool PrePaintTreeWalk::ContextRequiresTreeBuilderContext(
@@ -405,24 +406,6 @@
       ContextRequiresTreeBuilderContext(parent_context(), object) ||
       ObjectRequiresTreeBuilderContext(object);
 
-  if (object.PrePaintBlockedByDisplayLock()) {
-    // If we need a subtree walk due to context flags, we need to store that
-    // information on the display lock, since subsequent walks might not set the
-    // same bits on the parent context.
-    if (ContextRequiresTreeBuilderContext(parent_context(), object) ||
-        ContextRequiresPrePaint(parent_context())) {
-      // Note that effective allowed touch action changed is special in that
-      // it requires us to specifically recalculate this value on each subtree
-      // element. Other flags simply need a subtree walk. Some consideration
-      // needs to be given to |clip_changed| which ensures that we repaint every
-      // layer, but for the purposes of PrePaint, this flag is just forcing a
-      // subtree walk.
-      object.GetDisplayLockContext()->SetNeedsPrePaintSubtreeWalk(
-          parent_context().effective_allowed_touch_action_changed);
-    }
-    return;
-  }
-
   // The following is for debugging crbug.com/974639.
   CheckTreeBuilderContextState(object, parent_context());
 
@@ -432,11 +415,6 @@
     return;
   }
 
-  // TODO(vmpstr): Technically we should do this after prepaint finishes, but
-  // due to a possible early out this is more convenient. We should change this
-  // to RAII.
-  object.NotifyDisplayLockDidPrePaint();
-
   // Note that because we're emplacing an object constructed from
   // parent_context() (which is a reference to the vector itself), it's
   // important to first ensure that there's sufficient capacity in the vector.
@@ -459,31 +437,54 @@
   }
 
   WalkInternal(object, context());
+  object.NotifyDisplayLockDidPrePaint(DisplayLockContext::kSelf);
 
-  for (const LayoutObject* child = object.SlowFirstChild(); child;
-       child = child->NextSibling()) {
-    if (child->IsLayoutMultiColumnSpannerPlaceholder()) {
-      child->GetMutableForPainting().ClearPaintFlags();
-      continue;
-    }
-    Walk(*child);
+  bool child_walk_blocked =
+      object.PrePaintBlockedByDisplayLock(DisplayLockContext::kChildren);
+  // If we need a subtree walk due to context flags, we need to store that
+  // information on the display lock, since subsequent walks might not set the
+  // same bits on the context.
+  if (child_walk_blocked &&
+      (ContextRequiresTreeBuilderContext(context(), object) ||
+       ContextRequiresPrePaint(context()))) {
+    // Note that effective allowed touch action changed is special in that
+    // it requires us to specifically recalculate this value on each subtree
+    // element. Other flags simply need a subtree walk. Some consideration
+    // needs to be given to |clip_changed| which ensures that we repaint every
+    // layer, but for the purposes of PrePaint, this flag is just forcing a
+    // subtree walk.
+    object.GetDisplayLockContext()->SetNeedsPrePaintSubtreeWalk(
+        context().effective_allowed_touch_action_changed);
   }
 
-  if (object.IsLayoutEmbeddedContent()) {
-    const LayoutEmbeddedContent& layout_embedded_content =
-        ToLayoutEmbeddedContent(object);
-    FrameView* frame_view = layout_embedded_content.ChildFrameView();
-    if (auto* local_frame_view = DynamicTo<LocalFrameView>(frame_view)) {
-      if (context().tree_builder_context) {
-        auto& offset =
-            context().tree_builder_context->fragments[0].current.paint_offset;
-        offset += layout_embedded_content.ReplacedContentRect().offset;
-        offset -= PhysicalOffset(local_frame_view->FrameRect().Location());
-        offset = PhysicalOffset(RoundedIntPoint(offset));
+  if (!child_walk_blocked) {
+    for (const LayoutObject* child = object.SlowFirstChild(); child;
+         child = child->NextSibling()) {
+      if (child->IsLayoutMultiColumnSpannerPlaceholder()) {
+        child->GetMutableForPainting().ClearPaintFlags();
+        continue;
       }
-      Walk(*local_frame_view);
+      Walk(*child);
     }
-    // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281).
+
+    if (object.IsLayoutEmbeddedContent()) {
+      const LayoutEmbeddedContent& layout_embedded_content =
+          ToLayoutEmbeddedContent(object);
+      FrameView* frame_view = layout_embedded_content.ChildFrameView();
+      if (auto* local_frame_view = DynamicTo<LocalFrameView>(frame_view)) {
+        if (context().tree_builder_context) {
+          auto& offset =
+              context().tree_builder_context->fragments[0].current.paint_offset;
+          offset += layout_embedded_content.ReplacedContentRect().offset;
+          offset -= PhysicalOffset(local_frame_view->FrameRect().Location());
+          offset = PhysicalOffset(RoundedIntPoint(offset));
+        }
+        Walk(*local_frame_view);
+      }
+      // TODO(pdr): Investigate RemoteFrameView (crbug.com/579281).
+    }
+
+    object.NotifyDisplayLockDidPrePaint(DisplayLockContext::kChildren);
   }
 
   object.GetMutableForPainting().ClearPaintFlags();
diff --git a/third_party/blink/renderer/core/probe/BUILD.gn b/third_party/blink/renderer/core/probe/BUILD.gn
index 93ef592..c439b5d9 100644
--- a/third_party/blink/renderer/core/probe/BUILD.gn
+++ b/third_party/blink/renderer/core/probe/BUILD.gn
@@ -39,7 +39,6 @@
 # Compiles the sources generated above.
 blink_core_sources("probe") {
   sources = [
-    "async_task_id.h",
     "core_probes.cc",
     "core_probes.h",
   ]
diff --git a/third_party/blink/renderer/core/probe/async_task_id.h b/third_party/blink/renderer/core/probe/async_task_id.h
deleted file mode 100644
index eeba800..0000000
--- a/third_party/blink/renderer/core/probe/async_task_id.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PROBE_ASYNC_TASK_ID_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PROBE_ASYNC_TASK_ID_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-
-namespace blink {
-
-namespace probe {
-
-// The core probes use this class as an identifier for an async task.
-class CORE_EXPORT AsyncTaskId {
- public:
-  void SetAdTask() { ad_task_ = true; }
-  bool IsAdTask() const { return ad_task_; }
-
- private:
-  bool ad_task_ = false;
-};
-
-}  // namespace probe
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PROBE_ASYNC_TASK_ID_H_
diff --git a/third_party/blink/renderer/core/probe/core_probes.cc b/third_party/blink/renderer/core/probe/core_probes.cc
index a2a779c..f0277aa 100644
--- a/third_party/blink/renderer/core/probe/core_probes.cc
+++ b/third_party/blink/renderer/core/probe/core_probes.cc
@@ -31,30 +31,20 @@
 #include "third_party/blink/renderer/core/probe/core_probes.h"
 
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
-#include "third_party/blink/renderer/core/core_probes_inl.h"
 #include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
 #include "third_party/blink/renderer/core/inspector/thread_debugger.h"
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
 
 namespace blink {
 namespace probe {
 
 namespace {
-void* AsyncId(AsyncTaskId* task) {
+void* AsyncId(void* task) {
   // Blink uses odd ids for network requests and even ids for everything else.
   // We should make all of them even before reporting to V8 to avoid collisions
   // with internal V8 async events.
   return reinterpret_cast<void*>(reinterpret_cast<intptr_t>(task) << 1);
 }
-
-void AsyncTaskCanceled(v8::Isolate* isolate, AsyncTaskId* task) {
-  if (ThreadDebugger* debugger = ThreadDebugger::From(isolate))
-    debugger->AsyncTaskCanceled(AsyncId(task));
-  TRACE_EVENT_FLOW_END0("devtools.timeline.async", "AsyncTask",
-                        TRACE_ID_LOCAL(reinterpret_cast<uintptr_t>(task)));
-}
-
 }  // namespace
 
 TimeTicks ProbeBase::CaptureStartTime() const {
@@ -75,14 +65,13 @@
 }
 
 AsyncTask::AsyncTask(ExecutionContext* context,
-                     AsyncTaskId* task,
+                     void* task,
                      const char* step,
                      bool enabled)
     : debugger_(enabled && context ? ThreadDebugger::From(context->GetIsolate())
                                    : nullptr),
-      task_(task),
-      recurring_(step),
-      ad_tracker_(AdTracker::FromExecutionContext(context)) {
+      task_(AsyncId(task)),
+      recurring_(step) {
   if (recurring_) {
     TRACE_EVENT_FLOW_STEP0("devtools.timeline.async", "AsyncTask",
                            TRACE_ID_LOCAL(reinterpret_cast<uintptr_t>(task)),
@@ -92,54 +81,50 @@
                           TRACE_ID_LOCAL(reinterpret_cast<uintptr_t>(task)));
   }
   if (debugger_)
-    debugger_->AsyncTaskStarted(AsyncId(task_));
-
-  if (ad_tracker_)
-    ad_tracker_->DidStartAsyncTask(task_);
+    debugger_->AsyncTaskStarted(task_);
 }
 
 AsyncTask::~AsyncTask() {
   if (debugger_) {
-    debugger_->AsyncTaskFinished(AsyncId(task_));
+    debugger_->AsyncTaskFinished(task_);
     if (!recurring_)
-      debugger_->AsyncTaskCanceled(AsyncId(task_));
+      debugger_->AsyncTaskCanceled(task_);
   }
-
-  if (ad_tracker_)
-    ad_tracker_->DidFinishAsyncTask(task_);
 }
 
 void AsyncTaskScheduled(ExecutionContext* context,
                         const StringView& name,
-                        AsyncTaskId* task) {
+                        void* task) {
   TRACE_EVENT_FLOW_BEGIN1("devtools.timeline.async", "AsyncTask",
                           TRACE_ID_LOCAL(reinterpret_cast<uintptr_t>(task)),
                           "data", inspector_async_task::Data(name));
-  if (!context)
-    return;
-
-  if (ThreadDebugger* debugger = ThreadDebugger::From(context->GetIsolate()))
-    debugger->AsyncTaskScheduled(name, AsyncId(task), true);
-
-  blink::AdTracker* ad_tracker = AdTracker::FromExecutionContext(context);
-  if (ad_tracker)
-    ad_tracker->DidCreateAsyncTask(task);
+  if (context) {
+    if (ThreadDebugger* debugger = ThreadDebugger::From(context->GetIsolate()))
+      debugger->AsyncTaskScheduled(name, AsyncId(task), true);
+  }
 }
 
 void AsyncTaskScheduledBreakable(ExecutionContext* context,
                                  const char* name,
-                                 AsyncTaskId* task) {
+                                 void* task) {
   AsyncTaskScheduled(context, name, task);
   BreakableLocation(context, name);
 }
 
-void AsyncTaskCanceled(ExecutionContext* context, AsyncTaskId* task) {
+void AsyncTaskCanceled(ExecutionContext* context, void* task) {
   AsyncTaskCanceled(context ? context->GetIsolate() : nullptr, task);
 }
 
+void AsyncTaskCanceled(v8::Isolate* isolate, void* task) {
+  if (ThreadDebugger* debugger = ThreadDebugger::From(isolate))
+    debugger->AsyncTaskCanceled(AsyncId(task));
+  TRACE_EVENT_FLOW_END0("devtools.timeline.async", "AsyncTask",
+                        TRACE_ID_LOCAL(reinterpret_cast<uintptr_t>(task)));
+}
+
 void AsyncTaskCanceledBreakable(ExecutionContext* context,
                                 const char* name,
-                                AsyncTaskId* task) {
+                                void* task) {
   AsyncTaskCanceled(context, task);
   BreakableLocation(context, name);
 }
diff --git a/third_party/blink/renderer/core/probe/core_probes.h b/third_party/blink/renderer/core/probe/core_probes.h
index 71c77ef0..fd04373 100644
--- a/third_party/blink/renderer/core/probe/core_probes.h
+++ b/third_party/blink/renderer/core/probe/core_probes.h
@@ -33,7 +33,6 @@
 
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/frame/ad_tracker.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource.h"
 
@@ -53,8 +52,6 @@
 
 namespace probe {
 
-class AsyncTaskId;
-
 class CORE_EXPORT ProbeBase {
   STACK_ALLOCATED();
 
@@ -73,18 +70,15 @@
 
  public:
   AsyncTask(ExecutionContext*,
-            AsyncTaskId* task,
+            void* task,
             const char* step = nullptr,
             bool enabled = true);
   ~AsyncTask();
 
  private:
   ThreadDebugger* debugger_;
-  AsyncTaskId* task_;
+  void* task_;
   bool recurring_;
-
-  // This persistent is safe since the class is STACK_ALLOCATED.
-  Persistent<AdTracker> ad_tracker_;
 };
 
 // Called from generated instrumentation code.
@@ -119,14 +113,15 @@
 
 CORE_EXPORT void AsyncTaskScheduled(ExecutionContext*,
                                     const StringView& name,
-                                    AsyncTaskId*);
+                                    void*);
 CORE_EXPORT void AsyncTaskScheduledBreakable(ExecutionContext*,
                                              const char* name,
-                                             AsyncTaskId*);
-CORE_EXPORT void AsyncTaskCanceled(ExecutionContext*, AsyncTaskId*);
+                                             void*);
+CORE_EXPORT void AsyncTaskCanceled(ExecutionContext*, void*);
+CORE_EXPORT void AsyncTaskCanceled(v8::Isolate*, void*);
 CORE_EXPORT void AsyncTaskCanceledBreakable(ExecutionContext*,
                                             const char* name,
-                                            AsyncTaskId*);
+                                            void*);
 CORE_EXPORT void AllAsyncTasksCanceled(ExecutionContext*);
 
 }  // namespace probe
diff --git a/third_party/blink/renderer/core/testing/data/frameserialization/picture.html b/third_party/blink/renderer/core/testing/data/frameserialization/picture.html
new file mode 100644
index 0000000..cf54501
--- /dev/null
+++ b/third_party/blink/renderer/core/testing/data/frameserialization/picture.html
@@ -0,0 +1,13 @@
+<html>
+<head>
+<meta charset="utf8">
+<title>Test Picture Element</title>
+</head>
+<body>
+<picture>
+  <source media="(min-width: 500px)" srcset="2x.png">
+  <source media="(min-width: 200px)" srcset="1x.png">
+  <img />
+</picture>
+</body>
+</html>
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
index 384cfa5..4579ba6 100644
--- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
+++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
@@ -1027,8 +1027,7 @@
   // Also, only async requests support upload progress events.
   bool upload_events = false;
   if (async_) {
-    probe::AsyncTaskScheduled(&execution_context, "XMLHttpRequest.send",
-                              &async_task_id_);
+    probe::AsyncTaskScheduled(&execution_context, "XMLHttpRequest.send", this);
     DispatchProgressEvent(event_type_names::kLoadstart, 0, 0);
     // Event handler could have invalidated this send operation,
     // (re)setting the send flag and/or initiating another send
@@ -1307,8 +1306,8 @@
 
   ExecutionContext* context = GetExecutionContext();
   probe::AsyncTask async_task(
-      context, &async_task_id_,
-      type == event_type_names::kLoadend ? nullptr : "progress", async_);
+      context, this, type == event_type_names::kLoadend ? nullptr : "progress",
+      async_);
   progress_event_throttle_->DispatchProgressEvent(type, length_computable,
                                                   loaded, total);
 }
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h
index ae2af2ce..a77bc7a 100644
--- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h
+++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h
@@ -31,7 +31,6 @@
 #include "third_party/blink/renderer/core/dom/document_parser_client.h"
 #include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
 #include "third_party/blink/renderer/core/loader/threadable_loader_client.h"
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/core/xmlhttprequest/xml_http_request_event_target.h"
 #include "third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.h"
 #include "third_party/blink/renderer/platform/bindings/exception_code.h"
@@ -164,8 +163,6 @@
   XMLHttpRequestUpload* upload();
   bool IsAsync() { return async_; }
 
-  probe::AsyncTaskId* async_task_id() { return &async_task_id_; }
-
   DEFINE_ATTRIBUTE_EVENT_LISTENER(readystatechange, kReadystatechange)
 
   void Trace(blink::Visitor*) override;
@@ -377,8 +374,6 @@
   bool response_text_overflow_ = false;
   bool send_flag_ = false;
   bool response_array_buffer_failure_ = false;
-
-  probe::AsyncTaskId async_task_id_;
 };
 
 std::ostream& operator<<(std::ostream&, const XMLHttpRequest*);
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.cc b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.cc
index 0cec76a..1dbea17 100644
--- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.cc
+++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.cc
@@ -131,9 +131,8 @@
     // the previously dispatched event changes the readyState (e.g. when
     // the event handler calls xhr.abort()). In such cases a
     // readystatechange should have been already dispatched if necessary.
-    probe::AsyncTask async_task(target_->GetExecutionContext(),
-                                target_->async_task_id(), "progress",
-                                target_->IsAsync());
+    probe::AsyncTask async_task(target_->GetExecutionContext(), target_,
+                                "progress", target_->IsAsync());
     target_->DispatchEvent(*event);
   }
 }
@@ -146,9 +145,8 @@
     TRACE_EVENT1("devtools.timeline", "XHRReadyStateChange", "data",
                  inspector_xhr_ready_state_change_event::Data(
                      target_->GetExecutionContext(), target_));
-    probe::AsyncTask async_task(target_->GetExecutionContext(),
-                                target_->async_task_id(), "progress",
-                                target_->IsAsync());
+    probe::AsyncTask async_task(target_->GetExecutionContext(), target_,
+                                "progress", target_->IsAsync());
     target_->DispatchEvent(*Event::Create(event_type_names::kReadystatechange));
   }
 
@@ -156,9 +154,8 @@
     return;
 
   has_dispatched_progress_progress_event_ = true;
-  probe::AsyncTask async_task(target_->GetExecutionContext(),
-                              target_->async_task_id(), "progress",
-                              target_->IsAsync());
+  probe::AsyncTask async_task(target_->GetExecutionContext(), target_,
+                              "progress", target_->IsAsync());
   target_->DispatchEvent(*progress_event);
 }
 
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_upload.cc b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_upload.cc
index 1ee0eb4..099554a 100644
--- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_upload.cc
+++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_upload.cc
@@ -51,9 +51,8 @@
     uint64_t total_bytes_to_be_sent) {
   last_bytes_sent_ = bytes_sent;
   last_total_bytes_to_be_sent_ = total_bytes_to_be_sent;
-  probe::AsyncTask async_task(GetExecutionContext(),
-                              xml_http_request_->async_task_id(), "progress",
-                              xml_http_request_->IsAsync());
+  probe::AsyncTask async_task(GetExecutionContext(), xml_http_request_,
+                              "progress", xml_http_request_->IsAsync());
   DispatchEvent(*ProgressEvent::Create(event_type_names::kProgress, true,
                                        bytes_sent, total_bytes_to_be_sent));
 }
@@ -65,8 +64,7 @@
   DCHECK(type == event_type_names::kLoad || type == event_type_names::kAbort ||
          type == event_type_names::kError ||
          type == event_type_names::kTimeout);
-  probe::AsyncTask async_task(GetExecutionContext(),
-                              xml_http_request_->async_task_id(), "event",
+  probe::AsyncTask async_task(GetExecutionContext(), xml_http_request_, "event",
                               xml_http_request_->IsAsync());
   DispatchEvent(
       *ProgressEvent::Create(type, length_computable, bytes_sent, total));
@@ -77,8 +75,7 @@
 void XMLHttpRequestUpload::HandleRequestError(const AtomicString& type) {
   bool length_computable = last_total_bytes_to_be_sent_ > 0 &&
                            last_bytes_sent_ <= last_total_bytes_to_be_sent_;
-  probe::AsyncTask async_task(GetExecutionContext(),
-                              xml_http_request_->async_task_id(), "error",
+  probe::AsyncTask async_task(GetExecutionContext(), xml_http_request_, "error",
                               xml_http_request_->IsAsync());
   DispatchEventAndLoadEnd(type, length_computable, last_bytes_sent_,
                           last_total_bytes_to_be_sent_);
diff --git a/third_party/blink/renderer/devtools/front_end/Images/mediumIcons.svg b/third_party/blink/renderer/devtools/front_end/Images/mediumIcons.svg
index ac3a45c..db69efe 100644
--- a/third_party/blink/renderer/devtools/front_end/Images/mediumIcons.svg
+++ b/third_party/blink/renderer/devtools/front_end/Images/mediumIcons.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="96" height="96"><defs><linearGradient id="a"><stop offset="0" stop-color="#d7687d"/><stop offset="1" stop-color="#b21402"/></linearGradient><linearGradient id="b"><stop offset="0" stop-color="#606eda"/><stop offset="1" stop-color="#021db2"/></linearGradient><linearGradient xlink:href="#a" id="m" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -.41667 -.41667 0 25 10)" x2="24"/><linearGradient xlink:href="#b" id="k" gradientUnits="userSpaceOnUse" gradientTransform="translate(-.714 -69.286) scale(.71429)" x1="113" y1="104" x2="127" y2="104"/></defs><path d="M3 36h10v9.008A1.99 1.99 0 0 1 11 47H5c-1.105 0-2-.9-2-1.992zm-1-2h12v1H2zm3-1h6v1H5zM29.526 38.25h-1.474v-.75c0-.414-.33-.75-.737-.75h-1.473V36c0-.414-.33-.75-.737-.75h-.737v-1.5a.743.743 0 0 0-.494-.7.494.494 0 0 0-.243-.05C19.968 33 17 36.022 17 39.75s2.968 6.75 6.631 6.75c3.663 0 6.632-3.022 6.632-6.75V39c0-.414-.33-.75-.737-.75zm-9.947 2.25c-.611 0-1.106-.503-1.106-1.125s.495-1.125 1.106-1.125c.61 0 1.105.503 1.105 1.125s-.495 1.125-1.105 1.125zm1.105-4.125c0-.622.495-1.125 1.105-1.125.611 0 1.105.503 1.105 1.125 0 .621-.494 1.125-1.105 1.125-.61 0-1.105-.504-1.105-1.125zM22.894 45c-.61 0-1.105-.503-1.105-1.125 0-.62.495-1.125 1.105-1.125.611 0 1.106.504 1.106 1.125 0 .622-.495 1.125-1.106 1.125zm.369-3.75c-.61 0-1.105-.504-1.105-1.125S22.653 39 23.263 39s1.105.504 1.105 1.125-.495 1.125-1.105 1.125zm3.684 1.5c-.61 0-1.105-.504-1.105-1.125s.495-1.125 1.105-1.125 1.105.504 1.105 1.125-.495 1.125-1.105 1.125z" fill="#212121"/><path d="M40 38c3.314 0 6-.895 6-2s-2.686-2-6-2-6 .895-6 2 2.686 2 6 2zm-6 7c0 1.105 2.686 2 6 2s6-.895 6-2v-2c0 1.105-2.686 2-6 2s-6-.895-6-2zm0-3c0 1.105 2.686 2 6 2s6-.895 6-2v-2c0 1.105-2.686 2-6 2s-6-.895-6-2zm0-3c0 1.105 2.686 2 6 2s6-.895 6-2v-2c0 1.105-2.686 2-6 2s-6-.895-6-2z"/><g fill="none"><path d="M48 32h16v16H48z"/><path d="M57 33h-5.005c-.54 0-.995.45-.995 1.007v11.986A1 1 0 0 0 51.995 47h8.01c.54 0 .995-.451.995-1.007V37l-4-4zm3.29 4H57v-3.29z" fill="#000"/></g><path d="M6.5 51.229V49h3v2.229a4.994 4.994 0 0 1 1.88 1.087l1.932-1.115 1.5 2.598-1.93 1.115a5.018 5.018 0 0 1 0 2.173l1.93 1.114-1.5 2.598-1.931-1.115A4.995 4.995 0 0 1 9.5 60.771v2.23h-3v-2.23a4.994 4.994 0 0 1-1.88-1.087L2.687 60.8l-1.5-2.598 1.93-1.114a5.018 5.018 0 0 1 0-2.173l-1.93-1.115 1.5-2.598 1.931 1.115A4.995 4.995 0 0 1 6.5 51.23zM8 58.5a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5zM18 51.999a1 1 0 0 1 .99-.999H24v3h-6v-2.001zM18 59h6v3h-5.01a.992.992 0 0 1-.99-.999V59zm0-4h6v3h-6zm7-4h5.01c.546 0 .99.443.99.999V54h-6v-3zm0 8h6v2.001a1 1 0 0 1-.99.999H25v-3zm0-4h6v3h-6z" fill="#212121"/><path d="M39.5 61a5.5 5.5 0 1 0 0-11 5.5 5.5 0 0 0 0 11zm0-2.2v-2.2h-3.3v-2.2h3.3v-2.2l3.3 3.3z"/><g transform="translate(-26 25)"><circle transform="matrix(1.2 0 0 1.2 72.4 21.2)" cx="10.5" cy="11.5" r="2.5" fill="#009802"/><path d="M78 25c-.544 0-1 .45-1 1v8c0 .54.45 1 1 1h3.031a3.533 3.533 0 0 1-.031-.5c0-.17.008-.337.031-.5H78v-8h3v3h3v1.5c.163-.023.33 0 .5 0 .17 0 .337-.023.5 0V28l-3-3zm4 1l2 2h-2z"/></g><path d="M8 66H3.997a1 1 0 0 0-.997.995v8.01c0 .54.446.995.997.995h6.006a1 1 0 0 0 .997-.995V69l-3-3zm0 1l2 2H8zm-4 0h3v3h3v5H4z"/><path d="M17 71.5a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0" fill="#9f9f9f"/><path d="M27 69.43l-.93-.93-2.57 2.57-2.57-2.57-.93.93L22.57 72 20 74.57l.93.93 2.57-2.57 2.57 2.57.93-.93L24.43 72z" fill-opacity=".36"/><path d="M27 68.93l-.93-.93-2.57 2.57L20.93 68l-.93.93 2.57 2.57L20 74.07l.93.93 2.57-2.57L26.07 75l.93-.93-2.57-2.57z" fill="#fff"/><path d="M33 71.5a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0" fill="#bebebe"/><path d="M43 69.43l-.93-.93-2.57 2.57-2.57-2.57-.93.93L38.57 72 36 74.57l.93.93 2.57-2.57 2.57 2.57.93-.93L40.43 72z" fill-opacity=".37"/><path d="M43 68.93l-.93-.93-2.57 2.57L36.93 68l-.93.93 2.57 2.57L36 74.07l.93.93 2.57-2.57L42.07 75l.93-.93-2.57-2.57z" fill="#fff"/><g transform="translate(49 65)"><path transform="translate(-111 -96)" d="M118 96c-3.87 0-7 3.13-7 7s3.13 7 7 7 7-3.13 7-7-3.13-7-7-7" fill="url(#c)"/><path d="M.5 7a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0" fill="#f27d82"/><path d="M10.5 4.93L9.57 4 7 6.57 4.43 4l-.93.93L6.07 7.5 3.5 10.07l.93.93L7 8.43 9.57 11l.93-.93L7.93 7.5z" fill-opacity=".36"/><path d="M10.5 4.43l-.93-.93L7 6.07 4.43 3.5l-.93.93L6.07 7 3.5 9.57l.93.93L7 7.93l2.57 2.57.93-.93L7.93 7z" fill="#fff"/><defs><linearGradient id="d"><stop stop-color="#d7687d" offset="0"/><stop stop-color="#b21402" offset="1"/></linearGradient><linearGradient id="c" x2="24" gradientTransform="matrix(0 -.58333 -.58333 0 118 110)" gradientUnits="userSpaceOnUse" xlink:href="#d"/></defs></g><g transform="translate(1 81)"><path transform="translate(-96 -96)" d="M103 110c3.87 0 7-3.13 7-7s-3.13-7-7-7-7 3.13-7 7 3.13 7 7 7" fill="url(#e)"/><path transform="translate(-96 -96)" d="M103 96.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13" fill="url(#f)"/><path d="M10.5 4.93L9.57 4 7 6.57 4.43 4l-.93.93L6.07 7.5 3.5 10.07l.93.93L7 8.43 9.57 11l.93-.93L7.93 7.5z" fill="#993c35"/><path d="M10.5 4.43l-.93-.93L7 6.07 4.43 3.5l-.93.93L6.07 7 3.5 9.57l.93.93L7 7.93l2.57 2.57.93-.93L7.93 7z" fill="#fff"/><defs><linearGradient id="f" x1="96.5" x2="109.5" y1="103" y2="103" gradientTransform="rotate(90 103 103)" gradientUnits="userSpaceOnUse" xlink:href="#g"/><linearGradient id="g"><stop stop-color="#e59290" offset="0"/><stop stop-color="#e99890" offset="1"/></linearGradient><linearGradient id="e" x1="113" x2="127" y1="104" y2="104" gradientTransform="rotate(90 112 95)" gradientUnits="userSpaceOnUse" xlink:href="#h"/><linearGradient id="h"><stop stop-color="#c0544f" offset="0"/><stop stop-color="#d08481" offset="1"/></linearGradient></defs></g><path d="M26.27 90.92a4.5 4.5 0 1 1 .73-.684l2.346 2.346-.707.707zm-2.692-.106a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7z" fill="#5b5b5b"/><text style="line-height:0%" x="-11.403" y="91.208" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#b3b3b3"><tspan x="-11.403" y="91.208" style="line-height:1.25" font-size="10">1</tspan></text><text style="line-height:0%" x="-11.144" y="75.675" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#b3b3b3"><tspan x="-11.144" y="75.675" style="line-height:1.25" font-size="10">2</tspan></text><text style="line-height:0%" x="-11.066" y="60.143" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#b3b3b3"><tspan x="-11.066" y="60.143" style="line-height:1.25" font-size="10">3</tspan></text><text style="line-height:0%" x="-11.266" y="44.611" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#b3b3b3"><tspan x="-11.266" y="44.611" style="line-height:1.25" font-size="10">4</tspan></text><text style="line-height:0%" x="5.935" y="108.082" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#b3b3b3"><tspan x="5.935" y="108.082" style="line-height:1.25" font-size="10">a</tspan></text><text style="line-height:0%" x="21.659" y="108.082" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#b3b3b3"><tspan x="21.659" y="108.082" style="line-height:1.25" font-size="10">b</tspan></text><text style="line-height:0%" x="37.384" y="108.082" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#b3b3b3"><tspan x="37.384" y="108.082" style="line-height:1.25" font-size="10">c</tspan></text><text style="line-height:0%" x="53.108" y="108.082" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#b3b3b3"><tspan x="53.108" y="108.082" style="line-height:1.25" font-size="10">d</tspan></text><g fill="none"><path d="M48 96H32V80h16z"/><path d="M40 81c-3.864 0-7 3.136-7 7s3.136 7 7 7 7-3.136 7-7-3.136-7-7-7zm-5.5 7c0-3.032 2.468-5.5 5.5-5.5s5.5 2.468 5.5 5.5-2.468 5.5-5.5 5.5a5.507 5.507 0 0 1-5.5-5.5zm6.5 4v-5h-2v5zm-2-6h2v-2h-2z" fill="#000"/></g><g transform="matrix(1.39974 0 0 1.39343 65.054 81.02)" mask="url(#i)"><path d="M1 9l4-8 4 8z" stroke="#c19600" stroke-width="2" stroke-linejoin="round"/><path d="M1 9l4-8 4 8z" fill="#f4bd00" stroke="#f5bd00" stroke-width="1.5" stroke-linejoin="round"/><path d="M3.75 2.75h2.5v2.5L5.75 7h-1.5l-.5-1.75v-2.5m0 5.25h2.5v1.25h-2.5" fill="#ad8601"/><mask id="i"><path transform="translate(-60)" d="M64 3h2v2.25L65.5 7h-1L64 5.25V3m0 5h2v1h-2"/><path fill="#fff" d="M0 0h10v10H0z"/></mask></g><g transform="matrix(1.36 0 0 1.34 65.3 65.5)" mask="url(#j)"><path transform="translate(-80)" d="M85 0c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5" fill="url(#k)"/><path d="M.36 5C.36 7.56 2.44 9.64 5 9.64c2.56 0 4.64-2.08 4.64-4.64C9.64 2.44 7.56.36 5 .36 2.44.36.36 2.44.36 5" fill="#2a53cd"/><mask id="j"><path transform="translate(-80)" d="M83.93 2.14c-.03-.53.55-.97 1.06-.83.5.12.79.73.56 1.18-.2.44-.79.61-1.2.36a.812.812 0 0 1-.42-.71zm1.7 5.46h.67v.53h-2.89V7.6h.66V3.99h-.66v-.53h2.22z"/><path fill="#fff" d="M0 0h10v10H0z"/></mask></g><g transform="matrix(1.37 0 0 1.36 65.2 49.3)" mask="url(#l)"><path transform="translate(-20)" d="M25 0c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5" fill="url(#m)"/><path d="M.36 5C.36 7.56 2.44 9.64 5 9.64c2.56 0 4.64-2.08 4.64-4.64C9.64 2.44 7.56.36 5 .36 2.44.36.36 2.44.36 5" fill="#eb3941"/><mask id="l"><path transform="translate(-20)" d="M23 3l4 4M27 3l-4 4" stroke="#000"/><path fill="#fff" d="M0 0h10v10H0z"/></mask></g><path d="M72 33.333A6.67 6.67 0 0 0 65.333 40 6.67 6.67 0 0 0 72 46.667 6.67 6.67 0 0 0 78.667 40 6.67 6.67 0 0 0 72 33.333zm0 2c1.107 0 2 .894 2 2 0 1.107-.893 2-2 2s-2-.893-2-2c0-1.106.893-2 2-2zm0 9.467a4.8 4.8 0 0 1-4-2.147c.02-1.326 2.667-2.053 4-2.053 1.327 0 3.98.727 4 2.053a4.8 4.8 0 0 1-4 2.147z"/><path d="M64 32h16v16H64z" fill="none"/><text style="line-height:0%;-inkscape-font-specification:Sans;text-align:start" x="-10.738" y="28.118" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill-opacity=".373"><tspan x="-10.738" y="28.118" style="line-height:1.25" font-size="10">5</tspan></text><text style="line-height:0%;-inkscape-font-specification:Sans;text-align:start" x="68.649" y="107.697" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill-opacity=".351"><tspan x="68.649" y="107.697" style="line-height:1.25" font-size="10">e</tspan></text><path d="M65.25 24.75h1.5v-1.5h-1.5zm0 3h1.5v-1.5h-1.5zm0-6h1.5v-1.5h-1.5zm3 3h10.5v-1.5h-10.5zm0 3h10.5v-1.5h-10.5zm0-7.5v1.5h10.5v-1.5z"/><path d="M63 15h18v18H63zM47 79h18v18H47z" fill="none"/><path d="M62 85h-2.107a4.489 4.489 0 0 0-1.366-1.47l1.223-1.222-1.058-1.058-1.627 1.627a4.439 4.439 0 0 0-2.122 0l-1.635-1.627-1.058 1.058 1.215 1.222A4.547 4.547 0 0 0 52.108 85H50v1.5h1.568a4.978 4.978 0 0 0-.068.75V88H50v1.5h1.5v.75c0 .255.03.503.068.75H50v1.5h2.108A4.498 4.498 0 0 0 56 94.75a4.498 4.498 0 0 0 3.893-2.25H62V91h-1.567c.037-.248.067-.495.067-.75v-.75H62V88h-1.5v-.75c0-.255-.03-.503-.067-.75H62zm-4.5 6h-3v-1.5h3zm0-3h-3v-1.5h3z"/><g fill="none"><path opacity=".2" d="M48 16h16v16H48z"/><path d="M48.5 30h15L56 17zm8.5-2h-2v-2h2zm0-3h-2v-3h2z" fill="#000"/></g><text style="line-height:0%" x="32.47" y="23.902" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0"><tspan x="32.47" y="23.902" style="line-height:1.25" font-weight="700" font-size="10">A</tspan></text><text style="line-height:0%" x="40.363" y="31.525" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0"><tspan x="40.363" y="31.525" style="line-height:1.25" font-weight="700" font-size="10">B</tspan></text><path d="M37.955 29.089c-1.915-.292-2.12-.9-2.237-4.13h-1.22c.047 3.856.062 5.297 5.736 5.258l.316-.014-2.595-2.996a39.95 39.95 0 0 0 0 1.882z"/><g fill="none" fill-rule="evenodd"><path d="M0 16h16v16H0z"/><g fill="#000" fill-rule="nonzero"><path d="M9.58 27.313l1.417 1.294c-.86.577-1.89.913-2.997.913-3.004 0-5.44-2.471-5.44-5.52 0-.917.22-1.782.61-2.543l1.417 1.294c-.138.39-.214.81-.214 1.249 0 2.032 1.624 3.68 3.627 3.68.567 0 1.103-.132 1.58-.367zm1.826-2.046c.143-.395.22-.822.22-1.267 0-2.032-1.623-3.68-3.626-3.68-.573 0-1.116.135-1.598.375l-1.414-1.292A5.36 5.36 0 0 1 8 18.48c3.004 0 5.44 2.471 5.44 5.52 0 .924-.224 1.795-.619 2.56z"/><path d="M8 25.84v5.52l3.022-2.76zM8 22.16v-5.52L4.978 19.4z"/></g></g><g fill="none" fill-rule="evenodd"><path fill="#000" d="M20 20h2v6h-2zM26 22h2v6h-2z"/><path fill="#000" fill-rule="nonzero" d="M24.667 20.667l-3.667-4-3.667 4h4.584zM23.333 27.333l3.667 4 3.667-4h-4.584z"/><path d="M16 16h16v16H16z"/></g><text style="line-height:0%;-inkscape-font-specification:Sans;text-align:start" x="-10.547" y="11.352" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill-opacity=".373"><tspan x="-10.547" y="11.352" style="line-height:1.25" font-size="10">6</tspan></text><text style="line-height:0%;-inkscape-font-specification:Sans;text-align:start" x="85.725" y="108.235" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill-opacity=".351"><tspan x="85.725" y="108.235" style="line-height:1.25" font-size="10">f</tspan></text><g><path d="M1 1h14v14H1z" fill="none"/><path d="M12.287 6.857A4.37 4.37 0 0 0 4.121 5.69 3.497 3.497 0 0 0 1 9.167c0 1.93 1.57 3.5 3.5 3.5h7.583A2.918 2.918 0 0 0 15 9.75a2.903 2.903 0 0 0-2.713-2.893z"/></g><g><path d="M24.044 15a1.44 1.44 0 0 0 1.435-1.436h-2.871c0 .79.639 1.436 1.436 1.436zm4.307-4.308v-3.59c0-2.204-1.177-4.049-3.23-4.537v-.488C25.12 1.48 24.639 1 24.044 1c-.596 0-1.077.481-1.077 1.077v.488c-2.06.488-3.231 2.326-3.231 4.538v3.59L18.3 12.127v.718h11.487v-.718z"/></g></svg>
\ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="96" height="96"><defs><linearGradient id="a"><stop offset="0" stop-color="#d7687d"/><stop offset="1" stop-color="#b21402"/></linearGradient><linearGradient id="b"><stop offset="0" stop-color="#606eda"/><stop offset="1" stop-color="#021db2"/></linearGradient><linearGradient xlink:href="#a" id="m" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0 -.41667 -.41667 0 25 10)" x2="24"/><linearGradient xlink:href="#b" id="k" gradientUnits="userSpaceOnUse" gradientTransform="translate(-.714 -69.286) scale(.71429)" x1="113" y1="104" x2="127" y2="104"/></defs><path d="M3 36h10v9.008A1.99 1.99 0 0 1 11 47H5c-1.105 0-2-.9-2-1.992zm-1-2h12v1H2zm3-1h6v1H5zM29.526 38.25h-1.474v-.75c0-.414-.33-.75-.737-.75h-1.473V36c0-.414-.33-.75-.737-.75h-.737v-1.5a.743.743 0 0 0-.494-.7.494.494 0 0 0-.243-.05C19.968 33 17 36.022 17 39.75s2.968 6.75 6.631 6.75c3.663 0 6.632-3.022 6.632-6.75V39c0-.414-.33-.75-.737-.75zm-9.947 2.25c-.611 0-1.106-.503-1.106-1.125s.495-1.125 1.106-1.125c.61 0 1.105.503 1.105 1.125s-.495 1.125-1.105 1.125zm1.105-4.125c0-.622.495-1.125 1.105-1.125.611 0 1.105.503 1.105 1.125 0 .621-.494 1.125-1.105 1.125-.61 0-1.105-.504-1.105-1.125zM22.894 45c-.61 0-1.105-.503-1.105-1.125 0-.62.495-1.125 1.105-1.125.611 0 1.106.504 1.106 1.125 0 .622-.495 1.125-1.106 1.125zm.369-3.75c-.61 0-1.105-.504-1.105-1.125S22.653 39 23.263 39s1.105.504 1.105 1.125-.495 1.125-1.105 1.125zm3.684 1.5c-.61 0-1.105-.504-1.105-1.125s.495-1.125 1.105-1.125 1.105.504 1.105 1.125-.495 1.125-1.105 1.125z" fill="#212121"/><path d="M40 38c3.314 0 6-.895 6-2s-2.686-2-6-2-6 .895-6 2 2.686 2 6 2zm-6 7c0 1.105 2.686 2 6 2s6-.895 6-2v-2c0 1.105-2.686 2-6 2s-6-.895-6-2zm0-3c0 1.105 2.686 2 6 2s6-.895 6-2v-2c0 1.105-2.686 2-6 2s-6-.895-6-2zm0-3c0 1.105 2.686 2 6 2s6-.895 6-2v-2c0 1.105-2.686 2-6 2s-6-.895-6-2z"/><g fill="none"><path d="M48 32h16v16H48z"/><path d="M57 33h-5.005c-.54 0-.995.45-.995 1.007v11.986A1 1 0 0 0 51.995 47h8.01c.54 0 .995-.451.995-1.007V37l-4-4zm3.29 4H57v-3.29z" fill="#000"/></g><path d="M6.5 51.229V49h3v2.229a4.994 4.994 0 0 1 1.88 1.087l1.932-1.115 1.5 2.598-1.93 1.115a5.018 5.018 0 0 1 0 2.173l1.93 1.114-1.5 2.598-1.931-1.115A4.995 4.995 0 0 1 9.5 60.771v2.23h-3v-2.23a4.994 4.994 0 0 1-1.88-1.087L2.687 60.8l-1.5-2.598 1.93-1.114a5.018 5.018 0 0 1 0-2.173l-1.93-1.115 1.5-2.598 1.931 1.115A4.995 4.995 0 0 1 6.5 51.23zM8 58.5a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5zM18 51.999a1 1 0 0 1 .99-.999H24v3h-6v-2.001zM18 59h6v3h-5.01a.992.992 0 0 1-.99-.999V59zm0-4h6v3h-6zm7-4h5.01c.546 0 .99.443.99.999V54h-6v-3zm0 8h6v2.001a1 1 0 0 1-.99.999H25v-3zm0-4h6v3h-6z" fill="#212121"/><path d="M39.5 61a5.5 5.5 0 1 0 0-11 5.5 5.5 0 0 0 0 11zm0-2.2v-2.2h-3.3v-2.2h3.3v-2.2l3.3 3.3z"/><g transform="translate(-26 25)"><circle transform="matrix(1.2 0 0 1.2 72.4 21.2)" cx="10.5" cy="11.5" r="2.5" fill="#009802"/><path d="M78 25c-.544 0-1 .45-1 1v8c0 .54.45 1 1 1h3.031a3.533 3.533 0 0 1-.031-.5c0-.17.008-.337.031-.5H78v-8h3v3h3v1.5c.163-.023.33 0 .5 0 .17 0 .337-.023.5 0V28l-3-3zm4 1l2 2h-2z"/></g><path d="M8 66H3.997a1 1 0 0 0-.997.995v8.01c0 .54.446.995.997.995h6.006a1 1 0 0 0 .997-.995V69l-3-3zm0 1l2 2H8zm-4 0h3v3h3v5H4z"/><path d="M17 71.5a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0" fill="#9f9f9f"/><path d="M27 69.43l-.93-.93-2.57 2.57-2.57-2.57-.93.93L22.57 72 20 74.57l.93.93 2.57-2.57 2.57 2.57.93-.93L24.43 72z" fill-opacity=".36"/><path d="M27 68.93l-.93-.93-2.57 2.57L20.93 68l-.93.93 2.57 2.57L20 74.07l.93.93 2.57-2.57L26.07 75l.93-.93-2.57-2.57z" fill="#fff"/><path d="M33 71.5a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0" fill="#bebebe"/><path d="M43 69.43l-.93-.93-2.57 2.57-2.57-2.57-.93.93L38.57 72 36 74.57l.93.93 2.57-2.57 2.57 2.57.93-.93L40.43 72z" fill-opacity=".37"/><path d="M43 68.93l-.93-.93-2.57 2.57L36.93 68l-.93.93 2.57 2.57L36 74.07l.93.93 2.57-2.57L42.07 75l.93-.93-2.57-2.57z" fill="#fff"/><g transform="translate(49 65)"><path transform="translate(-111 -96)" d="M118 96c-3.87 0-7 3.13-7 7s3.13 7 7 7 7-3.13 7-7-3.13-7-7-7" fill="url(#c)"/><path d="M.5 7a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0" fill="#f27d82"/><path d="M10.5 4.93L9.57 4 7 6.57 4.43 4l-.93.93L6.07 7.5 3.5 10.07l.93.93L7 8.43 9.57 11l.93-.93L7.93 7.5z" fill-opacity=".36"/><path d="M10.5 4.43l-.93-.93L7 6.07 4.43 3.5l-.93.93L6.07 7 3.5 9.57l.93.93L7 7.93l2.57 2.57.93-.93L7.93 7z" fill="#fff"/><defs><linearGradient id="d"><stop stop-color="#d7687d" offset="0"/><stop stop-color="#b21402" offset="1"/></linearGradient><linearGradient id="c" x2="24" gradientTransform="matrix(0 -.58333 -.58333 0 118 110)" gradientUnits="userSpaceOnUse" xlink:href="#d"/></defs></g><g transform="translate(1 81)"><path transform="translate(-96 -96)" d="M103 110c3.87 0 7-3.13 7-7s-3.13-7-7-7-7 3.13-7 7 3.13 7 7 7" fill="url(#e)"/><path transform="translate(-96 -96)" d="M103 96.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13" fill="url(#f)"/><path d="M10.5 4.93L9.57 4 7 6.57 4.43 4l-.93.93L6.07 7.5 3.5 10.07l.93.93L7 8.43 9.57 11l.93-.93L7.93 7.5z" fill="#993c35"/><path d="M10.5 4.43l-.93-.93L7 6.07 4.43 3.5l-.93.93L6.07 7 3.5 9.57l.93.93L7 7.93l2.57 2.57.93-.93L7.93 7z" fill="#fff"/><defs><linearGradient id="f" x1="96.5" x2="109.5" y1="103" y2="103" gradientTransform="rotate(90 103 103)" gradientUnits="userSpaceOnUse" xlink:href="#g"/><linearGradient id="g"><stop stop-color="#e59290" offset="0"/><stop stop-color="#e99890" offset="1"/></linearGradient><linearGradient id="e" x1="113" x2="127" y1="104" y2="104" gradientTransform="rotate(90 112 95)" gradientUnits="userSpaceOnUse" xlink:href="#h"/><linearGradient id="h"><stop stop-color="#c0544f" offset="0"/><stop stop-color="#d08481" offset="1"/></linearGradient></defs></g><path d="M26.27 90.92a4.5 4.5 0 1 1 .73-.684l2.346 2.346-.707.707zm-2.692-.106a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7z" fill="#5b5b5b"/><text style="line-height:0%" x="-11.403" y="91.208" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#b3b3b3"><tspan x="-11.403" y="91.208" style="line-height:1.25" font-size="10">1</tspan></text><text style="line-height:0%" x="-11.144" y="75.675" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#b3b3b3"><tspan x="-11.144" y="75.675" style="line-height:1.25" font-size="10">2</tspan></text><text style="line-height:0%" x="-11.066" y="60.143" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#b3b3b3"><tspan x="-11.066" y="60.143" style="line-height:1.25" font-size="10">3</tspan></text><text style="line-height:0%" x="-11.266" y="44.611" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#b3b3b3"><tspan x="-11.266" y="44.611" style="line-height:1.25" font-size="10">4</tspan></text><text style="line-height:0%" x="5.935" y="108.082" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#b3b3b3"><tspan x="5.935" y="108.082" style="line-height:1.25" font-size="10">a</tspan></text><text style="line-height:0%" x="21.659" y="108.082" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#b3b3b3"><tspan x="21.659" y="108.082" style="line-height:1.25" font-size="10">b</tspan></text><text style="line-height:0%" x="37.384" y="108.082" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#b3b3b3"><tspan x="37.384" y="108.082" style="line-height:1.25" font-size="10">c</tspan></text><text style="line-height:0%" x="53.108" y="108.082" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#b3b3b3"><tspan x="53.108" y="108.082" style="line-height:1.25" font-size="10">d</tspan></text><g fill="none"><path d="M48 96H32V80h16z"/><path d="M40 81c-3.864 0-7 3.136-7 7s3.136 7 7 7 7-3.136 7-7-3.136-7-7-7zm-5.5 7c0-3.032 2.468-5.5 5.5-5.5s5.5 2.468 5.5 5.5-2.468 5.5-5.5 5.5a5.507 5.507 0 0 1-5.5-5.5zm6.5 4v-5h-2v5zm-2-6h2v-2h-2z" fill="#000"/></g><g transform="matrix(1.39974 0 0 1.39343 65.054 81.02)" mask="url(#i)"><path d="M1 9l4-8 4 8z" stroke="#c19600" stroke-width="2" stroke-linejoin="round"/><path d="M1 9l4-8 4 8z" fill="#f4bd00" stroke="#f5bd00" stroke-width="1.5" stroke-linejoin="round"/><path d="M3.75 2.75h2.5v2.5L5.75 7h-1.5l-.5-1.75v-2.5m0 5.25h2.5v1.25h-2.5" fill="#ad8601"/><mask id="i"><path fill="#fff" d="M0 0h10v10H0z"/><path transform="translate(-60)" d="M64 3h2v2.25L65.5 7h-1L64 5.25V3m0 5h2v1h-2"/></mask></g><g transform="matrix(1.36 0 0 1.34 65.3 65.5)" mask="url(#j)"><path transform="translate(-80)" d="M85 0c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5" fill="url(#k)"/><path d="M.36 5C.36 7.56 2.44 9.64 5 9.64c2.56 0 4.64-2.08 4.64-4.64C9.64 2.44 7.56.36 5 .36 2.44.36.36 2.44.36 5" fill="#2a53cd"/><mask id="j"><path fill="#fff" d="M0 0h10v10H0z"/><path transform="translate(-80)" d="M83.93 2.14c-.03-.53.55-.97 1.06-.83.5.12.79.73.56 1.18-.2.44-.79.61-1.2.36a.812.812 0 0 1-.42-.71zm1.7 5.46h.67v.53h-2.89V7.6h.66V3.99h-.66v-.53h2.22z"/></mask></g><g transform="matrix(1.37 0 0 1.36 65.2 49.3)" mask="url(#l)"><path transform="translate(-20)" d="M25 0c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5" fill="url(#m)"/><path d="M.36 5C.36 7.56 2.44 9.64 5 9.64c2.56 0 4.64-2.08 4.64-4.64C9.64 2.44 7.56.36 5 .36 2.44.36.36 2.44.36 5" fill="#eb3941"/><mask id="l"><path fill="#fff" d="M0 0h10v10H0z"/><path transform="translate(-20)" d="M23 3l4 4M27 3l-4 4" stroke="#000"/></mask></g><path d="M72 33.333A6.67 6.67 0 0 0 65.333 40 6.67 6.67 0 0 0 72 46.667 6.67 6.67 0 0 0 78.667 40 6.67 6.67 0 0 0 72 33.333zm0 2c1.107 0 2 .894 2 2 0 1.107-.893 2-2 2s-2-.893-2-2c0-1.106.893-2 2-2zm0 9.467a4.8 4.8 0 0 1-4-2.147c.02-1.326 2.667-2.053 4-2.053 1.327 0 3.98.727 4 2.053a4.8 4.8 0 0 1-4 2.147z"/><path d="M64 32h16v16H64z" fill="none"/><text style="line-height:0%;-inkscape-font-specification:Sans;text-align:start" x="-10.738" y="28.118" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill-opacity=".373"><tspan x="-10.738" y="28.118" style="line-height:1.25" font-size="10">5</tspan></text><text style="line-height:0%;-inkscape-font-specification:Sans;text-align:start" x="68.649" y="107.697" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill-opacity=".351"><tspan x="68.649" y="107.697" style="line-height:1.25" font-size="10">e</tspan></text><path d="M65.25 24.75h1.5v-1.5h-1.5zm0 3h1.5v-1.5h-1.5zm0-6h1.5v-1.5h-1.5zm3 3h10.5v-1.5h-10.5zm0 3h10.5v-1.5h-10.5zm0-7.5v1.5h10.5v-1.5z"/><path d="M63 15h18v18H63zM47 79h18v18H47z" fill="none"/><path d="M62 85h-2.107a4.489 4.489 0 0 0-1.366-1.47l1.223-1.222-1.058-1.058-1.627 1.627a4.439 4.439 0 0 0-2.122 0l-1.635-1.627-1.058 1.058 1.215 1.222A4.547 4.547 0 0 0 52.108 85H50v1.5h1.568a4.978 4.978 0 0 0-.068.75V88H50v1.5h1.5v.75c0 .255.03.503.068.75H50v1.5h2.108A4.498 4.498 0 0 0 56 94.75a4.498 4.498 0 0 0 3.893-2.25H62V91h-1.567c.037-.248.067-.495.067-.75v-.75H62V88h-1.5v-.75c0-.255-.03-.503-.067-.75H62zm-4.5 6h-3v-1.5h3zm0-3h-3v-1.5h3z"/><g fill="none"><path opacity=".2" d="M48 16h16v16H48z"/><path d="M48.5 30h15L56 17zm8.5-2h-2v-2h2zm0-3h-2v-3h2z" fill="#000"/></g><text style="line-height:0%" x="32.47" y="23.902" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0"><tspan x="32.47" y="23.902" style="line-height:1.25" font-weight="700" font-size="10">A</tspan></text><text style="line-height:0%" x="40.363" y="31.525" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0"><tspan x="40.363" y="31.525" style="line-height:1.25" font-weight="700" font-size="10">B</tspan></text><path d="M37.955 29.089c-1.915-.292-2.12-.9-2.237-4.13h-1.22c.047 3.856.062 5.297 5.736 5.258l.316-.014-2.595-2.996a39.95 39.95 0 0 0 0 1.882z"/><g fill="none" fill-rule="evenodd"><path d="M0 16h16v16H0z"/><g fill="#000" fill-rule="nonzero"><path d="M9.58 27.313l1.417 1.294c-.86.577-1.89.913-2.997.913-3.004 0-5.44-2.471-5.44-5.52 0-.917.22-1.782.61-2.543l1.417 1.294c-.138.39-.214.81-.214 1.249 0 2.032 1.624 3.68 3.627 3.68.567 0 1.103-.132 1.58-.367zm1.826-2.046c.143-.395.22-.822.22-1.267 0-2.032-1.623-3.68-3.626-3.68-.573 0-1.116.135-1.598.375l-1.414-1.292A5.36 5.36 0 0 1 8 18.48c3.004 0 5.44 2.471 5.44 5.52 0 .924-.224 1.795-.619 2.56z"/><path d="M8 25.84v5.52l3.022-2.76zM8 22.16v-5.52L4.978 19.4z"/></g></g><g fill="none" fill-rule="evenodd"><path fill="#000" d="M20 20h2v6h-2zM26 22h2v6h-2z"/><path fill="#000" fill-rule="nonzero" d="M24.667 20.667l-3.667-4-3.667 4h4.584zM23.333 27.333l3.667 4 3.667-4h-4.584z"/><path d="M16 16h16v16H16z"/></g><text style="line-height:0%;-inkscape-font-specification:Sans;text-align:start" x="-10.547" y="11.352" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill-opacity=".373"><tspan x="-10.547" y="11.352" style="line-height:1.25" font-size="10">6</tspan></text><text style="line-height:0%;-inkscape-font-specification:Sans;text-align:start" x="85.725" y="108.235" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill-opacity=".351"><tspan x="85.725" y="108.235" style="line-height:1.25" font-size="10">f</tspan></text><g><path d="M1 1h14v14H1z" fill="none"/><path d="M12.287 6.857A4.37 4.37 0 0 0 4.121 5.69 3.497 3.497 0 0 0 1 9.167c0 1.93 1.57 3.5 3.5 3.5h7.583A2.918 2.918 0 0 0 15 9.75a2.903 2.903 0 0 0-2.713-2.893z"/></g><g><path d="M24.044 15a1.44 1.44 0 0 0 1.435-1.436h-2.871c0 .79.639 1.436 1.436 1.436zm4.307-4.308v-3.59c0-2.204-1.177-4.049-3.23-4.537v-.488C25.12 1.48 24.639 1 24.044 1c-.596 0-1.077.481-1.077 1.077v.488c-2.06.488-3.231 2.326-3.231 4.538v3.59L18.3 12.127v.718h11.487v-.718z"/></g></svg>
\ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/Images/smallIcons.svg b/third_party/blink/renderer/devtools/front_end/Images/smallIcons.svg
index e4ae476..1ac8139 100644
--- a/third_party/blink/renderer/devtools/front_end/Images/smallIcons.svg
+++ b/third_party/blink/renderer/devtools/front_end/Images/smallIcons.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="110" height="110"><defs><linearGradient id="y" x1="113" x2="127" y1="104" y2="104" gradientTransform="translate(-.714 -69.286) scale(.71429)" gradientUnits="userSpaceOnUse" xlink:href="#a"/><linearGradient id="a"><stop stop-color="#606eda" offset="0"/><stop stop-color="#021db2" offset="1"/></linearGradient><linearGradient id="A" x2="24" gradientTransform="matrix(0 -.41667 -.41667 0 25 10)" gradientUnits="userSpaceOnUse" xlink:href="#b"/><linearGradient id="b"><stop stop-color="#d7687d" offset="0"/><stop stop-color="#b21402" offset="1"/></linearGradient></defs><path d="M0 20.995c0-.55.456-.995.995-.995h8.01c.55 0 .995.455.995.995v8.01c0 .549-.456.995-.995.995H.995C.445 30 0 29.544 0 29.004zm5.123 4.744C7.691 25.312 8.75 24.546 8.75 22h-1.5c0 1.62-.44 1.939-2.373 2.26-2.568.429-3.627 1.194-3.627 3.74h1.5c0-1.62.44-1.937 2.373-2.26zM23.65 27.21l-1.44-2.03L21 26.39 23.55 30 30 22.33 28.88 21z"/><path d="M6.5 46c0 .55.45 1 1 1s1-.45 1-1-.45-1-1-1-1 .45-1 1" fill="#bababa"/><path d="M5.75 42.75L2.25 46l3.5 3.25" fill="none" stroke="#bababa" stroke-width="1.5"/><path d="M27.5 42.43l-.93-.93L24 44.07l-2.57-2.57-.93.93L23.07 45l-2.57 2.57.93.93L24 45.93l2.57 2.57.93-.93L24.93 45l2.57-2.57z" fill-opacity=".24"/><path d="M27.5 41.93l-.93-.93L24 43.57 21.43 41l-.93.93 2.57 2.57-2.57 2.57.93.93L24 45.43 26.57 48l.93-.93-2.57-2.57 2.57-2.57z" fill="#676767"/><path d="M43.25 20c-.7 0-1.25.5-1.25 1.25v7.5c0 .7.5 1.25 1.25 1.25h3.5c.7 0 1.25-.5 1.25-1.25v-7.5c0-.7-.5-1.25-1.25-1.25zM43 21h4v7h-4zm2 7.25c.4 0 .75.3.75.75 0 .4-.3.75-.75.75-.4 0-.75-.3-.75-.75 0-.4.3-.75.75-.75z"/><g transform="translate(40 40)"><path transform="translate(-20)" d="M25 0c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5" fill="url(#c)"/><path d="M.36 5C.36 7.56 2.44 9.64 5 9.64c2.56 0 4.64-2.08 4.64-4.64C9.64 2.44 7.56.36 5 .36 2.44.36.36 2.44.36 5" fill="#eb3941"/><path d="M3 3l4 4M7 3L3 7" stroke="#fff"/><defs><linearGradient id="d"><stop stop-color="#d7687d" offset="0"/><stop stop-color="#b21402" offset="1"/></linearGradient><linearGradient id="c" x2="24" gradientTransform="matrix(0 -.41667 -.41667 0 25 10)" gradientUnits="userSpaceOnUse" xlink:href="#d"/></defs></g><path d="M4.5 61.3l4 3.7-4 3.7v-1.2H1.425l.075-5h3z" fill="#adf2ad" stroke="#007200"/><g transform="translate(20 60)"><path transform="translate(-140)" d="M144.95 10A5.002 5.002 0 0 1 140 4.95 5.002 5.002 0 0 1 145.05 0c2.76.03 4.98 2.29 4.95 5.05a5.002 5.002 0 0 1-5.05 4.95z" fill="url(#e)"/><path d="M9.5 5.05A4.494 4.494 0 0 1 4.95 9.5 4.494 4.494 0 0 1 .5 4.95 4.494 4.494 0 0 1 5.05.5C7.54.53 9.53 2.56 9.5 5.05z" fill="#00be00"/><path transform="translate(-140)" d="M145.08.53c1.97.02 3.55 1.06 3.54 2.32-.01 1.26-1.62 2.26-3.59 2.24-1.97-.02-3.55-1.06-3.54-2.32.01-1.26 1.62-2.26 3.59-2.24z" fill="url(#f)"/><path transform="translate(-140)" d="M144.98 9.41c1.66.02 3.01-.68 3.02-1.56.01-.88-1.33-1.61-2.98-1.63-1.66-.02-3.01.68-3.02 1.56-.01.88 1.33 1.61 2.98 1.63z" fill="url(#g)"/><defs><linearGradient id="h"><stop stop-color="#00d600" stop-opacity="0" offset="0"/><stop stop-color="#d8fc7b" stop-opacity=".81" offset="1"/></linearGradient><linearGradient id="i"><stop stop-color="#00ba00" offset="0"/><stop stop-color="#fff" stop-opacity=".91" offset="1"/></linearGradient><linearGradient id="j"><stop stop-color="#00a104" offset="0"/><stop stop-color="#00c605" offset="1"/></linearGradient><linearGradient id="g" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(-.0048 .4396 .78038 .00853 65.608 -94.834)" gradientUnits="userSpaceOnUse" xlink:href="#h"/><linearGradient id="f" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(.00687 -.62923 .9267 .01012 47.871 147.44)" gradientUnits="userSpaceOnUse" xlink:href="#i"/><linearGradient id="e" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(-.01507 1.3791 -1.3006 -.0142 282.66 -312.8)" gradientUnits="userSpaceOnUse" xlink:href="#j"/></defs></g><g transform="translate(40 60)"><path transform="translate(-80)" d="M85 0c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5" fill="url(#k)"/><path d="M.36 5C.36 7.56 2.44 9.64 5 9.64c2.56 0 4.64-2.08 4.64-4.64C9.64 2.44 7.56.36 5 .36 2.44.36.36 2.44.36 5" fill="#2a53cd"/><path d="M3.93 2.14c-.03-.53.55-.97 1.06-.83.5.12.79.73.56 1.18-.2.44-.79.61-1.2.36a.812.812 0 0 1-.42-.71zm1.7 5.46h.67v.53H3.41V7.6h.66V3.99h-.66v-.53h2.22V7.6z" fill="#fff"/><defs><linearGradient id="l"><stop stop-color="#606eda" offset="0"/><stop stop-color="#021db2" offset="1"/></linearGradient><linearGradient id="k" x1="113" x2="127" y1="104" y2="104" gradientTransform="translate(-.714 -69.286) scale(.71429)" gradientUnits="userSpaceOnUse" xlink:href="#l"/></defs></g><path d="M60.45 20.467v9.079h5.373l3.582-4.54-3.582-4.539z" fill="#698cfe" stroke="#4073f4" stroke-width=".908"/><path d="M60.45 40.467v9.08h5.372l3.581-4.54-3.581-4.54z" fill="#ef9d0d" stroke="#a36c01" stroke-width=".908"/><g transform="translate(60 60)"><path d="M5 10c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z" fill="#e5a600"/><path d="M9.5 5c0 2.49-2.01 4.5-4.5 4.5S.5 7.49.5 5 2.51.5 5 .5 9.5 2.51 9.5 5z" fill="#ffbd00"/><path transform="translate(-160)" d="M165.03.53c1.97 0 3.56 1.02 3.56 2.28 0 1.26-1.59 2.28-3.56 2.28s-3.56-1.02-3.56-2.28c0-1.26 1.59-2.28 3.56-2.28z" fill="url(#m)"/><path transform="translate(-160)" d="M164.99 9.42c1.66 0 3-.71 3-1.59 0-.88-1.34-1.59-3-1.59s-3 .71-3 1.59c0 .88 1.34 1.59 3 1.59z" fill="url(#n)"/><defs><linearGradient id="o"><stop stop-color="#ffa801" stop-opacity="0" offset="0"/><stop stop-color="#f0fb3d" offset="1"/></linearGradient><linearGradient id="p"><stop stop-color="#ffbd00" stop-opacity=".65" offset="0"/><stop stop-color="#fff" stop-opacity=".91" offset="1"/></linearGradient><linearGradient id="n" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(0 .43966 .78049 0 84.444 -93.924)" gradientUnits="userSpaceOnUse" xlink:href="#o"/><linearGradient id="m" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(0 -.62931 .92683 0 69.47 148.53)" gradientUnits="userSpaceOnUse" xlink:href="#p"/></defs></g><g transform="translate(0 80)"><path transform="translate(-120)" d="M125 10c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z" fill="url(#q)"/><path d="M9.5 5c0 2.49-2.01 4.5-4.5 4.5S.5 7.49.5 5 2.51.5 5 .5 9.5 2.51 9.5 5z" fill="#d00"/><path transform="translate(-120)" d="M125.03.53c1.97 0 3.56 1.02 3.56 2.28 0 1.26-1.59 2.28-3.56 2.28s-3.56-1.02-3.56-2.28c0-1.26 1.59-2.28 3.56-2.28z" fill="url(#r)"/><path transform="translate(-120)" d="M125.03 9.47c1.66 0 3-.71 3-1.59 0-.88-1.34-1.59-3-1.59s-3 .71-3 1.59c0 .88 1.34 1.59 3 1.59z" fill="url(#s)"/><defs><linearGradient id="t"><stop stop-color="red" stop-opacity="0" offset="0"/><stop stop-color="#f0cb68" stop-opacity=".71" offset="1"/></linearGradient><linearGradient id="u"><stop stop-color="#e60000" stop-opacity=".65" offset="0"/><stop stop-color="#fff" stop-opacity=".91" offset="1"/></linearGradient><linearGradient id="v"><stop stop-color="#a10000" offset="0"/><stop stop-color="#c60000" offset="1"/></linearGradient><linearGradient id="s" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(0 .43966 .78049 0 44.488 -93.88)" gradientUnits="userSpaceOnUse" xlink:href="#t"/><linearGradient id="r" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(0 -.62931 .92683 0 29.47 148.53)" gradientUnits="userSpaceOnUse" xlink:href="#u"/><linearGradient id="q" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(0 1.3793 -1.3008 0 259.08 -314.35)" gradientUnits="userSpaceOnUse" xlink:href="#v"/></defs></g><path d="M20 80h10v10H20z" fill="none"/><path d="M27.5 82.5V80H20v7.5h2.5V90H30v-7.5zM21 81h5.5v5.5H21zm2.5 6.5h4v-4H29V89h-5.5z"/><path d="M23.5 87.5h4v-4H29V89h-5.5z" fill-opacity=".25"/><g fill="#acf2ae" stroke="#007200" stroke-width="2.577"><path transform="matrix(.29356 0 0 .2909 2.65 86.864)" d="M144.95 10A5.002 5.002 0 0 1 140 4.95 5.002 5.002 0 0 1 145.05 0c2.76.03 4.98 2.29 4.95 5.05a5.002 5.002 0 0 1-5.05 4.95z"/><path transform="matrix(.29356 0 0 .2909 2.65 86.864)" d="M149.5 5.05a4.494 4.494 0 0 1-4.55 4.45 4.494 4.494 0 0 1-4.45-4.55A4.494 4.494 0 0 1 145.05.5c2.49.03 4.48 2.06 4.45 4.55z"/></g><path d="M48.313 82.5L45.21 86l-3.102-3.5h1.24v-1.92h3.723v1.92z" fill="#adf2ad" stroke="#007200"/><path d="M66.537 88.514a1.314 1.314 0 0 1-1.335 1.295 1.313 1.313 0 0 1-1.306-1.324 1.314 1.314 0 0 1 1.335-1.294c.731.009 1.315.6 1.307 1.323z" fill="#acf2ae" stroke="#007200" stroke-width=".753"/><path d="M62.108 83.5l3.102-2.982 3.102 2.982h-1.24v2h-3.723v-2z" fill="#adf2ad" stroke="#007200"/><path d="M83.25 21.75l3.5 3.25-3.5 3.25" fill="none" stroke="#367cf1" stroke-width="1.5"/><path d="M86 40l-5 5 5 5v-2h3v-6h-3zM84 60l5 5-5 5.022v-2.045L81 68v-6h3z" fill="#4688f1"/><path d="M84.5 88l3.5-6h-7M7 104.5L2 101v7M24 100l4 7h-8"/><path d="M43.25 102.75l3.5 3.25-3.5 3.25" fill="none" stroke="#939393" stroke-width="1.5"/><path d="M61 109l4-8 4 8z" stroke="#c19600" stroke-width="2" stroke-linejoin="round"/><path d="M61 109l4-8 4 8z" fill="#f4bd00" stroke="#f5bd00" stroke-width="1.5" stroke-linejoin="round"/><path d="M63.75 102.75h2.5v2.5l-.5 1.75h-1.5l-.5-1.75v-2.5m0 5.25h2.5v1.25h-2.5" fill="#ad8601"/><path d="M64 103h2v2.25l-.5 1.75h-1l-.5-1.75V103m0 5h2v1h-2" fill="#fff"/><text style="line-height:0%" x="3.051" y="118.387" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="3.051" y="118.387" style="line-height:1.25" font-size="8">a</tspan></text><text style="line-height:0%" x="23.051" y="118.387" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="23.051" y="118.387" style="line-height:1.25" font-size="8">b</tspan></text><text style="line-height:0%" x="43.051" y="118.387" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="43.051" y="118.387" style="line-height:1.25" font-size="8">c</tspan></text><text style="line-height:0%" x="63.051" y="118.387" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="63.051" y="118.387" style="line-height:1.25" font-size="8">d</tspan></text><text style="line-height:0%" x="83.051" y="118.387" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="83.051" y="118.387" style="line-height:1.25" font-size="8">e</tspan></text><text style="line-height:0%" x="-7.026" y="107.818" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-7.026" y="107.818" style="line-height:1.25" font-size="8">1</tspan></text><text style="line-height:0%" x="-6.819" y="87.88" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-6.819" y="87.88" style="line-height:1.25" font-size="8">2</tspan></text><text style="line-height:0%" x="-6.756" y="67.992" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-6.756" y="67.992" style="line-height:1.25" font-size="8">3</tspan></text><text style="line-height:0%" x="-6.917" y="47.994" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-6.917" y="47.994" style="line-height:1.25" font-size="8">4</tspan></text><text style="line-height:0%" x="-7.108" y="28.056" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-7.108" y="28.056" style="line-height:1.25" font-size="8">5</tspan></text><circle cx="3" cy="3" r="2.5" transform="matrix(1.13208 0 0 1.13208 81.604 102.604)" fill="#00bcd4" stroke="#000" stroke-width=".3"/><path d="M5 0a5 5 0 1 0 0 10A5 5 0 0 0 5 0zm.048.721c1.083 0 2.179.4 3.005 1.226a4.234 4.234 0 0 1 0 5.986L5.048 4.952l-2.98-3.005A4.18 4.18 0 0 1 5.047.721z"/><text style="line-height:0%" x="-6.68" y="8" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-6.68" y="8" style="line-height:1.25" font-size="8">6</tspan></text><path d="M17.601-2.913h16.232v16.232H17.601z" fill="none"/><path d="M21.11 5.556L20 6.667 23.334 10 30 3.334l-1.11-1.111-5.556 5.555z" fill-rule="evenodd"/><path d="M44.954 8.42a3.467 3.467 0 0 1-3.462-3.46c0-.678.2-1.309.531-1.84l4.77 4.77c-.531.338-1.162.53-1.84.53m3.462-3.46c0 .676-.2 1.307-.53 1.838l-4.77-4.77a3.405 3.405 0 0 1 1.839-.53 3.467 3.467 0 0 1 3.461 3.461M45 .005a5 5 0 1 0 0 10 5 5 0 0 0 0-10"/><path d="M68.875 2.219L63.344 7.78l-.407-.406L61.844 8.5l1.5 1.5L70 3.344l-1.125-1.125z" fill-rule="evenodd"/><text style="line-height:0%" x="103.739" y="118.482" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="103.739" y="118.482" style="line-height:1.25" font-size="8">f</tspan></text><g transform="translate(100 100)" mask="url(#w)"><path d="M1 9l4-8 4 8z" stroke="#c19600" stroke-width="2" stroke-linejoin="round"/><path d="M1 9l4-8 4 8z" fill="#f4bd00" stroke="#f5bd00" stroke-width="1.5" stroke-linejoin="round"/><path d="M3.75 2.75h2.5v2.5L5.75 7h-1.5l-.5-1.75v-2.5m0 5.25h2.5v1.25h-2.5" fill="#ad8601"/><mask id="w"><path transform="translate(-60)" d="M64 3h2v2.25L65.5 7h-1L64 5.25V3m0 5h2v1h-2"/><path fill="#fff" d="M0 0h10v10H0z"/></mask></g><g transform="translate(100 80)" mask="url(#x)"><path transform="translate(-80)" d="M85 0c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5" fill="url(#y)"/><path d="M.36 5C.36 7.56 2.44 9.64 5 9.64c2.56 0 4.64-2.08 4.64-4.64C9.64 2.44 7.56.36 5 .36 2.44.36.36 2.44.36 5" fill="#2a53cd"/><mask id="x"><path transform="translate(-80)" d="M83.93 2.14c-.03-.53.55-.97 1.06-.83.5.12.79.73.56 1.18-.2.44-.79.61-1.2.36a.812.812 0 0 1-.42-.71zm1.7 5.46h.67v.53h-2.89V7.6h.66V3.99h-.66v-.53h2.22V7.6z"/><path fill="#fff" d="M0 0h10v10H0z"/></mask></g><g transform="translate(100 60)" mask="url(#z)"><path transform="translate(-20)" d="M25 0c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5" fill="url(#A)"/><path d="M.36 5C.36 7.56 2.44 9.64 5 9.64c2.56 0 4.64-2.08 4.64-4.64C9.64 2.44 7.56.36 5 .36 2.44.36.36 2.44.36 5" fill="#eb3941"/><mask id="z"><path transform="translate(-20)" d="M23 3l4 4M27 3l-4 4" stroke="#000"/><path fill="#fff" d="M0 0h10v10H0z"/></mask></g><g><path d="M105.1 40.267a4.835 4.835 0 0 0-4.833 4.833 4.835 4.835 0 0 0 4.833 4.833 4.835 4.835 0 0 0 4.833-4.833 4.835 4.835 0 0 0-4.833-4.833zm0 1.45c.802 0 1.45.647 1.45 1.45 0 .802-.648 1.45-1.45 1.45-.802 0-1.45-.648-1.45-1.45 0-.803.648-1.45 1.45-1.45zm0 6.863a3.48 3.48 0 0 1-2.9-1.556c.014-.962 1.933-1.489 2.9-1.489.962 0 2.885.527 2.9 1.489a3.48 3.48 0 0 1-2.9 1.556z"/><path d="M99.3 39.3h11.6v11.6H99.3z" fill="none"/></g><path d="M105 22.528l-4 4.43.94 1.042 3.06-3.382L108.06 28l.94-1.041z"/><path d="M76.448 14.99h17.528v19.416H76.448z" fill="none"/><path d="M88.06 3.06L85 6.113 81.94 3.06 81 4l4 4 4-4z"/></svg>
\ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="110" height="110"><defs><linearGradient id="y" x1="113" x2="127" y1="104" y2="104" gradientTransform="translate(-.714 -69.286) scale(.71429)" gradientUnits="userSpaceOnUse" xlink:href="#a"/><linearGradient id="a"><stop stop-color="#606eda" offset="0"/><stop stop-color="#021db2" offset="1"/></linearGradient><linearGradient id="A" x2="24" gradientTransform="matrix(0 -.41667 -.41667 0 25 10)" gradientUnits="userSpaceOnUse" xlink:href="#b"/><linearGradient id="b"><stop stop-color="#d7687d" offset="0"/><stop stop-color="#b21402" offset="1"/></linearGradient></defs><path d="M0 20.995c0-.55.456-.995.995-.995h8.01c.55 0 .995.455.995.995v8.01c0 .549-.456.995-.995.995H.995C.445 30 0 29.544 0 29.004zm5.123 4.744C7.691 25.312 8.75 24.546 8.75 22h-1.5c0 1.62-.44 1.939-2.373 2.26-2.568.429-3.627 1.194-3.627 3.74h1.5c0-1.62.44-1.937 2.373-2.26zM23.65 27.21l-1.44-2.03L21 26.39 23.55 30 30 22.33 28.88 21z"/><path d="M6.5 46c0 .55.45 1 1 1s1-.45 1-1-.45-1-1-1-1 .45-1 1" fill="#bababa"/><path d="M5.75 42.75L2.25 46l3.5 3.25" fill="none" stroke="#bababa" stroke-width="1.5"/><path d="M27.5 42.43l-.93-.93L24 44.07l-2.57-2.57-.93.93L23.07 45l-2.57 2.57.93.93L24 45.93l2.57 2.57.93-.93L24.93 45l2.57-2.57z" fill-opacity=".24"/><path d="M27.5 41.93l-.93-.93L24 43.57 21.43 41l-.93.93 2.57 2.57-2.57 2.57.93.93L24 45.43 26.57 48l.93-.93-2.57-2.57 2.57-2.57z" fill="#676767"/><path d="M43.25 20c-.7 0-1.25.5-1.25 1.25v7.5c0 .7.5 1.25 1.25 1.25h3.5c.7 0 1.25-.5 1.25-1.25v-7.5c0-.7-.5-1.25-1.25-1.25zM43 21h4v7h-4zm2 7.25c.4 0 .75.3.75.75 0 .4-.3.75-.75.75-.4 0-.75-.3-.75-.75 0-.4.3-.75.75-.75z"/><g transform="translate(40 40)"><path transform="translate(-20)" d="M25 0c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5" fill="url(#c)"/><path d="M.36 5C.36 7.56 2.44 9.64 5 9.64c2.56 0 4.64-2.08 4.64-4.64C9.64 2.44 7.56.36 5 .36 2.44.36.36 2.44.36 5" fill="#eb3941"/><path d="M3 3l4 4M7 3L3 7" stroke="#fff"/><defs><linearGradient id="d"><stop stop-color="#d7687d" offset="0"/><stop stop-color="#b21402" offset="1"/></linearGradient><linearGradient id="c" x2="24" gradientTransform="matrix(0 -.41667 -.41667 0 25 10)" gradientUnits="userSpaceOnUse" xlink:href="#d"/></defs></g><path d="M4.5 61.3l4 3.7-4 3.7v-1.2H1.425l.075-5h3z" fill="#adf2ad" stroke="#007200"/><g transform="translate(20 60)"><path transform="translate(-140)" d="M144.95 10A5.002 5.002 0 0 1 140 4.95 5.002 5.002 0 0 1 145.05 0c2.76.03 4.98 2.29 4.95 5.05a5.002 5.002 0 0 1-5.05 4.95z" fill="url(#e)"/><path d="M9.5 5.05A4.494 4.494 0 0 1 4.95 9.5 4.494 4.494 0 0 1 .5 4.95 4.494 4.494 0 0 1 5.05.5C7.54.53 9.53 2.56 9.5 5.05z" fill="#00be00"/><path transform="translate(-140)" d="M145.08.53c1.97.02 3.55 1.06 3.54 2.32-.01 1.26-1.62 2.26-3.59 2.24-1.97-.02-3.55-1.06-3.54-2.32.01-1.26 1.62-2.26 3.59-2.24z" fill="url(#f)"/><path transform="translate(-140)" d="M144.98 9.41c1.66.02 3.01-.68 3.02-1.56.01-.88-1.33-1.61-2.98-1.63-1.66-.02-3.01.68-3.02 1.56-.01.88 1.33 1.61 2.98 1.63z" fill="url(#g)"/><defs><linearGradient id="h"><stop stop-color="#00d600" stop-opacity="0" offset="0"/><stop stop-color="#d8fc7b" stop-opacity=".81" offset="1"/></linearGradient><linearGradient id="i"><stop stop-color="#00ba00" offset="0"/><stop stop-color="#fff" stop-opacity=".91" offset="1"/></linearGradient><linearGradient id="j"><stop stop-color="#00a104" offset="0"/><stop stop-color="#00c605" offset="1"/></linearGradient><linearGradient id="g" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(-.0048 .4396 .78038 .00853 65.608 -94.834)" gradientUnits="userSpaceOnUse" xlink:href="#h"/><linearGradient id="f" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(.00687 -.62923 .9267 .01012 47.871 147.44)" gradientUnits="userSpaceOnUse" xlink:href="#i"/><linearGradient id="e" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(-.01507 1.3791 -1.3006 -.0142 282.66 -312.8)" gradientUnits="userSpaceOnUse" xlink:href="#j"/></defs></g><g transform="translate(40 60)"><path transform="translate(-80)" d="M85 0c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5" fill="url(#k)"/><path d="M.36 5C.36 7.56 2.44 9.64 5 9.64c2.56 0 4.64-2.08 4.64-4.64C9.64 2.44 7.56.36 5 .36 2.44.36.36 2.44.36 5" fill="#2a53cd"/><path d="M3.93 2.14c-.03-.53.55-.97 1.06-.83.5.12.79.73.56 1.18-.2.44-.79.61-1.2.36a.812.812 0 0 1-.42-.71zm1.7 5.46h.67v.53H3.41V7.6h.66V3.99h-.66v-.53h2.22V7.6z" fill="#fff"/><defs><linearGradient id="l"><stop stop-color="#606eda" offset="0"/><stop stop-color="#021db2" offset="1"/></linearGradient><linearGradient id="k" x1="113" x2="127" y1="104" y2="104" gradientTransform="translate(-.714 -69.286) scale(.71429)" gradientUnits="userSpaceOnUse" xlink:href="#l"/></defs></g><path d="M60.45 20.467v9.079h5.373l3.582-4.54-3.582-4.539z" fill="#698cfe" stroke="#4073f4" stroke-width=".908"/><path d="M60.45 40.467v9.08h5.372l3.581-4.54-3.581-4.54z" fill="#ef9d0d" stroke="#a36c01" stroke-width=".908"/><g transform="translate(60 60)"><path d="M5 10c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z" fill="#e5a600"/><path d="M9.5 5c0 2.49-2.01 4.5-4.5 4.5S.5 7.49.5 5 2.51.5 5 .5 9.5 2.51 9.5 5z" fill="#ffbd00"/><path transform="translate(-160)" d="M165.03.53c1.97 0 3.56 1.02 3.56 2.28 0 1.26-1.59 2.28-3.56 2.28s-3.56-1.02-3.56-2.28c0-1.26 1.59-2.28 3.56-2.28z" fill="url(#m)"/><path transform="translate(-160)" d="M164.99 9.42c1.66 0 3-.71 3-1.59 0-.88-1.34-1.59-3-1.59s-3 .71-3 1.59c0 .88 1.34 1.59 3 1.59z" fill="url(#n)"/><defs><linearGradient id="o"><stop stop-color="#ffa801" stop-opacity="0" offset="0"/><stop stop-color="#f0fb3d" offset="1"/></linearGradient><linearGradient id="p"><stop stop-color="#ffbd00" stop-opacity=".65" offset="0"/><stop stop-color="#fff" stop-opacity=".91" offset="1"/></linearGradient><linearGradient id="n" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(0 .43966 .78049 0 84.444 -93.924)" gradientUnits="userSpaceOnUse" xlink:href="#o"/><linearGradient id="m" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(0 -.62931 .92683 0 69.47 148.53)" gradientUnits="userSpaceOnUse" xlink:href="#p"/></defs></g><g transform="translate(0 80)"><path transform="translate(-120)" d="M125 10c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z" fill="url(#q)"/><path d="M9.5 5c0 2.49-2.01 4.5-4.5 4.5S.5 7.49.5 5 2.51.5 5 .5 9.5 2.51 9.5 5z" fill="#d00"/><path transform="translate(-120)" d="M125.03.53c1.97 0 3.56 1.02 3.56 2.28 0 1.26-1.59 2.28-3.56 2.28s-3.56-1.02-3.56-2.28c0-1.26 1.59-2.28 3.56-2.28z" fill="url(#r)"/><path transform="translate(-120)" d="M125.03 9.47c1.66 0 3-.71 3-1.59 0-.88-1.34-1.59-3-1.59s-3 .71-3 1.59c0 .88 1.34 1.59 3 1.59z" fill="url(#s)"/><defs><linearGradient id="t"><stop stop-color="red" stop-opacity="0" offset="0"/><stop stop-color="#f0cb68" stop-opacity=".71" offset="1"/></linearGradient><linearGradient id="u"><stop stop-color="#e60000" stop-opacity=".65" offset="0"/><stop stop-color="#fff" stop-opacity=".91" offset="1"/></linearGradient><linearGradient id="v"><stop stop-color="#a10000" offset="0"/><stop stop-color="#c60000" offset="1"/></linearGradient><linearGradient id="s" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(0 .43966 .78049 0 44.488 -93.88)" gradientUnits="userSpaceOnUse" xlink:href="#t"/><linearGradient id="r" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(0 -.62931 .92683 0 29.47 148.53)" gradientUnits="userSpaceOnUse" xlink:href="#u"/><linearGradient id="q" x1="227.88" x2="235.12" y1="103.16" y2="103.16" gradientTransform="matrix(0 1.3793 -1.3008 0 259.08 -314.35)" gradientUnits="userSpaceOnUse" xlink:href="#v"/></defs></g><path d="M20 80h10v10H20z" fill="none"/><path d="M27.5 82.5V80H20v7.5h2.5V90H30v-7.5zM21 81h5.5v5.5H21zm2.5 6.5h4v-4H29V89h-5.5z"/><path d="M23.5 87.5h4v-4H29V89h-5.5z" fill-opacity=".25"/><g fill="#acf2ae" stroke="#007200" stroke-width="2.577"><path transform="matrix(.29356 0 0 .2909 2.65 86.864)" d="M144.95 10A5.002 5.002 0 0 1 140 4.95 5.002 5.002 0 0 1 145.05 0c2.76.03 4.98 2.29 4.95 5.05a5.002 5.002 0 0 1-5.05 4.95z"/><path transform="matrix(.29356 0 0 .2909 2.65 86.864)" d="M149.5 5.05a4.494 4.494 0 0 1-4.55 4.45 4.494 4.494 0 0 1-4.45-4.55A4.494 4.494 0 0 1 145.05.5c2.49.03 4.48 2.06 4.45 4.55z"/></g><path d="M48.313 82.5L45.21 86l-3.102-3.5h1.24v-1.92h3.723v1.92z" fill="#adf2ad" stroke="#007200"/><path d="M66.537 88.514a1.314 1.314 0 0 1-1.335 1.295 1.313 1.313 0 0 1-1.306-1.324 1.314 1.314 0 0 1 1.335-1.294c.731.009 1.315.6 1.307 1.323z" fill="#acf2ae" stroke="#007200" stroke-width=".753"/><path d="M62.108 83.5l3.102-2.982 3.102 2.982h-1.24v2h-3.723v-2z" fill="#adf2ad" stroke="#007200"/><path d="M83.25 21.75l3.5 3.25-3.5 3.25" fill="none" stroke="#367cf1" stroke-width="1.5"/><path d="M86 40l-5 5 5 5v-2h3v-6h-3zM84 60l5 5-5 5.022v-2.045L81 68v-6h3z" fill="#4688f1"/><path d="M84.5 88l3.5-6h-7M7 104.5L2 101v7M24 100l4 7h-8"/><path d="M43.25 102.75l3.5 3.25-3.5 3.25" fill="none" stroke="#939393" stroke-width="1.5"/><path d="M61 109l4-8 4 8z" stroke="#c19600" stroke-width="2" stroke-linejoin="round"/><path d="M61 109l4-8 4 8z" fill="#f4bd00" stroke="#f5bd00" stroke-width="1.5" stroke-linejoin="round"/><path d="M63.75 102.75h2.5v2.5l-.5 1.75h-1.5l-.5-1.75v-2.5m0 5.25h2.5v1.25h-2.5" fill="#ad8601"/><path d="M64 103h2v2.25l-.5 1.75h-1l-.5-1.75V103m0 5h2v1h-2" fill="#fff"/><text style="line-height:0%" x="3.051" y="118.387" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="3.051" y="118.387" style="line-height:1.25" font-size="8">a</tspan></text><text style="line-height:0%" x="23.051" y="118.387" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="23.051" y="118.387" style="line-height:1.25" font-size="8">b</tspan></text><text style="line-height:0%" x="43.051" y="118.387" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="43.051" y="118.387" style="line-height:1.25" font-size="8">c</tspan></text><text style="line-height:0%" x="63.051" y="118.387" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="63.051" y="118.387" style="line-height:1.25" font-size="8">d</tspan></text><text style="line-height:0%" x="83.051" y="118.387" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="83.051" y="118.387" style="line-height:1.25" font-size="8">e</tspan></text><text style="line-height:0%" x="-7.026" y="107.818" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-7.026" y="107.818" style="line-height:1.25" font-size="8">1</tspan></text><text style="line-height:0%" x="-6.819" y="87.88" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-6.819" y="87.88" style="line-height:1.25" font-size="8">2</tspan></text><text style="line-height:0%" x="-6.756" y="67.992" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-6.756" y="67.992" style="line-height:1.25" font-size="8">3</tspan></text><text style="line-height:0%" x="-6.917" y="47.994" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-6.917" y="47.994" style="line-height:1.25" font-size="8">4</tspan></text><text style="line-height:0%" x="-7.108" y="28.056" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-7.108" y="28.056" style="line-height:1.25" font-size="8">5</tspan></text><circle cx="3" cy="3" r="2.5" transform="matrix(1.13208 0 0 1.13208 81.604 102.604)" fill="#00bcd4" stroke="#000" stroke-width=".3"/><path d="M5 0a5 5 0 1 0 0 10A5 5 0 0 0 5 0zm.048.721c1.083 0 2.179.4 3.005 1.226a4.234 4.234 0 0 1 0 5.986L5.048 4.952l-2.98-3.005A4.18 4.18 0 0 1 5.047.721z"/><text style="line-height:0%" x="-6.68" y="8" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="-6.68" y="8" style="line-height:1.25" font-size="8">6</tspan></text><path d="M17.601-2.913h16.232v16.232H17.601z" fill="none"/><path d="M21.11 5.556L20 6.667 23.334 10 30 3.334l-1.11-1.111-5.556 5.555z" fill-rule="evenodd"/><path d="M44.954 8.42a3.467 3.467 0 0 1-3.462-3.46c0-.678.2-1.309.531-1.84l4.77 4.77c-.531.338-1.162.53-1.84.53m3.462-3.46c0 .676-.2 1.307-.53 1.838l-4.77-4.77a3.405 3.405 0 0 1 1.839-.53 3.467 3.467 0 0 1 3.461 3.461M45 .005a5 5 0 1 0 0 10 5 5 0 0 0 0-10"/><path d="M68.875 2.219L63.344 7.78l-.407-.406L61.844 8.5l1.5 1.5L70 3.344l-1.125-1.125z" fill-rule="evenodd"/><text style="line-height:0%" x="103.739" y="118.482" font-weight="400" font-family="sans-serif" letter-spacing="0" word-spacing="0" fill="#ccc"><tspan x="103.739" y="118.482" style="line-height:1.25" font-size="8">f</tspan></text><g transform="translate(100 100)" mask="url(#w)"><path d="M1 9l4-8 4 8z" stroke="#c19600" stroke-width="2" stroke-linejoin="round"/><path d="M1 9l4-8 4 8z" fill="#f4bd00" stroke="#f5bd00" stroke-width="1.5" stroke-linejoin="round"/><path d="M3.75 2.75h2.5v2.5L5.75 7h-1.5l-.5-1.75v-2.5m0 5.25h2.5v1.25h-2.5" fill="#ad8601"/><mask id="w"><path fill="#fff" d="M0 0h10v10H0z"/><path transform="translate(-60)" d="M64 3h2v2.25L65.5 7h-1L64 5.25V3m0 5h2v1h-2"/></mask></g><g transform="translate(100 80)" mask="url(#x)"><path transform="translate(-80)" d="M85 0c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5" fill="url(#y)"/><path d="M.36 5C.36 7.56 2.44 9.64 5 9.64c2.56 0 4.64-2.08 4.64-4.64C9.64 2.44 7.56.36 5 .36 2.44.36.36 2.44.36 5" fill="#2a53cd"/><mask id="x"><path fill="#fff" d="M0 0h10v10H0z"/><path transform="translate(-80)" d="M83.93 2.14c-.03-.53.55-.97 1.06-.83.5.12.79.73.56 1.18-.2.44-.79.61-1.2.36a.812.812 0 0 1-.42-.71zm1.7 5.46h.67v.53h-2.89V7.6h.66V3.99h-.66v-.53h2.22V7.6z"/></mask></g><g transform="translate(100 60)" mask="url(#z)"><path transform="translate(-20)" d="M25 0c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5" fill="url(#A)"/><path d="M.36 5C.36 7.56 2.44 9.64 5 9.64c2.56 0 4.64-2.08 4.64-4.64C9.64 2.44 7.56.36 5 .36 2.44.36.36 2.44.36 5" fill="#eb3941"/><mask id="z"><path fill="#fff" d="M0 0h10v10H0z"/><path transform="translate(-20)" d="M23 3l4 4M27 3l-4 4" stroke="#000"/></mask></g><g><path d="M105.1 40.267a4.835 4.835 0 0 0-4.833 4.833 4.835 4.835 0 0 0 4.833 4.833 4.835 4.835 0 0 0 4.833-4.833 4.835 4.835 0 0 0-4.833-4.833zm0 1.45c.802 0 1.45.647 1.45 1.45 0 .802-.648 1.45-1.45 1.45-.802 0-1.45-.648-1.45-1.45 0-.803.648-1.45 1.45-1.45zm0 6.863a3.48 3.48 0 0 1-2.9-1.556c.014-.962 1.933-1.489 2.9-1.489.962 0 2.885.527 2.9 1.489a3.48 3.48 0 0 1-2.9 1.556z"/><path d="M99.3 39.3h11.6v11.6H99.3z" fill="none"/></g><path d="M105 22.528l-4 4.43.94 1.042 3.06-3.382L108.06 28l.94-1.041z"/><path d="M76.448 14.99h17.528v19.416H76.448z" fill="none"/><path d="M88.06 3.06L85 6.113 81.94 3.06 81 4l4 4 4-4z"/></svg>
\ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/Images/src/mediumIcons.svg b/third_party/blink/renderer/devtools/front_end/Images/src/mediumIcons.svg
index 02c7356..53230f4 100644
--- a/third_party/blink/renderer/devtools/front_end/Images/src/mediumIcons.svg
+++ b/third_party/blink/renderer/devtools/front_end/Images/src/mediumIcons.svg
@@ -518,12 +518,6 @@
        style="fill:#ad8601" />
     <mask
        id="path4453-6-mask">
-      <path
-         transform="translate(-60)"
-         d="m 64,3 h 2 V 5.25 L 65.5,7 h -1 L 64,5.25 V 3 m 0,5 h 2 v 1 h -2"
-         id="path4453-6"
-         inkscape:connector-curvature="0"
-         style="fill:#000000" />
       <rect
          width="10"
          height="10"
@@ -531,6 +525,12 @@
          id="rect8990"
          x="0"
          y="0" />
+      <path
+         transform="translate(-60)"
+         d="m 64,3 h 2 V 5.25 L 65.5,7 h -1 L 64,5.25 V 3 m 0,5 h 2 v 1 h -2"
+         id="path4453-6"
+         inkscape:connector-curvature="0"
+         style="fill:#000000" />
     </mask>
   </g>
   <g
@@ -551,12 +551,6 @@
        style="fill:#2a53cd" />
     <mask
        id="path4287-3-mask">
-      <path
-         transform="translate(-80)"
-         d="m 83.93,2.14 c -0.03,-0.53 0.55,-0.97 1.06,-0.83 0.5,0.12 0.79,0.73 0.56,1.18 -0.2,0.44 -0.79,0.61 -1.2,0.36 C 84.09,2.71 83.93,2.43 83.93,2.14 Z m 1.7,5.46 H 86.3 V 8.13 H 83.41 V 7.6 h 0.66 V 3.99 H 83.41 V 3.46 h 2.22 z"
-         id="path4287-3"
-         inkscape:connector-curvature="0"
-         style="fill:#000000" />
       <rect
          width="10"
          height="10"
@@ -564,6 +558,12 @@
          id="rect8997"
          x="0"
          y="0" />
+      <path
+         transform="translate(-80)"
+         d="m 83.93,2.14 c -0.03,-0.53 0.55,-0.97 1.06,-0.83 0.5,0.12 0.79,0.73 0.56,1.18 -0.2,0.44 -0.79,0.61 -1.2,0.36 C 84.09,2.71 83.93,2.43 83.93,2.14 Z m 1.7,5.46 H 86.3 V 8.13 H 83.41 V 7.6 h 0.66 V 3.99 H 83.41 V 3.46 h 2.22 z"
+         id="path4287-3"
+         inkscape:connector-curvature="0"
+         style="fill:#000000" />
     </mask>
     <defs
        id="defs4289-6">
@@ -607,6 +607,13 @@
        style="fill:#eb3941" />
     <mask
        id="path4229-9-path4231-2-mask">
+      <rect
+         width="10"
+         height="10"
+         style="fill:#ffffff"
+         id="rect9010"
+         x="0"
+         y="0" />
       <path
          transform="translate(-20)"
          d="m 23,3 4,4"
@@ -619,13 +626,6 @@
          id="path4231-2"
          inkscape:connector-curvature="0"
          style="stroke:#000000" />
-      <rect
-         width="10"
-         height="10"
-         style="fill:#ffffff"
-         id="rect9010"
-         x="0"
-         y="0" />
     </mask>
     <defs
        id="defs4233-0">
diff --git a/third_party/blink/renderer/devtools/front_end/Images/src/optimize_svg.hashes b/third_party/blink/renderer/devtools/front_end/Images/src/optimize_svg.hashes
index b211ce4..6a00d835 100644
--- a/third_party/blink/renderer/devtools/front_end/Images/src/optimize_svg.hashes
+++ b/third_party/blink/renderer/devtools/front_end/Images/src/optimize_svg.hashes
@@ -4,12 +4,12 @@
     "breakpointConditional.svg": "4cf90210b2af2ed84db2f60b07bcde28",
     "checkboxCheckmark.svg": "f039bf85cee42ad5c30ca3bfdce7912a",
     "errorWave.svg": "e183fa242a22ed4784a92f6becbc2c45",
-    "smallIcons.svg": "40aefe4606ebba939725954ff9f908ef",
-    "mediumIcons.svg": "e2878b1c2a8e27c52d146c8942a153cb",
+    "smallIcons.svg": "19940dda6f171380bfd7d04d0061b44c",
+    "mediumIcons.svg": "81ec104f4ca13f18d1389883e2f771c8",
     "breakpoint.svg": "69cd92d807259c022791112809b97799",
     "treeoutlineTriangles.svg": "2d26ab85d919f83d5021f2f385dffd0b",
     "largeIcons.svg": "faf26930e93e7525a3cbcc595527662c",
     "chevrons.svg": "79b4b527771e30b6388ce664077b3409",
     "audits_logo.svg": "3a4893bd2ef5bb233e924f15e51af69a",
-    "accelerometer-front.svg": "536ad784f667f32b2f3a94b6cce9e217"
+    "accelerometer-front.svg": "a4dcdac47131aa923346c15e01bc644a"
 }
\ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/Images/src/smallIcons.svg b/third_party/blink/renderer/devtools/front_end/Images/src/smallIcons.svg
index 6b36da94..ab48f666 100644
--- a/third_party/blink/renderer/devtools/front_end/Images/src/smallIcons.svg
+++ b/third_party/blink/renderer/devtools/front_end/Images/src/smallIcons.svg
@@ -893,17 +893,17 @@
        style="fill:#ad8601" />
     <mask
        id="path4453-6-mask">
+      <rect
+         width="10"
+         height="10"
+         style="fill:#ffffff"
+         id="rect8990" />
       <path
          transform="translate(-60,0)"
          d="m 64,3 h 2 V 5.25 L 65.5,7 h -1 L 64,5.25 V 3 m 0,5 h 2 v 1 h -2"
          id="path4453-6"
          inkscape:connector-curvature="0"
          style="fill:#000000" />
-      <rect
-         width="10"
-         height="10"
-         style="fill:#ffffff"
-         id="rect8990" />
     </mask>
   </g>
   <g
@@ -924,17 +924,17 @@
        style="fill:#2a53cd" />
     <mask
        id="path4287-3-mask">
+      <rect
+         width="10"
+         height="10"
+         style="fill:#ffffff"
+         id="rect8997" />
       <path
          transform="translate(-80,0)"
          d="m 83.93,2.14 c -0.03,-0.53 0.55,-0.97 1.06,-0.83 0.5,0.12 0.79,0.73 0.56,1.18 -0.2,0.44 -0.79,0.61 -1.2,0.36 C 84.09,2.71 83.93,2.43 83.93,2.14 z m 1.7,5.46 H 86.3 V 8.13 H 83.41 V 7.6 h 0.66 V 3.99 H 83.41 V 3.46 h 2.22 V 7.6 z"
          id="path4287-3"
          inkscape:connector-curvature="0"
          style="fill:#000000" />
-      <rect
-         width="10"
-         height="10"
-         style="fill:#ffffff"
-         id="rect8997" />
     </mask>
     <defs
        id="defs4289-6">
@@ -978,6 +978,11 @@
        style="fill:#eb3941" />
     <mask
        id="path4229-9-path4231-2-mask">
+      <rect
+         width="10"
+         height="10"
+         style="fill:#ffffff"
+         id="rect9010" />
       <path
          transform="translate(-20,0)"
          d="m 23,3 4,4"
@@ -990,11 +995,6 @@
          id="path4231-2"
          inkscape:connector-curvature="0"
          style="stroke:#000000" />
-      <rect
-         width="10"
-         height="10"
-         style="fill:#ffffff"
-         id="rect9010" />
     </mask>
     <defs
        id="defs4233-0">
diff --git a/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js b/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js
index fba0085..d67fe2d 100644
--- a/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js
+++ b/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js
@@ -726,8 +726,6 @@
       case recordTypes.StyleRecalcInvalidationTracking:
       case recordTypes.StyleInvalidatorInvalidationTracking:
       case recordTypes.LayoutInvalidationTracking:
-      case recordTypes.LayerInvalidationTracking:
-      case recordTypes.PaintInvalidationTracking:
         this._invalidationTracker.addInvalidation(new TimelineModel.InvalidationTrackingEvent(event));
         break;
 
@@ -1210,8 +1208,6 @@
   StyleRecalcInvalidationTracking: 'StyleRecalcInvalidationTracking',
   StyleInvalidatorInvalidationTracking: 'StyleInvalidatorInvalidationTracking',
   LayoutInvalidationTracking: 'LayoutInvalidationTracking',
-  LayerInvalidationTracking: 'LayerInvalidationTracking',
-  PaintInvalidationTracking: 'PaintInvalidationTracking',
 
   ParseHTML: 'ParseHTML',
   ParseAuthorStyleSheet: 'ParseAuthorStyleSheet',
@@ -1593,8 +1589,6 @@
     /** @type {?string} */
     this.nodeName = eventData['nodeName'];
     /** @type {?number} */
-    this.paintId = eventData['paintId'];
-    /** @type {?number} */
     this.invalidationSet = eventData['invalidationSet'];
     /** @type {?string} */
     this.invalidatedSelectorId = eventData['invalidatedSelectorId'];
@@ -1649,24 +1643,13 @@
   addInvalidation(invalidation) {
     this._startNewFrameIfNeeded();
 
-    if (!invalidation.nodeId && !invalidation.paintId) {
+    if (!invalidation.nodeId) {
       console.error('Invalidation lacks node information.');
       console.error(invalidation);
       return;
     }
 
-    // PaintInvalidationTracking events provide a paintId and a nodeId which
-    // we can use to update the paintId for all other invalidation tracking
-    // events.
     const recordTypes = TimelineModel.TimelineModel.RecordType;
-    if (invalidation.type === recordTypes.PaintInvalidationTracking && invalidation.nodeId) {
-      const invalidations = this._invalidationsByNodeId[invalidation.nodeId] || [];
-      for (let i = 0; i < invalidations.length; ++i)
-        invalidations[i].paintId = invalidation.paintId;
-
-      // PaintInvalidationTracking is only used for updating paintIds.
-      return;
-    }
 
     // Suppress StyleInvalidator StyleRecalcInvalidationTracking invalidations because they
     // will be handled by StyleInvalidatorInvalidationTracking.
@@ -1812,28 +1795,6 @@
    */
   didPaint(paintEvent) {
     this._didPaint = true;
-
-    // If a paint doesn't have a corresponding graphics layer id, it paints
-    // into its parent so add an effectivePaintId to these events.
-    const layerId = paintEvent.args['data']['layerId'];
-    if (layerId)
-      this._lastPaintWithLayer = paintEvent;
-    // Quietly discard top-level paints without layerId, as these are likely
-    // to come from overlay.
-    if (!this._lastPaintWithLayer)
-      return;
-
-    const effectivePaintId = this._lastPaintWithLayer.args['data']['nodeId'];
-    const paintFrameId = paintEvent.args['data']['frame'];
-    const types = [
-      TimelineModel.TimelineModel.RecordType.StyleRecalcInvalidationTracking,
-      TimelineModel.TimelineModel.RecordType.LayoutInvalidationTracking,
-      TimelineModel.TimelineModel.RecordType.PaintInvalidationTracking
-    ];
-    for (const invalidation of this._invalidationsOfTypes(types)) {
-      if (invalidation.paintId === effectivePaintId)
-        this._addInvalidationToEvent(paintEvent, paintFrameId, invalidation);
-    }
   }
 
   /**
diff --git a/third_party/blink/renderer/modules/csspaint/css_paint_image_generator_impl.cc b/third_party/blink/renderer/modules/csspaint/css_paint_image_generator_impl.cc
index 46543be..4b8fe31 100644
--- a/third_party/blink/renderer/modules/csspaint/css_paint_image_generator_impl.cc
+++ b/third_party/blink/renderer/modules/csspaint/css_paint_image_generator_impl.cc
@@ -59,7 +59,7 @@
 }
 
 bool CSSPaintImageGeneratorImpl::HasDocumentDefinition() const {
-  return paint_worklet_->GetDocumentDefinitionMap().Contains(name_);
+  return paint_worklet_->GetDocumentDefinitionMap().at(name_);
 }
 
 bool CSSPaintImageGeneratorImpl::GetValidDocumentDefinition(
@@ -77,8 +77,8 @@
     DCHECK(definition);
     return true;
   }
-  if (definition && definition->GetRegisteredDefinitionCount() !=
-                        PaintWorklet::kNumGlobalScopesPerThread) {
+  if (definition->GetRegisteredDefinitionCount() !=
+      PaintWorklet::kNumGlobalScopesPerThread) {
     definition = nullptr;
     return false;
   }
@@ -91,8 +91,6 @@
     return 0;
   DocumentPaintDefinition* definition =
       paint_worklet_->GetDocumentDefinitionMap().at(name_);
-  if (!definition)
-    return 0;
   return definition->GetRegisteredDefinitionCount();
 }
 
diff --git a/third_party/blink/renderer/modules/filesystem/dom_file_system.cc b/third_party/blink/renderer/modules/filesystem/dom_file_system.cc
index 54ff95f6..10156fe 100644
--- a/third_party/blink/renderer/modules/filesystem/dom_file_system.cc
+++ b/third_party/blink/renderer/modules/filesystem/dom_file_system.cc
@@ -34,7 +34,6 @@
 
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_security_origin.h"
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/core/probe/core_probes.h"
 #include "third_party/blink/renderer/modules/filesystem/directory_entry.h"
 #include "third_party/blink/renderer/modules/filesystem/dom_file_path.h"
@@ -53,7 +52,7 @@
 
 void RunCallback(ExecutionContext* execution_context,
                  base::OnceClosure task,
-                 std::unique_ptr<probe::AsyncTaskId> identifier) {
+                 std::unique_ptr<int> identifier) {
   if (!execution_context)
     return;
   DCHECK(execution_context->IsContextThread());
@@ -167,8 +166,7 @@
 
   DCHECK(execution_context->IsContextThread());
 
-  std::unique_ptr<probe::AsyncTaskId> identifier =
-      std::make_unique<probe::AsyncTaskId>();
+  std::unique_ptr<int> identifier = std::make_unique<int>(0);
   probe::AsyncTaskScheduled(execution_context, TaskNameForInstrumentation(),
                             identifier.get());
   execution_context->GetTaskRunner(TaskType::kFileReading)
diff --git a/third_party/blink/renderer/modules/filesystem/file_writer.cc b/third_party/blink/renderer/modules/filesystem/file_writer.cc
index 0d0259e6..c91f83f 100644
--- a/third_party/blink/renderer/modules/filesystem/file_writer.cc
+++ b/third_party/blink/renderer/modules/filesystem/file_writer.cc
@@ -255,8 +255,7 @@
 }
 
 void FileWriter::DoOperation(Operation operation) {
-  probe::AsyncTaskScheduled(GetExecutionContext(), "FileWriter",
-                            &async_task_id_);
+  probe::AsyncTaskScheduled(GetExecutionContext(), "FileWriter", this);
   switch (operation) {
     case kOperationWrite:
       DCHECK_EQ(kOperationNone, operation_in_progress_);
@@ -306,11 +305,11 @@
   }
   FireEvent(event_type_names::kWriteend);
 
-  probe::AsyncTaskCanceled(GetExecutionContext(), &async_task_id_);
+  probe::AsyncTaskCanceled(GetExecutionContext(), this);
 }
 
 void FileWriter::FireEvent(const AtomicString& type) {
-  probe::AsyncTask async_task(GetExecutionContext(), &async_task_id_);
+  probe::AsyncTask async_task(GetExecutionContext(), this);
   ++recursion_depth_;
   DispatchEvent(
       *ProgressEvent::Create(type, true, bytes_written_, bytes_to_write_));
diff --git a/third_party/blink/renderer/modules/filesystem/file_writer.h b/third_party/blink/renderer/modules/filesystem/file_writer.h
index 89f6b8b..adb3dbc 100644
--- a/third_party/blink/renderer/modules/filesystem/file_writer.h
+++ b/third_party/blink/renderer/modules/filesystem/file_writer.h
@@ -34,7 +34,6 @@
 #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
 #include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/modules/event_target_modules.h"
 #include "third_party/blink/renderer/modules/filesystem/file_writer_base.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
@@ -131,7 +130,6 @@
   double last_progress_notification_time_ms_;
   Member<Blob> blob_being_written_;
   int request_id_;
-  probe::AsyncTaskId async_task_id_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_factory.cc b/third_party/blink/renderer/modules/indexeddb/idb_factory.cc
index b4b93bcb..0608709 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_factory.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_factory.cc
@@ -41,7 +41,6 @@
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/core/probe/core_probes.h"
 #include "third_party/blink/renderer/modules/indexed_db_names.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_database.h"
@@ -74,14 +73,13 @@
       : promise_resolver_(promise_resolver) {
     probe::AsyncTaskScheduled(
         ExecutionContext::From(promise_resolver_->GetScriptState()),
-        indexed_db_names::kIndexedDB, &async_task_id_);
+        indexed_db_names::kIndexedDB, this);
   }
 
   ~WebIDBGetDBNamesCallbacksImpl() override {
     if (promise_resolver_) {
       probe::AsyncTaskCanceled(
-          ExecutionContext::From(promise_resolver_->GetScriptState()),
-          &async_task_id_);
+          ExecutionContext::From(promise_resolver_->GetScriptState()), this);
       promise_resolver_->Reject(MakeGarbageCollected<DOMException>(
           DOMExceptionCode::kUnknownError,
           "An unexpected shutdown occured before the "
@@ -97,8 +95,8 @@
       return;
 
     probe::AsyncTask async_task(
-        ExecutionContext::From(promise_resolver_->GetScriptState()),
-        &async_task_id_, "error");
+        ExecutionContext::From(promise_resolver_->GetScriptState()), this,
+        "error");
     promise_resolver_->Reject(MakeGarbageCollected<DOMException>(
         DOMExceptionCode::kUnknownError,
         "The databases() promise was rejected."));
@@ -123,8 +121,8 @@
     }
 
     probe::AsyncTask async_task(
-        ExecutionContext::From(promise_resolver_->GetScriptState()),
-        &async_task_id_, "success");
+        ExecutionContext::From(promise_resolver_->GetScriptState()), this,
+        "success");
     promise_resolver_->Resolve(name_and_version_list);
     promise_resolver_.Clear();
   }
@@ -185,7 +183,6 @@
   void DetachRequestFromCallback() override { NOTREACHED(); }
 
  private:
-  probe::AsyncTaskId async_task_id_;
   Persistent<ScriptPromiseResolver> promise_resolver_;
 };
 
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_metadata.cc b/third_party/blink/renderer/modules/indexeddb/idb_metadata.cc
index 0f7f8d8..6f54902a 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_metadata.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_metadata.cc
@@ -68,17 +68,20 @@
 IDBDatabaseMetadata::IDBDatabaseMetadata(const String& name,
                                          int64_t id,
                                          int64_t version,
-                                         int64_t max_object_store_id)
+                                         int64_t max_object_store_id,
+                                         bool was_cold_open)
     : name(name),
       id(id),
       version(version),
-      max_object_store_id(max_object_store_id) {}
+      max_object_store_id(max_object_store_id),
+      was_cold_open(was_cold_open) {}
 
 void IDBDatabaseMetadata::CopyFrom(const IDBDatabaseMetadata& metadata) {
   name = metadata.name;
   id = metadata.id;
   version = metadata.version;
   max_object_store_id = metadata.max_object_store_id;
+  was_cold_open = metadata.was_cold_open;
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_metadata.h b/third_party/blink/renderer/modules/indexeddb/idb_metadata.h
index 8425d65..acbb4132 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_metadata.h
+++ b/third_party/blink/renderer/modules/indexeddb/idb_metadata.h
@@ -104,7 +104,8 @@
   IDBDatabaseMetadata(const String& name,
                       int64_t id,
                       int64_t version,
-                      int64_t max_object_store_id);
+                      int64_t max_object_store_id,
+                      bool was_cold_open);
 
   // Overwrites the database metadata, but does not change the object store and
   // index metadata.
@@ -115,6 +116,7 @@
   int64_t version;
   int64_t max_object_store_id;
   HashMap<int64_t, scoped_refptr<IDBObjectStoreMetadata>> object_stores;
+  bool was_cold_open;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.cc b/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.cc
index 49f2838..2ec51b0d 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.cc
+++ b/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.cc
@@ -37,6 +37,7 @@
 #include "third_party/blink/renderer/modules/indexeddb/idb_tracing.h"
 #include "third_party/blink/renderer/modules/indexeddb/idb_version_change_event.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/histogram.h"
 
 namespace blink {
 
@@ -54,7 +55,8 @@
       database_callbacks_(callbacks),
       transaction_backend_(std::move(transaction_backend)),
       transaction_id_(transaction_id),
-      version_(version) {
+      version_(version),
+      start_time_(WTF::Time::Now()) {
   DCHECK(!ResultAsAny());
 }
 
@@ -111,7 +113,8 @@
     old_version = IDBDatabaseMetadata::kDefaultVersion;
   }
   IDBDatabaseMetadata old_database_metadata(
-      metadata.name, metadata.id, old_version, metadata.max_object_store_id);
+      metadata.name, metadata.id, old_version, metadata.max_object_store_id,
+      metadata.was_cold_open);
 
   transaction_ = IDBTransaction::CreateVersionChange(
       GetExecutionContext(), std::move(transaction_backend_), transaction_id_,
@@ -188,6 +191,22 @@
     return DispatchEventResult::kCanceledBeforeDispatch;
   }
 
+  if (!open_time_recorded_ &&
+      (event.type() == event_type_names::kSuccess ||
+       event.type() == event_type_names::kUpgradeneeded) &&
+      ResultAsAny()->GetType() == IDBAny::kIDBDatabaseType) {
+    // Note: The result type is checked because this request type is also used
+    // for calls to DeleteDatabase, which sets the result to undefined (see
+    // EnqueueResponse(int64_t) above).
+    open_time_recorded_ = true;
+    IDBDatabase* idb_database = ResultAsAny()->IdbDatabase();
+    WTF::TimeDelta time_diff = base::Time::Now() - start_time_;
+    if (idb_database->Metadata().was_cold_open)
+      UMA_HISTOGRAM_MEDIUM_TIMES("WebCore.IndexedDB.OpenTime.Cold", time_diff);
+    else
+      UMA_HISTOGRAM_MEDIUM_TIMES("WebCore.IndexedDB.OpenTime.Warm", time_diff);
+  }
+
   return IDBRequest::DispatchEventInternal(event);
 }
 
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.h b/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.h
index 57fa3f5..77e5fd7 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.h
+++ b/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.h
@@ -27,9 +27,11 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_IDB_OPEN_DB_REQUEST_H_
 
 #include <memory>
+
 #include "third_party/blink/renderer/modules/indexeddb/idb_request.h"
 #include "third_party/blink/renderer/modules/indexeddb/web_idb_database.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/wtf/time.h"
 
 namespace blink {
 
@@ -80,6 +82,9 @@
   std::unique_ptr<WebIDBTransaction> transaction_backend_;
   const int64_t transaction_id_;
   int64_t version_;
+
+  WTF::Time start_time_;
+  bool open_time_recorded_ = false;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc
index 7839741..df898d69 100644
--- a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc
+++ b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc
@@ -45,6 +45,7 @@
     DCHECK(!out->object_stores.Contains(key));
     out->object_stores.insert(key, object_store);
   }
+  out->was_cold_open = data.was_cold_open();
   return true;
 }
 
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.h b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.h
index 6cc540b..44cd49e 100644
--- a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.h
+++ b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.h
@@ -37,6 +37,9 @@
   object_stores(const blink::IDBDatabaseMetadata& metadata) {
     return metadata.object_stores;
   }
+  static bool was_cold_open(const blink::IDBDatabaseMetadata& metadata) {
+    return metadata.was_cold_open;
+  }
   static bool Read(blink::mojom::IDBDatabaseMetadataDataView data,
                    blink::IDBDatabaseMetadata* out);
 };
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc b/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc
index 642ade68..ee2025c8 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc
+++ b/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc
@@ -72,7 +72,7 @@
   task_runner_ =
       request_->GetExecutionContext()->GetTaskRunner(TaskType::kDatabaseAccess);
   probe::AsyncTaskScheduled(request_->GetExecutionContext(),
-                            indexed_db_names::kIndexedDB, &async_task_id_);
+                            indexed_db_names::kIndexedDB, this);
 }
 
 WebIDBCallbacksImpl::~WebIDBCallbacksImpl() {
@@ -86,7 +86,7 @@
 
 void WebIDBCallbacksImpl::DetachCallbackFromRequest() {
   if (request_) {
-    probe::AsyncTaskCanceled(request_->GetExecutionContext(), &async_task_id_);
+    probe::AsyncTaskCanceled(request_->GetExecutionContext(), this);
 #if DCHECK_IS_ON()
     DCHECK_EQ(static_cast<WebIDBCallbacks*>(this), request_->WebCallbacks());
 #endif  // DCHECK_IS_ON()
@@ -117,8 +117,7 @@
     return;
   }
 
-  probe::AsyncTask async_task(request_->GetExecutionContext(), &async_task_id_,
-                              "error");
+  probe::AsyncTask async_task(request_->GetExecutionContext(), this, "error");
   IDBRequest* request = request_.Get();
   Detach();
   request->HandleResponse(MakeGarbageCollected<DOMException>(
@@ -135,8 +134,7 @@
   if (!request_)
     return;
 
-  probe::AsyncTask async_task(request_->GetExecutionContext(), &async_task_id_,
-                              "success");
+  probe::AsyncTask async_task(request_->GetExecutionContext(), this, "success");
 #if DCHECK_IS_ON()
   DCHECK(!request_->TransactionHasQueuedResults());
 #endif  // DCHECK_IS_ON()
@@ -164,8 +162,7 @@
   }
   DCHECK(value);
 
-  probe::AsyncTask async_task(request_->GetExecutionContext(), &async_task_id_,
-                              "success");
+  probe::AsyncTask async_task(request_->GetExecutionContext(), this, "success");
   value->SetIsolate(request_->GetIsolate());
   IDBRequest* request = request_.Get();
   Detach();
@@ -194,8 +191,8 @@
                                               task_runner_);
   }
   if (request_) {
-    probe::AsyncTask async_task(request_->GetExecutionContext(),
-                                &async_task_id_, "success");
+    probe::AsyncTask async_task(request_->GetExecutionContext(), this,
+                                "success");
 #if DCHECK_IS_ON()
     DCHECK(!request_->TransactionHasQueuedResults());
 #endif  // DCHECK_IS_ON()
@@ -211,8 +208,7 @@
   if (!request_)
     return;
 
-  probe::AsyncTask async_task(request_->GetExecutionContext(), &async_task_id_,
-                              "success");
+  probe::AsyncTask async_task(request_->GetExecutionContext(), this, "success");
   IDBRequest* request = request_.Get();
   Detach();
   request->HandleResponse(std::move(key));
@@ -224,8 +220,7 @@
     return;
 
   std::unique_ptr<IDBValue> value = ConvertReturnValue(return_value);
-  probe::AsyncTask async_task(request_->GetExecutionContext(), &async_task_id_,
-                              "success");
+  probe::AsyncTask async_task(request_->GetExecutionContext(), this, "success");
   value->SetIsolate(request_->GetIsolate());
   IDBRequest* request = request_.Get();
   Detach();
@@ -237,8 +232,7 @@
   if (!request_)
     return;
 
-  probe::AsyncTask async_task(request_->GetExecutionContext(), &async_task_id_,
-                              "success");
+  probe::AsyncTask async_task(request_->GetExecutionContext(), this, "success");
   Vector<std::unique_ptr<IDBValue>> idb_values;
   idb_values.ReserveInitialCapacity(values.size());
   for (const mojom::blink::IDBReturnValuePtr& value : values) {
@@ -255,8 +249,7 @@
   if (!request_)
     return;
 
-  probe::AsyncTask async_task(request_->GetExecutionContext(), &async_task_id_,
-                              "success");
+  probe::AsyncTask async_task(request_->GetExecutionContext(), this, "success");
   IDBRequest* request = request_.Get();
   Detach();
   request->HandleResponse(value);
@@ -266,8 +259,7 @@
   if (!request_)
     return;
 
-  probe::AsyncTask async_task(request_->GetExecutionContext(), &async_task_id_,
-                              "success");
+  probe::AsyncTask async_task(request_->GetExecutionContext(), this, "success");
   IDBRequest* request = request_.Get();
   Detach();
   request->HandleResponse();
@@ -280,8 +272,7 @@
   if (!request_)
     return;
 
-  probe::AsyncTask async_task(request_->GetExecutionContext(), &async_task_id_,
-                              "success");
+  probe::AsyncTask async_task(request_->GetExecutionContext(), this, "success");
   std::unique_ptr<IDBValue> value;
   if (optional_value.has_value()) {
     value = std::move(optional_value.value());
@@ -301,8 +292,7 @@
   if (!request_)
     return;
 
-  probe::AsyncTask async_task(request_->GetExecutionContext(), &async_task_id_,
-                              "blocked");
+  probe::AsyncTask async_task(request_->GetExecutionContext(), this, "blocked");
 #if DCHECK_IS_ON()
   DCHECK(!request_->TransactionHasQueuedResults());
 #endif  // DCHECK_IS_ON()
@@ -324,8 +314,8 @@
                                               task_runner_);
   }
   if (request_) {
-    probe::AsyncTask async_task(request_->GetExecutionContext(),
-                                &async_task_id_, "upgradeNeeded");
+    probe::AsyncTask async_task(request_->GetExecutionContext(), this,
+                                "upgradeNeeded");
 #if DCHECK_IS_ON()
     DCHECK(!request_->TransactionHasQueuedResults());
 #endif  // DCHECK_IS_ON()
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.h b/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.h
index ddae52a6a..b189a94 100644
--- a/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.h
+++ b/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.h
@@ -33,7 +33,6 @@
 
 #include "base/memory/weak_ptr.h"
 #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink.h"
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/modules/indexeddb/web_idb_callbacks.h"
 #include "third_party/blink/renderer/platform/heap/persistent.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
@@ -100,7 +99,6 @@
   Persistent<IDBRequest> request_;
   base::WeakPtr<WebIDBCursorImpl> cursor_;
   int64_t transaction_id_;
-  probe::AsyncTaskId async_task_id_;
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
 };
 
diff --git a/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc b/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc
index 0be2bf7..8d9f136 100644
--- a/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc
+++ b/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc
@@ -17,7 +17,6 @@
 #include "third_party/blink/renderer/core/html/media/html_video_element.h"
 #include "third_party/blink/renderer/core/html/media/remote_playback_observer.h"
 #include "third_party/blink/renderer/core/html_names.h"
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/core/probe/core_probes.h"
 #include "third_party/blink/renderer/modules/event_target_modules.h"
 #include "third_party/blink/renderer/modules/presentation/presentation_availability_state.h"
@@ -51,7 +50,7 @@
 
 void RunRemotePlaybackTask(ExecutionContext* context,
                            base::OnceClosure task,
-                           std::unique_ptr<probe::AsyncTaskId> task_id) {
+                           std::unique_ptr<int> task_id) {
   probe::AsyncTask async_task(context, task_id.get());
   std::move(task).Run();
 }
@@ -261,9 +260,7 @@
     // task id.
     base::OnceClosure task =
         WTF::Bind(&RemotePlayback::PromptCancelled, WrapPersistent(this));
-
-    std::unique_ptr<probe::AsyncTaskId> task_id =
-        std::make_unique<probe::AsyncTaskId>();
+    std::unique_ptr<int> task_id = std::make_unique<int>(0);
     probe::AsyncTaskScheduled(GetExecutionContext(), "promptCancelled",
                               task_id.get());
     GetExecutionContext()
@@ -293,8 +290,7 @@
   // We can remove the wrapper if InspectorInstrumentation returns a task id.
   base::OnceClosure task = WTF::Bind(&RemotePlayback::NotifyInitialAvailability,
                                      WrapPersistent(this), id);
-  std::unique_ptr<probe::AsyncTaskId> task_id =
-      std::make_unique<probe::AsyncTaskId>();
+  std::unique_ptr<int> task_id = std::make_unique<int>(0);
   probe::AsyncTaskScheduled(GetExecutionContext(), "watchAvailabilityCallback",
                             task_id.get());
   GetExecutionContext()
diff --git a/third_party/blink/renderer/modules/webdatabase/database.cc b/third_party/blink/renderer/modules/webdatabase/database.cc
index d0e9ecee..c413db01 100644
--- a/third_party/blink/renderer/modules/webdatabase/database.cc
+++ b/third_party/blink/renderer/modules/webdatabase/database.cc
@@ -35,7 +35,6 @@
 #include "third_party/blink/public/platform/web_security_origin.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/inspector/console_message.h"
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/core/probe/core_probes.h"
 #include "third_party/blink/renderer/modules/webdatabase/change_version_data.h"
 #include "third_party/blink/renderer/modules/webdatabase/change_version_wrapper.h"
@@ -295,15 +294,14 @@
           << "Scheduling DatabaseCreationCallbackTask for database " << this;
       auto* v8persistent_callback =
           ToV8PersistentCallbackFunction(creation_callback);
-      auto task_id = std::make_unique<probe::AsyncTaskId>();
       probe::AsyncTaskScheduled(GetExecutionContext(), "openDatabase",
-                                task_id.get());
+                                v8persistent_callback);
       GetExecutionContext()
           ->GetTaskRunner(TaskType::kDatabaseAccess)
-          ->PostTask(FROM_HERE, WTF::Bind(&Database::RunCreationCallback,
-                                          WrapPersistent(this),
-                                          WrapPersistent(v8persistent_callback),
-                                          std::move(task_id)));
+          ->PostTask(
+              FROM_HERE,
+              WTF::Bind(&Database::RunCreationCallback, WrapPersistent(this),
+                        WrapPersistent(v8persistent_callback)));
     }
   }
 
@@ -311,9 +309,8 @@
 }
 
 void Database::RunCreationCallback(
-    V8PersistentCallbackFunction<V8DatabaseCallback>* creation_callback,
-    std::unique_ptr<probe::AsyncTaskId> task_id) {
-  probe::AsyncTask async_task(GetExecutionContext(), task_id.get());
+    V8PersistentCallbackFunction<V8DatabaseCallback>* creation_callback) {
+  probe::AsyncTask async_task(GetExecutionContext(), creation_callback);
   creation_callback->InvokeAndReportException(nullptr, this);
 }
 
diff --git a/third_party/blink/renderer/modules/webdatabase/database.h b/third_party/blink/renderer/modules/webdatabase/database.h
index 9399bb56..d8c509f 100644
--- a/third_party/blink/renderer/modules/webdatabase/database.h
+++ b/third_party/blink/renderer/modules/webdatabase/database.h
@@ -138,8 +138,7 @@
                             DatabaseError&,
                             String& error_message);
   void RunCreationCallback(
-      V8PersistentCallbackFunction<V8DatabaseCallback>* creation_callback,
-      std::unique_ptr<probe::AsyncTaskId> task_id);
+      V8PersistentCallbackFunction<V8DatabaseCallback>* creation_callback);
 
   void ScheduleTransaction();
 
diff --git a/third_party/blink/renderer/modules/webdatabase/sql_statement.cc b/third_party/blink/renderer/modules/webdatabase/sql_statement.cc
index c5a0fce..5daf639 100644
--- a/third_party/blink/renderer/modules/webdatabase/sql_statement.cc
+++ b/third_party/blink/renderer/modules/webdatabase/sql_statement.cc
@@ -90,7 +90,7 @@
 
   if (HasCallback() || HasErrorCallback()) {
     probe::AsyncTaskScheduled(database->GetExecutionContext(), "SQLStatement",
-                              &async_task_id_);
+                              this);
   }
 }
 
@@ -123,7 +123,7 @@
   SQLErrorData* error = backend_->SqlError();
 
   probe::AsyncTask async_task(transaction->GetDatabase()->GetExecutionContext(),
-                              &async_task_id_);
+                              this);
 
   // Call the appropriate statement callback and track if it resulted in an
   // error, because then we need to jump to the transaction error callback.
diff --git a/third_party/blink/renderer/modules/webdatabase/sql_statement.h b/third_party/blink/renderer/modules/webdatabase/sql_statement.h
index a41a970b..7fd086c 100644
--- a/third_party/blink/renderer/modules/webdatabase/sql_statement.h
+++ b/third_party/blink/renderer/modules/webdatabase/sql_statement.h
@@ -30,7 +30,6 @@
 
 #include "third_party/blink/renderer/bindings/modules/v8/v8_sql_statement_callback.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_sql_statement_error_callback.h"
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/modules/webdatabase/sql_result_set.h"
 #include "third_party/blink/renderer/modules/webdatabase/sqlite/sql_value.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -121,8 +120,6 @@
 
   Member<OnSuccessCallback> success_callback_;
   Member<OnErrorCallback> error_callback_;
-
-  probe::AsyncTaskId async_task_id_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc b/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc
index d8d85d1..ca901e6 100644
--- a/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc
+++ b/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc
@@ -103,8 +103,7 @@
       read_only_(read_only) {
   DCHECK(IsMainThread());
   DCHECK(database_);
-  probe::AsyncTaskScheduled(db->GetExecutionContext(), "SQLTransaction",
-                            &async_task_id_);
+  probe::AsyncTaskScheduled(db->GetExecutionContext(), "SQLTransaction", this);
 }
 
 SQLTransaction::~SQLTransaction() = default;
@@ -185,7 +184,7 @@
 
 SQLTransactionState SQLTransaction::DeliverTransactionCallback() {
   bool should_deliver_error_callback = false;
-  probe::AsyncTask async_task(database_->GetExecutionContext(), &async_task_id_,
+  probe::AsyncTask async_task(database_->GetExecutionContext(), this,
                               "transaction");
 
   // Spec 4.3.2 4: Invoke the transaction callback with the new SQLTransaction
@@ -209,8 +208,7 @@
 }
 
 SQLTransactionState SQLTransaction::DeliverTransactionErrorCallback() {
-  probe::AsyncTask async_task(database_->GetExecutionContext(),
-                              &async_task_id_);
+  probe::AsyncTask async_task(database_->GetExecutionContext(), this);
 
   // Spec 4.3.2.10: If exists, invoke error callback with the last
   // error to have occurred in this transaction.
@@ -274,8 +272,7 @@
 
 SQLTransactionState SQLTransaction::DeliverSuccessCallback() {
   DCHECK(IsMainThread());
-  probe::AsyncTask async_task(database_->GetExecutionContext(),
-                              &async_task_id_);
+  probe::AsyncTask async_task(database_->GetExecutionContext(), this);
 
   // Spec 4.3.2.8: Deliver success callback.
   if (OnSuccessCallback* success_callback = success_callback_.Release())
diff --git a/third_party/blink/renderer/modules/webdatabase/sql_transaction.h b/third_party/blink/renderer/modules/webdatabase/sql_transaction.h
index f2ecb13..7ba7863 100644
--- a/third_party/blink/renderer/modules/webdatabase/sql_transaction.h
+++ b/third_party/blink/renderer/modules/webdatabase/sql_transaction.h
@@ -36,7 +36,6 @@
 #include "third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_sql_transaction_callback.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_sql_transaction_error_callback.h"
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/modules/webdatabase/sql_statement.h"
 #include "third_party/blink/renderer/modules/webdatabase/sql_transaction_state_machine.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -206,7 +205,6 @@
 
   bool execute_sql_allowed_;
   std::unique_ptr<SQLErrorData> transaction_error_;
-  probe::AsyncTaskId async_task_id_;
 
   bool read_only_;
 };
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
index 27b7b39..2bb26db 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -1644,7 +1644,7 @@
   // is a separate path for the accelerated case is that we assume texture
   // copying is faster than drawImage.
   scoped_refptr<StaticBitmapImage> image = GetImage(kPreferAcceleration);
-  if (!image)
+  if (!image || !image->PaintImageForCurrentFrame())
     return false;
   cc::PaintFlags paint_flags;
   paint_flags.setBlendMode(SkBlendMode::kSrc);
diff --git a/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.cc b/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.cc
index 613701c..8f799cd 100644
--- a/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.cc
+++ b/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.cc
@@ -12,15 +12,6 @@
 
 namespace blink {
 
-XRFrameRequestCallbackCollection::CallbackAndTask::CallbackAndTask(
-    V8XRFrameRequestCallback* callback)
-    : callback(callback) {}
-
-void XRFrameRequestCallbackCollection::CallbackAndTask::Trace(
-    blink::Visitor* visitor) {
-  visitor->Trace(callback);
-}
-
 XRFrameRequestCallbackCollection::XRFrameRequestCallbackCollection(
     ExecutionContext* context)
     : context_(context) {}
@@ -29,12 +20,10 @@
 XRFrameRequestCallbackCollection::RegisterCallback(
     V8XRFrameRequestCallback* callback) {
   CallbackId id = ++next_callback_id_;
-  auto* callback_and_task = MakeGarbageCollected<CallbackAndTask>(callback);
-  callbacks_.Set(id, callback_and_task);
+  callbacks_.Set(id, callback);
   pending_callbacks_.push_back(id);
 
-  probe::AsyncTaskScheduledBreakable(context_, "XRRequestFrame",
-                                     &callback_and_task->task_id);
+  probe::AsyncTaskScheduledBreakable(context_, "XRRequestFrame", callback);
   return id;
 }
 
@@ -69,9 +58,9 @@
     if (it == current_callbacks_.end())
       continue;
 
-    probe::AsyncTask async_task(context_, &it->value->task_id);
+    probe::AsyncTask async_task(context_, it->value);
     probe::UserCallback probe(context_, "XRRequestFrame", AtomicString(), true);
-    it->value->callback->InvokeAndReportException(session, timestamp, frame);
+    it->value->InvokeAndReportException(session, timestamp, frame);
   }
 
   current_callbacks_.clear();
diff --git a/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.h b/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.h
index 6de9aa1..f61136f5 100644
--- a/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.h
+++ b/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.h
@@ -5,7 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_FRAME_REQUEST_CALLBACK_COLLECTION_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_FRAME_REQUEST_CALLBACK_COLLECTION_H_
 
-#include "third_party/blink/renderer/core/probe/async_task_id.h"
 #include "third_party/blink/renderer/platform/bindings/name_client.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
@@ -41,15 +40,7 @@
            !WTF::IsHashTraitsEmptyValue<Traits, CallbackId>(id);
   }
 
-  struct CallbackAndTask : public GarbageCollectedFinalized {
-    explicit CallbackAndTask(V8XRFrameRequestCallback* callback);
-    void Trace(blink::Visitor* visitor);
-
-    Member<V8XRFrameRequestCallback> callback;
-    probe::AsyncTaskId task_id;
-  };
-
-  using CallbackMap = HeapHashMap<CallbackId, Member<CallbackAndTask>>;
+  using CallbackMap = HeapHashMap<CallbackId, Member<V8XRFrameRequestCallback>>;
   CallbackMap callbacks_;
   Vector<CallbackId> pending_callbacks_;
 
diff --git a/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.cc b/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.cc
index 984a9be3..b57bf9c 100644
--- a/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.cc
+++ b/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.cc
@@ -312,14 +312,22 @@
 
     // compressionDiffDb is the difference between current compression level and
     // the desired level.
-    float compression_diff_db =
-        LinearToDecibels(compressor_gain_ / scaled_desired_gain);
+    float compression_diff_db;
+
+    if (scaled_desired_gain == 0) {
+      compression_diff_db = is_releasing ? -1 : 1;
+    } else {
+      compression_diff_db =
+          LinearToDecibels(compressor_gain_ / scaled_desired_gain);
+    }
 
     if (is_releasing) {
       // Release mode - compressionDiffDb should be negative dB
       max_attack_compression_diff_db_ = -1;
 
       // Fix gremlins.
+      // TODO(rtoy): Replace with a DCHECK so we can figure out how NaN can
+      // occur.
       if (std::isnan(compression_diff_db))
         compression_diff_db = -1;
       if (std::isinf(compression_diff_db))
@@ -349,6 +357,8 @@
       // Attack mode - compressionDiffDb should be positive dB
 
       // Fix gremlins.
+      // TODO(rtoy): Replace with a DCHECK so we can figure out how NaN can
+      // occur.
       if (std::isnan(compression_diff_db))
         compression_diff_db = 1;
       if (std::isinf(compression_diff_db))
diff --git a/third_party/blink/web_tests/LeakExpectations b/third_party/blink/web_tests/LeakExpectations
index 3c70d1ac..a6f3756 100644
--- a/third_party/blink/web_tests/LeakExpectations
+++ b/third_party/blink/web_tests/LeakExpectations
@@ -94,9 +94,6 @@
 #Sheriff 2019-04-10
 crbug.com/951453 [ Linux ] external/wpt/html/user-activation/activation-transfer-cross-origin-with-click.sub.tentative.html [ Pass Leak ]
 
-#Sheriff 2019-05-16
-crbug.com/963749 [ Linux ] virtual/threaded/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations.js [ Pass Timeout ]
-
 ###########################################################################
 # WARNING: Memory leaks must be fixed asap. Sheriff is expected to revert #
 # culprit CLs instead of suppressing the leaks. If you have any question, #
diff --git a/third_party/blink/web_tests/MSANExpectations b/third_party/blink/web_tests/MSANExpectations
index 3c80644..a5a3581 100644
--- a/third_party/blink/web_tests/MSANExpectations
+++ b/third_party/blink/web_tests/MSANExpectations
@@ -74,12 +74,9 @@
 
 # Tests timing out on WebKit Linux Trusty MSAN
 crbug.com/760543 [ Linux ] http/tests/devtools/tracing/timeline-layout/timeline-layout-with-invalidations.js [ Pass Timeout ]
-crbug.com/760543 [ Linux ] http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations.js [ Pass Timeout ]
-crbug.com/760543 [ Linux ] http/tests/devtools/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations.js [ Pass Timeout ]
 crbug.com/760543 [ Linux ] http/tests/devtools/tracing/timeline-style/timeline-style-recalc-with-invalidations.js [ Pass Timeout ]
 crbug.com/760543 [ Linux ] http/tests/devtools/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.js [ Pass Timeout ]
 crbug.com/760543 [ Linux ] http/tests/devtools/tracing/timeline-misc/timeline-event-causes.js [ Pass Timeout ]
-crbug.com/760543 [ Linux ] http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.js [ Pass Timeout ]
 crbug.com/760543 [ Linux ] http/tests/devtools/tracing/timeline-time/timeline-usertiming.js [ Pass Timeout ]
 crbug.com/760543 [ Linux ] http/tests/devtools/tracing/timeline-paint/timeline-paint.js [ Pass Timeout ]
 crbug.com/760543 [ Linux ] http/tests/devtools/oopif/oopif-performance-cpu-profiles.js [ Pass Timeout ]
diff --git a/third_party/blink/web_tests/SlowTests b/third_party/blink/web_tests/SlowTests
index 2fcedc1c..b10b3ba1 100644
--- a/third_party/blink/web_tests/SlowTests
+++ b/third_party/blink/web_tests/SlowTests
@@ -331,7 +331,6 @@
 # Tests with slowest_run >= 10s on flakiness dashboard for site_per_process_webkit_layout_tests
 crbug.com/874695 http/tests/devtools/sources/debugger-breakpoints/breakpoints-ui-shifted-breakpoint.js [ Slow ]
 crbug.com/874695 http/tests/devtools/sources/sourcemap-hot-reload.js [ Slow ]
-crbug.com/874695 http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.js [ Slow ]
 
 # Tests where |3s <= slowest_run < 10s| on flakiness dashboard for site_per_process_webkit_layout_tests
 crbug.com/874695 accessibility/is-ignored-change-sends-notification.html [ Slow ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index bc13cde..f8f6127a 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -890,6 +890,7 @@
 crbug.com/591099 [ Mac10.11 ] fast/events/before-unload-return-value-from-listener.html [ Crash Timeout ]
 crbug.com/591099 [ Mac10.11 ] media/track/track-cue-rendering-position-auto-rtl.html [ Failure ]
 crbug.com/591099 [ Mac10.11 ] virtual/scalefactor200/fast/hidpi/static/popup-menu-appearance.html [ Failure ]
+crbug.com/976355 [ Mac10.12 ] fast/events/before-unload-return-value-from-listener.html [ Crash Timeout ]
 crbug.com/591099 [ Mac10.13 ] compositing/geometry/root-layer-update.html [ Failure ]
 crbug.com/591099 [ Mac10.13 ] compositing/overlap-blending/reflection-opacity-huge.html [ Failure ]
 crbug.com/591099 [ Mac10.13 ] compositing/reflections/reflection-positioning2.html [ Failure ]
@@ -2267,13 +2268,10 @@
 # Next 1 here: https://ci.chromium.org/buildbot/tryserver.blink/win7-blink-rel/1180
 # Next 2 here: https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux-blink-rel/1541
 crbug.com/891427 virtual/android/rootscroller/gesture-scroll-document-not-root-scroller.html [ Pass Failure Timeout Crash ]
-crbug.com/891427 virtual/threaded/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations.js [ Pass Failure Timeout Crash ]
 # Next 1 here: https://ci.chromium.org/p/chromium/builders/luci.chromium.try/linux-blink-rel/1547
 crbug.com/891427 virtual/threaded/external/wpt/css/css-scroll-snap/snap-at-user-scroll-end-manual.html [ Pass Failure Timeout Crash ]
 # Next 1 here: https://ci.chromium.org/p/chromium/builders/luci.chromium.try/win7-blink-rel/1504
 crbug.com/891427 tables/mozilla_expected_failures/marvin/table_overflow_dirty_reflow_tbody.html [ Pass Failure Timeout Crash ]
-# Next 1 here: https://ci.chromium.org/p/chromium/builders/luci.chromium.try/win10-blink-rel/1510
-crbug.com/891427 virtual/threaded/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.js [ Pass Failure Timeout Crash ]
 
 # The following fail only on Mac.
 crbug.com/891427 [ Mac ] fast/events/touch/gesture/touch-gesture-scroll-listbox.html [ Pass Failure Timeout Crash ]
@@ -4481,7 +4479,6 @@
 crbug.com/957457 virtual/threaded/external/wpt/css/css-paint-api/geometry-background-image-tiled-001.https.html [ Crash ]
 crbug.com/957457 virtual/threaded/external/wpt/css/css-paint-api/invalid-image-pending-script.https.html [ Crash ]
 crbug.com/957457 virtual/threaded/external/wpt/css/css-paint-api/paint2d-image.https.html [ Failure Timeout ]
-crbug.com/957459 virtual/threaded/external/wpt/css/css-paint-api/parse-input-arguments-018.https.html [ Crash Failure ]
 crbug.com/957459 virtual/threaded/external/wpt/css/css-paint-api/registered-property-interpolation-004.https.html [ Failure ]
 crbug.com/957459 virtual/threaded/external/wpt/css/css-paint-api/registered-property-interpolation-010.https.html [ Failure ]
 crbug.com/957459 virtual/threaded/external/wpt/css/css-paint-api/registered-property-stylemap.https.html [ Failure ]
@@ -5658,7 +5655,6 @@
 
 
 # Sheriff 2018-10-29
-crbug.com/899710 [ Win ] virtual/threaded/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations.js [ Failure Pass Timeout ]
 crbug.com/766357 [ Win ] virtual/threaded/fast/scrolling/wheel-and-touch-scroll-use-count.html [ Failure Pass ]
 
 # Sheriff 2018-10-30
@@ -6159,7 +6155,6 @@
 # Sheriff 2019-05-20
 crbug.com/963739 [ Fuchsia ] synthetic_gestures/smooth-scroll-tiny-delta.html [ Pass Timeout ]
 crbug.com/964158 [ Linux ] external/wpt/payment-handler/change-payment-method.https.html [ Pass Crash ]
-crbug.com/899710 [ Linux ] virtual/threaded/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations.js [ Pass Timeout ]
 crbug.com/964239 external/wpt/css/css-scroll-snap/scroll-margin.html [ Pass Failure ]
 crbug.com/965389 [ Mac ] media/track/track-cue-rendering-position-auto.html [ Pass Failure ]
 
diff --git a/third_party/blink/web_tests/WebDriverExpectations b/third_party/blink/web_tests/WebDriverExpectations
index f2c4922..f57323d 100644
--- a/third_party/blink/web_tests/WebDriverExpectations
+++ b/third_party/blink/web_tests/WebDriverExpectations
@@ -3,933 +3,21 @@
 # separate runner, run_webdriver_tests.py. Thus this is a separate
 # expectation file from TestExpectations.
 # ====== New tests from wpt-importer added here ======
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element_from_element/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/select.py>>test_click_multiple_option [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[R_END-expected48] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[NUMPAD8-expected60] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/events.py>>test_not_blurred[input] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[SPACE-expected21] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_printable_key_sends_correct_events[a-KeyA0] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/release_actions/sequence.py>>test_release_no_actions_sends_no_events [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/get.py>>test_primitives[undefined-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_origin.py>>test_element_center_point [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/navigate.py>>test_null_response_value [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/add.py>>test_null_response_value [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_dismiss[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_modifier_key_sends_correct_events[\ue050-R_SHIFT] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/release_actions/sequence.py>>test_no_release_mouse_sequence_keeps_dblclick_state [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key.py>>test_element_not_focused [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/user_prompts.py>>test_accept[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/get.py>>test_element_stale [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/center_point.py>>test_css_pixel_rounding[10] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_boolean_attribute[img-attrs7] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_modifier_click.py>>test_modifier_click[\ue008-shiftKey] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_drag_and_drop[-20-0-800] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_cookie/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/properties.py>>test_content_attribute [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_element/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_async_script/properties.py>>test_script_defining_property [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_dismiss[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/scroll_into_view.py>>test_partially_visible_does_not_scroll[1] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_selected/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_async_script/collections.py>>test_html_all_collection [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/get.py>>test_primitives_set_by_execute_script[null-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_all_cookies/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/get.py>>test_sucess_input [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_element/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/screenshot.py>>test_format_and_dimensions [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_rect/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_cookie/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_tag_name/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/properties.py>>test_idl_attribute_element [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_clear/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/center_point.py>>test_css_pixel_rounding[2] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_selected/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_tag_name/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_clear/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/interactability.py>>test_body_is_interactable [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_element/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/form_controls.py>>test_textarea [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_cookie/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/select.py>>test_option_disabled [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_selected/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/set_timeouts/set.py>>test_parameters_unknown_fields[value1] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_all_cookies/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_clear/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/switch_to_frame/switch.py>>test_frame_id_webelement_iframe[1-bar] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/release_actions/sequence.py>>test_release_char_sequence_sends_keyup_events_in_reverse [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[EQUALS-expected38] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/events.py>>test_form_control_send_text[input] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[CLEAR-expected36] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_all_cookies/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/get.py>>test_title_from_frame [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_fieldset_enabled_descendant[select] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[NUMPAD3-expected35] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_fieldset_enabled_descendant_legend[textarea] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[BACKSPACE-expected12] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/close_window/close.py>>test_close_browsing_context_with_dismissed_beforeunload_prompt [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/center_point.py>>test_css_pixel_rounding[9] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_accept[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/center_point.py>>test_entirely_in_view [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_xhtml_form_control_disabled[textarea] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/switch_to_frame/switch.py>>test_frame_id_number_index[1-bar] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/dismiss_alert/dismiss.py>>test_dismiss_alert [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/file_upload.py>>test_strict_hidden[capabilities0] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/file_upload.py>>test_multiple_files_send_twice [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/interactability.py>>test_not_a_focusable_element [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_clear/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_element/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/get.py>>test_success_document [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[F7-expected57] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_xml_always_not_enabled [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[F10-expected46] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/get.py>>test_primitives[js_primitive2-py_primitive2] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_special_keys.py>>test_invalid_multiple_codepoint_keys_fail[fa] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[PAGE_UP-expected6] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_element/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[NUMPAD5-expected61] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_fieldset_enabled_descendant_legend[select] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_boolean_attribute[dialog-attrs3] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_modifiers.py>>test_shift_modifier_and_non_printable_keys[\ue050] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_rect/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/send_keys.py>>test_invalid_text_type[True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_drag_and_drop[10--15-800] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[NUMPAD4-expected22] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/switch_to_frame/switch.py>>test_frame_id_webelement_frame[0-foo] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_async_script/collections.py>>test_file_list [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_drag_and_drop[0-15-300] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_text/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/scroll_into_view.py>>test_scroll_into_view [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_text/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/get.py>>test_primitives[null-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_boolean_attribute[track-attrs16] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[ADD-expected40] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[R_PAGEDOWN-expected39] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/get.py>>test_property_name_not_existent [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[DIVIDE-expected33] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/collections.py>>test_html_collection [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_drag_and_drop[-10--15-0] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_boolean_attribute[iframe-attrs6] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/select.py>>test_out_of_view_dropdown [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/get.py>>test_primitives[js_primitive3-py_primitive3] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_rect/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_tag_name/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_xhtml_form_control_disabled[select] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[R_SHIFT-expected65] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_page_source/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_xhtml_form_control_enabled[input] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_origin.py>>test_element_outside_of_view_port [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[F12-expected10] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_cookie/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_cookie/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_text/get.py>>test_getting_text_of_a_non_existant_element_is_an_error [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/get.py>>test_missing_document_element [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/interactability.py>>test_transparent_element [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/interactability.py>>test_display_none [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_form_control_disabled[select] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_tag_name/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_shortcuts.py>>test_mod_a_and_backspace_deletes_all_text [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/file_upload.py>>test_display_none [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_element_stale [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[CONTROL-expected17] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/file_upload.py>>test_single_file_replaces_without_multiple_attribute [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_text/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/user_prompts.py>>test_dismiss[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_selected/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/scroll_into_view.py>>test_partially_visible_does_not_scroll[4] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_selected/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_tag_name/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_shortcuts.py>>test_mod_a_mod_x_deletes_all_text [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[DECIMAL-expected27] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_cookie/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_all_cookies/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/get.py>>test_success_iframe_content [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_clear/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/center_point.py>>test_css_pixel_rounding[6] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_tag_name/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_origin.py>>test_element_center_point_with_offset [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_modifier_click.py>>test_modifier_click[\ue03d-metaKey] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_current_url/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/interactability.py>>test_readonly_element [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_rect/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_clear/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_current_url/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_modifier_click.py>>test_many_modifiers_click [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element_from_element/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/forward.py>>test_dismissed_beforeunload [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_fieldset_disabled_descendant[select] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/interactability.py>>test_visibility_hidden [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_tag_name/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element_from_element/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/send_keys.py>>test_invalid_text_type[None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_tag_name/get.py>>test_element_stale [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_drag_and_drop[10-15-800] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/select.py>>test_click_preselected_option [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_clear/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/file_upload.py>>test_obscured [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[INSERT-expected18] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_rect/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_printable_key_sends_correct_events[@-Digit2] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/get.py>>test_element_stale [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_page_source/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_dismiss[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/switch_to_frame/switch.py>>test_frame_id_webelement_no_element_reference [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/switch_to_frame/switch.py>>test_frame_id_number_index_out_of_bounds [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_async_script/collections.py>>test_html_form_controls_collection [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/file_upload.py>>test_transparent [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_page_source/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_printable_key_sends_correct_events[\xe0-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/user_prompts.py>>test_dismiss[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_click_at_coordinates [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_all_cookies/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/navigate.py>>test_link_closes_window [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_fieldset_disabled_descendant[input] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_fieldset_enabled_descendant[input] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[PAUSE-expected31] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_current_url/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_boolean_attribute[script-attrs13] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[F5-expected55] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/select.py>>test_click_multiple_does_not_deselect_others [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_current_url/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[END-expected32] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_all_cookies/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/get.py>>test_property_name_value [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_rect/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_printable_key_sends_correct_events[\u2603-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/dismiss_alert/dismiss.py>>test_dismiss_prompt [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/get.py>>test_primitives_set_by_execute_script[js_primitive3-py_primitive3] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_origin.py>>test_element_larger_than_viewport [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[R_INSERT-expected42] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[NUMPAD6-expected45] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_selected/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_drag_and_drop[20-0-0] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/get.py>>test_title_from_top_context [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_fieldset_disabled_descendant[button] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_fieldset_enabled_descendant_legend[button] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/screenshot.py>>test_stale [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/sequence.py>>test_perform_no_actions_send_no_events [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_dismiss[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_text/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[F1-expected51] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_modifier_click.py>>test_modifier_click[\ue052-altKey] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_rect/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/user_prompts.py>>test_dismiss[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/forward.py>>test_history_pushstate [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_fieldset_disabled_descendant[textarea] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/get.py>>test_get_named_cookie [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_shortcuts.py>>test_mod_a_mod_c_right_mod_v_pastes_text [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_text/get.py>>test_read_element_text [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_selected/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_drag_and_drop[0-15-800] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_fieldset_enabled_descendant[button] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_element/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_boolean_attribute[input-attrs8] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_special_keys.py>>test_invalid_multiple_codepoint_keys_fail[\u0ba8\u0bbfb] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_page_source/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/scroll_into_view.py>>test_partially_visible_does_not_scroll[9] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_click_navigation [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_page_source/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/send_keys.py>>test_invalid_text_type[value4] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/release_actions/sequence.py>>test_release_mouse_sequence_resets_dblclick_state [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_pause_dblclick.py>>test_dblclick_with_pause_after_second_pointerdown [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_all_cookies/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[TAB-expected24] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_all_cookies/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/center_point.py>>test_css_pixel_rounding[1] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[R_CONTROL-expected62] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/file_upload.py>>test_empty_text [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element_from_element/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/file_upload.py>>test_hidden [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_pause_dblclick.py>>test_no_dblclick [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[DOWN-expected9] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/get.py>>test_primitives_set_by_execute_script["foobar"-foobar] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[R_ALT-expected25] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_non_printable_key_sends_events[\ue014-RIGHT] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_tag_name/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/collections.py>>test_html_form_controls_collection [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_sequence_of_keydown_printable_keys_sends_events [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/get.py>>test_success_explicit_focus [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_keyup_only_sends_no_events [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_alert_text/get.py>>test_get_confirm_text [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[F8-expected58] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/center_point.py>>test_css_pixel_rounding[8] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_rect/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_cookie/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_tag_name/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_current_url/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[ZENKAKUHANKAKU-expected64] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_fieldset_disabled_descendant_legend[textarea] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/switch_to_frame/switch.py>>test_frame_id_webelement_frame[1-bar] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_boolean_attribute[fieldset-attrs4] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_origin.py>>test_viewport_inside [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/interactability.py>>test_disabled [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/get.py>>test_primitives[42-42] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[R_ARROWDOWN-expected68] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/user_prompts.py>>test_accept[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_drag_and_drop[-10--15-300] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_boolean_attribute[audio-attrs0] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_page_source/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_boolean_attribute[video-attrs17] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_page_source/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[NUMPAD2-expected50] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_accept[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[LEFT-expected28] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_modifier_click.py>>test_modifier_click[\ue00a-altKey] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_non_printable_key_sends_events[\ue00c-ESCAPE] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/get.py>>test_primitives_set_by_execute_script[42-42] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_alert_text/get.py>>test_get_prompt_text [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/switch_to_frame/switch.py>>test_null_response_value [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_modifier_key_sends_correct_events[\ue052-R_ALT] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/interactability.py>>test_hidden [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/events.py>>test_file_upload [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_accept[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_text/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/refresh.py>>test_basic [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/get.py>>test_title_after_modification [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[ENTER-expected43] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_text/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_text/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_selected/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_clear/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/file_upload.py>>test_multiple_files_reset_with_element_clear [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_element_stale [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/forward.py>>test_fragments [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/back.py>>test_history_pushstate [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/get.py>>test_title_without_element [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_cookie/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_cookie/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/user_prompts.py>>test_accept[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_drag_and_drop[10--15-300] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_current_url/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[SUBTRACT-expected16] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[ESCAPE-expected5] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_cookie/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_normal [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/navigate.py>>test_link_unload_event [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/file_upload.py>>test_single_file_appends_with_multiple_attribute [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_page_source/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_current_url/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_element/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[PAGE_DOWN-expected30] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_fieldset_enabled_descendant_legend[input] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/scroll_into_view.py>>test_partially_visible_does_not_scroll[7] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_async_script/collections.py>>test_node_list [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_form_control_enabled[input] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_dblclick.py>>test_dblclick_at_coordinates[0] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/center_point.py>>test_css_pixel_rounding[5] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_element/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/accept_alert/accept.py>>test_accept_alert [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_accept[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_cookie/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_all_cookies/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_selected/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_origin.py>>test_element_in_view_center_point_partly_visible [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/events.py>>test_form_control_send_text[textarea] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/send_keys.py>>test_invalid_text_type[value3] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/dismiss_alert/dismiss.py>>test_dismiss_confirm [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_rect/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/switch_to_parent_frame/switch.py>>test_null_response_value [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_clear/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_drag_and_drop[10-15-0] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_printable_key_sends_correct_events[\u0416-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_boolean_attribute[menuitem-attrs9] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element_from_element/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_drag_and_drop[0-15-0] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_element/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/cyclic.py>>test_element_in_collection [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_context_menu_at_coordinates [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_xhtml_form_control_enabled[textarea] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_all_cookies/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_text/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/refresh.py>>test_dismissed_beforeunload [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/collections.py>>test_html_all_collection [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_page_source/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_boolean_attribute[details-attrs2] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/stale.py>>test_is_stale [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_drag_and_drop[-20-0-300] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_printable_key_sends_correct_events[\uf6c2-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_selected/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/collections.py>>test_node_list [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/interactability.py>>test_obscured_element [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_async_script/properties.py>>test_idl_attribute_element [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_boolean_attribute[form-attrs5] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_all_cookies/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_rect/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_printable_key_sends_correct_events["-Quote] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_drag_and_drop[10-15-300] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_form_control_enabled[button] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/switch_to_frame/cross_origin.py>>test_nested_cross_origin_iframe [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/select.py>>test_click_selected_multiple_option [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_current_url/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/interactability.py>>test_iframe_is_interactable [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[R_DELETE-expected29] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_selected/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/get.py>>test_title_strip_and_collapse [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/forward.py>>test_null_response_value [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_form_control_enabled[select] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[F2-expected52] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_async_script/collections.py>>test_html_collection [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_selected/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_cookie/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_rect/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key.py>>test_backspace_erases_keys [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/navigate.py>>test_numbers_link [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_element/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/center_point.py>>test_css_pixel_rounding[7] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/accept_alert/accept.py>>test_accept_prompt [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_clear/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_selected/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/scroll_into_view.py>>test_partially_visible_does_not_scroll[3] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/form_controls.py>>test_input_append [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/file_upload.py>>test_single_file [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/forward.py>>test_no_browsing_history [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_page_source/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_dismiss[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/get.py>>test_primitives["foobar"-foobar] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_text/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[R_HOME-expected63] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_clear/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/file_upload.py>>test_outside_viewport [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_modifier_key_sends_correct_events[\ue00a-ALT] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_rect/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element_from_element/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_cookie/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[NULL-expected15] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_rect/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/center_point.py>>test_css_pixel_rounding[4] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_element/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_drag_and_drop[-20-0-0] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_current_url/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/scroll_into_view.py>>test_partially_visible_does_not_scroll[8] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/switch_to_frame/cross_origin.py>>test_cross_origin_iframe [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_tag_name/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_modifier_key_sends_correct_events[\ue051-R_CONTROL] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_selected/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/click.py>>test_null_response_value [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_page_source/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_all_cookies/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_session/delete.py>>test_dismissed_beforeunload_prompt [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_element/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_form_control_enabled[textarea] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/get.py>>test_sucess_input_non_interactable [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_all_cookies/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/dismiss_alert/dismiss.py>>test_null_response_value [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[RIGHT-expected23] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_element/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_clear/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_element/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_modifier_click.py>>test_modifier_click[\ue053-metaKey] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_global_boolean_attributes [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_cookie/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_page_source/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_dblclick.py>>test_dblclick_at_coordinates[200] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/refresh.py>>test_history_pushstate [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_all_cookies/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/switch_to_frame/switch.py>>test_frame_id_webelement_stale_reference [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_rect/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_boolean_attribute[optgroup-attrs11] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_async_script/properties.py>>test_content_attribute [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_text/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/back.py>>test_fragments [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[R_PAGEUP-expected7] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_page_source/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_accept[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_tag_name/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/switch_to_parent_frame/switch.py>>test_stale_element_from_iframe [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/file_upload.py>>test_multiple_files [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_text/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[ALT-expected67] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_async_script/properties.py>>test_idl_attribute [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_current_url/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_xhtml_form_control_disabled[input] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/scroll_into_view.py>>test_contenteditable_element_outside_of_scrollable_viewport [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/events.py>>test_not_blurred[textarea] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element_from_element/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_tag_name/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_printable_key_sends_correct_events[a-KeyA1] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[HOME-expected14] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[F4-expected54] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_rect/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/send_keys.py>>test_stale_element [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element_from_element/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/back.py>>test_null_response_value [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_boolean_attribute[select-attrs14] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/get.py>>test_get_named_session_cookie [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_clear/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_page_source/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/scroll_into_view.py>>test_element_outside_of_scrollable_viewport [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_printable_key_sends_correct_events[,-Comma] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_element/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/switch_to_frame/switch.py>>test_frame_id_null [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_modifiers.py>>test_shift_modifier_and_non_printable_keys[\ue008] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_boolean_attribute[textarea-attrs15] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_form_control_disabled[textarea] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_current_url/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/form_controls.py>>test_input [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_page_source/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[MULTIPLY-expected13] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/get.py>>test_duplicated_cookie [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/form_controls.py>>test_textarea_append [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_boolean_attribute[option-attrs12] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/get.py>>test_primitives_set_by_execute_script[undefined-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/forward.py>>test_data_urls [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_xhtml_form_control_disabled[button] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_current_url/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/file_upload.py>>test_strict_display_none[capabilities0] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_fieldset_disabled_descendant_legend[select] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/refresh.py>>test_null_response_value [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_clear/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_text/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[F11-expected47] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_rect/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/switch_to_frame/switch.py>>test_frame_id_webelement_iframe[0-foo] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/get.py>>test_title_with_duplicate_element [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[UP-expected8] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_selected/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_tag_name/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_clear/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_modifiers.py>>test_shift_modifier_generates_capital_letters[\ue050] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_fieldset_disabled_descendant_legend[input] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_tag_name/get.py>>test_get_element_tag_name [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/scroll_into_view.py>>test_partially_visible_does_not_scroll[6] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_tag_name/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_page_source/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/back.py>>test_data_urls [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[R_ARROWLEFT-expected37] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/add.py>>test_add_non_session_cookie [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_current_url/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[HELP-expected2] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_boolean_attribute[ol-attrs10] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_clear/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_modifier_click.py>>test_modifier_click[\ue050-shiftKey] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/user_prompts.py>>test_dismiss[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[R_ARROWRIGHT-expected4] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_text/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/file_upload.py>>test_multiple_files_without_multiple_attribute [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/center_point.py>>test_css_pixel_rounding[3] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_tag_name/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_current_url/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/user_prompts.py>>test_accept[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/screenshot.py>>test_format_and_dimensions [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_tag_name/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/get.py>>test_primitives_set_by_execute_script[js_primitive2-py_primitive2] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_form_control_disabled[input] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/user_prompts.py>>test_dismiss[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/user_prompts.py>>test_accept[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element_from_element/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_rect/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_cookie/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_rect/get.py>>test_basic [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_all_cookies/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_clear/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_selected/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[SHIFT-expected3] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_text/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/file_upload.py>>test_multiple_files_last_path_not_found [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/select.py>>test_click_selected_option [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_form_control_disabled[button] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_accept[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[NUMPAD7-expected49] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_rect/get.py>>test_element_stale [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/user_prompts.py>>test_dismiss[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_sequence_of_keydown_printable_characters_sends_events [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[R_ARROWUP-expected34] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_alert_text/get.py>>test_get_alert_text [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_drag_and_drop[-10--15-800] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[RETURN-expected1] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[SEMICOLON-expected20] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/add.py>>test_add_domain_cookie [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[NUMPAD0-expected26] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/select.py>>test_click_deselects_others [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_modifiers.py>>test_shift_modifier_generates_capital_letters[\ue008] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element_from_element/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[CANCEL-expected44] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element_from_element/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/properties.py>>test_idl_attribute [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/select.py>>test_out_of_view_multiple [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/get.py>>test_property_non_existent [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/back.py>>test_dismissed_beforeunload [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_all_cookies/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_fieldset_disabled_descendant_legend[button] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/add.py>>test_add_session_cookie [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/switch_to_frame/switch.py>>test_frame_id_webelement_no_frame_element [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/accept_alert/accept.py>>test_null_response_value [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_clear/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_text/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_element/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element_from_element/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/accept_alert/accept.py>>test_accept_confirm [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/scroll_into_view.py>>test_partially_visible_does_not_scroll[2] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/refresh.py>>test_refresh_switches_to_parent_browsing_context [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/get.py>>test_mutated_element [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_rect/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_element/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/collections.py>>test_html_options_collection [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_async_script/collections.py>>test_html_options_collection [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_page_source/user_prompts.py>>test_default[prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_all_cookies/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_tag_name/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/cyclic.py>>test_element_in_object [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements_from_element/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_cookie/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_all_cookies/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[SEPARATOR-expected66] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element_from_element/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_special_keys.py>>test_invalid_multiple_codepoint_keys_fail[\u0ba8\u0bbf\u0ba8] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element_from_element/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_current_url/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_xhtml_form_control_enabled[button] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element_from_element/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[NUMPAD9-expected0] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_text/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_modifier_key_sends_correct_events[\ue008-SHIFT] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_fieldset_enabled_descendant[textarea] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/navigate.py>>test_link_hash [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_page_source/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_boolean_attribute[button-attrs1] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/scroll_into_view.py>>test_partially_visible_does_not_scroll[5] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/add.py>>test_add_session_cookie_with_leading_dot_character_in_domain [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_modifier_key_sends_correct_events[\ue009-CONTROL] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_page_source/source.py>>test_source_matches_outer_html [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_cookie/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_selected/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_contextmenu.py>>test_release_control_click [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_text/user_prompts.py>>test_default[confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_tag_name/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_cookie/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/navigate.py>>test_multi_line_link [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_xhtml_form_control_enabled[select] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[DELETE-expected69] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[NUMPAD1-expected41] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[F9-expected59] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_current_url/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/select.py>>test_click_option [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/select.py>>test_click_preselected_multiple_option [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_drag_and_drop[20-0-300] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/switch_to_frame/switch.py>>test_frame_id_number_index[0-foo] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/get.py>>test_content_attribute [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_current_url/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_origin.py>>test_pointer_inside [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/send_keys.py>>test_null_response_value [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_elements/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/send_keys.py>>test_invalid_text_type[1] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_drag_and_drop[10--15-0] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[F3-expected53] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/properties.py>>test_script_defining_property [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/send_keys.py>>test_null_parameter_value [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/user_prompts.py>>test_default[alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/get.py>>test_idl_attribute [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/user_prompts.py>>test_accept[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/collections.py>>test_file_list [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/navigate.py>>test_file_protocol [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/bubbling.py>>test_element_disappears_during_click [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_click_element_center [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element_from_element/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element_from_element/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[F6-expected56] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_dismiss[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_drag_and_drop[20-0-800] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_text/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/bubbling.py>>test_click_event_bubbles_to_parents [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_selected/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_current_url/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_special_keys.py>>test_invalid_multiple_codepoint_keys_fail[\u1100\u1161\u11a8c] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/find_element_from_element/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/minimize_window/minimize.py>>test_fully_exit_fullscreen [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_dismiss[capabilities0-confirm] [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state[realmSetting2-denied] [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_contextmenu.py>>test_control_click[\ue009-ctrlKey] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_non_secure_context[denied] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_invalid_parameters[parameters2] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/interactability.py>>test_document_element_is_interactable [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/fullscreen_window/stress.py>>test_stress[4] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/bubbling.py>>test_spin_event_loop [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state[realmSetting2-denied] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/content_editable.py>>test_sets_insertion_point_to_after_last_text_node [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_session/create_alwaysMatch.py>>test_valid[pageLoadStrategy-eager] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_invalid_parameters[parameters7] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_non_secure_context[granted] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_dismiss[capabilities0-prompt] [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/json_serialize_windowproxy.py>>test_window_open [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/user_prompts.py>>test_accept[capabilities0-prompt] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_click/file_upload.py>>test_file_upload_state [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state[realmSetting2-granted] [ Failure ]
@@ -937,44 +25,40 @@
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/maximize_window/maximize.py>>test_fully_exit_fullscreen [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state_cross_realm[realmSetting1-granted] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state[realmSetting1-prompt] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/fullscreen_window/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/fullscreen_window/fullscreen.py>>test_fullscreen [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_accept_and_notify[capabilities0-confirm] [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/user_prompts.py>>test_accept[capabilities0-confirm] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_accept[capabilities0-confirm] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/set_window_rect/set.py>>test_width_height_floats [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state_cross_realm[realmSetting1-denied] [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_session/merge.py>>test_merge_platformName [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state[realmSetting0-denied] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/user_prompts.py>>test_accept_and_notify[capabilities0-alert] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_default[confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_accept_and_notify[capabilities0-prompt] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/set_window_rect/set.py>>test_restore_from_minimized [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/scroll_into_view.py>>test_option_stays_outside_of_scrollable_viewport [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state[realmSetting1-granted] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_special_key_sends_keydown[META-expected11] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/content_editable.py>>test_sets_insertion_point_to_end [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_invalid_parameters[parameters0] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_accept_and_notify[capabilities0-alert] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_special_keys.py>>test_codepoint_keys_behave_correctly[\u1100\u1161\u11a8] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/status/status.py>>test_status_with_session_running_on_endpoint_node [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/scroll_into_view.py>>test_option_select_container_outside_of_scrollable_viewport [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_default[prompt] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/user_prompts.py>>test_dismiss[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state[realmSetting0-denied] [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state_cross_realm[realmSetting1-denied] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/fullscreen_window/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/promise.py>>test_promise_reject_timeout [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/maximize_window/maximize.py>>test_maximize_when_resized_to_max_size [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/json_serialize_windowproxy.py>>test_window_open [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_accept_and_notify[capabilities0-alert] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state_cross_realm[realmSetting0-denied] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/fullscreen_window/stress.py>>test_stress[1] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_default[alert] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/user_prompts.py>>test_default[prompt] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state[realmSetting0-prompt] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/promise.py>>test_promise_resolve_timeout [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_invalid_parameters[parameters7] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_modifier_key_sends_correct_events[\ue03d-META] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_accept[capabilities0-prompt] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_session/merge.py>>test_merge_browserName [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_session/default_values.py>>test_no_capabilites [ Failure ]
@@ -982,33 +66,36 @@
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/fullscreen_window/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_special_keys.py>>test_codepoint_keys_behave_correctly[\U0001f60d] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/fullscreen_window/stress.py>>test_stress[0] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_session/merge.py>>test_merge_platformName [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/set_window_rect/set.py>>test_restore_from_maximized [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_non_secure_context[prompt] [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_invalid_parameters[parameters6] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_accept[capabilities0-alert] [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_default[prompt] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_dismiss[capabilities0-alert] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/user_prompts.py>>test_accept_and_notify[capabilities0-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_invalid_parameters[parameters6] [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_non_secure_context[prompt] [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/user_prompts.py>>test_accept_and_notify[capabilities0-confirm] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/fullscreen_window/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_session/default_values.py>>test_repeat_new_session [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_events.py>>test_modifier_key_sends_correct_events[\ue053-R_META] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/user_prompts.py>>test_default[confirm] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/fullscreen_window/stress.py>>test_stress[3] [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_dismiss[capabilities0-confirm] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/user_prompts.py>>test_dismiss[capabilities0-prompt] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_invalid_parameters[parameters5] [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state[realmSetting1-prompt] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/json_serialize_windowproxy.py>>test_frame [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/set_window_rect/set.py>>test_fully_exit_fullscreen [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state_cross_realm[realmSetting0-granted] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/fullscreen_window/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state[realmSetting1-denied] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_contextmenu.py>>test_control_click[\ue009-ctrlKey] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/user_prompts.py>>test_dismiss[capabilities0-confirm] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/user_prompts.py>>test_accept[capabilities0-alert] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/fullscreen_window/stress.py>>test_stress[2] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/user_prompts.py>>test_default[alert] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_contextmenu.py>>test_control_click[\ue051-ctrlKey] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_invalid_parameters[parameters4] [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state[realmSetting1-denied] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_session/create_firstMatch.py>>test_valid[pageLoadStrategy-eager] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state[realmSetting0-granted] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ]
@@ -1016,11 +103,13 @@
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_session/page_load_strategy.py>>test_pageLoadStrategy [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_special_keys.py>>test_codepoint_keys_behave_correctly[\u0ba8\u0bbf] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state_cross_realm[realmSetting1-prompt] [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/set_window_rect/set.py>>test_restore_from_maximized [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/user_prompts.py>>test_accept_and_notify[capabilities0-prompt] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/fullscreen_window/fullscreen.py>>test_fullscreen_twice_is_idempotent [ Failure ]
-crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert] [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/navigate.py>>test_file_protocol [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_current_url/get.py>>test_get_current_url_file_protocol [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/json_serialize_windowproxy.py>>test_initial_window [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_invalid_parameters[parameters3] [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/set_timeouts/set.py>>test_parameters_unknown_fields[value1] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_session/default_values.py>>test_valid_but_unmatchable_key [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm] [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/scroll_into_view.py>>test_element_outside_of_not_scrollable_viewport [ Failure ]
diff --git a/third_party/blink/web_tests/fast/inline/remove-text-near-float-and-line-boundary-crash.html b/third_party/blink/web_tests/fast/inline/remove-text-near-float-and-line-boundary-crash.html
new file mode 100644
index 0000000..9f5bcbb
--- /dev/null
+++ b/third_party/blink/web_tests/fast/inline/remove-text-near-float-and-line-boundary-crash.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<style>
+  .c0 { float:right; width:100px; height:150px; }
+  .c15 { font-size:20px; font-family:Ahem; }
+  .c17 { height:10px; padding-right:100%; }
+  .c19 { float:left; width:100px; height:100px; }
+</style>
+
+<!-- Add something editable, to disable LayoutNG, to trigger the bug. -->
+<div contenteditable></div>
+
+<div id="container" style="width:400px;">
+  <div></div>
+  <span class="c15">888888888<span id="removeme"> 88</span>
+    8888888888</span><div class="c0"></div><span class="c17"></span>
+  <div class="c19"></div>
+</div>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script>
+  test(() => {
+    container.offsetTop;
+
+    // Remove some text without affecting where lines break.
+    removeme.style.display = "none";
+    container.offsetTop;
+
+    // Relayout the container without changing line widths.
+    container.style.paddingBottom = "1px";
+  }, "No crash");
+</script>
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations-expected.txt
deleted file mode 100644
index 68d64a25..0000000
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations-expected.txt
+++ /dev/null
@@ -1,77 +0,0 @@
-Tests the Timeline API instrumentation of paint events with layout invalidations.
-
-
-Running: testLocalFrame
-paint invalidations[
-    {
-        cause : {reason: Inline CSS style declaration was mutated, stackTrace: test://evaluations/0/timeline-paint-with-layout-invalidations.js:17}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : ""
-        nodeName : "BODY"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-    {
-        cause : {reason: Inline CSS style declaration was mutated, stackTrace: test://evaluations/0/timeline-paint-with-layout-invalidations.js:18}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : ""
-        nodeName : "DIV id='testElement'"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-    {
-        cause : {reason: Style changed, stackTrace: test://evaluations/0/timeline-paint-with-layout-invalidations.js:19}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : undefined
-        nodeName : "DIV id='testElement'"
-        selectorPart : undefined
-        type : "LayoutInvalidationTracking"
-    }
-]
-
-Running: testSubframe
-second paint invalidations[
-    {
-        cause : {reason: Inline CSS style declaration was mutated, stackTrace: test://evaluations/0/timeline-paint-with-layout-invalidations.js:25}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : ""
-        nodeName : "DIV"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-    {
-        cause : {reason: Style changed, stackTrace: test://evaluations/0/timeline-paint-with-layout-invalidations.js:26}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : undefined
-        nodeName : "DIV"
-        selectorPart : undefined
-        type : "LayoutInvalidationTracking"
-    }
-    {
-        cause : {reason: Scrollbar changed, stackTrace: test://evaluations/0/timeline-paint-with-layout-invalidations.js:26}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : undefined
-        nodeName : "#document"
-        selectorPart : undefined
-        type : "LayoutInvalidationTracking"
-    }
-]
-
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-grouped-invalidations-expected.txt b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-grouped-invalidations-expected.txt
deleted file mode 100644
index 1aeae29..0000000
--- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-grouped-invalidations-expected.txt
+++ /dev/null
@@ -1,95 +0,0 @@
-Tests grouped invalidations on the timeline.
-
-paint invalidations[
-    {
-        cause : {reason: Inline CSS style declaration was mutated, stackTrace: test://evaluations/0/timeline-grouped-invalidations.js:22}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : ""
-        nodeName : "DIV class='testElement'"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-    {
-        cause : {reason: Inline CSS style declaration was mutated, stackTrace: test://evaluations/0/timeline-grouped-invalidations.js:23}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : ""
-        nodeName : "DIV class='testElement'"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-    {
-        cause : {reason: Inline CSS style declaration was mutated, stackTrace: test://evaluations/0/timeline-grouped-invalidations.js:22}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : ""
-        nodeName : "DIV class='testElement'"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-    {
-        cause : {reason: Inline CSS style declaration was mutated, stackTrace: test://evaluations/0/timeline-grouped-invalidations.js:23}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : ""
-        nodeName : "DIV class='testElement'"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-    {
-        cause : {reason: Inline CSS style declaration was mutated, stackTrace: test://evaluations/0/timeline-grouped-invalidations.js:22}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : ""
-        nodeName : "DIV class='testElement'"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-    {
-        cause : {reason: Inline CSS style declaration was mutated, stackTrace: test://evaluations/0/timeline-grouped-invalidations.js:23}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : ""
-        nodeName : "DIV class='testElement'"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-    {
-        cause : {reason: Inline CSS style declaration was mutated, stackTrace: test://evaluations/0/timeline-grouped-invalidations.js:22}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : ""
-        nodeName : "DIV class='testElement'"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-    {
-        cause : {reason: Inline CSS style declaration was mutated, stackTrace: test://evaluations/0/timeline-grouped-invalidations.js:23}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : ""
-        nodeName : "DIV class='testElement'"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-]
-PASS - record contained Inline CSS style declaration was mutated for [ DIV class='testElement' ], [ DIV class='testElement' ], and 2 others. (anonymous) @ timeline-grouped-invalidations.js:22
-PASS - record contained Inline CSS style declaration was mutated for [ DIV class='testElement' ], [ DIV class='testElement' ], and 2 others. (anonymous) @ timeline-grouped-invalidations.js:23
-
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-grouped-invalidations.js b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-grouped-invalidations.js
deleted file mode 100644
index 266dd79..0000000
--- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-misc/timeline-grouped-invalidations.js
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-(async function() {
-  TestRunner.addResult(`Tests grouped invalidations on the timeline.\n`);
-  await TestRunner.loadModule('performance_test_runner');
-  await TestRunner.showPanel('timeline');
-  await TestRunner.loadHTML(`
-    <!DOCTYPE HTML>
-    <div class="testElement">P</div><div class="testElement">A</div>
-    <div class="testElement">S</div><div class="testElement">S</div>
-  `);
-  await TestRunner.addScriptTag('../../../resources/run-after-layout-and-paint.js');
-  await TestRunner.evaluateInPagePromise(`
-    function display()
-    {
-      return new Promise(resolve => {
-        requestAnimationFrame(function() {
-          var testElements = document.body.getElementsByClassName("testElement");
-          for (var i = 0; i < testElements.length; i++) {
-            testElements[i].style.color = "red";
-            testElements[i].style.backgroundColor = "blue";
-          }
-          runAfterLayoutAndPaint(resolve);
-        });
-      });
-    }
-  `);
-
-  Runtime.experiments.enableForTest('timelineInvalidationTracking');
-
-  await PerformanceTestRunner.invokeAsyncWithTimeline('display');
-  var event = PerformanceTestRunner.findTimelineEvent(TimelineModel.TimelineModel.RecordType.Paint);
-  TestRunner.addArray(
-      TimelineModel.InvalidationTracker.invalidationEventsFor(event), PerformanceTestRunner.InvalidationFormatters,
-      '', 'paint invalidations');
-
-  var linkifier = new Components.Linkifier();
-  var target = PerformanceTestRunner.timelineModel().targetByEvent(event);
-  var contentHelper = new Timeline.TimelineDetailsContentHelper(target, linkifier, true);
-  Timeline.TimelineUIUtils._generateCauses(event, target, null, contentHelper);
-  var invalidationsTree = contentHelper.element.getElementsByClassName('invalidations-tree')[0];
-  var invalidations = invalidationsTree.shadowRoot.textContent;
-  checkStringContains(
-      invalidations,
-      `Inline CSS style declaration was mutated for [ DIV class='testElement' ], [ DIV class='testElement' ], and 2 others. (anonymous) @ timeline-grouped-invalidations.js:22`);
-  checkStringContains(
-      invalidations,
-      `Inline CSS style declaration was mutated for [ DIV class='testElement' ], [ DIV class='testElement' ], and 2 others. (anonymous) @ timeline-grouped-invalidations.js:23`);
-  TestRunner.completeTest();
-
-  function checkStringContains(string, contains) {
-    var doesContain = string.indexOf(contains) >= 0;
-    TestRunner.check(doesContain, contains + ' should be present in ' + string);
-    TestRunner.addResult('PASS - record contained ' + contains);
-  }
-})();
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations-expected.txt b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations-expected.txt
deleted file mode 100644
index 3b71d2e..0000000
--- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations-expected.txt
+++ /dev/null
@@ -1,75 +0,0 @@
-Tests the Timeline API instrumentation of multiple style recalc invalidations and ensures they are all collected on the paint event.
-
-first style recalc[
-    {
-        cause : {reason: Element has pending invalidation list, stackTrace: test://evaluations/0/timeline-paint-and-multiple-style-invalidations.js:29}
-        changedAttribute : undefined
-        changedClass : "red"
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : undefined
-        nodeName : "DIV id='testElementOne' class='red'"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-]
-second style recalc[
-    {
-        cause : {reason: Element has pending invalidation list, stackTrace: test://evaluations/0/timeline-paint-and-multiple-style-invalidations.js:31}
-        changedAttribute : undefined
-        changedClass : "snow"
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : undefined
-        nodeName : "DIV id='testElementOne' class='snow'"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-    {
-        cause : {reason: Element has pending invalidation list, stackTrace: test://evaluations/0/timeline-paint-and-multiple-style-invalidations.js:31}
-        changedAttribute : undefined
-        changedClass : "red"
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : undefined
-        nodeName : "DIV id='testElementOne' class='snow'"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-]
-first paint[
-    {
-        cause : {reason: Element has pending invalidation list, stackTrace: test://evaluations/0/timeline-paint-and-multiple-style-invalidations.js:29}
-        changedAttribute : undefined
-        changedClass : "red"
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : undefined
-        nodeName : "DIV id='testElementOne' class='red'"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-    {
-        cause : {reason: Element has pending invalidation list, stackTrace: test://evaluations/0/timeline-paint-and-multiple-style-invalidations.js:31}
-        changedAttribute : undefined
-        changedClass : "snow"
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : undefined
-        nodeName : "DIV id='testElementOne' class='snow'"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-    {
-        cause : {reason: Element has pending invalidation list, stackTrace: test://evaluations/0/timeline-paint-and-multiple-style-invalidations.js:31}
-        changedAttribute : undefined
-        changedClass : "red"
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : undefined
-        nodeName : "DIV id='testElementOne' class='snow'"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-]
-
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations.js b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations.js
deleted file mode 100644
index 6652a04..0000000
--- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations.js
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-(async function() {
-  TestRunner.addResult(
-      `Tests the Timeline API instrumentation of multiple style recalc invalidations and ensures they are all collected on the paint event.\n`);
-  await TestRunner.loadModule('performance_test_runner');
-  await TestRunner.showPanel('timeline');
-  await TestRunner.loadHTML(`
-      <!DOCTYPE HTML>
-      <style>
-          .testHolder > .red { background-color: red; }
-          .testHolder > .green { background-color: green; }
-          .testHolder > .blue { background-color: blue; }
-          .testHolder > .snow { background-color: snow; }
-          .testHolder > .red .dummy { }
-          .testHolder > .green .dummy { }
-          .testHolder > .blue .dummy { }
-          .testHolder > .snow .dummy { }
-      </style>
-      <div class="testHolder">
-      <div id="testElementOne">PASS</div><div id="testElementTwo">PASS</div><div id="testElementThree">PASS</div>
-      </div>
-    `);
-  await TestRunner.evaluateInPagePromise(`
-      function multipleStyleRecalcsAndDisplay()
-      {
-          document.getElementById("testElementOne").className = "red";
-          var forceStyleRecalc1 = document.body.offsetTop;
-          document.getElementById("testElementOne").className = "snow";
-          var forceStyleRecalc2 = document.body.offsetTop;
-          return waitForFrame();
-      }
-  `);
-
-  Runtime.experiments.enableForTest('timelineInvalidationTracking');
-  await PerformanceTestRunner.invokeAsyncWithTimeline('multipleStyleRecalcsAndDisplay');
-
-  PerformanceTestRunner.dumpInvalidations(
-      TimelineModel.TimelineModel.RecordType.UpdateLayoutTree, 0, 'first style recalc');
-  PerformanceTestRunner.dumpInvalidations(
-      TimelineModel.TimelineModel.RecordType.UpdateLayoutTree, 1, 'second style recalc');
-  PerformanceTestRunner.dumpInvalidations(TimelineModel.TimelineModel.RecordType.Paint, 0, 'first paint');
-  var thirdRecalc =
-      PerformanceTestRunner.findTimelineEvent(TimelineModel.TimelineModel.RecordType.UpdateLayoutTree, 2);
-  TestRunner.assertTrue(thirdRecalc === undefined, 'There should be no additional style recalc records.');
-  var secondPaint = PerformanceTestRunner.findTimelineEvent(TimelineModel.TimelineModel.RecordType.Paint, 1);
-  TestRunner.assertTrue(secondPaint === undefined, 'There should be no additional paint records.');
-
-  TestRunner.completeTest();
-})();
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations-expected.txt b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations-expected.txt
deleted file mode 100644
index 68d64a25..0000000
--- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations-expected.txt
+++ /dev/null
@@ -1,77 +0,0 @@
-Tests the Timeline API instrumentation of paint events with layout invalidations.
-
-
-Running: testLocalFrame
-paint invalidations[
-    {
-        cause : {reason: Inline CSS style declaration was mutated, stackTrace: test://evaluations/0/timeline-paint-with-layout-invalidations.js:17}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : ""
-        nodeName : "BODY"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-    {
-        cause : {reason: Inline CSS style declaration was mutated, stackTrace: test://evaluations/0/timeline-paint-with-layout-invalidations.js:18}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : ""
-        nodeName : "DIV id='testElement'"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-    {
-        cause : {reason: Style changed, stackTrace: test://evaluations/0/timeline-paint-with-layout-invalidations.js:19}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : undefined
-        nodeName : "DIV id='testElement'"
-        selectorPart : undefined
-        type : "LayoutInvalidationTracking"
-    }
-]
-
-Running: testSubframe
-second paint invalidations[
-    {
-        cause : {reason: Inline CSS style declaration was mutated, stackTrace: test://evaluations/0/timeline-paint-with-layout-invalidations.js:25}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : ""
-        nodeName : "DIV"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-    {
-        cause : {reason: Style changed, stackTrace: test://evaluations/0/timeline-paint-with-layout-invalidations.js:26}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : undefined
-        nodeName : "DIV"
-        selectorPart : undefined
-        type : "LayoutInvalidationTracking"
-    }
-    {
-        cause : {reason: Scrollbar changed, stackTrace: test://evaluations/0/timeline-paint-with-layout-invalidations.js:26}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : undefined
-        nodeName : "#document"
-        selectorPart : undefined
-        type : "LayoutInvalidationTracking"
-    }
-]
-
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node-expected.txt b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node-expected.txt
deleted file mode 100644
index 97b753c..0000000
--- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node-expected.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-Tests the Timeline API instrumentation of layout invalidations on a deleted node.
-
-
-Running: testLocalFrame
-paint invalidations[
-    {
-        cause : {reason: Inline CSS style declaration was mutated, stackTrace: test://evaluations/0/timeline-paint-with-layout-invalidations-on-deleted-node.js:17}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : ""
-        nodeName : "BODY"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-]
-
-Running: testSubframe
-
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.js b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.js
deleted file mode 100644
index bb71ff8..0000000
--- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.js
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-(async function() {
-  TestRunner.addResult(`Tests the Timeline API instrumentation of layout invalidations on a deleted node.\n`);
-  await TestRunner.loadModule('performance_test_runner');
-  await TestRunner.showPanel('timeline');
-  await TestRunner.loadHTML(`
-      <!DOCTYPE HTML>
-      <div id="testElement">FAIL - this should not be present when the test finishes.</div>
-      <iframe src="../resources/timeline-iframe-paint.html" style="position: absolute; left: 40px; top: 40px; width: 100px; height: 100px; border: none"></iframe>
-    `);
-  await TestRunner.evaluateInPagePromise(`
-      function display()
-      {
-          document.body.style.backgroundColor = "blue";
-          var element = document.getElementById("testElement");
-          element.style.width = "100px";
-          var forceLayout = document.body.offsetTop;
-          element.parentElement.removeChild(element);
-          return waitForFrame();
-      }
-
-      function updateSubframeAndDisplay()
-      {
-          var element = frames[0].document.body.children[0];
-          element.style.width = "200px";
-          var forceLayout = frames[0].document.body.offsetTop;
-          element.parentElement.removeChild(element);
-          return waitForFrame();
-      }
-  `);
-
-  Runtime.experiments.enableForTest('timelineInvalidationTracking');
-
-  TestRunner.runTestSuite([
-    async function testLocalFrame(next) {
-      await PerformanceTestRunner.invokeAsyncWithTimeline('display');
-      PerformanceTestRunner.dumpInvalidations(TimelineModel.TimelineModel.RecordType.Paint, 0, 'paint invalidations');
-      next();
-    },
-
-    async function testSubframe(next) {
-      await PerformanceTestRunner.invokeAsyncWithTimeline('updateSubframeAndDisplay');
-      // The first paint corresponds to the local frame and should have no invalidations.
-      var firstPaintEvent = PerformanceTestRunner.findTimelineEvent(TimelineModel.TimelineModel.RecordType.Paint);
-      var firstInvalidations = TimelineModel.InvalidationTracker.invalidationEventsFor(firstPaintEvent);
-      TestRunner.assertEquals(firstInvalidations, null);
-
-      // We don't invalidate paint of deleted elements which doesn't affect other elements.
-      var secondPaintEvent = PerformanceTestRunner.findTimelineEvent(TimelineModel.TimelineModel.RecordType.Paint);
-      var secondInvalidations = TimelineModel.InvalidationTracker.invalidationEventsFor(secondPaintEvent);
-      TestRunner.assertEquals(secondInvalidations, null);
-
-      next();
-    }
-  ]);
-})();
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations.js b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations.js
deleted file mode 100644
index 72a2840..0000000
--- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations.js
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-(async function() {
-  TestRunner.addResult(`Tests the Timeline API instrumentation of paint events with layout invalidations.\n`);
-  await TestRunner.loadModule('performance_test_runner');
-  await TestRunner.showPanel('timeline');
-  await TestRunner.loadHTML(`
-      <!DOCTYPE HTML>
-      <div id="testElement">PASS</div>
-      <iframe src="../resources/timeline-iframe-paint.html" style="position: absolute; left: 40px; top: 40px; width: 100px; height: 100px; border: none"></iframe>
-    `);
-  await TestRunner.evaluateInPagePromise(`
-      function display()
-      {
-          document.body.style.backgroundColor = "blue";
-          document.getElementById("testElement").style.width = "100px";
-          var forceLayout = document.body.offsetTop;
-          return waitForFrame();
-      }
-
-      function updateSubframeAndDisplay()
-      {
-          frames[0].document.body.children[0].style.width = "200px";
-          var forceLayout = frames[0].document.body.offsetTop;
-          return waitForFrame();
-      }
-  `);
-
-  Runtime.experiments.enableForTest('timelineInvalidationTracking');
-
-  TestRunner.runTestSuite([
-    async function testLocalFrame(next) {
-      await PerformanceTestRunner.invokeAsyncWithTimeline('display');
-      PerformanceTestRunner.dumpInvalidations(TimelineModel.TimelineModel.RecordType.Paint, 0, 'paint invalidations');
-      next();
-    },
-
-   async function testSubframe(next) {
-      await PerformanceTestRunner.invokeAsyncWithTimeline('updateSubframeAndDisplay');
-      // The first paint corresponds to the local frame and should have no invalidations.
-      var firstPaintEvent = PerformanceTestRunner.findTimelineEvent(TimelineModel.TimelineModel.RecordType.Paint);
-      var firstInvalidations = TimelineModel.InvalidationTracker.invalidationEventsFor(firstPaintEvent);
-      TestRunner.assertEquals(firstInvalidations, null);
-
-      // The second paint corresponds to the subframe and should have our layout/style invalidations.
-      PerformanceTestRunner.dumpInvalidations(
-          TimelineModel.TimelineModel.RecordType.Paint, 1, 'second paint invalidations');
-      next();
-    }
-  ]);
-})();
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations-expected.txt b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations-expected.txt
deleted file mode 100644
index 71ded10..0000000
--- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations-expected.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-Tests the Timeline API instrumentation of paint events with style recalc invalidations.
-
-
-Running: testLocalFrame
-first paint invalidations[
-    {
-        cause : {reason: Inline CSS style declaration was mutated, stackTrace: test://evaluations/0/timeline-paint-with-style-recalc-invalidations.js:17}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : ""
-        nodeName : "BODY"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-    {
-        cause : {reason: Inline CSS style declaration was mutated, stackTrace: test://evaluations/0/timeline-paint-with-style-recalc-invalidations.js:18}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : ""
-        nodeName : "DIV id='testElement'"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-]
-
-Running: testSubframe
-second paint invalidations[
-    {
-        cause : {reason: Inline CSS style declaration was mutated, stackTrace: test://evaluations/0/timeline-paint-with-style-recalc-invalidations.js:24}
-        changedAttribute : undefined
-        changedClass : undefined
-        changedId : undefined
-        changedPseudo : undefined
-        extraData : ""
-        nodeName : "DIV"
-        selectorPart : undefined
-        type : "StyleRecalcInvalidationTracking"
-    }
-]
-
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations.js b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations.js
deleted file mode 100644
index cc73c009..0000000
--- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-style-recalc-invalidations.js
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-(async function() {
-  TestRunner.addResult(`Tests the Timeline API instrumentation of paint events with style recalc invalidations.\n`);
-  await TestRunner.loadModule('performance_test_runner');
-  await TestRunner.showPanel('timeline');
-  await TestRunner.loadHTML(`
-      <!DOCTYPE HTML>
-      <div id="testElement">PASS</div>
-      <iframe src="../resources/timeline-iframe-paint.html" style="position: absolute; left: 40px; top: 40px; width: 100px; height: 100px; border: none"></iframe>
-    `);
-  await TestRunner.evaluateInPagePromise(`
-      function display()
-      {
-          document.body.style.backgroundColor = "blue";
-          document.getElementById("testElement").style.backgroundColor = "salmon";
-          return waitForFrame();
-      }
-
-      function updateSubframeAndDisplay()
-      {
-          frames[0].document.body.children[0].style.backgroundColor = "green";
-          return waitForFrame();
-      }
-  `);
-
-  Runtime.experiments.enableForTest('timelineInvalidationTracking');
-
-  TestRunner.runTestSuite([
-    async function testLocalFrame(next) {
-      await PerformanceTestRunner.invokeAsyncWithTimeline('display');
-      PerformanceTestRunner.dumpInvalidations(
-          TimelineModel.TimelineModel.RecordType.Paint, 0, 'first paint invalidations');
-      next();
-    },
-
-    async function testSubframe(next) {
-      await PerformanceTestRunner.invokeAsyncWithTimeline('updateSubframeAndDisplay');
-      // The first paint corresponds to the local frame and should have no invalidations.
-      var firstPaintEvent = PerformanceTestRunner.findTimelineEvent(TimelineModel.TimelineModel.RecordType.Paint);
-      var firstInvalidations = TimelineModel.InvalidationTracker.invalidationEventsFor(firstPaintEvent);
-      TestRunner.assertEquals(firstInvalidations, null);
-
-      // The second paint corresponds to the subframe and should have our style invalidations.
-      PerformanceTestRunner.dumpInvalidations(
-          TimelineModel.TimelineModel.RecordType.Paint, 1, 'second paint invalidations');
-      next();
-    }
-  ]);
-})();
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-user-verification-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-user-verification-expected.txt
new file mode 100644
index 0000000..cc77158
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-user-verification-expected.txt
@@ -0,0 +1,4 @@
+Check that the WebAuthn command addVirtualAuthenticator sets user verification
+NotAllowedError: The operation either timed out or was not allowed. See: https://w3c.github.io/webauthn/#sec-assertion-privacy.
+OK
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-user-verification.js b/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-user-verification.js
new file mode 100644
index 0000000..9e3387b
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/webauthn/webauthn-user-verification.js
@@ -0,0 +1,38 @@
+(async function(testRunner) {
+  const {page, session, dp} =
+      await testRunner.startURL(
+          "https://devtools.test:8443/inspector-protocol/webauthn/resources/webauthn-test.https.html",
+          "Check that the WebAuthn command addVirtualAuthenticator sets user verification");
+
+  // Create an authenticator that supports user verification and fails the
+  // check.
+  await dp.WebAuthn.enable();
+  const authenticatorId = (await dp.WebAuthn.addVirtualAuthenticator({
+    options: {
+      protocol: "ctap2",
+      transport: "nfc",
+      hasResidentKey: false,
+      hasUserVerification: true,
+    },
+  })).result.authenticatorId;
+  await dp.WebAuthn.setUserVerified({authenticatorId, isUserVerified: false});
+
+  // This should return a NotAllowedError.
+  testRunner.log((await session.evaluateAsync(`registerCredential({
+    authenticatorSelection: {
+      userVerification: "required"
+    }
+  })`)).status);
+
+  // Instruct the authenticator to succeed the user verification.
+  await dp.WebAuthn.setUserVerified({authenticatorId, isUserVerified: true});
+
+  // This should succeed.
+  testRunner.log((await session.evaluateAsync(`registerCredential({
+    authenticatorSelection: {
+      userVerification: "required"
+    }
+  })`)).status);
+
+  testRunner.completeTest();
+})
diff --git a/third_party/fuchsia-sdk/gen_build_defs.py b/third_party/fuchsia-sdk/gen_build_defs.py
index 67be3d6..7c8ed537 100755
--- a/third_party/fuchsia-sdk/gen_build_defs.py
+++ b/third_party/fuchsia-sdk/gen_build_defs.py
@@ -170,11 +170,12 @@
 
   # No need to build targets for these types yet.
   'dart_library': ConvertNoOp,
+  'device_profile': ConvertNoOp,
+  'documentation': ConvertNoOp,
   'host_tool': ConvertNoOp,
   'image': ConvertNoOp,
   'loadable_module': ConvertNoOp,
   'sysroot': ConvertNoOp,
-  'documentation': ConvertNoOp,
 }
 
 
@@ -193,7 +194,7 @@
       convert_function = _CONVERSION_FUNCTION_MAP.get(part['type'])
       if convert_function is None:
         raise Exception('Unexpected SDK artifact type %s in %s.' %
-                        (parsed['type'], next_part))
+                        (parsed['type'], part['meta']))
 
       converted = convert_function(parsed)
       if converted:
diff --git a/third_party/webxr_test_pages/README.chromium b/third_party/webxr_test_pages/README.chromium
index 5bb9adc..b5f5f71 100644
--- a/third_party/webxr_test_pages/README.chromium
+++ b/third_party/webxr_test_pages/README.chromium
@@ -42,3 +42,12 @@
    serving media like the gltf files, try using "npm serve".
    To install: `sudo npm install -g serve`
    To run: `serve .` in src/third_party/webxr_test_pages/webxr-samples
+
+To publish samples for OT:
+
+1. python make_ot_samples_folder.py webxr-samples <dest-folder>
+   That copies just the subset of samples that we want to publish.
+
+2. Serve <dest-folder> locally and make sure everything works.
+
+3. python update_bucket.py --direct-publish-samples-source=<dest-folder> --direct-publish-samples-dest=<bucket-dest-subfolder>
diff --git a/third_party/webxr_test_pages/make_ot_samples_folder.py b/third_party/webxr_test_pages/make_ot_samples_folder.py
new file mode 100755
index 0000000..34ab7e5
--- /dev/null
+++ b/third_party/webxr_test_pages/make_ot_samples_folder.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import shutil
+import sys
+
+samples_pages = [
+  'xr-barebones.html',
+  'magic-window.html',
+  'teleportation.html',
+  'gamepad.html'
+]
+
+other_pages = [
+  'attribution.html',
+  'favicon-32x32.png',
+  'favicon-96x96.png',
+  'favicon.ico',
+  'LICENSE.md'
+]
+
+copy_folders = [
+  'css',
+  'js',
+  'media' # Won't be uploaded.
+]
+
+def make_ot_samples_folder(source, dest):
+  os.mkdir(dest)
+  for f in samples_pages:
+    shutil.copy(os.path.join(source, f), dest)
+  for f in other_pages:
+    shutil.copy(os.path.join(source, f), dest)
+  for f in copy_folders:
+    shutil.copytree(os.path.join(source, f), os.path.join(dest, f))
+  shutil.copy(
+    os.path.join(source, 'index.published.html'),
+    os.path.join(dest, 'index.html'))
+
+def main():
+  make_ot_samples_folder(sys.argv[1], sys.argv[2])
+
+if __name__ == '__main__':
+  main()
diff --git a/third_party/webxr_test_pages/update_bucket.py b/third_party/webxr_test_pages/update_bucket.py
index f06b94c..3b42cc0 100755
--- a/third_party/webxr_test_pages/update_bucket.py
+++ b/third_party/webxr_test_pages/update_bucket.py
@@ -137,6 +137,15 @@
   # misconfigured. Sanity check and fix if needed.
   check_and_fix_content_types(destination)
 
+def direct_publish_samples(source, dest_subfolder):
+  destination = 'gs://chromium-webxr-samples' + '/' + dest_subfolder
+  run_modify('gsutil.py', '-m', 'rsync', '-x', 'media', '-r', './' + source,
+          destination)
+
+  # The copy used mime types based on system-local mappings which may be
+  # misconfigured. Sanity check and fix if needed.
+  check_and_fix_content_types(destination)
+
 def check_and_fix_content_types(destination):
   mimetypes.init()
   for suffix, content_type in SUFFIX_TYPES.iteritems():
@@ -269,6 +278,12 @@
   parser.add_argument('--bucket', default=BUCKET,
                       help=("Destination Cloud Storage location, including "
                             "'gs://' prefix"))
+  parser.add_argument('--direct-publish-samples-source', default=None,
+                      help=("Publish samples from this folder directly to a "
+                            "bucket."))
+  parser.add_argument('--direct-publish-samples-dest', default=None,
+                      help=("Publish samples directly to this subfolder in the "
+                            "chromium-webxr-samples bucket."))
 
   global g_flags
   g_flags = parser.parse_args()
@@ -283,6 +298,12 @@
   if os.path.isdir(node_modules):
     raise Exception('Please delete the obsolete directory "%s"' % node_modules)
 
+  if g_flags.direct_publish_samples_source and g_flags.direct_publish_samples_dest:
+    direct_publish_samples(
+      g_flags.direct_publish_samples_source,
+      g_flags.direct_publish_samples_dest)
+    return
+
   need_index_update = False
   if g_flags.update_index_only:
     need_index_update = True
diff --git a/third_party/webxr_test_pages/webxr-samples/attribution.html b/third_party/webxr_test_pages/webxr-samples/attribution.html
new file mode 100644
index 0000000..d3db771
--- /dev/null
+++ b/third_party/webxr_test_pages/webxr-samples/attribution.html
@@ -0,0 +1,154 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset='utf-8'>
+    <meta http-equiv='X-UA-Compatible' content='chrome=1'>
+    <meta name='viewport' content='width=device-width, initial-scale=1'>
+    <meta name='mobile-web-app-capable' content='yes'>
+    <meta name='apple-mobile-web-app-capable' content='yes'>
+
+    <meta name='twitter:card' content='summary'>
+    <meta name='twitter:title' content='WebXR Samples'>
+    <meta name='twitter:description' content='Sample WebXR pages for testing and reference'>
+
+    <link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png">
+    <link rel="icon" type="image/png" sizes="96x96" href="favicon-96x96.png">
+
+    <link rel='stylesheet' href='css/stylesheet.css'>
+    <link rel='stylesheet' href='css/pygment_trac.css'>
+
+    <style>
+      article {
+        position: relative;
+        padding: 0.5em;
+        background-color: rgba(255, 255, 255, 0.90);
+        margin-bottom: 1em;
+        border-radius: 3px;
+      }
+
+      article h3 {
+        font-size: 1.0em;
+        margin-top: 0px;
+        margin-bottom: 0px;
+      }
+
+      article h3::before {
+        display: inline-block;
+        content: attr(data-index) ' - ';
+        font-weight: bold;
+        white-space: nowrap;
+        margin-right: 0.2em;
+      }
+
+      article h4 {
+        position: absolute;
+        right: 0.5em;
+        top: 0.5em;
+        margin-top: 0px;
+        margin-bottom: 0px;
+      }
+
+      article p {
+        margin: 0.5em;
+      }
+
+      article .links {
+        margin-left: 0.5em;
+        margin-right: 0.5em;
+      }
+
+      article a {
+        display: inline-block;
+      }
+
+      article a:not(:first-child)::before {
+        display: inline-block;
+        content: '•';
+        font-weight: bold;
+        white-space: nowrap;
+        margin-left: 0.5em;
+        margin-right: 0.5em;
+      }
+
+      .github-link {
+        font-size: 0.8em;
+      }
+    </style>
+
+    <!--[if lt IE 9]>
+    <script src='https://html5shiv.googlecode.com/svn/trunk/html5.js'></script>
+    <![endif]-->
+    <title>Models Attribution</title>
+  </head>
+  <body>
+    <p>
+      <b>Camp</b><br>
+      All models used in this scene are licensed under [CC-BY 3.0](https://creativecommons.org/licenses/by/3.0/legalcode).<br>
+"Campground" scene by Brandon Jones.<br>
+"[Lowpoly Squirrel](https://poly.google.com/view/eGdXC-5V2wM)" model by Tipatat Chennavasin.<br>
+"[Fox](https://poly.google.com/view/1DsQKS4G-aj)" model by Jake Blakeley.<br>
+"[Tent](https://poly.google.com/view/2tvQrMLf_tP)" model by Jarlan Perez.<br>
+"[Pine Tree](https://poly.google.com/view/2Qo-fmVKuSG)" and "[Pastel Plume Flowers](https://poly.google.com/view/eLVv17bTyB-)" models by Danny Bittman.<br>
+    </p>
+    <p>
+      <b>Cave</b><br>
+      All models used in this scene are licensed under [CC-BY 3.0](https://creativecommons.org/licenses/by/3.0/legalcode).<br>
+"Cave" scene by Brandon Jones.<br>
+"[Mushroom](https://poly.google.com/view/2DAaKHD48ZP)" and "[Bat](https://poly.google.com/view/fzJn9xTT-UO)" models by Poly by Google.<br>
+"[Crystal Cluster](https://poly.google.com/view/6NY2BPvOISW)" model by Lee Mason.<br>
+"[Tree-2](https://poly.google.com/view/cRipmFHCEVU)" model by Trackball.<br>
+    </p>
+    <p>
+      <b>Controller</b><br>
+      "[controller](https://poly.google.com/view/cdts4fBVXe7)" model by Jack Brookes is licensed under [CC-BY 3.0](https://creativecommons.org/licenses/by/3.0/legalcode).<br>
+      Minor edits by Brandon Jones.<br>
+    </p>
+    <p>
+      <b>Cube Room</b><br>
+      "[Cube Room](https://poly.google.com/view/1fahMeqZOw_)" model by Naomi Chen is licensed under [CC-BY 3.0](https://creativecommons.org/licenses/by/3.0/legalcode).<br>
+    </p>
+    <p>
+      <b>Garage</b><br>
+All models used in this scene are licensed under [CC-BY 3.0](https://creativecommons.org/licenses/by/3.0/legalcode).<br>
+"Garage" scene by Brandon Jones.<br>
+"[Light Switch](https://poly.google.com/view/7yVvvpp-ftQ)", "[CRT Monitor](https://poly.google.com/view/8jVB0zIXKCv)", "[Fire Extinguisher](https://poly.google.com/view/71rR7PaeXNN)", "[Wooden Stool](https://poly.google.com/view/dn419U6vWYx)", "[Cork Board](https://poly.google.com/view/5Ql0Sdq6fmy)", "[Industrial Broom](https://poly.google.com/view/eH6PcHmWOdK)", "[Wall Shelf](https://poly.google.com/view/7544dJq1UVu)", and "[HTC Vive Headset](https://poly.google.com/view/bFZbl-mmCeD)" models by Jarlan Perez.<br>
+"[Red Cooler](https://poly.google.com/view/f7q6m6IL8UI)" model by S. Paul Michael.<br>
+"[Ladder](https://poly.google.com/view/32UszyQQLtJ)" model by Carwyn Pelley.<br>
+"[Window](https://poly.google.com/view/dwBpM-aSA_t)" model by Justin Randall.<br>
+"[SNES](https://poly.google.com/view/7yVvvpp-ftQ)" model by Gabriel Valdivia.<br>
+    </p>
+    <p>
+      <b>Headset</b><br>
+      "[VR Headset](https://poly.google.com/view/bvd33G7Q66m)" model by Poly by Google is licensed under [CC-BY 3.0](https://creativecommons.org/licenses/by/3.0/legalcode).<br>
+    </p>
+    <p>
+      <b>Home Theater</b><br>
+All models used in this scene are licensed under [CC-BY 3.0](https://creativecommons.org/licenses/by/3.0/legalcode).<br>
+"[Home Theater](https://poly.google.com/view/6wJboiESaWR)" scene by Brandon Jones.<br>
+"[Projector](https://poly.google.com/view/4oVHZbDvwV8)" and "[Window](https://poly.google.com/view/9FqbXmzB-CS)" models by Jonathan Granskog.<br>
+"[Woonkamerkast](https://poly.google.com/view/70n22Lhssat)" model by Vincent van de Goolberg.<br>
+"[Nice Door](https://poly.google.com/view/00xFHE4LR_6)" model by Wesley Thompson.<br>
+    </p>
+    <p>
+      <b>Space</b><br>
+      "[Solar System](https://poly.google.com/view/8hnnpNiQMmy)" model by Jarlan Perez is licensed under [CC-BY 3.0](https://creativecommons.org/licenses/by/3.0/legalcode).<br>
+    </p>
+    <p>
+      <b>Stereo</b><br>
+      "[Stereo](https://poly.google.com/view/5gXgHgP-dmh)" model by Poly by Google is licensed under [CC-BY 3.0](https://creativecommons.org/licenses/by/3.0/legalcode).<br>
+    </p>
+    <p>
+      <b>Sunflower</b><br>
+      All models used in this application are licensed under [CC-BY 3.0](https://creativecommons.org/licenses/by/3.0/legalcode).<br>
+      "[Sunflower](https://poly.google.com/view/ce4GXw3VYE5)" by Poly by Google.<br>
+    </p>
+    <p>
+      <b>Textures</b><br>
+      "[Le panorama de la Voie Lactée](http://www.eso.org/public/images/eso0932a/)" image by European Southern Observatory is licensed under [CC-BY 4.0](https://creativecommons.org/licenses/by/4.0/legalcode).<br>
+    </p>
+    <p>
+      <b>Video</b><br>
+      "[Big Buck Bunny](https://peach.blender.org/about/)" by the [Blender Foundation](www.blender.org) is licensed under [CC-BY 3.0](https://creativecommons.org/licenses/by/3.0/legalcode).<br>
+    </p>
+  </body>
+</html>
diff --git a/third_party/webxr_test_pages/webxr-samples/css/stylesheet.css b/third_party/webxr_test_pages/webxr-samples/css/stylesheet.css
index d63a1194..32272730 100644
--- a/third_party/webxr_test_pages/webxr-samples/css/stylesheet.css
+++ b/third_party/webxr_test_pages/webxr-samples/css/stylesheet.css
@@ -69,13 +69,12 @@
 }
 
 .wordmark > span {
-  background: #2ea;
+  background: #369;
   box-shadow: 3px 3px 0 0 rgba(0,0,0,.15);
   color: #fff;
   display: inline-block;
-  font-size: 64px;
-  font-size: calc(16px + 1vh + 3vw);  /* Responsive font-size for mobile */
-  font-style: italic;
+  font-size: 48px;
+  /*font-size: calc(16px + 1vh + 3vw);*/  /* Responsive font-size for mobile */
   font-weight: 300;
   margin-bottom: 15px;
   max-width: 100%;
@@ -88,7 +87,7 @@
 }
 
 .wordmark:hover > span {
-  background: #2ea;
+  background: #369;
   box-shadow: 3px 3px 0 0 rgba(0,0,0,.25);
 }
 
diff --git a/third_party/webxr_test_pages/webxr-samples/gamepad.html b/third_party/webxr_test_pages/webxr-samples/gamepad.html
index 1b02c53..290273d 100644
--- a/third_party/webxr_test_pages/webxr-samples/gamepad.html
+++ b/third_party/webxr_test_pages/webxr-samples/gamepad.html
@@ -26,8 +26,8 @@
     <meta name='mobile-web-app-capable' content='yes'>
     <meta name='apple-mobile-web-app-capable' content='yes'>
 
-    <!-- Origin Trial Token, feature = WebXR Device API, origin = https://immersive-web.github.io, expires = 2018-08-28 -->
-<meta http-equiv="origin-trial" data-feature="WebXR Device API" data-expires="2018-08-28" content="AnNpu7ceXvLew05ccD8Zr1OZsdZiB2hLQKK82kTTMDwF7oRKtP3QEJ4RzkeHrmB8Sq0vSV6ZNmszpBCZ0I8p9gAAAABceyJvcmlnaW4iOiJodHRwczovL2ltbWVyc2l2ZS13ZWIuZ2l0aHViLmlvOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZSIsImV4cGlyeSI6MTUzNTQxNDQwMH0=">
+    <!-- Origin Trial Token, feature = WebXR Device API (For Chrome M76+), origin = storage.googleapis.com, expires = 2019-07-24 -->
+    <meta http-equiv="origin-trial" data-feature="WebXR Device API (For Chrome M76+)" data-expires="2019-07-24" content="Ap6io/uhkGK7vXCD+golNnQfj8wJ4so790EzZoqb8YOljMXIBTvBEQFPTHYIz5d/BgtuwZTKOLrmHAOt30f38g8AAABxeyJvcmlnaW4iOiJodHRwczovL3N0b3JhZ2UuZ29vZ2xlYXBpcy5jb206NDQzIiwiZmVhdHVyZSI6IldlYlhSRGV2aWNlTTc2IiwiZXhwaXJ5IjoxNTY0MDA5MzU2LCJpc1N1YmRvbWFpbiI6dHJ1ZX0=">
 
     <title>Gamepad</title>
 
@@ -130,6 +130,10 @@
           this.color_state = !this.color_state;
         }
 
+        // If this was something like a full-fledged game instead of just a
+        // sample, timestamps should be used when calculating how much to move
+        // on each frame. The way this code is right now, having a higher frame
+        // rate means the boxes move faster.
         move(dx, dy) {
           const inv_speed = 100;
           let translation = [dx / inv_speed, dy / inv_speed, 0];
@@ -138,7 +142,7 @@
 
         // Returns true iff button which was previously pressed is not pressed
         // anymore. The WebXR + Gamepad APIs don't support button press events
-        // which is why keeping track of the state this way is necessary.
+        // (yet) which is why keeping track of the state this way is necessary.
         update_button_state(is_button_pressed) {
           let did_button_fire = this.is_button_pressed && !is_button_pressed;
           this.is_button_pressed = is_button_pressed;
@@ -215,6 +219,8 @@
         boxTable[hand].update_state(gamepad);
       }
 
+      // Don't bother starting an inline session in this sample since WebXR
+      // gamepads are not available during inline sessions.
       function initXR() {
         xrButton = new XRDeviceButton({
           onRequestSession: onRequestSession,
@@ -294,6 +300,7 @@
         scene.startFrame();
         session.requestAnimationFrame(onXRFrame);
 
+        // Check for and respond to any gamepad state changes.
         for (let source of session.inputSources) {
           if (source.gamepad) {
             ProcessGamepad(source.gamepad, source.handedness);
diff --git a/third_party/webxr_test_pages/webxr-samples/index.published.html b/third_party/webxr_test_pages/webxr-samples/index.published.html
new file mode 100644
index 0000000..17f0594
--- /dev/null
+++ b/third_party/webxr_test_pages/webxr-samples/index.published.html
@@ -0,0 +1,161 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset='utf-8'>
+    <meta http-equiv='X-UA-Compatible' content='chrome=1'>
+    <meta name='viewport' content='width=device-width, initial-scale=1'>
+    <meta name='mobile-web-app-capable' content='yes'>
+    <meta name='apple-mobile-web-app-capable' content='yes'>
+
+    <meta name='twitter:card' content='summary'>
+    <meta name='twitter:title' content='WebXR Samples'>
+    <meta name='twitter:description' content='Sample WebXR pages for testing and reference'>
+
+    <link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png">
+    <link rel="icon" type="image/png" sizes="96x96" href="favicon-96x96.png">
+
+    <link rel='stylesheet' href='css/stylesheet.css'>
+    <link rel='stylesheet' href='css/pygment_trac.css'>
+
+    <style>
+      article {
+        position: relative;
+        padding: 0.5em;
+        background-color: rgba(255, 255, 255, 0.90);
+        margin-bottom: 1em;
+        border-radius: 3px;
+      }
+
+      article h3 {
+        font-size: 1.0em;
+        margin-top: 0px;
+        margin-bottom: 0px;
+      }
+
+      article h3::before {
+        display: inline-block;
+        content: attr(data-index) ' - ';
+        font-weight: bold;
+        white-space: nowrap;
+        margin-right: 0.2em;
+      }
+
+      article h4 {
+        position: absolute;
+        right: 0.5em;
+        top: 0.5em;
+        margin-top: 0px;
+        margin-bottom: 0px;
+      }
+
+      article p {
+        margin: 0.5em;
+      }
+
+      article .links {
+        margin-left: 0.5em;
+        margin-right: 0.5em;
+      }
+
+      article a {
+        display: inline-block;
+      }
+
+      article a:not(:first-child)::before {
+        display: inline-block;
+        content: '•';
+        font-weight: bold;
+        white-space: nowrap;
+        margin-left: 0.5em;
+        margin-right: 0.5em;
+      }
+
+      .github-link {
+        font-size: 0.8em;
+      }
+    </style>
+
+    <!--[if lt IE 9]>
+    <script src='https://html5shiv.googlecode.com/svn/trunk/html5.js'></script>
+    <![endif]-->
+    <title>WebXR - Samples</title>
+  </head>
+  <body>
+
+    <div class='container' id='container'>
+        <h1><a href='' class='wordmark'><span>WebXR Samples for Chrome</span></a></h1>
+      </header>
+
+      <main class='main' id='main'>
+        <p>Sample pages demonstrating how to use various aspects of the WebXR API <b><em>as implemented in Chrome versions 76-77.</b></em><br/>
+
+        <script>
+          let pages = [
+            { title: 'Barebones', category: 'Basics',
+              path: 'xr-barebones.html',
+              description: 'Extremely simple use of WebXR with no library dependencies. Doesn\'t render anything exciting.' },
+
+            { title: 'Magic Window', category: 'Basics',
+              path: 'magic-window.html',
+              description: 'Demonstrates use of a non-exclusive XRSession to present "Magic Window" content.' },
+
+            { title: 'Teleportation', category: 'Spatial Tracking, Input',
+              path: 'teleportation.html',
+              description: 'Demonstrates teleporting the viewer by updating the XRSession reference space.' },
+
+            { title: 'Gamepad', category: 'Input',
+              path: 'gamepad.html',
+              description: 'Demonstrates handling input from Gamepads attached to XRInputSources.' }
+          ];
+
+          let mainElement = document.getElementById("main");
+
+          // Append an element for every item in the pages list.
+          let tag_count = 0;
+          for (var i = 0; i < pages.length; ++i) {
+            var page = pages[i];
+
+            if (page.tag) {
+              tag_count++;
+              mainElement.appendChild(document.createElement(page.tag));
+              continue;
+            }
+
+            let article = document.createElement('article');
+
+            let title = document.createElement('h3');
+            title.setAttribute('data-index', i + 1 - tag_count);
+
+            let titleLink = document.createElement('a');
+            titleLink.href = page.path;
+            titleLink.innerHTML = page.title;
+            title.appendChild(titleLink);
+            article.appendChild(title);
+
+            let category = document.createElement('h4');
+            category.innerHTML = page.category;
+            article.appendChild(category);
+
+            let description = document.createElement('p');
+            description.innerHTML = page.description;
+            article.appendChild(description);
+
+            let links = document.createElement('div');
+            links.classList.add('links');
+
+            article.appendChild(links);
+
+            mainElement.appendChild(article);
+          }
+        </script>
+      </main>
+
+      <p>Models used in these samples come from <a href="https://poly.google.com">Poly</a>, and many were modeled in <a href="https://vr.google.com/blocks/">Blocks</a>.<br/>
+      They are stored and loaded using the <a href="https://www.khronos.org/gltf/">glTF 2.0 format</a>.<br/>
+      Attribution for individual models can be found <a href="attribution.html">here</a>.</p>
+
+      <footer class='footer'>
+      </footer>
+    </div>
+  </body>
+</html>
diff --git a/third_party/webxr_test_pages/webxr-samples/magic-window.html b/third_party/webxr_test_pages/webxr-samples/magic-window.html
index 9413131..050930b 100644
--- a/third_party/webxr_test_pages/webxr-samples/magic-window.html
+++ b/third_party/webxr_test_pages/webxr-samples/magic-window.html
@@ -26,8 +26,8 @@
     <meta name='mobile-web-app-capable' content='yes'>
     <meta name='apple-mobile-web-app-capable' content='yes'>
 
-    <!-- Origin Trial Token, feature = WebXR Device API, origin = https://immersive-web.github.io, expires = 2018-08-28 -->
-<meta http-equiv="origin-trial" data-feature="WebXR Device API" data-expires="2018-08-28" content="AnNpu7ceXvLew05ccD8Zr1OZsdZiB2hLQKK82kTTMDwF7oRKtP3QEJ4RzkeHrmB8Sq0vSV6ZNmszpBCZ0I8p9gAAAABceyJvcmlnaW4iOiJodHRwczovL2ltbWVyc2l2ZS13ZWIuZ2l0aHViLmlvOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZSIsImV4cGlyeSI6MTUzNTQxNDQwMH0=">
+    <!-- Origin Trial Token, feature = WebXR Device API (For Chrome M76+), origin = storage.googleapis.com, expires = 2019-07-24 -->
+    <meta http-equiv="origin-trial" data-feature="WebXR Device API (For Chrome M76+)" data-expires="2019-07-24" content="Ap6io/uhkGK7vXCD+golNnQfj8wJ4so790EzZoqb8YOljMXIBTvBEQFPTHYIz5d/BgtuwZTKOLrmHAOt30f38g8AAABxeyJvcmlnaW4iOiJodHRwczovL3N0b3JhZ2UuZ29vZ2xlYXBpcy5jb206NDQzIiwiZmVhdHVyZSI6IldlYlhSRGV2aWNlTTc2IiwiZXhwaXJ5IjoxNTY0MDA5MzU2LCJpc1N1YmRvbWFpbiI6dHJ1ZX0=">
 
     <title>Magic Window</title>
 
@@ -93,8 +93,7 @@
 
       // XR globals.
       let xrButton = null;
-      let xrImmersiveRefSpace = null;
-      let xrNonImmersiveRefSpace = null;
+      let xrRefSpaces = {};
 
       // WebGL scene globals.
       let gl = null;
@@ -126,6 +125,8 @@
 
       function onRequestSession() {
         navigator.xr.requestSession('immersive-vr').then((session) => {
+          // Keep track of the session mode so that we use the correct reference
+          // space later.
           session.mode = 'immersive-vr';
           xrButton.setSession(session);
           onSessionStarted(session);
@@ -175,7 +176,7 @@
         }, (e) => {
           if (!session.mode.startsWith('immersive')) {
             // If we're in inline mode, our underlying platform may not support
-            // the stationary reference space, but an identity space is guaranteed.
+            // the stationary reference space, but a viewer space is guaranteed.
             return session.requestReferenceSpace('viewer');
           } else {
             throw e;
@@ -183,11 +184,7 @@
         }).then((refSpace) => {
           // Since we're dealing with multple sessions now we need to track
           // which XRReferenceSpace is associated with which XRSession.
-          if (session.mode.startsWith('immersive')) {
-            xrImmersiveRefSpace = refSpace;
-          } else {
-            xrNonImmersiveRefSpace = refSpace;
-          }
+          xrRefSpaces[session.mode] = refSpace;
           session.requestAnimationFrame(onXRFrame);
         });
       }
@@ -203,6 +200,8 @@
         }
       }
 
+      // Allow the user to click and drag the mouse to adjust the viewer pose
+      // for inline sessions.
       let lookYaw = 0;
       let lookPitch = 0;
       const lookSpeed = 0.0025;
@@ -218,41 +217,79 @@
         }
       });
 
-      // Called every time a XRSession requests that a new frame be drawn.
-      function onXRFrame(t, frame) {
-        let session = frame.session;
-        // Ensure that we're using the right frame of reference for the session.
-        let refSpace = session.mode.startsWith('immersive') ?
-                         xrImmersiveRefSpace :
-                         xrNonImmersiveRefSpace;
-
-        // Account for the click-and-drag mouse movement when calculating the
-        // viewer pose.
+      // XRReferenceSpace offset is immutable, so return a new reference space
+      // that has an updated orientation.
+      function getAdjustedRefSpace(refSpace) {
+        // Represent the rotational component of the reference space as a
+        // quaternion.
         let invOrientation = quat.create();
         quat.rotateX(invOrientation, invOrientation, -lookPitch);
         quat.rotateY(invOrientation, invOrientation, -lookYaw);
         let xform = new XRRigidTransform(
             {x: 0, y: 0, z: 0},
             {x: invOrientation[0], y: invOrientation[1], z: invOrientation[2], w: invOrientation[3]});
-        refSpace = refSpace.getOffsetReferenceSpace(xform);
-        let pose = frame.getViewerPose(refSpace);
+        return refSpace.getOffsetReferenceSpace(xform);
+      }
 
+      // Called every time a XRSession requests that a new frame be drawn.
+      function onXRFrame(t, frame) {
+        let session = frame.session;
+
+        // Per-frame scene setup. Nothing WebXR specific here.
         scene.startFrame();
+
+        // Inform the session that we're ready for the next frame.
         session.requestAnimationFrame(onXRFrame);
 
+        // Ensure that we're using the right reference space for the session.
+        let refSpace = xrRefSpaces[session.mode];
+
+        // Account for the click-and-drag mouse movement when calculating the
+        // viewer pose for inline sessions.
+        if (session.mode == 'inline') {
+          refSpace = getAdjustedRefSpace(refSpace);
+        }
+
+        let pose = frame.getViewerPose(refSpace);
+
+        // In most other samples, these rendering details will be handeld by
+        // cottontail by calling scene.drawXRFrame.
         if (pose) {
           gl.bindFramebuffer(gl.FRAMEBUFFER, session.renderState.baseLayer.framebuffer);
           if (!arMode) {
             gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
           }
 
+          // Loop through each of the views reported by the frame and draw them
+          // into the corresponding viewport.
           for (let view of pose.views) {
             let viewport = session.renderState.baseLayer.getViewport(view);
             gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
+
+            // Draw this view of the scene. What happens in this function really
+            // isn't all that important. What is important is that it renders
+            // into the XRWebGLLayer's framebuffer, using the viewport into that
+            // framebuffer reported by the current view, and using the
+            // projection and view matricies from the current view and pose.
+            // We bound the framebuffer and viewport up above, and are passing
+            // in the appropriate matrices here to be used when rendering.
             scene.draw(view.projectionMatrix, view.transform.inverse.matrix);
           }
+        } else {
+          // There's several options for handling cases where no pose is given.
+          // The simplest, which these samples opt for, is to simply not draw
+          // anything. That way the device will continue to show the last frame
+          // drawn, possibly even with reprojection. Alternately you could
+          // re-draw the scene again with the last known good pose (which is now
+          // likely to be wrong), clear to black, or draw a head-locked message
+          // for the user indicating that they should try to get back to an area
+          // with better tracking. In all cases it's possible that the device
+          // may override what is drawn here to show the user it's own error
+          // message, so it should not be anything critical to the application's
+          // use.
         }
 
+        // Per-frame scene teardown. Nothing WebXR specific here.
         scene.endFrame();
       }
 
diff --git a/third_party/webxr_test_pages/webxr-samples/teleportation.html b/third_party/webxr_test_pages/webxr-samples/teleportation.html
index 20f6558..6aa3f5f 100644
--- a/third_party/webxr_test_pages/webxr-samples/teleportation.html
+++ b/third_party/webxr_test_pages/webxr-samples/teleportation.html
@@ -26,8 +26,8 @@
     <meta name='mobile-web-app-capable' content='yes'>
     <meta name='apple-mobile-web-app-capable' content='yes'>
 
-    <!-- Origin Trial Token, feature = WebXR Device API, origin = https://immersive-web.github.io, expires = 2018-08-28 -->
-<meta http-equiv="origin-trial" data-feature="WebXR Device API" data-expires="2018-08-28" content="AnNpu7ceXvLew05ccD8Zr1OZsdZiB2hLQKK82kTTMDwF7oRKtP3QEJ4RzkeHrmB8Sq0vSV6ZNmszpBCZ0I8p9gAAAABceyJvcmlnaW4iOiJodHRwczovL2ltbWVyc2l2ZS13ZWIuZ2l0aHViLmlvOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZSIsImV4cGlyeSI6MTUzNTQxNDQwMH0=">
+    <!-- Origin Trial Token, feature = WebXR Device API (For Chrome M76+), origin = storage.googleapis.com, expires = 2019-07-24 -->
+    <meta http-equiv="origin-trial" data-feature="WebXR Device API (For Chrome M76+)" data-expires="2019-07-24" content="Ap6io/uhkGK7vXCD+golNnQfj8wJ4so790EzZoqb8YOljMXIBTvBEQFPTHYIz5d/BgtuwZTKOLrmHAOt30f38g8AAABxeyJvcmlnaW4iOiJodHRwczovL3N0b3JhZ2UuZ29vZ2xlYXBpcy5jb206NDQzIiwiZmVhdHVyZSI6IldlYlhSRGV2aWNlTTc2IiwiZXhwaXJ5IjoxNTY0MDA5MzU2LCJpc1N1YmRvbWFpbiI6dHJ1ZX0=">
 
     <title>Teleportation</title>
 
@@ -76,7 +76,8 @@
       // If requested, don't display the frame rate info.
       let hideStats = QueryArgs.getBool('hideStats', false);
 
-      // XR globals.
+      // XR globals. Several additional reference spaces are required because of
+      // how the teleportation mechanic in onSelect works.
       let xrButton = null;
       let xrImmersiveRefSpaceBase = null;
       let xrImmersiveRefSpaceOffset = null;
@@ -84,6 +85,17 @@
       let xrNonImmersiveRefSpaceOffset = null;
       let xrViewerSpace = null;
 
+      // For inline sessions, use an estimated height of 1.5 meters.
+      let trackingSpaceOriginInWorldSpace = {
+        'immersive-vr' : vec3.create(),
+        'inline' : vec3.fromValues(0, 1.5, 0)
+      };
+
+      let trackingSpaceHeadingDegrees = 0;  // around +Y axis, positive angles rotate left
+      let floorSize = 10;
+      let floorPosition = [0, -floorSize / 2 + 0.01, 0];
+      let floorNode = null;
+
       // WebGL scene globals.
       let gl = null;
       let renderer = null;
@@ -97,12 +109,6 @@
 
       let boxes = [];
 
-      let trackingSpaceOriginInWorldSpace = vec3.create();
-      let trackingSpaceHeadingDegrees = 0;  // around +Y axis, positive angles rotate left
-      let floorSize = 10;
-      let floorPosition = [0, -floorSize / 2 + 0.01, 0];
-      let floorNode = null;
-
       function initXR() {
         xrButton = new XRDeviceButton({
           onRequestSession: onRequestSession,
@@ -118,6 +124,7 @@
             onSessionStarted(session);
           });
         } else {
+          // Still render the initial scene if WebXR is not available.
           initFallback();
         }
       }
@@ -147,6 +154,23 @@
         scene.addNode(boxNode);
       }
 
+      function addFloorBox() {
+        let boxBuilder = new BoxBuilder();
+        boxBuilder.pushCube([0, 0, 0], floorSize);
+        let boxPrimitive = boxBuilder.finishPrimitive(renderer);
+
+        let boxMaterial = new PbrMaterial();
+        boxMaterial.baseColorFactor.value = [0.3, 0.3, 0.3, 1.0];
+        let boxRenderPrimitive = renderer.createRenderPrimitive(boxPrimitive, boxMaterial);
+
+        floorNode = new Node();
+        floorNode.addRenderPrimitive(boxRenderPrimitive);
+        floorNode.selectable = true;
+        scene.addNode(floorNode);
+        mat4.identity(floorNode.matrix);
+        mat4.translate(floorNode.matrix, floorNode.matrix, floorPosition);
+      }
+
       function initGL() {
         if (gl)
           return;
@@ -173,26 +197,12 @@
         addBox(0.0, 1.7, -1.5, 0.0, 1.0, 0.0, boxes);
         addBox(1.0, 1.6, -1.3, 0.0, 0.0, 1.0, boxes);
 
+        // Represent the floor as a box so that we can perform a hit test
+        // against it onSelect so that we can teleport the user to that
+        // particular location.
         addFloorBox();
       }
 
-      function addFloorBox() {
-        let boxBuilder = new BoxBuilder();
-        boxBuilder.pushCube([0, 0, 0], floorSize);
-        let boxPrimitive = boxBuilder.finishPrimitive(renderer);
-
-        let boxMaterial = new PbrMaterial();
-        boxMaterial.baseColorFactor.value = [0.3, 0.3, 0.3, 1.0];
-        let boxRenderPrimitive = renderer.createRenderPrimitive(boxPrimitive, boxMaterial);
-
-        floorNode = new Node();
-        floorNode.addRenderPrimitive(boxRenderPrimitive);
-        floorNode.selectable = true;
-        scene.addNode(floorNode);
-        mat4.identity(floorNode.matrix);
-        mat4.translate(floorNode.matrix, floorNode.matrix, floorPosition);
-      }
-
       function onRequestSession() {
         const mode = 'immersive-vr';
         navigator.xr.requestSession(mode).then((session) => {
@@ -221,36 +231,52 @@
             })
         });
 
-        // Same logic for establishing a reference space as in room-scale.html
         session.requestReferenceSpace('local-floor').then((refSpace) => {
           return refSpace;
         }, (e) => {
           if (!session.mode.startsWith('immersive')) {
             // If we're in inline mode, our underlying platform may not support
-            // the stationary reference space, but an identity space is guaranteed.
-            console.log("falling back to identity reference space");
+            // the stationary reference space, but a viewer space is guaranteed.
+            console.log("falling back to viewer reference space");
             return session.requestReferenceSpace('viewer');
           } else {
             throw e;
           }
         }).then((refSpace) => {
-          // Save the session-specific reference space, and apply the
-          // current player orientation/position as originOffset.
+          // Save the session-specific base reference space, and apply the current
+          // player orientation/position as originOffset. This reference space
+          // won't change for the duration of the session and is used when
+          // updating the player position and/or orientation in onSelect.
           setRefSpace(session, refSpace, false);
           updateOriginOffset(session);
+
           session.requestReferenceSpace('viewer').then(function(viewerSpace){
+            // Save a separate reference space that represents the tracking space
+            // origin, which does not change for the duration of the session.
+            // This is used when updating the player position and/or orientation
+            // in onSelect.
             xrViewerSpace = viewerSpace;
             session.requestAnimationFrame(onXRFrame);
           });
         });
       }
 
+      // Used for updating the origin offset.
       let playerInWorldSpaceOld = vec3.create();
       let playerInWorldSpaceNew = vec3.create();
       let playerOffsetInWorldSpaceOld = vec3.create();
       let playerOffsetInWorldSpaceNew = vec3.create();
       let rotationDeltaQuat = quat.create();
+      let invPosition = vec3.create();
+      let invOrientation = quat.create();
 
+      // If the user selected a point on the floor, teleport them to that
+      // position while keeping their orientation the same.
+      // Otherwise, check if one of the boxes was selected and update the
+      // user's orientation accordingly:
+      //    left box: turn left by 30 degress
+      //    center box: reset orientation
+      //    right box: turn right by 30 degrees
       function onSelect(ev) {
         let session = ev.frame.session;
         let refSpace = getRefSpace(session, true);
@@ -262,7 +288,10 @@
         // to the player's feet. The headPose position is the head position in world space.
         // Subtract the tracking space origin position in world space to get a relative world space vector.
         vec3.set(playerInWorldSpaceOld, headPose.transform.position.x, 0, headPose.transform.position.z);
-        vec3.sub(playerOffsetInWorldSpaceOld, playerInWorldSpaceOld, trackingSpaceOriginInWorldSpace);
+        vec3.sub(
+          playerOffsetInWorldSpaceOld,
+          playerInWorldSpaceOld,
+          trackingSpaceOriginInWorldSpace[session.mode]);
 
         // based on https://github.com/immersive-web/webxr/blob/master/input-explainer.md#targeting-ray-pose
         let inputSourcePose = ev.frame.getPose(ev.inputSource.targetRaySpace, refSpace);
@@ -323,7 +352,10 @@
         trackingSpaceHeadingDegrees += rotationDelta;
 
         // Update tracking space origin so that origin + playerOffset == player location in world space
-        vec3.sub(trackingSpaceOriginInWorldSpace, playerInWorldSpaceNew, playerOffsetInWorldSpaceNew);
+        vec3.sub(
+          trackingSpaceOriginInWorldSpace[session.mode],
+          playerInWorldSpaceNew,
+          playerOffsetInWorldSpaceNew);
 
         updateOriginOffset(session);
       }
@@ -332,18 +364,19 @@
         // Compute the origin offset based on player position/orientation.
         quat.identity(invOrientation);
         quat.rotateY(invOrientation, invOrientation, -trackingSpaceHeadingDegrees * Math.PI / 180);
-        vec3.negate(invPosition, trackingSpaceOriginInWorldSpace);
+        vec3.negate(invPosition, trackingSpaceOriginInWorldSpace[session.mode]);
         vec3.transformQuat(invPosition, invPosition, invOrientation);
         let xform = new XRRigidTransform(
           {x: invPosition[0], y: invPosition[1], z: invPosition[2]},
           {x: invOrientation[0], y: invOrientation[1], z: invOrientation[2], w: invOrientation[3]});
 
-        // Update offset reference to use a new originOffset with the teleported player position and orientation.
+        // Update offset reference to use a new originOffset with the teleported
+        // player position and orientation.
         // This new offset needs to be applied to the base ref space.
         let refSpace = getRefSpace(session, false).getOffsetReferenceSpace(xform);
         setRefSpace(session, refSpace, true);
 
-        console.log('teleport to', trackingSpaceOriginInWorldSpace);
+        console.log('teleport to', trackingSpaceOriginInWorldSpace[session.mode]);
       }
 
       function onEndSession(session) {
@@ -356,9 +389,6 @@
         }
       }
 
-      let invPosition = vec3.create();
-      let invOrientation = quat.create();
-
       function getRefSpace(session, isOffset) {
         return session.mode.startsWith('immersive') ?
               (isOffset ? xrImmersiveRefSpaceOffset : xrImmersiveRefSpaceBase) :
diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids
index 3b5ef81..f73ef93 100644
--- a/tools/gritsettings/resource_ids
+++ b/tools/gritsettings/resource_ids
@@ -314,7 +314,7 @@
     "structures": [23520],
   },
   "ash/ash_strings.grd": {
-    "messages": [23530],
+    "messages": [23525],
   },
   "ash/components/ash_components_strings.grd": {
     "messages": [24100],
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 90ef0f71..49c4ab32 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -11866,6 +11866,69 @@
   <description>User pressed 'Voice Search' in the app menu.</description>
 </action>
 
+<action name="MobileMessagesBadgeAcceptedTapped">
+  <owner>sczs@chromium.org</owner>
+  <owner>thegreenfrog@chromium.org</owner>
+  <description>
+    User tapped on an accepted Infobar Message badge which displayed the Modal.
+  </description>
+</action>
+
+<action name="MobileMessagesBadgeNonAcceptedTapped">
+  <owner>sczs@chromium.org</owner>
+  <owner>thegreenfrog@chromium.org</owner>
+  <description>
+    User tapped on a non-accepted Infobar Message badge which displayed the
+    Modal.
+  </description>
+</action>
+
+<action name="MobileMessagesBannerDraggedDown">
+  <owner>sczs@chromium.org</owner>
+  <owner>thegreenfrog@chromium.org</owner>
+  <description>
+    User dragged down the Infobar Message Banner which expanded it into a Modal.
+  </description>
+</action>
+
+<action name="MobileMessagesBannerTapped">
+  <owner>sczs@chromium.org</owner>
+  <owner>thegreenfrog@chromium.org</owner>
+  <description>
+    User tapped the Infobar Message Banner which expanded it into a Modal.
+  </description>
+</action>
+
+<action name="MobileMessagesModalAcceptedTapped">
+  <owner>sczs@chromium.org</owner>
+  <owner>thegreenfrog@chromium.org</owner>
+  <description>User accepted the Infobar Modal main action.</description>
+</action>
+
+<action name="MobileMessagesModalCancelledTapped">
+  <owner>sczs@chromium.org</owner>
+  <owner>thegreenfrog@chromium.org</owner>
+  <description>
+    User dismissed the Infobar Modal without any action.
+  </description>
+</action>
+
+<action name="MobileMessagesModalNever">
+  <owner>sczs@chromium.org</owner>
+  <owner>thegreenfrog@chromium.org</owner>
+  <description>
+    User dismissed both the Infobar Modal and the InfobarBadge.
+  </description>
+</action>
+
+<action name="MobileMessagesModalSettings">
+  <owner>sczs@chromium.org</owner>
+  <owner>thegreenfrog@chromium.org</owner>
+  <description>
+    User dismissed the Infobar Modal by opening the Infobar Settings.
+  </description>
+</action>
+
 <action name="MobileMWSession">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <description>Please enter the description of this user action.</description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 5c31f07..f5783a1 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -33625,6 +33625,7 @@
   <int value="-1684773837" label="TabEngagementReportingAndroid:disabled"/>
   <int value="-1684123448" label="disable-best-effort-tasks"/>
   <int value="-1682843294" label="DataReductionProxyDecidesTransform:enabled"/>
+  <int value="-1681832882" label="shelf-scrollable"/>
   <int value="-1677715989" label="UnifiedConsent:disabled"/>
   <int value="-1676256979"
       label="AutofillUpstreamUseGooglePayOnAndroidBranding:enabled"/>
@@ -34009,6 +34010,8 @@
   <int value="-1172572865" label="NTPShowGoogleGInOmnibox:enabled"/>
   <int value="-1172204005" label="enable-offline-auto-reload-visible-only"/>
   <int value="-1167992523" label="DesktopPWAsCustomTabUI:disabled"/>
+  <int value="-1166745977"
+      label="BluetoothAggressiveAppearanceFilter:disabled"/>
   <int value="-1166715563" label="ChromeOSAssistant:disabled"/>
   <int value="-1165191758" label="ForegroundNotificationManager:disabled"/>
   <int value="-1164858657" label="CrostiniUsbAllowUnsupported:disabled"/>
@@ -34627,6 +34630,7 @@
   <int value="-241353344" label="MidiManagerWinrt:disabled"/>
   <int value="-240531943" label="ContextualSearchRankerQuery:disabled"/>
   <int value="-239616243" label="HighDynamicRange:enabled"/>
+  <int value="-239176328" label="BluetoothAggressiveAppearanceFilter:enabled"/>
   <int value="-234966279" label="PointerEvent:disabled"/>
   <int value="-234687894"
       label="NonValidatingReloadOnRefreshContentV2:disabled"/>
@@ -35857,6 +35861,7 @@
   <int value="1614309501" label="DataSaverLiteModeRebranding:enabled"/>
   <int value="1614596813" label="CloseButtonsInactiveTabs:disabled"/>
   <int value="1615988672" label="GrantNotificationsToDSE:enabled"/>
+  <int value="1616782064" label="shelf-dense-clamshell"/>
   <int value="1616938915"
       label="OmniboxUIExperimentWhiteBackgroundOnBlur:disabled"/>
   <int value="1617187093" label="enable-improved-a2hs"/>
@@ -58099,6 +58104,10 @@
 </enum>
 
 <enum name="UserActivationFrameResultEnum">
+  <obsolete>
+    This was added to assess possible impact of UserActivationV2, by comparing
+    pre- and post-launch stats.
+  </obsolete>
   <int value="0" label="NullFailure"/>
   <int value="1" label="NullSuccess"/>
   <int value="2" label="SelfFailure"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index a486d48c..a548266 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -2721,15 +2721,17 @@
   <summary>Records how the omnibox was focused.</summary>
 </histogram>
 
-<histogram name="Android.PackageStats.CacheSize" units="MB" expires_after="M77">
+<histogram name="Android.PackageStats.CacheSize" units="MB" expires_after="M86">
   <owner>nyquist@chromium.org</owner>
+  <owner>yfriedman@chromium.org</owner>
   <summary>
     Records the size of the user's cache at startup on Android O and above.
   </summary>
 </histogram>
 
-<histogram name="Android.PackageStats.CodeSize" units="MB" expires_after="M77">
+<histogram name="Android.PackageStats.CodeSize" units="MB" expires_after="M86">
   <owner>nyquist@chromium.org</owner>
+  <owner>yfriedman@chromium.org</owner>
   <summary>
     At startup, records the space on disk taken by Chrome application including
     APK resources, compiled libraries, and extracted native code. Only recorded
@@ -2737,8 +2739,9 @@
   </summary>
 </histogram>
 
-<histogram name="Android.PackageStats.DataSize" units="MB" expires_after="M77">
+<histogram name="Android.PackageStats.DataSize" units="MB" expires_after="M86">
   <owner>nyquist@chromium.org</owner>
+  <owner>yfriedman@chromium.org</owner>
   <summary>
     Records the size of the user's data directory at startup on Android O and
     above. Does not include cache size.
@@ -10190,14 +10193,18 @@
 
 <histogram name="Autofill.SuggestionAcceptedIndex" units="position">
   <owner>mathp@chromium.org</owner>
-  <summary>The index of the accepted Autofill suggestion in the popup.</summary>
+  <summary>
+    The index of the accepted Autofill suggestion in the popup. Due to
+    crbug.com/966411, the iOS data is incorrect.
+  </summary>
 </histogram>
 
 <histogram name="Autofill.SuggestionAcceptedIndex.Autocomplete"
     units="position">
   <owner>mathp@chromium.org</owner>
   <summary>
-    The index of the accepted Autocomplete suggestion in the popup.
+    The index of the accepted Autocomplete suggestion in the popup. Due to
+    crbug.com/966411, the iOS data is incorrect.
   </summary>
 </histogram>
 
@@ -12770,6 +12777,10 @@
 
 <histogram name="Blink.Gesture.Merged" enum="GestureMergeState"
     expires_after="M77">
+  <obsolete>
+    UserActivationV2 made UserGestureTokens obselete, so the merge stats is now
+    irrelevant.
+  </obsolete>
   <owner>jyasskin@chromium.org</owner>
   <owner>domenic@google.com</owner>
   <summary>
@@ -23924,7 +23935,7 @@
 </histogram>
 
 <histogram name="DataReductionProxy.DaysSinceEnabled" units="days"
-    expires_after="M77">
+    expires_after="M82">
   <owner>tbansal@chromium.org</owner>
   <owner>bengr@chromium.org</owner>
   <summary>
@@ -32005,7 +32016,7 @@
 </histogram>
 
 <histogram name="Enterprise.EnrollmentForced" enum="EnterpriseEnrollmentType"
-    expires_after="M77">
+    expires_after="M85">
   <owner>tnagel@chromium.org</owner>
   <summary>
     Events related to forced re-enrollment (FRE) of Chrome OS devices.
@@ -32013,7 +32024,7 @@
 </histogram>
 
 <histogram name="Enterprise.EnrollmentForcedAttestationBased"
-    enum="EnterpriseEnrollmentType" expires_after="M77">
+    enum="EnterpriseEnrollmentType" expires_after="M85">
   <owner>drcrash@chromium.org</owner>
   <summary>
     Events related to attestation-based re-enrollment (Auto RE) of Chrome OS
@@ -32849,7 +32860,7 @@
 </histogram>
 
 <histogram name="Event.AsyncTargeting.ResponseTime" units="ms"
-    expires_after="M77">
+    expires_after="M79">
   <owner>riajiang@chromium.org</owner>
   <summary>
     Tracks how long it takes for a client to respond to an asynchronous request
@@ -54022,11 +54033,16 @@
 
 <histogram name="Media.AudioChannelLayout" enum="ChannelLayout"
     expires_after="M77">
+  <obsolete>
+    Deprecated 06/2019 in issue 975301.
+  </obsolete>
   <owner>dalecurtis@chromium.org</owner>
   <summary>Audio channel layout in HTML5 media.</summary>
 </histogram>
 
-<histogram name="Media.AudioCodec" enum="AudioCodec">
+<histogram name="Media.AudioCodec" enum="AudioCodec" expires_after="never">
+<!-- expires-never: Codec support planning metric. -->
+
   <owner>dalecurtis@chromium.org</owner>
   <summary>Audio codec used in HTML5 media.</summary>
 </histogram>
@@ -54292,6 +54308,9 @@
 
 <histogram name="Media.AudioSampleFormat" enum="AudioSampleFormat"
     expires_after="M77">
+  <obsolete>
+    Deprecated 06/2019 in issue 975301.
+  </obsolete>
   <owner>dalecurtis@chromium.org</owner>
   <summary>
     Audio sample format in HTML5 media. Logged when Audio Decoder initializes.
@@ -54299,12 +54318,18 @@
 </histogram>
 
 <histogram name="Media.AudioSamplesPerSecond" enum="AudioSampleRate">
+  <obsolete>
+    Deprecated 06/2019 in issue 975301.
+  </obsolete>
   <owner>dalecurtis@chromium.org</owner>
   <summary>Audio samples per second in HTML5 media.</summary>
 </histogram>
 
 <histogram name="Media.AudioSamplesPerSecondUnexpected" units="Hz"
     expires_after="M77">
+  <obsolete>
+    Deprecated 06/2019 in issue 975301.
+  </obsolete>
   <owner>dalecurtis@chromium.org</owner>
   <summary>
     Audio samples per second in HTML5 media (atypical values, in Hz).
@@ -54815,7 +54840,9 @@
 </histogram>
 
 <histogram name="Media.DetectedAudioCodecHash" enum="FFmpegCodecHashes"
-    expires_after="M77">
+    expires_after="never">
+<!-- expires-never: Codec support planning metric. -->
+
   <owner>media-dev@chromium.org</owner>
   <summary>
     Audio codec used in HTML5 media. Reporting corrected in M51 to include all
@@ -54824,13 +54851,19 @@
   </summary>
 </histogram>
 
-<histogram name="Media.DetectedAudioCodecHash.Local" enum="FFmpegCodecHashes">
+<histogram name="Media.DetectedAudioCodecHash.Local" enum="FFmpegCodecHashes"
+    expires_after="never">
+<!-- expires-never: Codec support planning metric. -->
+
   <owner>media-dev@chromium.org</owner>
   <summary>Audio codec used in HTML5 media for a local file playback.</summary>
 </histogram>
 
-<histogram name="Media.DetectedContainer" enum="MediaContainers">
-  <owner>jrummell@chromium.org</owner>
+<histogram name="Media.DetectedContainer" enum="MediaContainers"
+    expires_after="never">
+<!-- expires-never: Codec support planning metric. -->
+
+  <owner>media-dev@chromium.org</owner>
   <summary>
     Container used for HTML5 media. Views that include pre-M34 data will
     categorize dash (38) and smooth streaming (39) in the &quot;Other&quot;
@@ -54838,7 +54871,10 @@
   </summary>
 </histogram>
 
-<histogram name="Media.DetectedContainer.Local" enum="MediaContainers">
+<histogram name="Media.DetectedContainer.Local" enum="MediaContainers"
+    expires_after="never">
+<!-- expires-never: Codec support planning metric. -->
+
   <owner>media-dev@chromium.org</owner>
   <summary>Container used for HTML5 media for a local file playback.</summary>
 </histogram>
@@ -54876,8 +54912,11 @@
   <summary>Video codec used in HTML5 media.</summary>
 </histogram>
 
-<histogram name="Media.DetectedVideoCodecHash" enum="FFmpegCodecHashes">
-  <owner>jrummell@chromium.org</owner>
+<histogram name="Media.DetectedVideoCodecHash" enum="FFmpegCodecHashes"
+    expires_after="never">
+<!-- expires-never: Codec support planning metric. -->
+
+  <owner>media-dev@chromium.org</owner>
   <summary>
     Video codec used in HTML5 media. Reporting corrected in M51 to include all
     detected video codecs, not just those up to and including the first one
@@ -54885,7 +54924,10 @@
   </summary>
 </histogram>
 
-<histogram name="Media.DetectedVideoCodecHash.Local" enum="FFmpegCodecHashes">
+<histogram name="Media.DetectedVideoCodecHash.Local" enum="FFmpegCodecHashes"
+    expires_after="never">
+<!-- expires-never: Codec support planning metric. -->
+
   <owner>media-dev@chromium.org</owner>
   <summary>Video codec used in HTML5 media for a local file playback.</summary>
 </histogram>
@@ -55494,6 +55536,9 @@
 </histogram>
 
 <histogram name="Media.FallbackHardwareAudioChannelCount" expires_after="M77">
+  <obsolete>
+    Removed 06/2019 in issue 975072. Not useful.
+  </obsolete>
   <owner>dalecurtis@chromium.org</owner>
   <summary>
     Channel count of the hardware audio device which failed to open in low
@@ -55503,6 +55548,9 @@
 
 <histogram name="Media.FallbackHardwareAudioChannelLayout" enum="ChannelLayout"
     expires_after="M77">
+  <obsolete>
+    Removed 06/2019 in issue 975072. Not useful.
+  </obsolete>
   <owner>dalecurtis@chromium.org</owner>
   <summary>
     Channel layout of the hardware audio device which failed to open in low
@@ -55512,6 +55560,9 @@
 
 <histogram name="Media.FallbackHardwareAudioSamplesPerSecond"
     enum="AudioSampleRate">
+  <obsolete>
+    Removed 06/2019 in issue 975072. Not useful.
+  </obsolete>
   <owner>dalecurtis@chromium.org</owner>
   <summary>
     Samples per second of the hardware audio device which failed to open in low
@@ -55521,6 +55572,9 @@
 
 <histogram name="Media.FallbackHardwareAudioSamplesPerSecondUnexpected"
     units="Hz" expires_after="M77">
+  <obsolete>
+    Removed 06/2019 in issue 975072. Not useful.
+  </obsolete>
   <owner>dalecurtis@chromium.org</owner>
   <summary>
     Samples per second of the hardware audio device (atypical values, in Hz)
@@ -55650,25 +55704,33 @@
   <summary>Bits per channel of the hardware audio device.</summary>
 </histogram>
 
-<histogram name="Media.HardwareAudioChannelCount">
+<histogram name="Media.HardwareAudioChannelCount" expires_after="never">
+<!-- expires-never: Media platform support planning metric. -->
+
   <owner>dalecurtis@chromium.org</owner>
   <summary>Channel count of the hardware audio device.</summary>
 </histogram>
 
 <histogram name="Media.HardwareAudioChannelLayout" enum="ChannelLayout"
-    expires_after="M77">
+    expires_after="never">
+<!-- expires-never: Media platform support planning metric. -->
+
   <owner>dalecurtis@chromium.org</owner>
   <summary>Channel layout of the hardware audio device.</summary>
 </histogram>
 
 <histogram name="Media.HardwareAudioSamplesPerSecond" enum="AudioSampleRate"
-    expires_after="M77">
+    expires_after="never">
+<!-- expires-never: Media platform support planning metric. -->
+
   <owner>dalecurtis@chromium.org</owner>
   <summary>Samples per second of the hardware audio device.</summary>
 </histogram>
 
-<histogram name="Media.HardwareAudioSamplesPerSecondUnexpected" units="Hz"
-    expires_after="M77">
+<histogram name="Media.HardwareAudioSamplesPerSecondUnexpected" units="Hz">
+  <obsolete>
+    Removed 06/2019 in issue 975072. Not useful.
+  </obsolete>
   <owner>dalecurtis@chromium.org</owner>
   <summary>
     Samples per second of the hardware audio device (atypical values, in Hz).
@@ -56052,7 +56114,9 @@
   </summary>
 </histogram>
 
-<histogram name="Media.MSE.AudioCodec" enum="MSECodec" expires_after="M77">
+<histogram name="Media.MSE.AudioCodec" enum="MSECodec" expires_after="never">
+<!-- expires-never: Codec support planning metric. -->
+
   <owner>acolwell@chromium.org</owner>
   <summary>
     Audio codec used in Media Source Extensions playback. Set when AddId() is
@@ -56255,7 +56319,9 @@
   </summary>
 </histogram>
 
-<histogram name="Media.MSE.VideoCodec" enum="MSECodec">
+<histogram name="Media.MSE.VideoCodec" enum="MSECodec" expires_after="never">
+<!-- expires-never: Codec support planning metric. -->
+
   <owner>acolwell@chromium.org</owner>
   <summary>
     Video codec used in Media Source Extensions playback. Set when AddId() is
@@ -57804,7 +57870,9 @@
   </summary>
 </histogram>
 
-<histogram name="Media.VideoCodec" enum="VideoCodec">
+<histogram name="Media.VideoCodec" enum="VideoCodec" expires_after="never">
+<!-- expires-never: Codec support planning metric. -->
+
   <owner>dalecurtis@chromium.org</owner>
   <summary>Video codec used in HTML5 media.</summary>
 </histogram>
@@ -64311,6 +64379,18 @@
   </summary>
 </histogram>
 
+<histogram name="Navigation.IOSNullContextInDidFailProvisionalNavigation"
+    enum="Boolean">
+  <owner>ajuma@chromium.org</owner>
+  <owner>eugenebut@chromium.org</owner>
+  <summary>
+    Logged when NavigationContext is null inside -[WKNavigationDelegate
+    webView:didFailProvisionalNavigation]. If Chrome stopped logging this metric
+    it means that it is now safe to remove workaround for
+    https://bugs.webkit.org/show_bug.cgi?id=198794.
+  </summary>
+</histogram>
+
 <histogram name="Navigation.IOSWKWebViewSlowFastBackForward"
     enum="BackForwardNavigationType" expires_after="M77">
   <owner>eugenebut@chromium.org</owner>
@@ -91458,8 +91538,9 @@
 </histogram>
 
 <histogram name="PasswordManager.HttpPasswordMigrationCount"
-    units="saved credentials" expires_after="M77">
+    units="saved credentials" expires_after="M82">
   <owner>vasilii@chromium.org</owner>
+  <owner>jdoerrie@chromium.org</owner>
   <summary>
     Number of HTTP saved passwords that were migrated to HTTPS. Recorded on
     HTTPS password form load when there are no credentials saved.
@@ -91467,8 +91548,9 @@
 </histogram>
 
 <histogram name="PasswordManager.HttpPasswordMigrationMode"
-    enum="HttpPasswordMigrationMode" expires_after="M77">
+    enum="HttpPasswordMigrationMode" expires_after="M82">
   <owner>jdoerrie@chromium.org</owner>
+  <owner>vasilii@chromium.org</owner>
   <summary>
     The mode of migration applied to HTTP passwords migrating to HTTPS. Recorded
     on HTTPS password form load when there are no credentials saved.
@@ -94379,7 +94461,7 @@
 </histogram>
 
 <histogram name="Platform.Cr50.BoardIdOfRlzMismatch" enum="Cr50CrosRlzCodes"
-    expires_after="M77">
+    expires_after="2020-07-30">
   <owner>vbendeb@chromium.org</owner>
   <summary>
     A sparse histogram of values indexed by 4 byte Board ID code programmed in
@@ -94411,7 +94493,7 @@
 </histogram>
 
 <histogram name="Platform.Cr50.RlzOfBoardIdMismatch" enum="Cr50CrosRlzCodes"
-    expires_after="M77">
+    expires_after="2020-07-30">
   <owner>vbendeb@chromium.org</owner>
   <summary>
     A sparse histogram of values indexed by 4 byte RLZ code reported by devices
@@ -100807,6 +100889,27 @@
   </summary>
 </histogram>
 
+<histogram
+    name="Previews.HintsFetcher.TopHostProvider.BlacklistSize.OnInitialize"
+    units="total host count" expires_after="M80">
+  <owner>mcrouse@chromium.org</owner>
+  <owner>dougarnett@chromium.org</owner>
+  <summary>
+    Records the number of hosts placed on the HintsFetcherTopHostBlacklist when
+    it is initialized.
+  </summary>
+</histogram>
+
+<histogram name="Previews.HintsFetcher.TopHostProvider.BlacklistSize.OnRequest"
+    units="total host count" expires_after="M80">
+  <owner>mcrouse@chromium.org</owner>
+  <owner>dougarnett@chromium.org</owner>
+  <summary>
+    Records the number of hosts on the HintsFetcherTopHostBlacklist when top
+    hosts are requested.
+  </summary>
+</histogram>
+
 <histogram name="Previews.InfoBarAction" enum="PreviewsInfoBarAction">
   <obsolete>
     Removed in M76.
@@ -100844,7 +100947,7 @@
 </histogram>
 
 <histogram name="Previews.Offline.CommittedErrorPage" enum="BooleanError"
-    expires_after="M77">
+    expires_after="M80">
   <owner>harrisonsean@chromium.org</owner>
   <owner>robertogden@chromium.org</owner>
   <summary>
@@ -101126,6 +101229,16 @@
   </summary>
 </histogram>
 
+<histogram name="Previews.ServerLitePage.ToggledPreresolve" enum="Boolean"
+    expires_after="M80">
+  <owner>robertogden@chromium.org</owner>
+  <owner>tbansal@chromium.org</owner>
+  <summary>
+    Recorded whenever the litepage host preresolve state is changed. True is
+    recorded when preresolving starts and False is recorded when it stops.
+  </summary>
+</histogram>
+
 <histogram name="Previews.ServerLitePage.Triggered" enum="Boolean">
   <owner>robertogden@chromium.org</owner>
   <summary>
@@ -118054,6 +118167,15 @@
   </summary>
 </histogram>
 
+<histogram name="Session.TimeSpentInFocusMode" units="s" expires_after="M80">
+  <owner>chrome-desktop-ui-sea@google.com</owner>
+  <owner>yiningwang@google.com</owner>
+  <summary>
+    Time spent in focus mode browser. This is recorded when the focus mode
+    window closes. This metric is only recorded on Win/Mac/Linux/ChromeOS.
+  </summary>
+</histogram>
+
 <histogram name="Session.TotalDuration" units="ms">
   <owner>asvitkine@chromium.org</owner>
   <owner>chrisha@chromium.org</owner>
@@ -137502,6 +137624,10 @@
 
 <histogram name="UserActivation.AvailabilityCheck.FrameResult"
     enum="UserActivationFrameResultEnum">
+  <obsolete>
+    This was added to assess possible impact of UserActivationV2, by comparing
+    pre- and post-launch stats.
+  </obsolete>
   <owner>mustaq@chromium.org</owner>
   <summary>
     Outcomes (success/failure) of transient user activation availability check
@@ -137511,6 +137637,10 @@
 
 <histogram name="UserActivation.Consumption.FrameResult"
     enum="UserActivationFrameResultEnum">
+  <obsolete>
+    This was added to assess possible impact of UserActivationV2, by comparing
+    pre- and post-launch stats.
+  </obsolete>
   <owner>mustaq@chromium.org</owner>
   <summary>
     Outcomes (success/failure) of user activation consumption attempts for each
@@ -142360,6 +142490,21 @@
   </summary>
 </histogram>
 
+<histogram name="WebCore.IndexedDB.OpenTime.Cold" units="ms"
+    expires_after="2020-07-01">
+  <owner>dmurph@chromium.org</owner>
+  <owner>pwnall@chromium.org</owner>
+  <summary>
+    Records the full time it takes to open a database that isn't open yet (so
+    files are loaded from disk, metadata checked, etc). The measurement happens
+    when a website calls &quot;indexedDB.open&quot;, and records the time it
+    takes from when this method is called to when the onsuccess event (or
+    onupgradeneeded event, in the case of a database upgrade) is dispatched. See
+    WebCore.IndexedDB.OpenTime.Warm for the time it takes an already-loaded
+    database to load.
+  </summary>
+</histogram>
+
 <histogram name="WebCore.IndexedDB.OpenTime.Error" units="ms"
     expires_after="2018-11-16">
   <obsolete>
@@ -142396,6 +142541,20 @@
   </summary>
 </histogram>
 
+<histogram name="WebCore.IndexedDB.OpenTime.Warm" units="ms"
+    expires_after="2020-07-01">
+  <owner>dmurph@chromium.org</owner>
+  <owner>pwnall@chromium.org</owner>
+  <summary>
+    Records the full time it takes to open an already-open database. The
+    measurement happens when a website calls &quot;indexedDB.open&quot;, and
+    records the time it takes from when this method is called to when the
+    onsuccess event (or onupgradeneeded event, in the case of a database
+    upgrade) is dispatched. See WebCore.IndexedDB.OpenTime.Cold for the time it
+    takes to open a database that is not open yet.
+  </summary>
+</histogram>
+
 <histogram name="WebCore.IndexedDB.PutBlobsCount" units="blobs">
   <owner>dmurph@chromium.org</owner>
   <summary>
@@ -143772,7 +143931,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.AgcClippingAdjustmentAllowed" enum="Boolean"
-    expires_after="M77">
+    expires_after="2020-06-18">
   <owner>hlundin@chromium.org</owner>
   <summary>
     The automatic gain control (AGC) in WebRTC tries to adjust the microphone
@@ -143784,7 +143943,8 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.Audio.AgcSetLevel" units="level" expires_after="M77">
+<histogram name="WebRTC.Audio.AgcSetLevel" units="level"
+    expires_after="2020-06-18">
   <owner>hlundin@chromium.org</owner>
   <summary>
     The automatic gain control (AGC) in WebRTC tries to adjust the microphone
@@ -144221,7 +144381,7 @@
 </histogram>
 
 <histogram name="WebRTC.Audio.Encoder.CodecType" enum="WebRtcAudioCodecs"
-    expires_after="M77">
+    expires_after="2020-06-18">
   <owner>aleloi@chromium.org</owner>
   <summary>
     Histogram of audio codec usage. Every sample corresponds to 5 seconds of
diff --git a/ui/android/java/src/org/chromium/ui/modelutil/ModelListAdapter.java b/ui/android/java/src/org/chromium/ui/modelutil/ModelListAdapter.java
index 13eab2d..7a6c12c 100644
--- a/ui/android/java/src/org/chromium/ui/modelutil/ModelListAdapter.java
+++ b/ui/android/java/src/org/chromium/ui/modelutil/ModelListAdapter.java
@@ -19,7 +19,24 @@
 import java.util.List;
 
 /**
- * Adapter for providing data and views to the omnibox results list.
+ * Adapter for providing data and views to a ListView.
+ *
+ * To use, register a {@link PropertyModelChangeProcessor.ViewBinder} and {@link ViewBuilder}
+ * for each view type in the list using
+ * {@link #registerType(int, ViewBuilder, PropertyModelChangeProcessor.ViewBinder)}.
+ * Then call {@link #updateModels(List)} to provide a list of items (represented by PropertyModels)
+ * to display in the list. If the items in the list change (e.g. items are added, removed, or
+ * change order), call #updateModels again with the new list of items. NOTE: There are plans to
+ * change the API surface to work with a PropertyObservable instead.
+ *
+ * When creating a new view, ModelListAdapter will bind all set properties. When reusing/rebinding
+ * a view, in addition to binding all properties set on the new model, properties that were
+ * previously set on the old model but are not set on the new model will be bound to "reset" the
+ * view. ViewBinders registered for this adapter may therefore need to handle bind calls for
+ * properties that are not set on the model being bound.
+ *
+ * Additionally, ModelListAdapter will hook up a {@link PropertyModelChangeProcessor} when binding
+ * views to ensure that changes to the PropertyModel for that list item are bound to the view.
  */
 public class ModelListAdapter extends BaseAdapter {
     /**
@@ -39,6 +56,9 @@
 
     /**
      * Update the visible models (list items).
+     * @param models A list of {@link PropertyModel}s to display. The Integer property in the pair
+     *         indicates the view type, while the PropertyModel contains the properties for the item
+     *         to display.
      */
     public void updateModels(List<Pair<Integer, PropertyModel>> models) {
         mModelList.clear();
diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc
index cb5df3b3..294ecbf 100644
--- a/ui/compositor/test/in_process_context_factory.cc
+++ b/ui/compositor/test/in_process_context_factory.cc
@@ -134,7 +134,7 @@
 
  private:
   void OnSwapBuffersComplete() {
-    client_->DidReceiveSwapBuffersAck();
+    client_->DidReceiveSwapBuffersAck(gfx::SwapTimings());
     client_->DidReceivePresentationFeedback(gfx::PresentationFeedback());
   }
 
diff --git a/ui/events/blink/fling_booster.cc b/ui/events/blink/fling_booster.cc
index 2fa2ae2..39ab3ba7 100644
--- a/ui/events/blink/fling_booster.cc
+++ b/ui/events/blink/fling_booster.cc
@@ -20,176 +20,153 @@
 // ticks, scrolls or flings of sufficient velocity relative to the current fling
 // are received. The default value on Android native views is 40ms, but we use a
 // slightly increased value to accomodate small IPC message delays.
-const double kFlingBoostTimeoutDelaySeconds = 0.05;
+constexpr base::TimeDelta kFlingBoostTimeoutDelay =
+    base::TimeDelta::FromSecondsD(0.05);
 }  // namespace
 
 namespace ui {
 
-FlingBooster::FlingBooster(const gfx::Vector2dF& fling_velocity,
-                           blink::WebGestureDevice source_device,
-                           int modifiers)
-    : current_fling_velocity_(fling_velocity),
-      source_device_(source_device),
-      modifiers_(modifiers),
-      deferred_fling_cancel_time_seconds_(0),
-      last_fling_animate_time_seconds_(0),
-      fling_boosted_(false) {}
+gfx::Vector2dF FlingBooster::GetVelocityForFlingStart(
+    const blink::WebGestureEvent& fling_start) {
+  DCHECK_EQ(blink::WebInputEvent::kGestureFlingStart, fling_start.GetType());
+  gfx::Vector2dF velocity(fling_start.data.fling_start.velocity_x,
+                          fling_start.data.fling_start.velocity_y);
 
-bool FlingBooster::FilterGestureEventForFlingBoosting(
-    const WebGestureEvent& gesture_event,
-    bool* out_cancel_current_fling) {
-  DCHECK(out_cancel_current_fling);
-  *out_cancel_current_fling = false;
+  if (ShouldBoostFling(fling_start))
+    velocity += current_fling_velocity_;
 
-  if (gesture_event.GetType() == WebInputEvent::kGestureFlingCancel) {
-    if (gesture_event.data.fling_cancel.prevent_boosting)
-      return false;
+  Reset();
 
-    if (current_fling_velocity_.LengthSquared() < kMinBoostFlingSpeedSquare)
-      return false;
+  current_fling_velocity_ = velocity;
+  source_device_ = fling_start.SourceDevice();
+  modifiers_ = fling_start.GetModifiers();
 
-    deferred_fling_cancel_time_seconds_ =
-        gesture_event.TimeStamp().since_origin().InSecondsF() +
-        kFlingBoostTimeoutDelaySeconds;
-    return true;
-  }
+  return current_fling_velocity_;
+}
 
-  // A fling is either inactive or is "free spinning", i.e., has yet to be
-  // interrupted by a touch gesture, in which case there is nothing to filter.
-  if (!deferred_fling_cancel_time_seconds_)
-    return false;
+void FlingBooster::ObserveGestureEvent(const WebGestureEvent& gesture_event) {
+  if (current_fling_velocity_.IsZero())
+    return;
 
-  // Gestures from a different source should immediately interrupt the fling.
-  if (gesture_event.SourceDevice() != source_device_) {
-    *out_cancel_current_fling = true;
-    return false;
-  }
+  // Gestures from a different source should prevent boosting.
+  if (gesture_event.SourceDevice() != source_device_)
+    Reset();
 
   switch (gesture_event.GetType()) {
-    case WebInputEvent::kGestureTapCancel:
-    case WebInputEvent::kGestureTapDown:
-      return false;
-
-    case WebInputEvent::kGestureScrollBegin:
-      // TODO(jdduke): Use |gesture_event.data.scrollBegin.delta{X,Y}Hint| to
-      // determine if the ScrollBegin should immediately cancel the fling.
-      ExtendBoostedFlingTimeout(gesture_event);
-      return true;
-
+    case WebInputEvent::kGestureScrollBegin: {
+      cutoff_time_for_boost_ =
+          gesture_event.TimeStamp() + kFlingBoostTimeoutDelay;
+      break;
+    }
     case WebInputEvent::kGestureScrollUpdate: {
       if (gesture_event.data.scroll_update.inertial_phase ==
           WebGestureEvent::InertialPhaseState::kMomentum) {
-        // GSU events in momentum phase are generated by FlingController to
-        // progress fling and should not interfere with fling boosting.
-        return false;
+        return;
       }
 
-      if (ShouldSuppressScrollForFlingBoosting(gesture_event)) {
-        ExtendBoostedFlingTimeout(gesture_event);
-        return true;
+      if (cutoff_time_for_boost_.is_null())
+        return;
+
+      if (gesture_event.TimeStamp() > cutoff_time_for_boost_) {
+        Reset();
+        return;
       }
 
-      *out_cancel_current_fling = true;
-      return false;
+      // If the user scrolls in a direction counter to the current scroll, don't
+      // boost.
+      gfx::Vector2dF delta(gesture_event.data.scroll_update.delta_x,
+                           gesture_event.data.scroll_update.delta_y);
+      if (gfx::DotProduct(current_fling_velocity_, delta) <= 0) {
+        Reset();
+        return;
+      }
+
+      // Scrolls must be of sufficient velocity to maintain the active fling.
+      // Unfortunately we can't simply use the velocity_x|y fields on the
+      // gesture event because they're not populated when converting from
+      // Android's MotionEvents.
+      if (!previous_boosting_scroll_timestamp_.is_null()) {
+        const double time_since_last_boost_event =
+            (gesture_event.TimeStamp() - previous_boosting_scroll_timestamp_)
+                .InSecondsF();
+        if (time_since_last_boost_event >= 0.001) {
+          const gfx::Vector2dF scroll_velocity =
+              gfx::ScaleVector2d(delta, 1. / time_since_last_boost_event);
+          if (scroll_velocity.LengthSquared() <
+              kMinBoostTouchScrollSpeedSquare) {
+            Reset();
+            return;
+          }
+        }
+      }
+
+      previous_boosting_scroll_timestamp_ = gesture_event.TimeStamp();
+      cutoff_time_for_boost_ =
+          gesture_event.TimeStamp() + kFlingBoostTimeoutDelay;
+      break;
     }
-
-    case WebInputEvent::kGestureScrollEnd:
-      // Clear the last fling boost event *prior* to fling cancellation,
-      // preventing insertion of a synthetic GestureScrollBegin.
-      last_fling_boost_event_ = WebGestureEvent();
-      *out_cancel_current_fling = true;
-      return true;
-
-    case WebInputEvent::kGestureFlingStart: {
-      DCHECK_EQ(source_device_, gesture_event.SourceDevice());
-      gfx::Vector2dF new_fling_velocity(
-          gesture_event.data.fling_start.velocity_x,
-          gesture_event.data.fling_start.velocity_y);
-      DCHECK(!new_fling_velocity.IsZero());
-
-      fling_boosted_ = ShouldBoostFling(gesture_event);
-      if (fling_boosted_)
-        current_fling_velocity_ += new_fling_velocity;
-      else
-        current_fling_velocity_ = new_fling_velocity;
-
-      deferred_fling_cancel_time_seconds_ = 0;
-      last_fling_boost_event_ = WebGestureEvent();
-      return true;
+    case WebInputEvent::kGestureScrollEnd: {
+      previous_boosting_scroll_timestamp_ = base::TimeTicks();
+      break;
     }
+    case WebInputEvent::kGestureFlingCancel: {
+      if (gesture_event.data.fling_cancel.prevent_boosting) {
+        Reset();
+        return;
+      }
 
+      previous_boosting_scroll_timestamp_ = base::TimeTicks();
+      cutoff_time_for_boost_ =
+          gesture_event.TimeStamp() + kFlingBoostTimeoutDelay;
+      break;
+    }
     default:
-      // All other types of gestures (taps, presses, etc...) will complete the
-      // deferred fling cancellation.
-      *out_cancel_current_fling = true;
-      return false;
+      break;
   }
 }
 
-bool FlingBooster::MustCancelDeferredFling() const {
-  return deferred_fling_cancel_time_seconds_ &&
-         last_fling_animate_time_seconds_ > deferred_fling_cancel_time_seconds_;
-}
-
 bool FlingBooster::ShouldBoostFling(const WebGestureEvent& fling_start_event) {
   DCHECK_EQ(WebInputEvent::kGestureFlingStart, fling_start_event.GetType());
-
-  gfx::Vector2dF new_fling_velocity(
-      fling_start_event.data.fling_start.velocity_x,
-      fling_start_event.data.fling_start.velocity_y);
-
-  if (gfx::DotProduct(current_fling_velocity_, new_fling_velocity) <= 0)
+  if (current_fling_velocity_.IsZero())
     return false;
 
-  if (current_fling_velocity_.LengthSquared() < kMinBoostFlingSpeedSquare)
-    return false;
-
-  if (new_fling_velocity.LengthSquared() < kMinBoostFlingSpeedSquare)
+  if (source_device_ != fling_start_event.SourceDevice())
     return false;
 
   if (modifiers_ != fling_start_event.GetModifiers())
     return false;
 
-  return true;
-}
-
-bool FlingBooster::ShouldSuppressScrollForFlingBoosting(
-    const WebGestureEvent& scroll_update_event) {
-  DCHECK_EQ(WebInputEvent::kGestureScrollUpdate, scroll_update_event.GetType());
-
-  gfx::Vector2dF dx(scroll_update_event.data.scroll_update.delta_x,
-                    scroll_update_event.data.scroll_update.delta_y);
-  if (gfx::DotProduct(current_fling_velocity_, dx) <= 0)
+  if (cutoff_time_for_boost_.is_null())
     return false;
 
-  const double time_since_last_fling_animate = std::max(
-      0.0, scroll_update_event.TimeStamp().since_origin().InSecondsF() -
-               last_fling_animate_time_seconds_);
-  if (time_since_last_fling_animate > kFlingBoostTimeoutDelaySeconds)
+  if (fling_start_event.TimeStamp() > cutoff_time_for_boost_)
     return false;
 
-  const double time_since_last_boost_event =
-      (scroll_update_event.TimeStamp() - last_fling_boost_event_.TimeStamp())
-          .InSecondsF();
-  if (time_since_last_boost_event < 0.001)
-    return true;
+  gfx::Vector2dF new_fling_velocity(
+      fling_start_event.data.fling_start.velocity_x,
+      fling_start_event.data.fling_start.velocity_y);
 
-  // TODO(jdduke): Use |scroll_update_event.data.scrollUpdate.velocity{X,Y}|.
-  // The scroll must be of sufficient velocity to maintain the active fling.
-  const gfx::Vector2dF scroll_velocity =
-      gfx::ScaleVector2d(dx, 1. / time_since_last_boost_event);
-  if (scroll_velocity.LengthSquared() < kMinBoostTouchScrollSpeedSquare)
+  if (gfx::DotProduct(current_fling_velocity_, new_fling_velocity) <= 0) {
     return false;
+  }
+
+  if (current_fling_velocity_.LengthSquared() < kMinBoostFlingSpeedSquare) {
+    return false;
+  }
+
+  if (new_fling_velocity.LengthSquared() < kMinBoostFlingSpeedSquare) {
+    return false;
+  }
 
   return true;
 }
 
-void FlingBooster::ExtendBoostedFlingTimeout(
-    const blink::WebGestureEvent& event) {
-  deferred_fling_cancel_time_seconds_ =
-      event.TimeStamp().since_origin().InSecondsF() +
-      kFlingBoostTimeoutDelaySeconds;
-  last_fling_boost_event_ = event;
+void FlingBooster::Reset() {
+  cutoff_time_for_boost_ = base::TimeTicks();
+  current_fling_velocity_ = gfx::Vector2dF();
+  source_device_ = blink::WebGestureDevice::kUninitialized;
+  modifiers_ = 0;
+  previous_boosting_scroll_timestamp_ = base::TimeTicks();
 }
 
 }  // namespace ui
diff --git a/ui/events/blink/fling_booster.h b/ui/events/blink/fling_booster.h
index 21f2554..112bd0a7 100644
--- a/ui/events/blink/fling_booster.h
+++ b/ui/events/blink/fling_booster.h
@@ -9,76 +9,46 @@
 
 namespace ui {
 
-// TODO(dcheng): This class should probably be using base::TimeTicks internally.
+// This class is used to track fling state and provide "fling boosting".
+// Boosting is a feature where successive flings can repeatedly increase the
+// fling velocity so that users can scroll through long documents. This
+// boosting logic occurs only in certain circumstances so we track the state
+// and conditions in this class. The FlingController will request the velocity
+// for all flings from this class; if FlingBooster decides the fling should be
+// boosted it'll add the new fling's velocity to the previous one's.
 class FlingBooster {
  public:
-  FlingBooster(const gfx::Vector2dF& fling_velocity,
-               blink::WebGestureDevice source_device,
-               int modifiers);
+  FlingBooster() = default;
 
-  // Returns true if the event should be suppressed due to to an active,
-  // boost-enabled fling, in which case further processing should cease.
-  bool FilterGestureEventForFlingBoosting(
-      const blink::WebGestureEvent& gesture_event,
-      bool* out_cancel_current_fling);
-
-  bool MustCancelDeferredFling() const;
-
-  void set_last_fling_animation_time(double last_fling_animate_time_seconds) {
-    last_fling_animate_time_seconds_ = last_fling_animate_time_seconds;
-  }
-
-  gfx::Vector2dF current_fling_velocity() const {
-    return current_fling_velocity_;
-  }
-
-  void set_current_fling_velocity(const gfx::Vector2dF& fling_velocity) {
-    current_fling_velocity_ = fling_velocity;
-  }
-
-  bool fling_boosted() const { return fling_boosted_; }
-
-  bool fling_cancellation_is_deferred() const {
-    return !!deferred_fling_cancel_time_seconds_;
-  }
-
-  blink::WebGestureEvent last_boost_event() const {
-    return last_fling_boost_event_;
-  }
+  gfx::Vector2dF GetVelocityForFlingStart(
+      const blink::WebGestureEvent& gesture_start);
+  void ObserveGestureEvent(const blink::WebGestureEvent& gesture_event);
 
  private:
   bool ShouldBoostFling(const blink::WebGestureEvent& fling_start_event);
 
-  bool ShouldSuppressScrollForFlingBoosting(
-      const blink::WebGestureEvent& scroll_update_event);
+  void Reset();
 
-  // Set a time in the future after which a boost-enabled fling will terminate
-  // without further momentum from the user.
-  void ExtendBoostedFlingTimeout(const blink::WebGestureEvent& event);
+  // When non-null, the current gesture stream is being considered for
+  // boosting. If a fling hasn't occurred by this time, we won't cause a boost.
+  // Note, however, that we'll extend this time as we see scroll updates.
+  base::TimeTicks cutoff_time_for_boost_;
 
+  // Tracks velocity at fling start of the currently ongoing fling. When a new
+  // fling is started and we decide to boost, we'll add this velocity to it.
   gfx::Vector2dF current_fling_velocity_;
 
-  // These store the current active fling source device and modifiers since a
-  // new fling start event must have the same source device and modifiers to be
-  // able to boost the active fling.
-  blink::WebGestureDevice source_device_;
-  int modifiers_;
+  // These store the current active fling source device and modifier keys (e.g.
+  // Ctrl) since a new fling start event must have the same source device and
+  // modifiers to be able to boost the active fling.
+  blink::WebGestureDevice source_device_ =
+      blink::WebGestureDevice::kUninitialized;
+  int modifiers_ = 0;
 
-  // Time at which an active fling should expire due to a deferred cancellation
-  // event.
-  double deferred_fling_cancel_time_seconds_;
-
-  // Time at which the last fling animation has happened.
-  double last_fling_animate_time_seconds_;
-
-  // Whether the current active fling is boosted or replaced by a new fling
-  // start event.
-  bool fling_boosted_;
-
-  // The last event that extended the lifetime of the boosted fling. If the
-  // event was a scroll gesture, a GestureScrollBegin needs to be inserted if
-  // the fling terminates.
-  blink::WebGestureEvent last_fling_boost_event_;
+  // Track the last timestamp we've seen a scroll update that we're evaluating
+  // as a boost. This is used to calculate the velocity; if it's to slow we'll
+  // avoid boosting.
+  base::TimeTicks previous_boosting_scroll_timestamp_;
 
   DISALLOW_COPY_AND_ASSIGN(FlingBooster);
 };
diff --git a/ui/events/blink/fling_booster_unittest.cc b/ui/events/blink/fling_booster_unittest.cc
index 0bdc3ab..fce6110 100644
--- a/ui/events/blink/fling_booster_unittest.cc
+++ b/ui/events/blink/fling_booster_unittest.cc
@@ -11,294 +11,238 @@
 #include "ui/events/base_event_utils.h"
 #include "ui/events/event_modifiers.h"
 
+using base::TimeDelta;
 using blink::WebGestureDevice;
 using blink::WebGestureEvent;
 using blink::WebInputEvent;
+using gfx::Vector2dF;
 
 namespace ui {
 namespace test {
 
+static constexpr TimeDelta kEventDelta = TimeDelta::FromMilliseconds(10);
+
+// Constants from fling_booster.cc
+static constexpr double kMinBoostScrollSpeed = 150.;
+static constexpr double kMinBoostFlingSpeed = 350.;
+static constexpr base::TimeDelta kFlingBoostTimeoutDelay =
+    base::TimeDelta::FromSecondsD(0.05);
+
 class FlingBoosterTest : public testing::Test {
  public:
-  FlingBoosterTest() : delta_time_(base::TimeDelta::FromMilliseconds(10)) {
-    gesture_scroll_event_.SetSourceDevice(
-        blink::WebGestureDevice::kTouchscreen);
-  }
+  FlingBoosterTest() = default;
 
-  WebGestureEvent CreateFlingStart(base::TimeTicks timestamp,
-                                   WebGestureDevice source_device,
-                                   const gfx::Vector2dF& velocity,
-                                   int modifiers) {
+  WebGestureEvent CreateFlingStart(
+      const gfx::Vector2dF& velocity,
+      int modifiers = 0,
+      WebGestureDevice source_device = WebGestureDevice::kTouchscreen) {
     WebGestureEvent fling_start(WebInputEvent::kGestureFlingStart, modifiers,
-                                timestamp, source_device);
+                                event_time_, source_device);
     fling_start.data.fling_start.velocity_x = velocity.x();
     fling_start.data.fling_start.velocity_y = velocity.y();
     return fling_start;
   }
 
-  WebGestureEvent CreateFlingCancel(base::TimeTicks timestamp,
-                                    WebGestureDevice source_device) {
+  WebGestureEvent CreateFlingCancel(
+      WebGestureDevice source_device = WebGestureDevice::kTouchscreen) {
     WebGestureEvent fling_cancel(WebInputEvent::kGestureFlingCancel, 0,
-                                 timestamp, source_device);
+                                 event_time_, source_device);
     return fling_cancel;
   }
 
-  void StartFirstFling() {
-    event_time_ = base::TimeTicks() + delta_time_;
-    fling_booster_.reset(new FlingBooster(
-        gfx::Vector2dF(1000, 1000), blink::WebGestureDevice::kTouchscreen, 0));
-    fling_booster_->set_last_fling_animation_time(
-        EventTimeStampToSeconds(event_time_));
+  WebGestureEvent CreateScrollBegin(
+      gfx::Vector2dF delta,
+      WebGestureDevice source_device = WebGestureDevice::kTouchscreen) {
+    WebGestureEvent scroll_begin(WebInputEvent::kGestureScrollBegin, 0,
+                                 event_time_, source_device);
+    scroll_begin.data.scroll_begin.delta_x_hint = delta.x();
+    scroll_begin.data.scroll_begin.delta_y_hint = delta.y();
+    scroll_begin.data.scroll_begin.delta_hint_units =
+        ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
+    return scroll_begin;
   }
 
-  void CancelFling() {
-    WebGestureEvent fling_cancel_event =
-        CreateFlingCancel(event_time_, blink::WebGestureDevice::kTouchscreen);
-    bool cancel_current_fling;
-    EXPECT_TRUE(fling_booster_->FilterGestureEventForFlingBoosting(
-        fling_cancel_event, &cancel_current_fling));
-    EXPECT_FALSE(cancel_current_fling);
-    EXPECT_TRUE(fling_booster_->fling_cancellation_is_deferred());
+  WebGestureEvent CreateScrollUpdate(
+      gfx::Vector2dF delta,
+      WebGestureDevice source_device = WebGestureDevice::kTouchscreen) {
+    WebGestureEvent scroll_update(WebInputEvent::kGestureScrollUpdate, 0,
+                                  event_time_, source_device);
+    scroll_update.data.scroll_update.delta_x = delta.x();
+    scroll_update.data.scroll_update.delta_y = delta.y();
+    scroll_update.data.scroll_update.delta_units =
+        ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
+    return scroll_update;
+  }
+
+  Vector2dF DeltaFromVelocity(Vector2dF velocity, TimeDelta delta) {
+    float delta_seconds = static_cast<float>(delta.InSecondsF());
+    Vector2dF out = velocity;
+    out.Scale(1.f / delta_seconds);
+    return out;
+  }
+
+  Vector2dF SendFlingStart(WebGestureEvent event) {
+    DCHECK_EQ(WebInputEvent::kGestureFlingStart, event.GetType());
+
+    // The event will first be observed, then the FlingController will request
+    // a possibly boosted velocity.
+    fling_booster_.ObserveGestureEvent(event);
+    return fling_booster_.GetVelocityForFlingStart(event);
+  }
+
+  // Simulates the gesture scroll stream for a scroll that should create a
+  // boost.
+  void SimulateBoostingScroll() {
+    event_time_ += kEventDelta;
+    fling_booster_.ObserveGestureEvent(CreateFlingCancel());
+    fling_booster_.ObserveGestureEvent(CreateScrollBegin(Vector2dF(0, 1)));
+
+    // GestureScrollUpdates in the same direction and at sufficient speed should
+    // be considered boosting. First GSU speed is ignored since we need 2 to
+    // determine velocity.
+    event_time_ += kEventDelta;
+    fling_booster_.ObserveGestureEvent(CreateScrollUpdate(Vector2dF(0, 1)));
+    event_time_ += kEventDelta;
+    fling_booster_.ObserveGestureEvent(CreateScrollUpdate(
+        DeltaFromVelocity(Vector2dF(0, kMinBoostScrollSpeed), kEventDelta)));
   }
 
  protected:
-  std::unique_ptr<FlingBooster> fling_booster_;
-  base::TimeDelta delta_time_;
-  base::TimeTicks event_time_;
-  WebGestureEvent gesture_scroll_event_;
+  base::TimeTicks event_time_ =
+      base::TimeTicks() + TimeDelta::FromSeconds(100000);
+  FlingBooster fling_booster_;
 };
 
-TEST_F(FlingBoosterTest, FlingBoost) {
-  StartFirstFling();
+TEST_F(FlingBoosterTest, FlingBoostBasic) {
+  Vector2dF fling_velocity;
 
-  // The fling cancellation should be deferred to allow fling boosting events to
-  // arrive.
-  CancelFling();
+  fling_velocity = SendFlingStart(CreateFlingStart(Vector2dF(0, 1000)));
+  EXPECT_EQ(Vector2dF(0, 1000), fling_velocity)
+      << "First fling shouldn't be boosted";
 
-  // The GestureScrollBegin should be swallowed by the fling when a fling
-  // cancellation is deferred.
-  gesture_scroll_event_.SetTimeStamp(event_time_);
-  gesture_scroll_event_.SetType(WebInputEvent::kGestureScrollBegin);
-  bool cancel_current_fling;
-  EXPECT_TRUE(fling_booster_->FilterGestureEventForFlingBoosting(
-      gesture_scroll_event_, &cancel_current_fling));
-  EXPECT_FALSE(cancel_current_fling);
+  SimulateBoostingScroll();
 
-  // Animate calls within the deferred cancellation window should continue.
-  event_time_ += delta_time_;
-  fling_booster_->set_last_fling_animation_time(
-      EventTimeStampToSeconds(event_time_));
-  EXPECT_FALSE(fling_booster_->MustCancelDeferredFling());
-
-  // GestureScrollUpdates in the same direction and at sufficient speed should
-  // be swallowed by the fling.
-  gesture_scroll_event_.SetTimeStamp(event_time_);
-  gesture_scroll_event_.SetType(WebInputEvent::kGestureScrollUpdate);
-  gesture_scroll_event_.data.scroll_update.delta_x = 100;
-  gesture_scroll_event_.data.scroll_update.delta_y = 100;
-  EXPECT_TRUE(fling_booster_->FilterGestureEventForFlingBoosting(
-      gesture_scroll_event_, &cancel_current_fling));
-  EXPECT_FALSE(cancel_current_fling);
-
-  // Animate calls within the deferred cancellation window should continue.
-  event_time_ += delta_time_;
-  fling_booster_->set_last_fling_animation_time(
-      EventTimeStampToSeconds(event_time_));
-  EXPECT_FALSE(fling_booster_->MustCancelDeferredFling());
-
-  // GestureFlingStart in the same direction and at sufficient speed should
-  // boost the active fling.
-  WebGestureEvent fling_start_event =
-      CreateFlingStart(event_time_, blink::WebGestureDevice::kTouchscreen,
-                       gfx::Vector2dF(1000, 1000), 0);
-  EXPECT_TRUE(fling_booster_->FilterGestureEventForFlingBoosting(
-      fling_start_event, &cancel_current_fling));
-  EXPECT_FALSE(cancel_current_fling);
-  EXPECT_EQ(gfx::Vector2dF(2000, 2000),
-            fling_booster_->current_fling_velocity());
-  EXPECT_TRUE(fling_booster_->fling_boosted());
-
-  // Animate calls within the deferred cancellation window should continue.
-  event_time_ += delta_time_;
-  fling_booster_->set_last_fling_animation_time(
-      EventTimeStampToSeconds(event_time_));
-  EXPECT_FALSE(fling_booster_->MustCancelDeferredFling());
-
-  // GestureFlingCancel should terminate the fling if no boosting gestures are
-  // received within the timeout window.
-  CancelFling();
-  event_time_ += base::TimeDelta::FromMilliseconds(100);
-  fling_booster_->set_last_fling_animation_time(
-      EventTimeStampToSeconds(event_time_));
-  EXPECT_TRUE(fling_booster_->MustCancelDeferredFling());
+  fling_velocity = SendFlingStart(CreateFlingStart(Vector2dF(0, 2000)));
+  EXPECT_EQ(Vector2dF(0, 3000), fling_velocity)
+      << "FlingStart with ongoing fling should be boosted";
 }
 
 TEST_F(FlingBoosterTest, NoFlingBoostIfScrollDelayed) {
-  StartFirstFling();
+  Vector2dF fling_velocity;
 
-  // The fling cancellation should be deferred to allow fling boosting events to
-  // arrive.
-  CancelFling();
+  fling_velocity = SendFlingStart(CreateFlingStart(Vector2dF(0, 1000)));
+  SimulateBoostingScroll();
 
-  // The GestureScrollBegin should be swallowed by the fling when a fling
-  // cancellation is deferred.
-  gesture_scroll_event_.SetTimeStamp(event_time_);
-  gesture_scroll_event_.SetType(WebInputEvent::kGestureScrollBegin);
-  bool cancel_current_fling;
-  EXPECT_TRUE(fling_booster_->FilterGestureEventForFlingBoosting(
-      gesture_scroll_event_, &cancel_current_fling));
-  EXPECT_FALSE(cancel_current_fling);
+  // Delay longer than the timeout and ensure we don't boost.
+  event_time_ += kFlingBoostTimeoutDelay + TimeDelta::FromMilliseconds(1);
+  fling_booster_.ObserveGestureEvent(CreateScrollUpdate(Vector2dF(0, 10000)));
 
-  // If no GestureScrollUpdate or GestureFlingStart is received within the
-  // timeout window, the fling should be cancelled and scrolling should resume.
-  event_time_ += base::TimeDelta::FromMilliseconds(100);
-  fling_booster_->set_last_fling_animation_time(
-      EventTimeStampToSeconds(event_time_));
-  EXPECT_TRUE(fling_booster_->MustCancelDeferredFling());
+  fling_velocity = SendFlingStart(CreateFlingStart(Vector2dF(0, 2000)));
+  EXPECT_EQ(Vector2dF(0, 2000), fling_velocity)
+      << "ScrollUpdate delayed longer than boosting timeout; fling shouldn't "
+         "be boosted.";
 }
 
-TEST_F(FlingBoosterTest, NoFlingBoostIfNotAnimated) {
-  StartFirstFling();
+TEST_F(FlingBoosterTest, NoFlingBoostIfBoostTooSlow) {
+  Vector2dF fling_velocity;
 
-  // Animate fling once.
-  event_time_ += delta_time_;
-  fling_booster_->set_last_fling_animation_time(
-      EventTimeStampToSeconds(event_time_));
-  EXPECT_FALSE(fling_booster_->MustCancelDeferredFling());
+  fling_velocity = SendFlingStart(CreateFlingStart(Vector2dF(0, 1000)));
+  SimulateBoostingScroll();
 
-  // Cancel the fling after long delay of no animate. The fling cancellation
-  // should be deferred to allow fling boosting events to arrive.
-  event_time_ += base::TimeDelta::FromMilliseconds(100);
-  CancelFling();
+  auto new_velocity = Vector2dF(0, kMinBoostFlingSpeed - 1);
+  fling_velocity = SendFlingStart(CreateFlingStart(new_velocity));
+  EXPECT_EQ(new_velocity, fling_velocity)
+      << "Boosting FlingStart too slow; fling shouldn't be boosted.";
+}
 
-  // The GestureScrollBegin should be swallowed by the fling when a fling
-  // cancellation is deferred.
-  gesture_scroll_event_.SetTimeStamp(event_time_);
-  gesture_scroll_event_.SetType(WebInputEvent::kGestureScrollBegin);
-  bool cancel_current_fling;
-  EXPECT_TRUE(fling_booster_->FilterGestureEventForFlingBoosting(
-      gesture_scroll_event_, &cancel_current_fling));
-  EXPECT_FALSE(cancel_current_fling);
+TEST_F(FlingBoosterTest, NoFlingBoostIfCurrentVelocityTooSlow) {
+  Vector2dF fling_velocity;
 
-  // Should exit scroll boosting on GestureScrollUpdate due to long delay since
-  // last animate and cancel old fling. The scroll update event shouldn't get
-  // filtered.
-  gesture_scroll_event_.SetType(WebInputEvent::kGestureScrollUpdate);
-  gesture_scroll_event_.data.scroll_update.delta_y = 100;
-  EXPECT_FALSE(fling_booster_->FilterGestureEventForFlingBoosting(
-      gesture_scroll_event_, &cancel_current_fling));
-  EXPECT_TRUE(cancel_current_fling);
+  fling_velocity =
+      SendFlingStart(CreateFlingStart(Vector2dF(0, kMinBoostFlingSpeed - 1)));
+
+  SimulateBoostingScroll();
+  fling_velocity = SendFlingStart(CreateFlingStart(Vector2dF(0, 2000)));
+  EXPECT_EQ(Vector2dF(0, 2000), fling_velocity)
+      << "Existing fling too slow and shouldn't be boosted.";
 }
 
 TEST_F(FlingBoosterTest, NoFlingBoostIfFlingInDifferentDirection) {
-  StartFirstFling();
+  Vector2dF fling_velocity;
 
-  // The fling cancellation should be deferred to allow fling boosting events to
-  // arrive.
-  CancelFling();
+  fling_velocity = SendFlingStart(CreateFlingStart(Vector2dF(0, 1000)));
+  SimulateBoostingScroll();
 
-  // If the new fling is orthogonal to the existing fling, no boosting should
-  // take place, with the new fling replacing the old.
-  WebGestureEvent fling_start_event =
-      CreateFlingStart(event_time_, blink::WebGestureDevice::kTouchscreen,
-                       gfx::Vector2dF(-1000, -1000), 0);
-  bool cancel_current_fling;
-  EXPECT_TRUE(fling_booster_->FilterGestureEventForFlingBoosting(
-      fling_start_event, &cancel_current_fling));
-  EXPECT_FALSE(cancel_current_fling);
-  EXPECT_EQ(gfx::Vector2dF(-1000, -1000),
-            fling_booster_->current_fling_velocity());
-  EXPECT_FALSE(fling_booster_->fling_boosted());
+  fling_velocity = SendFlingStart(CreateFlingStart(Vector2dF(1000, 0)));
+  EXPECT_EQ(Vector2dF(1000, 0), fling_velocity)
+      << "Fling isn't in same direction, shouldn't boost.";
 }
 
 TEST_F(FlingBoosterTest, NoFlingBoostIfScrollInDifferentDirection) {
-  StartFirstFling();
+  Vector2dF fling_velocity;
 
-  // The fling cancellation should be deferred to allow fling boosting events to
-  // arrive.
-  CancelFling();
+  fling_velocity = SendFlingStart(CreateFlingStart(Vector2dF(0, 1000)));
+  SimulateBoostingScroll();
 
-  // If the GestureScrollUpdate is in a different direction than the fling,
-  // the fling should be cancelled and the update event shouldn't get filtered.
-  gesture_scroll_event_.SetTimeStamp(event_time_);
-  gesture_scroll_event_.SetType(WebInputEvent::kGestureScrollUpdate);
-  gesture_scroll_event_.data.scroll_update.delta_x = -100;
-  bool cancel_current_fling;
-  EXPECT_FALSE(fling_booster_->FilterGestureEventForFlingBoosting(
-      gesture_scroll_event_, &cancel_current_fling));
-  EXPECT_TRUE(cancel_current_fling);
-}
+  // Start a new scroll in an orthogonal direction and fling in the direction
+  // of the original fling.
+  event_time_ += kEventDelta;
+  fling_booster_.ObserveGestureEvent(CreateScrollUpdate(Vector2dF(1000, 0)));
 
-TEST_F(FlingBoosterTest, NoFlingBoostIfFlingTooSlow) {
-  StartFirstFling();
-
-  // The fling cancellation should be deferred to allow fling boosting events to
-  // arrive.
-  CancelFling();
-
-  // If the new fling velocity is too small, no boosting should take place, with
-  // the new fling replacing the old.
-  WebGestureEvent fling_start_event =
-      CreateFlingStart(event_time_, blink::WebGestureDevice::kTouchscreen,
-                       gfx::Vector2dF(100, 100), 0);
-  bool cancel_current_fling;
-  EXPECT_TRUE(fling_booster_->FilterGestureEventForFlingBoosting(
-      fling_start_event, &cancel_current_fling));
-  EXPECT_FALSE(cancel_current_fling);
-  EXPECT_EQ(gfx::Vector2dF(100, 100), fling_booster_->current_fling_velocity());
-  EXPECT_FALSE(fling_booster_->fling_boosted());
+  fling_velocity = SendFlingStart(CreateFlingStart(Vector2dF(0, 2000)));
+  EXPECT_EQ(Vector2dF(0, 2000), fling_velocity)
+      << "Scrolling in an orthogonal direction should prevent boosting, even "
+         "if the fling is in the original direction.";
 }
 
 TEST_F(FlingBoosterTest, NoFlingBoostIfPreventBoostingFlagIsSet) {
-  StartFirstFling();
+  WebGestureEvent fling_start = CreateFlingStart(Vector2dF(0, 1000));
 
-  // The fling cancellation should not be deferred because of prevent boosting
-  // flag set.
-  WebGestureEvent fling_cancel_event =
-      CreateFlingCancel(event_time_, blink::WebGestureDevice::kTouchscreen);
-  fling_cancel_event.data.fling_cancel.prevent_boosting = true;
-  bool cancel_current_fling;
-  EXPECT_FALSE(fling_booster_->FilterGestureEventForFlingBoosting(
-      fling_cancel_event, &cancel_current_fling));
-  EXPECT_FALSE(cancel_current_fling);
-  EXPECT_FALSE(fling_booster_->fling_cancellation_is_deferred());
+  Vector2dF fling_velocity = SendFlingStart(fling_start);
+
+  // Start a new scroll.
+  event_time_ += kEventDelta;
+  WebGestureEvent cancel_event = CreateFlingCancel();
+  cancel_event.data.fling_cancel.prevent_boosting = true;
+  fling_booster_.ObserveGestureEvent(cancel_event);
+  fling_booster_.ObserveGestureEvent(CreateScrollBegin(Vector2dF(0, 1)));
+
+  // GestureScrollUpdates in the same direction and at sufficient speed should
+  // be considered boosting. However, since the prevent_boosting flag was set,
+  // we shouldn't boost.
+  event_time_ += kEventDelta;
+  fling_booster_.ObserveGestureEvent(CreateScrollUpdate(Vector2dF(0, 10000)));
+  event_time_ += kEventDelta;
+  fling_booster_.ObserveGestureEvent(CreateScrollUpdate(Vector2dF(0, 10000)));
+
+  fling_velocity = SendFlingStart(CreateFlingStart(Vector2dF(0, 2000)));
+  EXPECT_EQ(Vector2dF(0, 2000), fling_velocity)
+      << "prevent_boosting on FlingCancel should avoid boosting a subsequent "
+         "FlingStart";
 }
 
 TEST_F(FlingBoosterTest, NoFlingBoostIfDifferentFlingModifiers) {
-  StartFirstFling();
+  Vector2dF fling_velocity;
 
-  // The fling cancellation should be deferred to allow fling boosting events to
-  // arrive.
-  CancelFling();
+  fling_velocity = SendFlingStart(CreateFlingStart(Vector2dF(0, 1000)));
+  SimulateBoostingScroll();
 
-  // GestureFlingStart with different modifiers should replace the old fling.
-  WebGestureEvent fling_start_event =
-      CreateFlingStart(event_time_, blink::WebGestureDevice::kTouchscreen,
-                       gfx::Vector2dF(500, 500), MODIFIER_SHIFT);
-  bool cancel_current_fling;
-  EXPECT_TRUE(fling_booster_->FilterGestureEventForFlingBoosting(
-      fling_start_event, &cancel_current_fling));
-  EXPECT_FALSE(cancel_current_fling);
-  EXPECT_EQ(gfx::Vector2dF(500, 500), fling_booster_->current_fling_velocity());
-  EXPECT_FALSE(fling_booster_->fling_boosted());
+  fling_velocity =
+      SendFlingStart(CreateFlingStart(Vector2dF(0, 2000), MODIFIER_SHIFT));
+  EXPECT_EQ(Vector2dF(0, 2000), fling_velocity)
+      << "Changed modifier keys should prevent boost.";
 }
 
 TEST_F(FlingBoosterTest, NoFlingBoostIfDifferentFlingSourceDevices) {
-  StartFirstFling();
+  Vector2dF fling_velocity;
 
-  // The fling cancellation should be deferred to allow fling boosting events to
-  // arrive.
-  CancelFling();
+  fling_velocity = SendFlingStart(CreateFlingStart(Vector2dF(0, 1000)));
+  SimulateBoostingScroll();
 
-  // GestureFlingStart with different source device should not get filtered by
-  // fling_booster.
-  WebGestureEvent fling_start_event =
-      CreateFlingStart(event_time_, blink::WebGestureDevice::kTouchpad,
-                       gfx::Vector2dF(500, 500), 0);
-  bool cancel_current_fling;
-  EXPECT_FALSE(fling_booster_->FilterGestureEventForFlingBoosting(
-      fling_start_event, &cancel_current_fling));
-  EXPECT_TRUE(cancel_current_fling);
+  fling_velocity = SendFlingStart(
+      CreateFlingStart(Vector2dF(0, 1000), 0, WebGestureDevice::kTouchpad));
+  EXPECT_EQ(Vector2dF(0, 1000), fling_velocity)
+      << "Changed modifier keys should prevent boost.";
 }
 
 }  // namespace test
diff --git a/ui/views/controls/webview/webview.cc b/ui/views/controls/webview/webview.cc
index 3b523e4..805703d 100644
--- a/ui/views/controls/webview/webview.cc
+++ b/ui/views/controls/webview/webview.cc
@@ -255,7 +255,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 // WebView, content::WebContentsDelegate implementation:
 
-bool WebView::EmbedsFullscreenWidget() const {
+bool WebView::EmbedsFullscreenWidget() {
   DCHECK(wc_owner_.get());
   return embed_fullscreen_widget_mode_enabled_;
 }
diff --git a/ui/views/controls/webview/webview.h b/ui/views/controls/webview/webview.h
index 9ba9464..9872ad3 100644
--- a/ui/views/controls/webview/webview.h
+++ b/ui/views/controls/webview/webview.h
@@ -134,7 +134,7 @@
   gfx::NativeViewAccessible GetNativeViewAccessible() override;
 
   // Overridden from content::WebContentsDelegate:
-  bool EmbedsFullscreenWidget() const override;
+  bool EmbedsFullscreenWidget() override;
 
   // Overridden from content::WebContentsObserver:
   void RenderViewCreated(content::RenderViewHost* render_view_host) override;
diff --git a/ui/views/controls/webview/webview_unittest.cc b/ui/views/controls/webview/webview_unittest.cc
index aff0d51..e2fc822 100644
--- a/ui/views/controls/webview/webview_unittest.cc
+++ b/ui/views/controls/webview/webview_unittest.cc
@@ -111,7 +111,7 @@
 
   // content::WebContentsDelegate overrides.
   bool IsFullscreenForTabOrPending(
-      const content::WebContents* ignored) const override {
+      const content::WebContents* ignored) override {
     return is_fullscreened_;
   }
 
diff --git a/ui/views/view.cc b/ui/views/view.cc
index 5df93cb..d98cabd 100644
--- a/ui/views/view.cc
+++ b/ui/views/view.cc
@@ -581,6 +581,20 @@
   CreateOrDestroyLayer();
 }
 
+std::vector<ui::Layer*> View::GetLayersInOrder() {
+  // If not painting to a layer, there are no layers immediately related to this
+  // view.
+  if (!layer())
+    return {};
+
+  std::vector<ui::Layer*> result;
+  for (ui::Layer* layer_beneath : layers_beneath_)
+    result.push_back(layer_beneath);
+  result.push_back(layer());
+
+  return result;
+}
+
 void View::LayerDestroyed(ui::Layer* layer) {
   // Only layers added with |AddLayerBeneathView()| are observed so |layer| can
   // safely be removed.
diff --git a/ui/views/view.h b/ui/views/view.h
index 78b42e0..3538efc9 100644
--- a/ui/views/view.h
+++ b/ui/views/view.h
@@ -631,6 +631,12 @@
   virtual void AddLayerBeneathView(ui::Layer* new_layer);
   virtual void RemoveLayerBeneathView(ui::Layer* old_layer);
 
+  // Gets the layers associated with this view that should be immediate children
+  // of the parent layer. They are returned in bottom-to-top order. This
+  // includes |this->layer()| and any layers added with |AddLayerBeneathView()|.
+  // Returns an empty vector if this view doesn't paint to a layer.
+  std::vector<ui::Layer*> GetLayersInOrder();
+
   // ui::LayerObserver:
   void LayerDestroyed(ui::Layer* layer) override;
 
diff --git a/ui/views/widget/desktop_aura/desktop_screen_x11.cc b/ui/views/widget/desktop_aura/desktop_screen_x11.cc
index ab33751..2a28717 100644
--- a/ui/views/widget/desktop_aura/desktop_screen_x11.cc
+++ b/ui/views/widget/desktop_aura/desktop_screen_x11.cc
@@ -23,8 +23,7 @@
 #include "ui/events/platform/platform_event_source.h"
 #include "ui/events/platform/x11/x11_event_source.h"
 #include "ui/gfx/font_render_params.h"
-#include "ui/gfx/geometry/point_conversions.h"
-#include "ui/gfx/geometry/size_conversions.h"
+#include "ui/gfx/geometry/dip_util.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gfx/switches.h"
 #include "ui/gfx/x/x11.h"
@@ -50,14 +49,6 @@
   return device_scale_factor;
 }
 
-gfx::Point PixelToDIPPoint(const gfx::Point& pixel_point) {
-  return gfx::ScaleToFlooredPoint(pixel_point, 1.0f / GetDeviceScaleFactor());
-}
-
-gfx::Point DIPToPixelPoint(const gfx::Point& dip_point) {
-  return gfx::ScaleToFlooredPoint(dip_point, GetDeviceScaleFactor());
-}
-
 }  // namespace
 
 namespace views {
@@ -111,7 +102,7 @@
     auto point = ui::X11EventSource::GetInstance()
                      ->GetRootCursorLocationFromCurrentEvent();
     if (point)
-      return PixelToDIPPoint(point.value());
+      return gfx::ConvertPointToDIP(GetDeviceScaleFactor(), point.value());
   }
 
   ::Window root, child;
@@ -120,7 +111,8 @@
   XQueryPointer(xdisplay_, x_root_window_, &root, &child, &root_x, &root_y,
                 &win_x, &win_y, &mask);
 
-  return PixelToDIPPoint(gfx::Point(root_x, root_y));
+  return gfx::ConvertPointToDIP(GetDeviceScaleFactor(),
+                                gfx::Point(root_x, root_y));
 }
 
 bool DesktopScreenX11::IsWindowUnderCursor(gfx::NativeWindow window) {
@@ -131,7 +123,7 @@
     const gfx::Point& point) {
   X11TopmostWindowFinder finder;
   return finder.FindLocalProcessWindowAt(
-      DIPToPixelPoint(point), std::set<aura::Window*>());
+      gfx::ConvertPointToPixel(GetDeviceScaleFactor(), point), {});
 }
 
 int DesktopScreenX11::GetNumDisplays() const {
@@ -161,11 +153,10 @@
     DesktopWindowTreeHostX11* rwh = DesktopWindowTreeHostX11::GetHostForXID(
         host->GetAcceleratedWidget());
     if (rwh) {
-      const float scale = 1.0f / GetDeviceScaleFactor();
       const gfx::Rect pixel_rect = rwh->GetX11RootWindowBounds();
-      return GetDisplayMatching(
-          gfx::Rect(gfx::ScaleToFlooredPoint(pixel_rect.origin(), scale),
-                    gfx::ScaleToCeiledSize(pixel_rect.size(), scale)));
+      const gfx::Rect dip_rect =
+          gfx::ConvertRectToDIP(GetDeviceScaleFactor(), pixel_rect);
+      return GetDisplayMatching(dip_rect);
     }
   }
 
diff --git a/ui/views/widget/window_reorderer.cc b/ui/views/widget/window_reorderer.cc
index 003f65493..ce52ff2 100644
--- a/ui/views/widget/window_reorderer.cc
+++ b/ui/views/widget/window_reorderer.cc
@@ -168,19 +168,24 @@
   // windows not associated to a view are stacked above windows with an
   // associated view.
   for (View* view : base::Reversed(view_with_layer_order)) {
-    ui::Layer* layer = view->layer();
+    std::vector<ui::Layer*> layers;
     aura::Window* window = nullptr;
 
     auto hosted_window_it = hosted_windows.find(view);
     if (hosted_window_it != hosted_windows.end()) {
       window = hosted_window_it->second;
-      layer = window->layer();
+      layers.push_back(window->layer());
+    } else {
+      layers = view->GetLayersInOrder();
+      std::reverse(layers.begin(), layers.end());
     }
 
-    DCHECK(layer);
+    DCHECK(!layers.empty());
     if (window)
       parent_window_->StackChildAtBottom(window);
-    children_layer_order.emplace_back(layer);
+
+    for (ui::Layer* layer : layers)
+      children_layer_order.emplace_back(layer);
   }
   std::reverse(children_layer_order.begin(), children_layer_order.end());
   parent_window_->layer()->StackChildrenAtBottom(children_layer_order);
diff --git a/ui/views/widget/window_reorderer_unittest.cc b/ui/views/widget/window_reorderer_unittest.cc
index 856ee7e..32b8e672 100644
--- a/ui/views/widget/window_reorderer_unittest.cc
+++ b/ui/views/widget/window_reorderer_unittest.cc
@@ -259,5 +259,43 @@
   parent->Close();
 }
 
+// Test that a layer added beneath a view is restacked correctly.
+TEST_F(WindowReordererTest, ViewWithLayerBeneath) {
+  std::unique_ptr<Widget> parent(
+      CreateControlWidget(root_window(), gfx::Rect(0, 0, 100, 100)));
+  parent->Show();
+
+  aura::Window* parent_window = parent->GetNativeWindow();
+
+  View* contents_view = new View;
+  parent->SetContentsView(contents_view);
+
+  View* view_with_layer_beneath =
+      contents_view->AddChildView(std::make_unique<View>());
+  ui::Layer layer_beneath;
+  view_with_layer_beneath->AddLayerBeneathView(&layer_beneath);
+
+  ASSERT_NE(nullptr, view_with_layer_beneath->layer());
+  view_with_layer_beneath->layer()->set_name("view");
+  layer_beneath.set_name("beneath");
+
+  // Verify that the initial ordering is correct.
+  EXPECT_EQ("beneath view",
+            ui::test::ChildLayerNamesAsString(*parent_window->layer()));
+
+  // Add a hosted window to make WindowReorderer::ReorderChildWindows() restack
+  // layers.
+  std::unique_ptr<Widget> child_widget(
+      CreateControlWidget(parent_window, gfx::Rect(gfx::Rect(0, 0, 50, 50))));
+  SetWindowAndLayerName(child_widget->GetNativeView(), "child_widget");
+  child_widget->Show();
+  View* host_view = contents_view->AddChildView(std::make_unique<View>());
+  child_widget->GetNativeView()->SetProperty(kHostViewKey, host_view);
+
+  // Verify the new order is correct.
+  EXPECT_EQ("beneath view child_widget",
+            ui::test::ChildLayerNamesAsString(*parent_window->layer()));
+}
+
 }  // namespace
 }  // namespace views
diff --git a/ui/webui/resources/cr_components/chromeos/bluetooth_dialog.html b/ui/webui/resources/cr_components/chromeos/bluetooth_dialog.html
index 32d93a3..478259a1 100644
--- a/ui/webui/resources/cr_components/chromeos/bluetooth_dialog.html
+++ b/ui/webui/resources/cr_components/chromeos/bluetooth_dialog.html
@@ -80,7 +80,7 @@
     <!-- TODO(stevenjb/dschuyler): Find a solution to support i18n{} here -->
     <cr-dialog id="dialog" no-cancel="[[noCancel]]"
         close-text="[[i18n('close')]]" on-cancel="onDialogCanceled_"
-        on-closed="onDialogCanceled_">
+        on-closed="onDialogCanceled_" exportparts="dialog">
       <div slot="title">[[dialogTitle]]</div>
       <div slot="body">
         <div class="contents layout vertical center center-justified">
diff --git a/ui/webui/resources/cr_components/chromeos/smb_shares/add_smb_share_dialog.html b/ui/webui/resources/cr_components/chromeos/smb_shares/add_smb_share_dialog.html
index 25a8f7f..bdb8ff6 100644
--- a/ui/webui/resources/cr_components/chromeos/smb_shares/add_smb_share_dialog.html
+++ b/ui/webui/resources/cr_components/chromeos/smb_shares/add_smb_share_dialog.html
@@ -65,7 +65,7 @@
       }
     </style>
 
-    <cr-dialog id="dialog">
+    <cr-dialog id="dialog" exportparts="dialog">
       <div slot="title">[[i18n('addSmbShare')]]</div>
       <div slot="body" spellcheck="false">
         <div id="general-error-container">
diff --git a/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html b/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html
index 6317338..2b9d430 100644
--- a/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html
+++ b/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html
@@ -23,6 +23,10 @@
         padding: 0;
         top: 50%;
         width: 512px;
+
+        /* Avoid using the mixin. Use ::part(dialog) instead.
+         * Necessary for backward compatibility with Polymer1/SDv0 (only used by
+         * OOBE). TODO(crbug.com/955194): Remove this once fixed.*/
         @apply --cr-dialog-native;
       }
 
@@ -189,7 +193,7 @@
       }
     </style>
     <dialog id="dialog" on-close="onNativeDialogClose_"
-        on-cancel="onNativeDialogCancel_">
+        on-cancel="onNativeDialogCancel_" part="dialog">
       <!-- This wrapper is necessary, such that the "pulse" animation is not
         erroneously played when the user clicks on the outer-most scrollbar. -->
       <div id="content-wrapper">
diff --git a/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.js b/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.js
index e5e048f..0d5d7b8 100644
--- a/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.js
+++ b/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.js
@@ -15,7 +15,7 @@
  *
  * Note that <cr-dialog> wrapper itself always has 0x0 dimensions, and
  * specifying width/height on <cr-dialog> directly will have no effect on the
- * internal native <dialog>. Instead use the --cr-dialog-native mixin to specify
+ * internal native <dialog>. Instead use cr-dialog::part(dialog) to specify
  * width/height (as well as other available mixins to style other parts of the
  * dialog contents).
  */
diff --git a/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html b/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html
index c50372d2c..97965d2 100644
--- a/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html
+++ b/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html
@@ -55,7 +55,8 @@
         border-color: var(--avatar-selected-color);
       }
 
-      :host-context(.focus-outline-visible) #avatar-grid .avatar:focus {
+      :host-context(.focus-outline-visible) #avatar-grid
+          .avatar:not(.iron-selected):focus {
         --avatar-outline-color: var(--avatar-focus-color);
         --avatar-outline-width: 1px;
       }