diff --git a/DEPS b/DEPS
index 2634016..27f3f168 100644
--- a/DEPS
+++ b/DEPS
@@ -262,7 +262,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '0ea0cd51026f96232359b78a32ce21eaf41bef1e',
+  'catapult_revision': 'cdb0ce794bb76b49a46a5b80ef0ab4818a21c9c3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -270,7 +270,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '2a41471831919582f75a836c80716ebecc6f2acf',
+  'devtools_frontend_revision': 'f6d8669ad9a0eebd62a2093c27de6cd2fd3bf114',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -306,7 +306,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'spv_tools_revision': '4c33fb0d3dbaf8b2579c112cdbb7e9794143e337',
+  'spv_tools_revision': '7221ccf85e26a29459729b3d296b71346c538a94',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -322,7 +322,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '82961129b0543b27edd3fc185be7bc47e41b2a10',
+  'dawn_revision': '1b9b53a395769e15ca7b79a5b964f1b254fc3f84',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -350,7 +350,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling nearby
   # and whatever else without interference from each other.
-  'nearby_revision': '31ab07b5d7183572a4250be2e0ff26a03f920e77',
+  'nearby_revision': 'ae277748ce068ef1730d5104002d4324fc4ed89e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling securemessage
   # and whatever else without interference from each other.
@@ -899,7 +899,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '5fcb48536cceaa77db9af14cd00e049e3a74b9b9',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'e9e8c01f3c5a92657c57adc134d074454f29933d',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -947,10 +947,10 @@
     Var('chromium_git') + '/external/github.com/google/emoji-segmenter.git' + '@' + Var('emoji_segmenter_revision'),
 
   'src/third_party/libgav1/src':
-    Var('chromium_git') + '/codecs/libgav1.git' + '@' + 'ba8dd2919fcaf65646858a6d7fd5e75ed4946cb1',
+    Var('chromium_git') + '/codecs/libgav1.git' + '@' + 'e46493b9148e0d1e63f55b5890bff503822616e5',
 
   'src/third_party/glslang/src':
-    Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + 'b481744aea1ecf52ee4591afaa0f5e270b9d1636',
+    Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + 'f3cb1896971f449706bb1df5053d0e8fad6b0675',
 
   'src/third_party/google_toolbox_for_mac/src': {
       'url': Var('chromium_git') + '/external/github.com/google/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'),
@@ -1252,7 +1252,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'c63cdce64c9e4dc5fb9fa4f820b39bac1de8553b',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '8d8e2e15743a5134fe9ebd8b8ed77353e244be55',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1552,7 +1552,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@d6108deaa5b33b2e1991ae864bef83f50e04224b',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@21731f72a5879d1c7974267e2ae098ee550d4420',
     'condition': 'checkout_src_internal',
   },
 
@@ -1571,7 +1571,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': 'kja0EkIEJxvfaxk2OLA8JxNbZ4dGj9MBSTSAZFoPEkAC',
+        'version': '2Ci5mbO7xjTsQepp4zPBnSBFD21jNiVQSncC7uK12TwC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/ash/shelf/home_button_unittest.cc b/ash/shelf/home_button_unittest.cc
index d44803c0..18145dd 100644
--- a/ash/shelf/home_button_unittest.cc
+++ b/ash/shelf/home_button_unittest.cc
@@ -559,7 +559,8 @@
             AssistantUiController::Get()->GetModel()->visibility());
 }
 
-TEST_P(HomeButtonTest, LongPressGestureInTabletMode) {
+// Started failing consistently https://crbug.com/1106253
+TEST_P(HomeButtonTest, DISABLED_LongPressGestureInTabletMode) {
   // Simulate two users with primary user as active.
   CreateUserSessions(2);
 
diff --git a/ash/style/ash_color_provider.cc b/ash/style/ash_color_provider.cc
index a66b16d0..4bc105f 100644
--- a/ash/style/ash_color_provider.cc
+++ b/ash/style/ash_color_provider.cc
@@ -315,10 +315,10 @@
       dark_color = SkColorSetA(SK_ColorWHITE, 0x24);
       break;
     case ContentLayerType::kTextColorPrimary:
-      return cros_colors::ResolveColor(ColorName::kDefaultTextColor,
+      return cros_colors::ResolveColor(ColorName::kTextColorPrimary,
                                        color_mode);
     case ContentLayerType::kTextColorSecondary:
-      return cros_colors::ResolveColor(ColorName::kDefaultTextColorSecondary,
+      return cros_colors::ResolveColor(ColorName::kTextColorSecondary,
                                        color_mode);
     case ContentLayerType::kTextColorAlert:
       light_color = gfx::kGoogleRed600;
@@ -333,7 +333,7 @@
       dark_color = gfx::kGoogleGreen300;
       break;
     case ContentLayerType::kIconColorPrimary:
-      return cros_colors::ResolveColor(ColorName::kDefaultIconColorPrimary,
+      return cros_colors::ResolveColor(ColorName::kIconColorPrimary,
                                        color_mode);
     case ContentLayerType::kIconColorSecondary:
       light_color = dark_color = gfx::kGoogleGrey500;
@@ -352,7 +352,7 @@
       break;
     case ContentLayerType::kIconColorProminent:
     case ContentLayerType::kSliderThumbColorEnabled:
-      return cros_colors::ResolveColor(ColorName::kDefaultIconColorProminent,
+      return cros_colors::ResolveColor(ColorName::kIconColorProminent,
                                        color_mode);
     case ContentLayerType::kButtonLabelColor:
     case ContentLayerType::kButtonIconColor:
diff --git a/ash/wm/client_controlled_state.cc b/ash/wm/client_controlled_state.cc
index 155692c..1d410ea 100644
--- a/ash/wm/client_controlled_state.cc
+++ b/ash/wm/client_controlled_state.cc
@@ -12,6 +12,7 @@
 #include "ash/shell.h"
 #include "ash/wm/pip/pip_positioner.h"
 #include "ash/wm/screen_pinning_controller.h"
+#include "ash/wm/splitview/split_view_controller.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ash/wm/window_positioning_utils.h"
 #include "ash/wm/window_state.h"
@@ -82,11 +83,18 @@
     return;
   }
 
+  auto* window = window_state->window();
   switch (event->type()) {
     case WM_EVENT_NORMAL:
     case WM_EVENT_MAXIMIZE:
     case WM_EVENT_MINIMIZE:
     case WM_EVENT_FULLSCREEN: {
+      // Clients handle a window state change asynchronously. So in the case
+      // that the window is in a transitional state (already snapped but not
+      // applied to its window state yet), we here skip to pass WM_EVENT.
+      if (SplitViewController::Get(window)->IsWindowInTransitionalState(window))
+        return;
+
       // Reset window state
       window_state->UpdateWindowPropertiesFromStateType();
       WindowStateType next_state =
@@ -102,15 +110,14 @@
       if (window_state->CanSnap()) {
         // Get the desired window bounds for the snap state.
         gfx::Rect bounds = GetSnappedWindowBoundsInParent(
-            window_state->window(), event->type() == WM_EVENT_SNAP_LEFT
-                                        ? WindowStateType::kLeftSnapped
-                                        : WindowStateType::kRightSnapped);
+            window, event->type() == WM_EVENT_SNAP_LEFT
+                        ? WindowStateType::kLeftSnapped
+                        : WindowStateType::kRightSnapped);
         window_state->set_bounds_changed_by_user(true);
 
         // We don't want Unminimize() to restore the pre-snapped state during
         // the transition.
-        window_state->window()->ClearProperty(
-            aura::client::kPreMinimizedShowStateKey);
+        window->ClearProperty(aura::client::kPreMinimizedShowStateKey);
 
         window_state->UpdateWindowPropertiesFromStateType();
         WindowStateType next_state =
diff --git a/ash/wm/client_controlled_state_unittest.cc b/ash/wm/client_controlled_state_unittest.cc
index fba017af..6724557 100644
--- a/ash/wm/client_controlled_state_unittest.cc
+++ b/ash/wm/client_controlled_state_unittest.cc
@@ -11,6 +11,7 @@
 #include "ash/wm/desks/desks_util.h"
 #include "ash/wm/pip/pip_positioner.h"
 #include "ash/wm/screen_pinning_controller.h"
+#include "ash/wm/splitview/split_view_controller.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
@@ -588,4 +589,35 @@
   EXPECT_EQ(WindowStateType::kMaximized, delegate()->new_state());
 }
 
+TEST_F(ClientControlledStateTest,
+       IgnoreWmEventWhenWindowIsInTransitionalSnappedState) {
+  auto* split_view_controller =
+      SplitViewController::Get(window_state()->window());
+
+  widget_delegate()->EnableSnap();
+  split_view_controller->SnapWindow(window_state()->window(),
+                                    SplitViewController::SnapPosition::RIGHT);
+
+  EXPECT_EQ(WindowStateType::kRightSnapped, delegate()->new_state());
+  EXPECT_FALSE(window_state()->IsSnapped());
+
+  // Ensures the window is in a transitional snapped state.
+  EXPECT_TRUE(split_view_controller->IsWindowInTransitionalState(
+      window_state()->window()));
+  EXPECT_EQ(WindowStateType::kRightSnapped, delegate()->new_state());
+  EXPECT_FALSE(window_state()->IsSnapped());
+
+  // Ignores WMEvent if in a transitional state.
+  widget()->Maximize();
+  EXPECT_NE(WindowStateType::kMaximized, delegate()->new_state());
+
+  // Applies snap request.
+  state()->EnterNextState(window_state(), delegate()->new_state());
+  EXPECT_TRUE(window_state()->IsSnapped());
+
+  // After exiting the transitional state, works normally.
+  widget()->Maximize();
+  EXPECT_EQ(WindowStateType::kMaximized, delegate()->new_state());
+}
+
 }  // namespace ash
diff --git a/ash/wm/splitview/split_view_controller.cc b/ash/wm/splitview/split_view_controller.cc
index 841bd66..42ea38b7 100644
--- a/ash/wm/splitview/split_view_controller.cc
+++ b/ash/wm/splitview/split_view_controller.cc
@@ -36,6 +36,7 @@
 #include "ash/wm/window_transient_descendant_iterator.h"
 #include "ash/wm/window_util.h"
 #include "ash/wm/wm_event.h"
+#include "base/containers/flat_set.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/numerics/ranges.h"
@@ -57,6 +58,7 @@
 #include "ui/wm/core/coordinate_conversion.h"
 #include "ui/wm/core/shadow_controller.h"
 #include "ui/wm/core/window_util.h"
+#include "ui/wm/public/activation_change_observer.h"
 #include "ui/wm/public/activation_client.h"
 
 namespace ash {
@@ -356,6 +358,187 @@
   base::Optional<ui::ThroughputTracker> tracker_;
 };
 
+// The controller that observes the window state and performs auto snapping
+// for the window if needed. When it's created, it observes the root window
+// and all windows in a current active desk. When 1) an observed window is
+// activated or 2) changed to visible from minimized, this class performs
+// auto snapping for the window if it's possible.
+class SplitViewController::AutoSnapController
+    : public wm::ActivationChangeObserver,
+      public aura::WindowObserver {
+ public:
+  explicit AutoSnapController(SplitViewController* split_view_controller)
+      : split_view_controller_(split_view_controller) {
+    Shell::Get()->activation_client()->AddObserver(this);
+    AddWindow(split_view_controller->root_window());
+    for (auto* window :
+         Shell::Get()->mru_window_tracker()->BuildMruWindowList(kActiveDesk)) {
+      AddWindow(window);
+    }
+  }
+
+  ~AutoSnapController() override {
+    for (auto* window : observed_windows_)
+      window->RemoveObserver(this);
+    Shell::Get()->activation_client()->RemoveObserver(this);
+  }
+
+  AutoSnapController(const AutoSnapController&) = delete;
+  AutoSnapController& operator=(const AutoSnapController&) = delete;
+
+  // wm::ActivationChangeObserver:
+  void OnWindowActivated(ActivationReason reason,
+                         aura::Window* gained_active,
+                         aura::Window* lost_active) override {
+    if (!gained_active)
+      return;
+
+    // If |gained_active| was activated as a side effect of a window disposition
+    // change, do nothing. For example, when a snapped window is closed, another
+    // window will be activated before OnWindowDestroying() is called. We should
+    // not try to snap another window in this case.
+    if (reason == ActivationReason::WINDOW_DISPOSITION_CHANGED)
+      return;
+
+    AutoSnapWindowIfNeeded(gained_active);
+  }
+
+  // aura::WindowObserver:
+  void OnWindowVisibilityChanging(aura::Window* window, bool visible) override {
+    // TODO(toshikikikuchi): Consider avoiding to use kAnimationsDisabledKey
+    // here just for |DragWindowFromShelfController|.
+    if (visible && WindowState::Get(window) &&
+        WindowState::Get(window)->IsMinimized() &&
+        !window->GetProperty(aura::client::kAnimationsDisabledKey)) {
+      // A visible but minimized window state triggers an implicit un-minimizing
+      // by someone (e.g.
+      // |WorkspaceLayoutManager::OnChildWindowVisibilityChanged| or
+      // |WorkspaceLayoutManager::OnWindowActivating|). This emits a window
+      // state change event but it is unnecessary for to-be-snapped windows
+      // because some clients (e.g. ARC app) handle a window state change
+      // asynchronously. So in the case, we here try to snap a window before
+      // other's handling. Animation-disabled visibility changes are used for
+      // transient hide & show operations so not applicable for auto snapping.
+      AutoSnapWindowIfNeeded(window);
+    }
+  }
+
+  void OnWindowAddedToRootWindow(aura::Window* window) override {
+    AddWindow(window);
+  }
+
+  void OnWindowRemovingFromRootWindow(aura::Window* window,
+                                      aura::Window* new_root) override {
+    RemoveWindow(window);
+  }
+
+  void OnWindowDestroying(aura::Window* window) override {
+    RemoveWindow(window);
+  }
+
+ private:
+  void AutoSnapWindowIfNeeded(aura::Window* window) {
+    DCHECK(window);
+
+    if (window->GetRootWindow() != split_view_controller_->root_window())
+      return;
+
+    // We perform an "auto" snapping only if split view mode is active.
+    if (!split_view_controller_->InSplitViewMode())
+      return;
+
+    if (DesksController::Get()->AreDesksBeingModified()) {
+      // Activating a desk from its mini view will activate its most-recently
+      // used window, but this should not result in snapping and ending overview
+      // mode now. Overview will be ended explicitly as part of the desk
+      // activation animation.
+      return;
+    }
+
+    // Only windows that are in the MRU list and are not already in split view
+    // can be auto-snapped.
+    if (split_view_controller_->IsWindowInSplitView(window) ||
+        !base::Contains(
+            Shell::Get()->mru_window_tracker()->BuildMruWindowList(kActiveDesk),
+            window)) {
+      return;
+    }
+
+    // We do not auto snap windows in clamshell splitview mode if a new window
+    // is activated when clamshell splitview mode is active. In this case we'll
+    // just end overview mode which will then end splitview mode.
+    // TODO(xdai): Handle this logic in OverivewSession::OnWindowActivating().
+    if (split_view_controller_->InClamshellSplitViewMode()) {
+      Shell::Get()->overview_controller()->EndOverview();
+      return;
+    }
+
+    DCHECK(split_view_controller_->InTabletSplitViewMode());
+
+    // Do not snap the window if the activation change is caused by dragging a
+    // window, or by dragging a tab. Note the two values
+    // WindowState::is_dragged() and IsDraggingTabs() might not be exactly the
+    // same under certain circumstance, e.g., when a tab is dragged out from a
+    // browser window, a new browser window will be created for the dragged tab
+    // and then be activated, and at that time, IsDraggingTabs() is true, but
+    // WindowState::is_dragged() is still false. And later after the window drag
+    // starts, WindowState::is_dragged() will then be true.
+    if (WindowState::Get(window)->is_dragged() ||
+        window_util::IsDraggingTabs(window)) {
+      return;
+    }
+
+    // If the divider is animating, then |window| cannot be snapped (and is
+    // not already snapped either, because then we would have bailed out by
+    // now). Then if |window| is user-positionable, we should end split view
+    // mode, but the cannot snap toast would be inappropriate because the user
+    // still might be able to snap |window|.
+    if (split_view_controller_->IsDividerAnimating()) {
+      if (WindowState::Get(window)->IsUserPositionable())
+        split_view_controller_->EndSplitView(
+            EndReason::kUnsnappableWindowActivated);
+      return;
+    }
+
+    // If it's a user positionable window but can't be snapped, end split view
+    // mode and show the cannot snap toast.
+    if (!split_view_controller_->CanSnapWindow(window)) {
+      if (WindowState::Get(window)->IsUserPositionable()) {
+        split_view_controller_->EndSplitView(
+            EndReason::kUnsnappableWindowActivated);
+        ShowAppCannotSnapToast();
+      }
+      return;
+    }
+
+    // Snap the window on the non-default side of the screen if split view mode
+    // is active.
+    split_view_controller_->SnapWindow(
+        window, (split_view_controller_->default_snap_position() == LEFT)
+                    ? RIGHT
+                    : LEFT);
+  }
+
+  void AddWindow(aura::Window* window) {
+    if (split_view_controller_->root_window() != window->GetRootWindow())
+      return;
+
+    if (!window->HasObserver(this))
+      window->AddObserver(this);
+    observed_windows_.insert(window);
+  }
+
+  void RemoveWindow(aura::Window* window) {
+    window->RemoveObserver(this);
+    observed_windows_.erase(window);
+  }
+
+  SplitViewController* split_view_controller_;
+
+  // Tracks observed windows.
+  base::flat_set<aura::Window*> observed_windows_;
+};
+
 // static
 SplitViewController* SplitViewController::Get(const aura::Window* window) {
   DCHECK(window);
@@ -459,7 +642,8 @@
     // Add observers when the split view mode starts.
     Shell::Get()->AddShellObserver(this);
     Shell::Get()->overview_controller()->AddObserver(this);
-    Shell::Get()->activation_client()->AddObserver(this);
+
+    auto_snap_controller_ = std::make_unique<AutoSnapController>(this);
 
     // If there is pre-set |divider_position_|, use it. It can happen during
     // tablet <-> clamshell transition or multi-user transition.
@@ -867,7 +1051,8 @@
   // Remove observers when the split view mode ends.
   Shell::Get()->RemoveShellObserver(this);
   Shell::Get()->overview_controller()->RemoveObserver(this);
-  Shell::Get()->activation_client()->RemoveObserver(this);
+
+  auto_snap_controller_.reset();
 
   StopObserving(LEFT);
   StopObserving(RIGHT);
@@ -907,6 +1092,14 @@
   divider_position_ = divider_position;
 }
 
+bool SplitViewController::IsWindowInTransitionalState(
+    const aura::Window* window) const {
+  if (!IsWindowInSplitView(window))
+    return false;
+  return WindowState::Get(window)->GetStateType() !=
+         GetStateTypeFromSnapPosition(GetPositionOfSnappedWindow(window));
+}
+
 void SplitViewController::OnOverviewButtonTrayLongPressed(
     const gfx::Point& event_location) {
   // Do nothing if split view is not enabled.
@@ -1128,86 +1321,6 @@
   }
 }
 
-void SplitViewController::OnWindowActivated(ActivationReason reason,
-                                            aura::Window* gained_active,
-                                            aura::Window* lost_active) {
-  if (!gained_active || gained_active->GetRootWindow() != root_window_)
-    return;
-
-  if (DesksController::Get()->AreDesksBeingModified()) {
-    // Activating a desk from its mini view will activate its most-recently used
-    // window, but this should not result in snapping and ending overview mode
-    // now. Overview will be ended explicitly as part of the desk activation
-    // animation.
-    return;
-  }
-
-  // If |gained_active| was activated as a side effect of a window disposition
-  // change, do nothing. For example, when a snapped window is closed, another
-  // window will be activated before OnWindowDestroying() is called. We should
-  // not try to snap another window in this case.
-  if (reason == ActivationReason::WINDOW_DISPOSITION_CHANGED)
-    return;
-
-  // Only windows that are in the MRU list and are not already in split view can
-  // be auto-snapped.
-  if (IsWindowInSplitView(gained_active) ||
-      !base::Contains(
-          Shell::Get()->mru_window_tracker()->BuildMruWindowList(kActiveDesk),
-          gained_active)) {
-    return;
-  }
-
-  // We do not auto snap windows in clamshell splitview mode if a new window
-  // is activated when clamshell splitview mode is active. In this case we'll
-  // just end overview mode which will then end splitview mode.
-  // TODO(xdai): Handle this logic in OverivewSession::OnWindowActivating().
-  if (InClamshellSplitViewMode()) {
-    Shell::Get()->overview_controller()->EndOverview();
-    return;
-  }
-
-  DCHECK(InTabletSplitViewMode());
-
-  // Do not snap the window if the activation change is caused by dragging a
-  // window, or by dragging a tab. Note the two values WindowState::is_dragged()
-  // and IsDraggingTabs() might not be exactly the same under certain
-  // circumstance, e.g., when a tab is dragged out from a browser window, a new
-  // browser window will be created for the dragged tab and then be activated,
-  // and at that time, IsDraggingTabs() is true, but WindowState::is_dragged()
-  // is still false. And later after the window drag starts,
-  // WindowState::is_dragged() will then be true.
-  if (WindowState::Get(gained_active)->is_dragged() ||
-      window_util::IsDraggingTabs(gained_active)) {
-    return;
-  }
-
-  // If the divider is animating, then |gained_active| cannot be snapped (and is
-  // not already snapped either, because then we would have bailed out by now).
-  // Then if |gained_active| is user-positionable, we should end split view
-  // mode, but the cannot snap toast would be inappropriate because the user
-  // still might be able to snap |gained_active|.
-  if (IsDividerAnimating()) {
-    if (WindowState::Get(gained_active)->IsUserPositionable())
-      EndSplitView(EndReason::kUnsnappableWindowActivated);
-    return;
-  }
-
-  // If it's a user positionable window but can't be snapped, end split view
-  // mode and show the cannot snap toast.
-  if (!CanSnapWindow(gained_active)) {
-    if (WindowState::Get(gained_active)->IsUserPositionable()) {
-      EndSplitView(EndReason::kUnsnappableWindowActivated);
-      ShowAppCannotSnapToast();
-    }
-    return;
-  }
-
-  // Snap the window on the non-default side of the screen if split view mode
-  // is active.
-  SnapWindow(gained_active, (default_snap_position_ == LEFT) ? RIGHT : LEFT);
-}
-
 void SplitViewController::OnPinnedStateChanged(aura::Window* pinned_window) {
   // Disable split view for pinned windows.
   if (WindowState::Get(pinned_window)->IsPinned() && InSplitViewMode())
diff --git a/ash/wm/splitview/split_view_controller.h b/ash/wm/splitview/split_view_controller.h
index c83047a..6b481be 100644
--- a/ash/wm/splitview/split_view_controller.h
+++ b/ash/wm/splitview/split_view_controller.h
@@ -23,7 +23,6 @@
 #include "ui/display/display.h"
 #include "ui/display/display_observer.h"
 #include "ui/gfx/geometry/point.h"
-#include "ui/wm/public/activation_change_observer.h"
 
 namespace ui {
 class Layer;
@@ -43,7 +42,6 @@
 // TODO(xdai): Make it work for multi-display non mirror environment.
 class ASH_EXPORT SplitViewController : public aura::WindowObserver,
                                        public WindowStateObserver,
-                                       public wm::ActivationChangeObserver,
                                        public ShellObserver,
                                        public OverviewObserver,
                                        public display::DisplayObserver,
@@ -204,6 +202,13 @@
   // on the middle split position).
   void InitDividerPositionForTransition(int divider_position);
 
+  // Returns true if |window| is in a transitinal state which means that
+  // |SplitViewController| has already changed its internal snapped state for
+  // |window| but the snapped state has not been applied to |window|'s window
+  // state yet. The transional state can be happen in some clients (e.g. ARC
+  // app) which handle window states asynchronously.
+  bool IsWindowInTransitionalState(const aura::Window* window) const;
+
   // Called when the overview button tray has been long pressed. Enters
   // splitview mode if the active window is snappable. Also enters overview mode
   // if device is not currently in overview mode.
@@ -236,11 +241,6 @@
   void OnPostWindowStateTypeChange(WindowState* window_state,
                                    WindowStateType old_type) override;
 
-  // wm::ActivationChangeObserver:
-  void OnWindowActivated(ActivationReason reason,
-                         aura::Window* gained_active,
-                         aura::Window* lost_active) override;
-
   // ShellObserver:
   void OnPinnedStateChanged(aura::Window* pinned_window) override;
 
@@ -279,6 +279,7 @@
   friend class SplitViewOverviewSessionTest;
   class TabDraggedWindowObserver;
   class DividerSnapAnimation;
+  class AutoSnapController;
 
   // These functions return |left_window_| and |right_window_|, swapped in
   // nonprimary screen orientations. Note that they may return null.
@@ -507,6 +508,9 @@
   // Records the presentation time of resize operation in split view mode.
   std::unique_ptr<PresentationTimeRecorder> presentation_time_recorder_;
 
+  // Observes windows and performs auto snapping if needed.
+  std::unique_ptr<AutoSnapController> auto_snap_controller_;
+
   DISALLOW_COPY_AND_ASSIGN(SplitViewController);
 };
 
diff --git a/ash/wm/splitview/split_view_controller_unittest.cc b/ash/wm/splitview/split_view_controller_unittest.cc
index b3fef33..f8660b26 100644
--- a/ash/wm/splitview/split_view_controller_unittest.cc
+++ b/ash/wm/splitview/split_view_controller_unittest.cc
@@ -2706,6 +2706,54 @@
       1);
 }
 
+// Tests that auto snapping is properly triggered if a window is going to
+// unminimized (visible but minimized) in tablet split view mode.
+TEST_P(SplitViewControllerTest, AutoSnapFromMinimizedState) {
+  const gfx::Rect bounds(0, 0, 400, 400);
+  std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
+  std::unique_ptr<aura::Window> window2(CreateNonSnappableWindow(bounds));
+  std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
+
+  // Nothing should happen in clamshell mode.
+  Shell::Get()->tablet_mode_controller()->SetEnabledForTest(false);
+  WindowState::Get(window1.get())->Minimize();
+  window1->Show();
+  EXPECT_FALSE(split_view_controller()->InSplitViewMode());
+  EXPECT_FALSE(split_view_controller()->IsWindowInSplitView(window1.get()));
+
+  // Nothing should happen not in tablet split view mode.
+  Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
+  WindowState::Get(window1.get())->Minimize();
+  window1->Show();
+  EXPECT_FALSE(split_view_controller()->InSplitViewMode());
+  EXPECT_FALSE(split_view_controller()->IsWindowInSplitView(window1.get()));
+
+  // Nothing should happen for a non-snappable window.
+  Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
+  WindowState::Get(window2.get())->Minimize();
+  window2->Show();
+  EXPECT_FALSE(split_view_controller()->InSplitViewMode());
+  EXPECT_FALSE(split_view_controller()->IsWindowInSplitView(window2.get()));
+
+  // Should performs auto snapping when showing a snappable window in table
+  // split view mode.
+  Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
+  split_view_controller()->SnapWindow(window3.get(), SplitViewController::LEFT);
+  EXPECT_TRUE(split_view_controller()->InTabletSplitViewMode());
+  EXPECT_TRUE(split_view_controller()->IsWindowInSplitView(window3.get()));
+  EXPECT_EQ(split_view_controller()->GetPositionOfSnappedWindow(window3.get()),
+            SplitViewController::LEFT);
+
+  WindowState::Get(window1.get())->Minimize();
+  window1->Show();
+  EXPECT_TRUE(split_view_controller()->InTabletSplitViewMode());
+  EXPECT_TRUE(split_view_controller()->IsWindowInSplitView(window1.get()));
+  EXPECT_EQ(split_view_controller()->GetPositionOfSnappedWindow(window1.get()),
+            SplitViewController::RIGHT);
+
+  EndSplitView();
+}
+
 // Test the tab-dragging related functionalities in tablet mode. Tab(s) can be
 // dragged out of a window and then put in split view mode or merge into another
 // window.
diff --git a/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc b/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc
index 033e673..24aab8f 100644
--- a/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc
+++ b/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc
@@ -11,14 +11,8 @@
 namespace {
 
 base::ThreadSafePartitionRoot& Allocator() {
-  static base::NoDestructor<base::ThreadSafePartitionRoot> allocator;
-  allocator->Init(false /* enforce_alignment */);
-  return *allocator;
-}
-
-base::ThreadSafePartitionRoot& AlignedAllocator() {
-  static base::NoDestructor<base::ThreadSafePartitionRoot> allocator;
-  allocator->Init(true /* enforce_alignment */);
+  static base::NoDestructor<base::ThreadSafePartitionRoot> allocator{
+      false /* enforce_alignment */};
   return *allocator;
 }
 
@@ -39,7 +33,9 @@
                         size_t alignment,
                         size_t size,
                         void* context) {
-  return AlignedAllocator().AlignedAlloc(alignment, size);
+  static base::NoDestructor<base::ThreadSafePartitionRoot> aligned_allocator{
+      true /* enforce_alignment */};
+  return aligned_allocator->AlignedAlloc(alignment, size);
 }
 
 void* PartitionRealloc(const AllocatorDispatch*,
diff --git a/base/allocator/partition_allocator/partition_alloc.cc b/base/allocator/partition_allocator/partition_alloc.cc
index 2b94f89..96bc8571 100644
--- a/base/allocator/partition_allocator/partition_alloc.cc
+++ b/base/allocator/partition_allocator/partition_alloc.cc
@@ -193,10 +193,9 @@
 }
 
 template <bool thread_safe>
-void PartitionRoot<thread_safe>::InitSlowPath(bool enforce_alignment) {
+void PartitionRoot<thread_safe>::Init(bool enforce_alignment) {
   ScopedGuard guard{lock_};
-
-  if (initialized.load(std::memory_order_relaxed))
+  if (initialized)
     return;
 
 #if defined(ARCH_CPU_64_BITS) && !defined(OS_NACL)
diff --git a/base/allocator/partition_allocator/partition_alloc.h b/base/allocator/partition_allocator/partition_alloc.h
index 970395a..55dfc1d0 100644
--- a/base/allocator/partition_allocator/partition_alloc.h
+++ b/base/allocator/partition_allocator/partition_alloc.h
@@ -404,8 +404,7 @@
   // nothing) instead of true|false, so that we can just add or subtract the
   // size instead of having an if branch on the hot paths.
   bool allow_extras;
-  // Atomic as initialization can be concurrent.
-  std::atomic<bool> initialized = {};
+  bool initialized = false;
   char* next_super_page = nullptr;
   char* next_partition_page = nullptr;
   char* next_partition_page_end = nullptr;
@@ -432,6 +431,9 @@
   Bucket buckets[kGenericNumBuckets] = {};
 
   PartitionRoot() = default;
+  explicit PartitionRoot(bool enable_tag_pointers) {
+    Init(enable_tag_pointers);
+  }
   ~PartitionRoot() = default;
 
   // Public API
@@ -444,15 +446,7 @@
   //
   // Moving it a layer lower couples PartitionRoot and PartitionBucket, but
   // preserves the layering of the includes.
-  ALWAYS_INLINE void Init(bool enforce_alignment) {
-    if (LIKELY(initialized.load(std::memory_order_relaxed)))
-      return;
-
-    InitSlowPath(enforce_alignment);
-#if ENABLE_TAG_FOR_CHECKED_PTR2 || ENABLE_TAG_FOR_MTE_CHECKED_PTR
-    current_partition_tag = base::RandUint64();
-#endif
-  }
+  void Init(bool enforce_alignment);
 
   ALWAYS_INLINE static bool IsValidPage(Page* page);
   ALWAYS_INLINE static PartitionRoot* FromPage(Page* page);
@@ -507,7 +501,6 @@
   internal::PartitionBucket<thread_safe>* SizeToBucket(size_t size) const;
 
  private:
-  void InitSlowPath(bool enforce_alignment);
   ALWAYS_INLINE void* AllocFromBucket(Bucket* bucket, int flags, size_t size)
       EXCLUSIVE_LOCKS_REQUIRED(lock_);
   bool ReallocDirectMappedInPlace(internal::PartitionPage<thread_safe>* page,
diff --git a/base/files/file_util_posix.cc b/base/files/file_util_posix.cc
index 091d9ef..148d52b 100644
--- a/base/files/file_util_posix.cc
+++ b/base/files/file_util_posix.cc
@@ -531,7 +531,17 @@
   ssize_t count =
       ::readlink(symlink_path.value().c_str(), buf, base::size(buf));
 
-  if (count <= 0) {
+#if defined(OS_ANDROID) && defined(__LP64__)
+  // A few 64-bit Android L/M devices return INT_MAX instead of -1 here for
+  // errors; this is related to bionic's (incorrect) definition of ssize_t as
+  // being long int instead of int. Cast it so the compiler generates the
+  // comparison we want here. https://crbug.com/1101940
+  bool error = static_cast<int32_t>(count) <= 0;
+#else
+  bool error = count <= 0;
+#endif
+
+  if (error) {
     target_path->clear();
     return false;
   }
diff --git a/base/memory/checked_ptr_unittest.cc b/base/memory/checked_ptr_unittest.cc
index 8018b49e..e7929703 100644
--- a/base/memory/checked_ptr_unittest.cc
+++ b/base/memory/checked_ptr_unittest.cc
@@ -11,6 +11,7 @@
 #include <utility>
 
 #include "base/allocator/partition_allocator/partition_alloc.h"
+#include "base/allocator/partition_allocator/partition_alloc_features.h"
 #include "base/allocator/partition_allocator/partition_tag.h"
 #include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -740,6 +741,34 @@
   LOG(FATAL) << "Out of memory";
 }
 
+// This test works only when PartitionAlloc is used, when tags are enabled.
+// Don't enable it when MEMORY_TOOL_REPLACES_ALLOCATOR is defined, because it
+// makes PartitionAlloc take a different path that doesn't provide tags, thus no
+// crash on UaF, thus missing the EXPECT_DEATH_IF_SUPPORTED expectation.
+#if BUILDFLAG(USE_PARTITION_ALLOC) &&                                  \
+    (ENABLE_TAG_FOR_CHECKED_PTR2 || ENABLE_TAG_FOR_MTE_CHECKED_PTR) && \
+    !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
+
+TEST(CheckedPtr2OrMTEImpl, CrashOnUseAfterFree) {
+  // This test works only if GigaCage is enabled. Bail out otherwise.
+  if (!IsPartitionAllocGigaCageEnabled())
+    return;
+
+  // TODO(bartekn): Avoid using PartitionAlloc API directly. Switch to
+  // new/delete once PartitionAlloc Everywhere is fully enabled.
+  PartitionAllocGlobalInit(HandleOOM);
+  PartitionAllocator<ThreadSafe> allocator;
+  allocator.init();
+  void* raw_ptr = allocator.root()->Alloc(sizeof(int), "int");
+  CheckedPtr<int> ptr = static_cast<int*>(raw_ptr);
+  *ptr = 42;
+  EXPECT_TRUE(*ptr == 42);
+  allocator.root()->Free(raw_ptr);
+  EXPECT_DEATH_IF_SUPPORTED(if (*ptr == 42) return, "");
+}
+
+#endif
+
 }  // namespace internal
 }  // namespace base
 
diff --git a/base/stl_util.h b/base/stl_util.h
index d8db9b14..8e9fab3 100644
--- a/base/stl_util.h
+++ b/base/stl_util.h
@@ -447,10 +447,22 @@
                                   std::forward<Args>(args)...);
 }
 
-// Returns true if the container is sorted.
+// Returns true if the container is sorted. Requires constexpr std::begin/end,
+// which exists for arrays in C++14.
+// Note that std::is_sorted is constexpr beginning C++20 and this should be
+// switched to use it when C++20 is supported.
 template <typename Container>
-bool STLIsSorted(const Container& cont) {
-  return std::is_sorted(std::begin(cont), std::end(cont));
+constexpr bool STLIsSorted(const Container& cont) {
+  auto it = std::begin(cont);
+  const auto end = std::end(cont);
+  if (it == end)
+    return true;
+
+  for (auto prev = it++; it != end; prev = it++) {
+    if (*it < *prev)
+      return false;
+  }
+  return true;
 }
 
 // Returns a new ResultType containing the difference of two sorted containers.
diff --git a/base/stl_util_unittest.cc b/base/stl_util_unittest.cc
index 2440064..55980a51 100644
--- a/base/stl_util_unittest.cc
+++ b/base/stl_util_unittest.cc
@@ -808,5 +808,16 @@
   EXPECT_NE(nullptr, base::OptionalOrNullptr(optional));
 }
 
+TEST(STLUtilTest, STLIsSortedConstexpr) {
+  constexpr int kArrayAscending[] = {1, 2, 3, 4};
+  static_assert(base::STLIsSorted(kArrayAscending), "");
+
+  constexpr int kArrayDescending[] = {4, 3, 2, 1};
+  static_assert(!base::STLIsSorted(kArrayDescending), "");
+
+  constexpr int kArrayEqual[] = {1, 1, 1, 1};
+  static_assert(base::STLIsSorted(kArrayEqual), "");
+}
+
 }  // namespace
 }  // namespace base
diff --git a/base/trace_event/traced_value.h b/base/trace_event/traced_value.h
index 67d788ca8..58a3ec4 100644
--- a/base/trace_event/traced_value.h
+++ b/base/trace_event/traced_value.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 
 #include <memory>
+#include <sstream>
 #include <string>
 #include <vector>
 
@@ -130,6 +131,14 @@
     KeptValueType kept_value_type_;
   };
 
+  // Return std::string representation given by |value|'s ostream operator<<.
+  template <class T>
+  static std::string ValueToString(const T& value) {
+    std::stringstream ss;
+    ss << value;
+    return ss.str();
+  }
+
   // A custom serialization class can be supplied by implementing the
   // Writer interface and supplying a factory class to SetWriterFactoryCallback.
   // Primarily used by Perfetto to write TracedValues directly into its proto
diff --git a/base/trace_event/traced_value_unittest.cc b/base/trace_event/traced_value_unittest.cc
index 652db8f..657a390 100644
--- a/base/trace_event/traced_value_unittest.cc
+++ b/base/trace_event/traced_value_unittest.cc
@@ -15,6 +15,11 @@
 namespace base {
 namespace trace_event {
 
+TEST(TraceEventArgumentTest, ValueToString) {
+  std::string zero = TracedValue::ValueToString(0);
+  EXPECT_EQ("0", zero);
+}
+
 TEST(TraceEventArgumentTest, InitializerListCreatedFlatDictionary) {
   std::string json;
   TracedValue::Build({{"bool_var", true},
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 4d465b18..22b77fa 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -3037,7 +3037,8 @@
               [ get_label_info(":$target_name", "label_no_toolchain") ],
               [
                 "//base*",
-                "//chrome*",
+                "//chrome/browser*",
+                "//chromecast*",
                 "//clank*",
                 "//components*",
                 "//content*",
@@ -3050,6 +3051,9 @@
                 "//third_party*",
                 "//ui*",
                 "//weblayer*",
+
+                # This is due to the "special group" bypass.
+                "*_bundle_module__java__header",
               ]) == []
 
       if (invoker.use_turbine && !_allow_transitive_interfaces) {
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index d6f26911..4e48046 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-0.20200715.2.1
+0.20200716.0.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index e7bda5f..4e48046 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-0.20200715.1.1
+0.20200716.0.1
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index ba82a5a5..38260acc 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -866,10 +866,12 @@
     "//third_party/android_deps:androidx_recyclerview_recyclerview_java",
     "//third_party/android_deps:androidx_swiperefreshlayout_swiperefreshlayout_java",
     "//third_party/android_deps:androidx_test_core_java",
+    "//third_party/android_deps:androidx_test_runner_java",
     "//third_party/android_deps:com_google_dagger_dagger_java",
     "//third_party/android_deps:com_google_protobuf_protobuf_javalite_java",
     "//third_party/android_deps:com_googlecode_java_diff_utils_diffutils_java",
     "//third_party/android_sdk/androidx_browser:androidx_browser_java",
+    "//third_party/android_support_test_runner:runner_java",
     "//third_party/blink/public:blink_headers_java",
     "//third_party/blink/public/mojom:android_mojo_bindings_java",
     "//third_party/blink/public/mojom:mojom_platform_java",
@@ -1107,6 +1109,7 @@
     "//third_party/android_deps:androidx_lifecycle_lifecycle_common_java",
     "//third_party/android_deps:androidx_preference_preference_java",
     "//third_party/android_deps:androidx_recyclerview_recyclerview_java",
+    "//third_party/android_deps:androidx_test_runner_java",
     "//third_party/android_deps:androidx_viewpager_viewpager_java",
     "//url:origin_java",
 
@@ -1211,6 +1214,7 @@
     "//chrome/android:app_hooks_java",
     "//chrome/android:chrome_java",
     "//chrome/android/features/vr:java",
+    "//chrome/browser/flags:java",
     "//chrome/browser/tab:java",
     "//chrome/browser/ui/messages/android:java",
     "//chrome/browser/util:java",
@@ -1225,6 +1229,7 @@
     "//third_party/android_deps:androidx_annotation_annotation_java",
     "//third_party/android_deps:androidx_lifecycle_lifecycle_common_java",
     "//third_party/android_deps:androidx_recyclerview_recyclerview_java",
+    "//third_party/android_deps:androidx_test_runner_java",
     "//third_party/android_sdk/androidx_browser:androidx_browser_java",
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
@@ -1866,6 +1871,7 @@
     "//components/sync/protocol:protocol_java",
     "//content/public/android:content_java",
     "//content/public/test/android:content_java_test_support",
+    "//third_party/android_deps:androidx_annotation_annotation_java",
     "//third_party/android_deps:com_google_protobuf_protobuf_javalite_java",
     "//third_party/junit",
   ]
@@ -2430,6 +2436,7 @@
     "//base:base_java_test_support",
     "//chrome/test/android:chrome_java_test_pagecontroller",
     "//content/public/test/android:content_java_test_support",
+    "//third_party/android_deps:androidx_test_runner_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/junit",
     "//third_party/ub-uiautomator:ub_uiautomator_java",
@@ -2470,6 +2477,7 @@
     "//base:base_java_test_support",
     "//chrome/test/android:chrome_java_test_pagecontroller",
     "//content/public/test/android:content_java_test_support",
+    "//third_party/android_deps:androidx_test_runner_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/junit",
   ]
@@ -3227,6 +3235,7 @@
     "//ui/android:ui_java",
     "//ui/android:ui_java_test_support",
     "//url:gurl_java",
+    "//url:origin_java",
     "//url/mojom:url_mojom_gurl_java",
   ]
 
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 696a869..eeebf6f 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -467,6 +467,7 @@
   "java/src/org/chromium/chrome/browser/customtabs/content/CustomTabIntentHandler.java",
   "java/src/org/chromium/chrome/browser/customtabs/content/CustomTabIntentHandlingStrategy.java",
   "java/src/org/chromium/chrome/browser/customtabs/content/DefaultCustomTabIntentHandlingStrategy.java",
+  "java/src/org/chromium/chrome/browser/customtabs/content/ProfileProvider.java",
   "java/src/org/chromium/chrome/browser/customtabs/content/TabCreationMode.java",
   "java/src/org/chromium/chrome/browser/customtabs/content/TabObserverRegistrar.java",
   "java/src/org/chromium/chrome/browser/customtabs/dependency_injection/BaseCustomTabActivityComponent.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni
index 00b2ce0..1625124 100644
--- a/chrome/android/chrome_junit_test_java_sources.gni
+++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -47,6 +47,7 @@
   "junit/src/org/chromium/chrome/browser/compositor/animation/CompositorAnimatorTest.java",
   "junit/src/org/chromium/chrome/browser/compositor/layouts/CompositorModelChangeProcessorUnitTest.java",
   "junit/src/org/chromium/chrome/browser/compositor/layouts/MockLayoutUpdateHost.java",
+  "junit/src/org/chromium/chrome/browser/compositor/layouts/StaticLayoutUnitTest.java",
   "junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java",
   "junit/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuCoordinatorTest.java",
   "junit/src/org/chromium/chrome/browser/contextmenu/RevampedContextMenuHeaderMediatorTest.java",
@@ -212,6 +213,7 @@
   "junit/src/org/chromium/chrome/browser/signin/SigninPromoUtilTest.java",
   "junit/src/org/chromium/chrome/browser/signin/SigninUtilsStartActivityTest.java",
   "junit/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerMediatorTest.java",
+  "junit/src/org/chromium/chrome/browser/site_settings/SingleWebsiteSettingsTest.java",
   "junit/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorMediatorTest.java",
   "junit/src/org/chromium/chrome/browser/suggestions/SuggestionsImageFetcherTest.java",
   "junit/src/org/chromium/chrome/browser/suggestions/tile/TileGroupUnitTest.java",
diff --git a/chrome/android/features/autofill_assistant/BUILD.gn b/chrome/android/features/autofill_assistant/BUILD.gn
index d1bcfdad..e78311e3 100644
--- a/chrome/android/features/autofill_assistant/BUILD.gn
+++ b/chrome/android/features/autofill_assistant/BUILD.gn
@@ -63,6 +63,7 @@
     "//third_party/android_deps:androidx_lifecycle_lifecycle_common_java",
     "//third_party/android_deps:androidx_lifecycle_lifecycle_runtime_java",
     "//third_party/android_deps:androidx_recyclerview_recyclerview_java",
+    "//third_party/android_deps:com_android_support_support_annotations_java",
     "//third_party/android_deps:com_google_android_material_material_java",
     "//third_party/blink/public/mojom:android_mojo_bindings_java",
     "//ui/android:ui_java",
@@ -227,9 +228,11 @@
   deps = [
     ":java",
     ":test_support_jni_headers",
+    "//base:base_java",
     "//base:jni_java",
     "//components/autofill_assistant/browser:proto_java",
     "//content/public/test/android:content_java_test_support",
+    "//third_party/android_deps:androidx_annotation_annotation_java",
     "//third_party/android_deps:com_google_protobuf_protobuf_javalite_java",
     "//third_party/hamcrest:hamcrest_java",
   ]
@@ -277,6 +280,7 @@
     "//base:base_java_test_support",
     "//chrome/android:chrome_java",
     "//chrome/android:chrome_test_util_java",
+    "//chrome/browser/flags:java",
     "//chrome/browser/image_fetcher:java",
     "//chrome/browser/password_manager/android_test_helpers:test_support_java",
     "//chrome/browser/preferences:java",
@@ -290,16 +294,20 @@
     "//content/public/android:content_java",
     "//content/public/test/android:content_java_test_support",
     "//net/android:net_java_test_support",
+    "//third_party/android_deps:androidx_annotation_annotation_java",
     "//third_party/android_deps:androidx_coordinatorlayout_coordinatorlayout_java",
     "//third_party/android_deps:androidx_recyclerview_recyclerview_java",
+    "//third_party/android_deps:androidx_test_runner_java",
     "//third_party/android_deps:com_google_android_material_material_java",
     "//third_party/android_deps:com_google_protobuf_protobuf_javalite_java",
     "//third_party/android_deps:espresso_java",
     "//third_party/android_support_test_runner:runner_java",
+    "//third_party/gif_player:gif_player_java",
     "//third_party/hamcrest:hamcrest_java",
     "//third_party/junit",
     "//third_party/mockito:mockito_java",
     "//ui/android:ui_full_java",
+    "//ui/android:ui_java_test_support",
     "//url:gurl_java",
   ]
 
diff --git a/chrome/android/features/keyboard_accessory/BUILD.gn b/chrome/android/features/keyboard_accessory/BUILD.gn
index 9e61e4e8..54ffffd 100644
--- a/chrome/android/features/keyboard_accessory/BUILD.gn
+++ b/chrome/android/features/keyboard_accessory/BUILD.gn
@@ -60,6 +60,7 @@
     "//chrome/android:chrome_java",
     "//chrome/android:chrome_test_java",
     "//chrome/android:chrome_test_util_java",
+    "//chrome/browser/flags:java",
     "//chrome/browser/profiles/android:java",
     "//chrome/browser/tab:java",
     "//chrome/browser/ui/messages/android:java",
@@ -73,7 +74,9 @@
     "//content/public/android:content_java",
     "//content/public/test/android:content_java_test_support",
     "//net/android:net_java_test_support",
+    "//third_party/android_deps:androidx_annotation_annotation_java",
     "//third_party/android_deps:androidx_recyclerview_recyclerview_java",
+    "//third_party/android_deps:androidx_test_runner_java",
     "//third_party/android_deps:com_google_android_material_material_java",
     "//third_party/android_deps:espresso_java",
     "//third_party/android_support_test_runner:runner_java",
@@ -111,10 +114,12 @@
     "//chrome/browser/tabmodel:java",
     "//chrome/test/android:chrome_java_test_support",
     "//components/autofill/android:autofill_java",
+    "//components/browser_ui/android/bottomsheet:java",
     "//components/embedder_support/android:content_view_java",
     "//components/feature_engagement/public:public_java",
     "//components/module_installer/android:module_installer_java",
     "//content/public/android:content_java",
+    "//third_party/android_deps:androidx_annotation_annotation_java",
     "//third_party/android_deps:androidx_recyclerview_recyclerview_java",
     "//third_party/android_deps:com_google_android_material_material_java",
     "//third_party/hamcrest:hamcrest_java",
diff --git a/chrome/android/features/keyboard_accessory/internal/BUILD.gn b/chrome/android/features/keyboard_accessory/internal/BUILD.gn
index 4243bd3b..e5cd846 100644
--- a/chrome/android/features/keyboard_accessory/internal/BUILD.gn
+++ b/chrome/android/features/keyboard_accessory/internal/BUILD.gn
@@ -29,6 +29,7 @@
     "//components/feature_engagement/public:public_java",
     "//content/public/android:content_java",
     "//third_party/android_deps:android_support_v7_appcompat_java",
+    "//third_party/android_deps:androidx_annotation_annotation_java",
     "//third_party/android_deps:androidx_appcompat_appcompat_resources_java",
     "//third_party/android_deps:androidx_recyclerview_recyclerview_java",
     "//third_party/android_deps:androidx_viewpager_viewpager_java",
diff --git a/chrome/android/features/keyboard_accessory/public/BUILD.gn b/chrome/android/features/keyboard_accessory/public/BUILD.gn
index a88bcc3..5a7b7f1 100644
--- a/chrome/android/features/keyboard_accessory/public/BUILD.gn
+++ b/chrome/android/features/keyboard_accessory/public/BUILD.gn
@@ -10,6 +10,7 @@
     "//components/autofill/android:autofill_java",
     "//components/browser_ui/android/bottomsheet:java",
     "//third_party/android_deps:androidx_annotation_annotation_java",
+    "//ui/android:ui_full_java",
   ]
   sources = [
     "java/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingComponent.java",
diff --git a/chrome/android/features/media_router/BUILD.gn b/chrome/android/features/media_router/BUILD.gn
index 2d21e33b1..1001a754 100644
--- a/chrome/android/features/media_router/BUILD.gn
+++ b/chrome/android/features/media_router/BUILD.gn
@@ -21,6 +21,7 @@
     "//components/browser_ui/media/android:java",
     "//services/media_session/public/cpp/android:media_session_java",
     "//third_party/android_deps:android_support_v7_appcompat_java",
+    "//third_party/android_deps:androidx_annotation_annotation_java",
     "//third_party/android_deps:androidx_collection_collection_java",
     "//third_party/android_deps:androidx_core_core_java",
     "//third_party/android_deps:androidx_mediarouter_mediarouter_java",
@@ -94,13 +95,17 @@
     "//base:base_java_test_support",
     "//chrome/android:chrome_java",
     "//chrome/android:chrome_test_util_java",
+    "//chrome/browser/flags:java",
     "//chrome/test/android:chrome_java_test_support",
     "//content/public/android:content_java",
     "//content/public/test/android:content_java_test_support",
     "//net/android:net_java_test_support",
+    "//third_party/android_deps:androidx_annotation_annotation_java",
+    "//third_party/android_deps:androidx_test_runner_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/hamcrest:hamcrest_java",
     "//third_party/junit",
+    "//ui/android:ui_java_test_support",
   ]
 }
 
@@ -131,6 +136,7 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
+    "//third_party/android_deps:androidx_annotation_annotation_java",
     "//third_party/android_deps:androidx_mediarouter_mediarouter_java",
   ]
 }
diff --git a/chrome/android/features/start_surface/internal/BUILD.gn b/chrome/android/features/start_surface/internal/BUILD.gn
index 3cd34ad..4599e022 100644
--- a/chrome/android/features/start_surface/internal/BUILD.gn
+++ b/chrome/android/features/start_surface/internal/BUILD.gn
@@ -79,6 +79,7 @@
     "//components/prefs/android:java",
     "//components/user_prefs/android:java",
     "//third_party/android_deps:android_support_v7_appcompat_java",
+    "//third_party/android_deps:androidx_annotation_annotation_java",
     "//third_party/android_deps:com_google_android_material_material_java",
     "//ui/android:ui_full_java",
   ]
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java
index 6eb11e7..185d39db 100644
--- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java
+++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java
@@ -54,10 +54,11 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
+import org.chromium.chrome.browser.compositor.layouts.Layout;
 import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChromePhone;
 import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChromeTablet;
 import org.chromium.chrome.browser.compositor.layouts.OverviewModeState;
-import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
+import org.chromium.chrome.browser.compositor.layouts.StaticLayout;
 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
 import org.chromium.chrome.browser.flags.CachedFeatureFlags;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
@@ -774,7 +775,7 @@
     @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE})
     @Features.DisableFeatures(ChromeFeatureList.START_SURFACE_ANDROID)
     public void testInstantStartWithoutStartSurface() throws IOException {
-        createTabStateFile(new int[] {0});
+        createTabStateFile(new int[] {123});
         mActivityTestRule.startMainActivityFromLauncher();
 
         Assert.assertTrue(TabUiFeatureUtilities.supportInstantStart(false));
@@ -783,10 +784,9 @@
 
         Assert.assertEquals(1,
                 mActivityTestRule.getActivity().getTabModelSelector().getCurrentModel().getCount());
-        LayoutTab layoutTab =
-                mActivityTestRule.getActivity().getLayoutManager().getLayoutTabForTesting(
-                        mActivityTestRule.getActivity().getTabModelSelector().getCurrentTabId());
-        Assert.assertNotNull(layoutTab);
+        Layout activeLayout = mActivityTestRule.getActivity().getLayoutManager().getActiveLayout();
+        Assert.assertTrue(activeLayout instanceof StaticLayout);
+        Assert.assertEquals(123, ((StaticLayout) activeLayout).getCurrentTabIdForTesting());
     }
 
     /**
diff --git a/chrome/android/features/tab_ui/java/res/layout/tab_grid_dialog_layout.xml b/chrome/android/features/tab_ui/java/res/layout/tab_grid_dialog_layout.xml
index 47bef58..98fb055d 100644
--- a/chrome/android/features/tab_ui/java/res/layout/tab_grid_dialog_layout.xml
+++ b/chrome/android/features/tab_ui/java/res/layout/tab_grid_dialog_layout.xml
@@ -13,6 +13,8 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:id="@+id/dialog_container_view"
+        android:focusable="true"
+        android:focusableInTouchMode="true"
         android:background="@drawable/tab_grid_dialog_background">
         <!-- Ignore useless parents here for two reasons:
         1. Content recyclerView and toolbar view will be added programmatically later.
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogView.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogView.java
index bf08684e..d358488 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogView.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogView.java
@@ -19,6 +19,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.PopupWindow;
@@ -187,6 +188,8 @@
             @Override
             public void onAnimationEnd(Animator animation) {
                 mCurrentDialogAnimator = null;
+                mDialogContainerView.requestFocus();
+                mDialogContainerView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
             }
         };
         mHideDialogAnimationListener = new AnimatorListenerAdapter() {
@@ -194,6 +197,7 @@
             public void onAnimationEnd(Animator animation) {
                 setVisibility(View.GONE);
                 mCurrentDialogAnimator = null;
+                mDialogContainerView.clearFocus();
             }
         };
 
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewTest.java
index 104f081..c601cf0f 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewTest.java
@@ -281,6 +281,7 @@
             View sourceView = new View(getActivity());
             mTabGridDialogView.setupDialogAnimation(sourceView);
             parentViewReference.set((ViewGroup) mTabGridDialogContainer.getParent());
+            Assert.assertFalse(mTabGridDialogContainer.isFocused());
         });
         ViewGroup parent = parentViewReference.get();
 
@@ -304,8 +305,10 @@
                                 mTabGridDialogView.getCurrentDialogAnimatorForTesting(),
                                 Matchers.nullValue()));
 
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> Assert.assertEquals(0f, mBackgroundFrameView.getAlpha(), 0.0));
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            Assert.assertEquals(0f, mBackgroundFrameView.getAlpha(), 0.0);
+            Assert.assertTrue(mTabGridDialogContainer.isFocused());
+        });
 
         // Hide the dialog with zoom-in animation.
         TestThreadUtils.runOnUiThreadBlocking(() -> {
@@ -336,6 +339,7 @@
             Assert.assertEquals(0f, mTabGridDialogContainer.getTranslationY(), 0.0);
             Assert.assertEquals(1f, mTabGridDialogContainer.getScaleX(), 0.0);
             Assert.assertEquals(1f, mTabGridDialogContainer.getScaleY(), 0.0);
+            Assert.assertFalse(mTabGridDialogContainer.isFocused());
         });
     }
 
@@ -346,6 +350,7 @@
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             View sourceView = new View(getActivity());
             mTabGridDialogView.setupDialogAnimation(sourceView);
+            Assert.assertFalse(mTabGridDialogContainer.isFocused());
         });
         // Show the dialog.
         TestThreadUtils.runOnUiThreadBlocking(() -> mTabGridDialogView.showDialog());
@@ -358,6 +363,7 @@
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             Assert.assertEquals(0f, mAnimationCardView.getAlpha(), 0.0);
             Assert.assertEquals(0f, mBackgroundFrameView.getAlpha(), 0.0);
+            Assert.assertTrue(mTabGridDialogContainer.isFocused());
         });
 
         // Hide the dialog with basic fade-out animation.
@@ -381,6 +387,7 @@
             Assert.assertEquals(View.GONE, mTabGridDialogView.getVisibility());
             Assert.assertEquals(0f, mAnimationCardView.getAlpha(), 0.0);
             Assert.assertEquals(0f, mBackgroundFrameView.getAlpha(), 0.0);
+            Assert.assertFalse(mTabGridDialogContainer.isFocused());
         });
     }
 
@@ -393,6 +400,7 @@
             // Initially alpha of animation related views should be 0.
             Assert.assertEquals(0f, mAnimationCardView.getAlpha(), 0.0);
             Assert.assertEquals(0f, mBackgroundFrameView.getAlpha(), 0.0);
+            Assert.assertFalse(mTabGridDialogContainer.isFocused());
         });
 
         // Show the dialog with basic fade-in animation.
@@ -411,6 +419,7 @@
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             Assert.assertEquals(0f, mAnimationCardView.getAlpha(), 0.0);
             Assert.assertEquals(0f, mBackgroundFrameView.getAlpha(), 0.0);
+            Assert.assertTrue(mTabGridDialogContainer.isFocused());
         });
 
         // Hide the dialog with basic fade-out animation.
@@ -436,6 +445,7 @@
             Assert.assertEquals(View.GONE, mTabGridDialogView.getVisibility());
             Assert.assertEquals(0f, mAnimationCardView.getAlpha(), 0.0);
             Assert.assertEquals(0f, mBackgroundFrameView.getAlpha(), 0.0);
+            Assert.assertFalse(mTabGridDialogContainer.isFocused());
         });
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java b/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java
index 5617063..83745ce 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java
@@ -354,7 +354,7 @@
 
         mWebContentsCreatedForCCT = forCCT;
         mSpareWebContents = new WebContentsFactory().createWebContentsWithWarmRenderer(
-                false /* incognito */, true /* initiallyHidden */);
+                Profile.getLastUsedRegularProfile(), true /* initiallyHidden */);
         mObserver = new RenderProcessGoneObserver();
         mSpareWebContents.addObserver(mObserver);
         mWebContentsCreationTimeMs = SystemClock.elapsedRealtime();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/WebContentsFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/WebContentsFactory.java
index 8677c2a..94358b4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/WebContentsFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/WebContentsFactory.java
@@ -59,26 +59,6 @@
      *
      * Also creates and initializes the renderer.
      *
-     * @param incognito       Whether or not the {@link WebContents} should be built with an
-     *                        off-the-record profile or not.
-     * @param initiallyHidden Whether or not the {@link WebContents} should be initially hidden.
-     * @return                A newly created {@link WebContents} object.
-     *
-     * @deprecated use {@link #createWebContentsWithWarmRenderer(Profile, boolean)} instead.
-     */
-    @Deprecated
-    public WebContents createWebContentsWithWarmRenderer(
-            boolean incognito, boolean initiallyHidden) {
-        Profile profile = Profile.getLastUsedRegularProfile();
-        if (incognito) profile = profile.getPrimaryOTRProfile();
-        return createWebContents(profile, initiallyHidden, true);
-    }
-
-    /**
-     * A factory method to build a {@link WebContents} object.
-     *
-     * Also creates and initializes the renderer.
-     *
      * @param profile         The profile to be used by the WebContents.
      * @param initiallyHidden Whether or not the {@link WebContents} should be initially hidden.
      * @return                A newly created {@link WebContents} object.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/CompositorModelChangeProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/CompositorModelChangeProcessor.java
index f881278..e429358 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/CompositorModelChangeProcessor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/CompositorModelChangeProcessor.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.compositor.layouts;
 
+import androidx.annotation.VisibleForTesting;
+
 import org.chromium.base.Callback;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.ObservableSupplierImpl;
@@ -26,17 +28,18 @@
      * request another frame.
      */
     public static class FrameRequestSupplier extends ObservableSupplierImpl<Long> {
-        private final LayoutManagerHost mHost;
+        private final LayoutUpdateHost mHost;
 
-        public FrameRequestSupplier(LayoutManagerHost host) {
+        public FrameRequestSupplier(LayoutUpdateHost host) {
             mHost = host;
         }
 
         /**
          * Request to generate a new frame.
          */
-        private void request() {
-            mHost.requestRender();
+        @VisibleForTesting
+        void request() {
+            mHost.requestUpdate();
         }
     }
 
@@ -124,4 +127,4 @@
 
         mFrameSupplier.request();
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java
index 3c30dd4a..ca90a4d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/Layout.java
@@ -27,6 +27,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
+import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.resources.ResourceManager;
 
 import java.lang.annotation.Retention;
@@ -284,13 +285,13 @@
      * Update snapping to pixel. To be called once every frame.
      *
      * TODO(crbug.com/1070281): Temporary placement. This is some Mediator logic and should move to
-     * the appropriate location when doing MVC.
+     * the appropriate location when doing MVC. Maybe move to {@link LayoutMediator}.
      *
      * @param dt The delta time between update frames in ms.
      * @param layoutTab The {@link LayoutTab} that needs to be updating.
      * @return   True if the snapping requests to render at least one more frame.
      */
-    protected boolean updateSnap(long dt, LayoutTab layoutTab) {
+    protected boolean updateSnap(long dt, PropertyModel layoutTab) {
         final float step = dt * SNAP_SPEED / 1000.0f;
         final float renderX = layoutTab.get(LayoutTab.RENDER_X);
         final float renderY = layoutTab.get(LayoutTab.RENDER_Y);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java
index f46f7fb..8b5f9f43 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java
@@ -18,6 +18,8 @@
 
 import org.chromium.base.ObserverList;
 import org.chromium.base.TraceEvent;
+import org.chromium.base.supplier.ObservableSupplierImpl;
+import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsUtils;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsVisibilityManager;
 import org.chromium.chrome.browser.compositor.LayerTitleCache;
@@ -150,6 +152,14 @@
      */
     private Tab mCurrentTab;
 
+    private final ObservableSupplierImpl<TabModelSelector> mTabModelSelectorSupplier =
+            new ObservableSupplierImpl<>();
+    private final ObservableSupplierImpl<TabContentManager> mTabContentManagerSupplier =
+            new ObservableSupplierImpl<>();
+    private final ObservableSupplierImpl<BrowserControlsStateProvider>
+            mBrowserControlsStateProviderSupplier = new ObservableSupplierImpl<>();
+    private final CompositorModelChangeProcessor.FrameRequestSupplier mFrameRequestSupplier;
+
     /**
      * Protected class to handle {@link TabModelObserver} related tasks. Extending classes will
      * need to override any related calls to add new functionality */
@@ -239,8 +249,13 @@
 
         mOverlayPanelManager = new OverlayPanelManager();
 
+        mFrameRequestSupplier = new CompositorModelChangeProcessor.FrameRequestSupplier(this);
+
+        // TODO(crbug.com/1070281): Move this to #init.
         // Build Layouts
-        mStaticLayout = new StaticLayout(mContext, this, renderHost, null, mOverlayPanelManager);
+        mStaticLayout = new StaticLayout(mContext, this, renderHost, mHost, mFrameRequestSupplier,
+                mTabModelSelectorSupplier, mTabContentManagerSupplier,
+                mBrowserControlsStateProviderSupplier);
 
         // Set up layout parameters
         mStaticLayout.setLayoutHandlesTabLifecycles(true);
@@ -366,11 +381,15 @@
         // has its own timer.
         boolean areAnimatorsComplete = mAnimationHandler.pushUpdate();
 
+        // TODO(crbug.com/1070281): Remove after the FrameRequestSupplier migrates to the animation
+        //  system.
         final Layout layout = getActiveLayout();
         if (layout != null && layout.onUpdate(timeMs, dtMs) && layout.isHiding()
                 && areAnimatorsComplete) {
             layout.doneHiding();
         }
+
+        mFrameRequestSupplier.set(timeMs);
         return mUpdateRequested;
     }
 
@@ -410,6 +429,8 @@
 
         // Initialize Layouts
         mStaticLayout.setTabModelSelector(selector, content);
+        mTabContentManagerSupplier.set(content);
+        mBrowserControlsStateProviderSupplier.set(mHost.getBrowserControlsManager());
 
         // Initialize Contextual Search Panel
         mContextualSearchPanel.setManagementDelegate(contextualSearchDelegate);
@@ -432,7 +453,7 @@
 
     public void setTabModelSelector(TabModelSelector selector) {
         mTabModelSelector = selector;
-        mStaticLayout.setTabModelSelector(selector, null);
+        mTabModelSelectorSupplier.set(selector);
         mTabModelSelectorTabObserver = new TabModelSelectorTabObserver(mTabModelSelector) {
             @Override
             public void onShown(Tab tab, @TabSelectionType int type) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/StaticLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/StaticLayout.java
index 22668da..d3902701 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/StaticLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/StaticLayout.java
@@ -5,28 +5,41 @@
 package org.chromium.chrome.browser.compositor.layouts;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.RectF;
 import android.os.Handler;
 
+import androidx.annotation.VisibleForTesting;
+
+import org.chromium.base.Callback;
+import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.compositor.LayerTitleCache;
+import org.chromium.chrome.browser.compositor.animation.CompositorAnimationHandler;
 import org.chromium.chrome.browser.compositor.animation.CompositorAnimator;
-import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager;
 import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
 import org.chromium.chrome.browser.compositor.layouts.eventfilter.EventFilter;
 import org.chromium.chrome.browser.compositor.scene_layer.SceneLayer;
 import org.chromium.chrome.browser.compositor.scene_layer.StaticTabSceneLayer;
+import org.chromium.chrome.browser.native_page.NativePageFactory;
+import org.chromium.chrome.browser.tab.SadTab;
 import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.chrome.browser.tab.TabSelectionType;
+import org.chromium.chrome.browser.tab.TabThemeColorHelper;
 import org.chromium.chrome.browser.tabmodel.TabModelImpl;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver;
+import org.chromium.chrome.browser.toolbar.ToolbarColors;
+import org.chromium.components.embedder_support.util.UrlConstants;
+import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.resources.ResourceManager;
 
 import java.util.Arrays;
 import java.util.LinkedList;
 
+// TODO(meiliang): Rename to StaticLayoutMediator.
 /**
  * A {@link Layout} that shows a single tab at full screen. This tab is chosen based on the
  * {@link #tabSelecting(long, int)} call, and is used to show a thumbnail of a {@link Tab}
@@ -44,40 +57,184 @@
         @Override
         public void run() {
             mUnstalling = false;
-            if (mLayoutTabs == null || mLayoutTabs.length == 0) return;
             CompositorAnimator
-                    .ofWritableFloatPropertyKey(getAnimationHandler(), mLayoutTabs[0],
-                            LayoutTab.SATURATION, mLayoutTabs[0].getSaturation(), 1.0f,
-                            HIDE_DURATION_MS)
+                    .ofWritableFloatPropertyKey(mAnimationHandler, mModel, LayoutTab.SATURATION,
+                            mModel.get(LayoutTab.SATURATION), 1.0f, HIDE_DURATION_MS)
                     .start();
             CompositorAnimator
-                    .ofWritableFloatPropertyKey(getAnimationHandler(), mLayoutTabs[0],
-                            LayoutTab.STATIC_TO_VIEW_BLEND, mLayoutTabs[0].getStaticToViewBlend(),
-                            0.0f, HIDE_DURATION_MS)
+                    .ofWritableFloatPropertyKey(mAnimationHandler, mModel,
+                            LayoutTab.STATIC_TO_VIEW_BLEND,
+                            mModel.get(LayoutTab.STATIC_TO_VIEW_BLEND), 0.0f, HIDE_DURATION_MS)
                     .start();
-            mLayoutTabs[0].setShouldStall(false);
+            mModel.set(LayoutTab.SHOULD_STALL, false);
         }
     }
+    private final Context mContext;
+    private final LayoutManagerHost mViewHost;
+    private final CompositorModelChangeProcessor.FrameRequestSupplier mRequestSupplier;
+
+    private final PropertyModel mModel;
+    private CompositorModelChangeProcessor mMcp;
+
+    private StaticTabSceneLayer mSceneLayer;
 
     private final UnstallRunnable mUnstallRunnable;
     private final Handler mHandler;
     private boolean mUnstalling;
-    private StaticTabSceneLayer mSceneLayer;
+
+    private TabModelSelector mTabModelSelector;
+    private TabModelSelectorTabModelObserver mTabModelSelectorTabModelObserver;
+    private TabModelSelectorTabObserver mTabModelSelectorTabObserver;
+
+    private BrowserControlsStateProvider mBrowserControlsStateProvider;
+    private BrowserControlsStateProvider.Observer mBrowserControlsStateProviderObserver;
+
+    private TabContentManager mTabContentManager;
+
+    private final CompositorAnimationHandler mAnimationHandler;
+
+    private boolean mIsActive;
+    private boolean mIsInitialized;
+
+    private static Integer sToolbarTextBoxBackgroundColorForTesting;
+    private static Float sToolbarTextBoxAlphaForTesting;
+
+    private float mPxToDp;
 
     /**
      * Creates an instance of the {@link StaticLayout}.
      * @param context             The current Android's context.
      * @param updateHost          The {@link LayoutUpdateHost} view for this layout.
      * @param renderHost          The {@link LayoutRenderHost} view for this layout.
-     * @param panelManager        The {@link OverlayPanelManager} responsible for showing panels.
      */
     public StaticLayout(Context context, LayoutUpdateHost updateHost, LayoutRenderHost renderHost,
-            EventFilter eventFilter, OverlayPanelManager panelManager) {
+            LayoutManagerHost viewHost,
+            CompositorModelChangeProcessor.FrameRequestSupplier requestSupplier,
+            ObservableSupplier<TabModelSelector> tabModelSelectoSupplier,
+            ObservableSupplier<TabContentManager> tabContentManagerSupplier,
+            ObservableSupplier<BrowserControlsStateProvider> browserControlsStateProviderSupplier) {
         super(context, updateHost, renderHost);
+        mContext = context;
+        mViewHost = viewHost;
+        mRequestSupplier = requestSupplier;
+
+        tabModelSelectoSupplier.addObserver(new Callback<TabModelSelector>() {
+            @Override
+            public void onResult(TabModelSelector tabModelSelector) {
+                setTabModelSelector(tabModelSelector);
+                tabModelSelectoSupplier.removeObserver(this);
+            }
+        });
+
+        tabContentManagerSupplier.addObserver(new Callback<TabContentManager>() {
+            @Override
+            public void onResult(TabContentManager tabContentManager) {
+                setTabContentManager(tabContentManager);
+                tabContentManagerSupplier.removeObserver(this);
+            }
+        });
+
+        browserControlsStateProviderSupplier.addObserver(
+                new Callback<BrowserControlsStateProvider>() {
+                    @Override
+                    public void onResult(
+                            BrowserControlsStateProvider browserControlsStateProvider) {
+                        setBrowserControlsStateProvider(browserControlsStateProvider);
+                        browserControlsStateProviderSupplier.removeObserver(this);
+                    }
+                });
+
+        mModel = new PropertyModel.Builder(LayoutTab.ALL_KEYS)
+                         .with(LayoutTab.SCALE, 1.0f)
+                         .with(LayoutTab.X, 0.0f)
+                         .with(LayoutTab.Y, 0.0f)
+                         .with(LayoutTab.RENDER_X, 0.0f)
+                         .with(LayoutTab.RENDER_Y, 0.0f)
+                         .with(LayoutTab.SATURATION, 1.0f)
+                         .with(LayoutTab.STATIC_TO_VIEW_BLEND, 0.0f)
+                         .with(LayoutTab.BRIGHTNESS, 1.0f)
+                         .build();
+
+        mAnimationHandler = updateHost.getAnimationHandler();
 
         mHandler = new Handler();
         mUnstallRunnable = new UnstallRunnable();
         mUnstalling = false;
+
+        Resources res = context.getResources();
+        float dpToPx = res.getDisplayMetrics().density;
+        mPxToDp = 1.0f / dpToPx;
+    }
+
+    private void setTabModelSelector(TabModelSelector tabModelSelector) {
+        assert tabModelSelector != null;
+        assert mTabModelSelector == null : "The TabModelSelector should set at most once";
+
+        mTabModelSelector = tabModelSelector;
+        // TODO(crbug.com/1070281): Investigating to use ActivityTabProvider instead.
+        mTabModelSelectorTabModelObserver = new TabModelSelectorTabModelObserver(tabModelSelector) {
+            @Override
+            public void didSelectTab(Tab tab, int type, int lastId) {
+                if (mIsActive) setStaticTab(tab);
+            }
+        };
+
+        mTabModelSelectorTabObserver = new TabModelSelectorTabObserver(tabModelSelector) {
+            @Override
+            public void onPageLoadFinished(Tab tab, String url) {
+                if (mIsActive) unstallImmediately(tab.getId());
+            }
+            @Override
+            public void onShown(Tab tab, @TabSelectionType int type) {
+                if (mModel.get(LayoutTab.TAB_ID) != tab.getId()) {
+                    setStaticTab(tab);
+                } else {
+                    updateStaticTab(tab);
+                }
+            }
+
+            @Override
+            public void onContentChanged(Tab tab) {
+                updateStaticTab(tab);
+            }
+
+            @Override
+            public void onBackgroundColorChanged(Tab tab, int color) {
+                updateStaticTab(tab);
+            }
+
+            @Override
+            public void onDidChangeThemeColor(Tab tab, int color) {
+                updateStaticTab(tab);
+            }
+        };
+    }
+
+    private void setTabContentManager(TabContentManager tabContentManager) {
+        assert tabContentManager != null;
+        assert mTabContentManager == null : "The TabContentManager should set at most once";
+
+        mTabContentManager = tabContentManager;
+        mSceneLayer.setTabContentManager(tabContentManager);
+    }
+
+    private void setBrowserControlsStateProvider(
+            BrowserControlsStateProvider browserControlsStateProvider) {
+        assert browserControlsStateProvider != null;
+        assert mBrowserControlsStateProvider
+                == null : "The ChromeFullscreenManager should set at most once";
+
+        mModel.set(LayoutTab.CONTENT_OFFSET, browserControlsStateProvider.getContentOffset());
+        mBrowserControlsStateProvider = browserControlsStateProvider;
+        mBrowserControlsStateProviderObserver = new BrowserControlsStateProvider.Observer() {
+            @Override
+            public void onControlsOffsetChanged(int topOffset, int topControlsMinHeightOffset,
+                    int bottomOffset, int bottomControlsMinHeightOffset, boolean needsAnimate) {
+                mModel.set(
+                        LayoutTab.CONTENT_OFFSET, browserControlsStateProvider.getContentOffset());
+            }
+        };
+        mBrowserControlsStateProvider.addObserver(mBrowserControlsStateProviderObserver);
     }
 
     /**
@@ -90,7 +247,16 @@
 
     @Override
     public void onFinishNativeInitialization() {
-        mSceneLayer = new StaticTabSceneLayer();
+        assert !mIsInitialized : "StaticLayoutMediator should initialize at most once";
+
+        mIsInitialized = true;
+
+        if (mSceneLayer == null) {
+            mSceneLayer = new StaticTabSceneLayer();
+        }
+
+        mMcp = CompositorModelChangeProcessor.create(
+                mModel, mSceneLayer, StaticTabSceneLayer::bind, mRequestSupplier);
     }
 
     @Override
@@ -107,100 +273,152 @@
     public void show(long time, boolean animate) {
         super.show(time, animate);
 
-        mLayoutTabs = null;
-        setStaticTab(mTabModelSelector.getCurrentTabId());
+        mIsActive = true;
+        Tab tab = mTabModelSelector.getCurrentTab();
+        if (tab == null) return;
+        setStaticTab(tab);
     }
 
     @Override
     protected void updateLayout(long time, long dt) {
         super.updateLayout(time, dt);
-        if (mLayoutTabs != null && mLayoutTabs.length > 0) updateSnap(dt, mLayoutTabs[0]);
+        updateSnap(dt, mModel);
+    }
+
+    @Override
+    public void doneHiding() {
+        super.doneHiding();
+        mIsActive = false;
     }
 
     @Override
     public void onTabSelected(long time, int id, int prevId, boolean incognito) {
-        setStaticTab(id);
-        super.onTabSelected(time, id, prevId, incognito);
+
     }
 
     @Override
     public void onTabSelecting(long time, int id) {
-        setStaticTab(id);
-        super.onTabSelecting(time, id);
+
     }
 
     @Override
     public void onTabCreated(long time, int tabId, int tabIndex, int sourceTabId,
             boolean newIsIncognito, boolean background, float originX, float originY) {
-        super.onTabCreated(
-                time, tabId, tabIndex, sourceTabId, newIsIncognito, background, originX, originY);
-        if (!background) setStaticTab(tabId);
+
     }
 
     @Override
     public void onTabModelSwitched(boolean incognito) {
-        super.onTabModelSwitched(incognito);
-        setStaticTab(mTabModelSelector.getCurrentTabId());
+
     }
 
     @Override
-    public void setTabModelSelector(TabModelSelector modelSelector, TabContentManager manager) {
-        super.setTabModelSelector(modelSelector, manager);
-        new TabModelSelectorTabObserver(mTabModelSelector) {
-            @Override
-            public void onPageLoadFinished(Tab tab, String url) {
-                if (isActive()) unstallImmediately(tab.getId());
-            }
-        };
-    }
+    public void setTabModelSelector(TabModelSelector modelSelector, TabContentManager manager) {}
 
     private void setPreHideState() {
         mHandler.removeCallbacks(mUnstallRunnable);
-        mLayoutTabs[0].setStaticToViewBlend(1.0f);
-        mLayoutTabs[0].setSaturation(0.0f);
+        mModel.set(LayoutTab.STATIC_TO_VIEW_BLEND, 1.0f);
+        mModel.set(LayoutTab.SATURATION, 0.0f);
         mUnstalling = true;
     }
 
     private void setPostHideState() {
         mHandler.removeCallbacks(mUnstallRunnable);
-        mLayoutTabs[0].setStaticToViewBlend(0.0f);
-        mLayoutTabs[0].setSaturation(1.0f);
+        mModel.set(LayoutTab.STATIC_TO_VIEW_BLEND, 0.0f);
+        mModel.set(LayoutTab.SATURATION, 1.0f);
         mUnstalling = false;
     }
 
-    private void setStaticTab(final int id) {
-        if (mLayoutTabs != null && mLayoutTabs.length > 0 && mLayoutTabs[0].getId() == id) {
-            if (!mLayoutTabs[0].shouldStall()) setPostHideState();
+    private void setStaticTab(Tab tab) {
+        assert tab != null;
+
+        if (mModel.get(LayoutTab.TAB_ID) == tab.getId() && !mModel.get(LayoutTab.SHOULD_STALL)) {
+            setPostHideState();
             return;
         }
-        TabModel model = mTabModelSelector.getModelForTabId(id);
-        if (model == null) return;
 
-        updateCacheVisibleIdsAndPrimary(new LinkedList<Integer>(Arrays.asList(id)), id);
+        if (mTabContentManager != null) {
+            mTabContentManager.updateVisibleIds(
+                    new LinkedList<Integer>(Arrays.asList(tab.getId())), tab.getId());
+        }
 
-        if (mLayoutTabs == null || mLayoutTabs.length != 1) mLayoutTabs = new LayoutTab[1];
-        mLayoutTabs[0] = createLayoutTab(id, model.isIncognito(), NO_CLOSE_BUTTON, NO_TITLE);
-        mLayoutTabs[0].setDrawDecoration(false);
-        if (mLayoutTabs[0].shouldStall()) {
+        mModel.set(LayoutTab.TAB_ID, tab.getId());
+        mModel.set(LayoutTab.IS_INCOGNITO, tab.isIncognito());
+        mModel.set(LayoutTab.ORIGINAL_CONTENT_WIDTH_IN_DP, mViewHost.getWidth() * mPxToDp);
+        mModel.set(LayoutTab.ORIGINAL_CONTENT_HEIGHT_IN_DP, mViewHost.getHeight() * mPxToDp);
+        mModel.set(LayoutTab.MAX_CONTENT_WIDTH, mViewHost.getWidth() * mPxToDp);
+        mModel.set(LayoutTab.MAX_CONTENT_HEIGHT, mViewHost.getHeight() * mPxToDp);
+
+        updateStaticTab(tab);
+
+        if (mModel.get(LayoutTab.SHOULD_STALL)) {
             setPreHideState();
             mHandler.postDelayed(mUnstallRunnable, HIDE_TIMEOUT_MS);
         } else {
             setPostHideState();
         }
-        requestRender();
+    }
+
+    private void updateStaticTab(Tab tab) {
+        if (!mIsActive || mModel.get(LayoutTab.TAB_ID) != tab.getId()) return;
+
+        mModel.set(LayoutTab.BACKGROUND_COLOR, TabThemeColorHelper.getBackgroundColor(tab));
+        mModel.set(LayoutTab.TOOLBAR_BACKGROUND_COLOR,
+                ToolbarColors.getToolbarSceneLayerBackground(tab));
+        mModel.set(LayoutTab.TEXT_BOX_ALPHA, getTextBoxAlphaForToolbarBackground(tab));
+        mModel.set(LayoutTab.SHOULD_STALL, shouldStall(tab));
+        mModel.set(LayoutTab.TEXT_BOX_BACKGROUND_COLOR, getToolbarTextBoxBackgroundColor(tab));
+
+        String url = tab.getUrlString();
+        boolean isNativePage = tab.isNativePage()
+                || (url != null && url.startsWith(UrlConstants.CHROME_NATIVE_URL_PREFIX));
+        boolean canUseLiveTexture =
+                tab.getWebContents() != null && !SadTab.isShowing(tab) && !isNativePage;
+        mModel.set(LayoutTab.CAN_USE_LIVE_TEXTURE, canUseLiveTexture);
+    }
+
+    private int getToolbarTextBoxBackgroundColor(Tab tab) {
+        if (sToolbarTextBoxBackgroundColorForTesting != null) {
+            return sToolbarTextBoxBackgroundColorForTesting;
+        }
+
+        int themeColor = TabThemeColorHelper.getColor(tab);
+        return ToolbarColors.getTextBoxColorForToolbarBackground(
+                mContext.getResources(), tab, themeColor);
+    }
+
+    @VisibleForTesting
+    void setTextBoxBackgroundColorForTesting(Integer color) {
+        sToolbarTextBoxBackgroundColorForTesting = color;
+    }
+
+    private float getTextBoxAlphaForToolbarBackground(Tab tab) {
+        if (sToolbarTextBoxAlphaForTesting != null) return sToolbarTextBoxAlphaForTesting;
+        return ToolbarColors.getTextBoxAlphaForToolbarBackground(tab);
+    }
+
+    @VisibleForTesting
+    void setToolbarTextBoxAlphaForTesting(Float alpha) {
+        sToolbarTextBoxAlphaForTesting = alpha;
+    }
+
+    // Whether the tab is ready to display or it should be faded in as it loads.
+    private boolean shouldStall(Tab tab) {
+        return (tab.isFrozen() || tab.needsReload())
+                && !NativePageFactory.isNativePageUrl(tab.getUrlString(), tab.isIncognito());
     }
 
     @Override
     public void unstallImmediately(int tabId) {
-        if (mLayoutTabs != null && mLayoutTabs.length > 0 && mLayoutTabs[0].getId() == tabId) {
+        if (mModel.get(LayoutTab.TAB_ID) == tabId && mModel.get(LayoutTab.SHOULD_STALL)
+                && mUnstalling) {
             unstallImmediately();
         }
     }
 
     @Override
     public void unstallImmediately() {
-        if (mLayoutTabs != null && mLayoutTabs.length > 0 && mLayoutTabs[0].shouldStall()
-                && mUnstalling) {
+        if (mModel.get(LayoutTab.SHOULD_STALL) && mUnstalling) {
             mHandler.removeCallbacks(mUnstallRunnable);
             mUnstallRunnable.run();
         }
@@ -244,19 +462,11 @@
                 resourceManager, browserControls);
         assert mSceneLayer != null;
 
-        final LayoutTab[] tabs = getLayoutTabsToRender();
-        if (tabs == null || tabs.length != 1 || tabs[0].getId() == Tab.INVALID_TAB_ID) {
-            return;
-        }
-        LayoutTab layoutTab = tabs[0];
-        final float dpToPx = getContext().getResources().getDisplayMetrics().density;
-
-        mSceneLayer.update(dpToPx, layerTitleCache, tabContentManager, browserControls, layoutTab);
-
-        // TODO(dtrainor): Find the best way to properly track this metric for cold starts.
-        // We should probably erase the thumbnail when we select a tab that we need to restore.
+        // TODO(dtrainor, crbug.com/1070281): Find the best way to properly track this metric for
+        //  cold starts. We should probably erase the thumbnail when we select a tab that we need to
+        //  restore. Potentially move to show().
         if (tabContentManager != null
-                && tabContentManager.hasFullCachedThumbnail(layoutTab.getId())) {
+                && tabContentManager.hasFullCachedThumbnail(mModel.get(LayoutTab.TAB_ID))) {
             TabModelImpl.logPerceivedTabSwitchLatencyMetric();
         }
     }
@@ -267,5 +477,43 @@
             mSceneLayer.destroy();
             mSceneLayer = null;
         }
+        if (mMcp != null) {
+            mMcp.destroy();
+            mMcp = null;
+        }
+        if (mTabModelSelector != null) {
+            mTabModelSelectorTabModelObserver.destroy();
+            mTabModelSelectorTabObserver.destroy();
+        }
+    }
+
+    @VisibleForTesting
+    PropertyModel getModelForTesting() {
+        return mModel;
+    }
+
+    @VisibleForTesting
+    void setSceneLayerForTesting(StaticTabSceneLayer sceneLayer) {
+        mSceneLayer = sceneLayer;
+    }
+
+    @VisibleForTesting
+    TabModelSelector getTabModelSelectorForTesting() {
+        return mTabModelSelector;
+    }
+
+    @VisibleForTesting
+    TabContentManager getTabContentManagerForTesting() {
+        return mTabContentManager;
+    }
+
+    @VisibleForTesting
+    BrowserControlsStateProvider getBrowserControlsStateProviderForTesting() {
+        return mBrowserControlsStateProvider;
+    }
+
+    @VisibleForTesting
+    public int getCurrentTabIdForTesting() {
+        return mModel.get(LayoutTab.TAB_ID);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/components/LayoutTab.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/components/LayoutTab.java
index 1ab3bcb..b7e8494 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/components/LayoutTab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/components/LayoutTab.java
@@ -28,7 +28,7 @@
     public static final float SHADOW_ALPHA_ON_LIGHT_BG = 0.8f;
     public static final float SHADOW_ALPHA_ON_DARK_BG = 1.0f;
 
-    private static float sDpToPx;
+    public static float sDpToPx;
     private static float sPxToDp;
     // End section --------------
 
@@ -158,7 +158,10 @@
 
     // End section --------------
 
-    private static final PropertyKey[] ALL_KEYS = new PropertyKey[] {TAB_ID, IS_INCOGNITO, SCALE,
+    public static final PropertyModel.WritableFloatPropertyKey CONTENT_OFFSET =
+            new PropertyModel.WritableFloatPropertyKey();
+
+    public static final PropertyKey[] ALL_KEYS = new PropertyKey[] {TAB_ID, IS_INCOGNITO, SCALE,
             TILT_X_IN_DEGREES, TILT_Y_IN_DEGREES, TILT_X_PIVOT_OFFSET, TILT_Y_PIVOT_OFFSET, X, Y,
             RENDER_X, RENDER_Y, CLIPPED_X, CLIPPED_Y, CLIPPED_WIDTH, CLIPPED_HEIGHT, ALPHA,
             SATURATION, BORDER_ALPHA, BORDER_CLOSE_BUTTON_ALPHA, BORDER_SCALE,
@@ -167,7 +170,8 @@
             CAN_USE_LIVE_TEXTURE, SHOW_TOOLBAR, ANONYMIZE_TOOLBAR, TOOLBAR_ALPHA,
             INSET_BORDER_VERTICAL, TOOLBAR_Y_OFFSET, SIDE_BORDER_SCALE, CLOSE_BUTTON_IS_ON_RIGHT,
             BOUNDS, CLOSE_PLACEMENT, DECORATION_ALPHA, IS_TITLE_NEEDED, INIT_FROM_HOST_CALLED,
-            BACKGROUND_COLOR, TOOLBAR_BACKGROUND_COLOR, TEXT_BOX_BACKGROUND_COLOR, TEXT_BOX_ALPHA};
+            BACKGROUND_COLOR, TOOLBAR_BACKGROUND_COLOR, TEXT_BOX_BACKGROUND_COLOR, TEXT_BOX_ALPHA,
+            CONTENT_OFFSET};
 
     /**
      * Default constructor for a {@link LayoutTab}.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/StaticTabSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/StaticTabSceneLayer.java
index 296ac45..840fc9b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/StaticTabSceneLayer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/StaticTabSceneLayer.java
@@ -6,45 +6,59 @@
 
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.base.annotations.NativeMethods;
-import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
-import org.chromium.chrome.browser.compositor.LayerTitleCache;
 import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
+import org.chromium.ui.modelutil.PropertyKey;
+import org.chromium.ui.modelutil.PropertyModel;
 
 /**
  * A SceneLayer to render a static tab.
  */
 @JNINamespace("android")
 public class StaticTabSceneLayer extends SceneLayer {
+    /**
+     * ViewBinder for the StaticTabSceneLayer.
+     * @param model The model to bind.
+     * @param view The View that the model bind to.
+     * @param propertyKey The property of the view that changed. This is NULL until SceneLayer is
+     *                    able to do partial update.
+     */
+    public static void bind(
+            PropertyModel model, StaticTabSceneLayer view, PropertyKey propertyKey) {
+        view.update(model);
+    }
+
     // NOTE: If you use SceneLayer's native pointer here, the JNI generator will try to
     // downcast using reinterpret_cast<>. We keep a separate pointer to avoid it.
     private long mNativePtr;
 
     /**
-     * Update {@link StaticTabSceneLayer} with the given parameters.
-     *
-     * @param dpToPx            The ratio of dp to px.
-     * @param contentViewport   The viewport of the content.
-     * @param layerTitleCache   The LayerTitleCache.
-     * @param tabContentManager The TabContentManager.
-     * @param browserControls   The BrowserControlsStateProvider.
-     * @param layoutTab         The LayoutTab.
+     * Update {@link StaticTabSceneLayer} with the given {@link PropertyModel}.
+     * @param model         The {@link PropertyModel} to use.
      */
-    public void update(float dpToPx, LayerTitleCache layerTitleCache,
-            TabContentManager tabContentManager, BrowserControlsStateProvider browserControls,
-            LayoutTab layoutTab) {
-        if (layoutTab == null) {
+    public void update(PropertyModel model) {
+        if (model == null) {
             return;
         }
 
-        float contentOffset = browserControls != null ? browserControls.getContentOffset() : 0.f;
-        float x = layoutTab.getRenderX() * dpToPx;
-        float y = contentOffset + layoutTab.getRenderY() * dpToPx;
+        float x = model.get(LayoutTab.RENDER_X) * LayoutTab.sDpToPx;
+        float y = model.get(LayoutTab.CONTENT_OFFSET)
+                + model.get(LayoutTab.RENDER_Y) * LayoutTab.sDpToPx;
 
         StaticTabSceneLayerJni.get().updateTabLayer(mNativePtr, StaticTabSceneLayer.this,
-                tabContentManager, layoutTab.getId(), layoutTab.canUseLiveTexture(),
-                layoutTab.getBackgroundColor(), x, y, layoutTab.getStaticToViewBlend(),
-                layoutTab.getSaturation(), layoutTab.getBrightness());
+                model.get(LayoutTab.TAB_ID), model.get(LayoutTab.CAN_USE_LIVE_TEXTURE),
+                model.get(LayoutTab.BACKGROUND_COLOR), x, y,
+                model.get(LayoutTab.STATIC_TO_VIEW_BLEND), model.get(LayoutTab.SATURATION),
+                model.get(LayoutTab.BRIGHTNESS));
+    }
+
+    /**
+     * Set {@link TabContentManager}.
+     * @param tabContentManager {@link TabContentManager} to set.
+     */
+    public void setTabContentManager(TabContentManager tabContentManager) {
+        StaticTabSceneLayerJni.get().setTabContentManager(
+                mNativePtr, StaticTabSceneLayer.this, tabContentManager);
     }
 
     @Override
@@ -64,9 +78,10 @@
     @NativeMethods
     interface Natives {
         long init(StaticTabSceneLayer caller);
-        void updateTabLayer(long nativeStaticTabSceneLayer, StaticTabSceneLayer caller,
-                TabContentManager tabContentManager, int id, boolean canUseLiveLayer,
-                int backgroundColor, float x, float y, float staticToViewBlend, float saturation,
-                float brightness);
+        void updateTabLayer(long nativeStaticTabSceneLayer, StaticTabSceneLayer caller, int id,
+                boolean canUseLiveLayer, int backgroundColor, float x, float y,
+                float staticToViewBlend, float saturation, float brightness);
+        void setTabContentManager(long nativeStaticTabSceneLayer, StaticTabSceneLayer caller,
+                TabContentManager tabContentManager);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java
index f2b51d7c..0a49a2f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabListSceneLayer.java
@@ -35,11 +35,20 @@
     private TabModelSelector mTabModelSelector;
     private int[] mAdditionalIds = new int[4];
     private boolean mUseAdditionalIds;
+    private boolean mIsInitialized;
 
     public void setTabModelSelector(TabModelSelector tabModelSelector) {
         mTabModelSelector = tabModelSelector;
     }
 
+    public void init(LayerTitleCache layerTitleCache, TabContentManager tabContentManager,
+            ResourceManager resourceManager) {
+        if (mNativePtr == 0 || mIsInitialized) return;
+        TabListSceneLayerJni.get().setDependencies(mNativePtr, TabListSceneLayer.this,
+                tabContentManager, layerTitleCache, resourceManager);
+        mIsInitialized = true;
+    }
+
     /**
      * Pushes all relevant {@link LayoutTab}s from a {@link Layout} to the CC Layer tree.  This will
      * let them be rendered on the screen.  This should only be called when the Compositor has
@@ -72,11 +81,16 @@
         LayoutTab[] tabs = layout.getLayoutTabsToRender();
         int tabsCount = tabs != null ? tabs.length : 0;
 
+        if (!mIsInitialized) {
+            init(layerTitleCache, tabContentManager, resourceManager);
+        }
+
         TabListSceneLayerJni.get().beginBuildingFrame(mNativePtr, TabListSceneLayer.this);
 
+        // TODO(crbug.com/1070281): Use Supplier to get viewport and forward it to native, then
+        // updateLayer can become obsolete.
         TabListSceneLayerJni.get().updateLayer(mNativePtr, TabListSceneLayer.this, tabListBgColor,
-                viewport.left, viewport.top, viewport.width(), viewport.height(), layerTitleCache,
-                tabContentManager, resourceManager);
+                viewport.left, viewport.top, viewport.width(), viewport.height());
 
         if (backgroundResourceId != INVALID_RESOURCE_ID) {
             TabListSceneLayerJni.get().putBackgroundLayer(mNativePtr, TabListSceneLayer.this,
@@ -189,10 +203,12 @@
         long init(TabListSceneLayer caller);
         void beginBuildingFrame(long nativeTabListSceneLayer, TabListSceneLayer caller);
         void finishBuildingFrame(long nativeTabListSceneLayer, TabListSceneLayer caller);
+        void setDependencies(long nativeTabListSceneLayer, TabListSceneLayer caller,
+                TabContentManager tabContentManager, LayerTitleCache layerTitleCache,
+                ResourceManager resourceManager);
         void updateLayer(long nativeTabListSceneLayer, TabListSceneLayer caller,
                 int backgroundColor, float viewportX, float viewportY, float viewportWidth,
-                float viewportHeight, LayerTitleCache layerTitleCache,
-                TabContentManager tabContentManager, ResourceManager resourceManager);
+                float viewportHeight);
         // TODO(meiliang): Need to provide a resource that indicates the selected tab on the layer.
         void putTabLayer(long nativeTabListSceneLayer, TabListSceneLayer caller, int selectedId,
                 int[] ids, boolean useAdditionalIds, int toolbarResourceId,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java
index af569db..96fcc464 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java
@@ -41,6 +41,7 @@
 import org.chromium.chrome.browser.init.StartupTabPreloader;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.InflationObserver;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.RedirectHandlerTabHelper;
 import org.chromium.chrome.browser.tab.Tab;
@@ -102,6 +103,7 @@
     private final StartupTabPreloader mStartupTabPreloader;
     private final ReparentingTaskProvider mReparentingTaskProvider;
     private final Lazy<CustomTabIncognitoManager> mCustomTabIncognitoManager;
+    private final ProfileProvider mProfileProvider;
 
     @Nullable
     private final CustomTabsSessionToken mSession;
@@ -127,7 +129,8 @@
             CustomTabNavigationEventObserver tabNavigationEventObserver,
             CustomTabActivityTabProvider tabProvider, StartupTabPreloader startupTabPreloader,
             ReparentingTaskProvider reparentingTaskProvider,
-            Lazy<CustomTabIncognitoManager> customTabIncognitoManager) {
+            Lazy<CustomTabIncognitoManager> customTabIncognitoManager,
+            ProfileProvider profileProvider) {
         mCustomTabDelegateFactory = customTabDelegateFactory;
         mActivity = activity;
         mConnection = connection;
@@ -145,6 +148,7 @@
         mStartupTabPreloader = startupTabPreloader;
         mReparentingTaskProvider = reparentingTaskProvider;
         mCustomTabIncognitoManager = customTabIncognitoManager;
+        mProfileProvider = profileProvider;
 
         mSession = mIntentDataProvider.getSession();
         mIntent = mIntentDataProvider.getIntent();
@@ -429,8 +433,10 @@
             return mWebContentsFactory.createWebContentsWithWarmRenderer(
                     mCustomTabIncognitoManager.get().getProfile(), false);
         } else {
-            return mWebContentsFactory.createWebContentsWithWarmRenderer(
-                    mIntentDataProvider.isIncognito(), false);
+            Profile profile = mIntentDataProvider.isIncognito()
+                    ? mProfileProvider.getPrimaryOTRProfile()
+                    : mProfileProvider.getLastUsedRegularProfile();
+            return mWebContentsFactory.createWebContentsWithWarmRenderer(profile, false);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/ProfileProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/ProfileProvider.java
new file mode 100644
index 0000000..535db5d0
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/ProfileProvider.java
@@ -0,0 +1,25 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.customtabs.content;
+
+import org.chromium.chrome.browser.profiles.Profile;
+
+import javax.inject.Inject;
+
+/**
+ * Wrapper for the Profile class that allows for easier mocking.
+ */
+public class ProfileProvider {
+    @Inject
+    public ProfileProvider() {}
+
+    public Profile getLastUsedRegularProfile() {
+        return Profile.getLastUsedRegularProfile();
+    }
+
+    public Profile getPrimaryOTRProfile() {
+        return Profile.getLastUsedRegularProfile().getPrimaryOTRProfile();
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/BaseCustomTabActivityComponent.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/BaseCustomTabActivityComponent.java
index 7972d6c..eef7f609 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/BaseCustomTabActivityComponent.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/BaseCustomTabActivityComponent.java
@@ -25,6 +25,7 @@
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabFactory;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider;
 import org.chromium.chrome.browser.customtabs.content.CustomTabIntentHandler;
+import org.chromium.chrome.browser.customtabs.content.ProfileProvider;
 import org.chromium.chrome.browser.customtabs.content.TabObserverRegistrar;
 import org.chromium.chrome.browser.customtabs.features.toolbar.CustomTabToolbarCoordinator;
 import org.chromium.chrome.browser.dependency_injection.ActivityScope;
@@ -59,6 +60,7 @@
     CustomTabStatusBarColorProvider resolveCustomTabStatusBarColorProvider();
     CustomTabTaskDescriptionHelper resolveTaskDescriptionHelper();
     CustomTabToolbarCoordinator resolveToolbarCoordinator();
+    ProfileProvider resolveProfileProvider();
     TabObserverRegistrar resolveTabObserverRegistrar();
     TwaFinishHandler resolveTwaFinishHandler();
     Verifier resolveVerifier();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
index 16d0d67..c7a580f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
@@ -20,7 +20,6 @@
 import androidx.annotation.StringRes;
 import androidx.annotation.VisibleForTesting;
 
-import org.chromium.base.ActivityState;
 import org.chromium.base.Callback;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.IntentUtils;
@@ -579,8 +578,7 @@
         // When invoked directly from a browser, we want to trigger switch to tab animation.
         // If invoded from other activitiies, ex. searchActivity, we do not need to trigger the
         // animation since Android will show the animation for switching apps.
-        if (tab.getWindowAndroid().getActivityState() != ActivityState.STOPPED
-                && tab.getWindowAndroid().getActivityState() != ActivityState.DESTROYED) {
+        if (mWindowAndroid.equals(tab.getWindowAndroid())) {
             // TODO(1097292):  Do not use Activity to get TabModelSelector.
             assert tab.getWindowAndroid().getActivity().get() instanceof ChromeActivity;
 
@@ -591,13 +589,13 @@
             chromeActivity.getTabModelSelector().getCurrentModel().setIndex(
                     tabIndex, TabSelectionType.FROM_OMNIBOX);
         } else {
-            // Browser is in background, bring to to foreground and switch to the tab.
             Intent newIntent = ChromeIntentUtil.createBringTabToFrontIntent(tab.getId());
             if (newIntent != null) {
                 newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                 IntentUtils.safeStartActivity(ContextUtils.getApplicationContext(), newIntent);
             }
         }
+
         recordMetrics(position, WindowOpenDisposition.SWITCH_TO_TAB, suggestion);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/ConfirmImportSyncDataDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/ConfirmImportSyncDataDialog.java
index 6488c7be..4d7b810 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/ConfirmImportSyncDataDialog.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/ConfirmImportSyncDataDialog.java
@@ -16,6 +16,7 @@
 
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.components.browser_ui.settings.ManagedPreferencesUtils;
 import org.chromium.components.browser_ui.widget.RadioButtonWithDescription;
 
@@ -106,8 +107,10 @@
         mConfirmImportOption.setRadioButtonGroup(radioGroup);
         mKeepSeparateOption.setRadioButtonGroup(radioGroup);
 
+        SigninManager signinManager = IdentityServicesProvider.get().getSigninManager(
+                Profile.getLastUsedRegularProfile());
         // If the account is managed, disallow merging information.
-        if (IdentityServicesProvider.get().getSigninManager().getManagementDomain() != null) {
+        if (signinManager.getManagementDomain() != null) {
             mKeepSeparateOption.setChecked(true);
             mConfirmImportOption.setOnClickListener(
                     view -> ManagedPreferencesUtils.showManagedByAdministratorToast(getActivity()));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/ConfirmSyncDataStateMachine.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/ConfirmSyncDataStateMachine.java
index 6604006d..ff9c003b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/ConfirmSyncDataStateMachine.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/ConfirmSyncDataStateMachine.java
@@ -11,6 +11,7 @@
 import androidx.annotation.Nullable;
 
 import org.chromium.base.ThreadUtils;
+import org.chromium.chrome.browser.profiles.Profile;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -172,8 +173,9 @@
     }
 
     private void requestNewAccountManagementStatus() {
-        IdentityServicesProvider.get().getSigninManager().isAccountManaged(
-                mNewAccountName, this::setIsNewAccountManaged);
+        IdentityServicesProvider.get()
+                .getSigninManager(Profile.getLastUsedRegularProfile())
+                .isAccountManaged(mNewAccountName, this::setIsNewAccountManaged);
     }
 
     private void setIsNewAccountManaged(Boolean isManaged) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/ProfileDownloader.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/ProfileDownloader.java
index b16fd3e..f6014b1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/ProfileDownloader.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/ProfileDownloader.java
@@ -79,7 +79,7 @@
             if (sPendingProfileDownloads == null) {
                 sPendingProfileDownloads = new PendingProfileDownloads();
                 IdentityServicesProvider.get()
-                        .getAccountTrackerService()
+                        .getAccountTrackerService(Profile.getLastUsedRegularProfile())
                         .addSystemAccountsSeededListener(sPendingProfileDownloads);
             }
             return sPendingProfileDownloads;
@@ -125,7 +125,7 @@
         ThreadUtils.assertOnUiThread();
         Profile profile = Profile.getLastUsedRegularProfile();
         if (!IdentityServicesProvider.get()
-                        .getAccountTrackerService()
+                        .getAccountTrackerService(profile)
                         .checkAndSeedSystemAccounts()) {
             PendingProfileDownloads.get(context).pendProfileDownload(
                     profile, accountId, imageSidePixels);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SignOutDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SignOutDialogFragment.java
index 7484862..1cded3e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SignOutDialogFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SignOutDialogFragment.java
@@ -17,6 +17,7 @@
 
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.profiles.ProfileAccountManagementMetrics;
 import org.chromium.components.signin.GAIAServiceType;
 
@@ -64,7 +65,9 @@
             mGaiaServiceType = getArguments().getInt(
                     SHOW_GAIA_SERVICE_TYPE_EXTRA, mGaiaServiceType);
         }
-        String domain = IdentityServicesProvider.get().getSigninManager().getManagementDomain();
+        String domain = IdentityServicesProvider.get()
+                                .getSigninManager(Profile.getLastUsedRegularProfile())
+                                .getManagementDomain();
         if (domain != null) {
             return createDialogForManagedAccount(domain);
         }
@@ -100,7 +103,9 @@
     public void onClick(DialogInterface dialog, int which) {
         if (which == AlertDialog.BUTTON_POSITIVE) {
             SigninUtils.logEvent(ProfileAccountManagementMetrics.SIGNOUT_SIGNOUT, mGaiaServiceType);
-            if (IdentityServicesProvider.get().getSigninManager().getManagementDomain() == null) {
+            SigninManager signinManager = IdentityServicesProvider.get().getSigninManager(
+                    Profile.getLastUsedRegularProfile());
+            if (signinManager.getManagementDomain() == null) {
                 RecordHistogram.recordBooleanHistogram(
                         "Signin.UserRequestedWipeDataOnSignout", mWipeUserData.isChecked());
             }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragment.java
index e6ffe9922..2bab8a7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragment.java
@@ -140,7 +140,9 @@
             callback.run();
             return;
         }
-        IdentityServicesProvider.get().getSigninManager().signIn(
+        SigninManager signinManager = IdentityServicesProvider.get().getSigninManager(
+                Profile.getLastUsedRegularProfile());
+        signinManager.signIn(
                 mSigninAccessPoint, account, new SigninManager.SignInCallback() {
                     @Override
                     public void onSignInComplete() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragmentBase.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragmentBase.java
index b28e514..d9bc9ea 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragmentBase.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragmentBase.java
@@ -404,7 +404,8 @@
         // as this is needed for the previous account check.
         final long seedingStartTime = SystemClock.elapsedRealtime();
         final AccountTrackerService accountTrackerService =
-                IdentityServicesProvider.get().getAccountTrackerService();
+                IdentityServicesProvider.get().getAccountTrackerService(
+                        Profile.getLastUsedRegularProfile());
         if (accountTrackerService.checkAndSeedSystemAccounts()) {
             recordAccountTrackerServiceSeedingTime(seedingStartTime);
             runStateMachineAndSignin(settingsClicked);
@@ -655,8 +656,9 @@
                 && mGooglePlayServicesUpdateErrorHandler.isShowing()) {
             return;
         }
-        boolean cancelable =
-                !IdentityServicesProvider.get().getSigninManager().isForceSigninEnabled();
+        boolean cancelable = !IdentityServicesProvider.get()
+                                      .getSigninManager(Profile.getLastUsedRegularProfile())
+                                      .isForceSigninEnabled();
         mGooglePlayServicesUpdateErrorHandler =
                 new UserRecoverableErrorHandler.ModalDialog(getActivity(), cancelable);
         mGooglePlayServicesUpdateErrorHandler.handleError(getActivity(), gmsErrorCode);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
index 4cb04dba..6e6028a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java
@@ -18,6 +18,7 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
 import org.chromium.base.task.AsyncTask;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.signin.SigninManager.SignInCallback;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
 import org.chromium.components.signin.AccountManagerFacadeProvider;
@@ -102,8 +103,9 @@
 
     private SigninHelper() {
         mProfileSyncService = ProfileSyncService.get();
-        mSigninManager = IdentityServicesProvider.get().getSigninManager();
-        mAccountTrackerService = IdentityServicesProvider.get().getAccountTrackerService();
+        Profile profile = Profile.getLastUsedRegularProfile();
+        mSigninManager = IdentityServicesProvider.get().getSigninManager(profile);
+        mAccountTrackerService = IdentityServicesProvider.get().getAccountTrackerService(profile);
         mPrefsManager = SigninPreferencesManager.getInstance();
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoUtil.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoUtil.java
index da86770a..14f5bd2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoUtil.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninPromoUtil.java
@@ -18,6 +18,7 @@
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.components.signin.AccountManagerFacadeProvider;
 import org.chromium.components.signin.AccountUtils;
+import org.chromium.components.signin.identitymanager.IdentityManager;
 import org.chromium.components.signin.metrics.SigninAccessPoint;
 import org.chromium.components.user_prefs.UserPrefs;
 import org.chromium.ui.base.WindowAndroid;
@@ -46,9 +47,10 @@
         List<String> accountNames = AccountUtils.toAccountNames(
                 AccountManagerFacadeProvider.getInstance().tryGetGoogleAccounts());
         Supplier<Set<String>> accountNamesSupplier = () -> new ArraySet<>(accountNames);
+        IdentityManager identityManager = IdentityServicesProvider.get().getIdentityManager(
+                Profile.getLastUsedRegularProfile());
         if (!shouldLaunchSigninPromo(preferencesManager, currentMajorVersion,
-                    IdentityServicesProvider.get().getIdentityManager().hasPrimaryAccount(),
-                    wasSignedIn, accountNamesSupplier)) {
+                    identityManager.hasPrimaryAccount(), wasSignedIn, accountNamesSupplier)) {
             return false;
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninUtils.java
index a6dc6e6..e9e0bc1d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninUtils.java
@@ -18,6 +18,7 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.NativeMethods;
 import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.signin.account_picker.AccountPickerBottomSheetCoordinator;
 import org.chromium.chrome.browser.signin.account_picker.AccountPickerDelegate;
 import org.chromium.chrome.browser.sync.settings.AccountManagementFragment;
@@ -75,7 +76,9 @@
     private static void openAccountPickerBottomSheet(
             WindowAndroid windowAndroid, String continueUrl) {
         ThreadUtils.assertOnUiThread();
-        if (IdentityServicesProvider.get().getSigninManager().isSignInAllowed()) {
+        SigninManager signinManager = IdentityServicesProvider.get().getSigninManager(
+                Profile.getLastUsedRegularProfile());
+        if (signinManager.isSignInAllowed()) {
             ChromeActivity activity = (ChromeActivity) windowAndroid.getActivity().get();
             AccountPickerBottomSheetCoordinator coordinator =
                     new AccountPickerBottomSheetCoordinator(activity,
@@ -91,7 +94,8 @@
      */
     public static boolean startSigninActivityIfAllowed(
             Context context, @SigninAccessPoint int accessPoint) {
-        SigninManager signinManager = IdentityServicesProvider.get().getSigninManager();
+        SigninManager signinManager = IdentityServicesProvider.get().getSigninManager(
+                Profile.getLastUsedRegularProfile());
         if (signinManager.isSignInAllowed()) {
             SigninActivityLauncher.get().launchActivity(context, accessPoint);
             return true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegate.java
index dac4fc40..970a460c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegate.java
@@ -11,6 +11,7 @@
 
 import org.chromium.base.task.PostTask;
 import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.signin.IdentityServicesProvider;
 import org.chromium.chrome.browser.signin.SigninManager;
 import org.chromium.chrome.browser.signin.SigninUtils;
@@ -31,12 +32,15 @@
     private final ChromeActivity mChromeActivity;
     private final Tab mTab;
     private final String mContinueUrl;
+    private final SigninManager mSigninManager;
 
     public AccountPickerDelegate(ChromeActivity chromeActivity, String continueUrl) {
         mChromeActivity = chromeActivity;
         // TODO(https://crbug.com/1095554): Check if website redirects after sign-in
         mTab = mChromeActivity.getActivityTab();
         mContinueUrl = continueUrl;
+        mSigninManager = IdentityServicesProvider.get().getSigninManager(
+                Profile.getLastUsedRegularProfile());
     }
     /**
      * Signs the user into the account of the given accountName.
@@ -44,7 +48,7 @@
     public void signIn(String accountName) {
         Account account = AccountUtils.findAccountByName(
                 AccountManagerFacadeProvider.getInstance().tryGetGoogleAccounts(), accountName);
-        IdentityServicesProvider.get().getSigninManager().signIn(
+        mSigninManager.signIn(
                 SigninAccessPoint.WEB_SIGNIN, account, new SigninManager.SignInCallback() {
                     @Override
                     public void onSignInComplete() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java
index 782cc37..bc72e28 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java
@@ -36,6 +36,7 @@
 import org.chromium.chrome.browser.accessibility_tab_switcher.OverviewListLayout;
 import org.chromium.chrome.browser.compositor.animation.CompositorAnimationHandler;
 import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
+import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
 import org.chromium.chrome.browser.compositor.layouts.eventfilter.EdgeSwipeHandler;
 import org.chromium.chrome.browser.compositor.layouts.eventfilter.ScrollDirection;
 import org.chromium.chrome.browser.compositor.layouts.phone.StackLayout;
@@ -152,6 +153,8 @@
         }
         mTabModelSelector.selectModel(incognitoSelected);
         LayoutManagerHost layoutManagerHost = new MockLayoutHost(context);
+        TabContentManager tabContentManager = new TabContentManager(context, null, false, null);
+        tabContentManager.initWithNative();
 
         // Build a fake content container
         FrameLayout parentContainer = new FrameLayout(context);
@@ -161,7 +164,7 @@
         mManagerPhone = new LayoutManagerChromePhone(layoutManagerHost, null);
         mManager = mManagerPhone;
         CompositorAnimationHandler.setTestingMode(true);
-        mManager.init(mTabModelSelector, null, null, container, null, null, null);
+        mManager.init(mTabModelSelector, null, tabContentManager, container, null, null, null);
         initializeMotionEvent();
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/SwitchToTabTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/SwitchToTabTest.java
index 5398a26..c87a762 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/SwitchToTabTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/SwitchToTabTest.java
@@ -8,6 +8,7 @@
 import android.app.Instrumentation;
 import android.app.Instrumentation.ActivityMonitor;
 import android.content.Intent;
+import android.os.Build;
 import android.support.test.InstrumentationRegistry;
 import android.util.Pair;
 import android.view.ViewGroup;
@@ -23,9 +24,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import org.chromium.base.ActivityState;
-import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisableIf;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
@@ -42,7 +42,6 @@
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.content_public.browser.test.util.Criteria;
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
-import org.chromium.content_public.browser.test.util.CriteriaNotSatisfiedException;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.content_public.browser.test.util.TestTouchUtils;
 import org.chromium.net.test.EmbeddedTestServer;
@@ -95,47 +94,30 @@
      *
      * @param activity The Activity which url_bar is in.
      * @param locationBarLayout The layout which omnibox suggestions will show in.
-     * @param input The text will be typed into url_bar.
-     * @param expectedMatchUrl The expected url to visit after clicking tab switch button.
+     * @param text The text will be typed into url_bar.
      */
-    private void typeAndClickMatchingTabMatchSuggestion(Activity activity,
-            LocationBarLayout locationBarLayout, String input, String expectedMatchUrl)
-            throws InterruptedException {
+    private void typeAndWaitForTabMatchSuggestions(Activity activity,
+            LocationBarLayout locationBarLayout, String input) throws InterruptedException {
         typeInOmnibox(activity, input);
 
         OmniboxTestUtils.waitForOmniboxSuggestions(locationBarLayout);
         // waitForOmniboxSuggestions only wait until one suggestion shows up, we need to wait util
         // autocomplete return more suggestions.
         CriteriaHelper.pollUiThread(() -> {
-            Pair<Integer, OmniboxSuggestion> matchSuggestion =
-                    findFirstTabMatchOmniboxSuggestion(locationBarLayout);
-
-            Criteria.checkThat(matchSuggestion.first, Matchers.not(INVALID_INDEX));
-            Criteria.checkThat(
-                    matchSuggestion.second.getUrl().getSpec(), Matchers.is(expectedMatchUrl));
-
-            OmniboxSuggestionsDropdown suggestionsDropdown =
-                    AutocompleteCoordinatorTestUtils.getSuggestionsDropdown(
-                            locationBarLayout.getAutocompleteCoordinator());
-            try {
-                clickSuggestionActionAt(suggestionsDropdown, matchSuggestion.first);
-            } catch (InterruptedException e) {
-                throw new CriteriaNotSatisfiedException(e);
-            }
+            Criteria.checkThat(findFirstTabMatchOmniboxSuggestion(locationBarLayout).first,
+                    Matchers.not(INVALID_INDEX));
         });
     }
 
     /**
      * Find the first switch to tab suggestion in the omnibox suggestion list, and return the
-     * suggestion and its index. This method needs to run on the UI thread.
+     * suggestion and its index.
      *
      * @param locationBarLayout The layout which omnibox suggestions will show in.
-     * @return The first switch to tab suggestion's index, and the suggesstion.
+     * @return The the first switch to tab suggestion's index, and the suggesstion.
      */
     private Pair<Integer, OmniboxSuggestion> findFirstTabMatchOmniboxSuggestion(
             LocationBarLayout locationBarLayout) {
-        ThreadUtils.assertOnUiThread();
-
         OmniboxSuggestionsDropdown suggestionsDropdown =
                 AutocompleteCoordinatorTestUtils.getSuggestionsDropdown(
                         locationBarLayout.getAutocompleteCoordinator());
@@ -189,6 +171,9 @@
 
     @Test
     @MediumTest
+    @DisableIf.Build(message = "https://crbug.com/1101433",
+            sdk_is_greater_than = Build.VERSION_CODES.LOLLIPOP_MR1,
+            sdk_is_less_than = Build.VERSION_CODES.N)
     @EnableFeatures("OmniboxTabSwitchSuggestions")
     public void
     testSwitchToTabSuggestion() throws InterruptedException {
@@ -204,8 +189,20 @@
 
         LocationBarLayout locationBarLayout =
                 (LocationBarLayout) mActivityTestRule.getActivity().findViewById(R.id.location_bar);
-        typeAndClickMatchingTabMatchSuggestion(
-                mActivityTestRule.getActivity(), locationBarLayout, "about", testHttpsUrl1);
+        typeAndWaitForTabMatchSuggestions(
+                mActivityTestRule.getActivity(), locationBarLayout, "about");
+
+        Pair<Integer, OmniboxSuggestion> matchSuggestion =
+                findFirstTabMatchOmniboxSuggestion(locationBarLayout);
+
+        Assert.assertNotEquals(INVALID_INDEX, (int) matchSuggestion.first);
+        Assert.assertNotNull("No Switch to Tab suggestion returned.", matchSuggestion.second);
+        Assert.assertEquals(matchSuggestion.second.getUrl().getSpec(), testHttpsUrl1);
+
+        OmniboxSuggestionsDropdown suggestionsDropdown =
+                AutocompleteCoordinatorTestUtils.getSuggestionsDropdown(
+                        locationBarLayout.getAutocompleteCoordinator());
+        clickSuggestionActionAt(suggestionsDropdown, (int) matchSuggestion.first);
 
         CriteriaHelper.pollUiThread(() -> {
             Tab tab = mActivityTestRule.getActivity().getActivityTab();
@@ -238,18 +235,17 @@
         mActivityTestRule.typeInOmnibox("about", false);
         OmniboxTestUtils.waitForOmniboxSuggestions(locationBarLayout);
 
-        CriteriaHelper.pollUiThread(() -> {
-            Pair<Integer, OmniboxSuggestion> matchSuggestion =
-                    findFirstTabMatchOmniboxSuggestion(locationBarLayout);
+        Pair<Integer, OmniboxSuggestion> matchSuggestion =
+                findFirstTabMatchOmniboxSuggestion(locationBarLayout);
 
-            Criteria.checkThat(matchSuggestion.first, Matchers.is(INVALID_INDEX));
-        });
+        Assert.assertNull(
+                "Should no Switch to Incognito Tab from normal tab.", matchSuggestion.second);
     }
 
     @Test
     @MediumTest
     @EnableFeatures("OmniboxTabSwitchSuggestions")
-    public void testSwitchToTabInSearchActivity() throws InterruptedException {
+    public void testSwitchToTabInSearchActiviy() throws InterruptedException {
         mTestServer = EmbeddedTestServer.createAndStartHTTPSServer(
                 InstrumentationRegistry.getInstrumentation().getContext(),
                 ServerCertificate.CERT_OK);
@@ -261,26 +257,30 @@
         mActivityTestRule.loadUrlInNewTab(testHttpsUrl3);
 
         final SearchActivity searchActivity = startSearchActivity();
-        CriteriaHelper.pollUiThread(() -> {
-            Tab tab = mActivityTestRule.getActivity().getActivityTab();
-            Criteria.checkThat(tab, Matchers.notNullValue());
-            // Make sure chrome fully in background.
-            Criteria.checkThat(tab.getWindowAndroid().getActivityState(),
-                    Matchers.isOneOf(ActivityState.STOPPED, ActivityState.DESTROYED));
-        });
 
         final LocationBarLayout locationBarLayout =
                 (LocationBarLayout) searchActivity.findViewById(R.id.search_location_bar);
-        typeAndClickMatchingTabMatchSuggestion(
-                searchActivity, locationBarLayout, "about", testHttpsUrl1);
+        typeAndWaitForTabMatchSuggestions(searchActivity, locationBarLayout, "about");
+
+        Pair<Integer, OmniboxSuggestion> matchSuggestion =
+                findFirstTabMatchOmniboxSuggestion(locationBarLayout);
+
+        Assert.assertNotEquals(INVALID_INDEX, (int) matchSuggestion.first);
+        Assert.assertNotNull("No Switch to Tab suggestion returned.", matchSuggestion.second);
+        Assert.assertEquals(matchSuggestion.second.getUrl().getSpec(), testHttpsUrl1);
+
+        OmniboxSuggestionsDropdown suggestionsDropdown =
+                AutocompleteCoordinatorTestUtils.getSuggestionsDropdown(
+                        locationBarLayout.getAutocompleteCoordinator());
+        clickSuggestionActionAt(suggestionsDropdown, (int) matchSuggestion.first);
 
         CriteriaHelper.pollUiThread(() -> {
             Tab tab = mActivityTestRule.getActivity().getActivityTab();
-            Criteria.checkThat(tab, Matchers.notNullValue());
-            Criteria.checkThat(tab.getUrlString(), Matchers.is(testHttpsUrl1));
-            // Make sure tab is loaded and in foreground.
-            Criteria.checkThat(
-                    tab.getWindowAndroid().getActivityState(), Matchers.is(ActivityState.RESUMED));
+            if (tab == null) return false;
+            // Make sure tab is in either upload page or result page. cannot only verify one of
+            // them since on fast device tab jump to result page really quick but on slow device
+            // may stay on upload page for a really long time.
+            return tab.getUrlString().equals(testHttpsUrl1);
         });
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/profiles/ProfileTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/profiles/ProfileTest.java
index 05f4a631..3ca00b22 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/profiles/ProfileTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/profiles/ProfileTest.java
@@ -58,6 +58,7 @@
 
             Profile incognitoProfile1 = mRegularProfile.getPrimaryOTRProfile();
             Assert.assertTrue(incognitoProfile1.isOffTheRecord());
+            Assert.assertTrue(incognitoProfile1.isPrimaryOTRProfile());
             Assert.assertTrue(incognitoProfile1.isNativeInitialized());
             Assert.assertTrue(mRegularProfile.hasPrimaryOTRProfile());
 
@@ -80,6 +81,7 @@
             Profile nonPrimaryOtrProfile1 = mRegularProfile.getOffTheRecordProfile(profileID);
 
             Assert.assertTrue(nonPrimaryOtrProfile1.isOffTheRecord());
+            Assert.assertFalse(nonPrimaryOtrProfile1.isPrimaryOTRProfile());
             Assert.assertTrue(nonPrimaryOtrProfile1.isNativeInitialized());
             Assert.assertTrue(mRegularProfile.hasOffTheRecordProfile(profileID));
             Assert.assertFalse(mRegularProfile.hasPrimaryOTRProfile());
@@ -108,10 +110,12 @@
             Profile nonPrimaryOtrProfile2 = mRegularProfile.getOffTheRecordProfile(profileID2);
 
             Assert.assertTrue(nonPrimaryOtrProfile1.isOffTheRecord());
+            Assert.assertFalse(nonPrimaryOtrProfile1.isPrimaryOTRProfile());
             Assert.assertTrue(nonPrimaryOtrProfile1.isNativeInitialized());
             Assert.assertTrue(mRegularProfile.hasOffTheRecordProfile(profileID1));
 
             Assert.assertTrue(nonPrimaryOtrProfile2.isOffTheRecord());
+            Assert.assertFalse(nonPrimaryOtrProfile2.isPrimaryOTRProfile());
             Assert.assertTrue(nonPrimaryOtrProfile2.isNativeInitialized());
             Assert.assertTrue(mRegularProfile.hasOffTheRecordProfile(profileID2));
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/ConfirmSyncDataIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/ConfirmSyncDataIntegrationTest.java
index 651887f..39c5ea9b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/ConfirmSyncDataIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/ConfirmSyncDataIntegrationTest.java
@@ -35,6 +35,7 @@
 import org.chromium.base.test.util.JniMocker;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.ui.test.util.DummyUiActivityTestCase;
@@ -71,6 +72,9 @@
     @Mock
     private ConfirmSyncDataStateMachine.Listener mListenerMock;
 
+    @Mock
+    private Profile mProfile;
+
     private ConfirmSyncDataStateMachineDelegate mDelegate;
 
     @Before
@@ -78,7 +82,8 @@
         initMocks(this);
         mocker.mock(SigninManagerJni.TEST_HOOKS, mSigninManagerNativeMock);
         IdentityServicesProvider.setInstanceForTests(mIdentityServicesProviderMock);
-        when(IdentityServicesProvider.get().getSigninManager()).thenReturn(mSigninManagerMock);
+        Profile.setLastUsedProfileForTesting(mProfile);
+        when(IdentityServicesProvider.get().getSigninManager(any())).thenReturn(mSigninManagerMock);
         mDelegate =
                 new ConfirmSyncDataStateMachineDelegate(getActivity().getSupportFragmentManager());
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/IdentityManagerIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/IdentityManagerIntegrationTest.java
index ab89d09..1b994f18 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/IdentityManagerIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/IdentityManagerIntegrationTest.java
@@ -14,6 +14,7 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.test.BaseJUnit4ClassRunner;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule;
 import org.chromium.components.signin.AccountManagerFacadeProvider;
 import org.chromium.components.signin.ChromeSigninController;
@@ -58,9 +59,10 @@
 
         mAccountManagerTestRule.waitForSeeding();
         TestThreadUtils.runOnUiThreadBlocking(() -> {
+            Profile profile = Profile.getLastUsedRegularProfile();
             mIdentityMutator =
-                    IdentityServicesProvider.get().getSigninManager().getIdentityMutator();
-            mIdentityManager = IdentityServicesProvider.get().getIdentityManager();
+                    IdentityServicesProvider.get().getSigninManager(profile).getIdentityMutator();
+            mIdentityManager = IdentityServicesProvider.get().getIdentityManager(profile);
         });
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SignOutDialogRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SignOutDialogRenderTest.java
index ec5e012e..05bc9c9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SignOutDialogRenderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SignOutDialogRenderTest.java
@@ -8,6 +8,7 @@
 import static androidx.test.espresso.action.ViewActions.pressBack;
 import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 import static org.mockito.MockitoAnnotations.initMocks;
@@ -28,6 +29,7 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.JniMocker;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.ChromeRenderTestRule;
 import org.chromium.components.signin.GAIAServiceType;
@@ -58,12 +60,16 @@
     @Mock
     private SigninManager mSigninManagerMock;
 
+    @Mock
+    private Profile mProfile;
+
     @Before
     public void setUp() {
         initMocks(this);
         mocker.mock(SigninUtilsJni.TEST_HOOKS, mSigninUtilsNativeMock);
+        Profile.setLastUsedProfileForTesting(mProfile);
         IdentityServicesProvider.setInstanceForTests(mock(IdentityServicesProvider.class));
-        when(IdentityServicesProvider.get().getSigninManager()).thenReturn(mSigninManagerMock);
+        when(IdentityServicesProvider.get().getSigninManager(any())).thenReturn(mSigninManagerMock);
     }
 
     @After
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFragmentTest.java
index 9d5f529..910103c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFragmentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFragmentTest.java
@@ -39,6 +39,7 @@
 import org.chromium.base.test.util.Matchers;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
 import org.chromium.chrome.browser.sync.SyncTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -159,7 +160,7 @@
         // Wait for sign in process to finish.
         CriteriaHelper.pollUiThread(() -> {
             return IdentityServicesProvider.get()
-                    .getSigninManager()
+                    .getSigninManager(Profile.getLastUsedRegularProfile())
                     .getIdentityManager()
                     .hasPrimaryAccount();
         }, CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL, CriteriaHelper.DEFAULT_POLLING_INTERVAL);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninSignoutIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninSignoutIntegrationTest.java
index 6aacaba7..609e02bb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninSignoutIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninSignoutIntegrationTest.java
@@ -94,8 +94,10 @@
         initMocks(this);
         mocker.mock(SigninUtilsJni.TEST_HOOKS, mSigninUtilsNativeMock);
         mActivityTestRule.startMainActivityOnBlankPage();
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> { mSigninManager = IdentityServicesProvider.get().getSigninManager(); });
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            mSigninManager = IdentityServicesProvider.get().getSigninManager(
+                    Profile.getLastUsedRegularProfile());
+        });
         mSigninManager.addSignInStateObserver(mSignInStateObserverMock);
     }
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/layouts/CompositorModelChangeProcessorUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/layouts/CompositorModelChangeProcessorUnitTest.java
index d50baf4..5b33562 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/layouts/CompositorModelChangeProcessorUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/layouts/CompositorModelChangeProcessorUnitTest.java
@@ -37,7 +37,7 @@
     @Mock
     private PropertyModelChangeProcessor.ViewBinder mViewBinder;
     @Mock
-    private LayoutManagerHost mLayoutManagerHost;
+    private LayoutUpdateHost mLayoutUpdateHost;
 
     private CompositorModelChangeProcessor.FrameRequestSupplier mFrameSupplier;
     private CompositorModelChangeProcessor mCompositorMCP;
@@ -48,8 +48,7 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
-        mFrameSupplier =
-                new CompositorModelChangeProcessor.FrameRequestSupplier(mLayoutManagerHost);
+        mFrameSupplier = new CompositorModelChangeProcessor.FrameRequestSupplier(mLayoutUpdateHost);
         mModel = new PropertyModel(PROPERTY_CHANGED);
 
         mCompositorMCP = CompositorModelChangeProcessor.create(
@@ -59,7 +58,7 @@
     @Test
     public void testBindAndRequestFrame() {
         mModel.set(PROPERTY_CHANGED, mPropertyChangedValue.getAndSet(!mPropertyChangedValue.get()));
-        verify(mLayoutManagerHost).requestRender();
+        verify(mLayoutUpdateHost).requestUpdate();
 
         mFrameSupplier.set(System.currentTimeMillis());
         verify(mViewBinder).bind(eq(mModel), eq(mView), eq(null));
@@ -70,14 +69,14 @@
         mFrameSupplier.set(System.currentTimeMillis());
 
         verify(mViewBinder).bind(eq(mModel), eq(mView), eq(null));
-        verify(mLayoutManagerHost, never()).requestRender();
+        verify(mLayoutUpdateHost, never()).requestUpdate();
     }
 
     @Test
     public void testRequestFrameAndNoBindOnPropertyChanged() {
         mModel.set(PROPERTY_CHANGED, mPropertyChangedValue.getAndSet(!mPropertyChangedValue.get()));
 
-        verify(mLayoutManagerHost).requestRender();
+        verify(mLayoutUpdateHost).requestUpdate();
         verify(mViewBinder, never()).bind(any(), any(), any());
     }
 }
\ No newline at end of file
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/layouts/StaticLayoutUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/layouts/StaticLayoutUnitTest.java
new file mode 100644
index 0000000..f8ed861
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/layouts/StaticLayoutUnitTest.java
@@ -0,0 +1,342 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.compositor.layouts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.util.DisplayMetrics;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.UserDataHost;
+import org.chromium.base.supplier.ObservableSupplierImpl;
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
+import org.chromium.chrome.browser.compositor.animation.CompositorAnimationHandler;
+import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
+import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
+import org.chromium.chrome.browser.compositor.scene_layer.StaticTabSceneLayer;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tab.TabObserver;
+import org.chromium.chrome.browser.tab.TabSelectionType;
+import org.chromium.chrome.browser.tab.TabThemeColorHelper;
+import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.chrome.browser.tabmodel.TabModelObserver;
+import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.content_public.browser.WebContents;
+import org.chromium.ui.modelutil.PropertyModel;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+
+/**
+ * Unit tests for {@link StaticLayout}.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class StaticLayoutUnitTest {
+    private static final int TAB1_ID = 456;
+    private static final int TAB2_ID = 789;
+    private static final int POSITION1 = 0;
+    private static final int POSITION2 = 1;
+    private static final String TAB1_URL = "https://tab1.com";
+    private static final String TAB2_URL = "https://tab2.com";
+
+    private static final int BACKGROUND_COLOR = Color.WHITE;
+    private static final int TOOLBAR_BACKGROUND_COLOR = Color.BLUE;
+    private static final int TEXT_BOX_BACKGROUND_COLOR = Color.BLACK;
+    private static final float TEXT_BOX_ALPHA = 1.0f;
+    private static final int WIDTH = 9;
+    private static final int HEIGHT = 16;
+
+    @Mock
+    private Context mContext;
+    @Mock
+    private Resources mResource;
+    @Mock
+    private DisplayMetrics mDisplayMetrics;
+    @Mock
+    private LayoutUpdateHost mUpdateHost;
+    @Mock
+    private LayoutRenderHost mRenderHost;
+    @Mock
+    private LayoutManagerHost mViewHost;
+    @Mock
+    private CompositorModelChangeProcessor.FrameRequestSupplier mRequestSupplier;
+    @Mock
+    StaticTabSceneLayer mStaticTabSceneLayer;
+
+    @Mock
+    private TabContentManager mTabContentManager;
+
+    @Mock
+    private TabModelSelector mTabModelSelector;
+    @Mock
+    private TabModel mTabModel;
+    @Captor
+    private ArgumentCaptor<TabModelObserver> mTabModelObserverCaptor;
+
+    @Mock
+    private BrowserControlsStateProvider mBrowserControlsStateProvider;
+    @Captor
+    private ArgumentCaptor<BrowserControlsStateProvider.Observer>
+            mBrowserControlsStateProviderObserverCaptor;
+
+    private UserDataHost mUserDataHost = new UserDataHost();
+    @Mock
+    private TabThemeColorHelper mTabThemeColorHelper;
+
+    private Tab mTab1;
+    private Tab mTab2;
+    @Captor
+    private ArgumentCaptor<TabObserver> mTabObserverCaptor;
+
+    private CompositorAnimationHandler mCompositorAnimationHandler;
+    private ObservableSupplierImpl<TabModelSelector> mTabModelSelectoSupplier =
+            new ObservableSupplierImpl<>();
+    private ObservableSupplierImpl<TabContentManager> mTabContentManagerSupplier =
+            new ObservableSupplierImpl<>();
+    private ObservableSupplierImpl<BrowserControlsStateProvider>
+            mBrowserControlsStateProviderSupplier = new ObservableSupplierImpl<>();
+
+    private StaticLayout mStaticLayout;
+    private PropertyModel mModel;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mCompositorAnimationHandler = new CompositorAnimationHandler(mUpdateHost);
+        CompositorAnimationHandler.setTestingMode(true);
+
+        mTab1 = prepareTab(TAB1_ID, TAB1_URL);
+        mTab2 = prepareTab(TAB2_ID, TAB2_URL);
+
+        doReturn(mResource).when(mContext).getResources();
+        doReturn(mDisplayMetrics).when(mResource).getDisplayMetrics();
+        mDisplayMetrics.density = 1;
+
+        doReturn(mTabModel).when(mTabModel).getComprehensiveModel();
+        doReturn(2).when(mTabModel).getCount();
+        doReturn(mTab1).when(mTabModel).getTabAt(0);
+        doReturn(mTab2).when(mTabModel).getTabAt(1);
+        doNothing().when(mTab1).addObserver(mTabObserverCaptor.capture());
+        doNothing().when(mTab2).addObserver(mTabObserverCaptor.capture());
+        doReturn(POSITION1).when(mTabModel).indexOf(mTab1);
+        doReturn(POSITION2).when(mTabModel).indexOf(mTab2);
+        doReturn(POSITION1).when(mTabModel).index();
+
+        doReturn(mTab1).when(mTabModelSelector).getCurrentTab();
+        doReturn(Arrays.asList(mTabModel)).when(mTabModelSelector).getModels();
+        doNothing().when(mTabModel).addObserver(mTabModelObserverCaptor.capture());
+
+        doNothing().when(mRequestSupplier).request();
+        doNothing()
+                .when(mBrowserControlsStateProvider)
+                .addObserver(mBrowserControlsStateProviderObserverCaptor.capture());
+        doNothing().when(mTabContentManager).updateVisibleIds(any(), anyInt());
+        doReturn(WIDTH).when(mViewHost).getWidth();
+        doReturn(HEIGHT).when(mViewHost).getHeight();
+        doReturn(mCompositorAnimationHandler).when(mUpdateHost).getAnimationHandler();
+
+        mStaticLayout = new StaticLayout(mContext, mUpdateHost, mRenderHost, mViewHost,
+                mRequestSupplier, mTabModelSelectoSupplier, mTabContentManagerSupplier,
+                mBrowserControlsStateProviderSupplier);
+        mModel = mStaticLayout.getModelForTesting();
+
+        mStaticLayout.setSceneLayerForTesting(mStaticTabSceneLayer);
+        mStaticLayout.onFinishNativeInitialization();
+
+        mUserDataHost.setUserData(TabThemeColorHelper.class, mTabThemeColorHelper);
+        doReturn(BACKGROUND_COLOR).when(mTabThemeColorHelper).getBackgroundColor();
+        doReturn(TOOLBAR_BACKGROUND_COLOR).when(mTabThemeColorHelper).getColor();
+        mStaticLayout.setTextBoxBackgroundColorForTesting(TEXT_BOX_BACKGROUND_COLOR);
+        mStaticLayout.setToolbarTextBoxAlphaForTesting(TEXT_BOX_ALPHA);
+
+        initAndAssertAllDependencies();
+
+        mStaticLayout.show(System.currentTimeMillis(), false);
+    }
+
+    @After
+    public void tearDown() {
+        CompositorAnimationHandler.setTestingMode(false);
+        mUserDataHost.removeUserData(TabThemeColorHelper.class);
+        mStaticLayout.setSceneLayerForTesting(null);
+        mStaticLayout.setTextBoxBackgroundColorForTesting(null);
+        mStaticLayout.setToolbarTextBoxAlphaForTesting(null);
+        mStaticLayout.destroy();
+    }
+
+    private void initAndAssertAllDependencies() {
+        assertNull(mStaticLayout.getTabModelSelectorForTesting());
+        mTabModelSelectoSupplier.set(mTabModelSelector);
+        assertEquals(mTabModelSelector, mStaticLayout.getTabModelSelectorForTesting());
+
+        assertNull(mStaticLayout.getTabContentManagerForTesting());
+        mTabContentManagerSupplier.set(mTabContentManager);
+        assertEquals(mTabContentManager, mStaticLayout.getTabContentManagerForTesting());
+
+        assertNull(mStaticLayout.getBrowserControlsStateProviderForTesting());
+        mBrowserControlsStateProviderSupplier.set(mBrowserControlsStateProvider);
+        assertEquals(mBrowserControlsStateProvider,
+                mStaticLayout.getBrowserControlsStateProviderForTesting());
+    }
+
+    private Tab prepareTab(int id, String url) {
+        Tab tab = mock(Tab.class);
+        doReturn(id).when(tab).getId();
+        doReturn(false).when(tab).isIncognito();
+        doReturn(url).when(tab).getUrlString();
+        doReturn(false).when(tab).isNativePage();
+        doReturn(mock(WebContents.class)).when(tab).getWebContents();
+        doReturn(true).when(tab).isInitialized();
+        when(tab.getUserDataHost()).thenReturn(mUserDataHost);
+        return tab;
+    }
+
+    private TabModelObserver getTabModelSelectorTabModelObserverFromCaptor() {
+        // Index 1 captured the TabModelSelectorTabObserver.
+        return mTabModelObserverCaptor.getAllValues().get(0);
+    }
+
+    @Test
+    public void testBrowserControlsContentOffsetChanged() {
+        final int offset = 10;
+        doReturn(offset).when(mBrowserControlsStateProvider).getContentOffset();
+        mBrowserControlsStateProviderObserverCaptor.getValue().onControlsOffsetChanged(
+                offset, offset, 0, 0, true);
+        assertEquals(offset, (int) mModel.get(LayoutTab.CONTENT_OFFSET));
+    }
+
+    @Test
+    public void testTabSelection() {
+        assertNotEquals(mTab2.getId(), mModel.get(LayoutTab.TAB_ID));
+
+        getTabModelSelectorTabModelObserverFromCaptor().didSelectTab(
+                mTab2, TabSelectionType.FROM_USER, TAB1_ID);
+
+        assertEquals(mTab2.getId(), mModel.get(LayoutTab.TAB_ID));
+        assertFalse(mModel.get(LayoutTab.SHOULD_STALL));
+        assertEquals(0.0f, mModel.get(LayoutTab.STATIC_TO_VIEW_BLEND), 0);
+        assertEquals(1.0f, mModel.get(LayoutTab.SATURATION), 0);
+    }
+
+    @Test
+    public void testTabSelection_Stall() {
+        doReturn(true).when(mTab2).isFrozen();
+
+        getTabModelSelectorTabModelObserverFromCaptor().didSelectTab(
+                mTab2, TabSelectionType.FROM_USER, TAB1_ID);
+
+        assertTrue(mModel.get(LayoutTab.SHOULD_STALL));
+        assertEquals(1.0f, mModel.get(LayoutTab.STATIC_TO_VIEW_BLEND), 0);
+        assertEquals(0.0f, mModel.get(LayoutTab.SATURATION), 0);
+    }
+
+    @Test
+    public void testTabSelection_SameTab() {
+        getTabModelSelectorTabModelObserverFromCaptor().didSelectTab(
+                mTab1, TabSelectionType.FROM_USER, TAB1_ID);
+
+        assertFalse(mModel.get(LayoutTab.SHOULD_STALL));
+        assertEquals(0.0f, mModel.get(LayoutTab.STATIC_TO_VIEW_BLEND), 0);
+        assertEquals(1.0f, mModel.get(LayoutTab.SATURATION), 0);
+    }
+
+    @Test
+    public void testOnPageLoadFinished() {
+        doReturn(true).when(mTab2).isFrozen();
+        getTabModelSelectorTabModelObserverFromCaptor().didSelectTab(
+                mTab2, TabSelectionType.FROM_USER, TAB1_ID);
+        assertTrue(mModel.get(LayoutTab.SHOULD_STALL));
+        assertEquals(1.0f, mModel.get(LayoutTab.STATIC_TO_VIEW_BLEND), 0);
+        assertEquals(0.0f, mModel.get(LayoutTab.SATURATION), 0);
+
+        // Index 1 is the TabObserver for mTab2.
+        mTabObserverCaptor.getAllValues().get(1).onPageLoadFinished(mTab2, TAB2_URL);
+
+        assertFalse(mModel.get(LayoutTab.SHOULD_STALL));
+        assertEquals(0.0f, mModel.get(LayoutTab.STATIC_TO_VIEW_BLEND), 0);
+        assertEquals(1.0f, mModel.get(LayoutTab.SATURATION), 0);
+    }
+
+    @Test
+    public void testTabOnShown() {
+        assertNotEquals(TAB2_ID, mModel.get(LayoutTab.TAB_ID));
+
+        // Index 1 is the TabObserver for mTab2.
+        mTabObserverCaptor.getAllValues().get(1).onShown(mTab2, TabSelectionType.FROM_USER);
+        assertEquals(TAB2_ID, mModel.get(LayoutTab.TAB_ID));
+        assertTrue(mModel.get(LayoutTab.CAN_USE_LIVE_TEXTURE));
+        assertEquals(0.0f, mModel.get(LayoutTab.STATIC_TO_VIEW_BLEND), 0);
+
+        LinkedList visibleIdList = new LinkedList<Integer>(Arrays.asList(TAB2_ID));
+        verify(mTabContentManager).updateVisibleIds(eq(visibleIdList), eq(TAB2_ID));
+    }
+
+    @Test
+    public void testTabOnContentChanged() {
+        // Index 0 is the TabObserver for mTab1.
+        mTabObserverCaptor.getAllValues().get(0).onContentChanged(mTab1);
+        assertTrue(mModel.get(LayoutTab.CAN_USE_LIVE_TEXTURE));
+        assertEquals(0.0f, mModel.get(LayoutTab.STATIC_TO_VIEW_BLEND), 0);
+    }
+
+    @Test
+    public void testTabOnBackgroundColorChanged() {
+        mModel.set(LayoutTab.BACKGROUND_COLOR, Color.WHITE);
+
+        // Index 0 is the TabObserver for mTab1.
+        doReturn(Color.RED).when(mTabThemeColorHelper).getBackgroundColor();
+        mTabObserverCaptor.getAllValues().get(0).onBackgroundColorChanged(mTab1, Color.RED);
+
+        assertEquals(Color.RED, mModel.get(LayoutTab.BACKGROUND_COLOR));
+    }
+
+    @Test
+    public void testUpdateLayout() {
+        mModel.set(LayoutTab.RENDER_X, 0.0f);
+        mModel.set(LayoutTab.RENDER_Y, 0.0f);
+        mModel.set(LayoutTab.X, 1.0f);
+        mModel.set(LayoutTab.Y, 1.0f);
+
+        mStaticLayout.updateLayout(System.currentTimeMillis(), 1000);
+
+        assertEquals(1.0f, mModel.get(LayoutTab.RENDER_X), 0);
+        assertEquals(1.0f, mModel.get(LayoutTab.RENDER_Y), 0);
+
+        mModel.set(LayoutTab.X, 0.3f);
+        mModel.set(LayoutTab.Y, 0.3f);
+
+        mStaticLayout.updateLayout(System.currentTimeMillis(), 1000);
+
+        assertEquals(0.0f, mModel.get(LayoutTab.RENDER_X), 0);
+        assertEquals(0.0f, mModel.get(LayoutTab.RENDER_Y), 0);
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java
index 6b57660..df93196 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityContentTestEnvironment.java
@@ -140,13 +140,13 @@
     }
 
     // clang-format off
-    public CustomTabActivityTabController createTabController() {
+    public CustomTabActivityTabController createTabController(ProfileProvider profileProvider) {
         return new CustomTabActivityTabController(activity, () -> customTabDelegateFactory,
                 connection, intentDataProvider, activityTabProvider, tabObserverRegistrar,
                 () -> compositorViewHolder, lifecycleDispatcher, warmupManager,
                 tabPersistencePolicy, tabFactory, () -> customTabObserver, webContentsFactory,
                 navigationEventObserver, tabProvider, startupTabPreloader, reparentingTaskProvider,
-                () -> customTabIncognitoManager);
+                () -> customTabIncognitoManager, profileProvider);
     }
     // clang-format on
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabControllerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabControllerUnitTest.java
index c00d689a..0435331 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabControllerUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabControllerUnitTest.java
@@ -24,9 +24,12 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 import org.robolectric.annotation.Config;
 
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.components.embedder_support.util.ShadowUrlUtilities;
@@ -49,9 +52,17 @@
 
     private CustomTabActivityTabController mTabController;
 
+    @Mock
+    public ProfileProvider mProfileProvider;
+
+    @Mock
+    private Profile mProfile;
+
     @Before
     public void setUp() {
-        mTabController = env.createTabController();
+        MockitoAnnotations.initMocks(this);
+        when(mProfileProvider.getLastUsedRegularProfile()).thenReturn(mProfile);
+        mTabController = env.createTabController(mProfileProvider);
     }
 
     @Test
@@ -137,7 +148,7 @@
     @Test
     public void usesWebContentsCreatedWithWarmRenderer_ByDefault() {
         WebContents webContents = mock(WebContents.class);
-        when(env.webContentsFactory.createWebContentsWithWarmRenderer(anyBoolean(), anyBoolean()))
+        when(env.webContentsFactory.createWebContentsWithWarmRenderer(any(), anyBoolean()))
                 .thenReturn(webContents);
         env.reachNativeInit(mTabController);
         assertEquals(webContents, env.webContentsCaptor.getValue());
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java
index 09398abc..2985fe7 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java
@@ -33,6 +33,7 @@
 import org.chromium.base.test.util.JniMocker;
 import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.components.embedder_support.util.UrlUtilities;
@@ -55,6 +56,12 @@
     @Rule
     public Features.JUnitProcessor processor = new Features.JUnitProcessor();
 
+    @Mock
+    public ProfileProvider mProfileProvider;
+
+    @Mock
+    private Profile mProfile;
+
     private CustomTabActivityTabController mTabController;
     private CustomTabActivityNavigationController mNavigationController;
     private CustomTabIntentHandler mIntentHandler;
@@ -69,7 +76,8 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mocker.mock(UrlUtilitiesJni.TEST_HOOKS, mUrlUtilitiesJniMock);
-        mTabController = env.createTabController();
+        when(mProfileProvider.getLastUsedRegularProfile()).thenReturn(mProfile);
+        mTabController = env.createTabController(mProfileProvider);
         mNavigationController = env.createNavigationController(mTabController);
         mIntentHandler = env.createIntentHandler(mNavigationController);
     }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/signin/ConfirmImportSyncDataDialogTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/signin/ConfirmImportSyncDataDialogTest.java
index 5f80cc00..f7654436 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/signin/ConfirmImportSyncDataDialogTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/signin/ConfirmImportSyncDataDialogTest.java
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 package org.chromium.chrome.browser.signin;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
@@ -24,6 +25,7 @@
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.profiles.Profile;
 
 /** Tests for {@link ConfirmImportSyncDataDialog}. */
 @RunWith(BaseRobolectricTestRunner.class)
@@ -37,6 +39,9 @@
     @Mock
     private SigninManager mSigninManagerMock;
 
+    @Mock
+    private Profile mProfile;
+
     private FragmentManager mFragmentManager;
 
     private ConfirmSyncDataStateMachineDelegate mStateMachineDelegate;
@@ -45,7 +50,8 @@
     public void setUp() {
         initMocks(this);
         IdentityServicesProvider.setInstanceForTests(mock(IdentityServicesProvider.class));
-        when(IdentityServicesProvider.get().getSigninManager()).thenReturn(mSigninManagerMock);
+        Profile.setLastUsedProfileForTesting(mProfile);
+        when(IdentityServicesProvider.get().getSigninManager(any())).thenReturn(mSigninManagerMock);
         mFragmentManager =
                 Robolectric.setupActivity(FragmentActivity.class).getSupportFragmentManager();
         mStateMachineDelegate = new ConfirmSyncDataStateMachineDelegate(mFragmentManager);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/signin/ConfirmSyncDataStateMachineTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/signin/ConfirmSyncDataStateMachineTest.java
index d51a395c..2ed7ad2 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/signin/ConfirmSyncDataStateMachineTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/signin/ConfirmSyncDataStateMachineTest.java
@@ -25,6 +25,7 @@
 import org.chromium.base.Callback;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.JniMocker;
+import org.chromium.chrome.browser.profiles.Profile;
 
 /** Tests for {@link ConfirmSyncDataStateMachine}. */
 @RunWith(BaseRobolectricTestRunner.class)
@@ -44,6 +45,9 @@
     @Mock
     private SigninManager mSigninManagerMock;
 
+    @Mock
+    private Profile mProfile;
+
     @Captor
     private ArgumentCaptor<Callback<Boolean>> mCallbackArgument;
 
@@ -56,7 +60,8 @@
         initMocks(this);
         mocker.mock(SigninManagerJni.TEST_HOOKS, mSigninManagerNativeMock);
         IdentityServicesProvider.setInstanceForTests(mock(IdentityServicesProvider.class));
-        when(IdentityServicesProvider.get().getSigninManager()).thenReturn(mSigninManagerMock);
+        Profile.setLastUsedProfileForTesting(mProfile);
+        when(IdentityServicesProvider.get().getSigninManager(any())).thenReturn(mSigninManagerMock);
     }
 
     @Test(expected = AssertionError.class)
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SignOutDialogFragmentTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SignOutDialogFragmentTest.java
index 8e052bf..7939716 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SignOutDialogFragmentTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SignOutDialogFragmentTest.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.signin;
 
 import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -31,6 +32,7 @@
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.JniMocker;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.profiles.ProfileAccountManagementMetrics;
 import org.chromium.components.signin.GAIAServiceType;
 
@@ -55,6 +57,9 @@
     @Mock
     private SigninManager mSigninManagerMock;
 
+    @Mock
+    private Profile mProfile;
+
     @Spy
     private final DummySignOutTargetFragment mTargetFragment = new DummySignOutTargetFragment();
 
@@ -67,7 +72,8 @@
         initMocks(this);
         mocker.mock(SigninUtilsJni.TEST_HOOKS, mSigninUtilsNativeMock);
         IdentityServicesProvider.setInstanceForTests(mock(IdentityServicesProvider.class));
-        when(IdentityServicesProvider.get().getSigninManager()).thenReturn(mSigninManagerMock);
+        Profile.setLastUsedProfileForTesting(mProfile);
+        when(IdentityServicesProvider.get().getSigninManager(any())).thenReturn(mSigninManagerMock);
         setUpSignOutDialog();
     }
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninUtilsStartActivityTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninUtilsStartActivityTest.java
index 1633c34..d725c50 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninUtilsStartActivityTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninUtilsStartActivityTest.java
@@ -24,6 +24,7 @@
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.components.signin.metrics.SigninAccessPoint;
 
 /** Tests for the method startSigninActivityIfAllowed {@link SigninUtils}. */
@@ -35,13 +36,17 @@
     @Mock
     private SigninActivityLauncher mLauncherMock;
 
+    @Mock
+    private Profile mProfile;
+
     private final Context mContext = RuntimeEnvironment.application.getApplicationContext();
 
     @Before
     public void setUp() {
         initMocks(this);
         IdentityServicesProvider.setInstanceForTests(mock(IdentityServicesProvider.class));
-        when(IdentityServicesProvider.get().getSigninManager()).thenReturn(mSigninManagerMock);
+        Profile.setLastUsedProfileForTesting(mProfile);
+        when(IdentityServicesProvider.get().getSigninManager(any())).thenReturn(mSigninManagerMock);
         SigninActivityLauncher.setLauncherForTest(mLauncherMock);
     }
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/site_settings/OWNERS b/chrome/android/junit/src/org/chromium/chrome/browser/site_settings/OWNERS
new file mode 100644
index 0000000..72fb09a
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/site_settings/OWNERS
@@ -0,0 +1 @@
+file://components/browser_ui/site_settings/OWNERS
\ No newline at end of file
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/site_settings/SingleWebsiteSettingsTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/site_settings/SingleWebsiteSettingsTest.java
new file mode 100644
index 0000000..4a4d6e9
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/site_settings/SingleWebsiteSettingsTest.java
@@ -0,0 +1,81 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.site_settings;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.components.browser_ui.site_settings.SingleWebsiteSettings;
+import org.chromium.components.content_settings.ContentSettingsType;
+
+/**
+ * Tests the functionality of the SingleWebsiteSettings.java page.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+public class SingleWebsiteSettingsTest {
+    private @ContentSettingsType int getCorrectContentSettingsTypeForPreferenceKey(
+            String preferenceKey) {
+        switch (preferenceKey) {
+            case "ads_permission_list":
+                return ContentSettingsType.ADS;
+            case "automatic_downloads_permission_list":
+                return ContentSettingsType.AUTOMATIC_DOWNLOADS;
+            case "background_sync_permission_list":
+                return ContentSettingsType.BACKGROUND_SYNC;
+            case "bluetooth_scanning_permission_list":
+                return ContentSettingsType.BLUETOOTH_SCANNING;
+            case "cookies_permission_list":
+                return ContentSettingsType.COOKIES;
+            case "javascript_permission_list":
+                return ContentSettingsType.JAVASCRIPT;
+            case "popup_permission_list":
+                return ContentSettingsType.POPUPS;
+            case "sound_permission_list":
+                return ContentSettingsType.SOUND;
+            case "ar_permission_list":
+                return ContentSettingsType.AR;
+            case "camera_permission_list":
+                return ContentSettingsType.MEDIASTREAM_CAMERA;
+            case "clipboard_permission_list":
+                return ContentSettingsType.CLIPBOARD_READ_WRITE;
+            case "location_access_list":
+                return ContentSettingsType.GEOLOCATION;
+            case "microphone_permission_list":
+                return ContentSettingsType.MEDIASTREAM_MIC;
+            case "midi_sysex_permission_list":
+                return ContentSettingsType.MIDI_SYSEX;
+            case "nfc_permission_list":
+                return ContentSettingsType.NFC;
+            case "push_notifications_list":
+                return ContentSettingsType.NOTIFICATIONS;
+            case "protected_media_identifier_permission_list":
+                return ContentSettingsType.PROTECTED_MEDIA_IDENTIFIER;
+            case "sensors_permission_list":
+                return ContentSettingsType.SENSORS;
+            case "vr_permission_list":
+                return ContentSettingsType.VR;
+            default:
+                Assert.fail("Preference key not in list.");
+                return ContentSettingsType.DEFAULT;
+        }
+    }
+
+    /**
+     * Tests that the order of SingleWebsiteSettings.PERMISSION_PREFERENCE_KEYS matches the enums it
+     * comes from.
+     */
+    @Test
+    @SmallTest
+    public void testCorrectMapOfPreferenceKeyToContentSettingsType() {
+        for (String key : SingleWebsiteSettings.PERMISSION_PREFERENCE_KEYS) {
+            Assert.assertEquals(SingleWebsiteSettings.getContentSettingsTypeFromPreferenceKey(key),
+                    getCorrectContentSettingsTypeForPreferenceKey(key));
+        }
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/modules/test_dummy/provider/BUILD.gn b/chrome/android/modules/test_dummy/provider/BUILD.gn
index b35bd1e6..afc8f4a8 100644
--- a/chrome/android/modules/test_dummy/provider/BUILD.gn
+++ b/chrome/android/modules/test_dummy/provider/BUILD.gn
@@ -10,6 +10,7 @@
     "//base:jni_java",
     "//chrome/android/modules/test_dummy/public:java",
     "//chrome/browser/test_dummy:java",
+    "//components/module_installer/android:module_installer_java",
   ]
   sources = [ "java/src/org/chromium/chrome/modules/test_dummy/TestDummyModuleProvider.java" ]
 }
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index c487e4b..bd35f4c 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-86.0.4194.0_rc-r1-merged.afdo.bz2
+chromeos-chrome-amd64-86.0.4203.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/android/webapk/libs/runtime_library/BUILD.gn b/chrome/android/webapk/libs/runtime_library/BUILD.gn
index eaba3a5..71bb30ae 100644
--- a/chrome/android/webapk/libs/runtime_library/BUILD.gn
+++ b/chrome/android/webapk/libs/runtime_library/BUILD.gn
@@ -76,6 +76,7 @@
     "//base:base_java_test_support",
     "//chrome/test/android:chrome_java_test_support",
     "//content/public/test/android:content_java_test_support",
+    "//third_party/android_deps:androidx_test_runner_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/junit",
   ]
diff --git a/chrome/android/webapk/shell_apk/BUILD.gn b/chrome/android/webapk/shell_apk/BUILD.gn
index 075df97..c3bbeec 100644
--- a/chrome/android/webapk/shell_apk/BUILD.gn
+++ b/chrome/android/webapk/shell_apk/BUILD.gn
@@ -71,6 +71,7 @@
       "//chrome/android/webapk/libs/common:common_java",
       "//chrome/android/webapk/libs/common:splash_java",
       "//components/webapk/android/libs/common:java",
+      "//third_party/android_deps:androidx_annotation_annotation_java",
     ]
   }
 }
@@ -341,6 +342,7 @@
     "//base:base_java_test_support",
     "//chrome/android/webapk/libs/common:common_java",
     "//content/public/test/android:content_java_test_support",
+    "//third_party/android_deps:androidx_test_runner_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/junit",
   ]
@@ -365,6 +367,7 @@
     "//chrome/android/webapk/libs/runtime_library:runtime_library_for_tests_java",
     "//chrome/android/webapk/test:junit_test_support",
     "//components/webapk/android/libs/common:java",
+    "//third_party/android_deps:androidx_annotation_annotation_java",
   ]
 }
 
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index a73b7c8..c16ff790 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -4567,6 +4567,9 @@
   <message name="IDS_CROSTINI_UPGRADER_RESTORE_MESSAGE" desc="Title of the Crostini upgrader when the container upgrade fails and restore of a backup is in progress.">
     Linux files and apps are being restored to their backed up state.
   </message>
+  <message name="IDS_CROSTINI_UPGRADER_NOT_NOW" desc="Text on the button to defer performing the upgrade">
+    Not now
+  </message>
   <message name="IDS_CROSTINI_ANSIBLE_SOFTWARE_CONFIG_LABEL" desc="Label for dialog warning user of unavailable Linux container until software configurations are applied.">
     Configuring Linux
   </message>
diff --git a/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_UPGRADER_NOT_NOW.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_UPGRADER_NOT_NOW.png.sha1
new file mode 100644
index 0000000..a0eacbed
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_UPGRADER_NOT_NOW.png.sha1
@@ -0,0 +1 @@
+26e04e7c73a3943a4d16d99f51484cb6ec8d0486
\ No newline at end of file
diff --git a/chrome/app/theme/plugin_vm/plugin_vm_installer.png b/chrome/app/theme/plugin_vm/plugin_vm_installer.png
index 3e95c0b..96a0460 100644
--- a/chrome/app/theme/plugin_vm/plugin_vm_installer.png
+++ b/chrome/app/theme/plugin_vm/plugin_vm_installer.png
Binary files differ
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index fa3a907a..bc40fca 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -966,8 +966,6 @@
     "page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.h",
     "page_load_metrics/observers/ad_metrics/frame_data.cc",
     "page_load_metrics/observers/ad_metrics/frame_data.h",
-    "page_load_metrics/observers/ad_metrics/page_ad_density_tracker.cc",
-    "page_load_metrics/observers/ad_metrics/page_ad_density_tracker.h",
     "page_load_metrics/observers/amp_page_load_metrics_observer.cc",
     "page_load_metrics/observers/amp_page_load_metrics_observer.h",
     "page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index c532a1f..4c15e98 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -5881,7 +5881,15 @@
     {"lite-video-force-override-decision",
      flag_descriptions::kLiteVideoForceOverrideDecisionName,
      flag_descriptions::kLiteVideoForceOverrideDecisionDescription, kOsAll,
-     SINGLE_VALUE_TYPE(lite_video::switches::kLiteVideoForceOverrideDecision)}
+     SINGLE_VALUE_TYPE(lite_video::switches::kLiteVideoForceOverrideDecision)},
+
+#if !defined(OS_ANDROID)
+    {"edit-passwords-in-settings",
+     flag_descriptions::kEditPasswordsInDesktopSettingsName,
+     flag_descriptions::kEditPasswordsInDesktopSettingsDescription, kOsDesktop,
+     FEATURE_VALUE_TYPE(
+         password_manager::features::kEditPasswordsInDesktopSettings)}
+#endif  // !defined(OS_ANDROID)
 
     // NOTE: Adding a new flag requires adding a corresponding entry to enum
     // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag
diff --git a/chrome/browser/android/compositor/scene_layer/static_tab_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/static_tab_scene_layer.cc
index 6a25093..913a391 100644
--- a/chrome/browser/android/compositor/scene_layer/static_tab_scene_layer.cc
+++ b/chrome/browser/android/compositor/scene_layer/static_tab_scene_layer.cc
@@ -20,6 +20,7 @@
 StaticTabSceneLayer::StaticTabSceneLayer(JNIEnv* env,
                                          const JavaRef<jobject>& jobj)
     : SceneLayer(env, jobj),
+      tab_content_manager_(nullptr),
       last_set_tab_id_(-1),
       background_color_(SK_ColorWHITE),
       brightness_(1.f) {}
@@ -39,7 +40,6 @@
 void StaticTabSceneLayer::UpdateTabLayer(
     JNIEnv* env,
     const JavaParamRef<jobject>& jobj,
-    const JavaParamRef<jobject>& jtab_content_manager,
     jint id,
     jboolean can_use_live_layer,
     jint default_background_color,
@@ -48,11 +48,12 @@
     jfloat static_to_view_blend,
     jfloat saturation,
     jfloat brightness) {
+  DCHECK(tab_content_manager_)
+      << "TabContentManager must be set before updating the layer";
+
   background_color_ = default_background_color;
   if (!content_layer_.get()) {
-    android::TabContentManager* tab_content_manager =
-        android::TabContentManager::FromJavaObject(jtab_content_manager);
-    content_layer_ = android::ContentLayer::Create(tab_content_manager);
+    content_layer_ = android::ContentLayer::Create(tab_content_manager_);
     layer_->AddChild(content_layer_->layer());
   }
 
@@ -81,6 +82,16 @@
   }
 }
 
+void StaticTabSceneLayer::SetTabContentManager(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& jobj,
+    const base::android::JavaParamRef<jobject>& jtab_content_manager) {
+  if (!tab_content_manager_) {
+    tab_content_manager_ =
+        TabContentManager::FromJavaObject(jtab_content_manager);
+  }
+}
+
 static jlong JNI_StaticTabSceneLayer_Init(JNIEnv* env,
                                           const JavaParamRef<jobject>& jobj) {
   // This will automatically bind to the Java object and pass ownership there.
diff --git a/chrome/browser/android/compositor/scene_layer/static_tab_scene_layer.h b/chrome/browser/android/compositor/scene_layer/static_tab_scene_layer.h
index 21e610c..b8acd7c 100644
--- a/chrome/browser/android/compositor/scene_layer/static_tab_scene_layer.h
+++ b/chrome/browser/android/compositor/scene_layer/static_tab_scene_layer.h
@@ -22,6 +22,7 @@
 namespace android {
 
 class ContentLayer;
+class TabContentManager;
 
 // A SceneLayer to render a static tab.
 class StaticTabSceneLayer : public SceneLayer {
@@ -36,7 +37,6 @@
   void UpdateTabLayer(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& jobj,
-      const base::android::JavaParamRef<jobject>& jtab_content_manager,
       jint id,
       jboolean can_use_live_layer,
       jint default_background_color,
@@ -46,9 +46,15 @@
       jfloat saturation,
       jfloat brightness);
 
+  void SetTabContentManager(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& jobj,
+      const base::android::JavaParamRef<jobject>& jtab_content_manager);
+
  private:
   scoped_refptr<android::ContentLayer> content_layer_;
 
+  TabContentManager* tab_content_manager_;
   int last_set_tab_id_;
   int background_color_;
   float brightness_;
diff --git a/chrome/browser/android/compositor/scene_layer/tab_list_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/tab_list_scene_layer.cc
index ee595fef..6d2c61e3 100644
--- a/chrome/browser/android/compositor/scene_layer/tab_list_scene_layer.cc
+++ b/chrome/browser/android/compositor/scene_layer/tab_list_scene_layer.cc
@@ -68,22 +68,7 @@
     jfloat viewport_x,
     jfloat viewport_y,
     jfloat viewport_width,
-    jfloat viewport_height,
-    const JavaParamRef<jobject>& jlayer_title_cache,
-    const JavaParamRef<jobject>& jtab_content_manager,
-    const JavaParamRef<jobject>& jresource_manager) {
-  // TODO(changwan): move these to constructor if possible
-  if (!resource_manager_) {
-    resource_manager_ =
-        ui::ResourceManagerImpl::FromJavaObject(jresource_manager);
-  }
-  if (!layer_title_cache_)
-    layer_title_cache_ = LayerTitleCache::FromJavaObject(jlayer_title_cache);
-  if (!tab_content_manager_) {
-    tab_content_manager_ =
-        TabContentManager::FromJavaObject(jtab_content_manager);
-  }
-
+    jfloat viewport_height) {
   background_color_ = background_color;
   own_tree_->SetPosition(gfx::PointF(viewport_x, viewport_y));
   own_tree_->SetBounds(gfx::Size(viewport_width, viewport_height));
@@ -145,6 +130,13 @@
     jfloat content_offset,
     jfloat side_border_scale,
     jboolean inset_border) {
+  DCHECK(tab_content_manager_)
+      << "TabContentManager must be set before updating the TabLayer";
+  DCHECK(layer_title_cache_)
+      << "LayerTitleCache must be set before updating the TabLayer";
+  DCHECK(resource_manager_)
+      << "ResourceManager must be set before updating the TabLayer";
+
   scoped_refptr<TabLayer> layer;
   auto iter = tab_map_.find(id);
   if (iter != tab_map_.end()) {
@@ -222,6 +214,25 @@
   background_layer_->SetPosition(gfx::PointF(0, top_offset));
 }
 
+void TabListSceneLayer::SetDependencies(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& jobj,
+    const base::android::JavaParamRef<jobject>& jtab_content_manager,
+    const base::android::JavaParamRef<jobject>& jlayer_title_cache,
+    const base::android::JavaParamRef<jobject>& jresource_manager) {
+  if (!tab_content_manager_) {
+    tab_content_manager_ =
+        TabContentManager::FromJavaObject(jtab_content_manager);
+  }
+  if (!layer_title_cache_) {
+    layer_title_cache_ = LayerTitleCache::FromJavaObject(jlayer_title_cache);
+  }
+  if (!resource_manager_) {
+    resource_manager_ =
+        ui::ResourceManagerImpl::FromJavaObject(jresource_manager);
+  }
+}
+
 void TabListSceneLayer::OnDetach() {
   SceneLayer::OnDetach();
   for (auto tab : tab_map_)
diff --git a/chrome/browser/android/compositor/scene_layer/tab_list_scene_layer.h b/chrome/browser/android/compositor/scene_layer/tab_list_scene_layer.h
index 9c277fe..fd86840 100644
--- a/chrome/browser/android/compositor/scene_layer/tab_list_scene_layer.h
+++ b/chrome/browser/android/compositor/scene_layer/tab_list_scene_layer.h
@@ -15,6 +15,7 @@
 #include "cc/layers/ui_resource_layer.h"
 #include "chrome/browser/android/compositor/layer/layer.h"
 #include "chrome/browser/android/compositor/scene_layer/scene_layer.h"
+#include "chrome/browser/android/compositor/tab_content_manager.h"
 #include "third_party/skia/include/core/SkColor.h"
 
 namespace ui {
@@ -36,17 +37,13 @@
                           const base::android::JavaParamRef<jobject>& jobj);
   void FinishBuildingFrame(JNIEnv* env,
                            const base::android::JavaParamRef<jobject>& jobj);
-  void UpdateLayer(
-      JNIEnv* env,
-      const base::android::JavaParamRef<jobject>& jobj,
-      jint background_color,
-      jfloat viewport_x,
-      jfloat viewport_y,
-      jfloat viewport_width,
-      jfloat viewport_height,
-      const base::android::JavaParamRef<jobject>& jlayer_title_cache,
-      const base::android::JavaParamRef<jobject>& jtab_content_manager,
-      const base::android::JavaParamRef<jobject>& jresource_manager);
+  void UpdateLayer(JNIEnv* env,
+                   const base::android::JavaParamRef<jobject>& jobj,
+                   jint background_color,
+                   jfloat viewport_x,
+                   jfloat viewport_y,
+                   jfloat viewport_width,
+                   jfloat viewport_height);
   // TODO(meiliang): This method needs another parameter, a resource that can be
   // used to indicate the currently selected tab for the TabLayer.
   // TODO(dtrainor): This method is ridiculous.  Break this apart?
@@ -112,6 +109,13 @@
                           jfloat alpha,
                           jint top_offset);
 
+  void SetDependencies(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& jobj,
+      const base::android::JavaParamRef<jobject>& jtab_content_manager,
+      const base::android::JavaParamRef<jobject>& jlayer_title_cache,
+      const base::android::JavaParamRef<jobject>& jresource_manager);
+
   void OnDetach() override;
   bool ShouldShowBackground() override;
   SkColor GetBackgroundColor() override;
diff --git a/chrome/browser/apps/intent_helper/apps_navigation_throttle.cc b/chrome/browser/apps/intent_helper/apps_navigation_throttle.cc
index 274e2025f..79c166d 100644
--- a/chrome/browser/apps/intent_helper/apps_navigation_throttle.cc
+++ b/chrome/browser/apps/intent_helper/apps_navigation_throttle.cc
@@ -34,7 +34,7 @@
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/common/constants.h"
-#include "third_party/blink/public/mojom/referrer.mojom.h"
+#include "third_party/blink/public/mojom/loader/referrer.mojom.h"
 #include "ui/gfx/image/image.h"
 #include "url/origin.h"
 
diff --git a/chrome/browser/autofill/form_structure_browsertest.cc b/chrome/browser/autofill/form_structure_browsertest.cc
index 6bb4a2a..854c8a2 100644
--- a/chrome/browser/autofill/form_structure_browsertest.cc
+++ b/chrome/browser/autofill/form_structure_browsertest.cc
@@ -99,11 +99,11 @@
   for (const auto& kv : forms) {
     const auto* form = kv.second.get();
     for (const auto& field : *form) {
-      forms_string += field->Type().ToString();
-      forms_string += " | " + base::UTF16ToUTF8(field->name);
-      forms_string += " | " + base::UTF16ToUTF8(field->label);
-      forms_string += " | " + base::UTF16ToUTF8(field->value);
-      forms_string += " | " + field->section;
+      forms_string += base::JoinString(
+          {field->Type().ToString(), base::UTF16ToUTF8(field->name),
+           base::UTF16ToUTF8(field->label), base::UTF16ToUTF8(field->value),
+           field->section},
+          base::StringPiece(" | "));
       forms_string += "\n";
     }
   }
diff --git a/chrome/browser/chrome_security_exploit_browsertest.cc b/chrome/browser/chrome_security_exploit_browsertest.cc
index f77a04e0..cb97e7c 100644
--- a/chrome/browser/chrome_security_exploit_browsertest.cc
+++ b/chrome/browser/chrome_security_exploit_browsertest.cc
@@ -324,8 +324,8 @@
 
   EXPECT_TRUE(content::ExecuteScriptAndExtractString(rfh, script, &body));
   EXPECT_EQ(
-      "Your file was not found\n"
-      "It may have been moved or deleted.\n"
+      "Your file couldn’t be accessed\n"
+      "It may have been moved, edited, or deleted.\n"
       "ERR_FILE_NOT_FOUND",
       body);
 }
@@ -402,8 +402,8 @@
 
   EXPECT_TRUE(content::ExecuteScriptAndExtractString(rfh, script, &body));
   EXPECT_EQ(
-      "Your file was not found\n"
-      "It may have been moved or deleted.\n"
+      "Your file couldn’t be accessed\n"
+      "It may have been moved, edited, or deleted.\n"
       "ERR_FILE_NOT_FOUND",
       body);
 }
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
index 0b6f7e7..02ac56c1 100644
--- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
+++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.cc
@@ -60,118 +60,9 @@
 
 void AXTreeSourceArc::NotifyAccessibilityEvent(AXEventData* event_data) {
   root_id_.reset();
-  tree_map_.clear();
-  parent_map_.clear();
-  computed_bounds_.clear();
+  DCHECK(event_data);
 
-  window_id_ = event_data->window_id;
-  is_notification_ = event_data->notification_key.has_value();
-  is_input_method_window_ = event_data->is_input_method_window;
-
-  // Prepare the wrapper objects of mojom data from Android.
-  CHECK(event_data->window_data);
-  root_id_ = event_data->window_data->at(0)->window_id;
-  for (size_t i = 0; i < event_data->window_data->size(); ++i) {
-    int32_t window_id = event_data->window_data->at(i)->window_id;
-    int32_t root_node_id = event_data->window_data->at(i)->root_node_id;
-    AXWindowInfoData* window = event_data->window_data->at(i).get();
-    if (root_node_id)
-      parent_map_[root_node_id] = window_id;
-
-    tree_map_[window_id] =
-        std::make_unique<AccessibilityWindowInfoDataWrapper>(this, window);
-
-    std::vector<int32_t> children;
-    if (GetProperty(window->int_list_properties,
-                    AXWindowIntListProperty::CHILD_WINDOW_IDS, &children)) {
-      for (const int32_t child : children) {
-        DCHECK(child != root_id_);
-        parent_map_[child] = window_id;
-      }
-    }
-  }
-
-  for (size_t i = 0; i < event_data->node_data.size(); ++i) {
-    int32_t node_id = event_data->node_data[i]->id;
-    AXNodeInfoData* node = event_data->node_data[i].get();
-    tree_map_[node_id] =
-        std::make_unique<AccessibilityNodeInfoDataWrapper>(this, node);
-
-    std::vector<int32_t> children;
-    if (GetProperty(event_data->node_data[i].get()->int_list_properties,
-                    AXIntListProperty::CHILD_NODE_IDS, &children)) {
-      for (const int32_t child : children)
-        parent_map_[child] = node_id;
-    }
-  }
-
-  // Compute each node's bounds, based on its descendants.
-  // Assuming |nodeData| is in pre-order, compute cached bounds in post-order to
-  // avoid an O(n^2) amount of work as the computed bounds uses descendant
-  // bounds.
-  for (int i = event_data->node_data.size() - 1; i >= 0; --i) {
-    int32_t id = event_data->node_data[i]->id;
-    computed_bounds_[id] = ComputeEnclosingBounds(tree_map_[id].get());
-  }
-  for (int i = event_data->window_data->size() - 1; i >= 0; --i) {
-    int32_t id = event_data->window_data->at(i)->window_id;
-    computed_bounds_[id] = ComputeEnclosingBounds(tree_map_[id].get());
-  }
-
-  if (!UpdateAndroidFocusedId(*event_data)) {
-    // Exit this function if the focused node doesn't exist nor isn't visible.
-    return;
-  }
-
-  if (event_data->event_type == AXEventType::WINDOW_STATE_CHANGED &&
-      event_data->event_text) {
-    AccessibilityInfoDataWrapper* source_node =
-        GetFromId(event_data->source_id);
-    if (IsValid(source_node))
-      UpdateAXNameCache(source_node, *event_data->event_text);
-  }
-
-  ApplyCachedProperties();
-
-  ExtensionMsg_AccessibilityEventBundleParams event_bundle;
-  event_bundle.tree_id = ax_tree_id();
-
-  AccessibilityInfoDataWrapper* focused_node =
-      android_focused_id_.has_value() ? GetFromId(*android_focused_id_)
-                                      : nullptr;
-  event_bundle.events.emplace_back();
-  ui::AXEvent& event = event_bundle.events.back();
-  event.event_type = ToAXEvent(
-      event_data->event_type,
-      GetPropertyOrNull(
-          event_data->int_list_properties,
-          arc::mojom::AccessibilityEventIntListProperty::CONTENT_CHANGE_TYPES),
-      GetFromId(event_data->source_id), focused_node);
-  event.id = event_data->source_id;
-
-  if (HasProperty(event_data->int_properties,
-                  arc::mojom::AccessibilityEventIntProperty::ACTION)) {
-    event.event_from = ax::mojom::EventFrom::kAction;
-  }
-
-  HandleLiveRegions(&event_bundle.events);
-
-  event_bundle.updates.emplace_back();
-
-  // Force the tree, to update, so unignored fields get updated.
-  // On event type of WINDOW_STATE_CHANGED, update the entire tree so that
-  // window location is correctly calculated.
-  int32_t node_id_to_clear =
-      (event_data->event_type == AXEventType::WINDOW_STATE_CHANGED)
-          ? *root_id_
-          : event_data->source_id;
-  event_bundle.updates[0].node_id_to_clear = node_id_to_clear;
-  current_tree_serializer_->InvalidateSubtree(GetFromId(node_id_to_clear));
-
-  current_tree_serializer_->SerializeChanges(GetFromId(node_id_to_clear),
-                                             &event_bundle.updates.back());
-
-  GetAutomationEventRouter()->DispatchAccessibilityEvents(event_bundle);
+  NotifyAccessibilityEventInternal(*event_data);
 
   // Clear maps in order to prevent invalid access from dead pointers.
   tree_map_.clear();
@@ -260,6 +151,117 @@
   info_data->Serialize(out_data);
 }
 
+void AXTreeSourceArc::NotifyAccessibilityEventInternal(
+    const AXEventData& event_data) {
+  window_id_ = event_data.window_id;
+  is_notification_ = event_data.notification_key.has_value();
+  is_input_method_window_ = event_data.is_input_method_window;
+
+  // Prepare the wrapper objects of mojom data from Android.
+  CHECK(event_data.window_data);
+  root_id_ = event_data.window_data->at(0)->window_id;
+  for (size_t i = 0; i < event_data.window_data->size(); ++i) {
+    int32_t window_id = event_data.window_data->at(i)->window_id;
+    int32_t root_node_id = event_data.window_data->at(i)->root_node_id;
+    AXWindowInfoData* window = event_data.window_data->at(i).get();
+    if (root_node_id)
+      parent_map_[root_node_id] = window_id;
+
+    tree_map_[window_id] =
+        std::make_unique<AccessibilityWindowInfoDataWrapper>(this, window);
+
+    std::vector<int32_t> children;
+    if (GetProperty(window->int_list_properties,
+                    AXWindowIntListProperty::CHILD_WINDOW_IDS, &children)) {
+      for (const int32_t child : children) {
+        DCHECK(child != root_id_);
+        parent_map_[child] = window_id;
+      }
+    }
+  }
+
+  for (size_t i = 0; i < event_data.node_data.size(); ++i) {
+    int32_t node_id = event_data.node_data[i]->id;
+    AXNodeInfoData* node = event_data.node_data[i].get();
+    tree_map_[node_id] =
+        std::make_unique<AccessibilityNodeInfoDataWrapper>(this, node);
+
+    std::vector<int32_t> children;
+    if (GetProperty(event_data.node_data[i].get()->int_list_properties,
+                    AXIntListProperty::CHILD_NODE_IDS, &children)) {
+      for (const int32_t child : children)
+        parent_map_[child] = node_id;
+    }
+  }
+
+  // Compute each node's bounds, based on its descendants.
+  // Assuming |nodeData| is in pre-order, compute cached bounds in post-order to
+  // avoid an O(n^2) amount of work as the computed bounds uses descendant
+  // bounds.
+  for (int i = event_data.node_data.size() - 1; i >= 0; --i) {
+    int32_t id = event_data.node_data[i]->id;
+    computed_bounds_[id] = ComputeEnclosingBounds(tree_map_[id].get());
+  }
+  for (int i = event_data.window_data->size() - 1; i >= 0; --i) {
+    int32_t id = event_data.window_data->at(i)->window_id;
+    computed_bounds_[id] = ComputeEnclosingBounds(tree_map_[id].get());
+  }
+
+  if (!UpdateAndroidFocusedId(event_data)) {
+    // Exit this function if the focused node doesn't exist nor isn't visible.
+    return;
+  }
+
+  if (event_data.event_type == AXEventType::WINDOW_STATE_CHANGED &&
+      event_data.event_text) {
+    AccessibilityInfoDataWrapper* source_node = GetFromId(event_data.source_id);
+    if (IsValid(source_node))
+      UpdateAXNameCache(source_node, *event_data.event_text);
+  }
+
+  ApplyCachedProperties();
+
+  ExtensionMsg_AccessibilityEventBundleParams event_bundle;
+  event_bundle.tree_id = ax_tree_id();
+
+  AccessibilityInfoDataWrapper* focused_node =
+      android_focused_id_.has_value() ? GetFromId(*android_focused_id_)
+                                      : nullptr;
+  event_bundle.events.emplace_back();
+  ui::AXEvent& event = event_bundle.events.back();
+  event.event_type = ToAXEvent(
+      event_data.event_type,
+      GetPropertyOrNull(
+          event_data.int_list_properties,
+          arc::mojom::AccessibilityEventIntListProperty::CONTENT_CHANGE_TYPES),
+      GetFromId(event_data.source_id), focused_node);
+  event.id = event_data.source_id;
+
+  if (HasProperty(event_data.int_properties,
+                  arc::mojom::AccessibilityEventIntProperty::ACTION)) {
+    event.event_from = ax::mojom::EventFrom::kAction;
+  }
+
+  HandleLiveRegions(&event_bundle.events);
+
+  event_bundle.updates.emplace_back();
+
+  // Force the tree, to update, so unignored fields get updated.
+  // On event type of WINDOW_STATE_CHANGED, update the entire tree so that
+  // window location is correctly calculated.
+  int32_t node_id_to_clear =
+      (event_data.event_type == AXEventType::WINDOW_STATE_CHANGED)
+          ? *root_id_
+          : event_data.source_id;
+  event_bundle.updates[0].node_id_to_clear = node_id_to_clear;
+  current_tree_serializer_->InvalidateSubtree(GetFromId(node_id_to_clear));
+
+  current_tree_serializer_->SerializeChanges(GetFromId(node_id_to_clear),
+                                             &event_bundle.updates.back());
+
+  GetAutomationEventRouter()->DispatchAccessibilityEvents(event_bundle);
+}
+
 extensions::AutomationEventRouterInterface*
 AXTreeSourceArc::GetAutomationEventRouter() const {
   return extensions::AutomationEventRouter::GetInstance();
diff --git a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h
index db2763b..61338ad 100644
--- a/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h
+++ b/chrome/browser/chromeos/arc/accessibility/ax_tree_source_arc.h
@@ -96,6 +96,10 @@
  private:
   friend class arc::AXTreeSourceArcTest;
 
+  // Actual implementation of NotifyAccessibilityEvent.
+  void NotifyAccessibilityEventInternal(
+      const mojom::AccessibilityEventData& event_data);
+
   // virtual for testing.
   virtual extensions::AutomationEventRouterInterface* GetAutomationEventRouter()
       const;
diff --git a/chrome/browser/chromeos/arc/session/arc_service_launcher.cc b/chrome/browser/chromeos/arc/session/arc_service_launcher.cc
index 6a4dedf..7055bc1 100644
--- a/chrome/browser/chromeos/arc/session/arc_service_launcher.cc
+++ b/chrome/browser/chromeos/arc/session/arc_service_launcher.cc
@@ -73,6 +73,7 @@
 #include "components/arc/power/arc_power_bridge.h"
 #include "components/arc/property/arc_property_bridge.h"
 #include "components/arc/rotation_lock/arc_rotation_lock_bridge.h"
+#include "components/arc/sensor/arc_sensor_bridge.h"
 #include "components/arc/session/arc_session.h"
 #include "components/arc/session/arc_session_runner.h"
 #include "components/arc/storage_manager/arc_storage_manager.h"
@@ -204,6 +205,7 @@
   ArcProvisionNotificationService::GetForBrowserContext(profile);
   ArcRotationLockBridge::GetForBrowserContext(profile);
   ArcScreenCaptureBridge::GetForBrowserContext(profile);
+  ArcSensorBridge::GetForBrowserContext(profile);
   ArcSettingsService::GetForBrowserContext(profile);
   ArcSmartCardManagerBridge::GetForBrowserContext(profile);
   ArcTimerBridge::GetForBrowserContext(profile);
diff --git a/chrome/browser/chromeos/file_system_provider/notification_manager.cc b/chrome/browser/chromeos/file_system_provider/notification_manager.cc
index cb94234..a045d1f 100644
--- a/chrome/browser/chromeos/file_system_provider/notification_manager.cc
+++ b/chrome/browser/chromeos/file_system_provider/notification_manager.cc
@@ -44,8 +44,8 @@
 
 void NotificationManager::ShowUnresponsiveNotification(
     int id,
-    const NotificationCallback& callback) {
-  callbacks_[id] = callback;
+    NotificationCallback callback) {
+  callbacks_[id] = std::move(callback);
   ShowNotification();
 }
 
@@ -119,9 +119,9 @@
   CallbackMap::iterator it = callbacks_.begin();
   while (it != callbacks_.end()) {
     CallbackMap::iterator current_it = it++;
-    NotificationCallback callback = current_it->second;
+    NotificationCallback callback = std::move(current_it->second);
     callbacks_.erase(current_it);
-    callback.Run(result);
+    std::move(callback).Run(result);
   }
 }
 
diff --git a/chrome/browser/chromeos/file_system_provider/notification_manager.h b/chrome/browser/chromeos/file_system_provider/notification_manager.h
index 674a445..d2d6c48d 100644
--- a/chrome/browser/chromeos/file_system_provider/notification_manager.h
+++ b/chrome/browser/chromeos/file_system_provider/notification_manager.h
@@ -40,9 +40,8 @@
   ~NotificationManager() override;
 
   // NotificationManagerInterface overrides:
-  void ShowUnresponsiveNotification(
-      int id,
-      const NotificationCallback& callback) override;
+  void ShowUnresponsiveNotification(int id,
+                                    NotificationCallback callback) override;
   void HideUnresponsiveNotification(int id) override;
 
   // AppIconLoaderDelegate overrides:
diff --git a/chrome/browser/chromeos/file_system_provider/notification_manager_interface.h b/chrome/browser/chromeos/file_system_provider/notification_manager_interface.h
index 648916a..ade108ed4 100644
--- a/chrome/browser/chromeos/file_system_provider/notification_manager_interface.h
+++ b/chrome/browser/chromeos/file_system_provider/notification_manager_interface.h
@@ -18,16 +18,15 @@
   enum NotificationResult { ABORT, CONTINUE };
 
   // Callback for handling result of a notification.
-  typedef base::Callback<void(NotificationResult)> NotificationCallback;
+  typedef base::OnceCallback<void(NotificationResult)> NotificationCallback;
 
   NotificationManagerInterface() {}
   virtual ~NotificationManagerInterface() {}
 
   // Shows a notification about the request being unresponsive. The |callback|
   // is called when the notification is closed.
-  virtual void ShowUnresponsiveNotification(
-      int id,
-      const NotificationCallback& callback) = 0;
+  virtual void ShowUnresponsiveNotification(int id,
+                                            NotificationCallback callback) = 0;
 
   // Hides a notification previously shown with |id|.
   virtual void HideUnresponsiveNotification(int id) = 0;
diff --git a/chrome/browser/chromeos/file_system_provider/provided_file_system_unittest.cc b/chrome/browser/chromeos/file_system_provider/provided_file_system_unittest.cc
index dd5b2b5..6bd7334 100644
--- a/chrome/browser/chromeos/file_system_provider/provided_file_system_unittest.cc
+++ b/chrome/browser/chromeos/file_system_provider/provided_file_system_unittest.cc
@@ -193,9 +193,8 @@
   ~StubNotificationManager() override {}
 
   // NotificationManagerInterface overrides.
-  void ShowUnresponsiveNotification(
-      int id,
-      const NotificationCallback& callback) override {}
+  void ShowUnresponsiveNotification(int id,
+                                    NotificationCallback callback) override {}
   void HideUnresponsiveNotification(int id) override {}
 
  private:
diff --git a/chrome/browser/chromeos/file_system_provider/request_manager.cc b/chrome/browser/chromeos/file_system_provider/request_manager.cc
index 7178562..c37f9e9 100644
--- a/chrome/browser/chromeos/file_system_provider/request_manager.cc
+++ b/chrome/browser/chromeos/file_system_provider/request_manager.cc
@@ -171,8 +171,8 @@
   if (!IsInteractingWithUser()) {
     notification_manager_->ShowUnresponsiveNotification(
         request_id,
-        base::Bind(&RequestManager::OnUnresponsiveNotificationResult,
-                   weak_ptr_factory_.GetWeakPtr(), request_id));
+        base::BindOnce(&RequestManager::OnUnresponsiveNotificationResult,
+                       weak_ptr_factory_.GetWeakPtr(), request_id));
   } else {
     ResetTimer(request_id);
   }
diff --git a/chrome/browser/chromeos/file_system_provider/request_manager_unittest.cc b/chrome/browser/chromeos/file_system_provider/request_manager_unittest.cc
index 06b458d..155a7b67 100644
--- a/chrome/browser/chromeos/file_system_provider/request_manager_unittest.cc
+++ b/chrome/browser/chromeos/file_system_provider/request_manager_unittest.cc
@@ -38,10 +38,9 @@
   ~FakeNotificationManager() override {}
 
   // NotificationManagerInterface overrides:
-  void ShowUnresponsiveNotification(
-      int id,
-      const NotificationCallback& callback) override {
-    callbacks_[id] = callback;
+  void ShowUnresponsiveNotification(int id,
+                                    NotificationCallback callback) override {
+    callbacks_[id] = std::move(callback);
   }
 
   void HideUnresponsiveNotification(int id) override { callbacks_.erase(id); }
@@ -64,9 +63,9 @@
     CallbackMap::iterator it = callbacks_.begin();
     while (it != callbacks_.end()) {
       CallbackMap::iterator current_it = it++;
-      NotificationCallback callback = current_it->second;
+      NotificationCallback callback = std::move(current_it->second);
       callbacks_.erase(current_it);
-      callback.Run(result);
+      std::move(callback).Run(result);
     }
   }
 
diff --git a/chrome/browser/chromeos/login/saml/saml_browsertest.cc b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
index b598396..cbb8f7f4 100644
--- a/chrome/browser/chromeos/login/saml/saml_browsertest.cc
+++ b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
@@ -1221,9 +1221,11 @@
   LoginDisplayHost::default_host()->StartWizard(
       EnrollmentScreenView::kScreenId);
   WaitForGaiaPageBackButtonUpdate();
+  auto flow_change_waiter =
+      OobeBaseTest::CreateGaiaPageEventWaiter("authFlowChange");
   SigninFrameJS().TypeIntoPath(gaia_email, {"identifier"});
   SigninFrameJS().TapOn("nextButton");
-  OobeBaseTest::WaitForGaiaPageEvent("authFlowChange");
+  flow_change_waiter->Wait();
 }
 
 IN_PROC_BROWSER_TEST_F(SAMLEnrollmentTest, WithoutCredentialsPassingAPI) {
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.cc b/chrome/browser/chromeos/login/test/oobe_base_test.cc
index a794cfa..db7e783 100644
--- a/chrome/browser/chromeos/login/test/oobe_base_test.cc
+++ b/chrome/browser/chromeos/login/test/oobe_base_test.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/chromeos/login/session/user_session_manager_test_api.h"
 #include "chrome/browser/chromeos/login/test/https_forwarder.h"
 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
+#include "chrome/browser/chromeos/login/test/test_condition_waiter.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host_webui.h"
 #include "chrome/browser/chromeos/login/ui/webui_login_view.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
@@ -39,6 +40,46 @@
 
 namespace chromeos {
 
+namespace {
+
+class GaiaPageEventWaiter : public test::TestConditionWaiter {
+ public:
+  GaiaPageEventWaiter(const std::string& authenticator_id,
+                      const std::string& event) {
+    std::string js =
+        R"((function() {
+              var authenticator = $AuthenticatorId;
+              var f = function() {
+                authenticator.removeEventListener('$Event', f);
+                window.domAutomationController.send('Done');
+              };
+              authenticator.addEventListener('$Event', f);
+            })();)";
+    base::ReplaceSubstringsAfterOffset(&js, 0, "$AuthenticatorId",
+                                       authenticator_id);
+    base::ReplaceSubstringsAfterOffset(&js, 0, "$Event", event);
+    test::OobeJS().Evaluate(js);
+  }
+
+  ~GaiaPageEventWaiter() override { EXPECT_TRUE(wait_called_); }
+
+  // test::TestConditionWaiter:
+  void Wait() override {
+    ASSERT_FALSE(wait_called_) << "Wait should be called once";
+    wait_called_ = true;
+    std::string message;
+    do {
+      ASSERT_TRUE(message_queue.WaitForMessage(&message));
+    } while (message != "\"Done\"");
+  }
+
+ private:
+  content::DOMMessageQueue message_queue;
+  bool wait_called_ = false;
+};
+
+}  // namespace
+
 OobeBaseTest::OobeBaseTest() {
   set_exit_when_last_browser_closes(false);
 }
@@ -141,35 +182,16 @@
 }
 
 void OobeBaseTest::WaitForGaiaPageReload() {
-  WaitForGaiaPageEvent("ready");
+  CreateGaiaPageEventWaiter("ready")->Wait();
 }
 
 void OobeBaseTest::WaitForGaiaPageBackButtonUpdate() {
-  WaitForGaiaPageEvent("backButton");
+  CreateGaiaPageEventWaiter("backButton")->Wait();
 }
 
-void OobeBaseTest::WaitForGaiaPageEvent(const std::string& event) {
-  // Starts listening to message before executing the JS code that generates
-  // the message below.
-  content::DOMMessageQueue message_queue;
-  std::string js =
-      R"((function() {
-            var authenticator = $AuthenticatorId;
-            var f = function() {
-              authenticator.removeEventListener('$Event', f);
-              window.domAutomationController.send('Done');
-            };
-            authenticator.addEventListener('$Event', f);
-          })();)";
-  base::ReplaceSubstringsAfterOffset(&js, 0, "$AuthenticatorId",
-                                     authenticator_id_);
-  base::ReplaceSubstringsAfterOffset(&js, 0, "$Event", event);
-  test::OobeJS().Evaluate(js);
-
-  std::string message;
-  do {
-    ASSERT_TRUE(message_queue.WaitForMessage(&message));
-  } while (message != "\"Done\"");
+std::unique_ptr<test::TestConditionWaiter>
+OobeBaseTest::CreateGaiaPageEventWaiter(const std::string& event) {
+  return std::make_unique<GaiaPageEventWaiter>(authenticator_id_, event);
 }
 
 void OobeBaseTest::WaitForSigninScreen() {
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.h b/chrome/browser/chromeos/login/test/oobe_base_test.h
index 95bf4001..0b31385 100644
--- a/chrome/browser/chromeos/login/test/oobe_base_test.h
+++ b/chrome/browser/chromeos/login/test/oobe_base_test.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <string>
 
+#include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "chrome/browser/chromeos/login/test/embedded_test_server_mixin.h"
 #include "chrome/browser/chromeos/login/test/js_checker.h"
@@ -57,7 +58,8 @@
   void WaitForGaiaPageLoadAndPropertyUpdate();
   void WaitForGaiaPageReload();
   void WaitForGaiaPageBackButtonUpdate();
-  void WaitForGaiaPageEvent(const std::string& event);
+  WARN_UNUSED_RESULT std::unique_ptr<test::TestConditionWaiter>
+  CreateGaiaPageEventWaiter(const std::string& event);
   void WaitForSigninScreen();
   void CheckJsExceptionErrors(int number);
   test::JSChecker SigninFrameJS();
diff --git a/chrome/browser/chromeos/login/ui/simple_web_view_dialog.cc b/chrome/browser/chromeos/login/ui/simple_web_view_dialog.cc
index ef0e87a..ca1c96a 100644
--- a/chrome/browser/chromeos/login/ui/simple_web_view_dialog.cc
+++ b/chrome/browser/chromeos/login/ui/simple_web_view_dialog.cc
@@ -191,8 +191,7 @@
   location_bar_ = location_bar.get();
 
   // Reload button.
-  auto reload = std::make_unique<ReloadButton>(
-      command_updater_.get(), ReloadButton::IconStyle::kBrowser);
+  auto reload = std::make_unique<ReloadButton>(command_updater_.get());
   reload->set_triggerable_event_flags(ui::EF_LEFT_MOUSE_BUTTON |
                                       ui::EF_MIDDLE_MOUSE_BUTTON);
   reload->set_tag(IDC_RELOAD);
diff --git a/chrome/browser/chromeos/login/webview_login_browsertest.cc b/chrome/browser/chromeos/login/webview_login_browsertest.cc
index 0017a4c..1fd75fc1 100644
--- a/chrome/browser/chromeos/login/webview_login_browsertest.cc
+++ b/chrome/browser/chromeos/login/webview_login_browsertest.cc
@@ -397,18 +397,22 @@
   ExpectIdentifierPage();
 
   // Move to password page.
+  auto back_button_waiter = CreateGaiaPageEventWaiter("backButton");
   SigninFrameJS().TypeIntoPath(FakeGaiaMixin::kFakeUserEmail, {"identifier"});
   test::OobeJS().ClickOnPath(kPrimaryButton);
-  WaitForGaiaPageBackButtonUpdate();
+  back_button_waiter->Wait();
   ExpectPasswordPage();
 
   // Click back to identifier page.
+  back_button_waiter = CreateGaiaPageEventWaiter("backButton");
   test::OobeJS().ClickOnPath({"gaia-signin", "signin-back-button"});
-  WaitForGaiaPageBackButtonUpdate();
+  back_button_waiter->Wait();
   ExpectIdentifierPage();
+
+  back_button_waiter = CreateGaiaPageEventWaiter("backButton");
   // Click next to password page, user id is remembered.
   test::OobeJS().ClickOnPath(kPrimaryButton);
-  WaitForGaiaPageBackButtonUpdate();
+  back_button_waiter->Wait();
   ExpectPasswordPage();
 
   // Finish sign-up.
diff --git a/chrome/browser/download/android/intercept_oma_download_navigation_throttle.cc b/chrome/browser/download/android/intercept_oma_download_navigation_throttle.cc
index d218ff0d..dffd9550 100644
--- a/chrome/browser/download/android/intercept_oma_download_navigation_throttle.cc
+++ b/chrome/browser/download/android/intercept_oma_download_navigation_throttle.cc
@@ -13,7 +13,7 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
-#include "third_party/blink/public/mojom/referrer.mojom.h"
+#include "third_party/blink/public/mojom/loader/referrer.mojom.h"
 
 using content::BrowserThread;
 
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 20cfc30..e13957d 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -1009,6 +1009,11 @@
     "expiry_milestone": 90
   },
   {
+    "name": "edit-passwords-in-settings",
+    "owners": [ "irfedorova", "jdoerrie" ],
+    "expiry_milestone": 88
+  },
+  {
     "name": "elastic-overscroll-win",
     "owners": [ "arakeri@microsoft.com" ],
     "expiry_milestone": 90
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index b111934..3f72c12 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -3025,6 +3025,10 @@
 
 #else  // !defined(OS_ANDROID)
 
+const char kEditPasswordsInDesktopSettingsName[] = "Edit passwords in settings";
+const char kEditPasswordsInDesktopSettingsDescription[] =
+    "Enables password editing in settings.";
+
 const char kEnableAccessibilityLiveCaptionsName[] = "Live Captions";
 const char kEnableAccessibilityLiveCaptionsDescription[] =
     "Enables the live captions feature which generates captions for "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 64aa7cd3..d287a982 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1736,6 +1736,9 @@
 
 #else  // !defined(OS_ANDROID)
 
+extern const char kEditPasswordsInDesktopSettingsName[];
+extern const char kEditPasswordsInDesktopSettingsDescription[];
+
 extern const char kEnableAccessibilityLiveCaptionsName[];
 extern const char kEnableAccessibilityLiveCaptionsDescription[];
 
diff --git a/chrome/browser/history/history_tab_helper.cc b/chrome/browser/history/history_tab_helper.cc
index a637974c..94af992 100644
--- a/chrome/browser/history/history_tab_helper.cc
+++ b/chrome/browser/history/history_tab_helper.cc
@@ -24,7 +24,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_delegate.h"
 #include "content/public/common/frame_navigate_params.h"
-#include "third_party/blink/public/mojom/referrer.mojom.h"
+#include "third_party/blink/public/mojom/loader/referrer.mojom.h"
 #include "ui/base/page_transition_types.h"
 
 #if defined(OS_ANDROID)
diff --git a/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc
index ab1569f..0417129f 100644
--- a/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc
+++ b/chrome/browser/lookalikes/lookalike_url_navigation_throttle.cc
@@ -35,7 +35,7 @@
 #include "components/url_formatter/spoof_checks/top_domains/top500_domains.h"
 #include "components/url_formatter/spoof_checks/top_domains/top_domain_util.h"
 #include "content/public/browser/navigation_handle.h"
-#include "third_party/blink/public/mojom/referrer.mojom.h"
+#include "third_party/blink/public/mojom/loader/referrer.mojom.h"
 
 namespace {
 
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc
index c4f985ba9..c6b695a 100644
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc
@@ -47,8 +47,6 @@
 #include "third_party/blink/public/mojom/devtools/inspector_issue.mojom-shared.h"
 #include "third_party/blink/public/mojom/web_feature/web_feature.mojom.h"
 #include "ui/base/page_transition_types.h"
-#include "ui/gfx/geometry/point.h"
-#include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 #include "url/gurl.h"
 
@@ -335,7 +333,6 @@
 
     if (should_ignore_detected_ad &&
         (ad_id == previous_data->root_frame_tree_node_id())) {
-      page_ad_density_tracker_.RemoveRect(id_and_data->first);
       ad_frames_data_storage_.erase(id_and_data->second);
       ad_frames_data_.erase(id_and_data);
 
@@ -556,35 +553,6 @@
     ancestor_data->set_media_status(FrameData::MediaStatus::kPlayed);
 }
 
-void AdsPageLoadMetricsObserver::OnFrameIntersectionUpdate(
-    content::RenderFrameHost* render_frame_host,
-    const page_load_metrics::mojom::FrameIntersectionUpdate&
-        intersection_update) {
-  if (!intersection_update.main_frame_intersection_rect)
-    return;
-
-  int frame_tree_node_id = render_frame_host->GetFrameTreeNodeId();
-  if (render_frame_host == GetDelegate().GetWebContents()->GetMainFrame()) {
-    page_ad_density_tracker_.UpdateMainFrameRect(
-        *intersection_update.main_frame_intersection_rect);
-    return;
-  }
-
-  // If the frame whose size has changed is the root of the ad ancestry chain,
-  // then update it.
-  FrameData* ancestor_data = FindFrameData(frame_tree_node_id);
-  if (ancestor_data &&
-      frame_tree_node_id == ancestor_data->root_frame_tree_node_id()) {
-    page_ad_density_tracker_.RemoveRect(frame_tree_node_id);
-    // Only add frames if they are visible.
-    if (!ancestor_data->is_display_none()) {
-      page_ad_density_tracker_.AddRect(
-          frame_tree_node_id,
-          *intersection_update.main_frame_intersection_rect);
-    }
-  }
-}
-
 void AdsPageLoadMetricsObserver::OnFrameDeleted(
     content::RenderFrameHost* render_frame_host) {
   if (!render_frame_host)
@@ -610,7 +578,6 @@
     ancestor_data->RecordAdFrameLoadUkmEvent(GetDelegate().GetSourceId());
     DCHECK(id_and_data->second != ad_frames_data_storage_.end());
     ad_frames_data_storage_.erase(id_and_data->second);
-    page_ad_density_tracker_.RemoveRect(id_and_data->first);
   }
 
   // Delete this frame's entry from the map now that the store is deleted.
@@ -741,24 +708,6 @@
     return;
   PAGE_BYTES_HISTOGRAM("PageLoad.Clients.Ads.Resources.Bytes.Ads2",
                        aggregate_frame_data_->ad_network_bytes());
-
-  if (page_ad_density_tracker_.MaxPageAdDensityByArea() != -1) {
-    UMA_HISTOGRAM_PERCENTAGE("PageLoad.Clients.Ads.AdDensity.MaxPercentByArea",
-                             page_ad_density_tracker_.MaxPageAdDensityByArea());
-  }
-
-  if (page_ad_density_tracker_.MaxPageAdDensityByHeight() != -1) {
-    UMA_HISTOGRAM_PERCENTAGE(
-        "PageLoad.Clients.Ads.AdDensity.MaxPercentByHeight",
-        page_ad_density_tracker_.MaxPageAdDensityByHeight());
-  }
-
-  // Records true if both of the density calculations succeeded on the page.
-  UMA_HISTOGRAM_BOOLEAN(
-      "PageLoad.Clients.Ads.AdDensity.Recorded",
-      page_ad_density_tracker_.MaxPageAdDensityByArea() != -1 &&
-          page_ad_density_tracker_.MaxPageAdDensityByHeight() != -1);
-
   auto* ukm_recorder = ukm::UkmRecorder::Get();
   ukm::builders::AdPageLoad builder(source_id);
   builder.SetTotalBytes(aggregate_frame_data_->network_bytes() >> 10)
@@ -770,10 +719,7 @@
                            FrameData::ResourceMimeType::kVideo) >>
                        10)
       .SetMainframeAdBytes(ukm::GetExponentialBucketMinForBytes(
-          main_frame_data_->ad_network_bytes()))
-      .SetMaxAdDensityByArea(page_ad_density_tracker_.MaxPageAdDensityByArea())
-      .SetMaxAdDensityByHeight(
-          page_ad_density_tracker_.MaxPageAdDensityByHeight());
+          main_frame_data_->ad_network_bytes()));
 
   // Record cpu metrics for the page.
   builder.SetAdCpuTime(
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.h
index 07483ca9..66c9785 100644
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.h
@@ -14,7 +14,6 @@
 #include "base/scoped_observer.h"
 #include "base/time/tick_clock.h"
 #include "chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.h"
-#include "chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker.h"
 #include "components/page_load_metrics/browser/page_load_metrics_observer.h"
 #include "components/page_load_metrics/common/page_load_metrics.mojom-forward.h"
 #include "components/subresource_filter/content/browser/subresource_filter_observer.h"
@@ -121,10 +120,6 @@
   void MediaStartedPlaying(
       const content::WebContentsObserver::MediaPlayerInfo& video_type,
       content::RenderFrameHost* render_frame_host) override;
-  void OnFrameIntersectionUpdate(
-      content::RenderFrameHost* render_frame_host,
-      const page_load_metrics::mojom::FrameIntersectionUpdate&
-          intersection_update) override;
   void OnFrameDeleted(content::RenderFrameHost* render_frame_host) override;
 
   void SetHeavyAdThresholdNoiseProviderForTesting(
@@ -275,9 +270,6 @@
   std::unique_ptr<HeavyAdThresholdNoiseProvider>
       heavy_ad_threshold_noise_provider_;
 
-  // The maximum ad density measurements for the page during it's lifecycle.
-  PageAdDensityTracker page_ad_density_tracker_;
-
   DISALLOW_COPY_AND_ASSIGN(AdsPageLoadMetricsObserver);
 };
 
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc
index 166fc78c..8231fe19 100644
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc
+++ b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc
@@ -83,15 +83,6 @@
 const char kHeavyAdInterventionTypeHistogramId[] =
     "PageLoad.Clients.Ads.HeavyAds.InterventionType2";
 
-const char kMaxAdDensityByAreaHistogramId[] =
-    "PageLoad.Clients.Ads.AdDensity.MaxPercentByArea";
-
-const char kMaxAdDensityByHeightHistogramId[] =
-    "PageLoad.Clients.Ads.AdDensity.MaxPercentByHeight";
-
-const char kMaxAdDensityRecordedHistogramId[] =
-    "PageLoad.Clients.Ads.AdDensity.Recorded";
-
 const char kHttpOkResponseHeader[] =
     "HTTP/1.1 200 OK\r\n"
     "Content-Type: text/html; charset=utf-8\r\n"
@@ -246,244 +237,6 @@
       static_cast<int>(FrameData::OriginStatus::kCross));
 }
 
-// Verifies that the page ad density records the maximum value during
-// a page's lifecycling by creating a large ad frame, destroying it, and
-// creating a smaller iframe. The ad density recorded is the density with
-// the first larger frame.
-IN_PROC_BROWSER_TEST_F(AdsPageLoadMetricsObserverBrowserTest,
-                       PageAdDensityRecordsPageMax) {
-  base::HistogramTester histogram_tester;
-  ukm::TestAutoSetUkmRecorder ukm_recorder;
-  auto waiter = CreatePageLoadMetricsTestWaiter();
-  content::WebContents* web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-
-  // Evaluate the height and width of the page as the browser_test can
-  // vary the dimensions.
-  int document_height =
-      EvalJs(web_contents, "document.body.scrollHeight").ExtractInt();
-  int document_width =
-      EvalJs(web_contents, "document.body.scrollWidth").ExtractInt();
-
-  // Expectation is before NavigateToUrl for this test as the expectation can be
-  // met after NavigateToUrl and before the Wait.
-  waiter->AddMainFrameIntersectionExpectation(
-      gfx::Rect(0, 0, document_width,
-                document_height));  // Initial main frame rect.
-  ui_test_utils::NavigateToURL(
-      browser(), embedded_test_server()->GetURL(
-                     "a.com", "/ads_observer/blank_with_adiframe_writer.html"));
-  waiter->Wait();
-  web_contents = browser()->tab_strip_model()->GetActiveWebContents();
-
-  // Create a frame at 100,100 of size 200,200.
-  waiter->AddMainFrameIntersectionExpectation(gfx::Rect(100, 100, 200, 200));
-
-  // Create the frame with b.com as origin to not get caught by
-  // restricted ad tagging.
-  EXPECT_TRUE(ExecJs(
-      web_contents,
-      content::JsReplace(
-          "let frame = createAdIframeAtRect(100, 100, 200, 200); "
-          "frame.src = $1; ",
-          embedded_test_server()->GetURL("b.com", "/ads_observer/pixel.png"))));
-  waiter->Wait();
-
-  // Load should stop before we remove the frame.
-  EXPECT_TRUE(WaitForLoadStop(web_contents));
-  EXPECT_TRUE(ExecJs(web_contents,
-                     "let frames = document.getElementsByTagName('iframe'); "
-                     "frames[0].remove(); "));
-  waiter->AddMainFrameIntersectionExpectation(gfx::Rect(400, 400, 10, 10));
-
-  // Delete the frame and create a new frame at 400,400 of size 10x10. The
-  // ad density resulting from this frame is lower than the 200x200.
-  EXPECT_TRUE(ExecJs(
-      web_contents,
-      content::JsReplace("let frame = createAdIframeAtRect(400, 400, 10, 10); "
-                         "frame.src = $1; ",
-                         embedded_test_server()
-                             ->GetURL("b.com", "/ads_observer/pixel.png")
-                             .spec())));
-  waiter->Wait();
-
-  // Evaluate the height and width of the page as the browser_test can
-  // vary the dimensions.
-  document_height =
-      EvalJs(web_contents, "document.body.scrollHeight").ExtractInt();
-  document_width =
-      EvalJs(web_contents, "document.body.scrollWidth").ExtractInt();
-
-  int page_area = document_width * document_height;
-  int ad_area = 200 * 200;  // The area of the first larger ad iframe.
-  int expected_page_density_area = ad_area * 100 / page_area;
-  int expected_page_density_height = 200 * 100 / document_height;
-
-  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
-
-  histogram_tester.ExpectUniqueSample(kMaxAdDensityByAreaHistogramId,
-                                      expected_page_density_area, 1);
-  histogram_tester.ExpectUniqueSample(kMaxAdDensityByHeightHistogramId,
-                                      expected_page_density_height, 1);
-  histogram_tester.ExpectUniqueSample(kMaxAdDensityRecordedHistogramId, true,
-                                      1);
-  auto entries =
-      ukm_recorder.GetEntriesByName(ukm::builders::AdPageLoad::kEntryName);
-  EXPECT_EQ(1u, entries.size());
-  ukm_recorder.ExpectEntryMetric(
-      entries.front(), ukm::builders::AdPageLoad::kMaxAdDensityByAreaName,
-      expected_page_density_area);
-  ukm_recorder.ExpectEntryMetric(
-      entries.front(), ukm::builders::AdPageLoad::kMaxAdDensityByHeightName,
-      expected_page_density_height);
-}
-
-// Creates multiple overlapping frames and verifies the page ad density.
-IN_PROC_BROWSER_TEST_F(AdsPageLoadMetricsObserverBrowserTest,
-                       PageAdDensityMultipleFrames) {
-  base::HistogramTester histogram_tester;
-  ukm::TestAutoSetUkmRecorder ukm_recorder;
-  auto waiter = CreatePageLoadMetricsTestWaiter();
-  content::WebContents* web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-
-  int document_height =
-      EvalJs(web_contents, "document.body.scrollHeight").ExtractInt();
-  int document_width =
-      EvalJs(web_contents, "document.body.scrollWidth").ExtractInt();
-
-  // Expectation is before NavigateToUrl for this test as the expectation can be
-  // met after NavigateToUrl and before the Wait.
-  waiter->AddMainFrameIntersectionExpectation(
-      gfx::Rect(0, 0, document_width,
-                document_height));  // Initial main frame rect.
-
-  ui_test_utils::NavigateToURL(
-      browser(), embedded_test_server()->GetURL(
-                     "a.com", "/ads_observer/blank_with_adiframe_writer.html"));
-  waiter->Wait();
-  web_contents = browser()->tab_strip_model()->GetActiveWebContents();
-
-  // Create a frame of size 400,400 at 100,100.
-  waiter->AddMainFrameIntersectionExpectation(gfx::Rect(400, 400, 100, 100));
-
-  // Create the frame with b.com as origin to not get caught by
-  // restricted ad tagging.
-  EXPECT_TRUE(ExecJs(
-      web_contents, content::JsReplace(
-                        "let frame = createAdIframeAtRect(400, 400, 100, 100); "
-                        "frame.src = $1",
-                        embedded_test_server()
-                            ->GetURL("b.com", "/ads_observer/pixel.png")
-                            .spec())));
-
-  waiter->Wait();
-
-  // Create a frame at of size 200,200 at 450,450.
-  waiter->AddMainFrameIntersectionExpectation(gfx::Rect(450, 450, 200, 200));
-  EXPECT_TRUE(ExecJs(
-      web_contents, content::JsReplace(
-                        "let frame = createAdIframeAtRect(450, 450, 200, 200); "
-                        "frame.src = $1",
-                        embedded_test_server()
-                            ->GetURL("b.com", "/ads_observer/pixel.png")
-                            .spec())));
-  waiter->Wait();
-
-  // Evaluate the height and width of the page as the browser_test can
-  // vary the dimensions.
-  document_height =
-      EvalJs(web_contents, "document.body.scrollHeight").ExtractInt();
-  document_width =
-      EvalJs(web_contents, "document.body.scrollWidth").ExtractInt();
-
-  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
-
-  int page_area = document_width * document_height;
-  // The area of the two iframes minus the area of the overlapping section.
-  int ad_area = 100 * 100 + 200 * 200 - 50 * 50;
-  int expected_page_density_area = ad_area * 100 / page_area;
-  int expected_page_density_height = 250 * 100 / document_height;
-
-  histogram_tester.ExpectUniqueSample(kMaxAdDensityByAreaHistogramId,
-                                      expected_page_density_area, 1);
-  histogram_tester.ExpectUniqueSample(kMaxAdDensityByHeightHistogramId,
-                                      expected_page_density_height, 1);
-  histogram_tester.ExpectUniqueSample(kMaxAdDensityRecordedHistogramId, true,
-                                      1);
-  auto entries =
-      ukm_recorder.GetEntriesByName(ukm::builders::AdPageLoad::kEntryName);
-  EXPECT_EQ(1u, entries.size());
-  ukm_recorder.ExpectEntryMetric(
-      entries.front(), ukm::builders::AdPageLoad::kMaxAdDensityByAreaName,
-      expected_page_density_area);
-  ukm_recorder.ExpectEntryMetric(
-      entries.front(), ukm::builders::AdPageLoad::kMaxAdDensityByHeightName,
-      expected_page_density_height);
-}
-
-// Creates a frame with display:none styling and verifies that it has an
-// empty intersection with the main frame.
-IN_PROC_BROWSER_TEST_F(AdsPageLoadMetricsObserverBrowserTest,
-                       PageAdDensityIgnoreDisplayNoneFrame) {
-  base::HistogramTester histogram_tester;
-  ukm::TestAutoSetUkmRecorder ukm_recorder;
-  auto waiter = CreatePageLoadMetricsTestWaiter();
-  content::WebContents* web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-
-  // Evaluate the height and width of the page as the browser_test can
-  // vary the dimensions.
-  int document_height =
-      EvalJs(web_contents, "document.body.scrollHeight").ExtractInt();
-  int document_width =
-      EvalJs(web_contents, "document.body.scrollWidth").ExtractInt();
-
-  // Expectation is before NavigateToUrl for this test as the expectation can be
-  // met after NavigateToUrl and before the Wait.
-  waiter->AddMainFrameIntersectionExpectation(
-      gfx::Rect(0, 0, document_width,
-                document_height));  // Initial main frame rect.
-
-  ui_test_utils::NavigateToURL(
-      browser(), embedded_test_server()->GetURL(
-                     "a.com", "/ads_observer/blank_with_adiframe_writer.html"));
-  waiter->Wait();
-  web_contents = browser()->tab_strip_model()->GetActiveWebContents();
-
-  // Create a frame at 100,100 of size 200,200. The expectation is an empty rect
-  // as the frame is display:none and as a result has no main frame
-  // intersection.
-  waiter->AddMainFrameIntersectionExpectation(gfx::Rect(0, 0, 0, 0));
-
-  // Create the frame with b.com as origin to not get caught by
-  // restricted ad tagging.
-  EXPECT_TRUE(ExecJs(
-      web_contents, content::JsReplace(
-                        "let frame = createAdIframeAtRect(100, 100, 200, 200); "
-                        "frame.src = $1; "
-                        "frame.style.display = \"none\";",
-                        embedded_test_server()
-                            ->GetURL("b.com", "/ads_observer/pixel.png")
-                            .spec())));
-
-  waiter->Wait();
-
-  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
-
-  histogram_tester.ExpectUniqueSample(kMaxAdDensityByAreaHistogramId, 0, 1);
-  histogram_tester.ExpectUniqueSample(kMaxAdDensityByHeightHistogramId, 0, 1);
-  histogram_tester.ExpectUniqueSample(kMaxAdDensityRecordedHistogramId, true,
-                                      1);
-  auto entries =
-      ukm_recorder.GetEntriesByName(ukm::builders::AdPageLoad::kEntryName);
-  EXPECT_EQ(1u, entries.size());
-  ukm_recorder.ExpectEntryMetric(
-      entries.front(), ukm::builders::AdPageLoad::kMaxAdDensityByAreaName, 0);
-  ukm_recorder.ExpectEntryMetric(
-      entries.front(), ukm::builders::AdPageLoad::kMaxAdDensityByHeightName, 0);
-}
-
 // Each CreativeOriginStatus* browser test inputs a pointer to a frame object
 // representing the frame tree path of a website with with a (possibly null)
 // ad subframe, which itself may have linearly nested subframes.
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.h b/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.h
index 8f1000e..4fd6937 100644
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.h
+++ b/chrome/browser/page_load_metrics/observers/ad_metrics/frame_data.h
@@ -238,8 +238,6 @@
 
   gfx::Size frame_size() const { return frame_size_; }
 
-  bool is_display_none() const { return is_display_none_; }
-
   MediaStatus media_status() const { return media_status_; }
 
   void set_media_status(MediaStatus media_status) {
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker.cc
deleted file mode 100644
index 4daffc7..0000000
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker.cc
+++ /dev/null
@@ -1,297 +0,0 @@
-// Copyright 2020 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/page_load_metrics/observers/ad_metrics/page_ad_density_tracker.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/numerics/checked_math.h"
-#include "base/optional.h"
-
-namespace {
-
-// Calculates the combined length of a set of line segments. This counts
-// each overlapping area a single time and does not include areas where there
-// is no line segment.
-//
-// TODO(https://crbug.com/1068586): Optimize segment length calculation.
-// AddSegment and RemoveSegment are both logarithmic operations, making this
-// linearithmic with the number of segments. However the expected number
-// of segments at any given time in the density calculation is low.
-class SegmentLength {
- public:
-  // An event to process corresponding to the left or right point of each
-  // line segment.
-  struct SegmentEvent {
-    SegmentEvent(int segment_id, int pos, bool is_segment_start)
-        : segment_id(segment_id),
-          pos(pos),
-          is_segment_start(is_segment_start) {}
-    SegmentEvent(const SegmentEvent& other) = default;
-
-    // Tiebreak with position with |is_segment_start| and |segment_id|.
-    bool operator<(const SegmentEvent& rhs) const {
-      if (pos == rhs.pos) {
-        if (segment_id == rhs.segment_id) {
-          return is_segment_start != rhs.is_segment_start;
-        } else {
-          return segment_id < rhs.segment_id;
-        }
-      } else {
-        return pos < rhs.pos;
-      }
-    }
-
-    int segment_id;
-    int pos;
-    bool is_segment_start;
-  };
-
-  // Iterators into the set of segment events for efficient removal of
-  // segment events by segment_id. Maintained by |segment_event_iterators_|.
-  struct SegmentEventSetIterators {
-    SegmentEventSetIterators(std::set<SegmentEvent>::iterator start,
-                             std::set<SegmentEvent>::iterator end)
-        : start_it(start), end_it(end) {}
-
-    SegmentEventSetIterators(const SegmentEventSetIterators& other) = default;
-
-    std::set<SegmentEvent>::const_iterator start_it;
-    std::set<SegmentEvent>::const_iterator end_it;
-  };
-
-  SegmentLength() = default;
-  ~SegmentLength() = default;
-
-  // Add a line segment to the set of active line segments, the segment
-  // corresponds to the bottom or top of a rect.
-  void AddSegment(int segment_id, int start, int end) {
-    // Safe as insert will never return an invalid iterator, it will
-    // point to the existing element if already in the set.
-    auto start_it =
-        active_segments_
-            .insert(SegmentEvent(segment_id, start, true /*is_segment_start*/))
-            .first;
-    auto end_it =
-        active_segments_
-            .insert(SegmentEvent(segment_id, end, false /*is_segment_start*/))
-            .first;
-
-    segment_event_iterators_.emplace(
-        segment_id, SegmentEventSetIterators(start_it, end_it));
-  }
-
-  // Remove a segment from the set of active line segmnets.
-  void RemoveSegment(int segment_id) {
-    auto it = segment_event_iterators_.find(segment_id);
-    DCHECK(it != segment_event_iterators_.end());
-
-    const SegmentEventSetIterators& set_its = it->second;
-    active_segments_.erase(set_its.start_it);
-    active_segments_.erase(set_its.end_it);
-    segment_event_iterators_.erase(segment_id);
-  }
-
-  // Calculate the combined length of segments in the active set of segments by
-  // iterating over the the sorted set of segment events.
-  base::Optional<int> Length() {
-    base::CheckedNumeric<int> length = 0;
-    int last_event_pos = -1;
-    int num_active = 0;
-    for (const auto& segment_event : active_segments_) {
-      if (last_event_pos == -1) {
-        DCHECK(segment_event.is_segment_start);
-        last_event_pos = segment_event.pos;
-      }
-
-      if (num_active > 0)
-        length += segment_event.pos - last_event_pos;
-
-      last_event_pos = segment_event.pos;
-      if (segment_event.is_segment_start) {
-        num_active += 1;
-      } else {
-        num_active -= 1;
-      }
-    }
-
-    base::Optional<int> total_length;
-    if (length.IsValid())
-      total_length = length.ValueOrDie();
-
-    return total_length;
-  }
-
- private:
-  std::set<SegmentEvent> active_segments_;
-
-  // Map from the segment_id passed by user to the Segment struct.
-  std::unordered_map<int, SegmentEventSetIterators> segment_event_iterators_;
-
-  DISALLOW_COPY_AND_ASSIGN(SegmentLength);
-};
-
-}  // namespace
-
-PageAdDensityTracker::RectEvent::RectEvent(int id,
-                                           bool is_bottom,
-                                           const gfx::Rect& rect)
-    : rect_id(id), is_bottom(is_bottom), rect(rect) {}
-
-PageAdDensityTracker::RectEvent::RectEvent(const RectEvent& other) = default;
-
-PageAdDensityTracker::RectEventSetIterators::RectEventSetIterators(
-    std::set<RectEvent>::iterator top,
-    std::set<RectEvent>::iterator bottom)
-    : top_it(top), bottom_it(bottom) {}
-
-PageAdDensityTracker::RectEventSetIterators::RectEventSetIterators(
-    const RectEventSetIterators& other) = default;
-
-PageAdDensityTracker::PageAdDensityTracker() = default;
-
-PageAdDensityTracker::~PageAdDensityTracker() = default;
-
-int PageAdDensityTracker::MaxPageAdDensityByHeight() {
-  return max_page_ad_density_by_height_;
-}
-
-int PageAdDensityTracker::MaxPageAdDensityByArea() {
-  return max_page_ad_density_by_area_;
-}
-
-void PageAdDensityTracker::AddRect(int rect_id, const gfx::Rect& rect) {
-  // Check that we do not already have rect events for the rect.
-  DCHECK(rect_events_iterators_.find(rect_id) == rect_events_iterators_.end());
-
-  // We do not track empty rects.
-  if (rect.IsEmpty())
-    return;
-
-  // Limit the maximum number of rects tracked to 50 due to poor worst
-  // case performance.
-  const int kMaxRectsTracked = 50;
-  if (rect_events_iterators_.size() > kMaxRectsTracked)
-    return;
-
-  auto top_it =
-      rect_events_.insert(RectEvent(rect_id, true /*is_bottom*/, rect)).first;
-  auto bottom_it =
-      rect_events_.insert(RectEvent(rect_id, false /*is_bottom*/, rect)).first;
-  rect_events_iterators_.emplace(rect_id,
-                                 RectEventSetIterators(top_it, bottom_it));
-
-  // TODO(https://crbug.com/1068586): Improve performance by adding additional
-  // throttling to only calculate when max density can decrease (frame deleted
-  // or moved).
-  CalculateDensity();
-}
-
-void PageAdDensityTracker::RemoveRect(int rect_id) {
-  auto it = rect_events_iterators_.find(rect_id);
-
-  if (it == rect_events_iterators_.end())
-    return;
-
-  const RectEventSetIterators& set_its = it->second;
-  rect_events_.erase(set_its.top_it);
-  rect_events_.erase(set_its.bottom_it);
-  rect_events_iterators_.erase(rect_id);
-}
-
-void PageAdDensityTracker::UpdateMainFrameRect(const gfx::Rect& rect) {
-  if (!last_main_frame_size_ || rect != *last_main_frame_size_) {
-    last_main_frame_size_ = rect;
-    CalculateDensity();
-  }
-}
-
-// Ad density measurement uses a modified Bentley's Algorithm, the high level
-// approach is described on: http://jeffe.cs.illinois.edu/open/klee.html.
-void PageAdDensityTracker::CalculateDensity() {
-  // Cannot calculate density if there is no main frame rect.
-  if (!last_main_frame_size_)
-    return;
-
-  SegmentLength segment_length_tracker;
-
-  int last_y = -1;
-  base::CheckedNumeric<int> total_area = 0;
-  base::CheckedNumeric<int> total_height = 0;
-  for (const auto& rect_event : rect_events_) {
-    if (last_y == -1) {
-      DCHECK(rect_event.is_bottom);
-      segment_length_tracker.AddSegment(
-          rect_event.rect_id, rect_event.rect.x(),
-          rect_event.rect.x() + rect_event.rect.width());
-      last_y =
-          rect_event.is_bottom ? rect_event.rect.bottom() : rect_event.rect.y();
-    }
-
-    int current_y =
-        rect_event.is_bottom ? rect_event.rect.bottom() : rect_event.rect.y();
-    DCHECK_LE(current_y, last_y);
-
-    // If the segment length value is invalid, skip this ad density calculation.
-    base::Optional<int> segment_length = segment_length_tracker.Length();
-    if (!segment_length)
-      return;
-
-    // Check that the segment length multiplied by the height of the block
-    // does not overflow an int.
-    base::CheckedNumeric<int> current_area = *segment_length;
-    current_area *= (last_y - current_y);
-    if (!current_area.IsValid())
-      return;
-
-    total_area += *segment_length * (last_y - current_y);
-
-    if (*segment_length > 0)
-      total_height += (last_y - current_y);
-
-    // As we are iterating from the bottom of the page to the top, add segments
-    // when we see the start (bottom) of a new rect.
-    if (rect_event.is_bottom) {
-      segment_length_tracker.AddSegment(
-          rect_event.rect_id, rect_event.rect.x(),
-          rect_event.rect.x() + rect_event.rect.width());
-    } else {
-      segment_length_tracker.RemoveSegment(rect_event.rect_id);
-    }
-    last_y = current_y;
-  }
-
-  // If the measured height or area is invalid, skip recording this ad density
-  // calculation.
-  if (!total_height.IsValid() || !total_area.IsValid())
-    return;
-
-  base::CheckedNumeric<int> ad_density_by_height =
-      total_height * 100 / last_main_frame_size_->height();
-  if (ad_density_by_height.IsValid() &&
-      ad_density_by_height.ValueOrDie() > max_page_ad_density_by_height_)
-    max_page_ad_density_by_height_ = ad_density_by_height.ValueOrDie();
-
-  // Invalidate the check numeric if the checked area is invalid.
-  base::CheckedNumeric<int> ad_density_by_area =
-      total_area * 100 /
-      (last_main_frame_size_->size().GetCheckedArea().ValueOrDefault(0));
-  if (ad_density_by_area.IsValid() &&
-      ad_density_by_area.ValueOrDie() > max_page_ad_density_by_area_)
-    max_page_ad_density_by_area_ = ad_density_by_area.ValueOrDie();
-}
-
-bool PageAdDensityTracker::RectEvent::operator<(const RectEvent& rhs) const {
-  int lhs_y = is_bottom ? rect.bottom() : rect.y();
-  int rhs_y = rhs.is_bottom ? rhs.rect.bottom() : rhs.rect.y();
-
-  // Tiebreak with |rect_id| and |is_bottom|.
-  if (lhs_y == rhs_y) {
-    if (rect_id == rhs.rect_id) {
-      return is_bottom == rhs.is_bottom;
-    } else {
-      return rect_id < rhs.rect_id;
-    }
-  } else {
-    return lhs_y > rhs_y;
-  }
-}
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker.h b/chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker.h
deleted file mode 100644
index b2f013d..0000000
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2020 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_PAGE_LOAD_METRICS_OBSERVERS_AD_METRICS_PAGE_AD_DENSITY_TRACKER_H_
-#define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_AD_METRICS_PAGE_AD_DENSITY_TRACKER_H_
-
-#include <set>
-#include <unordered_map>
-
-#include "base/optional.h"
-#include "ui/gfx/geometry/rect.h"
-
-// Tracks the ad density of a page through the page's lifecycle.
-// It has the following usage:
-//    1. Set subframe and mainframe rects using subframe and mainframe rect
-//        operations (AddRect, RemoveRect, UpdateMainFrameRect).
-//    2. Once a page has a main frame rect, get current density using
-//        DensityByHeight or DensityByArea.
-class PageAdDensityTracker {
- public:
-  PageAdDensityTracker();
-  ~PageAdDensityTracker();
-
-  PageAdDensityTracker(const PageAdDensityTracker&) = delete;
-  PageAdDensityTracker& operator=(const PageAdDensityTracker&) = delete;
-
-  // Operations to track sub frame rects in the page density calcluation.
-  void AddRect(int rect_id, const gfx::Rect& rect);
-
-  // Removes a rect from the tracker if it is currently being tracked.
-  // Otherwise RemoveRect is a no op.
-  void RemoveRect(int rect_id);
-
-  // Operations to track the main frame dimensions. The main frame rect has to
-  // be set to calculate density.
-  void UpdateMainFrameRect(const gfx::Rect& rect);
-
-  // Returns the density by height, as a value from 0-100. If the density
-  // calculation fails (i.e. no main frame size), this returns -1. Percentage
-  // density by height is calculated as the the combined height of ads divided
-  // by the page's height.
-  int MaxPageAdDensityByHeight();
-
-  // Returns the density by area, as a value from 0-100. If the density
-  // calculation fails (i.e. no main frame size), this returns -1.
-  int MaxPageAdDensityByArea();
-
- private:
-  // An event to process corresponding to the top or bottom of each rect.
-  struct RectEvent {
-    RectEvent(int id, bool is_bottom, const gfx::Rect& rect);
-    RectEvent(const RectEvent& other);
-
-    // A unique identifier set when adding and removing rect events
-    // corresponding to a single rect.
-    int rect_id;
-    bool is_bottom;
-    gfx::Rect rect;
-
-    // RectEvents are sorted by descending y value of the segment associated
-    // with the event.
-    bool operator<(const RectEvent& rhs) const;
-  };
-
-  // Iterators into the set of rect events for efficient removal of
-  // rect events by rect_id. Maintained by |rect_events_iterators_|.
-  struct RectEventSetIterators {
-    RectEventSetIterators(std::set<RectEvent>::iterator top,
-                          std::set<RectEvent>::iterator bottom);
-    RectEventSetIterators(const RectEventSetIterators& other);
-
-    std::set<RectEvent>::const_iterator top_it;
-    std::set<RectEvent>::const_iterator bottom_it;
-  };
-
-  // Calculates the combined area and height of the set of rects, this populates
-  // total_height_ and total_area_.
-  void CalculateDensity();
-
-  // Maintain a sorted set of rect events for use in calculating ad area.
-  std::set<RectEvent> rect_events_;
-
-  // Map from rect_id to iterators of rect events in rect_events_. This allows
-  // efficient removal according to rect_id.
-  std::unordered_map<int, RectEventSetIterators> rect_events_iterators_;
-
-  // Percentage of page ad density as a value from 0-100. These only have
-  // a value of -1 when ad density has not yet been calculated successfully.
-  int max_page_ad_density_by_area_ = -1;
-  int max_page_ad_density_by_height_ = -1;
-
-  base::Optional<gfx::Rect> last_main_frame_size_;
-};
-
-#endif  // CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_AD_METRICS_PAGE_AD_DENSITY_TRACKER_H_"
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker_unittest.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker_unittest.cc
deleted file mode 100644
index 65d92c7..0000000
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker_unittest.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2020 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 <limits>
-
-#include "chrome/browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/geometry/rect.h"
-
-TEST(PageAdDensityTrackerTest, MultipleRects_MaxPageDensityByAreaCalculated) {
-  PageAdDensityTracker tracker;
-
-  // Page ad density is -1 before there is a main frame or subframes.
-  EXPECT_EQ(tracker.MaxPageAdDensityByArea(), -1);
-
-  tracker.UpdateMainFrameRect(gfx::Rect(0, 0, 100, 100));
-  tracker.AddRect(1 /* rect_id */, gfx::Rect(0, 0, 100, 10));
-  EXPECT_EQ(tracker.MaxPageAdDensityByArea(), 10);
-
-  tracker.AddRect(2 /* rect_id */, gfx::Rect(5, 5, 100, 10));
-  EXPECT_EQ(tracker.MaxPageAdDensityByArea(), 15);
-
-  tracker.AddRect(3 /* rect_id */, gfx::Rect(50, 50, 50, 50));
-  EXPECT_EQ(tracker.MaxPageAdDensityByArea(), 40);
-
-  // Removing a rect should not change the maximum ad density.
-  tracker.RemoveRect(3 /* rect_id */);
-  EXPECT_EQ(tracker.MaxPageAdDensityByArea(), 40);
-}
-
-TEST(PageAdDensityTrackerTest, MultipleRects_MaxPageDensityByHeightCalculated) {
-  PageAdDensityTracker tracker;
-
-  // Page ad density is -1 before there is a main frame or subframes.
-  EXPECT_EQ(tracker.MaxPageAdDensityByHeight(), -1);
-
-  tracker.UpdateMainFrameRect(gfx::Rect(0, 0, 100, 100));
-  tracker.AddRect(1 /* rect_id */, gfx::Rect(0, 0, 100, 10));
-  EXPECT_EQ(tracker.MaxPageAdDensityByHeight(), 10);
-
-  tracker.AddRect(2 /* rect_id */, gfx::Rect(5, 5, 100, 10));
-  EXPECT_EQ(tracker.MaxPageAdDensityByHeight(), 15);
-
-  tracker.AddRect(3 /* rect_id */, gfx::Rect(50, 50, 50, 50));
-  EXPECT_EQ(tracker.MaxPageAdDensityByHeight(), 65);
-
-  // Removing a rect should not change the maximum ad density.
-  tracker.RemoveRect(3 /* rect_id */);
-  EXPECT_EQ(tracker.MaxPageAdDensityByHeight(), 65);
-}
-
-// Remove a rect that was added twice, the second RemoveRect is
-// ignored as it is no longer being tracked.
-TEST(PageAdDensityTrackerTest, RemoveRectTwice_SecondRemoveIgnored) {
-  PageAdDensityTracker tracker;
-
-  tracker.AddRect(1 /* rect_id */, gfx::Rect(0, 0, 100, 10));
-  tracker.RemoveRect(1 /* rect_id */);
-  tracker.RemoveRect(1 /* rect_id */);
-}
-
-// Ensures that two rects with the same dimensions hash to different
-// values in the density tracker's frame set.
-TEST(PageAdDensityTrackerTest, SeperateRects_SameDimensions) {
-  PageAdDensityTracker tracker;
-
-  tracker.UpdateMainFrameRect(gfx::Rect(0, 0, 100, 100));
-
-  tracker.AddRect(1 /* rect_id */, gfx::Rect(0, 0, 100, 10));
-  tracker.AddRect(2 /* rect_id */, gfx::Rect(0, 0, 100, 10));
-  EXPECT_EQ(tracker.MaxPageAdDensityByArea(), 10);
-
-  tracker.RemoveRect(1 /* rect_id */);
-  tracker.RemoveRect(2 /* rect_id */);
-  EXPECT_EQ(tracker.MaxPageAdDensityByArea(), 10);
-}
-
-// Create 2 rects whose total area overflow an int.
-TEST(PageAdDensityTrackerTest, OverflowTotalAreaAndHeight) {
-  PageAdDensityTracker tracker;
-
-  tracker.AddRect(1 /* rect_id */, gfx::Rect(std::numeric_limits<int>::min(), 0,
-                                             std::numeric_limits<int>::max(),
-                                             std::numeric_limits<int>::max()));
-  tracker.AddRect(2 /* rect_id */, gfx::Rect(std::numeric_limits<int>::min(),
-                                             std::numeric_limits<int>::max(),
-                                             std::numeric_limits<int>::max(),
-                                             std::numeric_limits<int>::max()));
-
-  // Update main frame rect to force a calculation.
-  tracker.UpdateMainFrameRect(gfx::Rect(0, 0, 100, 100));
-
-  // Density should not be updated as the sum of area
-  // or height overflows.
-  EXPECT_EQ(tracker.MaxPageAdDensityByArea(), -1);
-  EXPECT_EQ(tracker.MaxPageAdDensityByHeight(), -1);
-}
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc
index ac02525..ef6eb82 100644
--- a/chrome/browser/prerender/prerender_browsertest.cc
+++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -70,9 +70,6 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/browsing_data/content/browsing_data_helper.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
-#include "components/omnibox/browser/omnibox_edit_model.h"
-#include "components/omnibox/browser/omnibox_popup_model.h"
-#include "components/omnibox/browser/omnibox_view.h"
 #include "components/page_load_metrics/browser/metrics_web_contents_observer.h"
 #include "components/page_load_metrics/browser/page_load_tracker.h"
 #include "components/page_load_metrics/common/test/page_load_metrics_test_util.h"
@@ -626,12 +623,6 @@
     return display_test_result;
   }
 
-  std::unique_ptr<TestPrerender> ExpectPrerender(
-      FinalStatus expected_final_status) {
-    return prerender_contents_factory()->ExpectPrerenderContents(
-        expected_final_status);
-  }
-
   void AddPrerender(const GURL& url, int index) {
     std::string javascript =
         base::StringPrintf("AddPrerender('%s', %d)", url.spec().c_str(), index);
@@ -986,150 +977,6 @@
                              true)) /* Enable delayed warnings experiment */
 );
 
-// Test interaction of the webNavigation and tabs API with prerender.
-class PrerenderBrowserTestWithExtensions : public PrerenderBrowserTest,
-                                           public extensions::ExtensionApiTest {
- public:
-  PrerenderBrowserTestWithExtensions() {
-    // The individual tests start the test server through ExtensionApiTest, so
-    // the port number can be passed through to the extension.
-    set_autostart_test_server(false);
-  }
-
-  void SetUp() override { PrerenderBrowserTest::SetUp(); }
-
-  void SetUpCommandLine(base::CommandLine* command_line) override {
-    extensions::ExtensionApiTest::SetUpCommandLine(command_line);
-  }
-
-  void SetUpInProcessBrowserTestFixture() override {
-    PrerenderBrowserTest::SetUpInProcessBrowserTestFixture();
-    extensions::ExtensionApiTest::SetUpInProcessBrowserTestFixture();
-  }
-
-  void TearDownInProcessBrowserTestFixture() override {
-    PrerenderBrowserTest::TearDownInProcessBrowserTestFixture();
-    extensions::ExtensionApiTest::TearDownInProcessBrowserTestFixture();
-  }
-
-  void TearDownOnMainThread() override {
-    PrerenderBrowserTest::TearDownOnMainThread();
-    extensions::ExtensionApiTest::TearDownOnMainThread();
-  }
-
-  void SetUpOnMainThread() override {
-    PrerenderBrowserTest::SetUpOnMainThread();
-    extensions::ExtensionApiTest::SetUpOnMainThread();
-  }
-};
-
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTestWithExtensions, WebNavigation) {
-  ASSERT_TRUE(StartEmbeddedTestServer());
-  extensions::FrameNavigationState::set_allow_extension_scheme(true);
-
-  // Wait for the extension to set itself up and return control to us.
-  ASSERT_TRUE(RunExtensionTest("webnavigation/prerender")) << message_;
-
-  extensions::ResultCatcher catcher;
-
-  PrerenderTestURL("/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
-
-  ChannelDestructionWatcher channel_close_watcher;
-  channel_close_watcher.WatchChannel(browser()
-                                         ->tab_strip_model()
-                                         ->GetActiveWebContents()
-                                         ->GetMainFrame()
-                                         ->GetProcess());
-  NavigateToDestURL();
-  channel_close_watcher.WaitForChannelClose();
-
-  ASSERT_TRUE(IsEmptyPrerenderLinkManager());
-  ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
-}
-
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTestWithExtensions, TabsApi) {
-  ASSERT_TRUE(StartEmbeddedTestServer());
-  extensions::FrameNavigationState::set_allow_extension_scheme(true);
-
-  // Wait for the extension to set itself up and return control to us.
-  ASSERT_TRUE(RunExtensionTest("tabs/on_replaced")) << message_;
-
-  extensions::ResultCatcher catcher;
-
-  PrerenderTestURL("/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
-
-  ChannelDestructionWatcher channel_close_watcher;
-  channel_close_watcher.WatchChannel(browser()
-                                         ->tab_strip_model()
-                                         ->GetActiveWebContents()
-                                         ->GetMainFrame()
-                                         ->GetProcess());
-  NavigateToDestURL();
-  channel_close_watcher.WaitForChannelClose();
-
-  ASSERT_TRUE(IsEmptyPrerenderLinkManager());
-  ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
-}
-
-// Checks that non-http/https/chrome-extension subresource cancels the
-// prerender.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
-                       PrerenderCancelSubresourceUnsupportedScheme) {
-  GURL image_url = GURL("invalidscheme://www.google.com/test.jpg");
-  base::StringPairs replacement_text;
-  replacement_text.push_back(
-      std::make_pair("REPLACE_WITH_IMAGE_URL", image_url.spec()));
-  std::string replacement_path = net::test_server::GetFilePathWithReplacements(
-      "/prerender/prerender_with_image.html", replacement_text);
-  // Disable load event checks because they race with cancellation.
-  DisableLoadEventCheck();
-  PrerenderTestURL(replacement_path, FINAL_STATUS_UNSUPPORTED_SCHEME, 0);
-}
-
-// Attempt a swap-in in a new tab. The session storage doesn't match, so it
-// should not swap.
-IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPageNewTab) {
-  PrerenderTestURL("/prerender/prerender_page.html",
-                   FINAL_STATUS_APP_TERMINATING, 1);
-
-  // Open a new tab to navigate in.
-  ui_test_utils::NavigateToURLWithDisposition(
-      current_browser(), GURL(url::kAboutBlankURL),
-      WindowOpenDisposition::NEW_FOREGROUND_TAB,
-      ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
-
-  // Now navigate in the new tab.
-  NavigateToDestURLWithDisposition(WindowOpenDisposition::CURRENT_TAB, false);
-}
-
-class PrerenderOmniboxBrowserTest : public PrerenderBrowserTest {
- public:
-  LocationBar* GetLocationBar() {
-    return current_browser()->window()->GetLocationBar();
-  }
-
-  OmniboxView* GetOmniboxView() { return GetLocationBar()->GetOmniboxView(); }
-
-  predictors::AutocompleteActionPredictor* GetAutocompleteActionPredictor() {
-    Profile* profile = current_browser()->profile();
-    return predictors::AutocompleteActionPredictorFactory::GetForProfile(
-        profile);
-  }
-
-  std::unique_ptr<TestPrerender> StartOmniboxPrerender(
-      const GURL& url,
-      FinalStatus expected_final_status) {
-    std::unique_ptr<TestPrerender> prerender =
-        ExpectPrerender(expected_final_status);
-    WebContents* web_contents = GetActiveWebContents();
-    GetAutocompleteActionPredictor()->StartPrerendering(
-        url, web_contents->GetController().GetDefaultSessionStorageNamespace(),
-        gfx::Size(50, 50));
-    prerender->WaitForStart();
-    return prerender;
-  }
-};
-
 }  // namespace prerender
 
 #endif  // !defined(OS_MACOSX) || !defined(ADDRESS_SANITIZER)
diff --git a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
index c6b6b96..a78df5e 100644
--- a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
+++ b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
@@ -22,6 +22,8 @@
 #include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/history/history_test_utils.h"
+#include "chrome/browser/predictors/autocomplete_action_predictor.h"
+#include "chrome/browser/predictors/autocomplete_action_predictor_factory.h"
 #include "chrome/browser/prerender/prerender_handle.h"
 #include "chrome/browser/prerender/prerender_manager.h"
 #include "chrome/browser/prerender/prerender_manager_factory.h"
@@ -31,12 +33,16 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/location_bar/location_bar.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
 #include "components/content_settings/core/common/pref_names.h"
 #include "components/embedder_support/switches.h"
+#include "components/omnibox/browser/omnibox_edit_model.h"
+#include "components/omnibox/browser/omnibox_view.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/appcache_service.h"
 #include "content/public/browser/browser_task_traits.h"
@@ -1709,6 +1715,16 @@
   WaitForRequestCount(src_server()->GetURL(kPrefetchScript2), 0);
 }
 
+// Checks that prerenders are aborted when an incognito profile is closed.
+// ToDo(crbug.com/994068): The test is crashing on multiple platforms.
+IN_PROC_BROWSER_TEST_F(NoStatePrefetchIncognitoBrowserTest,
+                       PrerenderIncognitoClosed) {
+  std::unique_ptr<TestPrerender> test_prerender =
+      PrefetchFromFile(kHungPrerenderPage, FINAL_STATUS_PROFILE_DESTROYED);
+  current_browser()->window()->Close();
+  test_prerender->WaitForStop();
+}
+
 // Checks that when the history is cleared, NoStatePrefetch history is cleared.
 IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, ClearHistory) {
   std::unique_ptr<TestPrerender> test_prerender = PrefetchFromFile(
@@ -1802,4 +1818,50 @@
       FINAL_STATUS_MEMORY_LIMIT_EXCEEDED);
 }
 
+class NoStatePrefetchOmniboxBrowserTest : public NoStatePrefetchBrowserTest {
+ public:
+  LocationBar* GetLocationBar() {
+    return current_browser()->window()->GetLocationBar();
+  }
+
+  OmniboxView* GetOmniboxView() { return GetLocationBar()->GetOmniboxView(); }
+
+  predictors::AutocompleteActionPredictor* GetAutocompleteActionPredictor() {
+    Profile* profile = current_browser()->profile();
+    return predictors::AutocompleteActionPredictorFactory::GetForProfile(
+        profile);
+  }
+
+  std::unique_ptr<TestPrerender> ExpectPrerender(
+      FinalStatus expected_final_status) {
+    return prerender_contents_factory()->ExpectPrerenderContents(
+        expected_final_status);
+  }
+
+  std::unique_ptr<TestPrerender> StartOmniboxPrerender(
+      const GURL& url,
+      FinalStatus expected_final_status) {
+    std::unique_ptr<TestPrerender> prerender =
+        ExpectPrerender(expected_final_status);
+    content::WebContents* web_contents = GetActiveWebContents();
+    GetAutocompleteActionPredictor()->StartPrerendering(
+        url, web_contents->GetController().GetDefaultSessionStorageNamespace(),
+        gfx::Size(50, 50));
+    prerender->WaitForStart();
+    return prerender;
+  }
+};
+
+// Checks that closing the omnibox popup cancels an omnibox prerender.
+IN_PROC_BROWSER_TEST_F(NoStatePrefetchOmniboxBrowserTest,
+                       PrerenderOmniboxCancel) {
+  // Fake an omnibox prerender.
+  std::unique_ptr<TestPrerender> prerender = StartOmniboxPrerender(
+      embedded_test_server()->GetURL("/empty.html"), FINAL_STATUS_CANCELLED);
+
+  // Revert the location bar. This should cancel the prerender.
+  GetLocationBar()->Revert();
+  prerender->WaitForStop();
+}
+
 }  // namespace prerender
diff --git a/chrome/browser/profiles/android/java/src/org/chromium/chrome/browser/profiles/Profile.java b/chrome/browser/profiles/android/java/src/org/chromium/chrome/browser/profiles/Profile.java
index 9d15c62..9148a66 100644
--- a/chrome/browser/profiles/android/java/src/org/chromium/chrome/browser/profiles/Profile.java
+++ b/chrome/browser/profiles/android/java/src/org/chromium/chrome/browser/profiles/Profile.java
@@ -141,6 +141,13 @@
         return ProfileJni.get().hasPrimaryOTRProfile(mNativeProfileAndroid, Profile.this);
     }
 
+    /**
+     * Returns if the profile is a primary OTR Profile.
+     */
+    public boolean isPrimaryOTRProfile() {
+        return ProfileJni.get().isPrimaryOTRProfile(mNativeProfileAndroid, Profile.this);
+    }
+
     public ProfileKey getProfileKey() {
         return (ProfileKey) ProfileJni.get().getProfileKey(mNativeProfileAndroid, Profile.this);
     }
@@ -219,6 +226,7 @@
                 long nativeProfileAndroid, Profile caller, OTRProfileID otrProfileID);
         boolean hasPrimaryOTRProfile(long nativeProfileAndroid, Profile caller);
         boolean isOffTheRecord(long nativeProfileAndroid, Profile caller);
+        boolean isPrimaryOTRProfile(long nativeProfileAndroid, Profile caller);
         boolean isChild(long nativeProfileAndroid, Profile caller);
         void wipe(long nativeProfileAndroid, Profile caller);
         Object getProfileKey(long nativeProfileAndroid, Profile caller);
diff --git a/chrome/browser/profiles/profile_android.cc b/chrome/browser/profiles/profile_android.cc
index 065f714e..d01502f 100644
--- a/chrome/browser/profiles/profile_android.cc
+++ b/chrome/browser/profiles/profile_android.cc
@@ -128,6 +128,11 @@
   return profile_->HasPrimaryOTRProfile();
 }
 
+jboolean ProfileAndroid::IsPrimaryOTRProfile(JNIEnv* env,
+                                             const JavaParamRef<jobject>& obj) {
+  return profile_->IsPrimaryOTRProfile();
+}
+
 base::android::ScopedJavaLocalRef<jobject> ProfileAndroid::GetProfileKey(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj) {
diff --git a/chrome/browser/profiles/profile_android.h b/chrome/browser/profiles/profile_android.h
index e7c11be..7d869cd 100644
--- a/chrome/browser/profiles/profile_android.h
+++ b/chrome/browser/profiles/profile_android.h
@@ -72,6 +72,10 @@
   jboolean IsOffTheRecord(JNIEnv* env,
                           const base::android::JavaParamRef<jobject>& obj);
 
+  // Whether this profile is primary off the record profile.
+  jboolean IsPrimaryOTRProfile(JNIEnv* env,
+                               const base::android::JavaParamRef<jobject>& obj);
+
   // Whether this profile is signed in to a child account.
   jboolean IsChild(JNIEnv* env,
                    const base::android::JavaParamRef<jobject>& obj);
diff --git a/chrome/browser/resources/chromeos/crostini_upgrader/app.html b/chrome/browser/resources/chromeos/crostini_upgrader/app.html
index b105134..919a85e 100644
--- a/chrome/browser/resources/chromeos/crostini_upgrader/app.html
+++ b/chrome/browser/resources/chromeos/crostini_upgrader/app.html
@@ -14,7 +14,7 @@
   }
 
   #icon {
-    fill: var(--cros-default-icon-color-prominent);
+    fill: var(--cros-icon-color-prominent);
     height: 32px;
     margin-top: 28px;
     width: 32px;
@@ -31,7 +31,7 @@
   }
 
   #main-title {
-    color: var(--cros-default-text-color);
+    color: var(--cros-text-color-primary);
     font-family: 'Google Sans';
     font-size: 28px;
     line-height: 1;
@@ -39,7 +39,7 @@
   }
 
   #status-container {
-    color: var(--cros-default-text-color-secondary);
+    color: var(--cros-text-color-secondary);
     flex-grow: 1;
     font-family: Roboto;
     font-size: 13px;
@@ -62,7 +62,7 @@
   }
 
   paper-progress {
-    --paper-progress-active-color: var(--cros-default-icon-color-prominent);
+    --paper-progress-active-color: var(--cros-icon-color-prominent);
     --paper-progress-container-color: rgba(var(--google-blue-600-rgb), .24);
     margin-top: 36px;
     width: 100%;
diff --git a/chrome/browser/resources/chromeos/crostini_upgrader/app.js b/chrome/browser/resources/chromeos/crostini_upgrader/app.js
index 7a2c4f4..dfa07b6 100644
--- a/chrome/browser/resources/chromeos/crostini_upgrader/app.js
+++ b/chrome/browser/resources/chromeos/crostini_upgrader/app.js
@@ -428,6 +428,8 @@
       case State.SUCCEEDED:
       case State.RESTORE_SUCCEEDED:
         return loadTimeData.getString('close');
+      case State.PROMPT:
+        return loadTimeData.getString('notNow');
       default:
         return loadTimeData.getString('cancel');
     }
diff --git a/chrome/browser/resources/chromeos/zip_archiver/html/passphrase-dialog.html b/chrome/browser/resources/chromeos/zip_archiver/html/passphrase-dialog.html
index a2a9a9e..9d69b17 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/html/passphrase-dialog.html
+++ b/chrome/browser/resources/chromeos/zip_archiver/html/passphrase-dialog.html
@@ -37,7 +37,7 @@
       }
 
       #title {
-        color: var(--cros-default-text-color-rgb);
+        color: var(--cros-text-color-primary-rgb);
         font-size: 16px;
         overflow: hidden;
         padding-bottom: 16px;
diff --git a/chrome/browser/resources/nearby_share/BUILD.gn b/chrome/browser/resources/nearby_share/BUILD.gn
index 2d59828..016739d 100644
--- a/chrome/browser/resources/nearby_share/BUILD.gn
+++ b/chrome/browser/resources/nearby_share/BUILD.gn
@@ -10,6 +10,7 @@
   deps = [
     ":app",
     ":nearby_confirmation_page",
+    ":nearby_device",
     ":nearby_discovery_page",
     ":nearby_preview",
     ":nearby_progress",
@@ -36,8 +37,15 @@
   ]
 }
 
+js_library("nearby_device") {
+  deps = [
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+  ]
+}
+
 js_library("nearby_discovery_page") {
   deps = [
+    ":nearby_device",
     ":nearby_preview",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/cr_elements/cr_button:cr_button.m",
@@ -62,6 +70,7 @@
     "app.js",
     "icons.js",
     "nearby_confirmation_page.js",
+    "nearby_device.js",
     "nearby_discovery_page.js",
     "nearby_preview.js",
     "nearby_progress.js",
diff --git a/chrome/browser/resources/nearby_share/nearby_device.html b/chrome/browser/resources/nearby_share/nearby_device.html
new file mode 100644
index 0000000..ea3a426
--- /dev/null
+++ b/chrome/browser/resources/nearby_share/nearby_device.html
@@ -0,0 +1,25 @@
+<style>
+  :host {
+    align-items: center;
+    border: 1px solid rgba(216, 216, 216, 0.76);
+    border-radius: 8px;
+    box-sizing: border-box;
+    display: flex;
+    height: 40px;
+    margin-top: 6px;
+  }
+
+  #name {
+    color: rgb(95, 99, 104);
+    flex-grow: 1;
+    font-size: 11px;
+    font-weight: 500;
+    letter-spacing: 0.3px;
+    overflow: hidden;
+    text-align: center;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+</style>
+
+<div id="name">[[name]]</div>
diff --git a/chrome/browser/resources/nearby_share/nearby_device.js b/chrome/browser/resources/nearby_share/nearby_device.js
new file mode 100644
index 0000000..22da70a
--- /dev/null
+++ b/chrome/browser/resources/nearby_share/nearby_device.js
@@ -0,0 +1,23 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview The 'nearby-device' component shows details of a remote device.
+ */
+
+import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+Polymer({
+  is: 'nearby-device',
+
+  _template: html`{__html_template__}`,
+
+  properties: {
+    /** The device name to show. */
+    name: {
+      type: String,
+      value: '',
+    },
+  },
+});
diff --git a/chrome/browser/resources/nearby_share/nearby_discovery_page.html b/chrome/browser/resources/nearby_share/nearby_discovery_page.html
index 282b0f5b..585ccbd 100644
--- a/chrome/browser/resources/nearby_share/nearby_discovery_page.html
+++ b/chrome/browser/resources/nearby_share/nearby_discovery_page.html
@@ -4,6 +4,11 @@
     text-align: end;
   }
 
+  #device-list {
+    overflow: auto;
+    width: 191px;
+  }
+
   nearby-preview {
     margin-inline-end: 10px;
     margin-inline-start: 10px;
@@ -27,7 +32,9 @@
   #process-row {
     display: flex;
     flex-grow: 1;
+    justify-content: space-between;
     margin-top: 48px;
+    overflow: hidden;
   }
 
   #subtitle {
@@ -54,6 +61,21 @@
 
   <div id="process-row">
     <nearby-preview title="Doggo.jpg"></nearby-preview>
+    <div id="device-list">
+      <nearby-device name="Alyssa's Pixel"></nearby-device>
+      <nearby-device name="Shangela's Pixel 2XL Name Is Looong"></nearby-device>
+      <nearby-device name="MirasChromebookIsAllInOneWord"></nearby-device>
+      <nearby-device name="One"></nearby-device>
+      <nearby-device name="Two"></nearby-device>
+      <nearby-device name="Three"></nearby-device>
+      <nearby-device name="Four"></nearby-device>
+      <nearby-device name="Five"></nearby-device>
+      <nearby-device name="Six"></nearby-device>
+      <nearby-device name="Seven"></nearby-device>
+      <nearby-device name="Eight"></nearby-device>
+      <nearby-device name="Nine"></nearby-device>
+      <nearby-device name="Ten"></nearby-device>
+    </div>
   </div>
 
   <div id="help">
diff --git a/chrome/browser/resources/nearby_share/nearby_discovery_page.js b/chrome/browser/resources/nearby_share/nearby_discovery_page.js
index ce5bdd8..16a535e 100644
--- a/chrome/browser/resources/nearby_share/nearby_discovery_page.js
+++ b/chrome/browser/resources/nearby_share/nearby_discovery_page.js
@@ -8,6 +8,7 @@
  */
 
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
+import './nearby_device.js';
 import './nearby_preview.js';
 
 import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/chrome/browser/resources/nearby_share/nearby_share_dialog_resources.grd b/chrome/browser/resources/nearby_share/nearby_share_dialog_resources.grd
index b615a14..52b17b3 100644
--- a/chrome/browser/resources/nearby_share/nearby_share_dialog_resources.grd
+++ b/chrome/browser/resources/nearby_share/nearby_share_dialog_resources.grd
@@ -26,6 +26,9 @@
       <include name="IDR_NEARBY_SHARE_NEARBY_CONFIRMATION_PAGE_JS"
                file="${root_gen_dir}/chrome/browser/resources/nearby_share/nearby_confirmation_page.js"
                use_base_dir="false" type="BINDATA"/>
+      <include name="IDR_NEARBY_SHARE_NEARBY_DEVICE_JS"
+               file="${root_gen_dir}/chrome/browser/resources/nearby_share/nearby_device.js"
+               use_base_dir="false" type="BINDATA"/>
       <include name="IDR_NEARBY_SHARE_NEARBY_DISCOVERY_PAGE_JS"
                file="${root_gen_dir}/chrome/browser/resources/nearby_share/nearby_discovery_page.js"
                use_base_dir="false" type="BINDATA"/>
diff --git a/chrome/browser/resources/pdf/pdf_viewer.js b/chrome/browser/resources/pdf/pdf_viewer.js
index 6537583..cd024f5 100644
--- a/chrome/browser/resources/pdf/pdf_viewer.js
+++ b/chrome/browser/resources/pdf/pdf_viewer.js
@@ -84,7 +84,7 @@
   }
 }
 
-class PDFViewerElement extends PDFViewerBaseElement {
+export class PDFViewerElement extends PDFViewerBaseElement {
   static get is() {
     return 'pdf-viewer';
   }
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html
index babe5d2..0ee08db 100644
--- a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html
@@ -63,7 +63,7 @@
       }
 
       iron-icon[icon='settings:check-circle'] {
-        fill: var(--cros-default-icon-color-prominent);
+        fill: var(--cros-icon-color-prominent);
       }
 
       iron-icon[icon='cr:error'] {
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_item.html b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_item.html
index 4f329e0..025c88e 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_item.html
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_item.html
@@ -12,7 +12,7 @@
       :host {
         align-items: center;
         border-bottom: var(--card-separator);
-        color: var(--cros-default-text-color);
+        color: var(--cros-text-color-primary);
         cursor: pointer;
         display: flex;
         flex-direction: row;
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/shared_style.html b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/shared_style.html
index 856fc8a..f01d974 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/shared_style.html
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/shared_style.html
@@ -8,7 +8,7 @@
   <template>
     <style include="cr-shared-style cros-color-overrides">
       .card-container {
-        background-color: var(--cros-default-bg-color);
+        background-color: var(--cros-bg-color);
         border-radius: var(--cr-card-border-radius);
         box-shadow: var(--cr-card-shadow);
         display: flex;
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/shared_vars.html b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/shared_vars.html
index c18182d..1f3102d 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/shared_vars.html
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/shared_vars.html
@@ -12,14 +12,14 @@
     --card-separator: 1px solid var(--cros-separator-color);
     --expanded-permission-row-height: 48px;
     --header-font-weight: 500;
-    --header-text-color: var(--cros-default-text-color-secondary);
+    --header-text-color: var(--cros-text-color-secondary);
     --permission-icon-color: var(--cros-app-management-permission-icon-color);
     --permission-icon-padding: 20px;
     --permission-list-item-height: 48px;
-    --primary-text-color: var(--cros-default-text-color);
+    --primary-text-color: var(--cros-text-color-primary);
     --row-item-icon-padding: 12px;
     --secondary-font-weight: 400;
-    --secondary-text-color: var(--cros-default-text-color-secondary);
+    --secondary-text-color: var(--cros-text-color-secondary);
     --text-permission-list-row-height: 40px;
   }
 </style>
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.html b/chrome/browser/resources/settings/chromeos/os_settings.html
index 1b27721d..5b3b0e1 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.html
+++ b/chrome/browser/resources/settings/chromeos/os_settings.html
@@ -9,7 +9,7 @@
   <link rel="stylesheet" href="chrome://resources/css/cros_colors.generated.css">
   <style>
     html {
-      background-color: var(--cros-default-bg-color);
+      background-color: var(--cros-bg-color);
       overflow: hidden;
       /* Remove 300ms delay for 'click' event, when using touch interface. */
       touch-action: manipulation;
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html
index 986588f..d363af5 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html
+++ b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html
@@ -17,9 +17,9 @@
   <template>
     <style include="settings-shared">
       :host {
-        --menu-link-color: var(--cros-default-icon-color-prominent);
-        --menu-text-color: var(--cros-default-text-color-secondary);
-        --menu-icon-color: var(--cros-default-text-color-secondary);
+        --menu-link-color: var(--cros-icon-color-prominent);
+        --menu-text-color: var(--cros-text-color-secondary);
+        --menu-icon-color: var(--cros-text-color-secondary);
         /* The tap target extends slightly above each visible menu item. */
         --tap-target-padding: 3px;
         /* Width of the keyboard focus border. */
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html
index 0885cdb89..08e97f4e 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html
@@ -33,7 +33,7 @@
 
       .banner {
         align-items: center;
-        background-color: var(--cros-default-bg-color);
+        background-color: var(--cros-bg-color);
         border: var(--cr-hairline);
         border-radius: var(--cr-card-border-radius);
         display: flex;
@@ -77,7 +77,7 @@
 
       #toggleContainer {
         align-items: center;
-        color: var(--cros-default-text-color);
+        color: var(--cros-text-color-primary);
         display: flex;
         font: inherit;
         justify-content: center;
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.html b/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.html
index 9c19015e..fd18bba 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.html
+++ b/chrome/browser/resources/settings/chromeos/os_settings_ui/os_settings_ui.html
@@ -47,7 +47,7 @@
 
       cr-drawer {
         --cr-separator-line: none;
-        --cr-drawer-header-color: var(--cros-default-text-color-secondary);
+        --cr-drawer-header-color: var(--cros-text-color-secondary);
         --cr-drawer-header-font-weight: 500;
         --cr-drawer-header-padding: 20px;
       }
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_v3.html b/chrome/browser/resources/settings/chromeos/os_settings_v3.html
index d97f6fa93..e3277b9 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_v3.html
+++ b/chrome/browser/resources/settings/chromeos/os_settings_v3.html
@@ -7,7 +7,7 @@
   <link rel="stylesheet" href="chrome://resources/css/cros_colors.generated.css">
   <style>
     html {
-      background-color: var(--cros-default-bg-color);
+      background-color: var(--cros-bg-color);
       overflow: hidden;
       /* Remove 300ms delay for 'click' event, when using touch interface. */
       touch-action: manipulation;
diff --git a/chrome/browser/resources/settings/chromeos/os_toolbar/os_toolbar.html b/chrome/browser/resources/settings/chromeos/os_toolbar/os_toolbar.html
index ead73e5..fde85cc 100644
--- a/chrome/browser/resources/settings/chromeos/os_toolbar/os_toolbar.html
+++ b/chrome/browser/resources/settings/chromeos/os_toolbar/os_toolbar.html
@@ -15,17 +15,17 @@
     <style include="cr-icons cr-hidden-style">
       :host {
         --cr-toolbar-search-field-background:
-            var(--cros-default-toolbar-search-bg-color);
+            var(--cros-toolbar-search-bg-color);
         --cr-toolbar-search-field-border-radius: 4px;
         --cr-toolbar-search-field-input-text-color:
-            var(--cros-default-text-color-secondary);
+            var(--cros-text-color-secondary);
         --cr-toolbar-search-field-input-icon-color:
-            var(--cros-default-text-color-secondary);
+            var(--cros-text-color-secondary);
         --cr-toolbar-search-field-input-bg-color:
-            var(--cros-default-toolbar-bg-color);
+            var(--cros-toolbar-bg-color);
         align-items: center;
-        background-color: var(--cros-default-toolbar-bg-color);
-        color: var(--cros-default-text-color-secondary);
+        background-color: var(--cros-toolbar-bg-color);
+        color: var(--cros-text-color-secondary);
         display: flex;
         height: var(--cr-toolbar-height);
         padding-top: 8px;
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.cc b/chrome/browser/safe_browsing/client_side_detection_host.cc
index 0e72a7cd..bcff2b9 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host.cc
@@ -48,7 +48,7 @@
 #include "net/base/ip_endpoint.h"
 #include "net/http/http_response_headers.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
-#include "third_party/blink/public/mojom/referrer.mojom.h"
+#include "third_party/blink/public/mojom/loader/referrer.mojom.h"
 #include "url/gurl.h"
 
 using content::BrowserThread;
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index b185871..377211c47 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -3791,8 +3791,6 @@
       "views/toolbar/browser_actions_container.h",
       "views/toolbar/browser_app_menu_button.cc",
       "views/toolbar/browser_app_menu_button.h",
-      "views/toolbar/button_utils.cc",
-      "views/toolbar/button_utils.h",
       "views/toolbar/extension_toolbar_menu_view.cc",
       "views/toolbar/extension_toolbar_menu_view.h",
       "views/toolbar/home_button.cc",
diff --git a/chrome/browser/ui/app_list/app_list_notifier_impl.cc b/chrome/browser/ui/app_list/app_list_notifier_impl.cc
index 0c98553..078d2710 100644
--- a/chrome/browser/ui/app_list/app_list_notifier_impl.cc
+++ b/chrome/browser/ui/app_list/app_list_notifier_impl.cc
@@ -49,9 +49,18 @@
 
 void AppListNotifierImpl::NotifySearchQueryChanged(
     const base::string16& query) {
+  // In some cases the query can change after the launcher is closed, in
+  // particular this happens when abandoning the launcher with a non-empty
+  // query. Only do a state transition if the launcher is open.
+  if (view_ != ash::AppListViewState::kClosed) {
+    DoStateTransition(Location::kList, State::kShown);
+    DoStateTransition(Location::kTile, State::kShown);
+  }
+
+  // Update the stored |query_| after performing the state transitions, so that
+  // an abandon triggered by the query change correctly uses the pre-abandon
+  // query.
   query_ = query;
-  DoStateTransition(Location::kList, State::kShown);
-  DoStateTransition(Location::kTile, State::kShown);
 }
 
 void AppListNotifierImpl::NotifyUIStateChanged(ash::AppListViewState view) {
diff --git a/chrome/browser/ui/search_engines/search_engine_tab_helper.cc b/chrome/browser/ui/search_engines/search_engine_tab_helper.cc
index b2fadd1..9e70ae2 100644
--- a/chrome/browser/ui/search_engines/search_engine_tab_helper.cc
+++ b/chrome/browser/ui/search_engines/search_engine_tab_helper.cc
@@ -25,8 +25,8 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 #include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/mojom/loader/referrer.mojom.h"
 #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
-#include "third_party/blink/public/mojom/referrer.mojom.h"
 
 using content::NavigationController;
 using content::NavigationEntry;
diff --git a/chrome/browser/ui/views/download/download_item_view.cc b/chrome/browser/ui/views/download/download_item_view.cc
index 70706358..8ea2f5f 100644
--- a/chrome/browser/ui/views/download/download_item_view.cc
+++ b/chrome/browser/ui/views/download/download_item_view.cc
@@ -260,14 +260,13 @@
   status_label->GetViewAccessibility().OverrideIsIgnored(true);
   status_label_ = AddChildView(std::move(status_label));
 
-  auto dangerous_download_label = std::make_unique<views::StyledLabel>(
+  auto warning_label = std::make_unique<views::StyledLabel>(
       base::string16(), /*listener=*/nullptr);
-  dangerous_download_label->SetTextContext(CONTEXT_DOWNLOAD_SHELF);
-  dangerous_download_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-  dangerous_download_label->SetAutoColorReadabilityEnabled(false);
-  dangerous_download_label->set_can_process_events_within_subtree(false);
-  dangerous_download_label_ = AddChildView(std::move(dangerous_download_label));
-  dangerous_download_label_->SetVisible(false);
+  warning_label->SetTextContext(CONTEXT_DOWNLOAD_SHELF);
+  warning_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  warning_label->SetAutoColorReadabilityEnabled(false);
+  warning_label->set_can_process_events_within_subtree(false);
+  warning_label_ = AddChildView(std::move(warning_label));
 
   auto deep_scanning_label = std::make_unique<views::StyledLabel>(
       base::string16(), /*listener=*/nullptr);
@@ -276,7 +275,6 @@
   deep_scanning_label->SetAutoColorReadabilityEnabled(false);
   deep_scanning_label->set_can_process_events_within_subtree(false);
   deep_scanning_label_ = AddChildView(std::move(deep_scanning_label));
-  deep_scanning_label_->SetVisible(false);
 
   auto open_now_button = views::MdTextButton::Create(
       this, l10n_util::GetStringUTF16(IDS_OPEN_DOWNLOAD_NOW));
@@ -303,8 +301,6 @@
 
   // Further configure default state, e.g. child visibility.
   OnDownloadUpdated();
-
-  UpdateColorsFromTheme();
 }
 
 DownloadItemView::~DownloadItemView() {
@@ -316,17 +312,15 @@
 void DownloadItemView::Layout() {
   View::Layout();
 
-  UpdateColorsFromTheme();
-
   open_button_->SetBoundsRect(GetLocalBounds());
 
   if (is_download_warning(mode_)) {
     gfx::Point child_origin(
         kStartPadding + GetWarningIconSize() + kStartPadding,
-        (height() - dangerous_download_label_->height()) / 2);
-    dangerous_download_label_->SetPosition(child_origin);
+        (height() - warning_label_->height()) / 2);
+    warning_label_->SetPosition(child_origin);
 
-    child_origin.Offset(dangerous_download_label_->width() + kLabelPadding, 0);
+    child_origin.Offset(warning_label_->width() + kLabelPadding, 0);
     gfx::Size button_size = GetButtonSize();
     child_origin.set_y((height() - button_size.height()) / 2);
     if (save_button_->GetVisible()) {
@@ -340,10 +334,10 @@
   } else if (is_mixed_content(mode_)) {
     gfx::Point child_origin(
         kStartPadding + GetWarningIconSize() + kStartPadding,
-        (height() - dangerous_download_label_->height()) / 2);
-    dangerous_download_label_->SetPosition(child_origin);
+        (height() - warning_label_->height()) / 2);
+    warning_label_->SetPosition(child_origin);
 
-    child_origin.Offset(dangerous_download_label_->width() + kLabelPadding, 0);
+    child_origin.Offset(warning_label_->width() + kLabelPadding, 0);
     gfx::Size button_size = GetButtonSize();
     child_origin.set_y((height() - button_size.height()) / 2);
     if (save_button_->GetVisible())
@@ -367,7 +361,11 @@
     int mirrored_x = GetMirroredXWithWidthInView(
         kStartPadding + kProgressIndicatorSize + kProgressTextPadding,
         kTextWidth);
-    int file_name_y = GetYForFilenameText();
+
+    int text_height = font_list_.GetHeight();
+    if (!status_label_->GetText().empty())
+      text_height += status_font_list_.GetHeight();
+    int file_name_y = (height() - text_height) / 2;
     file_name_label_->SetBoundsRect(
         gfx::Rect(mirrored_x, file_name_y, kTextWidth, font_list_.GetHeight()));
 
@@ -557,6 +555,7 @@
 }
 
 void DownloadItemView::OnDownloadOpened() {
+  file_name_label_->SetTextStyle(views::style::STYLE_DISABLED);
   // First, Calculate the download status opening string width.
   base::string16 status_string =
       l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_OPENING, base::string16());
@@ -607,7 +606,7 @@
   if (has_warning_label(mode_)) {
     // Width.
     width = kStartPadding + GetWarningIconSize() + kStartPadding +
-            dangerous_download_label_->width() + kLabelPadding;
+            warning_label_->width() + kLabelPadding;
     gfx::Size button_size = GetButtonSize();
     if (save_button_->GetVisible() && discard_button_->GetVisible())
       width += button_size.width() + kSaveDiscardButtonPadding;
@@ -696,36 +695,13 @@
 }
 
 void DownloadItemView::UpdateMode(Mode mode) {
-  // TODO(pkasting): This function is currently enormous and has a lot of
-  // repeated and/or unnecessary code.  Refactor further.
-
-  if (mode_ != Mode::kNormal) {
-    file_name_label_->SetVisible(true);
-    status_label_->SetVisible(true);
-    if (is_mixed_content(mode_) || is_download_warning(mode_)) {
-      dangerous_download_label_->SetVisible(false);
-    } else if (mode_ == Mode::kDeepScanning) {
-      deep_scanning_label_->SetVisible(false);
-    }
-  }
+  // TODO(pkasting): Refactor further.
 
   mode_ = mode;
+  UpdateLabels();
   UpdateButtons();
 
-  if (is_mixed_content(mode_)) {
-    dangerous_download_label_->SetVisible(true);
-    const base::string16 filename = ElidedFilename();
-    size_t filename_offset;
-    dangerous_download_label_->SetText(
-        model_->GetWarningText(filename, &filename_offset));
-    StyleFilename(*dangerous_download_label_, filename_offset,
-                  filename.length());
-    dangerous_download_label_->SizeToFit(
-        GetLabelWidth(*dangerous_download_label_));
-
-    file_name_label_->SetVisible(false);
-    status_label_->SetVisible(false);
-  } else if (is_download_warning(mode_)) {
+  if (is_download_warning(mode_)) {
     time_download_warning_shown_ = base::Time::Now();
     download::DownloadDangerType danger_type = model_->GetDangerType();
     RecordDangerousDownloadWarningShown(danger_type);
@@ -743,46 +719,13 @@
       UpdateAccessibleAlert(model_->GetWarningText(unelided_filename, &ignore),
                             true);
     }
-
-    dangerous_download_label_->SetVisible(true);
-    const base::string16 filename = ElidedFilename();
-    size_t filename_offset;
-    dangerous_download_label_->SetText(
-        model_->GetWarningText(filename, &filename_offset));
-    StyleFilename(*dangerous_download_label_, filename_offset,
-                  filename.length());
-    dangerous_download_label_->SizeToFit(
-        GetLabelWidth(*dangerous_download_label_));
-
-    file_name_label_->SetVisible(false);
-    status_label_->SetVisible(false);
   } else if (mode_ == Mode::kDeepScanning) {
-    const int id = (model_->download() &&
-                    safe_browsing::DeepScanningRequest::ShouldUploadBinary(
-                        model_->download()))
-                       ? IDS_PROMPT_DEEP_SCANNING_DOWNLOAD
-                       : IDS_PROMPT_DEEP_SCANNING_APP_DOWNLOAD;
-    deep_scanning_label_->SetVisible(true);
-    const base::string16 filename = ElidedFilename();
-    size_t filename_offset;
-    deep_scanning_label_->SetText(
-        l10n_util::GetStringFUTF16(id, filename, &filename_offset));
-    StyleFilename(*deep_scanning_label_, filename_offset, filename.length());
-    deep_scanning_label_->SizeToFit(GetLabelWidth(*deep_scanning_label_));
-
-    file_name_label_->SetVisible(false);
-    status_label_->SetVisible(false);
-
     UpdateAccessibleAlert(
         l10n_util::GetStringFUTF16(
             IDS_DEEP_SCANNING_ACCESSIBLE_ALERT,
             model_->GetFileNameToReportUser().LossyDisplayName()),
         false);
-  } else {
-    status_label_->SetText(GetStatusText());
-    status_label_->GetViewAccessibility().OverrideIsIgnored(
-        status_label_->GetText().empty());
-    file_name_label_->SetY(GetYForFilenameText());
+  } else if (mode_ == Mode::kNormal) {
     switch (model_->GetState()) {
       case DownloadItem::IN_PROGRESS:
         // No need to send accessible alert for "paused", as the button ends
@@ -844,6 +787,43 @@
   shelf_->SchedulePaint();
 }
 
+void DownloadItemView::UpdateLabels() {
+  file_name_label_->SetVisible(mode_ == Mode::kNormal);
+
+  status_label_->SetVisible(mode_ == Mode::kNormal);
+  if (status_label_->GetVisible()) {
+    const auto text_and_style = GetStatusTextAndStyle();
+    status_label_->SetText(text_and_style.first);
+    status_label_->SetTextStyle(text_and_style.second);
+    status_label_->GetViewAccessibility().OverrideIsIgnored(
+        status_label_->GetText().empty());
+  }
+
+  warning_label_->SetVisible(has_warning_label(mode_));
+  if (warning_label_->GetVisible()) {
+    const base::string16 filename = ElidedFilename();
+    size_t filename_offset;
+    warning_label_->SetText(model_->GetWarningText(filename, &filename_offset));
+    StyleFilename(*warning_label_, filename_offset, filename.length());
+    warning_label_->SizeToFit(GetLabelWidth(*warning_label_));
+  }
+
+  deep_scanning_label_->SetVisible(mode_ == Mode::kDeepScanning);
+  if (deep_scanning_label_->GetVisible()) {
+    const int id = (model_->download() &&
+                    safe_browsing::DeepScanningRequest::ShouldUploadBinary(
+                        model_->download()))
+                       ? IDS_PROMPT_DEEP_SCANNING_DOWNLOAD
+                       : IDS_PROMPT_DEEP_SCANNING_APP_DOWNLOAD;
+    const base::string16 filename = ElidedFilename();
+    size_t filename_offset;
+    deep_scanning_label_->SetText(
+        l10n_util::GetStringFUTF16(id, filename, &filename_offset));
+    StyleFilename(*deep_scanning_label_, filename_offset, filename.length());
+    deep_scanning_label_->SizeToFit(GetLabelWidth(*deep_scanning_label_));
+  }
+}
+
 void DownloadItemView::UpdateButtons() {
   bool prompt_to_scan = false, prompt_to_discard = false;
   if (is_download_warning(mode_)) {
@@ -915,13 +895,6 @@
 #endif
 }
 
-int DownloadItemView::GetYForFilenameText() const {
-  int text_height = font_list_.GetHeight();
-  if (!status_label_->GetText().empty())
-    text_height += status_font_list_.GetHeight();
-  return (height() - text_height) / 2;
-}
-
 void DownloadItemView::DrawIcon(gfx::Canvas* canvas) {
   bool use_new_warnings =
       base::FeatureList::IsEnabled(safe_browsing::kUseNewDownloadWarnings);
@@ -1023,17 +996,6 @@
   if (!GetThemeProvider())
     return;
 
-  file_name_label_->SetTextStyle(GetEnabled() ? views::style::STYLE_PRIMARY
-                                              : views::style::STYLE_DISABLED);
-  if (model_->GetDangerType() ==
-      download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_SAFE) {
-    status_label_->SetTextStyle(STYLE_GREEN);
-  } else if (model_->GetDangerType() ==
-             download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_OPENED_DANGEROUS) {
-    status_label_->SetTextStyle(STYLE_RED);
-  } else {
-    status_label_->SetTextStyle(views::style::STYLE_PRIMARY);
-  }
   SkColor background_color =
       GetThemeProvider()->GetColor(ThemeProperties::COLOR_DOWNLOAD_SHELF);
   file_name_label_->SetBackgroundColor(background_color);
@@ -1191,6 +1153,7 @@
 }
 
 void DownloadItemView::Reenable() {
+  file_name_label_->SetTextStyle(views::style::STYLE_PRIMARY);
   file_name_label_->SetText(ElidedFilename());
   SetEnabled(true);  // Triggers a repaint.
 }
@@ -1222,7 +1185,7 @@
 void DownloadItemView::UpdateAccessibleName() {
   base::string16 new_name;
   if (has_warning_label(mode_)) {
-    new_name = dangerous_download_label_->GetText();
+    new_name = warning_label_->GetText();
   } else {
     new_name = status_label_->GetText() + base::char16(' ') +
                model_->GetFileNameToReportUser().LossyDisplayName();
@@ -1369,30 +1332,29 @@
     SchedulePaint();
 }
 
-base::string16 DownloadItemView::GetStatusText() const {
-  if (model_->GetDangerType() ==
-      download::DownloadDangerType::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_SAFE) {
-    return l10n_util::GetStringUTF16(IDS_PROMPT_DOWNLOAD_DEEP_SCANNED_SAFE);
-  } else if (model_->GetDangerType() ==
-             download::DownloadDangerType::
-                 DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_OPENED_DANGEROUS) {
-    return l10n_util::GetStringUTF16(
-        IDS_PROMPT_DOWNLOAD_DEEP_SCANNED_OPENED_DANGEROUS);
+std::pair<base::string16, int> DownloadItemView::GetStatusTextAndStyle() const {
+  using DangerType = download::DownloadDangerType;
+  const auto type = model_->GetDangerType();
+  if (type == DangerType::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_SAFE) {
+    return {l10n_util::GetStringUTF16(IDS_PROMPT_DOWNLOAD_DEEP_SCANNED_SAFE),
+            STYLE_GREEN};
   }
+  constexpr int kDangerous = IDS_PROMPT_DOWNLOAD_DEEP_SCANNED_OPENED_DANGEROUS;
+  if (type == DangerType::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_OPENED_DANGEROUS)
+    return {l10n_util::GetStringUTF16(kDangerous), STYLE_RED};
 
-  if (!model_->ShouldPromoteOrigin() ||
-      model_->GetOriginalURL().GetOrigin().is_empty()) {
-    // Use the default status text.
-    return model_->GetStatusText();
-  }
-
-#if !defined(OS_ANDROID)
-  return url_formatter::ElideUrl(model_->GetOriginalURL().GetOrigin(),
-                                 status_font_list_, kTextWidth);
+  const GURL url = model_->GetOriginalURL().GetOrigin();
+  const base::string16 text =
+      (!model_->ShouldPromoteOrigin() || url.is_empty())
+          ? model_->GetStatusText()
+#if defined(OS_ANDROID)
+          // url_formatter::ElideUrl() doesn't exist on Android.
+          : base::string16();
 #else
-  NOTREACHED();
-  return base::string16();
+          : url_formatter::ElideUrl(url, status_label_->font_list(),
+                                    kTextWidth);
 #endif
+  return {text, views::style::STYLE_PRIMARY};
 }
 
 base::string16 DownloadItemView::ElidedFilename() {
diff --git a/chrome/browser/ui/views/download/download_item_view.h b/chrome/browser/ui/views/download/download_item_view.h
index 792386e7..18ea015 100644
--- a/chrome/browser/ui/views/download/download_item_view.h
+++ b/chrome/browser/ui/views/download/download_item_view.h
@@ -134,6 +134,9 @@
   // Sets the current mode to |mode| and updates UI appropriately.
   void UpdateMode(Mode mode);
 
+  // Updates the visibility, text, size, etc. of all labels.
+  void UpdateLabels();
+
   // Updates the visible and enabled state of all buttons.
   void UpdateButtons();
 
@@ -145,10 +148,6 @@
   bool SubmitDownloadToFeedbackService(
       DownloadCommands::Command download_command);
 
-  // This function calculates the vertical coordinate to draw the file name text
-  // relative to local bounds.
-  int GetYForFilenameText() const;
-
   void DrawIcon(gfx::Canvas* canvas);
   void LoadIcon();
 
@@ -228,8 +227,8 @@
   // Callback for |progress_timer_|.
   void ProgressTimerFired();
 
-  // Returns the status text to show in the notification.
-  base::string16 GetStatusText() const;
+  // Returns the text and style to use for the status label.
+  std::pair<base::string16, int> GetStatusTextAndStyle() const;
 
   // Returns the file name to report to user. It might be elided to fit into
   // the text width.
@@ -307,7 +306,7 @@
 
   views::Label* file_name_label_;
   views::Label* status_label_;
-  views::StyledLabel* dangerous_download_label_;
+  views::StyledLabel* warning_label_;
   views::StyledLabel* deep_scanning_label_;
 
   views::MdTextButton* open_now_button_;
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_button.cc b/chrome/browser/ui/views/extensions/extensions_toolbar_button.cc
index c4ea4fd9..c5f4e66 100644
--- a/chrome/browser/ui/views/extensions/extensions_toolbar_button.cc
+++ b/chrome/browser/ui/views/extensions/extensions_toolbar_button.cc
@@ -43,12 +43,6 @@
   CHECK(!IsInObserverList());
 }
 
-void ExtensionsToolbarButton::UpdateIcon() {
-  SetImage(views::Button::STATE_NORMAL,
-           gfx::CreateVectorIcon(vector_icons::kExtensionIcon, GetIconSize(),
-                                 extensions_container_->GetIconColor()));
-}
-
 gfx::Size ExtensionsToolbarButton::CalculatePreferredSize() const {
   return extensions_container_->GetToolbarActionSize();
 }
@@ -89,6 +83,13 @@
   return "ExtensionsToolbarButton";
 }
 
+void ExtensionsToolbarButton::UpdateIcon() {
+  SetImageModel(views::Button::STATE_NORMAL,
+                ui::ImageModel::FromVectorIcon(
+                    vector_icons::kExtensionIcon,
+                    extensions_container_->GetIconColor(), GetIconSize()));
+}
+
 void ExtensionsToolbarButton::ButtonPressed(views::Button* sender,
                                             const ui::Event& event) {
   if (ExtensionsMenuView::IsShowing()) {
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_button.h b/chrome/browser/ui/views/extensions/extensions_toolbar_button.h
index 86f7be1..a686432 100644
--- a/chrome/browser/ui/views/extensions/extensions_toolbar_button.h
+++ b/chrome/browser/ui/views/extensions/extensions_toolbar_button.h
@@ -23,13 +23,12 @@
                           ExtensionsToolbarContainer* extensions_container);
   ~ExtensionsToolbarButton() override;
 
-  void UpdateIcon();
-
   // ToolbarButton:
   gfx::Size CalculatePreferredSize() const override;
   gfx::Size GetMinimumSize() const override;
   void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
   const char* GetClassName() const override;
+  void UpdateIcon() override;
 
   // views::ButtonListener:
   void ButtonPressed(views::Button* sender, const ui::Event& event) override;
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc b/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc
index 026c2a3..e835433 100644
--- a/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc
+++ b/chrome/browser/ui/views/extensions/extensions_toolbar_container.cc
@@ -105,8 +105,6 @@
 }
 
 void ExtensionsToolbarContainer::UpdateAllIcons() {
-  extensions_button_->UpdateIcon();
-
   for (const auto& action : actions_)
     action->UpdateState();
 }
diff --git a/chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.h b/chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.h
index 62240028..0dc9b104 100644
--- a/chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.h
+++ b/chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.h
@@ -37,11 +37,9 @@
   // views::ButtonListener implementation.
   void ButtonPressed(views::Button* sender, const ui::Event& event) override;
 
-  // views::InkDropHostView implementation.
+  // ToolbarButton implementation.
   SkColor GetInkDropBaseColor() const override;
-
-  // Updates the icon image.
-  void UpdateIcon();
+  void UpdateIcon() override;
 
   void ShowPromo();
 
diff --git a/chrome/browser/ui/views/media_router/cast_toolbar_button.h b/chrome/browser/ui/views/media_router/cast_toolbar_button.h
index a43b740..106594e 100644
--- a/chrome/browser/ui/views/media_router/cast_toolbar_button.h
+++ b/chrome/browser/ui/views/media_router/cast_toolbar_button.h
@@ -38,9 +38,6 @@
                     std::unique_ptr<MediaRouterContextualMenu> context_menu);
   ~CastToolbarButton() override;
 
-  // Updates the icon image.
-  void UpdateIcon();
-
   // MediaRouterActionController::Observer:
   void ShowIcon() override;
   void HideIcon() override;
@@ -60,6 +57,7 @@
   bool OnMousePressed(const ui::MouseEvent& event) override;
   void OnMouseReleased(const ui::MouseEvent& event) override;
   void OnGestureEvent(ui::GestureEvent* event) override;
+  void UpdateIcon() override;
 
   // views::ButtonListener:
   void ButtonPressed(views::Button* sender, const ui::Event& event) override;
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
index ecc038d91..a21c1c9 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -1546,6 +1546,46 @@
   return Textfield::HandleAccessibleAction(action_data);
 }
 
+void OmniboxViewViews::OnBoundsChanged(const gfx::Rect& previous_bounds) {
+  Textfield::OnBoundsChanged(previous_bounds);
+
+  if (!OmniboxFieldTrial::ShouldRevealPathQueryRefOnHover() &&
+      !OmniboxFieldTrial::ShouldHidePathQueryRefOnInteraction()) {
+    return;
+  }
+
+  // When simplified domain display field trials are enabled,
+  // Textfield::OnBoundsChanged() may have undone the effect of any previous URL
+  // elisions, because it expands the Textfield's display rect to the local
+  // bounds, which may bring more of the URL into view than intended. Re-apply
+  // simplified domain elisions now.
+
+  // Cancel any running animations. This could cause some abrupt transitions,
+  // but we can't adapt running animations to new bounds.
+  if (hover_elide_or_unelide_animation_)
+    hover_elide_or_unelide_animation_->Stop();
+  if (elide_after_interaction_animation_)
+    elide_after_interaction_animation_->Stop();
+
+  // |elide_after_interaction_animation_| is created when the user interacts
+  // with the page, if hide-on-interaction is enabled. If hide-on-interaction is
+  // disabled or the user has already interacted with the page, the simplified
+  // domain should have been showing before the bounds changed (or we would have
+  // been in the process of animating to the simplified domain).
+  if (!OmniboxFieldTrial::ShouldHidePathQueryRefOnInteraction() ||
+      elide_after_interaction_animation_) {
+    if (IsURLEligibleForSimplifiedDomainEliding() &&
+        !model()->ShouldPreventElision()) {
+      ElideURL();
+    }
+  } else {
+    // The user hasn't interacted with the page yet. This resets animation state
+    // and shows the partially elided URL with scheme and trivial subdomains
+    // hidden.
+    ResetToHideOnInteraction();
+  }
+}
+
 void OmniboxViewViews::OnFocus() {
   views::Textfield::OnFocus();
   // TODO(tommycli): This does not seem like it should be necessary.
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.h b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
index 6fbbf1cac..7052352b 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.h
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
@@ -175,6 +175,10 @@
       UserInteractionAndHover);
   FRIEND_TEST_ALL_PREFIXES(
       OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
+      BoundsChanged);
+  FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsRevealOnHoverTest, BoundsChanged);
+  FRIEND_TEST_ALL_PREFIXES(
+      OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
       SchemeAndTrivialSubdomainElision);
   FRIEND_TEST_ALL_PREFIXES(
       OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
@@ -367,6 +371,7 @@
   bool SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   bool HandleAccessibleAction(const ui::AXActionData& action_data) override;
+  void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
   void OnFocus() override;
   void OnBlur() override;
   base::string16 GetSelectionClipboardText() const override;
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
index 2088e60..a83a4214 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
@@ -1738,6 +1738,94 @@
       omnibox_view(), kSimplifiedDomainDisplayUrlSubdomainAndScheme));
 }
 
+// Tests that simplified domain elisions are re-applied when the omnibox's
+// bounds change.
+TEST_P(OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest, BoundsChanged) {
+  SetUpSimplifiedDomainTest();
+  gfx::RenderText* render_text = omnibox_view()->GetRenderText();
+
+  content::MockNavigationHandle navigation;
+  navigation.set_is_same_document(false);
+  omnibox_view()->DidFinishNavigation(&navigation);
+  ASSERT_NO_FATAL_FAILURE(ExpectUnelidedFromSimplifiedDomain(
+      omnibox_view()->GetRenderText(),
+      gfx::Range(kSimplifiedDomainDisplayUrlScheme.size(),
+                 kSimplifiedDomainDisplayUrl.size())));
+
+  // After the bounds change, the URL should remain unelided.
+  omnibox_view()->OnBoundsChanged(gfx::Rect());
+  ASSERT_NO_FATAL_FAILURE(ExpectUnelidedFromSimplifiedDomain(
+      omnibox_view()->GetRenderText(),
+      gfx::Range(kSimplifiedDomainDisplayUrlScheme.size(),
+                 kSimplifiedDomainDisplayUrl.size())));
+
+  // Hover over the omnibox and change the bounds during the animation. The
+  // animation should be cancelled and immediately transition back to the
+  // unelided URL.
+  omnibox_view()->OnMouseMoved(CreateMouseEvent(ui::ET_MOUSE_MOVED, {0, 0}));
+  OmniboxViewViews::ElideAnimation* unelide_animation =
+      omnibox_view()->GetHoverElideOrUnelideAnimationForTesting();
+  ASSERT_TRUE(unelide_animation);
+  EXPECT_TRUE(unelide_animation->IsAnimating());
+  omnibox_view()->OnBoundsChanged(gfx::Rect());
+  ASSERT_NO_FATAL_FAILURE(ExpectUnelidedFromSimplifiedDomain(
+      omnibox_view()->GetRenderText(),
+      gfx::Range(kSimplifiedDomainDisplayUrlScheme.size(),
+                 kSimplifiedDomainDisplayUrl.size())));
+
+  // Simulate a user interaction and change the bounds during the animation. The
+  // animation should be cancelled and immediately transition to the animation's
+  // end state (simplified domain).
+  omnibox_view()->DidGetUserInteraction(
+      blink::WebInputEvent::Type::kGestureScrollBegin);
+  OmniboxViewViews::ElideAnimation* elide_animation =
+      omnibox_view()->GetElideAfterInteractionAnimationForTesting();
+  ASSERT_TRUE(elide_animation);
+  EXPECT_TRUE(elide_animation->IsAnimating());
+  omnibox_view()->OnBoundsChanged(gfx::Rect());
+  ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain(
+      render_text, kSimplifiedDomainDisplayUrlSubdomainAndScheme,
+      kSimplifiedDomainDisplayUrlSubdomain,
+      kSimplifiedDomainDisplayUrlHostnameAndScheme,
+      kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain()));
+}
+
+// Tests that simplified domain elisions are re-applied when the omnibox's
+// bounds change when only reveal-on-hover is enabled.
+TEST_P(OmniboxViewViewsRevealOnHoverTest, BoundsChanged) {
+  SetUpSimplifiedDomainTest();
+  gfx::RenderText* render_text = omnibox_view()->GetRenderText();
+
+  ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain(
+      render_text, kSimplifiedDomainDisplayUrlSubdomainAndScheme,
+      kSimplifiedDomainDisplayUrlSubdomain,
+      kSimplifiedDomainDisplayUrlHostnameAndScheme,
+      kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain()));
+
+  // After the bounds change, the URL should remain elided.
+  omnibox_view()->OnBoundsChanged(gfx::Rect());
+  ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain(
+      render_text, kSimplifiedDomainDisplayUrlSubdomainAndScheme,
+      kSimplifiedDomainDisplayUrlSubdomain,
+      kSimplifiedDomainDisplayUrlHostnameAndScheme,
+      kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain()));
+
+  // Hover over the omnibox and change the bounds during the animation. The
+  // animation should be cancelled and immediately transition back to the
+  // simplified domain.
+  omnibox_view()->OnMouseMoved(CreateMouseEvent(ui::ET_MOUSE_MOVED, {0, 0}));
+  OmniboxViewViews::ElideAnimation* unelide_animation =
+      omnibox_view()->GetHoverElideOrUnelideAnimationForTesting();
+  ASSERT_TRUE(unelide_animation);
+  EXPECT_TRUE(unelide_animation->IsAnimating());
+  omnibox_view()->OnBoundsChanged(gfx::Rect());
+  ASSERT_NO_FATAL_FAILURE(ExpectElidedToSimplifiedDomain(
+      render_text, kSimplifiedDomainDisplayUrlSubdomainAndScheme,
+      kSimplifiedDomainDisplayUrlSubdomain,
+      kSimplifiedDomainDisplayUrlHostnameAndScheme,
+      kSimplifiedDomainDisplayUrlPath, ShouldElideToRegistrableDomain()));
+}
+
 // Tests scheme and trivial subdomain elision when simplified domain field
 // trials are enabled.
 TEST_P(OmniboxViewViewsHideOnInteractionAndRevealOnHoverTest,
diff --git a/chrome/browser/ui/views/passwords/move_to_account_store_bubble_view.cc b/chrome/browser/ui/views/passwords/move_to_account_store_bubble_view.cc
index a2d734c..00a01402 100644
--- a/chrome/browser/ui/views/passwords/move_to_account_store_bubble_view.cc
+++ b/chrome/browser/ui/views/passwords/move_to_account_store_bubble_view.cc
@@ -8,6 +8,7 @@
 #include "base/bind.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/app/vector_icons/vector_icons.h"
+#include "chrome/browser/profiles/profile_avatar_icon_util.h"
 #include "chrome/browser/ui/passwords/bubble_controllers/move_to_account_store_bubble_controller.h"
 #include "chrome/browser/ui/passwords/passwords_model_delegate.h"
 #include "chrome/browser/ui/views/accessibility/non_accessible_image_view.h"
@@ -37,8 +38,7 @@
 constexpr int kBadgeSpacing = 4;
 constexpr int kImageSize = BadgedProfilePhoto::kImageSize;
 // Width and Height of the badged icon.
-constexpr int kBadgedProfilePhotoWidth = kImageSize + kBadgeSpacing;
-constexpr int kBadgedProfilePhotoHeight = kImageSize;
+constexpr int kBadgedProfilePhotoSize = kImageSize + kBadgeSpacing;
 
 // An image view that shows a vector icon and tracks changes in the theme.
 class VectorIconView : public views::ImageView {
@@ -102,18 +102,20 @@
   // Use a Globe icon as the default badge.
   auto badge_view =
       std::make_unique<VectorIconView>(kGlobeIcon, kBadgeIconSize);
-  badge_view->SetPosition(
-      gfx::Point(kBadgedProfilePhotoWidth - kBadgeIconSize,
-                 kBadgedProfilePhotoHeight - kBadgeIconSize));
+  badge_view->SetPosition(gfx::Point(kBadgedProfilePhotoSize - kBadgeIconSize,
+                                     kBadgedProfilePhotoSize - kBadgeIconSize));
   badge_view->SizeToPreferredSize();
   badge_view_ = AddChildView(std::move(badge_view));
 
-  SetPreferredSize(
-      gfx::Size(kBadgedProfilePhotoWidth, kBadgedProfilePhotoHeight));
+  SetPreferredSize(gfx::Size(kBadgedProfilePhotoSize, kBadgedProfilePhotoSize));
 }
 
 void ImageWithBadge::UpdateBadge(const gfx::ImageSkia& badge_image) {
-  badge_view_->SetImage(badge_image);
+  gfx::Image rounded_badge = profiles::GetSizedAvatarIcon(
+      gfx::Image(badge_image),
+      /*is_rectangle=*/true, /*width=*/gfx::kFaviconSize,
+      /*height=*/gfx::kFaviconSize, profiles::SHAPE_CIRCLE);
+  badge_view_->SetImage(rounded_badge.ToImageSkia());
   badge_view_->SizeToPreferredSize();
 }
 
diff --git a/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc b/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc
index 925ffe0..d492652a 100644
--- a/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc
+++ b/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc
@@ -16,8 +16,11 @@
 #include "chrome/browser/ui/views/payments/payment_request_views_util.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/payments/content/icon/icon_size.h"
+#include "components/payments/core/features.h"
 #include "components/payments/core/native_error_strings.h"
+#include "components/payments/core/payments_experimental_features.h"
 #include "components/payments/core/url_util.h"
+#include "components/vector_icons/vector_icons.h"
 #include "components/web_modal/web_contents_modal_dialog_manager.h"
 #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h"
 #include "content/public/browser/navigation_handle.h"
@@ -29,6 +32,7 @@
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/background.h"
 #include "ui/views/border.h"
 #include "ui/views/controls/image_view.h"
@@ -90,8 +94,28 @@
       title_label->SetEnabledColor(foreground);
     }
 
-    title_origin_layout->StartRow(views::GridLayout::kFixedSize, 0);
-    auto* origin_label = title_origin_layout->AddView(
+    auto origin_container = std::make_unique<views::View>();
+    views::GridLayout* origin_layout = origin_container->SetLayoutManager(
+        std::make_unique<views::GridLayout>());
+
+    columns = origin_layout->AddColumnSet(0);
+    columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
+                       1.0, views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
+    columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING,
+                       1.0, views::GridLayout::ColumnSize::kUsePreferred, 0, 0);
+    origin_layout->StartRow(views::GridLayout::kFixedSize, 0);
+    if (PaymentsExperimentalFeatures::IsEnabled(
+            features::kPaymentHandlerLockIcon) &&
+        origin.SchemeIs(url::kHttpsScheme)) {
+      // TODO(https://crbug.com/1052493):
+      // Selecting the correct icon based on the SSL certificate state
+      // and adding test coverage for this code path.
+      auto lock_icon = std::make_unique<views::ImageView>();
+      lock_icon->SetImage(gfx::CreateVectorIcon(vector_icons::kLockIcon, 16,
+                                                gfx::kChromeIconGrey));
+      origin_layout->AddView(std::move(lock_icon));
+    }
+    auto* origin_label = origin_layout->AddView(
         std::make_unique<views::Label>(base::UTF8ToUTF16(origin.host())));
     origin_label->SetElideBehavior(gfx::ELIDE_HEAD);
     if (!title_is_valid) {
@@ -108,6 +132,8 @@
     origin_label->SetAutoColorReadabilityEnabled(false);
     origin_label->SetEnabledColor(foreground);
     origin_label->SetBackgroundColor(background_color);
+    title_origin_layout->StartRow(views::GridLayout::kFixedSize, 0);
+    title_origin_layout->AddView(std::move(origin_container));
 
     views::GridLayout* top_level_layout =
         SetLayoutManager(std::make_unique<views::GridLayout>());
diff --git a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.cc b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.cc
index e63aadd..96a4a42 100644
--- a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.cc
+++ b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.cc
@@ -30,6 +30,7 @@
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/text/bytes_formatting.h"
 #include "ui/chromeos/devicetype_utils.h"
+#include "ui/gfx/geometry/insets.h"
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/views/border.h"
 #include "ui/views/controls/image_view.h"
@@ -94,9 +95,7 @@
           plugin_vm::PluginVmInstallerFactory::GetForProfile(profile)) {
   // Layout constants from the spec.
   gfx::Insets kDialogInsets(60, 64, 0, 64);
-  constexpr gfx::Insets kLowerContainerInsets(12, 0, 52, 0);
   constexpr gfx::Size kLogoImageSize(32, 32);
-  constexpr gfx::Size kBigImageSize(264, 264);
   constexpr int kTitleFontSize = 28;
   const gfx::FontList kTitleFont({"Google Sans"}, gfx::Font::NORMAL,
                                  kTitleFontSize, gfx::Font::Weight::NORMAL);
@@ -128,9 +127,9 @@
   AddChildView(upper_container_view);
 
   views::View* lower_container_view = new views::View();
-  views::BoxLayout* lower_container_layout =
+  lower_container_layout_ =
       lower_container_view->SetLayoutManager(std::make_unique<views::BoxLayout>(
-          views::BoxLayout::Orientation::kVertical, kLowerContainerInsets));
+          views::BoxLayout::Orientation::kVertical));
   AddChildView(lower_container_view);
 
   views::ImageView* logo_image = new views::ImageView();
@@ -183,14 +182,10 @@
   upper_container_view->AddChildView(download_progress_message_label_);
 
   big_image_ = new views::ImageView();
-  big_image_->SetImageSize(kBigImageSize);
-  big_image_->SetImage(
-      ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
-          IDR_PLUGIN_VM_INSTALLER));
   lower_container_view->AddChildView(big_image_);
 
   // Make sure the lower_container_view is pinned to the bottom of the dialog.
-  lower_container_layout->set_main_axis_alignment(
+  lower_container_layout_->set_main_axis_alignment(
       views::BoxLayout::MainAxisAlignment::kEnd);
   layout->SetFlexForView(lower_container_view, 1, true);
 }
@@ -615,15 +610,26 @@
 }
 
 void PluginVmInstallerView::SetBigImage() {
-  if (state_ == State::kError) {
+  constexpr gfx::Size kRegularImageSize(314, 191);
+  constexpr gfx::Size kErrorImageSize(264, 264);
+  constexpr int kRegularImageBottomInset = 52 + 57;
+  constexpr int kErrorImageBottomInset = 52;
+
+  auto setImage = [this](int image_id, gfx::Size size, int bottom_inset) {
+    big_image_->SetImageSize(size);
+    lower_container_layout_->set_inside_border_insets(
+        gfx::Insets(0, 0, bottom_inset, 0));
     big_image_->SetImage(
-        ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
-            IDR_PLUGIN_VM_INSTALLER_ERROR));
+        ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(image_id));
+  };
+
+  if (state_ == State::kError) {
+    setImage(IDR_PLUGIN_VM_INSTALLER_ERROR, kErrorImageSize,
+             kErrorImageBottomInset);
     return;
   }
-  big_image_->SetImage(
-      ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
-          IDR_PLUGIN_VM_INSTALLER));
+  setImage(IDR_PLUGIN_VM_INSTALLER, kRegularImageSize,
+           kRegularImageBottomInset);
 }
 
 void PluginVmInstallerView::StartInstallation() {
diff --git a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.h b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.h
index 979d737f..f8abf2dd 100644
--- a/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.h
+++ b/chrome/browser/ui/views/plugin_vm/plugin_vm_installer_view.h
@@ -11,6 +11,7 @@
 #include "ui/views/bubble/bubble_dialog_delegate_view.h"
 
 namespace views {
+class BoxLayout;
 class ImageView;
 class Label;
 class Link;
@@ -89,6 +90,7 @@
   views::Label* message_label_ = nullptr;
   views::ProgressBar* progress_bar_ = nullptr;
   views::Label* download_progress_message_label_ = nullptr;
+  views::BoxLayout* lower_container_layout_ = nullptr;
   views::ImageView* big_image_ = nullptr;
   views::Link* learn_more_link_ = nullptr;
   base::TimeTicks setup_start_tick_;
diff --git a/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc b/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc
index 243a8d6..c80f25fc 100644
--- a/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc
+++ b/chrome/browser/ui/views/profiles/avatar_toolbar_button.cc
@@ -98,6 +98,8 @@
   for (auto state : kButtonStates)
     SetImage(state, GetAvatarIcon(state, gaia_account_image));
   delegate_->ShowIdentityAnimation(gaia_account_image);
+
+  SetInsets();
 }
 
 void AvatarToolbarButton::UpdateText() {
@@ -197,7 +199,6 @@
 
 void AvatarToolbarButton::OnThemeChanged() {
   ToolbarButton::OnThemeChanged();
-  UpdateIcon();
   UpdateText();
 }
 
diff --git a/chrome/browser/ui/views/profiles/avatar_toolbar_button.h b/chrome/browser/ui/views/profiles/avatar_toolbar_button.h
index dbe9c5069..33807b78 100644
--- a/chrome/browser/ui/views/profiles/avatar_toolbar_button.h
+++ b/chrome/browser/ui/views/profiles/avatar_toolbar_button.h
@@ -11,7 +11,6 @@
 #include "base/scoped_observer.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_button.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_icon_container_view.h"
-#include "ui/base/pointer/touch_ui_controller.h"
 #include "ui/events/event.h"
 
 class AvatarToolbarButtonDelegate;
@@ -45,7 +44,6 @@
   AvatarToolbarButton(Browser* browser, ToolbarIconContainerView* parent);
   ~AvatarToolbarButton() override;
 
-  void UpdateIcon();
   void UpdateText();
   void ShowAvatarHighlightAnimation();
   bool IsParentHighlighted() const;
@@ -60,6 +58,7 @@
   void OnMouseExited(const ui::MouseEvent& event) override;
   void OnBlur() override;
   void OnThemeChanged() override;
+  void UpdateIcon() override;
 
   // ToolbarIconContainerView::Observer:
   void OnHighlightChanged() override;
@@ -80,18 +79,11 @@
 
   void SetInsets();
 
-  void OnTouchUiChanged();
-
   std::unique_ptr<AvatarToolbarButtonDelegate> delegate_;
 
   Browser* const browser_;
   ToolbarIconContainerView* const parent_;
 
-  std::unique_ptr<ui::TouchUiController::Subscription> subscription_ =
-      ui::TouchUiController::Get()->RegisterCallback(
-          base::BindRepeating(&AvatarToolbarButton::SetInsets,
-                              base::Unretained(this)));
-
   base::ObserverList<Observer>::Unchecked observer_list_;
 
   base::WeakPtrFactory<AvatarToolbarButton> weak_ptr_factory_{this};
diff --git a/chrome/browser/ui/views/toolbar/back_forward_button.cc b/chrome/browser/ui/views/toolbar/back_forward_button.cc
index 33453880..1a1dee1 100644
--- a/chrome/browser/ui/views/toolbar/back_forward_button.cc
+++ b/chrome/browser/ui/views/toolbar/back_forward_button.cc
@@ -44,3 +44,15 @@
 }
 
 BackForwardButton::~BackForwardButton() = default;
+
+void BackForwardButton::UpdateIcon() {
+  const gfx::VectorIcon* image = nullptr;
+  const bool touch_ui = ui::TouchUiController::Get()->touch_ui();
+  if (direction_ == Direction::kBack) {
+    image = touch_ui ? &kBackArrowTouchIcon : &vector_icons::kBackArrowIcon;
+  } else {
+    image =
+        touch_ui ? &kForwardArrowTouchIcon : &vector_icons::kForwardArrowIcon;
+  }
+  UpdateIconsWithStandardColors(*image);
+}
diff --git a/chrome/browser/ui/views/toolbar/back_forward_button.h b/chrome/browser/ui/views/toolbar/back_forward_button.h
index 8460c8b4..4323c2f 100644
--- a/chrome/browser/ui/views/toolbar/back_forward_button.h
+++ b/chrome/browser/ui/views/toolbar/back_forward_button.h
@@ -20,6 +20,9 @@
   BackForwardButton& operator=(const BackForwardButton&) = delete;
   ~BackForwardButton() override;
 
+  // ToolbarButton:
+  void UpdateIcon() override;
+
  private:
   Direction direction_;
 };
diff --git a/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc b/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc
index c0896ed..8554f6e 100644
--- a/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc
+++ b/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc
@@ -270,11 +270,6 @@
   }
 }
 
-void BrowserAppMenuButton::OnThemeChanged() {
-  AppMenuButton::OnThemeChanged();
-  UpdateIcon();
-}
-
 const char* BrowserAppMenuButton::GetClassName() const {
   return "BrowserAppMenuButton";
 }
@@ -368,7 +363,6 @@
 }
 
 void BrowserAppMenuButton::OnTouchUiChanged() {
-  UpdateIcon();
   UpdateColorsAndInsets();
   PreferredSizeChanged();
 }
diff --git a/chrome/browser/ui/views/toolbar/browser_app_menu_button.h b/chrome/browser/ui/views/toolbar/browser_app_menu_button.h
index 5fe7b0e4..5169533 100644
--- a/chrome/browser/ui/views/toolbar/browser_app_menu_button.h
+++ b/chrome/browser/ui/views/toolbar/browser_app_menu_button.h
@@ -14,7 +14,6 @@
 #include "chrome/browser/ui/toolbar/app_menu_icon_controller.h"
 #include "chrome/browser/ui/views/frame/app_menu_button.h"
 #include "components/feature_engagement/buildflags.h"
-#include "ui/base/pointer/touch_ui_controller.h"
 #include "ui/views/view.h"
 
 class ToolbarView;
@@ -45,15 +44,11 @@
   // noticeable color, and the menu item appearance may be affected.
   void SetPromoFeature(base::Optional<InProductHelpFeature> promo_feature);
 
-  // Updates the presentation according to |severity_| and the theme provider.
-  void UpdateIcon();
-
   // Opens the app menu immediately during a drag-and-drop operation.
   // Used only in testing.
   static bool g_open_app_immediately_for_testing;
 
   // AppMenuButton:
-  void OnThemeChanged() override;
   const char* GetClassName() const override;
   bool GetDropFormats(int* formats,
                       std::set<ui::ClipboardFormatType>* format_types) override;
@@ -68,6 +63,8 @@
   std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override;
   SkColor GetInkDropBaseColor() const override;
   base::string16 GetTooltipText(const gfx::Point& p) const override;
+  // Updates the presentation according to |severity_| and the theme provider.
+  void UpdateIcon() override;
 
  protected:
   // If the button is being used as an anchor for a promo, returns the best
diff --git a/chrome/browser/ui/views/toolbar/button_utils.cc b/chrome/browser/ui/views/toolbar/button_utils.cc
deleted file mode 100644
index 6d2543a7..0000000
--- a/chrome/browser/ui/views/toolbar/button_utils.cc
+++ /dev/null
@@ -1,13 +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/ui/views/toolbar/button_utils.h"
-
-#if defined(OS_WIN)
-#include "base/win/windows_version.h"
-
-bool UseWindowsIconsForMinimalUI() {
-  return base::win::GetVersion() >= base::win::Version::WIN10;
-}
-#endif
diff --git a/chrome/browser/ui/views/toolbar/button_utils.h b/chrome/browser/ui/views/toolbar/button_utils.h
deleted file mode 100644
index 0523af79..0000000
--- a/chrome/browser/ui/views/toolbar/button_utils.h
+++ /dev/null
@@ -1,17 +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_UI_VIEWS_TOOLBAR_BUTTON_UTILS_H_
-#define CHROME_BROWSER_UI_VIEWS_TOOLBAR_BUTTON_UTILS_H_
-
-#include "build/build_config.h"
-
-#if defined(OS_WIN)
-// For Windows 10 and later, we use custom icons for minimal-ui web app
-// Back and Reload buttons, to conform to the native OS' appearance.
-// https://w3c.github.io/manifest/#dom-displaymodetype-minimal-ui
-bool UseWindowsIconsForMinimalUI();
-#endif
-
-#endif  // CHROME_BROWSER_UI_VIEWS_TOOLBAR_BUTTON_UTILS_H_
diff --git a/chrome/browser/ui/views/toolbar/home_button.cc b/chrome/browser/ui/views/toolbar/home_button.cc
index e5c18c5..b1fb3fad 100644
--- a/chrome/browser/ui/views/toolbar/home_button.cc
+++ b/chrome/browser/ui/views/toolbar/home_button.cc
@@ -6,6 +6,7 @@
 
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_dialogs.h"
@@ -192,3 +193,10 @@
   }
   return ui::DragDropTypes::DRAG_NONE;
 }
+
+void HomeButton::UpdateIcon() {
+  const gfx::VectorIcon& home_image = ui::TouchUiController::Get()->touch_ui()
+                                          ? kNavigateHomeTouchIcon
+                                          : kNavigateHomeIcon;
+  UpdateIconsWithStandardColors(home_image);
+}
diff --git a/chrome/browser/ui/views/toolbar/home_button.h b/chrome/browser/ui/views/toolbar/home_button.h
index c2e9e21a..b4dbce0 100644
--- a/chrome/browser/ui/views/toolbar/home_button.h
+++ b/chrome/browser/ui/views/toolbar/home_button.h
@@ -24,6 +24,7 @@
   bool CanDrop(const OSExchangeData& data) override;
   int OnDragUpdated(const ui::DropTargetEvent& event) override;
   int OnPerformDrop(const ui::DropTargetEvent& event) override;
+  void UpdateIcon() override;
 
  private:
   Browser* const browser_;
diff --git a/chrome/browser/ui/views/toolbar/reload_button.cc b/chrome/browser/ui/views/toolbar/reload_button.cc
index 4dc1338..fd5ddcc 100644
--- a/chrome/browser/ui/views/toolbar/reload_button.cc
+++ b/chrome/browser/ui/views/toolbar/reload_button.cc
@@ -14,7 +14,6 @@
 #include "chrome/browser/command_updater.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/view_ids.h"
-#include "chrome/browser/ui/views/toolbar/button_utils.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -29,23 +28,8 @@
 
 namespace {
 
-const gfx::VectorIcon& GetIconForMode(ReloadButton::IconStyle icon_style,
-                                      bool is_reload) {
-  const bool touch_ui = ui::TouchUiController::Get()->touch_ui();
-
-#if defined(OS_WIN)
-  if (icon_style == ReloadButton::IconStyle::kMinimalUi &&
-      UseWindowsIconsForMinimalUI()) {
-    if (touch_ui) {
-      return is_reload ? kReloadWindowsTouchIcon
-                       : kNavigateStopWindowsTouchIcon;
-    }
-
-    return is_reload ? kReloadWindowsIcon : kNavigateStopWindowsIcon;
-  }
-#endif
-
-  if (touch_ui)
+const gfx::VectorIcon& GetIconForMode(bool is_reload) {
+  if (ui::TouchUiController::Get()->touch_ui())
     return is_reload ? kReloadTouchIcon : kNavigateStopTouchIcon;
 
   return is_reload ? vector_icons::kReloadIcon : kNavigateStopIcon;
@@ -58,11 +42,9 @@
 // static
 const char ReloadButton::kViewClassName[] = "ReloadButton";
 
-ReloadButton::ReloadButton(CommandUpdater* command_updater,
-                           IconStyle icon_style)
+ReloadButton::ReloadButton(CommandUpdater* command_updater)
     : ToolbarButton(this, CreateMenuModel(), nullptr),
       command_updater_(command_updater),
-      icon_style_(icon_style),
       double_click_timer_delay_(
           base::TimeDelta::FromMilliseconds(views::GetDoubleClickInterval())),
       mode_switch_timer_delay_(base::TimeDelta::FromMilliseconds(1350)) {
@@ -106,12 +88,6 @@
   }
 }
 
-void ReloadButton::SetColors(SkColor normal_color, SkColor disabled_color) {
-  normal_color_ = normal_color;
-  disabled_color_ = disabled_color;
-  UpdateIcon();
-}
-
 void ReloadButton::OnThemeChanged() {
   ToolbarButton::OnThemeChanged();
   UpdateIcon();
@@ -123,15 +99,7 @@
   if (!GetWidget())
     return;
 
-  const gfx::VectorIcon& icon =
-      GetIconForMode(icon_style_, visible_mode_ == Mode::kReload);
-  DCHECK_EQ(normal_color_.has_value(), disabled_color_.has_value());
-  if (normal_color_.has_value()) {
-    UpdateIconsWithColors(icon, normal_color_.value(), normal_color_.value(),
-                          normal_color_.value(), disabled_color_.value());
-  } else {
-    UpdateIconsWithStandardColors(icon);
-  }
+  UpdateIconsWithStandardColors(GetIconForMode(visible_mode_ == Mode::kReload));
 }
 
 void ReloadButton::OnMouseExited(const ui::MouseEvent& event) {
diff --git a/chrome/browser/ui/views/toolbar/reload_button.h b/chrome/browser/ui/views/toolbar/reload_button.h
index 8db1d0a..33aceebf 100644
--- a/chrome/browser/ui/views/toolbar/reload_button.h
+++ b/chrome/browser/ui/views/toolbar/reload_button.h
@@ -26,13 +26,12 @@
                      public views::ButtonListener,
                      public ui::SimpleMenuModel::Delegate {
  public:
-  enum class IconStyle { kBrowser, kMinimalUi };
   enum class Mode { kReload = 0, kStop };
 
   // The button's class name.
   static const char kViewClassName[];
 
-  explicit ReloadButton(CommandUpdater* command_updater, IconStyle icon_style);
+  explicit ReloadButton(CommandUpdater* command_updater);
   ReloadButton(const ReloadButton&) = delete;
   ReloadButton& operator=(const ReloadButton&) = delete;
   ~ReloadButton() override;
@@ -40,12 +39,11 @@
   // Ask for a specified button state.  If |force| is true this will be applied
   // immediately.
   void ChangeMode(Mode mode, bool force);
+  Mode visible_mode() const { return visible_mode_; }
 
   // Enable reload drop-down menu.
   void set_menu_enabled(bool enable) { menu_enabled_ = enable; }
 
-  void SetColors(SkColor normal_color, SkColor disabled_color);
-
   // views::View:
   void OnThemeChanged() override;
 
@@ -56,6 +54,7 @@
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   bool ShouldShowMenu() override;
   void ShowDropDownMenu(ui::MenuSourceType source_type) override;
+  void UpdateIcon() override;
 
   // views::ButtonListener:
   void ButtonPressed(views::Button* /* button */,
@@ -76,9 +75,6 @@
 
   void ExecuteBrowserCommand(int command, int event_flags);
 
-  // Updates the icon images.
-  void UpdateIcon();
-
   void OnDoubleClickTimer();
   void OnStopToReloadTimer();
   void OnLongLoadTimer();
@@ -91,8 +87,6 @@
   // This may be NULL when testing.
   CommandUpdater* command_updater_;
 
-  const IconStyle icon_style_;
-
   // The mode we should be in assuming no timers are running.
   Mode intended_mode_ = Mode::kReload;
 
@@ -104,10 +98,6 @@
   base::TimeDelta double_click_timer_delay_;
   base::TimeDelta mode_switch_timer_delay_;
 
-  // The colors used for the icon if explicitly set by SetColors().
-  base::Optional<SkColor> normal_color_;
-  base::Optional<SkColor> disabled_color_;
-
   // Indicates if reload menu is enabled.
   bool menu_enabled_ = false;
 
diff --git a/chrome/browser/ui/views/toolbar/reload_button_unittest.cc b/chrome/browser/ui/views/toolbar/reload_button_unittest.cc
index f3cca24..9a216ef 100644
--- a/chrome/browser/ui/views/toolbar/reload_button_unittest.cc
+++ b/chrome/browser/ui/views/toolbar/reload_button_unittest.cc
@@ -38,8 +38,7 @@
   ReloadButton reload_;
 };
 
-ReloadButtonTest::ReloadButtonTest()
-    : reload_(nullptr, ReloadButton::IconStyle::kBrowser) {
+ReloadButtonTest::ReloadButtonTest() : reload_(nullptr) {
   // Set the timer delays to 0 so that timers will fire as soon as we tell the
   // message loop to run pending tasks.
   reload_.double_click_timer_delay_ = base::TimeDelta();
diff --git a/chrome/browser/ui/views/toolbar/sharesheet_button.h b/chrome/browser/ui/views/toolbar/sharesheet_button.h
index 169fab8..5e4eefe 100644
--- a/chrome/browser/ui/views/toolbar/sharesheet_button.h
+++ b/chrome/browser/ui/views/toolbar/sharesheet_button.h
@@ -16,7 +16,8 @@
   SharesheetButton& operator=(const SharesheetButton&) = delete;
   ~SharesheetButton() override;
 
-  void UpdateIcon();
+  // ToolbarButton:
+  void UpdateIcon() override;
 
  private:
   // views::ButtonListener:
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.cc b/chrome/browser/ui/views/toolbar/toolbar_button.cc
index cc262c53..e473b08 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_button.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_button.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/ui/views/toolbar/toolbar_ink_drop_util.h"
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_node_data.h"
+#include "ui/base/models/image_model.h"
 #include "ui/base/models/menu_model.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
@@ -198,14 +199,14 @@
                                           SkColor hovered_color,
                                           SkColor pressed_color,
                                           SkColor disabled_color) {
-  SetImage(ButtonState::STATE_NORMAL,
-           gfx::CreateVectorIcon(icon, normal_color));
-  SetImage(ButtonState::STATE_HOVERED,
-           gfx::CreateVectorIcon(icon, hovered_color));
-  SetImage(ButtonState::STATE_PRESSED,
-           gfx::CreateVectorIcon(icon, pressed_color));
-  SetImage(views::Button::STATE_DISABLED,
-           gfx::CreateVectorIcon(icon, disabled_color));
+  SetImageModel(ButtonState::STATE_NORMAL,
+                ui::ImageModel::FromVectorIcon(icon, normal_color));
+  SetImageModel(ButtonState::STATE_HOVERED,
+                ui::ImageModel::FromVectorIcon(icon, hovered_color));
+  SetImageModel(ButtonState::STATE_PRESSED,
+                ui::ImageModel::FromVectorIcon(icon, pressed_color));
+  SetImageModel(Button::STATE_DISABLED,
+                ui::ImageModel::FromVectorIcon(icon, disabled_color));
 }
 
 void ToolbarButton::UpdateIconsWithStandardColors(const gfx::VectorIcon& icon) {
@@ -277,9 +278,12 @@
 }
 
 void ToolbarButton::OnThemeChanged() {
-  LabelButton::OnThemeChanged();
   if (installable_ink_drop_)
     installable_ink_drop_->SetConfig(GetToolbarInstallableInkDropConfig(this));
+  UpdateIcon();
+
+  // Call this after UpdateIcon() to properly reset images.
+  LabelButton::OnThemeChanged();
 }
 
 gfx::Rect ToolbarButton::GetAnchorBoundsInScreen() const {
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.h b/chrome/browser/ui/views/toolbar/toolbar_button.h
index 70fdc8d8..0066598 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_button.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_button.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "base/optional.h"
+#include "ui/base/pointer/touch_ui_controller.h"
 #include "ui/base/theme_provider.h"
 #include "ui/gfx/animation/animation_delegate.h"
 #include "ui/gfx/animation/slide_animation.h"
@@ -78,6 +79,10 @@
   // GetForegroundColor().
   void UpdateIconsWithStandardColors(const gfx::VectorIcon& icon);
 
+  // Updates the icon images and colors as necessary. Should be called any time
+  // icon state changes, e.g. in response to theme or touch mode changes.
+  virtual void UpdateIcon() {}
+
   // Sets |layout_insets_|, see comment there.
   void SetLayoutInsets(const gfx::Insets& insets);
 
@@ -273,6 +278,11 @@
   base::Optional<SkColor> last_border_color_;
   gfx::Insets last_paint_insets_;
 
+  std::unique_ptr<ui::TouchUiController::Subscription> subscription_ =
+      ui::TouchUiController::Get()->RegisterCallback(
+          base::BindRepeating(&ToolbarButton::UpdateIcon,
+                              base::Unretained(this)));
+
   // A factory for tasks that show the dropdown context menu for the button.
   base::WeakPtrFactory<ToolbarButton> show_menu_factory_{this};
 };
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc
index 84a8a67..31fec4e 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -17,7 +17,6 @@
 #include "base/util/ranges/algorithm.h"
 #include "build/build_config.h"
 #include "chrome/app/chrome_command_ids.h"
-#include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/command_updater.h"
 #include "chrome/browser/media/router/media_router_feature.h"
 #include "chrome/browser/profiles/profile.h"
@@ -68,7 +67,6 @@
 #include "components/omnibox/browser/omnibox_view.h"
 #include "components/prefs/pref_service.h"
 #include "components/strings/grit/components_strings.h"
-#include "components/vector_icons/vector_icons.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "media/base/media_switches.h"
@@ -205,8 +203,8 @@
   std::unique_ptr<ToolbarButton> forward = std::make_unique<BackForwardButton>(
       BackForwardButton::Direction::kForward, this, browser_);
 
-  std::unique_ptr<ReloadButton> reload = std::make_unique<ReloadButton>(
-      browser_->command_controller(), ReloadButton::IconStyle::kBrowser);
+  std::unique_ptr<ReloadButton> reload =
+      std::make_unique<ReloadButton>(browser_->command_controller());
 
   std::unique_ptr<HomeButton> home =
       std::make_unique<HomeButton>(this, browser_);
@@ -915,39 +913,11 @@
         ThemeProperties::COLOR_TOOLBAR_VERTICAL_SEPARATOR));
   }
 
-  const bool touch_ui = ui::TouchUiController::Get()->touch_ui();
-
-  const gfx::VectorIcon& back_image =
-      touch_ui ? kBackArrowTouchIcon : vector_icons::kBackArrowIcon;
-  back_->UpdateIconsWithStandardColors(back_image);
-
-  const gfx::VectorIcon& forward_image =
-      touch_ui ? kForwardArrowTouchIcon : vector_icons::kForwardArrowIcon;
-  forward_->UpdateIconsWithStandardColors(forward_image);
-
-  const gfx::VectorIcon& home_image =
-      touch_ui ? kNavigateHomeTouchIcon : kNavigateHomeIcon;
-  home_->UpdateIconsWithStandardColors(home_image);
-
   if (extensions_container_)
     extensions_container_->UpdateAllIcons();
 
-  if (cast_)
-    cast_->UpdateIcon();
-
-  if (media_button_)
-    media_button_->UpdateIcon();
-
-  if (sharesheet_button_)
-    sharesheet_button_->UpdateIcon();
-
-  if (avatar_)
-    avatar_->UpdateIcon();
-
   if (toolbar_account_icon_container_)
     toolbar_account_icon_container_->UpdateAllIcons();
-
-  app_menu_button_->UpdateIcon();
 }
 
 void ToolbarView::ShowCriticalNotification() {
diff --git a/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.cc b/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.cc
index 950e1b18..a53bddc 100644
--- a/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.cc
+++ b/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.cc
@@ -35,7 +35,6 @@
 #include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
 #include "chrome/browser/ui/views/toolbar/back_forward_button.h"
 #include "chrome/browser/ui/views/toolbar/browser_actions_container.h"
-#include "chrome/browser/ui/views/toolbar/button_utils.h"
 #include "chrome/browser/ui/views/toolbar/reload_button.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_button.h"
 #include "chrome/browser/ui/views/web_apps/web_app_menu_button.h"
@@ -75,6 +74,10 @@
 #include "ui/views/window/custom_frame_view.h"
 #include "ui/views/window/hit_test_utils.h"
 
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
+
 namespace {
 
 bool g_animation_disabled_for_testing = false;
@@ -115,6 +118,109 @@
   DISALLOW_COPY_AND_ASSIGN(WebAppToolbarActionsBar);
 };
 
+template <class BaseClass>
+class WebAppToolbarButton : public BaseClass {
+ public:
+  using BaseClass::BaseClass;
+  WebAppToolbarButton(const WebAppToolbarButton&) = delete;
+  WebAppToolbarButton& operator=(const WebAppToolbarButton&) = delete;
+  ~WebAppToolbarButton() override = default;
+
+#if defined(OS_WIN)
+  bool ShouldUseWindowsIconsForMinimalUI() const {
+    return base::win::GetVersion() >= base::win::Version::WIN10;
+  }
+#endif
+
+  void SetIconColor(SkColor icon_color) {
+    if (icon_color_ == icon_color)
+      return;
+
+    icon_color_ = icon_color;
+    UpdateIcon();
+  }
+
+  virtual const gfx::VectorIcon* GetAlternativeIcon() const { return nullptr; }
+
+  // ToolbarButton:
+  void UpdateIcon() override {
+    if (const auto* icon = GetAlternativeIcon()) {
+      BaseClass::UpdateIconsWithStandardColors(*icon);
+      return;
+    }
+
+    BaseClass::UpdateIcon();
+  }
+
+ protected:
+  // ToolbarButton:
+  SkColor GetForegroundColor(views::Button::ButtonState state) const override {
+    if (state == views::Button::STATE_DISABLED)
+      return SkColorSetA(icon_color_, gfx::kDisabledControlAlpha);
+
+    return icon_color_;
+  }
+
+ private:
+  SkColor icon_color_ = gfx::kPlaceholderColor;
+};
+
+class WebAppToolbarBackButton : public WebAppToolbarButton<BackForwardButton> {
+ public:
+  WebAppToolbarBackButton(views::ButtonListener* listener, Browser* browser);
+  WebAppToolbarBackButton(const WebAppToolbarBackButton&) = delete;
+  WebAppToolbarBackButton& operator=(const WebAppToolbarBackButton&) = delete;
+  ~WebAppToolbarBackButton() override = default;
+
+  // WebAppToolbarButton:
+  const gfx::VectorIcon* GetAlternativeIcon() const override;
+};
+
+WebAppToolbarBackButton::WebAppToolbarBackButton(
+    views::ButtonListener* listener,
+    Browser* browser)
+    : WebAppToolbarButton<BackForwardButton>(
+          BackForwardButton::Direction::kBack,
+          listener,
+          browser) {}
+
+const gfx::VectorIcon* WebAppToolbarBackButton::GetAlternativeIcon() const {
+#if defined(OS_WIN)
+  if (ShouldUseWindowsIconsForMinimalUI()) {
+    return ui::TouchUiController::Get()->touch_ui()
+               ? &kBackArrowWindowsTouchIcon
+               : &kBackArrowWindowsIcon;
+  }
+#endif
+  return nullptr;
+}
+
+class WebAppToolbarReloadButton : public WebAppToolbarButton<ReloadButton> {
+ public:
+  using WebAppToolbarButton<ReloadButton>::WebAppToolbarButton;
+  WebAppToolbarReloadButton(const WebAppToolbarReloadButton&) = delete;
+  WebAppToolbarReloadButton& operator=(const WebAppToolbarReloadButton&) =
+      delete;
+  ~WebAppToolbarReloadButton() override = default;
+
+  // WebAppToolbarButton:
+  const gfx::VectorIcon* GetAlternativeIcon() const override;
+};
+
+const gfx::VectorIcon* WebAppToolbarReloadButton::GetAlternativeIcon() const {
+#if defined(OS_WIN)
+  if (ShouldUseWindowsIconsForMinimalUI()) {
+    const bool is_reload = visible_mode() == ReloadButton::Mode::kReload;
+    if (ui::TouchUiController::Get()->touch_ui()) {
+      return is_reload ? &kReloadWindowsTouchIcon
+                       : &kNavigateStopWindowsTouchIcon;
+    }
+    return is_reload ? &kReloadWindowsIcon : &kNavigateStopWindowsIcon;
+  }
+#endif
+  return nullptr;
+}
+
 int HorizontalPaddingBetweenPageActionsAndAppMenuButtons() {
   return views::LayoutProvider::Get()->GetDistanceMetric(
       views::DISTANCE_RELATED_CONTROL_HORIZONTAL);
@@ -136,15 +242,6 @@
     toolbar_button->SetLayoutInsets(gfx::Insets(2));
 }
 
-const gfx::VectorIcon& GetBackImage(bool touch_ui) {
-#if defined(OS_WIN)
-  if (UseWindowsIconsForMinimalUI())
-    return touch_ui ? kBackArrowWindowsTouchIcon : kBackArrowWindowsIcon;
-#endif
-
-  return touch_ui ? kBackArrowTouchIcon : vector_icons::kBackArrowIcon;
-}
-
 }  // namespace
 
 const char WebAppFrameToolbarView::kViewClassName[] = "WebAppFrameToolbarView";
@@ -258,27 +355,12 @@
   explicit NavigationButtonContainer(BrowserView* browser_view);
   ~NavigationButtonContainer() override;
 
-  ToolbarButton* back_button() { return back_button_; }
-
-  ReloadButton* reload_button() { return reload_button_; }
+  WebAppToolbarBackButton* back_button() { return back_button_; }
+  WebAppToolbarReloadButton* reload_button() { return reload_button_; }
 
   void SetIconColor(SkColor icon_color) {
-    icon_color_ = icon_color;
-    GenerateMinimalUIButtonImages();
-  }
-
-  void GenerateMinimalUIButtonImages() {
-    const SkColor disabled_color =
-        SkColorSetA(icon_color_, gfx::kDisabledControlAlpha);
-
-    const bool touch_ui = ui::TouchUiController::Get()->touch_ui();
-    const gfx::VectorIcon& back_image = GetBackImage(touch_ui);
-    back_button_->SetImage(views::Button::STATE_NORMAL,
-                           gfx::CreateVectorIcon(back_image, icon_color_));
-    back_button_->SetImage(views::Button::STATE_DISABLED,
-                           gfx::CreateVectorIcon(back_image, disabled_color));
-
-    reload_button_->SetColors(icon_color_, disabled_color);
+    back_button_->SetIconColor(icon_color);
+    reload_button_->SetIconColor(icon_color);
   }
 
  protected:
@@ -312,16 +394,9 @@
   // The containing browser view.
   BrowserView* const browser_view_;
 
-  SkColor icon_color_ = gfx::kPlaceholderColor;
-
-  std::unique_ptr<ui::TouchUiController::Subscription> subscription_ =
-      ui::TouchUiController::Get()->RegisterCallback(base::BindRepeating(
-          &NavigationButtonContainer::GenerateMinimalUIButtonImages,
-          base::Unretained(this)));
-
   // These members are owned by the views hierarchy.
-  ToolbarButton* back_button_ = nullptr;
-  ReloadButton* reload_button_ = nullptr;
+  WebAppToolbarBackButton* back_button_ = nullptr;
+  WebAppToolbarReloadButton* reload_button_ = nullptr;
 };
 
 WebAppFrameToolbarView::NavigationButtonContainer::NavigationButtonContainer(
@@ -337,12 +412,11 @@
   layout.set_cross_axis_alignment(
       views::BoxLayout::CrossAxisAlignment::kCenter);
 
-  back_button_ = AddChildView(std::make_unique<BackForwardButton>(
-      BackForwardButton::Direction::kBack, this, browser_view_->browser()));
+  back_button_ = AddChildView(std::make_unique<WebAppToolbarBackButton>(
+      this, browser_view_->browser()));
   back_button_->set_tag(IDC_BACK);
-  reload_button_ = AddChildView(std::make_unique<ReloadButton>(
-      browser_view_->browser()->command_controller(),
-      ReloadButton::IconStyle::kMinimalUi));
+  reload_button_ = AddChildView(std::make_unique<WebAppToolbarReloadButton>(
+      browser_view_->browser()->command_controller()));
   reload_button_->set_tag(IDC_RELOAD);
 
   const bool is_browser_focus_mode = browser_view_->browser()->is_focus_mode();
diff --git a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.cc b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.cc
index a9dbb7b64..58835da 100644
--- a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.cc
@@ -47,6 +47,7 @@
       {"done", IDS_CROSTINI_UPGRADER_DONE_BUTTON},
       {"restore", IDS_CROSTINI_UPGRADER_RESTORE_BUTTON},
       {"learnMore", IDS_LEARN_MORE},
+      {"notNow", IDS_CROSTINI_UPGRADER_NOT_NOW},
 
       {"promptTitle", IDS_CROSTINI_UPGRADER_TITLE},
       {"backingUpTitle", IDS_CROSTINI_UPGRADER_BACKING_UP_TITLE},
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 79f70be..b60d6d9 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-master-1594857570-508aa514a52515f9e9dfbe5d476e51f86a549527.profdata
+chrome-mac-master-1594878809-35ea1154d4590798f7d37522056e8d492cada716.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 76cb488..a89f192 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-master-1594771186-8c7f3834398f8caaba6f32c369440926161c5207.profdata
+chrome-win64-master-1594814211-6e9c837aecb05743d0a6513baf4c13c15785a909.profdata
diff --git a/chrome/common/extensions/permissions/chrome_api_permissions.cc b/chrome/common/extensions/permissions/chrome_api_permissions.cc
index ec06f67..00aa1c2 100644
--- a/chrome/common/extensions/permissions/chrome_api_permissions.cc
+++ b/chrome/common/extensions/permissions/chrome_api_permissions.cc
@@ -44,7 +44,8 @@
     {APIPermission::kExperimental, "experimental",
      APIPermissionInfo::kFlagCannotBeOptional},
     {APIPermission::kGeolocation, "geolocation",
-     APIPermissionInfo::kFlagCannotBeOptional},
+     APIPermissionInfo::kFlagCannotBeOptional |
+         APIPermissionInfo::kFlagRequiresManagementUIWarning},
     {APIPermission::kNotifications, "notifications",
      APIPermissionInfo::kFlagDoesNotRequireManagedSessionFullLoginWarning},
     {APIPermission::kGcm, "gcm",
diff --git a/chrome/services/sharing/nearby/nearby_connections.cc b/chrome/services/sharing/nearby/nearby_connections.cc
index 13a1b76..7aa211a 100644
--- a/chrome/services/sharing/nearby/nearby_connections.cc
+++ b/chrome/services/sharing/nearby/nearby_connections.cc
@@ -5,6 +5,7 @@
 #include "chrome/services/sharing/nearby/nearby_connections.h"
 
 #include "base/run_loop.h"
+#include "third_party/nearby/src/cpp/core_v2/core.h"
 
 namespace location {
 namespace nearby {
@@ -41,11 +42,11 @@
   // There should only be one instance of NearbyConnections in a process.
   DCHECK(!g_instance);
   g_instance = this;
-  // TODO(alexchau): Create Core here after g_instance is set.
+  core_ = std::make_unique<Core>();
 }
 
 NearbyConnections::~NearbyConnections() {
-  // TODO(alexhcau): Destroy Core here before g_instance is reset.
+  core_.reset();
   g_instance = nullptr;
 }
 
diff --git a/chrome/services/sharing/nearby/nearby_connections.h b/chrome/services/sharing/nearby/nearby_connections.h
index e610775a..0b1c759a 100644
--- a/chrome/services/sharing/nearby/nearby_connections.h
+++ b/chrome/services/sharing/nearby/nearby_connections.h
@@ -16,10 +16,14 @@
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
+#include <memory>
+
 namespace location {
 namespace nearby {
 namespace connections {
 
+class Core;
+
 // Implementation of the NearbyConnections mojo interface.
 // This class acts as a bridge to the NearbyConnections library which is pulled
 // in as a third_party dependency. It handles the translation from mojo calls to
@@ -58,6 +62,8 @@
   mojo::Remote<sharing::mojom::WebRtcSignalingMessenger>
       webrtc_signaling_messenger_;
 
+  std::unique_ptr<Core> core_;
+
   base::WeakPtrFactory<NearbyConnections> weak_ptr_factory_{this};
 };
 
diff --git a/chrome/services/sharing/sharing_impl_unittest.cc b/chrome/services/sharing/sharing_impl_unittest.cc
index b3ea554..2ce37e3 100644
--- a/chrome/services/sharing/sharing_impl_unittest.cc
+++ b/chrome/services/sharing/sharing_impl_unittest.cc
@@ -87,7 +87,7 @@
   }
 
  protected:
-  base::test::SingleThreadTaskEnvironment task_environment_;
+  base::test::TaskEnvironment task_environment_;
   mojo::Remote<mojom::Sharing> remote_;
   std::unique_ptr<SharingImpl> service_;
 };
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index acdf97504..cafdf9e1 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -80,10 +80,13 @@
   android_library("test_support_java") {
     testonly = true
     deps = [
+      "//base:base_java",
       "//chrome/android:chrome_all_java",
       "//components/autofill/android:autofill_java",
       "//components/payments/content/android:java",
       "//components/payments/mojom:mojom_java",
+      "//content/public/android:content_java",
+      "//third_party/android_deps:androidx_annotation_annotation_java",
       "//third_party/blink/public/mojom:android_mojo_bindings_java",
     ]
     sources = [ "android/test_support/src/org/chromium/chrome/test_support/PaymentRequestTestBridge.java" ]
@@ -481,8 +484,6 @@
       "//testing/android/native_test:native_test_support",
     ]
 
-    data_deps = [ "//testing/buildbot/filters:android_browsertests_filters" ]
-
     sources = [
       "../browser/android/customtabs/custom_tabs_browsertest.cc",
       "../browser/android/webapk/webapk_icon_hasher_browsertest.cc",
@@ -3264,7 +3265,6 @@
     "../browser/page_load_metrics/metrics_web_contents_observer_unittest.cc",
     "../browser/page_load_metrics/observers/aborts_page_load_metrics_observer_unittest.cc",
     "../browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc",
-    "../browser/page_load_metrics/observers/ad_metrics/page_ad_density_tracker_unittest.cc",
     "../browser/page_load_metrics/observers/amp_page_load_metrics_observer_unittest.cc",
     "../browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer_test_utils.cc",
     "../browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer_test_utils.h",
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn
index 839c4b5..66a5360e 100644
--- a/chrome/test/android/BUILD.gn
+++ b/chrome/test/android/BUILD.gn
@@ -43,6 +43,7 @@
     "//base:base_java_test_support",
     "//chrome/android:chrome_java",
     "//chrome/browser/ui/android/appmenu/test:test_support_java",
+    "//third_party/android_deps:androidx_annotation_annotation_java",
     "//third_party/android_deps:androidx_drawerlayout_drawerlayout_java",
     "//third_party/android_deps:androidx_test_uiautomator_uiautomator_java",
     "//third_party/android_support_test_runner:runner_java",
@@ -67,6 +68,7 @@
     "//base:base_java_test_support",
     "//chrome/browser/flags:java",
     "//content/public/test/android:content_java_test_support",
+    "//third_party/android_deps:androidx_test_runner_java",
     "//third_party/hamcrest:hamcrest_java",
     "//third_party/junit",
   ]
@@ -87,11 +89,13 @@
     "//base:base_java",
     "//base:base_java_test_support",
     "//chrome/android:chrome_java",
+    "//chrome/browser/flags:java",
     "//chrome/browser/tab:java",
     "//chrome/browser/ui/android/native_page:java",
     "//components/embedder_support/android:util_java",
     "//content/public/test/android:content_java_test_support",
     "//third_party/android_deps:androidx_recyclerview_recyclerview_java",
+    "//third_party/android_deps:androidx_test_runner_java",
     "//third_party/android_deps:com_android_support_drawerlayout_java",
     "//third_party/android_deps:com_android_support_recyclerview_v7_java",
     "//third_party/android_deps:espresso_java",
@@ -119,6 +123,7 @@
     "//chrome/android/webapk/libs/client:client_java",
     "//components/webapk/android/libs/client:java",
     "//content/public/test/android:content_java_test_support",
+    "//third_party/android_deps:androidx_test_runner_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/junit",
   ]
@@ -139,6 +144,8 @@
   sources = [ "javatests/src/org/chromium/chrome/test/pagecontroller/tests/codelab/SettingsForCodelabTest.java" ]
   deps = [
     ":chrome_java_test_pagecontroller",
+    "//base:base_java_test_support",
+    "//third_party/android_deps:androidx_test_runner_java",
     "//third_party/junit",
   ]
 
@@ -248,9 +255,11 @@
     "//chrome/android/third_party/compositor_animator:compositor_animator_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/preferences:java",
+    "//chrome/browser/profiles/android:java",
     "//chrome/browser/settings:test_support_java",
     "//chrome/browser/tab:java",
     "//chrome/browser/tabmodel:java",
+    "//chrome/browser/thumbnail/generator:java",
     "//chrome/browser/ui/android/appmenu:java",
     "//chrome/browser/ui/android/appmenu/test:test_support_java",
     "//chrome/browser/ui/android/favicon:java",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java
index c0d08587..1a4e02d29 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java
@@ -11,6 +11,7 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.chrome.browser.SyncFirstSetupCompleteSource;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.signin.IdentityServicesProvider;
 import org.chromium.chrome.browser.signin.SigninManager;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
@@ -33,8 +34,9 @@
     static Account getCurrentAccount() {
         return TestThreadUtils.runOnUiThreadBlockingNoException(() -> {
             return CoreAccountInfo.getAndroidAccountFrom(
-                    IdentityServicesProvider.get().getIdentityManager().getPrimaryAccountInfo(
-                            ConsentLevel.SYNC));
+                    IdentityServicesProvider.get()
+                            .getIdentityManager(Profile.getLastUsedRegularProfile())
+                            .getPrimaryAccountInfo(ConsentLevel.SYNC));
         });
     }
 
@@ -44,7 +46,8 @@
     static void signIn(Account account) {
         CallbackHelper callbackHelper = new CallbackHelper();
         TestThreadUtils.runOnUiThreadBlocking(() -> {
-            SigninManager signinManager = IdentityServicesProvider.get().getSigninManager();
+            SigninManager signinManager = IdentityServicesProvider.get().getSigninManager(
+                    Profile.getLastUsedRegularProfile());
             signinManager.onFirstRunCheckDone(); // Allow sign-in
             signinManager.signIn(
                     SigninAccessPoint.UNKNOWN, account, new SigninManager.SignInCallback() {
@@ -69,7 +72,7 @@
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             Assert.assertEquals(account.name,
                     IdentityServicesProvider.get()
-                            .getIdentityManager()
+                            .getIdentityManager(Profile.getLastUsedRegularProfile())
                             .getPrimaryAccountInfo(ConsentLevel.SYNC)
                             .getEmail());
         });
@@ -83,7 +86,8 @@
         CallbackHelper ch = new CallbackHelper();
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             AccountTrackerService accountTrackerService =
-                    IdentityServicesProvider.get().getAccountTrackerService();
+                    IdentityServicesProvider.get().getAccountTrackerService(
+                            Profile.getLastUsedRegularProfile());
             if (accountTrackerService.checkAndSeedSystemAccounts()) {
                 ch.notifyCalled();
             } else {
@@ -109,8 +113,9 @@
         ThreadUtils.assertOnBackgroundThread();
         CallbackHelper callbackHelper = new CallbackHelper();
         TestThreadUtils.runOnUiThreadBlocking(() -> {
-            IdentityServicesProvider.get().getSigninManager().signOut(
-                    SignoutReason.SIGNOUT_TEST, callbackHelper::notifyCalled, false);
+            IdentityServicesProvider.get()
+                    .getSigninManager(Profile.getLastUsedRegularProfile())
+                    .signOut(SignoutReason.SIGNOUT_TEST, callbackHelper::notifyCalled, false);
         });
         try {
             callbackHelper.waitForFirst();
diff --git a/chrome/test/android/test_trusted_web_activity/BUILD.gn b/chrome/test/android/test_trusted_web_activity/BUILD.gn
index f8a3bc2..4911a9c 100644
--- a/chrome/test/android/test_trusted_web_activity/BUILD.gn
+++ b/chrome/test/android/test_trusted_web_activity/BUILD.gn
@@ -13,5 +13,8 @@
     "src/org/chromium/chrome/browser/browserservices/MessengerService.java",
     "src/org/chromium/chrome/browser/browserservices/TestTrustedWebActivityService.java",
   ]
-  deps = [ "//third_party/android_sdk/androidx_browser:androidx_browser_java" ]
+  deps = [
+    "//third_party/android_deps:androidx_annotation_annotation_java",
+    "//third_party/android_sdk/androidx_browser:androidx_browser_java",
+  ]
 }
diff --git a/chrome/test/data/ads_observer/ad_iframe_writer.js b/chrome/test/data/ads_observer/ad_iframe_writer.js
index b49e3a29..547188d 100644
--- a/chrome/test/data/ads_observer/ad_iframe_writer.js
+++ b/chrome/test/data/ads_observer/ad_iframe_writer.js
@@ -16,19 +16,3 @@
   document.body.appendChild(frame);
   return frame;
 }
-
-function createAdIframeAtRect(x, y, width, height) {
-  let frame = document.createElement('iframe');
-  frame.style.border = "0px none transparent";
-  frame.style.overflow = "hidden";
-  frame.style.position = "fixed";
-  frame.style.left = x;
-  frame.style.top = y;
-  frame.scrolling = "no";
-  frame.frameborder="0";
-  frame.allowTransparency="true";
-  frame.width = width;
-  frame.height = height;
-  document.body.appendChild(frame);
-  return frame;
-}
diff --git a/chrome/test/data/pdf/BUILD.gn b/chrome/test/data/pdf/BUILD.gn
index 9223d33..f4d49a4 100644
--- a/chrome/test/data/pdf/BUILD.gn
+++ b/chrome/test/data/pdf/BUILD.gn
@@ -12,12 +12,44 @@
                     "js_module_root=./gen/chrome/test/data/webui/",
                   ]
   deps = [
+    #":annotations_feature_enabled_test",
+    #":basic_plugin_test",
+    ":basic_test",
+
+    #":beep_test",
+    #":bookmarks_test",
     ":download_controls_test",
     ":gesture_detector_test",
+
+    #":layout_test",
+    #":material_elements_test",
+    #":metrics_test",
+    #":navigator_test",
+    #":nobeep_test",
+    #":page_change_test",
+    #":params_parser_test",
+    #":printing_icon_test",
+    #":redirects_fail_test",
     ":test_util",
+
+    #":title_test",
+    #":toolbar_manager_test",
+    #":touch_handling_test",
+    #":viewport_test",
+    #":whitespace_title_test",
+    #":zoom_manager_test",
   ]
 }
 
+js_library("basic_test") {
+  deps = [
+    "//chrome/browser/resources/pdf:pdf_viewer",
+    "//chrome/browser/resources/pdf/elements:viewer-pdf-toolbar",
+    "//chrome/browser/resources/pdf/elements:viewer-toolbar-dropdown",
+  ]
+  externs_list = [ "$externs_path/test.js" ]
+}
+
 js_library("gesture_detector_test") {
   deps = [
     "//chrome/browser/resources/pdf:gesture_detector",
diff --git a/chrome/test/data/pdf/basic_test.js b/chrome/test/data/pdf/basic_test.js
index 52667efb..e32b7ee 100644
--- a/chrome/test/data/pdf/basic_test.js
+++ b/chrome/test/data/pdf/basic_test.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {getFilenameFromURL} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/pdf_viewer.js';
+import {getFilenameFromURL, PDFViewerElement} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/pdf_viewer.js';
 import {shouldIgnoreKeyEvents} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/pdf_viewer_utils.js';
 import {$} from 'chrome://resources/js/util.m.js';
 import {pressAndReleaseKeyOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js';
@@ -13,7 +13,8 @@
    * verifies that Polymer is working correctly.
    */
   function testHasElements() {
-    const viewer = document.body.querySelector('pdf-viewer');
+    const viewer = /** @type {!PDFViewerElement} */ (
+        document.body.querySelector('pdf-viewer'));
     const elementNames = [
       'viewer-pdf-toolbar',
       'viewer-zoom-toolbar',
@@ -32,7 +33,8 @@
    * Test that the plugin element exists and is navigated to the correct URL.
    */
   function testPluginElement() {
-    const viewer = document.body.querySelector('pdf-viewer');
+    const viewer = /** @type {!PDFViewerElement} */ (
+        document.body.querySelector('pdf-viewer'));
     const plugin = viewer.shadowRoot.querySelector('#plugin');
     chrome.test.assertEq('embed', plugin.localName);
 
@@ -47,9 +49,11 @@
    */
   function testIgnoreKeyEvents() {
     // Test that the traversal through the shadow DOM works correctly.
-    const viewer = document.body.querySelector('pdf-viewer');
-    const toolbar = viewer.shadowRoot.querySelector('#toolbar');
-    toolbar.$.pageselector.pageSelector.focus();
+    const viewer = /** @type {!PDFViewerElement} */ (
+        document.body.querySelector('pdf-viewer'));
+    const toolbar = /** @type {!ViewerPdfToolbarElement} */ (
+        viewer.shadowRoot.querySelector('#toolbar'));
+    toolbar.$$('#pageselector').pageSelector.focus();
     chrome.test.assertTrue(shouldIgnoreKeyEvents(toolbar));
 
     // Test case where the active element has a shadow root of its own.
@@ -67,10 +71,13 @@
    * pressing escape.
    */
   function testOpenCloseBookmarks() {
-    const viewer = document.body.querySelector('pdf-viewer');
-    const toolbar = viewer.shadowRoot.querySelector('#toolbar');
+    const viewer = /** @type {!PDFViewerElement} */ (
+        document.body.querySelector('pdf-viewer'));
+    const toolbar = /** @type {!ViewerPdfToolbarElement} */ (
+        viewer.shadowRoot.querySelector('#toolbar'));
     toolbar.show();
-    const dropdown = toolbar.$.bookmarks;
+    const dropdown =
+        /** @type {!ViewerToolbarDropdownElement} */ (toolbar.$$('#bookmarks'));
     const plugin = viewer.shadowRoot.querySelector('#plugin');
     const ESC_KEY = 27;
 
diff --git a/chrome/test/data/webui/nearby_share/BUILD.gn b/chrome/test/data/webui/nearby_share/BUILD.gn
index 137a156f..18130787 100644
--- a/chrome/test/data/webui/nearby_share/BUILD.gn
+++ b/chrome/test/data/webui/nearby_share/BUILD.gn
@@ -13,11 +13,17 @@
                   ]
   deps = [
     ":nearby_confirmation_page_test",
+    ":nearby_device_test",
     ":nearby_preview_test",
     ":nearby_progress_test",
   ]
 }
 
+js_library("nearby_device_test") {
+  deps = [ "//chrome/browser/resources/nearby_share:nearby_device" ]
+  externs_list = [ "$externs_path/mocha-2.5.js" ]
+}
+
 js_library("nearby_confirmation_page_test") {
   deps = [ "//chrome/browser/resources/nearby_share:nearby_confirmation_page" ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
diff --git a/chrome/test/data/webui/nearby_share/nearby_browsertest.js b/chrome/test/data/webui/nearby_share/nearby_browsertest.js
index 1c26c6e..7460ded9 100644
--- a/chrome/test/data/webui/nearby_share/nearby_browsertest.js
+++ b/chrome/test/data/webui/nearby_share/nearby_browsertest.js
@@ -47,6 +47,7 @@
 };
 
 [['ConfirmationPage', 'nearby_confirmation_page_test.js'],
+ ['Device', 'nearby_device_test.js'],
  ['Preview', 'nearby_preview_test.js'],
  ['Progress', 'nearby_progress_test.js'],
 ].forEach(test => registerTest(...test));
diff --git a/chrome/test/data/webui/nearby_share/nearby_device_test.js b/chrome/test/data/webui/nearby_share/nearby_device_test.js
new file mode 100644
index 0000000..dce051a
--- /dev/null
+++ b/chrome/test/data/webui/nearby_share/nearby_device_test.js
@@ -0,0 +1,37 @@
+// Copyright 2020 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.
+
+// So that mojo is defined.
+import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
+
+import 'chrome://nearby/nearby_device.js';
+
+import {assertEquals} from '../chai_assert.js';
+
+suite('DeviceTest', function() {
+  /** @type {!NearbyDeviceElement} */
+  let deviceElement;
+
+  setup(function() {
+    deviceElement = /** @type {!NearbyDeviceElement} */ (
+        document.createElement('nearby-device'));
+    document.body.appendChild(deviceElement);
+  });
+
+  teardown(function() {
+    deviceElement.remove();
+  });
+
+  test('renders component', function() {
+    assertEquals('NEARBY-DEVICE', deviceElement.tagName);
+  });
+
+  test('renders name', function() {
+    const name = 'Name';
+    deviceElement.setAttribute('name', name);
+
+    const renderedName = deviceElement.$$('#name').textContent;
+    assertEquals(name, renderedName);
+  });
+});
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 456a3054..78c109c 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-13349.0.0
\ No newline at end of file
+13351.0.0
\ No newline at end of file
diff --git a/chromeos/components/media_app_ui/resources/js/web_app_file_handling.externs.js b/chromeos/components/media_app_ui/resources/js/web_app_file_handling.externs.js
index 3a31ae0..022f59fd 100644
--- a/chromeos/components/media_app_ui/resources/js/web_app_file_handling.externs.js
+++ b/chromeos/components/media_app_ui/resources/js/web_app_file_handling.externs.js
@@ -103,13 +103,6 @@
 /** @interface */
 class FileSystemFileHandle extends FileSystemHandle {
   /**
-   * @deprecated TODO(b/151564533): Remove when m82 is stable.
-   * @param {FileSystemCreateWriterOptions=} options
-   * @return {!Promise<!FileSystemWriter>}
-   */
-  createWriter(options) {}
-
-  /**
    * @param {FileSystemCreateWriterOptions=} options
    * @return {!Promise<!FileSystemWritableFileStream>}
    */
diff --git a/chromeos/components/media_app_ui/test/driver.js b/chromeos/components/media_app_ui/test/driver.js
index 26cefd0..29e15dce 100644
--- a/chromeos/components/media_app_ui/test/driver.js
+++ b/chromeos/components/media_app_ui/test/driver.js
@@ -146,10 +146,6 @@
     this.nextCreateWritableError;
   }
   /** @override */
-  createWriter(options) {
-    throw new Error('createWriter() deprecated.');
-  }
-  /** @override */
   async createWritable(options) {
     if (this.nextCreateWritableError) {
       throw this.nextCreateWritableError;
diff --git a/chromeos/components/print_management/resources/index.html b/chromeos/components/print_management/resources/index.html
index eed681fc..c30bdef 100644
--- a/chromeos/components/print_management/resources/index.html
+++ b/chromeos/components/print_management/resources/index.html
@@ -8,7 +8,7 @@
     <title>Print Jobs</title>
     <style>
       html {
-        background-color: var(--cros-default-bg-color);
+        background-color: var(--cros-bg-color);
       }
     </style>
   </head>
diff --git a/chromeos/components/print_management/resources/print_management.html b/chromeos/components/print_management/resources/print_management.html
index 2cd884bb..d22a4f8 100644
--- a/chromeos/components/print_management/resources/print_management.html
+++ b/chromeos/components/print_management/resources/print_management.html
@@ -1,6 +1,6 @@
 <style include="cr-shared-style print-management-shared print-management-fonts">
   html {
-    background-color: var(--cros-default-bg-color);
+    background-color: var(--cros-bg-color);
   }
 
   .column-headers {
diff --git a/chromeos/components/print_management/resources/print_management_shared_css.html b/chromeos/components/print_management/resources/print_management_shared_css.html
index 24052dd..e8ba704 100644
--- a/chromeos/components/print_management/resources/print_management_shared_css.html
+++ b/chromeos/components/print_management/resources/print_management_shared_css.html
@@ -5,7 +5,7 @@
 <template>
   <style include="cr-shared-style">
     html {
-      background-color: var(--cros-default-bg-color);
+      background-color: var(--cros-bg-color);
     }
 
     .flex-center {
diff --git a/chromeos/profiles/airmont.afdo.newest.txt b/chromeos/profiles/airmont.afdo.newest.txt
index 8b76862..766512b4 100644
--- a/chromeos/profiles/airmont.afdo.newest.txt
+++ b/chromeos/profiles/airmont.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-airmont-86-4181.3-1594633354-benchmark-86.0.4194.0-r1-redacted.afdo.xz
+chromeos-chrome-amd64-airmont-86-4181.3-1594633354-benchmark-86.0.4203.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/broadwell.afdo.newest.txt b/chromeos/profiles/broadwell.afdo.newest.txt
index 65b7990..7a9d7ef3 100644
--- a/chromeos/profiles/broadwell.afdo.newest.txt
+++ b/chromeos/profiles/broadwell.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-broadwell-86-4181.3-1594633791-benchmark-86.0.4194.0-r1-redacted.afdo.xz
+chromeos-chrome-amd64-broadwell-86-4181.3-1594633791-benchmark-86.0.4203.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/silvermont.afdo.newest.txt b/chromeos/profiles/silvermont.afdo.newest.txt
index 05aaef7f..0746fc5 100644
--- a/chromeos/profiles/silvermont.afdo.newest.txt
+++ b/chromeos/profiles/silvermont.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-silvermont-86-4181.3-1594638142-benchmark-86.0.4194.0-r1-redacted.afdo.xz
+chromeos-chrome-amd64-silvermont-86-4181.3-1594638142-benchmark-86.0.4203.0-r1-redacted.afdo.xz
diff --git a/chromeos/services/machine_learning/public/mojom/roll_mojoms.sh b/chromeos/services/machine_learning/public/mojom/roll_mojoms.sh
index b7c912d..78c52e4d 100755
--- a/chromeos/services/machine_learning/public/mojom/roll_mojoms.sh
+++ b/chromeos/services/machine_learning/public/mojom/roll_mojoms.sh
@@ -56,11 +56,6 @@
   -e 's~^import "ml~import "chromeos/services/machine_learning/public~g' \
   *.mojom
 
-echo "Applying Mojo syntax changes ..."
-sed --in-place --regexp-extended \
-  -e 's/(GraphExecutor|Model|TextClassifier|HandwritingRecognizer)& request/pending_receiver<\1> receiver/g' \
-  *.mojom
-
 echo "OK. Now:"
 echo "1. Examine 'git diff' to double-check the results of this tool."
 echo "2. After submitting, also update any google3 files generated from these "
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn
index bab7b96..7503525 100644
--- a/components/arc/BUILD.gn
+++ b/components/arc/BUILD.gn
@@ -64,6 +64,8 @@
     "property/arc_property_bridge.h",
     "rotation_lock/arc_rotation_lock_bridge.cc",
     "rotation_lock/arc_rotation_lock_bridge.h",
+    "sensor/arc_sensor_bridge.cc",
+    "sensor/arc_sensor_bridge.h",
     "storage_manager/arc_storage_manager.cc",
     "storage_manager/arc_storage_manager.h",
     "timer/arc_timer_bridge.cc",
diff --git a/components/arc/mojom/BUILD.gn b/components/arc/mojom/BUILD.gn
index ebb973f53..7b784cd 100644
--- a/components/arc/mojom/BUILD.gn
+++ b/components/arc/mojom/BUILD.gn
@@ -51,6 +51,8 @@
       "rotation_lock.mojom",
       "scale_factor.mojom",
       "screen_capture.mojom",
+      "sensor.mojom",
+      "sensor_service.mojom",
       "storage_manager.mojom",
       "timer.mojom",
       "tracing.mojom",
diff --git a/components/arc/mojom/arc_bridge.mojom b/components/arc/mojom/arc_bridge.mojom
index 127c819..aaa40070 100644
--- a/components/arc/mojom/arc_bridge.mojom
+++ b/components/arc/mojom/arc_bridge.mojom
@@ -42,6 +42,7 @@
 import "components/arc/mojom/property.mojom";
 import "components/arc/mojom/rotation_lock.mojom";
 import "components/arc/mojom/screen_capture.mojom";
+import "components/arc/mojom/sensor.mojom";
 import "components/arc/mojom/storage_manager.mojom";
 import "components/arc/mojom/timer.mojom";
 import "components/arc/mojom/tracing.mojom";
@@ -54,9 +55,9 @@
 import "components/arc/mojom/wake_lock.mojom";
 import "components/arc/mojom/wallpaper.mojom";
 
-// Next MinVersion: 49
+// Next MinVersion: 50
 // Deprecated method IDs: 101, 105, 121
-// Next method ID: 154
+// Next method ID: 155
 interface ArcBridgeHost {
   // Keep the entries alphabetical. In order to do so without breaking
   // compatibility with the ARC instance, explicitly assign each interface a
@@ -211,6 +212,10 @@
   [MinVersion=35] OnScreenCaptureInstanceReady@140(
       pending_remote<ScreenCaptureInstance> instance_remote);
 
+  // Notifies Chrome that the SensorInstance interface is ready.
+  [MinVersion=49] OnSensorInstanceReady@154(
+      pending_remote<SensorInstance> instance_ptr);
+
   // Notifies Chrome that the SmartCardManagerInstance interface is ready.
   [MinVersion=48] OnSmartCardManagerInstanceReady@153(
       pending_remote<SmartCardManagerInstance> instance_remote);
diff --git a/components/arc/mojom/sensor.mojom b/components/arc/mojom/sensor.mojom
new file mode 100644
index 0000000..57733174
--- /dev/null
+++ b/components/arc/mojom/sensor.mojom
@@ -0,0 +1,21 @@
+// Copyright 2020 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 arc.mojom;
+
+import "components/arc/mojom/sensor_service.mojom";
+
+// Chrome implements this interface to handle requests from ARC.
+// Next method ID: 1
+interface SensorHost {
+  // Binds the request to the sensor service.
+  GetSensorService@0(pending_receiver<SensorService> request);
+};
+
+// ARC implements this interface to interact with chrome.
+// Next method ID: 1
+interface SensorInstance {
+  // Establishes full-duplex communication with the host.
+  Init@0(pending_remote<SensorHost> host_ptr) => ();
+};
\ No newline at end of file
diff --git a/components/arc/mojom/sensor_service.mojom b/components/arc/mojom/sensor_service.mojom
new file mode 100644
index 0000000..414ef26
--- /dev/null
+++ b/components/arc/mojom/sensor_service.mojom
@@ -0,0 +1,37 @@
+// Copyright 2020 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 arc.mojom;
+
+enum AttributeIOResult {
+  SUCCESS = 0,
+  ERROR_CHANNEL_NOT_FOUND = 1,
+  ERROR_ATTRIBUTE_NOT_FOUND = 2,
+  ERROR_IO = 3,
+};
+
+// SensorService provides access to all sensor devices.
+// arc-sensor-service runs in minijail to implement this interface to provide
+// sensor data for ARC.
+interface SensorService {
+  // Returns the list of device names.
+  GetDeviceNames@0() => (array<string> names);
+
+  // Binds the request to the specified device.
+  GetDeviceByName@1(string name, SensorDevice& request);
+};
+
+// SensorDevice provides an interface to interact with a sensor device.
+// arc-sensor-service runs in minijail to implement this interface to provide
+// sensor data for ARC.
+interface SensorDevice {
+  // Returns the value of the specified device attribute.
+  GetAttribute@0(string name) => (AttributeIOResult result, string value);
+
+  // Sets the specified device attribute.
+  SetAttribute@1(string name, string value) => (AttributeIOResult result);
+
+  // Opens the device buffer.
+  OpenBuffer@2() => (handle? fd);
+};
diff --git a/components/arc/sensor/arc_sensor_bridge.cc b/components/arc/sensor/arc_sensor_bridge.cc
new file mode 100644
index 0000000..812229f
--- /dev/null
+++ b/components/arc/sensor/arc_sensor_bridge.cc
@@ -0,0 +1,85 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/arc/sensor/arc_sensor_bridge.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/files/scoped_file.h"
+#include "base/memory/singleton.h"
+#include "base/rand_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "chromeos/dbus/arc/arc_sensor_service_client.h"
+#include "components/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "components/arc/session/arc_bridge_service.h"
+#include "mojo/public/cpp/platform/platform_channel.h"
+#include "mojo/public/cpp/system/invitation.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+
+namespace arc {
+
+namespace {
+
+// Singleton factory for ArcSensorBridge.
+class ArcSensorBridgeFactory
+    : public internal::ArcBrowserContextKeyedServiceFactoryBase<
+          ArcSensorBridge,
+          ArcSensorBridgeFactory> {
+ public:
+  // Factory name used by ArcBrowserContextKeyedServiceFactoryBase.
+  static constexpr const char* kName = "ArcSensorBridgeFactory";
+
+  static ArcSensorBridgeFactory* GetInstance() {
+    return base::Singleton<ArcSensorBridgeFactory>::get();
+  }
+
+ private:
+  friend base::DefaultSingletonTraits<ArcSensorBridgeFactory>;
+  ArcSensorBridgeFactory() = default;
+  ~ArcSensorBridgeFactory() override = default;
+};
+
+}  // namespace
+
+// static
+ArcSensorBridge* ArcSensorBridge::GetForBrowserContext(
+    content::BrowserContext* context) {
+  return ArcSensorBridgeFactory::GetForBrowserContext(context);
+}
+
+ArcSensorBridge::ArcSensorBridge(content::BrowserContext* context,
+                                 ArcBridgeService* bridge_service)
+    : arc_bridge_service_(bridge_service) {
+  arc_bridge_service_->sensor()->SetHost(this);
+}
+
+ArcSensorBridge::~ArcSensorBridge() {
+  arc_bridge_service_->sensor()->SetHost(nullptr);
+}
+
+void ArcSensorBridge::GetSensorService(
+    mojo::PendingReceiver<mojom::SensorService> receiver) {
+  auto token = base::NumberToString(base::RandUint64());
+  mojo::OutgoingInvitation invitation;
+  mojo::PlatformChannel channel;
+  mojo::ScopedMessagePipeHandle pipe = invitation.AttachMessagePipe(token);
+  mojo::OutgoingInvitation::Send(std::move(invitation),
+                                 base::kNullProcessHandle,
+                                 channel.TakeLocalEndpoint());
+  // Fuse the receiver with the attached pipe so that the requester's pipe will
+  // be connected to the sensor service.
+  MojoResult result =
+      mojo::FuseMessagePipes(receiver.PassPipe(), std::move(pipe));
+  if (result != MOJO_RESULT_OK) {
+    LOG(ERROR) << "FuseMessagePipes() failed: " << result;
+    return;
+  }
+  base::ScopedFD fd =
+      channel.TakeRemoteEndpoint().TakePlatformHandle().TakeFD();
+  chromeos::ArcSensorServiceClient::Get()->BootstrapMojoConnection(
+      fd.get(), token, base::BindOnce([](bool success) {}));
+}
+
+}  // namespace arc
diff --git a/components/arc/sensor/arc_sensor_bridge.h b/components/arc/sensor/arc_sensor_bridge.h
new file mode 100644
index 0000000..77e0481
--- /dev/null
+++ b/components/arc/sensor/arc_sensor_bridge.h
@@ -0,0 +1,43 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_ARC_SENSOR_ARC_SENSOR_BRIDGE_H_
+#define COMPONENTS_ARC_SENSOR_ARC_SENSOR_BRIDGE_H_
+
+#include "components/arc/mojom/sensor.mojom.h"
+#include "components/keyed_service/core/keyed_service.h"
+
+namespace content {
+class BrowserContext;
+}  // namespace content
+
+namespace arc {
+
+class ArcBridgeService;
+
+// This class handles Sensor-related requests from the ARC container.
+class ArcSensorBridge : public KeyedService, public mojom::SensorHost {
+ public:
+  // Returns singleton instance for the given BrowserContext,
+  // or nullptr if the browser |context| is not allowed to use ARC.
+  static ArcSensorBridge* GetForBrowserContext(
+      content::BrowserContext* context);
+
+  ArcSensorBridge(content::BrowserContext* context,
+                  ArcBridgeService* bridge_service);
+  ~ArcSensorBridge() override;
+  ArcSensorBridge(const ArcSensorBridge&) = delete;
+  ArcSensorBridge& operator=(const ArcSensorBridge&) = delete;
+
+  // mojom::SensorHost overrides:
+  void GetSensorService(
+      mojo::PendingReceiver<mojom::SensorService> receiver) override;
+
+ private:
+  ArcBridgeService* const arc_bridge_service_;  // Owned by ArcServiceManager.
+};
+
+}  // namespace arc
+
+#endif  // COMPONENTS_ARC_SENSOR_ARC_SENSOR_BRIDGE_H_
diff --git a/components/arc/session/arc_bridge_host_impl.cc b/components/arc/session/arc_bridge_host_impl.cc
index 4bd630b..548b749 100644
--- a/components/arc/session/arc_bridge_host_impl.cc
+++ b/components/arc/session/arc_bridge_host_impl.cc
@@ -49,6 +49,7 @@
 #include "components/arc/mojom/property.mojom.h"
 #include "components/arc/mojom/rotation_lock.mojom.h"
 #include "components/arc/mojom/screen_capture.mojom.h"
+#include "components/arc/mojom/sensor.mojom.h"
 #include "components/arc/mojom/storage_manager.mojom.h"
 #include "components/arc/mojom/timer.mojom.h"
 #include "components/arc/mojom/tracing.mojom.h"
@@ -307,6 +308,11 @@
                   std::move(screen_capture_remote));
 }
 
+void ArcBridgeHostImpl::OnSensorInstanceReady(
+    mojo::PendingRemote<mojom::SensorInstance> sensor_remote) {
+  OnInstanceReady(arc_bridge_service_->sensor(), std::move(sensor_remote));
+}
+
 void ArcBridgeHostImpl::OnSmartCardManagerInstanceReady(
     mojo::PendingRemote<mojom::SmartCardManagerInstance>
         smart_card_manager_remote) {
diff --git a/components/arc/session/arc_bridge_host_impl.h b/components/arc/session/arc_bridge_host_impl.h
index bbe1860f..d55d17d 100644
--- a/components/arc/session/arc_bridge_host_impl.h
+++ b/components/arc/session/arc_bridge_host_impl.h
@@ -128,6 +128,8 @@
   void OnScreenCaptureInstanceReady(
       mojo::PendingRemote<mojom::ScreenCaptureInstance> screen_capture_remote)
       override;
+  void OnSensorInstanceReady(
+      mojo::PendingRemote<mojom::SensorInstance> sensor_ptr) override;
   void OnSmartCardManagerInstanceReady(
       mojo::PendingRemote<mojom::SmartCardManagerInstance>
           smart_card_manager_remote) override;
diff --git a/components/arc/session/arc_bridge_service.cc b/components/arc/session/arc_bridge_service.cc
index 5fae700..558cc0e 100644
--- a/components/arc/session/arc_bridge_service.cc
+++ b/components/arc/session/arc_bridge_service.cc
@@ -43,6 +43,7 @@
 #include "components/arc/mojom/property.mojom.h"
 #include "components/arc/mojom/rotation_lock.mojom.h"
 #include "components/arc/mojom/screen_capture.mojom.h"
+#include "components/arc/mojom/sensor.mojom.h"
 #include "components/arc/mojom/storage_manager.mojom.h"
 #include "components/arc/mojom/timer.mojom.h"
 #include "components/arc/mojom/tracing.mojom.h"
diff --git a/components/arc/session/arc_bridge_service.h b/components/arc/session/arc_bridge_service.h
index 93ed0c42..9cc494c 100644
--- a/components/arc/session/arc_bridge_service.h
+++ b/components/arc/session/arc_bridge_service.h
@@ -81,6 +81,8 @@
 class RotationLockInstance;
 class ScreenCaptureHost;
 class ScreenCaptureInstance;
+class SensorHost;
+class SensorInstance;
 class SmartCardManagerHost;
 class SmartCardManagerInstance;
 class StorageManagerInstance;
@@ -249,6 +251,9 @@
   screen_capture() {
     return &screen_capture_;
   }
+  ConnectionHolder<mojom::SensorInstance, mojom::SensorHost>* sensor() {
+    return &sensor_;
+  }
   ConnectionHolder<mojom::SmartCardManagerInstance,
                    mojom::SmartCardManagerHost>*
   smart_card_manager() {
@@ -334,6 +339,7 @@
   ConnectionHolder<mojom::RotationLockInstance> rotation_lock_;
   ConnectionHolder<mojom::ScreenCaptureInstance, mojom::ScreenCaptureHost>
       screen_capture_;
+  ConnectionHolder<mojom::SensorInstance, mojom::SensorHost> sensor_;
   ConnectionHolder<mojom::SmartCardManagerInstance, mojom::SmartCardManagerHost>
       smart_card_manager_;
   ConnectionHolder<mojom::StorageManagerInstance> storage_manager_;
diff --git a/components/arc/session/arc_vm_client_adapter.cc b/components/arc/session/arc_vm_client_adapter.cc
index f3091b0..dc224cb 100644
--- a/components/arc/session/arc_vm_client_adapter.cc
+++ b/components/arc/session/arc_vm_client_adapter.cc
@@ -59,6 +59,7 @@
 // ascii code in hex. So "arc_2dcreate_2ddata" becomes "arc-create-data".
 constexpr const char kArcCreateDataJobName[] = "arc_2dcreate_2ddata";
 constexpr const char kArcKeymasterJobName[] = "arc_2dkeymasterd";
+constexpr const char kArcSensorServiceJobName[] = "arc_2dsensor_2dservice";
 constexpr const char kArcVmServerProxyJobName[] = "arcvm_2dserver_2dproxy";
 constexpr const char kArcVmPerBoardFeaturesJobName[] =
     "arcvm_2dper_2dboard_2dfeatures";
@@ -551,6 +552,33 @@
       return;
     }
 
+    // Kill a stale arc-sensor-service job
+    chromeos::UpstartClient::Get()->StopJob(
+        kArcSensorServiceJobName, /*environment=*/{},
+        base::BindOnce(&ArcVmClientAdapter::OnArcSensorServiceStopped,
+                       weak_factory_.GetWeakPtr(), std::move(callback)));
+  }
+
+  void OnArcSensorServiceStopped(chromeos::VoidDBusMethodCallback callback,
+                                 bool result) {
+    VLOG(1) << "OnArcSensorServiceStopped: job "
+            << (result ? "stopped" : "not running?");
+
+    VLOG(1) << "Starting arc-sensor-service";
+    chromeos::UpstartClient::Get()->StartJob(
+        kArcSensorServiceJobName, /*environment=*/{},
+        base::BindOnce(&ArcVmClientAdapter::OnArcSensorServiceStarted,
+                       weak_factory_.GetWeakPtr(), std::move(callback)));
+  }
+
+  void OnArcSensorServiceStarted(chromeos::VoidDBusMethodCallback callback,
+                                 bool result) {
+    if (!result) {
+      LOG(ERROR) << "Failed to start arc-sensor-service job";
+      std::move(callback).Run(false);
+      return;
+    }
+
     // Kill a stale arcvm-boot-notification-server job
     chromeos::UpstartClient::Get()->StopJob(
         kArcVmBootNotificationServerJobName, /*environment=*/{},
diff --git a/components/arc/session/arc_vm_client_adapter_unittest.cc b/components/arc/session/arc_vm_client_adapter_unittest.cc
index eb8f849..b65a7c8 100644
--- a/components/arc/session/arc_vm_client_adapter_unittest.cc
+++ b/components/arc/session/arc_vm_client_adapter_unittest.cc
@@ -43,6 +43,7 @@
 
 constexpr const char kArcCreateDataJobName[] = "arc_2dcreate_2ddata";
 constexpr const char kArcKeymasterJobName[] = "arc_2dkeymasterd";
+constexpr const char kArcSensorServiceJobName[] = "arc_2dsensor_2dservice";
 constexpr const char kArcVmServerProxyJobName[] = "arcvm_2dserver_2dproxy";
 constexpr const char kArcVmPerBoardFeaturesJobName[] =
     "arcvm_2dper_2dboard_2dfeatures";
@@ -523,6 +524,27 @@
   EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
 }
 
+// Tests that StartMiniArc() fails if Upstart fails to start arc-sensor-service.
+TEST_F(ArcVmClientAdapterTest, StartMiniArc_StartArcSensorServiceJobFail) {
+  // Inject failure to FakeUpstartClient.
+  InjectUpstartStartJobFailure(kArcSensorServiceJobName);
+
+  StartMiniArcWithParams(false, {});
+  // Confirm that no VM is started. ARCVM doesn't support mini ARC yet.
+  EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
+}
+
+// Tests that StartMiniArc() succeeds if Upstart fails to stop
+// arc-sensor-service.
+TEST_F(ArcVmClientAdapterTest, StartMiniArc_StopArcSensorServiceJobFail) {
+  // Inject failure to FakeUpstartClient.
+  InjectUpstartStopJobFailure(kArcSensorServiceJobName);
+
+  StartMiniArc();
+  // Confirm that no VM is started. ARCVM doesn't support mini ARC yet.
+  EXPECT_FALSE(GetTestConciergeClient()->start_arc_vm_called());
+}
+
 // Tests that StartMiniArc() fails when Upstart fails to start the job.
 TEST_F(ArcVmClientAdapterTest, StartMiniArc_StartArcVmPerBoardFeaturesJobFail) {
   // Inject failure to FakeUpstartClient.
diff --git a/components/arc/test/fake_arc_bridge_host.cc b/components/arc/test/fake_arc_bridge_host.cc
index c58e2088..861b6923 100644
--- a/components/arc/test/fake_arc_bridge_host.cc
+++ b/components/arc/test/fake_arc_bridge_host.cc
@@ -43,6 +43,7 @@
 #include "components/arc/mojom/property.mojom.h"
 #include "components/arc/mojom/rotation_lock.mojom.h"
 #include "components/arc/mojom/screen_capture.mojom.h"
+#include "components/arc/mojom/sensor.mojom.h"
 #include "components/arc/mojom/storage_manager.mojom.h"
 #include "components/arc/mojom/timer.mojom.h"
 #include "components/arc/mojom/tracing.mojom.h"
@@ -182,6 +183,9 @@
 void FakeArcBridgeHost::OnScreenCaptureInstanceReady(
     mojo::PendingRemote<mojom::ScreenCaptureInstance> screen_capture_remote) {}
 
+void FakeArcBridgeHost::OnSensorInstanceReady(
+    mojo::PendingRemote<mojom::SensorInstance> sensor_remote) {}
+
 void FakeArcBridgeHost::OnSmartCardManagerInstanceReady(
     mojo::PendingRemote<mojom::SmartCardManagerInstance>
         smart_cardManager_remote) {}
diff --git a/components/arc/test/fake_arc_bridge_host.h b/components/arc/test/fake_arc_bridge_host.h
index 46816c05..8ad93fe 100644
--- a/components/arc/test/fake_arc_bridge_host.h
+++ b/components/arc/test/fake_arc_bridge_host.h
@@ -107,6 +107,8 @@
   void OnScreenCaptureInstanceReady(
       mojo::PendingRemote<mojom::ScreenCaptureInstance> screen_capture_remote)
       override;
+  void OnSensorInstanceReady(
+      mojo::PendingRemote<mojom::SensorInstance> sensor_remote) override;
   void OnSmartCardManagerInstanceReady(
       mojo::PendingRemote<mojom::SmartCardManagerInstance>
           smart_card_manager_remote) override;
diff --git a/components/autofill/core/browser/autofill_type.cc b/components/autofill/core/browser/autofill_type.cc
index 31428ca..b9a5ae2 100644
--- a/components/autofill/core/browser/autofill_type.cc
+++ b/components/autofill/core/browser/autofill_type.cc
@@ -460,6 +460,7 @@
 
   switch (html_type_) {
     case HTML_TYPE_UNSPECIFIED:
+    case HTML_TYPE_UNRECOGNIZED:
       NOTREACHED();
       break;
     case HTML_TYPE_NAME:
@@ -548,8 +549,6 @@
       return "HTML_TRANSACTION_CURRENCY";
     case HTML_TYPE_UPI_VPA:
       return "HTML_TYPE_UPI_VPA";
-    case HTML_TYPE_UNRECOGNIZED:
-      return "HTML_TYPE_UNRECOGNIZED";
   }
 
   NOTREACHED();
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingException.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingException.java
index d6bdef3..f440edf7 100644
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingException.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingException.java
@@ -21,21 +21,21 @@
  * Exception information for a given origin.
  */
 public class ContentSettingException implements Serializable {
-    @IntDef({Type.ADS, Type.AUTOMATIC_DOWNLOADS, Type.BACKGROUND_SYNC, Type.COOKIE, Type.JAVASCRIPT,
-            Type.POPUP, Type.SOUND, Type.BLUETOOTH_SCANNING})
+    @IntDef({Type.ADS, Type.AUTOMATIC_DOWNLOADS, Type.BACKGROUND_SYNC, Type.BLUETOOTH_SCANNING,
+            Type.COOKIE, Type.JAVASCRIPT, Type.POPUP, Type.SOUND})
     @Retention(RetentionPolicy.SOURCE)
     public @interface Type {
         // Values used to address array index - should be enumerated from 0 and can't have gaps.
         // All updates here must also be reflected in {@link #getContentSettingsType(int)
         // getContentSettingsType} and {@link SingleWebsiteSettings.PERMISSION_PREFERENCE_KEYS}.
         int ADS = 0;
-        int BACKGROUND_SYNC = 1;
-        int COOKIE = 2;
-        int JAVASCRIPT = 3;
-        int POPUP = 4;
-        int SOUND = 5;
-        int AUTOMATIC_DOWNLOADS = 6;
-        int BLUETOOTH_SCANNING = 7;
+        int AUTOMATIC_DOWNLOADS = 1;
+        int BACKGROUND_SYNC = 2;
+        int BLUETOOTH_SCANNING = 3;
+        int COOKIE = 4;
+        int JAVASCRIPT = 5;
+        int POPUP = 6;
+        int SOUND = 7;
         /**
          * Number of handled exceptions used for calculating array sizes.
          */
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
index 83a6645..94c2306 100644
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
@@ -71,10 +71,9 @@
 
     // Website permissions (if adding new, see hasPermissionsPreferences and resetSite below)
     // All permissions from the permissions preference category must be listed here.
-    private static final String[] PERMISSION_PREFERENCE_KEYS = {
+    public static final String[] PERMISSION_PREFERENCE_KEYS = {
             // Permission keys mapped for next {@link ContentSettingException.Type} values.
             "ads_permission_list", // ContentSettingException.Type.ADS
-            "ar_permission_list", // PermissionInfo.Type.AUGMENTED_REALITY
             "automatic_downloads_permission_list",
             // ContentSettingException.Type.AUTOMATIC_DOWNLOADS
             "background_sync_permission_list", // ContentSettingException.Type.BACKGROUND_SYNC
@@ -84,6 +83,7 @@
             "popup_permission_list", // ContentSettingException.Type.POPUP
             "sound_permission_list", // ContentSettingException.Type.SOUND
             // Permission keys mapped for next {@link PermissionInfo.Type} values.
+            "ar_permission_list", // PermissionInfo.Type.AUGMENTED_REALITY
             "camera_permission_list", // PermissionInfo.Type.CAMERA
             "clipboard_permission_list", // PermissionInfo.Type.CLIPBOARD
             "location_access_list", // PermissionInfo.Type.GEOLOCATION
@@ -934,7 +934,7 @@
         });
     }
 
-    private int getContentSettingsTypeFromPreferenceKey(String preferenceKey) {
+    public static int getContentSettingsTypeFromPreferenceKey(String preferenceKey) {
         for (int i = 0; i < PERMISSION_PREFERENCE_KEYS.length; i++) {
             if (PERMISSION_PREFERENCE_KEYS[i].equals(preferenceKey)) {
                 return i < ContentSettingException.Type.NUM_ENTRIES
diff --git a/components/error_page/common/localized_error.cc b/components/error_page/common/localized_error.cc
index bfa1f13..51b723e 100644
--- a/components/error_page/common/localized_error.cc
+++ b/components/error_page/common/localized_error.cc
@@ -168,6 +168,12 @@
    SUGGEST_NONE,
    SHOW_NO_BUTTONS,
   },
+  {net::ERR_UPLOAD_FILE_CHANGED,
+   IDS_ERRORPAGES_HEADING_FILE_NOT_FOUND,
+   IDS_ERRORPAGES_SUMMARY_FILE_NOT_FOUND,
+   SUGGEST_NONE,
+   SHOW_NO_BUTTONS,
+  },
   {net::ERR_CACHE_MISS,
    IDS_ERRORPAGES_HEADING_CACHE_READ_FAILURE,
    IDS_ERRORPAGES_SUMMARY_CACHE_READ_FAILURE,
diff --git a/components/error_page_strings.grdp b/components/error_page_strings.grdp
index 361b189..7c35948 100644
--- a/components/error_page_strings.grdp
+++ b/components/error_page_strings.grdp
@@ -127,8 +127,8 @@
   <message name="IDS_ERRORPAGES_HEADING_NOT_FOUND" desc="Heading in the error page when the server returns a 404 or 410.">
     This <ph name="HOST_NAME">&lt;span jscontent="hostName"&gt;&lt;/span&gt;<ex>www.whatever.com</ex></ph> page can’t be found
   </message>
-  <message name="IDS_ERRORPAGES_HEADING_FILE_NOT_FOUND" desc="Heading in the error page when the local file was not found.">
-    Your file was not found
+  <message name="IDS_ERRORPAGES_HEADING_FILE_NOT_FOUND" desc="Heading in the error page when the local file could not be accessed.">
+    Your file couldn’t be accessed
   </message>
   <message name="IDS_ERRORPAGES_HEADING_BLOCKED" desc="Heading of the error page when a request is blocked by the administrator policy, extension or the browser itself.">
     <ph name="HOST_NAME">&lt;span jscontent="hostName"&gt;&lt;/span&gt;<ex>www.example.com</ex></ph> is blocked
@@ -190,8 +190,8 @@
   <message name="IDS_ERRORPAGES_SUMMARY_NOT_FOUND" desc="Summary in the error page when the server returns a 404.">
     No webpage was found for the web address: <ph name="URL">&lt;strong jscontent="failedUrl"&gt;&lt;/strong&gt;</ph>
   </message>
-  <message name="IDS_ERRORPAGES_SUMMARY_FILE_NOT_FOUND" desc="Summary in the error page when a local file is not found.">
-    It may have been moved or deleted.
+  <message name="IDS_ERRORPAGES_SUMMARY_FILE_NOT_FOUND" desc="Summary in the error page when a local file could not be accessed.">
+    It may have been moved, edited, or deleted.
   </message>
   <message name="IDS_ERRORPAGES_SUMMARY_TOO_MANY_REDIRECTS" desc="Summary in the error page when there are too many URL redirects.">
     <ph name="HOST_NAME">&lt;strong jscontent="hostName"&gt;&lt;/strong&gt;<ex>www.whatever.com</ex></ph> redirected you too many times.
diff --git a/components/error_page_strings_grdp/IDS_ERRORPAGES_HEADING_FILE_NOT_FOUND.png.sha1 b/components/error_page_strings_grdp/IDS_ERRORPAGES_HEADING_FILE_NOT_FOUND.png.sha1
new file mode 100644
index 0000000..604ed90a
--- /dev/null
+++ b/components/error_page_strings_grdp/IDS_ERRORPAGES_HEADING_FILE_NOT_FOUND.png.sha1
@@ -0,0 +1 @@
+cf813c7007600a023efb077740640c1e03e952a3
\ No newline at end of file
diff --git a/components/error_page_strings_grdp/IDS_ERRORPAGES_SUMMARY_FILE_NOT_FOUND.png.sha1 b/components/error_page_strings_grdp/IDS_ERRORPAGES_SUMMARY_FILE_NOT_FOUND.png.sha1
new file mode 100644
index 0000000..604ed90a
--- /dev/null
+++ b/components/error_page_strings_grdp/IDS_ERRORPAGES_SUMMARY_FILE_NOT_FOUND.png.sha1
@@ -0,0 +1 @@
+cf813c7007600a023efb077740640c1e03e952a3
\ No newline at end of file
diff --git a/components/password_manager/core/browser/browser_save_password_progress_logger.cc b/components/password_manager/core/browser/browser_save_password_progress_logger.cc
index 4452b7f..949e8a8 100644
--- a/components/password_manager/core/browser/browser_save_password_progress_logger.cc
+++ b/components/password_manager/core/browser/browser_save_password_progress_logger.cc
@@ -209,14 +209,16 @@
           ", autocomplete=" + ScrubElementID(field->autocomplete_attribute);
 
     if (field->server_type() != autofill::NO_SERVER_DATA) {
-      field_info +=
-          ", SERVER_PREDICTION: " +
-          autofill::AutofillType::ServerFieldTypeToString(field->server_type());
+      base::StrAppend(&field_info,
+                      {", SERVER_PREDICTION: ",
+                       autofill::AutofillType::ServerFieldTypeToString(
+                           field->server_type())});
     }
 
     for (ServerFieldType type : field->possible_types())
-      field_info +=
-          ", VOTE: " + autofill::AutofillType::ServerFieldTypeToString(type);
+      base::StrAppend(
+          &field_info,
+          {", VOTE: ", autofill::AutofillType::ServerFieldTypeToString(type)});
 
     if (field->vote_type())
       field_info += ", vote_type=" + VoteTypeToString(field->vote_type());
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc
index d1892f1..371d371 100644
--- a/components/password_manager/core/browser/password_manager.cc
+++ b/components/password_manager/core/browser/password_manager.cc
@@ -13,6 +13,7 @@
 
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/platform_thread.h"
@@ -180,12 +181,12 @@
         field.type = NOT_USERNAME;
     }
     if (logger && local_prediction != UNKNOWN_TYPE) {
-      std::string message =
-          "form signature=" +
-          NumberToString(predictions->form_signature.value()) +
-          " , field signature=" + NumberToString(field.signature.value()) +
-          ", type=" +
-          autofill::AutofillType::ServerFieldTypeToString(local_prediction);
+      std::string message = base::StrCat(
+          {"form signature=",
+           NumberToString(predictions->form_signature.value()),
+           " , field signature=", NumberToString(field.signature.value()),
+           ", type=",
+           autofill::AutofillType::ServerFieldTypeToString(local_prediction)});
       logger->LogString(Logger::STRING_LOCALLY_SAVED_PREDICTION, message);
     }
   }
diff --git a/components/payments/core/features.cc b/components/payments/core/features.cc
index bc4b1a5..7b47a8b 100644
--- a/components/payments/core/features.cc
+++ b/components/payments/core/features.cc
@@ -66,5 +66,8 @@
     "AllowJITInstallationWhenAppIconIsMissing",
     base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kPaymentHandlerLockIcon{"PaymentHandlerLockIcon",
+                                            base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace features
 }  // namespace payments
diff --git a/components/payments/core/features.h b/components/payments/core/features.h
index 273a692..ece0789 100644
--- a/components/payments/core/features.h
+++ b/components/payments/core/features.h
@@ -75,6 +75,11 @@
 // Used to test icon refetch for JIT installed apps with missing icons.
 extern const base::Feature kAllowJITInstallationWhenAppIconIsMissing;
 
+// Desktop only, if enabled the lock icon would be showed next to the
+// payment handler's URL bar. It indicate that only secure content is
+// allowed inside the payment handler.
+extern const base::Feature kPaymentHandlerLockIcon;
+
 }  // namespace features
 }  // namespace payments
 
diff --git a/components/pdf/common/pdf.mojom b/components/pdf/common/pdf.mojom
index e80e86f..99cad44 100644
--- a/components/pdf/common/pdf.mojom
+++ b/components/pdf/common/pdf.mojom
@@ -4,7 +4,7 @@
 
 module pdf.mojom;
 
-import "third_party/blink/public/mojom/referrer.mojom";
+import "third_party/blink/public/mojom/loader/referrer.mojom";
 import "ui/gfx/geometry/mojom/geometry.mojom";
 import "url/mojom/url.mojom";
 
diff --git a/components/services/storage/public/mojom/service_worker_storage_control.mojom b/components/services/storage/public/mojom/service_worker_storage_control.mojom
index 8d9b9b3..ee858a7 100644
--- a/components/services/storage/public/mojom/service_worker_storage_control.mojom
+++ b/components/services/storage/public/mojom/service_worker_storage_control.mojom
@@ -247,6 +247,9 @@
   ClearUserDataForAllRegistrationsByKeyPrefix(string key_prefix) =>
       (ServiceWorkerDatabaseStatus status);
 
+  // Removes traces of deleted data on disk.
+  PerformStorageCleanup() => ();
+
   // Applies changes to data retention policy which are relevant at shutdown.
   // This is analogous to LocalStorageControl::ApplyPolicyUpdates.
   ApplyPolicyUpdates(array<LocalStoragePolicyUpdate> policy_updates);
diff --git a/components/translate/content/renderer/BUILD.gn b/components/translate/content/renderer/BUILD.gn
index bae4efd..b47398f 100644
--- a/components/translate/content/renderer/BUILD.gn
+++ b/components/translate/content/renderer/BUILD.gn
@@ -6,6 +6,8 @@
 
 static_library("renderer") {
   sources = [
+    "isolated_world_util.cc",
+    "isolated_world_util.h",
     "per_frame_translate_agent.cc",
     "per_frame_translate_agent.h",
     "translate_agent.cc",
diff --git a/components/translate/content/renderer/isolated_world_util.cc b/components/translate/content/renderer/isolated_world_util.cc
new file mode 100644
index 0000000..7e82bb3
--- /dev/null
+++ b/components/translate/content/renderer/isolated_world_util.cc
@@ -0,0 +1,36 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/translate/content/renderer/isolated_world_util.h"
+
+#include "base/check_op.h"
+#include "base/optional.h"
+#include "components/translate/core/common/translate_util.h"
+#include "third_party/blink/public/platform/web_isolated_world_info.h"
+#include "third_party/blink/public/platform/web_url.h"
+
+namespace translate {
+
+void EnsureIsolatedWorldInitialized(int world_id) {
+  static base::Optional<int> last_used_world_id;
+  if (last_used_world_id) {
+    // Early return since the isolated world info. is already initialized.
+    DCHECK_EQ(*last_used_world_id, world_id)
+        << "EnsureIsolatedWorldInitialized should always be called with the "
+           "same |world_id|";
+    return;
+  }
+
+  last_used_world_id = world_id;
+  constexpr char kContentSecurityPolicy[] = "script-src 'self' 'unsafe-eval'";
+
+  blink::WebIsolatedWorldInfo info;
+  info.security_origin =
+      blink::WebSecurityOrigin::Create(GetTranslateSecurityOrigin());
+  info.content_security_policy =
+      blink::WebString::FromUTF8(kContentSecurityPolicy);
+  blink::SetIsolatedWorldInfo(world_id, info);
+}
+
+}  // namespace translate
diff --git a/components/translate/content/renderer/isolated_world_util.h b/components/translate/content/renderer/isolated_world_util.h
new file mode 100644
index 0000000..8e692f5
--- /dev/null
+++ b/components/translate/content/renderer/isolated_world_util.h
@@ -0,0 +1,15 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_TRANSLATE_CONTENT_RENDERER_ISOLATED_WORLD_UTIL_H_
+#define COMPONENTS_TRANSLATE_CONTENT_RENDERER_ISOLATED_WORLD_UTIL_H_
+
+namespace translate {
+
+// Ensures the isolated world information for |world_id| is initialized.
+void EnsureIsolatedWorldInitialized(int world_id);
+
+}  // namespace translate
+
+#endif  // COMPONENTS_TRANSLATE_CONTENT_RENDERER_ISOLATED_WORLD_UTIL_H_
diff --git a/components/translate/content/renderer/per_frame_translate_agent.cc b/components/translate/content/renderer/per_frame_translate_agent.cc
index 39dd1b94..ec2a727 100644
--- a/components/translate/content/renderer/per_frame_translate_agent.cc
+++ b/components/translate/content/renderer/per_frame_translate_agent.cc
@@ -14,6 +14,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "components/translate/content/renderer/isolated_world_util.h"
 #include "components/translate/core/common/translate_constants.h"
 #include "components/translate/core/common/translate_metrics.h"
 #include "components/translate/core/common/translate_util.h"
@@ -23,7 +24,6 @@
 #include "content/public/renderer/render_frame.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
-#include "third_party/blink/public/platform/web_isolated_world_info.h"
 #include "third_party/blink/public/web/web_document.h"
 #include "third_party/blink/public/web/web_language_detection_details.h"
 #include "third_party/blink/public/web/web_local_frame.h"
@@ -35,7 +35,6 @@
 using blink::WebLanguageDetectionDetails;
 using blink::WebLocalFrame;
 using blink::WebScriptSource;
-using blink::WebSecurityOrigin;
 using blink::WebString;
 using blink::WebVector;
 
@@ -61,9 +60,6 @@
 // Language name passed to the Translate element for it to detect the language.
 const char kAutoDetectionLanguage[] = "auto";
 
-// Isolated world sets following content-security-policy.
-const char kContentSecurityPolicy[] = "script-src 'self' 'unsafe-eval'";
-
 }  // namespace
 
 namespace translate {
@@ -131,16 +127,7 @@
   GURL url(render_frame()->GetWebFrame()->GetDocument().Url());
   ReportPageScheme(url.scheme());
 
-  if (!isolated_world_initialized_) {
-    // Set up v8 isolated world with proper content-security-policy and
-    // security-origin.
-    blink::WebIsolatedWorldInfo info;
-    info.security_origin =
-        WebSecurityOrigin::Create(GetTranslateSecurityOrigin());
-    info.content_security_policy = WebString::FromUTF8(kContentSecurityPolicy);
-    render_frame()->GetWebFrame()->SetIsolatedWorldInfo(world_id_, info);
-    isolated_world_initialized_ = true;
-  }
+  EnsureIsolatedWorldInitialized(world_id_);
 
   if (!IsTranslateLibAvailable()) {
     // Evaluate the script to add the translation related method to the global
@@ -206,7 +193,7 @@
 }
 
 void PerFrameTranslateAgent::ExecuteScript(const std::string& script) {
-  EnsureIsolatedWorldInitialized();
+  EnsureIsolatedWorldInitialized(world_id_);
   WebLocalFrame* local_frame = render_frame()->GetWebFrame();
   if (!local_frame)
     return;
@@ -218,7 +205,7 @@
 bool PerFrameTranslateAgent::ExecuteScriptAndGetBoolResult(
     const std::string& script,
     bool fallback) {
-  EnsureIsolatedWorldInitialized();
+  EnsureIsolatedWorldInitialized(world_id_);
   WebLocalFrame* local_frame = render_frame()->GetWebFrame();
   if (!local_frame)
     return fallback;
@@ -235,7 +222,7 @@
 
 std::string PerFrameTranslateAgent::ExecuteScriptAndGetStringResult(
     const std::string& script) {
-  EnsureIsolatedWorldInitialized();
+  EnsureIsolatedWorldInitialized(world_id_);
   WebLocalFrame* local_frame = render_frame()->GetWebFrame();
   if (!local_frame)
     return std::string();
@@ -257,7 +244,7 @@
 
 double PerFrameTranslateAgent::ExecuteScriptAndGetDoubleResult(
     const std::string& script) {
-  EnsureIsolatedWorldInitialized();
+  EnsureIsolatedWorldInitialized(world_id_);
   WebLocalFrame* local_frame = render_frame()->GetWebFrame();
   if (!local_frame)
     return 0.0;
@@ -274,7 +261,7 @@
 
 int64_t PerFrameTranslateAgent::ExecuteScriptAndGetIntegerResult(
     const std::string& script) {
-  EnsureIsolatedWorldInitialized();
+  EnsureIsolatedWorldInitialized(world_id_);
   WebLocalFrame* local_frame = render_frame()->GetWebFrame();
   if (!local_frame)
     return 0;
@@ -422,19 +409,6 @@
   target_lang_.clear();
 }
 
-void PerFrameTranslateAgent::EnsureIsolatedWorldInitialized() {
-  if (!isolated_world_initialized_) {
-    // Set up v8 isolated world with proper content-security-policy and
-    // security-origin.
-    blink::WebIsolatedWorldInfo info;
-    info.security_origin =
-        WebSecurityOrigin::Create(GetTranslateSecurityOrigin());
-    info.content_security_policy = WebString::FromUTF8(kContentSecurityPolicy);
-    render_frame()->GetWebFrame()->SetIsolatedWorldInfo(world_id_, info);
-    isolated_world_initialized_ = true;
-  }
-}
-
 void PerFrameTranslateAgent::BindReceiver(
     mojo::PendingAssociatedReceiver<mojom::TranslateAgent> receiver) {
   receiver_.Bind(std::move(receiver));
diff --git a/components/translate/content/renderer/per_frame_translate_agent.h b/components/translate/content/renderer/per_frame_translate_agent.h
index b2d1e5e..d664f0d 100644
--- a/components/translate/content/renderer/per_frame_translate_agent.h
+++ b/components/translate/content/renderer/per_frame_translate_agent.h
@@ -103,9 +103,6 @@
   // Converts language code to the one used in server supporting list.
   static void ConvertLanguageCodeSynonym(std::string* code);
 
-  // Ensures that the isolated world for executing translation JS.
-  void EnsureIsolatedWorldInitialized();
-
   // Sets receiver for translate messages from browser process.
   void BindReceiver(
       mojo::PendingAssociatedReceiver<mojom::TranslateAgent> receiver);
@@ -148,9 +145,6 @@
   // The world ID to use for script execution.
   int world_id_;
 
-  // Whether the isolated world info has been initialized.
-  bool isolated_world_initialized_ = false;
-
   mojo::AssociatedReceiver<mojom::TranslateAgent> receiver_{this};
 
   // Method factory used to make calls to TranslateFrameImpl.
diff --git a/components/translate/content/renderer/translate_agent.cc b/components/translate/content/renderer/translate_agent.cc
index c3b668fb..162c7c67 100644
--- a/components/translate/content/renderer/translate_agent.cc
+++ b/components/translate/content/renderer/translate_agent.cc
@@ -17,6 +17,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "components/translate/content/renderer/isolated_world_util.h"
 #include "components/translate/core/common/translate_constants.h"
 #include "components/translate/core/common/translate_metrics.h"
 #include "components/translate/core/common/translate_util.h"
@@ -26,7 +27,6 @@
 #include "content/public/renderer/render_frame.h"
 #include "content/public/renderer/render_thread.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
-#include "third_party/blink/public/platform/web_isolated_world_info.h"
 #include "third_party/blink/public/web/web_document.h"
 #include "third_party/blink/public/web/web_language_detection_details.h"
 #include "third_party/blink/public/web/web_local_frame.h"
@@ -38,7 +38,6 @@
 using blink::WebLanguageDetectionDetails;
 using blink::WebLocalFrame;
 using blink::WebScriptSource;
-using blink::WebSecurityOrigin;
 using blink::WebString;
 using blink::WebVector;
 
@@ -58,10 +57,6 @@
 
 // Language name passed to the Translate element for it to detect the language.
 const char kAutoDetectionLanguage[] = "auto";
-
-// Isolated world sets following content-security-policy.
-const char kContentSecurityPolicy[] = "script-src 'self' 'unsafe-eval'";
-
 }  // namespace
 
 namespace translate {
@@ -320,13 +315,8 @@
   GURL url(main_frame->GetDocument().Url());
   ReportPageScheme(url.scheme());
 
-  // Set up v8 isolated world with proper content-security-policy and
-  // security-origin.
-  blink::WebIsolatedWorldInfo info;
-  info.security_origin =
-      WebSecurityOrigin::Create(GetTranslateSecurityOrigin());
-  info.content_security_policy = WebString::FromUTF8(kContentSecurityPolicy);
-  main_frame->SetIsolatedWorldInfo(world_id_, info);
+  // Set up v8 isolated world.
+  EnsureIsolatedWorldInitialized(world_id_);
 
   if (!IsTranslateLibAvailable()) {
     // Evaluate the script to add the translation related method to the global
diff --git a/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc b/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
index ff5eb68..61d2bc78 100644
--- a/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
+++ b/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
@@ -54,8 +54,8 @@
 #include "storage/browser/quota/quota_manager_proxy.h"
 #include "third_party/blink/public/common/cache_storage/cache_storage_utils.h"
 #include "third_party/blink/public/common/fetch/fetch_api_request_headers_map.h"
+#include "third_party/blink/public/mojom/loader/referrer.mojom.h"
 #include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
-#include "third_party/blink/public/mojom/referrer.mojom.h"
 
 using blink::mojom::CacheStorageError;
 using blink::mojom::CacheStorageVerboseError;
diff --git a/content/browser/net/split_cache_browsertest.cc b/content/browser/net/split_cache_browsertest.cc
index 3878728e..3a77415 100644
--- a/content/browser/net/split_cache_browsertest.cc
+++ b/content/browser/net/split_cache_browsertest.cc
@@ -335,6 +335,7 @@
     EXPECT_TRUE(ExecuteScript(host_to_load_resource, GetWorkerScript(worker)));
 
     observer.WaitForResourceCompletion(GenURL("3p.com", "/script"));
+    observer.WaitForResourceCompletion(worker);
 
     return (*observer.FindResource(worker))->was_cached;
   }
@@ -613,14 +614,8 @@
                                GenURL("c.com", "/title1.html")));
 }
 
-// TODO(http://crbug.com/997808): Flaky on Linux ASAN.
-#if defined(OS_LINUX) && (defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER))
-#define MAYBE_SplitCacheDedicatedWorkers DISABLED_SplitCacheDedicatedWorkers
-#else
-#define MAYBE_SplitCacheDedicatedWorkers SplitCacheDedicatedWorkers
-#endif
 IN_PROC_BROWSER_TEST_F(SplitCacheWithFrameOriginContentBrowserTest,
-                       MAYBE_SplitCacheDedicatedWorkers) {
+                       SplitCacheDedicatedWorkers) {
   // Load 3p.com/script from a.com's worker. The first time it's loaded from the
   // network and the second it's cached.
   EXPECT_FALSE(TestResourceLoadFromDedicatedWorker(
@@ -719,7 +714,7 @@
 }
 
 IN_PROC_BROWSER_TEST_P(SplitCacheContentBrowserTestEnabled,
-                       MAYBE_SplitCacheDedicatedWorkers) {
+                       SplitCacheDedicatedWorkers) {
   // Load 3p.com/script from a.com's worker. The first time it's loaded from the
   // network and the second it's cached.
   EXPECT_FALSE(TestResourceLoadFromDedicatedWorker(
@@ -762,15 +757,8 @@
       GenURL("e.com", "/worker.js")));
 }
 
-// TODO(http://crbug.com/997732): Flaky on Linux and macOS.
-#if defined(OS_LINUX) || defined(OS_MACOSX)
-#define MAYBE_SplitCacheDedicatedWorkerScripts \
-  DISABLED_SplitCacheDedicatedWorkersScripts
-#else
-#define MAYBE_SplitCacheDedicatedWorkerScripts SplitCacheDedicatedWorkersScripts
-#endif
 IN_PROC_BROWSER_TEST_P(SplitCacheContentBrowserTestEnabled,
-                       MAYBE_SplitCacheDedicatedWorkerScripts) {
+                       SplitCacheDedicatedWorkersScripts) {
   // Load a.com's worker. The first time the worker script is loaded from the
   // network and the second it's cached.
   EXPECT_FALSE(DedicatedWorkerScriptCached(
@@ -810,7 +798,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(SplitCacheContentBrowserTestDisabled,
-                       MAYBE_SplitCacheDedicatedWorkers) {
+                       SplitCacheDedicatedWorkers) {
   // Load 3p.com/script from a.com's worker. The first time it's loaded from the
   // network and the second it's cached.
   EXPECT_FALSE(TestResourceLoadFromDedicatedWorker(
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
index a43d0126..c88e3eb3 100644
--- a/content/browser/service_worker/service_worker_browsertest.cc
+++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -13,6 +13,7 @@
 #include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/command_line.h"
+#include "base/guid.h"
 #include "base/json/json_reader.h"
 #include "base/memory/ref_counted.h"
 #include "base/metrics/statistics_recorder.h"
@@ -40,6 +41,7 @@
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_context_core_observer.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/browser/service_worker/service_worker_fetch_dispatcher.h"
 #include "content/browser/service_worker/service_worker_registration.h"
 #include "content/browser/service_worker/service_worker_test_utils.h"
 #include "content/browser/service_worker/service_worker_version.h"
@@ -962,6 +964,79 @@
   run_loop.Run();
 }
 
+// Make sure that a fetch event is dispatched to a stopped worker in the task
+// which calls ServiceWorkerFetchDispatcher::Run().
+IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
+                       DispatchFetchEventToStoppedWorkerSynchronously) {
+  // Setup the server so that the test doesn't crash when tearing down.
+  StartServerAndNavigateToSetup();
+  // This test is meaningful only when ServiceWorkerOnUI is enabled.
+  if (!ServiceWorkerContext::IsServiceWorkerOnUIEnabled())
+    return;
+
+  WorkerRunningStatusObserver observer(public_context());
+  EXPECT_TRUE(NavigateToURL(shell(),
+                            embedded_test_server()->GetURL(
+                                "/service_worker/create_service_worker.html")));
+  EXPECT_EQ("DONE", EvalJs(shell(), "register('fetch_event.js');"));
+  observer.WaitUntilRunning();
+
+  ASSERT_TRUE(
+      BrowserThread::CurrentlyOn(ServiceWorkerContext::GetCoreThreadId()));
+  scoped_refptr<ServiceWorkerVersion> version =
+      wrapper()->GetLiveVersion(observer.version_id());
+  EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, version->running_status());
+
+  {
+    base::RunLoop loop;
+    version->StopWorker(loop.QuitClosure());
+    loop.Run();
+    EXPECT_EQ(EmbeddedWorkerStatus::STOPPED, version->running_status());
+  }
+
+  bool is_prepare_callback_called = false;
+  base::RunLoop fetch_loop;
+  blink::ServiceWorkerStatusCode fetch_status;
+  ServiceWorkerFetchDispatcher::FetchEventResult fetch_result;
+  blink::mojom::FetchAPIResponsePtr fetch_response;
+
+  auto request = blink::mojom::FetchAPIRequest::New();
+  request->url = embedded_test_server()->GetURL("/service_worker/in-scope");
+  request->method = "GET";
+  request->is_main_resource_load = true;
+  auto dispatcher = std::make_unique<ServiceWorkerFetchDispatcher>(
+      std::move(request), blink::mojom::ResourceType::kMainFrame,
+      /*client_id=*/base::GenerateGUID(), version,
+      base::BindLambdaForTesting([&]() { is_prepare_callback_called = true; }),
+      base::BindLambdaForTesting(
+          [&](blink::ServiceWorkerStatusCode status,
+              ServiceWorkerFetchDispatcher::FetchEventResult result,
+              blink::mojom::FetchAPIResponsePtr response,
+              blink::mojom::ServiceWorkerStreamHandlePtr,
+              blink::mojom::ServiceWorkerFetchEventTimingPtr,
+              scoped_refptr<ServiceWorkerVersion>) {
+            fetch_status = status;
+            fetch_result = result;
+            fetch_response = std::move(response);
+            fetch_loop.Quit();
+          }),
+      /*is_offline_capability_check=*/false);
+
+  // DispatchFetchEvent is called synchronously with dispatcher->Run() even if
+  // the worker is stopped.
+  dispatcher->Run();
+  EXPECT_TRUE(is_prepare_callback_called);
+  EXPECT_FALSE(fetch_response);
+
+  // Check if the fetch event is handled by fetch_event.js correctly.
+  fetch_loop.Run();
+  ASSERT_TRUE(fetch_response);
+  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, fetch_status);
+  EXPECT_EQ(ServiceWorkerFetchDispatcher::FetchEventResult::kGotResponse,
+            fetch_result);
+  EXPECT_EQ(301, fetch_response->status_code);
+}
+
 class ServiceWorkerEagerCacheStorageSetupTest
     : public ServiceWorkerBrowserTest {
  public:
diff --git a/content/browser/service_worker/service_worker_context_core.cc b/content/browser/service_worker/service_worker_context_core.cc
index 8ece6cd..9ce8ecc 100644
--- a/content/browser/service_worker/service_worker_context_core.cc
+++ b/content/browser/service_worker/service_worker_context_core.cc
@@ -551,7 +551,7 @@
 void ServiceWorkerContextCore::PerformStorageCleanup(
     base::OnceClosure callback) {
   DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId());
-  storage()->PerformStorageCleanup(std::move(callback));
+  GetStorageControl()->PerformStorageCleanup(std::move(callback));
 }
 
 void ServiceWorkerContextCore::DidGetRegistrationsForDeleteForOrigin(
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
index ab1a589..c797a8e5 100644
--- a/content/browser/service_worker/service_worker_fetch_dispatcher.cc
+++ b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -532,6 +532,13 @@
       GetEventType(),
       base::BindOnce(&ServiceWorkerFetchDispatcher::DidStartWorker,
                      weak_factory_.GetWeakPtr()));
+
+  if (ServiceWorkerContext::IsServiceWorkerOnUIEnabled() &&
+      version_->is_endpoint_ready()) {
+    // For an active service worker, the endpoint becomes ready synchronously
+    // with StartWorker(). In that case, we can dispatch FetchEvent immediately.
+    DispatchFetchEvent();
+  }
 }
 
 void ServiceWorkerFetchDispatcher::DidStartWorker(
@@ -545,17 +552,19 @@
     DidFail(status);
     return;
   }
-  DispatchFetchEvent();
+  if (!IsEventDispatched()) {
+    DispatchFetchEvent();
+  }
 }
 
 void ServiceWorkerFetchDispatcher::DispatchFetchEvent() {
-  DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, version_->running_status())
+  DCHECK(EmbeddedWorkerStatus::STARTING == version_->running_status() ||
+         EmbeddedWorkerStatus::RUNNING == version_->running_status())
       << "Worker stopped too soon after it was started.";
   TRACE_EVENT_WITH_FLOW0("ServiceWorker",
                          "ServiceWorkerFetchDispatcher::DispatchFetchEvent",
                          TRACE_ID_LOCAL(this),
                          TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
-
   // Grant the service worker's process access to files in the request body.
   if (request_->body) {
     GrantFileAccessToProcess(version_->embedded_worker()->process_id(),
@@ -759,6 +768,10 @@
   return ResourceTypeToEventType(resource_type_);
 }
 
+bool ServiceWorkerFetchDispatcher::IsEventDispatched() const {
+  return request_.is_null();
+}
+
 // static
 void ServiceWorkerFetchDispatcher::OnFetchEventFinished(
     ServiceWorkerVersion* version,
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.h b/content/browser/service_worker/service_worker_fetch_dispatcher.h
index c24c6308..87ffce31 100644
--- a/content/browser/service_worker/service_worker_fetch_dispatcher.h
+++ b/content/browser/service_worker/service_worker_fetch_dispatcher.h
@@ -109,6 +109,8 @@
 
   ServiceWorkerMetrics::EventType GetEventType() const;
 
+  bool IsEventDispatched() const;
+
   blink::mojom::FetchAPIRequestPtr request_;
   std::string client_id_;
   scoped_refptr<ServiceWorkerVersion> version_;
diff --git a/content/browser/service_worker/service_worker_script_cache_map.cc b/content/browser/service_worker/service_worker_script_cache_map.cc
index 712c3f0..a93966d7 100644
--- a/content/browser/service_worker/service_worker_script_cache_map.cc
+++ b/content/browser/service_worker/service_worker_script_cache_map.cc
@@ -10,10 +10,7 @@
 #include "base/check_op.h"
 #include "content/browser/service_worker/service_worker_consts.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
-#include "content/browser/service_worker/service_worker_disk_cache.h"
-#include "content/browser/service_worker/service_worker_storage.h"
 #include "content/browser/service_worker/service_worker_version.h"
-#include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
 
 namespace content {
@@ -112,16 +109,13 @@
     return;
   }
 
-  scoped_refptr<net::IOBuffer> buffer =
-      base::MakeRefCounted<net::IOBuffer>(data.size());
-  if (data.size())
-    memmove(buffer->data(), &data[0], data.size());
-  std::unique_ptr<ServiceWorkerResponseMetadataWriter> writer;
-  writer = context_->storage()->CreateResponseMetadataWriter(
-      found->second->resource_id);
-  ServiceWorkerResponseMetadataWriter* raw_writer = writer.get();
+  mojo_base::BigBuffer buffer(base::as_bytes(data));
+  mojo::Remote<storage::mojom::ServiceWorkerResourceMetadataWriter> writer;
+  context_->GetStorageControl()->CreateResourceMetadataWriter(
+      found->second->resource_id, writer.BindNewPipeAndPassReceiver());
+  auto* raw_writer = writer.get();
   raw_writer->WriteMetadata(
-      buffer.get(), data.size(),
+      std::move(buffer),
       base::BindOnce(&ServiceWorkerScriptCacheMap::OnMetadataWritten,
                      weak_factory_.GetWeakPtr(), std::move(writer),
                      std::move(callback)));
@@ -134,7 +128,7 @@
 }
 
 void ServiceWorkerScriptCacheMap::OnMetadataWritten(
-    std::unique_ptr<ServiceWorkerResponseMetadataWriter> writer,
+    mojo::Remote<storage::mojom::ServiceWorkerResourceMetadataWriter> writer,
     net::CompletionOnceCallback callback,
     int result) {
   std::move(callback).Run(result);
diff --git a/content/browser/service_worker/service_worker_script_cache_map.h b/content/browser/service_worker/service_worker_script_cache_map.h
index ef8a55e..18a44c4 100644
--- a/content/browser/service_worker/service_worker_script_cache_map.h
+++ b/content/browser/service_worker/service_worker_script_cache_map.h
@@ -13,8 +13,10 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "components/services/storage/public/mojom/service_worker_storage_control.mojom.h"
 #include "content/browser/service_worker/service_worker_database.h"
 #include "content/common/content_export.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "net/base/completion_once_callback.h"
 #include "net/base/net_errors.h"
 
@@ -24,7 +26,6 @@
 
 class ServiceWorkerContextCore;
 class ServiceWorkerVersion;
-class ServiceWorkerResponseMetadataWriter;
 
 // Class that maintains the mapping between urls and a resource id
 // for a particular version's implicit script resources.
@@ -80,7 +81,7 @@
   ~ServiceWorkerScriptCacheMap();
 
   void OnMetadataWritten(
-      std::unique_ptr<ServiceWorkerResponseMetadataWriter> writer,
+      mojo::Remote<storage::mojom::ServiceWorkerResourceMetadataWriter>,
       net::CompletionOnceCallback callback,
       int result);
 
diff --git a/content/browser/service_worker/service_worker_storage_control_impl.cc b/content/browser/service_worker/service_worker_storage_control_impl.cc
index 7257c19..f83c0005 100644
--- a/content/browser/service_worker/service_worker_storage_control_impl.cc
+++ b/content/browser/service_worker/service_worker_storage_control_impl.cc
@@ -353,6 +353,11 @@
                                                         std::move(callback));
 }
 
+void ServiceWorkerStorageControlImpl::PerformStorageCleanup(
+    PerformStorageCleanupCallback callback) {
+  storage_->PerformStorageCleanup(std::move(callback));
+}
+
 void ServiceWorkerStorageControlImpl::ApplyPolicyUpdates(
     const std::vector<storage::mojom::LocalStoragePolicyUpdatePtr>
         policy_updates) {
diff --git a/content/browser/service_worker/service_worker_storage_control_impl.h b/content/browser/service_worker/service_worker_storage_control_impl.h
index 5f350f2..b939948 100644
--- a/content/browser/service_worker/service_worker_storage_control_impl.h
+++ b/content/browser/service_worker/service_worker_storage_control_impl.h
@@ -140,6 +140,7 @@
   void ClearUserDataForAllRegistrationsByKeyPrefix(
       const std::string& key_prefix,
       ClearUserDataForAllRegistrationsByKeyPrefixCallback callback) override;
+  void PerformStorageCleanup(PerformStorageCleanupCallback callback) override;
   void ApplyPolicyUpdates(
       const std::vector<storage::mojom::LocalStoragePolicyUpdatePtr>
           policy_updates) override;
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index ca5ae8ca..1e01883 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -477,6 +477,12 @@
   switch (running_status()) {
     case EmbeddedWorkerStatus::STARTING:
     case EmbeddedWorkerStatus::RUNNING: {
+      // Endpoint isn't available after calling StopWorker(). This needs to be
+      // set here without waiting until the worker is actually stopped because
+      // subsequent StartWorker() may read the flag to decide whether an event
+      // can be dispatched or not.
+      is_endpoint_ready_ = false;
+
       // EmbeddedWorkerInstance::Stop() may synchronously call
       // ServiceWorkerVersion::OnStopped() and destroy |this|. This protection
       // avoids it.
@@ -583,8 +589,9 @@
     StatusCallback error_callback,
     const base::TimeDelta& timeout,
     TimeoutBehavior timeout_behavior) {
-  DCHECK_EQ(EmbeddedWorkerStatus::RUNNING, running_status())
-      << "Can only start a request with a running worker.";
+  DCHECK(EmbeddedWorkerStatus::RUNNING == running_status() ||
+         EmbeddedWorkerStatus::STARTING == running_status())
+      << "Can only start a request with a running or starting worker.";
   DCHECK(event_type == ServiceWorkerMetrics::EventType::INSTALL ||
          event_type == ServiceWorkerMetrics::EventType::ACTIVATE ||
          event_type == ServiceWorkerMetrics::EventType::MESSAGE ||
@@ -1021,6 +1028,7 @@
   }
 
   DCHECK(worker_host_);
+  DCHECK(service_worker_remote_);
   service_worker_remote_->InitializeGlobalScope(
       std::move(service_worker_host_),
       worker_host_->container_host()->CreateServiceWorkerRegistrationObjectInfo(
@@ -1028,6 +1036,8 @@
       worker_host_->container_host()->CreateServiceWorkerObjectInfoToSend(this),
       fetch_handler_existence_, std::move(subresource_loader_factories),
       std::move(reporting_observer_receiver_));
+
+  is_endpoint_ready_ = true;
 }
 
 void ServiceWorkerVersion::SetValidOriginTrialTokens(
@@ -1868,11 +1878,13 @@
       base::BindOnce(&OnConnectionError, embedded_worker_->AsWeakPtr()));
   receiver_.reset();
   receiver_.Bind(service_worker_host_.InitWithNewEndpointAndPassReceiver());
+
   // Initialize the global scope now if the worker won't be paused. Otherwise,
   // delay initialization until the main script is loaded.
-  if (!initialize_global_scope_after_main_script_loaded_)
+  if (!initialize_global_scope_after_main_script_loaded_) {
     InitializeGlobalScope(/*script_loader_factories=*/nullptr,
                           /*subresource_loader_factories=*/nullptr);
+  }
 
   if (!controller_receiver_.is_valid()) {
     controller_receiver_ = remote_controller_.BindNewPipeAndPassReceiver();
@@ -2230,6 +2242,7 @@
   request_timeouts_.clear();
   external_request_uuid_to_request_id_.clear();
   service_worker_remote_.reset();
+  is_endpoint_ready_ = false;
   remote_controller_.reset();
   DCHECK(!controller_receiver_.is_valid());
   installed_scripts_sender_.reset();
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
index 7fa90b2..7be6c098 100644
--- a/content/browser/service_worker/service_worker_version.h
+++ b/content/browser/service_worker/service_worker_version.h
@@ -339,7 +339,8 @@
   // code and the dispatch time. See service_worker.mojom.
   SimpleEventCallback CreateSimpleEventCallback(int request_id);
 
-  // This must be called when the worker is running.
+  // This must be called when is_endpoint_ready() returns true, which is after
+  // InitializeGlobalScope() is called.
   blink::mojom::ServiceWorker* endpoint() {
     DCHECK(running_status() == EmbeddedWorkerStatus::STARTING ||
            running_status() == EmbeddedWorkerStatus::RUNNING);
@@ -347,6 +348,8 @@
     return service_worker_remote_.get();
   }
 
+  bool is_endpoint_ready() const { return is_endpoint_ready_; }
+
   // Returns the 'controller' interface ptr of this worker. It is expected that
   // the worker is already starting or running, or is going to be started soon.
   // TODO(kinuko): Relying on the callsites to start the worker when it's
@@ -910,6 +913,9 @@
 
   Status status_ = NEW;
   std::unique_ptr<EmbeddedWorkerInstance> embedded_worker_;
+  // True if endpoint() is ready to dispatch events, which means
+  // InitializeGlobalScope() is already called.
+  bool is_endpoint_ready_ = false;
   std::vector<StatusCallback> start_callbacks_;
   std::vector<base::OnceClosure> stop_callbacks_;
   std::vector<base::OnceClosure> status_change_callbacks_;
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc
index 27cb3eeb..3c19196 100644
--- a/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -2422,6 +2422,9 @@
   EXPECT_CALL(delegate,
               RegisterProtocolHandler(contents(), "mailto", handler_url1, true))
       .Times(1);
+  EXPECT_CALL(delegate,
+              RegisterProtocolHandler(contents(), "mailto", handler_url2, true))
+      .Times(0);
 
   {
     contents()->RegisterProtocolHandler(main_test_rfh(), "mailto", handler_url1,
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
index d9817d5..a632d99 100644
--- a/content/common/frame.mojom
+++ b/content/common/frame.mojom
@@ -41,7 +41,7 @@
 import "third_party/blink/public/mojom/messaging/transferable_message.mojom";
 import "third_party/blink/public/mojom/page/widget.mojom";
 import "third_party/blink/public/mojom/portal/portal.mojom";
-import "third_party/blink/public/mojom/referrer.mojom";
+import "third_party/blink/public/mojom/loader/referrer.mojom";
 import "third_party/blink/public/mojom/service_worker/controller_service_worker.mojom";
 import "third_party/blink/public/mojom/service_worker/service_worker_container.mojom";
 import "third_party/blink/public/mojom/window_features/window_features.mojom";
diff --git a/content/common/navigation_params.mojom b/content/common/navigation_params.mojom
index 3e019dc1..fb9c824 100644
--- a/content/common/navigation_params.mojom
+++ b/content/common/navigation_params.mojom
@@ -20,7 +20,7 @@
 import "third_party/blink/public/mojom/feature_policy/feature_policy.mojom";
 import "third_party/blink/public/mojom/fetch/fetch_api_request.mojom";
 import "third_party/blink/public/mojom/frame/frame_policy.mojom";
-import "third_party/blink/public/mojom/referrer.mojom";
+import "third_party/blink/public/mojom/loader/referrer.mojom";
 import "url/mojom/origin.mojom";
 import "url/mojom/url.mojom";
 
diff --git a/content/public/common/referrer.cc b/content/public/common/referrer.cc
index 4542c0f..2faa0972 100644
--- a/content/public/common/referrer.cc
+++ b/content/public/common/referrer.cc
@@ -16,7 +16,7 @@
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/mojom/referrer_policy.mojom-shared.h"
-#include "third_party/blink/public/mojom/referrer.mojom.h"
+#include "third_party/blink/public/mojom/loader/referrer.mojom.h"
 
 namespace content {
 
diff --git a/content/public/common/referrer.h b/content/public/common/referrer.h
index e895e42..a6ef571 100644
--- a/content/public/common/referrer.h
+++ b/content/public/common/referrer.h
@@ -8,7 +8,7 @@
 #include "content/common/content_export.h"
 #include "net/url_request/referrer_policy.h"
 #include "services/network/public/mojom/referrer_policy.mojom-shared.h"
-#include "third_party/blink/public/mojom/referrer.mojom-forward.h"
+#include "third_party/blink/public/mojom/loader/referrer.mojom-forward.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
diff --git a/content/public/common/referrer_type_converters.h b/content/public/common/referrer_type_converters.h
index cffd525..c7f355c25 100644
--- a/content/public/common/referrer_type_converters.h
+++ b/content/public/common/referrer_type_converters.h
@@ -8,7 +8,7 @@
 #include "content/common/content_export.h"
 #include "content/public/common/referrer.h"
 #include "mojo/public/cpp/bindings/type_converter.h"
-#include "third_party/blink/public/mojom/referrer.mojom.h"
+#include "third_party/blink/public/mojom/loader/referrer.mojom.h"
 
 namespace mojo {
 // TODO(leonhsl): Remove these converters once we remove content::Referrer.
diff --git a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/TestTouchUtils.java b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/TestTouchUtils.java
index 23fbf56..485b818 100644
--- a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/TestTouchUtils.java
+++ b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/TestTouchUtils.java
@@ -203,7 +203,7 @@
      * @param v The view to call performClick on.
      */
     public static void performClickOnMainSync(Instrumentation instrumentation, final View v) {
-        TestThreadUtils.runOnUiThreadBlocking(() -> { v.performClick(); });
+        instrumentation.runOnMainSync(() -> v.performClick());
     }
 
     /**
diff --git a/content/public/test/mock_navigation_handle.h b/content/public/test/mock_navigation_handle.h
index 498ab6a..c132ce6 100644
--- a/content/public/test/mock_navigation_handle.h
+++ b/content/public/test/mock_navigation_handle.h
@@ -13,7 +13,7 @@
 #include "net/base/ip_endpoint.h"
 #include "net/base/isolation_info.h"
 #include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/blink/public/mojom/referrer.mojom.h"
+#include "third_party/blink/public/mojom/loader/referrer.mojom.h"
 #include "url/gurl.h"
 
 namespace content {
diff --git a/content/public/test/navigation_simulator.h b/content/public/test/navigation_simulator.h
index fcfc3a3..3ef5b96 100644
--- a/content/public/test/navigation_simulator.h
+++ b/content/public/test/navigation_simulator.h
@@ -14,7 +14,7 @@
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "net/dns/public/resolve_error_info.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
-#include "third_party/blink/public/mojom/referrer.mojom.h"
+#include "third_party/blink/public/mojom/loader/referrer.mojom.h"
 #include "ui/base/page_transition_types.h"
 
 class GURL;
diff --git a/content/renderer/performance_manager/v8_per_frame_memory_reporter_impl.cc b/content/renderer/performance_manager/v8_per_frame_memory_reporter_impl.cc
index 2cd2b9d..3d350549 100644
--- a/content/renderer/performance_manager/v8_per_frame_memory_reporter_impl.cc
+++ b/content/renderer/performance_manager/v8_per_frame_memory_reporter_impl.cc
@@ -7,6 +7,7 @@
 #include "base/containers/flat_map.h"
 #include "content/public/common/isolated_world_ids.h"
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
+#include "third_party/blink/public/platform/web_isolated_world_info.h"
 #include "third_party/blink/public/web/web_local_frame.h"
 #include "third_party/blink/public/web/web_local_frame_client.h"
 #include "v8/include/v8.h"
@@ -87,9 +88,9 @@
 
         if (world_id != content::ISOLATED_WORLD_ID_GLOBAL) {
           isolated_world_usage->stable_id =
-              frame->GetIsolatedWorldStableId(context).Utf8();
+              blink::GetIsolatedWorldStableId(context).Utf8();
           isolated_world_usage->human_readable_name =
-              frame->GetIsolatedWorldHumanReadableName(context).Utf8();
+              blink::GetIsolatedWorldHumanReadableName(context).Utf8();
         }
 
         DCHECK(
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 7f73a8952..2ead495 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -168,10 +168,10 @@
 #include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom.h"
 #include "third_party/blink/public/mojom/input/focus_type.mojom.h"
 #include "third_party/blink/public/mojom/input/input_handler.mojom-shared.h"
+#include "third_party/blink/public/mojom/loader/referrer.mojom.h"
 #include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom.h"
 #include "third_party/blink/public/mojom/loader/resource_load_info.mojom.h"
 #include "third_party/blink/public/mojom/permissions/permission.mojom.h"
-#include "third_party/blink/public/mojom/referrer.mojom.h"
 #include "third_party/blink/public/platform/file_path_conversion.h"
 #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
 #include "third_party/blink/public/platform/url_conversion.h"
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 0b3a871..f16af9a 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -588,24 +588,6 @@
   if (for_frame()) {
     SetZoomLevel(visual_properties.zoom_level);
 
-    if (root_widget_window_segments_ !=
-        visual_properties.root_widget_window_segments) {
-      root_widget_window_segments_ =
-          visual_properties.root_widget_window_segments;
-
-      blink::WebVector<blink::WebRect> web_segments;
-      web_segments.reserve(root_widget_window_segments_.size());
-      for (const auto& segment : root_widget_window_segments_)
-        web_segments.emplace_back(segment);
-
-      GetWebWidget()->SetWindowSegments(std::move(web_segments));
-
-      // Propagate changes down to child local root RenderWidgets in other frame
-      // trees/processes.
-      for (auto& observer : render_frame_proxies_)
-        observer.OnRootWindowSegmentsChanged(root_widget_window_segments_);
-    }
-
     bool capture_sequence_number_changed =
         visual_properties.capture_sequence_number !=
         last_capture_sequence_number_;
@@ -655,8 +637,12 @@
     // emulation.
     device_emulator_->OnSynchronizeVisualProperties(
         visual_properties.screen_info, visual_properties.new_size,
-        visual_properties.visible_viewport_size);
+        visual_properties.visible_viewport_size,
+        visual_properties.root_widget_window_segments);
   } else {
+    if (for_frame())
+      SetRootWindowSegments(visual_properties.root_widget_window_segments);
+
     // We can ignore browser-initialized resizing during synchronous
     // (renderer-controlled) mode, unless it is switching us to/from
     // fullsreen mode or changing the device scale factor.
@@ -787,9 +773,6 @@
         window_screen_rect_);
   }
   device_emulator_->ChangeEmulationParams(params);
-  // TODO: crbug.com/1099026
-  // https://chromium-review.googlesource.com/c/chromium/src/+/2262193/1
-  // Update root_widget_window_segments here.
 }
 
 void RenderWidget::OnDisableDeviceEmulation() {
@@ -854,6 +837,25 @@
   }
 }
 
+void RenderWidget::SetRootWindowSegments(
+    const std::vector<gfx::Rect>& root_window_segments) {
+  if (root_widget_window_segments_ != root_window_segments) {
+    root_widget_window_segments_ = root_window_segments;
+
+    blink::WebVector<blink::WebRect> web_segments;
+    web_segments.reserve(root_widget_window_segments_.size());
+    for (const auto& segment : root_widget_window_segments_)
+      web_segments.emplace_back(segment);
+
+    GetWebWidget()->SetWindowSegments(std::move(web_segments));
+
+    // Propagate changes down to child local root RenderWidgets in other frame
+    // trees/processes.
+    for (auto& observer : render_frame_proxies_)
+      observer.OnRootWindowSegmentsChanged(root_widget_window_segments_);
+  }
+}
+
 void RenderWidget::OnWasHidden() {
   // A provisional frame widget will never be hidden since that would require it
   // to be shown first. A frame must be attached to the frame tree before
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index 5887954..8ed53f5 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -263,6 +263,8 @@
                             const gfx::Size& visible_viewport_size) override;
   void SetScreenRects(const gfx::Rect& widget_screen_rect,
                       const gfx::Rect& window_screen_rect) override;
+  void SetRootWindowSegments(
+      const std::vector<gfx::Rect>& root_window_segments) override;
 
   // blink::WebWidgetClient
   void ScheduleAnimation() override;
diff --git a/content/renderer/render_widget_screen_metrics_emulator.cc b/content/renderer/render_widget_screen_metrics_emulator.cc
index 7b25b6e..4d8b170d 100644
--- a/content/renderer/render_widget_screen_metrics_emulator.cc
+++ b/content/renderer/render_widget_screen_metrics_emulator.cc
@@ -31,6 +31,7 @@
   delegate_->SetScreenMetricsEmulationParameters(false, emulation_params_);
   delegate_->SetScreenRects(original_view_screen_rect_,
                             original_window_screen_rect_);
+  delegate_->SetRootWindowSegments(original_root_window_segments_);
   delegate_->SetScreenInfoAndSize(original_screen_info_, original_widget_size_,
                                   original_visible_viewport_size_);
 }
@@ -130,6 +131,14 @@
   delegate_->SetScreenRects(gfx::Rect(widget_pos, widget_size),
                             gfx::Rect(window_pos, window_size));
 
+  // If there are no emulated window segments, use the original ones - when we
+  // switch from having them to having none, we need to fallback to the original
+  // value. If there never were any emulated segments this is a no-op.
+  bool emulated_window_segments = emulation_params_.window_segments.size();
+  delegate_->SetRootWindowSegments(emulated_window_segments
+                                       ? emulation_params_.window_segments
+                                       : original_root_window_segments_);
+
   blink::ScreenInfo screen_info = original_screen_info();
   screen_info.device_scale_factor = device_scale_factor;
   screen_info.rect = screen_rect;
@@ -143,10 +152,12 @@
 void RenderWidgetScreenMetricsEmulator::OnSynchronizeVisualProperties(
     const blink::ScreenInfo& screen_info,
     const gfx::Size& widget_size,
-    const gfx::Size& visible_viewport_size) {
+    const gfx::Size& visible_viewport_size,
+    const std::vector<gfx::Rect>& root_window_segments) {
   original_screen_info_ = screen_info;
   original_widget_size_ = widget_size;
   original_visible_viewport_size_ = visible_viewport_size;
+  original_root_window_segments_ = root_window_segments;
   Apply();
 }
 
diff --git a/content/renderer/render_widget_screen_metrics_emulator.h b/content/renderer/render_widget_screen_metrics_emulator.h
index a5a32d1..d40108fa 100644
--- a/content/renderer/render_widget_screen_metrics_emulator.h
+++ b/content/renderer/render_widget_screen_metrics_emulator.h
@@ -59,9 +59,12 @@
   // Sets new parameters and applies them to the RenderWidget.
   void ChangeEmulationParams(const blink::WebDeviceEmulationParams& params);
 
-  void OnSynchronizeVisualProperties(const blink::ScreenInfo& screen_info,
-                                     const gfx::Size& widget_size,
-                                     const gfx::Size& visible_viewport_size);
+  void OnSynchronizeVisualProperties(
+      const blink::ScreenInfo& screen_info,
+      const gfx::Size& widget_size,
+      const gfx::Size& visible_viewport_size,
+      const std::vector<gfx::Rect>& root_window_segments);
+
   void OnUpdateScreenRects(const gfx::Rect& view_screen_rect,
                            const gfx::Rect& window_screen_rect);
 
@@ -85,6 +88,7 @@
   gfx::Size original_visible_viewport_size_;
   gfx::Rect original_view_screen_rect_;
   gfx::Rect original_window_screen_rect_;
+  std::vector<gfx::Rect> original_root_window_segments_;
 
   DISALLOW_COPY_AND_ASSIGN(RenderWidgetScreenMetricsEmulator);
 };
diff --git a/content/renderer/render_widget_screen_metrics_emulator_delegate.h b/content/renderer/render_widget_screen_metrics_emulator_delegate.h
index 414323e9..1e12de88 100644
--- a/content/renderer/render_widget_screen_metrics_emulator_delegate.h
+++ b/content/renderer/render_widget_screen_metrics_emulator_delegate.h
@@ -33,6 +33,9 @@
   virtual void SetScreenRects(const gfx::Rect& view_screen_rect,
                               const gfx::Rect& window_screen_rect) = 0;
 
+  virtual void SetRootWindowSegments(
+      const std::vector<gfx::Rect>& root_window_segments) = 0;
+
  protected:
   virtual ~RenderWidgetScreenMetricsEmulatorDelegate() {}
 };
diff --git a/content/shell/renderer/web_test/test_runner.cc b/content/shell/renderer/web_test/test_runner.cc
index 0cec169b..d17476c 100644
--- a/content/shell/renderer/web_test/test_runner.cc
+++ b/content/shell/renderer/web_test/test_runner.cc
@@ -1108,7 +1108,7 @@
   // Clear the document->isolated world CSP mapping.
   GetWebFrame()->ClearIsolatedWorldCSPForTesting(world_id);
 
-  GetWebFrame()->SetIsolatedWorldInfo(world_id, info);
+  blink::SetIsolatedWorldInfo(world_id, info);
 }
 
 void TestRunnerBindings::AddOriginAccessAllowListEntry(
diff --git a/content/test/navigation_simulator_impl.h b/content/test/navigation_simulator_impl.h
index 86cee208..884e0eef 100644
--- a/content/test/navigation_simulator_impl.h
+++ b/content/test/navigation_simulator_impl.h
@@ -23,7 +23,7 @@
 #include "net/base/ip_endpoint.h"
 #include "net/dns/public/resolve_error_info.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
-#include "third_party/blink/public/mojom/referrer.mojom-forward.h"
+#include "third_party/blink/public/mojom/loader/referrer.mojom-forward.h"
 #include "url/gurl.h"
 
 struct FrameHostMsg_DidCommitProvisionalLoad_Params;
diff --git a/extensions/common/extension_api.cc b/extensions/common/extension_api.cc
index a8828f93..d1575cd5 100644
--- a/extensions/common/extension_api.cc
+++ b/extensions/common/extension_api.cc
@@ -224,18 +224,12 @@
 base::StringPiece ExtensionAPI::GetSchemaStringPiece(
     const std::string& api_name) {
   DCHECK_EQ(api_name, GetAPINameFromFullName(api_name, nullptr));
-  auto cached = schema_strings_.find(api_name);
-  if (cached != schema_strings_.end())
-    return cached->second;
-
   ExtensionsClient* client = ExtensionsClient::Get();
   DCHECK(client);
   if (!default_configuration_initialized_)
     return base::StringPiece();
 
   base::StringPiece schema = client->GetAPISchema(api_name);
-  if (!schema.empty())
-    schema_strings_[api_name] = schema;
   return schema;
 }
 
diff --git a/extensions/common/extension_api.h b/extensions/common/extension_api.h
index 01761a6..bdf05745 100644
--- a/extensions/common/extension_api.h
+++ b/extensions/common/extension_api.h
@@ -172,9 +172,6 @@
       std::map<std::string, std::unique_ptr<const base::DictionaryValue>>;
   SchemaMap schemas_;
 
-  using StringPieceMap = std::map<std::string, base::StringPiece>;
-  StringPieceMap schema_strings_;
-
   // FeatureProviders used for resolving dependencies.
   typedef std::map<std::string, const FeatureProvider*> FeatureProviderMap;
   FeatureProviderMap dependency_providers_;
diff --git a/extensions/common/permissions/extensions_api_permissions.cc b/extensions/common/permissions/extensions_api_permissions.cc
index 9bac9b019..4d82c54 100644
--- a/extensions/common/permissions/extensions_api_permissions.cc
+++ b/extensions/common/permissions/extensions_api_permissions.cc
@@ -39,7 +39,8 @@
          APIPermissionInfo::kFlagDoesNotRequireManagedSessionFullLoginWarning},
     {APIPermission::kAudio, "audio",
      APIPermissionInfo::kFlagDoesNotRequireManagedSessionFullLoginWarning},
-    {APIPermission::kAudioCapture, "audioCapture"},
+    {APIPermission::kAudioCapture, "audioCapture",
+     APIPermissionInfo::kFlagRequiresManagementUIWarning},
     {APIPermission::kBluetoothPrivate, "bluetoothPrivate",
      APIPermissionInfo::kFlagCannotBeOptional},
     {APIPermission::kCecPrivate, "cecPrivate",
@@ -144,7 +145,8 @@
     {APIPermission::kUsbDevice, "usbDevices",
      extensions::APIPermissionInfo::kFlagNone,
      &CreateAPIPermission<UsbDevicePermission>},
-    {APIPermission::kVideoCapture, "videoCapture"},
+    {APIPermission::kVideoCapture, "videoCapture",
+     APIPermissionInfo::kFlagRequiresManagementUIWarning},
     {APIPermission::kVirtualKeyboard, "virtualKeyboard"},
     {APIPermission::kVpnProvider, "vpnProvider",
      APIPermissionInfo::kFlagCannotBeOptional |
diff --git a/extensions/renderer/script_injection.cc b/extensions/renderer/script_injection.cc
index 6245142..73d37aaf 100644
--- a/extensions/renderer/script_injection.cc
+++ b/extensions/renderer/script_injection.cc
@@ -45,11 +45,10 @@
 // The id of the next pending injection.
 int64_t g_next_pending_id = 0;
 
-// Gets the isolated world ID to use for the given |injection_host|
-// in the given |frame|. If no isolated world has been created for that
-// |injection_host| one will be created and initialized.
-int GetIsolatedWorldIdForInstance(const InjectionHost* injection_host,
-                                  blink::WebLocalFrame* frame) {
+// Gets the isolated world ID to use for the given |injection_host|. If no
+// isolated world has been created for that |injection_host| one will be created
+// and initialized.
+int GetIsolatedWorldIdForInstance(const InjectionHost* injection_host) {
   static int g_next_isolated_world_id =
       ExtensionsRendererClient::Get()->GetLowestIsolatedWorldId();
 
@@ -67,9 +66,6 @@
     isolated_worlds[key] = id;
   }
 
-  // We need to set the isolated world origin and CSP even if it's not a new
-  // world since these are stored per frame, and we might not have used this
-  // isolated world in this frame before.
   blink::WebIsolatedWorldInfo info;
   info.security_origin =
       blink::WebSecurityOrigin::Create(injection_host->url());
@@ -80,7 +76,10 @@
   if (csp)
     info.content_security_policy = blink::WebString::FromUTF8(*csp);
 
-  frame->SetIsolatedWorldInfo(id, info);
+  // Even though there may be an existing world for this |injection_host|'s key,
+  // the properties may have changed (e.g. due to an extension update).
+  // Overwrite any existing entries.
+  blink::SetIsolatedWorldInfo(id, info);
 
   return id;
 }
@@ -285,12 +284,10 @@
 void ScriptInjection::InjectJs(std::set<std::string>* executing_scripts,
                                size_t* num_injected_js_scripts) {
   DCHECK(!did_inject_js_);
-  blink::WebLocalFrame* web_frame = render_frame_->GetWebFrame();
   std::vector<blink::WebScriptSource> sources = injector_->GetJsSources(
       run_location_, executing_scripts, num_injected_js_scripts);
   DCHECK(!sources.empty());
-  int world_id =
-      GetIsolatedWorldIdForInstance(injection_host_.get(), web_frame);
+  int world_id = GetIsolatedWorldIdForInstance(injection_host_.get());
   bool is_user_gesture = injector_->IsUserGesture();
 
   std::unique_ptr<blink::WebScriptExecutionCallback> callback(
@@ -315,7 +312,8 @@
       should_execute_asynchronously
           ? blink::WebLocalFrame::kAsynchronousBlockingOnload
           : blink::WebLocalFrame::kSynchronous;
-  web_frame->RequestExecuteScriptInIsolatedWorld(
+
+  render_frame_->GetWebFrame()->RequestExecuteScriptInIsolatedWorld(
       world_id, &sources.front(), sources.size(), is_user_gesture,
       execution_option, callback.release());
 }
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg
index 10cb002..13fa08f 100644
--- a/infra/config/generated/cr-buildbucket.cfg
+++ b/infra/config/generated/cr-buildbucket.cfg
@@ -17053,7 +17053,7 @@
         cipd_version: "refs/heads/master"
         cmd: "recipes"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\"},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma\",\"recipe\":\"chromium\"}"
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -17075,7 +17075,7 @@
         cipd_version: "refs/heads/master"
         cmd: "recipes"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\"},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma\",\"recipe\":\"chromium\"}"
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -17185,7 +17185,7 @@
         cipd_version: "refs/heads/master"
         cmd: "recipes"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\"},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma\",\"recipe\":\"chromium\"}"
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -17207,7 +17207,7 @@
         cipd_version: "refs/heads/master"
         cmd: "recipes"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\"},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma\",\"recipe\":\"chromium\"}"
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -17317,7 +17317,7 @@
         cipd_version: "refs/heads/master"
         cmd: "recipes"
       }
-      properties: "{\"$build/goma\":{\"jobs\":80,\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\"},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties: "{\"$build/goma\":{\"jobs\":80,\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma\",\"recipe\":\"chromium\"}"
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -17405,7 +17405,7 @@
         cipd_version: "refs/heads/master"
         cmd: "recipes"
       }
-      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\"},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma\",\"recipe\":\"chromium\"}"
+      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma\",\"recipe\":\"chromium\"}"
       execution_timeout_secs: 10800
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -17427,11 +17427,11 @@
         cipd_version: "refs/heads/master"
         cmd: "recipes"
       }
-      properties: "{\"$build/goma\":{\"jobs\":80,\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\"},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma\",\"recipe\":\"chromium\",\"xcode_build_version\":\"11c29\"}"
+      properties: "{\"$build/goma\":{\"jobs\":80,\"rpc_extra_params\":\"?tot\",\"server_host\":\"staging-goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma\",\"recipe\":\"chromium\",\"xcode_build_version\":\"11e146\"}"
       execution_timeout_secs: 10800
       caches {
-        name: "xcode_ios_11c29"
-        path: "xcode_ios_11c29.app"
+        name: "xcode_ios_11e146"
+        path: "xcode_ios_11e146.app"
       }
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -18192,11 +18192,11 @@
         cipd_version: "refs/heads/master"
         cmd: "recipes"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma.fyi\",\"recipe\":\"chromium\",\"xcode_build_version\":\"11c29\"}"
+      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma.fyi\",\"recipe\":\"chromium\",\"xcode_build_version\":\"11e146\"}"
       execution_timeout_secs: 36000
       caches {
-        name: "xcode_ios_11c29"
-        path: "xcode_ios_11c29.app"
+        name: "xcode_ios_11e146"
+        path: "xcode_ios_11e146.app"
       }
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -18217,11 +18217,11 @@
         cipd_version: "refs/heads/master"
         cmd: "recipes"
       }
-      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma.fyi\",\"recipe\":\"chromium\",\"xcode_build_version\":\"11c29\"}"
+      properties: "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma.fyi\",\"recipe\":\"chromium\",\"xcode_build_version\":\"11e146\"}"
       execution_timeout_secs: 36000
       caches {
-        name: "xcode_ios_11c29"
-        path: "xcode_ios_11c29.app"
+        name: "xcode_ios_11e146"
+        path: "xcode_ios_11e146.app"
       }
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -18242,11 +18242,11 @@
         cipd_version: "refs/heads/master"
         cmd: "recipes"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma.fyi\",\"recipe\":\"chromium\",\"xcode_build_version\":\"11c29\"}"
+      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma.fyi\",\"recipe\":\"chromium\",\"xcode_build_version\":\"11e146\"}"
       execution_timeout_secs: 36000
       caches {
-        name: "xcode_ios_11c29"
-        path: "xcode_ios_11c29.app"
+        name: "xcode_ios_11e146"
+        path: "xcode_ios_11e146.app"
       }
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
@@ -18267,11 +18267,11 @@
         cipd_version: "refs/heads/master"
         cmd: "recipes"
       }
-      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma.fyi\",\"recipe\":\"chromium\",\"xcode_build_version\":\"11c29\"}"
+      properties: "{\"$build/goma\":{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.goma.fyi\",\"recipe\":\"chromium\",\"xcode_build_version\":\"11e146\"}"
       execution_timeout_secs: 36000
       caches {
-        name: "xcode_ios_11c29"
-        path: "xcode_ios_11c29.app"
+        name: "xcode_ios_11e146"
+        path: "xcode_ios_11e146.app"
       }
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
diff --git a/infra/config/lib/builders.star b/infra/config/lib/builders.star
index 1fa8ae9d..c84369f4 100644
--- a/infra/config/lib/builders.star
+++ b/infra/config/lib/builders.star
@@ -162,7 +162,7 @@
   return chromium_tests or None
 
 
-def _goma_property(*, goma_backend, goma_debug, goma_enable_ats, goma_jobs, os):
+def _goma_property(*, goma_backend, goma_debug, goma_enable_ats, goma_jobs, goma_use_luci_auth, os):
   goma_properties = {}
 
   goma_backend = defaults.get_value('goma_backend', goma_backend)
@@ -187,6 +187,10 @@
   if goma_jobs != None:
     goma_properties['jobs'] = goma_jobs
 
+  goma_use_luci_auth = defaults.get_value('goma_use_luci_auth', goma_use_luci_auth)
+  if goma_use_luci_auth:
+    goma_properties['use_luci_auth'] = True
+
   return goma_properties or None
 
 
@@ -239,6 +243,7 @@
     goma_debug = False,
     goma_enable_ats = args.COMPUTE,
     goma_jobs = None,
+    goma_use_luci_auth = None,
     mastername = None,
     os = None,
     pool = None,
@@ -279,6 +284,7 @@
     goma_debug=args.DEFAULT,
     goma_enable_ats=args.DEFAULT,
     goma_jobs=args.DEFAULT,
+    goma_use_luci_auth=args.DEFAULT,
     use_clang_coverage=args.DEFAULT,
     use_java_coverage=args.DEFAULT,
     coverage_exclude_sources=args.DEFAULT,
@@ -351,6 +357,9 @@
       to be used by the builder. Sets the 'jobs' field of the '$build/goma'
       property will be set according to the enum member. By default, the 'jobs'
       considered None.
+    * goma_use_luci_auth - a boolean indicating whether luci_auth should be
+      used for accessing goma backend. If True, the 'use_luci_auth' field
+      will be set in the '$build/goma' property. By default, considered False.
     * use_clang_coverage - a boolean indicating whether clang coverage should be
       used. If True, the 'use_clang_coverage" field will be set in the
       '$build/code_coverage' property. By default, considered False.
@@ -446,6 +455,7 @@
       goma_debug = goma_debug,
       goma_enable_ats = goma_enable_ats,
       goma_jobs = goma_jobs,
+      goma_use_luci_auth = goma_use_luci_auth,
       os = os,
   )
   if goma != None:
diff --git a/infra/config/subprojects/goma/goma.star b/infra/config/subprojects/goma/goma.star
index f44522e3..3aaf83c 100644
--- a/infra/config/subprojects/goma/goma.star
+++ b/infra/config/subprojects/goma/goma.star
@@ -111,11 +111,11 @@
 
 fyi_goma_canary_builder(
     name = 'ios-device-goma-canary-clobber',
-    caches = [xcode_cache.x11c29],
+    caches = [xcode_cache.x11e146],
     cores = None,
     os = os.MAC_ANY,
     properties = {
-      'xcode_build_version': '11c29'
+      'xcode_build_version': '11e146'
     }
 )
 
@@ -187,11 +187,11 @@
 
 fyi_goma_rbe_canary_builder(
     name = 'ios-device-goma-rbe-canary-clobber',
-    caches = [xcode_cache.x11c29],
+    caches = [xcode_cache.x11e146],
     cores = None,
     os = os.MAC_ANY,
     properties = {
-      'xcode_build_version': '11c29'
+      'xcode_build_version': '11e146'
     }
 )
 
@@ -273,11 +273,11 @@
 
 fyi_goma_latest_client_builder(
     name = 'ios-device-goma-latest-clobber',
-    caches = [xcode_cache.x11c29],
+    caches = [xcode_cache.x11e146],
     cores = None,
     os = os.MAC_ANY,
     properties = {
-      'xcode_build_version': '11c29'
+      'xcode_build_version': '11e146'
     }
 )
 
@@ -363,11 +363,11 @@
 
 fyi_goma_rbe_latest_client_builder(
     name = 'ios-device-goma-rbe-latest-clobber',
-    caches = [xcode_cache.x11c29],
+    caches = [xcode_cache.x11e146],
     cores = None,
     os = os.MAC_ANY,
     properties = {
-      'xcode_build_version': '11c29'
+      'xcode_build_version': '11e146'
     }
 )
 
@@ -406,12 +406,14 @@
     name = 'Chromium Android ARM 32-bit Goma RBE ToT',
     goma_backend = goma.backend.RBE_TOT,
     goma_enable_ats = False,
+    goma_use_luci_auth = True,
 )
 
 goma_builder(
     name = 'Chromium Android ARM 32-bit Goma RBE ToT (ATS)',
     goma_backend = goma.backend.RBE_TOT,
     goma_enable_ats = True,
+    goma_use_luci_auth = True,
 )
 
 goma_builder(
@@ -442,12 +444,14 @@
     name = 'Chromium Linux Goma RBE ToT',
     goma_backend = goma.backend.RBE_TOT,
     goma_enable_ats = False,
+    goma_use_luci_auth = True,
 )
 
 goma_builder(
     name = 'Chromium Linux Goma RBE ToT (ATS)',
     goma_backend = goma.backend.RBE_TOT,
     goma_enable_ats = True,
+    goma_use_luci_auth = True,
 )
 
 
@@ -462,11 +466,12 @@
 
 goma_mac_builder(
     name = 'Chromium iOS Goma RBE ToT',
-    caches = [xcode_cache.x11c29],
+    caches = [xcode_cache.x11e146],
     goma_backend = goma.backend.RBE_TOT,
+    goma_use_luci_auth = True,
     os = os.MAC_10_14,
     properties = {
-      'xcode_build_version': "11c29",
+      'xcode_build_version': "11e146",
     }
 )
 
@@ -488,6 +493,7 @@
 goma_mac_builder(
     name = 'Chromium Mac Goma RBE ToT',
     goma_backend = goma.backend.RBE_TOT,
+    goma_use_luci_auth = True,
 )
 
 goma_mac_builder(
@@ -517,6 +523,7 @@
 goma_windows_builder(
     name = 'Chromium Win Goma RBE ToT',
     goma_backend = goma.backend.RBE_TOT,
+    goma_use_luci_auth = True,
 )
 
 goma_windows_builder(
diff --git a/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-device.json b/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-device.json
index a62ad82f..8af5c99 100644
--- a/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-device.json
+++ b/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-device.json
@@ -3,7 +3,7 @@
     "Builder for 64-bit devices.",
     "Build is performed with gn+ninja."
   ],
-  "xcode build version": "11c29",
+  "xcode build version": "11e146",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
     "ios_enable_code_signing=false",
diff --git a/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json b/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json
index c6c6849e..db2facc 100644
--- a/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json
+++ b/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json
@@ -2,7 +2,7 @@
   "comments": [
     "Runs tests on @3x, @2x, 64-bit phone, tablet, iOS 12."
   ],
-  "xcode build version": "11c29",
+  "xcode build version": "11e146",
   "gn_args": [
     "goma_dir=\"$(goma_dir)\"",
     "ios_enable_code_signing=false",
diff --git a/ios/chrome/browser/passwords/password_controller.mm b/ios/chrome/browser/passwords/password_controller.mm
index 91046e2..d7952036 100644
--- a/ios/chrome/browser/passwords/password_controller.mm
+++ b/ios/chrome/browser/passwords/password_controller.mm
@@ -14,7 +14,7 @@
 
 #include "base/bind.h"
 #include "base/mac/foundation_util.h"
-#include "base/metrics/histogram_macros.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/strings/string16.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
@@ -423,7 +423,7 @@
     _lastTypedfieldIdentifier = formQuery.uniqueFieldID;
     _lastTypedValue = formQuery.typedValue;
 
-    if ([formQuery.type isEqual:@"text"]) {
+    if ([formQuery.type isEqual:@"input"]) {
       [self.formHelper updateFieldDataOnUserInput:formQuery.uniqueFieldID
                                        inputValue:formQuery.typedValue];
     }
@@ -799,7 +799,15 @@
       delegate->set_handler(self.applicationCommandsHandler);
 
       if (IsInfobarUIRebootEnabled()) {
+        // Count only new infobar showings, not replacements.
+        if (![self findInfobarOfType:InfobarType::kInfobarTypePasswordSave
+                              manual:manual]) {
+          base::UmaHistogramBoolean("PasswordManager.iOS.InfoBar.PasswordSave",
+                                    true);
+        }
+
         std::unique_ptr<InfoBarIOS> infobar;
+
         // If manual save, skip showing banner.
         bool skip_banner = manual;
         if (IsInfobarOverlayUIEnabled()) {
@@ -827,6 +835,13 @@
     }
     case PasswordInfoBarType::UPDATE: {
       if (IsInfobarUIRebootEnabled()) {
+        // Count only new infobar showings, not replacements.
+        if (![self findInfobarOfType:InfobarType::kInfobarTypePasswordUpdate
+                              manual:manual]) {
+          base::UmaHistogramBoolean(
+              "PasswordManager.iOS.InfoBar.PasswordUpdate", true);
+        }
+
         auto delegate = std::make_unique<IOSChromeSavePasswordInfoBarDelegate>(
             isSyncUser, /*password_update*/ true, std::move(form));
         delegate->set_handler(self.applicationCommandsHandler);
diff --git a/ios/chrome/browser/passwords/password_controller_unittest.mm b/ios/chrome/browser/passwords/password_controller_unittest.mm
index adecfbc9..40f34c6 100644
--- a/ios/chrome/browser/passwords/password_controller_unittest.mm
+++ b/ios/chrome/browser/passwords/password_controller_unittest.mm
@@ -367,7 +367,7 @@
              fieldIdentifier:SysUTF8ToNSString(field_identifier)
                uniqueFieldID:uniqueFieldID
                    fieldType:@"not_important"
-                        type:@"text"
+                        type:@"input"
                   typedValue:SysUTF8ToNSString(typed_value)
                      frameID:SysUTF8ToNSString(main_frame_id)];
     [passwordController_ checkIfSuggestionsAvailableForForm:form_query
diff --git a/ios/chrome/browser/ui/download/download_manager_coordinator.mm b/ios/chrome/browser/ui/download/download_manager_coordinator.mm
index b74b4a2..fc4a276 100644
--- a/ios/chrome/browser/ui/download/download_manager_coordinator.mm
+++ b/ios/chrome/browser/ui/download/download_manager_coordinator.mm
@@ -282,7 +282,7 @@
         }
       }));
 
-  web::WebState* webState = self.downloadTask->GetWebState();
+  web::WebState* webState = download->GetWebState();
   OverlayRequestQueue::FromWebState(webState, OverlayModality::kWebContentArea)
       ->AddRequest(std::move(request));
 }
diff --git a/ios/chrome/browser/ui/download/download_manager_coordinator_unittest.mm b/ios/chrome/browser/ui/download/download_manager_coordinator_unittest.mm
index 920d2f1..a816cd9 100644
--- a/ios/chrome/browser/ui/download/download_manager_coordinator_unittest.mm
+++ b/ios/chrome/browser/ui/download/download_manager_coordinator_unittest.mm
@@ -669,6 +669,49 @@
   EXPECT_EQ(0U, queue->size());
 }
 
+// Tests downloadManagerTabHelper:decidePolicyForDownload:completionHandler:.
+// Coordinator should present the confirmation dialog.
+TEST_F(DownloadManagerCoordinatorTest,
+       DecidePolicyForDownloadFromBackgroundTab) {
+  web::FakeDownloadTask task(GURL(kTestUrl), kTestMimeType);
+  task.SetWebState(&web_state_);
+  coordinator_.downloadTask = nullptr;  // Current Tab does not have task.
+
+  OverlayRequestQueue* queue = OverlayRequestQueue::FromWebState(
+      &web_state_, OverlayModality::kWebContentArea);
+  ASSERT_EQ(0U, queue->size());
+  [coordinator_ downloadManagerTabHelper:&tab_helper_
+                 decidePolicyForDownload:&task
+                       completionHandler:^(NewDownloadPolicy){
+                       }];
+
+  // Verify that confirm request was sent.
+  ASSERT_EQ(1U, queue->size());
+
+  alert_overlays::AlertRequest* config =
+      queue->front_request()->GetConfig<alert_overlays::AlertRequest>();
+  ASSERT_TRUE(config);
+  EXPECT_NSEQ(@"Start New Download?", config->title());
+  EXPECT_NSEQ(@"This will stop all progress for your current download.",
+              config->message());
+  ASSERT_EQ(2U, config->button_configs().size());
+  EXPECT_NSEQ(@"OK", config->button_configs()[0].title);
+  EXPECT_EQ(kDownloadReplaceActionName,
+            config->button_configs()[0].user_action_name);
+  EXPECT_NSEQ(@"Cancel", config->button_configs()[1].title);
+  EXPECT_EQ(kDownloadDoNotReplaceActionName,
+            config->button_configs()[1].user_action_name);
+
+  queue->CancelAllRequests();
+  @autoreleasepool {
+    // task_environment_ has to outlive the coordinator. Dismissing coordinator
+    // retains are autoreleases it.
+    [coordinator_ stop];
+  }
+
+  EXPECT_EQ(0U, queue->size());
+}
+
 // Tests starting the download. Verifies that download task is started and its
 // file writer is configured to write into download directory.
 TEST_F(DownloadManagerCoordinatorTest, StartDownload) {
diff --git a/ios/chrome/browser/ui/settings/password/BUILD.gn b/ios/chrome/browser/ui/settings/password/BUILD.gn
index ec93263..af4b44f0 100644
--- a/ios/chrome/browser/ui/settings/password/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/password/BUILD.gn
@@ -40,6 +40,7 @@
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/passwords",
     "//ios/chrome/browser/signin",
+    "//ios/chrome/browser/sync",
     "//ios/chrome/browser/ui:feature_flags",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
@@ -47,11 +48,14 @@
     "//ios/chrome/browser/ui/settings/cells",
     "//ios/chrome/browser/ui/settings/cells:public",
     "//ios/chrome/browser/ui/settings/elements:enterprise_info_popover_view_controller",
+    "//ios/chrome/browser/ui/settings/password/password_details",
     "//ios/chrome/browser/ui/settings/utils",
     "//ios/chrome/browser/ui/table_view",
     "//ios/chrome/browser/ui/table_view/cells:cells_constants",
     "//ios/chrome/browser/ui/util",
+    "//ios/chrome/common",
     "//ios/chrome/common/ui/colors",
+    "//ios/chrome/common/ui/elements:popover_label_view_controller",
     "//ios/chrome/common/ui/reauthentication",
     "//ios/chrome/common/ui/util",
     "//ios/third_party/material_components_ios",
@@ -75,6 +79,7 @@
   ]
   deps = [
     "//base",
+    "//components/autofill/core/common",
     "//components/password_manager/core/browser",
     "//components/password_manager/core/common",
     "//components/prefs",
@@ -83,6 +88,7 @@
     "//ios/chrome/app/strings:ios_strings_grit",
     "//ios/chrome/browser",
     "//ios/chrome/browser/ui/settings:settings_root",
+    "//ios/chrome/browser/ui/settings/autofill",
     "//ios/chrome/browser/ui/table_view/cells",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/common/ui/util",
diff --git a/ios/chrome/browser/ui/settings/password/password_details/BUILD.gn b/ios/chrome/browser/ui/settings/password/password_details/BUILD.gn
new file mode 100644
index 0000000..4719b99
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_details/BUILD.gn
@@ -0,0 +1,59 @@
+# Copyright 2020 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.
+
+source_set("password_details") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  sources = [
+    "password_details_coordinator.h",
+    "password_details_coordinator.mm",
+    "password_details_coordinator_delegate.h",
+    "password_details_mediator.h",
+    "password_details_mediator.mm",
+  ]
+  deps = [
+    ":password_details_ui",
+    "//base",
+    "//components/autofill/core/common",
+    "//components/strings",
+    "//components/url_formatter",
+    "//ios/chrome/app/strings",
+    "//ios/chrome/browser",
+    "//ios/chrome/browser/passwords",
+    "//ios/chrome/browser/ui:feature_flags",
+    "//ios/chrome/browser/ui/commands",
+    "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
+    "//ios/chrome/browser/ui/table_view",
+    "//ios/chrome/common/ui/colors",
+    "//ios/chrome/common/ui/util",
+    "//ui/base",
+  ]
+}
+
+source_set("password_details_ui") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  sources = [
+    "password_details.h",
+    "password_details.mm",
+    "password_details_consumer.h",
+    "password_details_handler.h",
+    "password_details_table_view_constants.h",
+    "password_details_table_view_constants.mm",
+    "password_details_view_controller.h",
+    "password_details_view_controller.mm",
+    "password_details_view_controller_delegate.h",
+  ]
+  deps = [
+    "//base",
+    "//components/autofill/core/common",
+    "//components/password_manager/core/browser:browser",
+    "//components/strings",
+    "//ios/chrome/browser",
+    "//ios/chrome/browser/ui/settings:settings_root",
+    "//ios/chrome/browser/ui/settings/autofill",
+    "//ios/chrome/browser/ui/table_view/cells",
+    "//ios/chrome/browser/ui/util",
+    "//ios/chrome/common/ui/util",
+    "//ui/base",
+  ]
+}
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details.h b/ios/chrome/browser/ui/settings/password/password_details/password_details.h
new file mode 100644
index 0000000..092f213
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details.h
@@ -0,0 +1,37 @@
+// Copyright 2020 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_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_H_
+#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_H_
+
+#import <Foundation/Foundation.h>
+
+namespace autofill {
+struct PasswordForm;
+}
+
+// Object which is used by |PasswordDetailsViewController| to show
+// information about password.
+@interface PasswordDetails : NSObject
+
+// Short version of website.
+@property(nonatomic, strong, readonly) NSString* origin;
+
+// Associated website.
+@property(nonatomic, strong, readonly) NSString* website;
+
+// Associated username.
+@property(nonatomic, strong, readonly) NSString* username;
+
+// Associated password.
+@property(nonatomic, strong) NSString* password;
+
+- (instancetype)initWithPasswordForm:(const autofill::PasswordForm&)form
+    NS_DESIGNATED_INITIALIZER;
+
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details.mm
new file mode 100644
index 0000000..3e6855e
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details.mm
@@ -0,0 +1,29 @@
+// Copyright 2020 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/settings/password/password_details/password_details.h"
+
+#include "base/strings/sys_string_conversions.h"
+#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_ui_utils.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@implementation PasswordDetails
+
+- (instancetype)initWithPasswordForm:(const autofill::PasswordForm&)form {
+  self = [super init];
+  if (self) {
+    auto nameWithLink = password_manager::GetShownOriginAndLinkUrl(form);
+    _origin = base::SysUTF8ToNSString(nameWithLink.first);
+    _website = base::SysUTF8ToNSString(nameWithLink.second.spec());
+    _username = base::SysUTF16ToNSString(form.username_value);
+    _password = base::SysUTF16ToNSString(form.password_value);
+  }
+  return self;
+}
+
+@end
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_consumer.h b/ios/chrome/browser/ui/settings/password/password_details/password_details_consumer.h
new file mode 100644
index 0000000..9486313
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_consumer.h
@@ -0,0 +1,20 @@
+// Copyright 2020 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_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_CONSUMER_H_
+#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_CONSUMER_H_
+
+#import <Foundation/Foundation.h>
+
+@class PasswordDetails;
+
+// Sets the Password details for consumer.
+@protocol PasswordDetailsConsumer <NSObject>
+
+// Displays provided password details.
+- (void)setPassword:(PasswordDetails*)password;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_CONSUMER_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.h b/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.h
new file mode 100644
index 0000000..ab51f26
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.h
@@ -0,0 +1,33 @@
+// Copyright 2020 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_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_COORDINATOR_H_
+#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_COORDINATOR_H_
+
+#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
+
+@protocol PasswordDetailsCoordinatorDelegate;
+
+namespace autofill {
+struct PasswordForm;
+}
+
+// This coordinator presents a password details for the user.
+@interface PasswordDetailsCoordinator : ChromeCoordinator
+
+- (instancetype)initWithBaseNavigationController:
+                    (UINavigationController*)navigationController
+                                        password:(const autofill::PasswordForm&)
+                                                     password
+    NS_DESIGNATED_INITIALIZER;
+
+- (instancetype)initWithBaseViewController:(UIViewController*)viewController
+                                   browser:(Browser*)browser NS_UNAVAILABLE;
+
+// Delegate.
+@property(nonatomic, weak) id<PasswordDetailsCoordinatorDelegate> delegate;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.mm
new file mode 100644
index 0000000..517b6ee
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.mm
@@ -0,0 +1,76 @@
+// Copyright 2020 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/settings/password/password_details/password_details_coordinator.h"
+
+#include "base/mac/foundation_util.h"
+#include "components/autofill/core/common/password_form.h"
+#import "ios/chrome/browser/ui/settings/password/password_details/password_details_consumer.h"
+#import "ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator_delegate.h"
+#import "ios/chrome/browser/ui/settings/password/password_details/password_details_handler.h"
+#import "ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.h"
+#import "ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller.h"
+#include "ios/chrome/browser/ui/ui_feature_flags.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@interface PasswordDetailsCoordinator () <PasswordDetailsHandler> {
+  autofill::PasswordForm _password;
+}
+
+// Main view controller for this coordinator.
+@property(nonatomic, strong) PasswordDetailsViewController* viewController;
+
+// Main mediator for this coordinator.
+@property(nonatomic, strong) PasswordDetailsMediator* mediator;
+
+@end
+
+@implementation PasswordDetailsCoordinator
+
+@synthesize baseNavigationController = _baseNavigationController;
+
+- (instancetype)initWithBaseNavigationController:
+                    (UINavigationController*)navigationController
+                                        password:(const autofill::PasswordForm&)
+                                                     password {
+  self = [super initWithBaseViewController:navigationController browser:nil];
+  if (self) {
+    _password = password;
+    _baseNavigationController = navigationController;
+  }
+  return self;
+}
+
+- (void)start {
+  UITableViewStyle style = base::FeatureList::IsEnabled(kSettingsRefresh)
+                               ? UITableViewStylePlain
+                               : UITableViewStyleGrouped;
+
+  self.viewController =
+      [[PasswordDetailsViewController alloc] initWithStyle:style];
+
+  self.mediator = [[PasswordDetailsMediator alloc] initWithPassword:_password];
+  self.mediator.consumer = self.viewController;
+  self.viewController.handler = self;
+
+  [self.baseNavigationController pushViewController:self.viewController
+                                           animated:YES];
+}
+
+- (void)stop {
+  self.mediator = nil;
+  self.viewController = nil;
+}
+
+#pragma mark - PasswordDetailsHandler
+
+- (void)passwordDetailsViewControllerDidDisappear {
+  [self.delegate passwordDetailsCoordinatorDidRemove:self];
+}
+
+@end
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator_delegate.h b/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator_delegate.h
new file mode 100644
index 0000000..56e1c44a
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator_delegate.h
@@ -0,0 +1,28 @@
+// Copyright 2020 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_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_COORDINATOR_DELEGATE_H_
+#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_COORDINATOR_DELEGATE_H_
+
+@class PasswordDetailsCoordinator;
+
+namespace autofill {
+struct PasswordForm;
+}
+
+// Delegate for PasswordIssuesCoordinator.
+@protocol PasswordDetailsCoordinatorDelegate
+
+// Called when the view controller was removed from navigation controller.
+- (void)passwordDetailsCoordinatorDidRemove:
+    (PasswordDetailsCoordinator*)coordinator;
+
+// Called when user deleted password. This action should be handled
+// outside to update the list of passwords immediately.
+- (void)passwordDetailsCoordinator:(PasswordDetailsCoordinator*)coordinator
+                    deletePassword:(const autofill::PasswordForm&)password;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_COORDINATOR_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_handler.h b/ios/chrome/browser/ui/settings/password/password_details/password_details_handler.h
new file mode 100644
index 0000000..619395a
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_handler.h
@@ -0,0 +1,16 @@
+// Copyright 2020 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_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_HANDLER_H_
+#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_HANDLER_H_
+
+// Presenter which handles commands from |PasswordDetailsViewController|.
+@protocol PasswordDetailsHandler
+
+// Called when the view controller was dismissed.
+- (void)passwordDetailsViewControllerDidDisappear;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_HANDLER_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.h b/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.h
new file mode 100644
index 0000000..7419f17
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.h
@@ -0,0 +1,30 @@
+// Copyright 2020 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_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_MEDIATOR_H_
+#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_MEDIATOR_H_
+
+#import <Foundation/Foundation.h>
+
+@protocol PasswordDetailsConsumer;
+
+namespace autofill {
+struct PasswordForm;
+}
+
+// This mediator fetches and organises the credentials for its consumer.
+@interface PasswordDetailsMediator : NSObject
+
+// PasswordForm is converted to the PasswordDetails and passed to a consumer.
+- (instancetype)initWithPassword:(const autofill::PasswordForm&)passwordForm
+    NS_DESIGNATED_INITIALIZER;
+
+- (instancetype)init NS_UNAVAILABLE;
+
+// Consumer of this mediator.
+@property(nonatomic, weak) id<PasswordDetailsConsumer> consumer;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.mm
new file mode 100644
index 0000000..4af31a37
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_mediator.mm
@@ -0,0 +1,54 @@
+// Copyright 2020 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/settings/password/password_details/password_details_mediator.h"
+
+#include "components/autofill/core/common/password_form.h"
+#import "ios/chrome/browser/ui/settings/password/password_details/password_details.h"
+#import "ios/chrome/browser/ui/settings/password/password_details/password_details_consumer.h"
+#import "ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_delegate.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace autofill {
+struct PasswordForm;
+}
+
+@interface PasswordDetailsMediator () <PasswordDetailsViewControllerDelegate> {
+  autofill::PasswordForm _password;
+}
+
+@end
+
+@implementation PasswordDetailsMediator
+
+- (instancetype)initWithPassword:(const autofill::PasswordForm&)passwordForm {
+  self = [super init];
+  if (self) {
+    _password = passwordForm;
+  }
+  return self;
+}
+
+- (void)setConsumer:(id<PasswordDetailsConsumer>)consumer {
+  if (_consumer == consumer)
+    return;
+  _consumer = consumer;
+
+  PasswordDetails* password =
+      [[PasswordDetails alloc] initWithPasswordForm:_password];
+
+  [self.consumer setPassword:password];
+}
+
+#pragma mark - PasswordDetailsViewControllerDelegate
+- (void)passwordDetailsViewController:
+            (PasswordDetailsViewController*)viewController
+               didEditPasswordDetails:(PasswordDetails*)password {
+  // TODO:(crbug.com/1075494) - Edit password accordingly.
+}
+
+@end
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_constants.h b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_constants.h
new file mode 100644
index 0000000..ac54ac66
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_constants.h
@@ -0,0 +1,13 @@
+// Copyright 2020 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_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_TABLE_VIEW_CONSTANTS_H_
+#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_TABLE_VIEW_CONSTANTS_H_
+
+#import <Foundation/Foundation.h>
+
+// The accessibility identifier of the password details table view.
+extern NSString* const kPasswordDetailsViewControllerId;
+
+#endif  // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_TABLE_VIEW_CONSTANTS_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_constants.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_constants.mm
new file mode 100644
index 0000000..c74c413
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_constants.mm
@@ -0,0 +1,12 @@
+// Copyright 2020 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/settings/password/password_details/password_details_table_view_constants.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+NSString* const kPasswordDetailsViewControllerId =
+    @"kPasswordDetailsViewControllerId";
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller.h b/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller.h
new file mode 100644
index 0000000..ebbab60
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller.h
@@ -0,0 +1,26 @@
+// Copyright 2020 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_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_VIEW_CONTROLLER_H_
+#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_VIEW_CONTROLLER_H_
+
+#import "ios/chrome/browser/ui/settings/autofill/autofill_edit_table_view_controller.h"
+#import "ios/chrome/browser/ui/settings/password/password_details/password_details_consumer.h"
+
+@protocol PasswordDetailsHandler;
+@protocol PasswordDetailsViewControllerDelegate;
+
+// Screen which shows password details and allows to edit it.
+@interface PasswordDetailsViewController
+    : AutofillEditTableViewController <PasswordDetailsConsumer>
+
+// Handler for PasswordDetails related actions.
+@property(nonatomic, weak) id<PasswordDetailsHandler> handler;
+
+// Delegate for PasswordDetails related actions e.g. Password editing.
+@property(nonatomic, weak) id<PasswordDetailsViewControllerDelegate> delegate;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller.mm
new file mode 100644
index 0000000..464d031
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller.mm
@@ -0,0 +1,48 @@
+// Copyright 2020 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/settings/password/password_details/password_details_view_controller.h"
+
+#include "base/mac/foundation_util.h"
+#import "ios/chrome/browser/ui/settings/password/password_details/password_details.h"
+#import "ios/chrome/browser/ui/settings/password/password_details/password_details_consumer.h"
+#import "ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_constants.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+@interface PasswordDetailsViewController ()
+
+// Password which is shown on the screen.
+@property(nonatomic, strong) PasswordDetails* password;
+
+@end
+
+@implementation PasswordDetailsViewController
+
+#pragma mark - UIViewController
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+  self.tableView.accessibilityIdentifier = kPasswordDetailsViewControllerId;
+  self.tableView.allowsSelectionDuringEditing = YES;
+
+  [self loadModel];
+}
+
+#pragma mark - ChromeTableViewController
+
+- (void)loadModel {
+  [super loadModel];
+}
+
+#pragma mark - PasswordDetailsConsumer
+
+- (void)setPassword:(PasswordDetails*)password {
+  _password = password;
+  [self reloadData];
+}
+
+@end
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_delegate.h b/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_delegate.h
new file mode 100644
index 0000000..85e8a17
--- /dev/null
+++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_view_controller_delegate.h
@@ -0,0 +1,20 @@
+// Copyright 2020 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_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_VIEW_CONTROLLER_DELEGATE_H_
+#define IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_VIEW_CONTROLLER_DELEGATE_H_
+
+@class PasswordDetails;
+@class PasswordDetailsViewController;
+
+@protocol PasswordDetailsViewControllerDelegate
+
+// Called when user finished editing a password.
+- (void)passwordDetailsViewController:
+            (PasswordDetailsViewController*)viewController
+               didEditPasswordDetails:(PasswordDetails*)password;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_VIEW_CONTROLLER_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_issues_coordinator.mm b/ios/chrome/browser/ui/settings/password/password_issues_coordinator.mm
index e05a4b6..c2b33f4 100644
--- a/ios/chrome/browser/ui/settings/password/password_issues_coordinator.mm
+++ b/ios/chrome/browser/ui/settings/password/password_issues_coordinator.mm
@@ -5,6 +5,8 @@
 #import "ios/chrome/browser/ui/settings/password/password_issues_coordinator.h"
 
 #include "base/mac/foundation_util.h"
+#import "ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.h"
+#import "ios/chrome/browser/ui/settings/password/password_issue_with_form.h"
 #import "ios/chrome/browser/ui/settings/password/password_issues_consumer.h"
 #import "ios/chrome/browser/ui/settings/password/password_issues_mediator.h"
 #import "ios/chrome/browser/ui/settings/password/password_issues_presenter.h"
@@ -78,7 +80,15 @@
 }
 
 - (void)presentPasswordIssueDetails:(id<PasswordIssue>)password {
-  // TODO(crbug.com/1075494) - Show Password details page
+  autofill::PasswordForm form =
+      base::mac::ObjCCastStrict<PasswordIssueWithForm>(password).form;
+
+  PasswordDetailsCoordinator* passwordDetails =
+      [[PasswordDetailsCoordinator alloc]
+          initWithBaseNavigationController:self.baseNavigationController
+                                  password:form];
+  // TODO:(crbug.com/1075494) - Add self as delegate for coordinator.
+  [passwordDetails start];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/settings/password/passwords_consumer.h b/ios/chrome/browser/ui/settings/password/passwords_consumer.h
index a5d83ab..4435559 100644
--- a/ios/chrome/browser/ui/settings/password/passwords_consumer.h
+++ b/ios/chrome/browser/ui/settings/password/passwords_consumer.h
@@ -19,6 +19,8 @@
   PasswordCheckStateRunning,
   // When user has no passwords and check can't be performed.
   PasswordCheckStateDisabled,
+  // When password check failed due to network issues, quota limit or others.
+  PasswordCheckStateError,
 };
 
 // Consumer for the Passwords Screen.
diff --git a/ios/chrome/browser/ui/settings/password/passwords_mediator.h b/ios/chrome/browser/ui/settings/password/passwords_mediator.h
index b7d21c6..46f2c34 100644
--- a/ios/chrome/browser/ui/settings/password/passwords_mediator.h
+++ b/ios/chrome/browser/ui/settings/password/passwords_mediator.h
@@ -9,8 +9,10 @@
 
 #include "base/memory/scoped_refptr.h"
 
+class AuthenticationService;
 class IOSChromePasswordCheckManager;
 @protocol PasswordsConsumer;
+class SyncSetupService;
 
 namespace password_manager {
 class PasswordStore;
@@ -19,16 +21,22 @@
 // This mediator fetches and organises the passwords for its consumer.
 @interface PasswordsMediator : NSObject
 
-- (instancetype)initWithPasswordStore:
-                    (scoped_refptr<password_manager::PasswordStore>)
-                        passwordStore
-                 passwordCheckManager:(IOSChromePasswordCheckManager*)manager
+- (instancetype)
+    initWithPasswordStore:
+        (scoped_refptr<password_manager::PasswordStore>)passwordStore
+     passwordCheckManager:
+         (scoped_refptr<IOSChromePasswordCheckManager>)passwordCheckManager
+              authService:(AuthenticationService*)authService
+              syncService:(SyncSetupService*)syncService
     NS_DESIGNATED_INITIALIZER;
 
 - (instancetype)init NS_UNAVAILABLE;
 
 @property(nonatomic, weak) id<PasswordsConsumer> consumer;
 
+// Returns detailed information about error if applicable.
+- (NSAttributedString*)passwordCheckErrorInfo;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORDS_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/settings/password/passwords_mediator.mm b/ios/chrome/browser/ui/settings/password/passwords_mediator.mm
index 80b3861..d9e9a04 100644
--- a/ios/chrome/browser/ui/settings/password/passwords_mediator.mm
+++ b/ios/chrome/browser/ui/settings/password/passwords_mediator.mm
@@ -4,13 +4,24 @@
 
 #import "ios/chrome/browser/ui/settings/password/passwords_mediator.h"
 
+#include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
 #include "components/password_manager/core/browser/password_store.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "ios/chrome/browser/passwords/password_check_observer_bridge.h"
 #include "ios/chrome/browser/passwords/password_store_observer_bridge.h"
 #import "ios/chrome/browser/passwords/save_passwords_consumer.h"
+#import "ios/chrome/browser/signin/authentication_service.h"
+#include "ios/chrome/browser/sync/sync_setup_service.h"
 #import "ios/chrome/browser/ui/settings/password/passwords_consumer.h"
+#import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h"
 #include "ios/chrome/browser/ui/ui_feature_flags.h"
+#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
+#import "ios/chrome/common/string_util.h"
+#import "ios/chrome/common/ui/colors/semantic_color_names.h"
+#include "ios/chrome/grit/ios_chromium_strings.h"
+#import "net/base/mac/url_conversions.h"
+#include "ui/base/l10n/l10n_util_mac.h"
+#include "url/gurl.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -20,11 +31,17 @@
                                  PasswordStoreObserver,
                                  SavePasswordsConsumerDelegate> {
   // The service responsible for password check feature.
-  IOSChromePasswordCheckManager* _manager;
+  scoped_refptr<IOSChromePasswordCheckManager> _passwordCheckManager;
 
   // The interface for getting and manipulating a user's saved passwords.
   scoped_refptr<password_manager::PasswordStore> _passwordStore;
 
+  // Service used to check if user is signed in.
+  AuthenticationService* _authService;
+
+  // Service to check if passwords are synced.
+  SyncSetupService* _syncService;
+
   // A helper object for passing data about changes in password check status
   // and changes to compromised credentials list.
   std::unique_ptr<PasswordCheckObserverBridge> _passwordCheckObserver;
@@ -44,21 +61,26 @@
 
 @implementation PasswordsMediator
 
-- (instancetype)initWithPasswordStore:
-                    (scoped_refptr<password_manager::PasswordStore>)
-                        passwordStore
-                 passwordCheckManager:(IOSChromePasswordCheckManager*)manager {
+- (instancetype)
+    initWithPasswordStore:
+        (scoped_refptr<password_manager::PasswordStore>)passwordStore
+     passwordCheckManager:
+         (scoped_refptr<IOSChromePasswordCheckManager>)passwordCheckManager
+              authService:(AuthenticationService*)authService
+              syncService:(SyncSetupService*)syncService {
   self = [super init];
   if (self) {
-    _manager = manager;
     _passwordStore = passwordStore;
+    _authService = authService;
+    _syncService = syncService;
     _savedPasswordsConsumer =
         std::make_unique<ios::SavePasswordsConsumer>(self);
 
     if (base::FeatureList::IsEnabled(
             password_manager::features::kPasswordCheck)) {
-      _passwordCheckObserver =
-          std::make_unique<PasswordCheckObserverBridge>(self, manager);
+      _passwordCheckManager = passwordCheckManager;
+      _passwordCheckObserver = std::make_unique<PasswordCheckObserverBridge>(
+          self, _passwordCheckManager.get());
       _passwordStoreObserver =
           std::make_unique<PasswordStoreObserverBridge>(self);
       _passwordStore->AddObserver(_passwordStoreObserver.get());
@@ -78,8 +100,50 @@
     return;
   _consumer = consumer;
   [self loginsDidChange];
-  [self.consumer setPasswordCheckUIState:
-                     [self computePasswordCheckUIStateWithChangedState:NO]];
+
+  if (base::FeatureList::IsEnabled(
+          password_manager::features::kPasswordCheck)) {
+    _currentState = _passwordCheckManager->GetPasswordCheckState();
+    [self.consumer setPasswordCheckUIState:
+                       [self computePasswordCheckUIStateWith:_currentState]];
+  }
+}
+
+- (NSAttributedString*)passwordCheckErrorInfo {
+  if (!_passwordCheckManager->GetCompromisedCredentials().empty())
+    return nil;
+
+  NSString* message;
+  GURL linkURL;
+
+  switch (_currentState) {
+    case PasswordCheckState::kRunning:
+    case PasswordCheckState::kNoPasswords:
+    case PasswordCheckState::kCanceled:
+    case PasswordCheckState::kIdle:
+      return nil;
+    case PasswordCheckState::kSignedOut:
+      message = l10n_util::GetNSString(IDS_IOS_PASSWORD_CHECK_ERROR_SIGNED_OUT);
+      break;
+    case PasswordCheckState::kOffline:
+      message = l10n_util::GetNSString(IDS_IOS_PASSWORD_CHECK_ERROR_OFFLINE);
+      break;
+    case PasswordCheckState::kQuotaLimit:
+      if ([self canUseAccountPasswordCheckup]) {
+        message = l10n_util::GetNSString(
+            IDS_IOS_PASSWORD_CHECK_ERROR_QUOTA_LIMIT_VISIT_GOOGLE);
+        linkURL = password_manager::GetPasswordCheckupURL(
+            password_manager::PasswordCheckupReferrer::kPasswordCheck);
+      } else {
+        message =
+            l10n_util::GetNSString(IDS_IOS_PASSWORD_CHECK_ERROR_QUOTA_LIMIT);
+      }
+      break;
+    case PasswordCheckState::kOther:
+      message = l10n_util::GetNSString(IDS_IOS_PASSWORD_CHECK_ERROR_OTHER);
+      break;
+  }
+  return [self configureTextWithLink:message link:linkURL];
 }
 
 #pragma mark - PasswordCheckObserver
@@ -88,10 +152,9 @@
   if (state == _currentState)
     return;
 
-  _currentState = state;
   DCHECK(self.consumer);
-  [self.consumer setPasswordCheckUIState:
-                     [self computePasswordCheckUIStateWithChangedState:YES]];
+  [self.consumer
+      setPasswordCheckUIState:[self computePasswordCheckUIStateWith:state]];
 }
 
 - (void)compromisedCredentialsDidChange:
@@ -99,40 +162,80 @@
         credentials {
   DCHECK(self.consumer);
   [self.consumer setPasswordCheckUIState:
-                     [self computePasswordCheckUIStateWithChangedState:NO]];
+                     [self computePasswordCheckUIStateWith:_currentState]];
 }
 
 #pragma mark - Private Methods
 
 // Returns PasswordCheckUIState based on PasswordCheckState.
-// Parameter indicates whether function called when |_currentState| changed as
-// safe status is only possible if state changed from kRunning to kIdle.
-- (PasswordCheckUIState)computePasswordCheckUIStateWithChangedState:
-    (BOOL)stateChanged {
+- (PasswordCheckUIState)computePasswordCheckUIStateWith:
+    (PasswordCheckState)newState {
+  BOOL wasRunning = _currentState == PasswordCheckState::kRunning;
+  _currentState = newState;
+
   switch (_currentState) {
-    case PasswordCheckState::kRunning: {
+    case PasswordCheckState::kRunning:
       return PasswordCheckStateRunning;
-    }
-    case PasswordCheckState::kNoPasswords: {
+    case PasswordCheckState::kNoPasswords:
       return PasswordCheckStateDisabled;
-    }
-    case PasswordCheckState::kIdle:
     case PasswordCheckState::kSignedOut:
     case PasswordCheckState::kOffline:
     case PasswordCheckState::kQuotaLimit:
+    case PasswordCheckState::kOther:
+      return _passwordCheckManager->GetCompromisedCredentials().empty()
+                 ? PasswordCheckStateError
+                 : PasswordCheckStateUnSafe;
     case PasswordCheckState::kCanceled:
-    case PasswordCheckState::kOther: {
-      if (!_manager->GetCompromisedCredentials().empty()) {
+    case PasswordCheckState::kIdle: {
+      if (!_passwordCheckManager->GetCompromisedCredentials().empty()) {
         return PasswordCheckStateUnSafe;
       } else if (_currentState == PasswordCheckState::kIdle) {
-        return stateChanged ? PasswordCheckStateSafe
-                            : PasswordCheckStateDefault;
+        // Safe state is only possible after the state transitioned from
+        // kRunning to kIdle.
+        return wasRunning ? PasswordCheckStateSafe : PasswordCheckStateDefault;
       }
       return PasswordCheckStateDefault;
     }
   }
 }
 
+// Compute whether user is capable to run password check in Google Account.
+- (BOOL)canUseAccountPasswordCheckup {
+  return (_authService->IsAuthenticated() &&
+          _authService->GetAuthenticatedIdentity()) &&
+         (_syncService->IsSyncEnabled() &&
+          !_syncService->IsEncryptEverythingEnabled());
+}
+
+// Configures text for Error Info Popover.
+- (NSAttributedString*)configureTextWithLink:(NSString*)text link:(GURL)link {
+  NSRange range;
+
+  NSString* strippedText = ParseStringWithLink(text, &range);
+
+  NSRange fullRange = NSMakeRange(0, strippedText.length);
+  NSMutableAttributedString* attributedText =
+      [[NSMutableAttributedString alloc] initWithString:strippedText];
+  [attributedText addAttribute:NSForegroundColorAttributeName
+                         value:[UIColor colorNamed:kTextSecondaryColor]
+                         range:fullRange];
+
+  [attributedText
+      addAttribute:NSFontAttributeName
+             value:[UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]
+             range:fullRange];
+
+  if (range.location != NSNotFound && range.length != 0) {
+    NSURL* URL = net::NSURLWithGURL(link);
+    id linkValue = URL ? URL : @"";
+    [attributedText addAttribute:NSLinkAttributeName
+                           value:linkValue
+                           range:range];
+  }
+
+  return attributedText;
+}
+
 #pragma mark - PasswordStoreObserver
 
 - (void)loginsDidChange {
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm
index 51262114..9510a1b 100644
--- a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm
@@ -39,6 +39,7 @@
 #import "ios/chrome/browser/signin/authentication_service.h"
 #include "ios/chrome/browser/signin/authentication_service_factory.h"
 #import "ios/chrome/browser/signin/chrome_identity_service_observer_bridge.h"
+#include "ios/chrome/browser/sync/sync_setup_service_factory.h"
 #include "ios/chrome/browser/system_flags.h"
 #import "ios/chrome/browser/ui/settings/cells/settings_cells_constants.h"
 #import "ios/chrome/browser/ui/settings/cells/settings_check_cell.h"
@@ -68,9 +69,12 @@
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
 #import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h"
 #import "ios/chrome/common/ui/colors/semantic_color_names.h"
+#import "ios/chrome/common/ui/elements/popover_label_view_controller.h"
 #import "ios/chrome/common/ui/reauthentication/reauthentication_module.h"
 #import "ios/chrome/common/ui/util/constraints_ui_util.h"
+#include "ios/chrome/grit/ios_chromium_strings.h"
 #include "ios/chrome/grit/ios_strings.h"
+#import "net/base/mac/url_conversions.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 #include "url/gurl.h"
 
@@ -175,6 +179,7 @@
     PasswordExportActivityViewControllerDelegate,
     PasswordsConsumer,
     PasswordIssuesCoordinatorDelegate,
+    PopoverLabelViewControllerDelegate,
     UISearchControllerDelegate,
     UISearchBarDelegate,
     SuccessfulReauthTimeAccessor> {
@@ -268,9 +273,13 @@
     DCHECK(_passwordStore);
     _passwordCheck =
         IOSChromePasswordCheckManagerFactory::GetForBrowserState(_browserState);
-    _mediator =
-        [[PasswordsMediator alloc] initWithPasswordStore:_passwordStore
-                                    passwordCheckManager:_passwordCheck.get()];
+    _mediator = [[PasswordsMediator alloc]
+        initWithPasswordStore:_passwordStore
+         passwordCheckManager:_passwordCheck
+                  authService:AuthenticationServiceFactory::GetForBrowserState(
+                                  _browserState)
+                  syncService:SyncSetupServiceFactory::GetForBrowserState(
+                                  _browserState)];
     _mediator.consumer = self;
     _passwordManagerEnabled = [[PrefBackedBoolean alloc]
         initWithPrefService:_browserState->GetPrefs()
@@ -576,6 +585,13 @@
   return passwordItem;
 }
 
+#pragma mark - PopoverLabelViewControllerDelegate
+
+- (void)didTapLinkURL:(NSURL*)URL {
+  GURL convertedURL = net::GURLWithNSURL(URL);
+  [self view:nil didTapLinkURL:convertedURL];
+}
+
 #pragma mark - BooleanObserver
 
 - (void)booleanDidChange:(id<ObservableBoolean>)observableBoolean {
@@ -629,6 +645,28 @@
       UIPopoverArrowDirectionAny;
 }
 
+// Called when user tapped on the information button of the password check
+// item. Shows popover with detailed description of an error.
+- (void)didTapPasswordCheckInfoButton:(UIButton*)buttonView {
+  NSAttributedString* info = [_mediator passwordCheckErrorInfo];
+  // If no info returned by mediator handle this tap as tap on a cell.
+  if (!info) {
+    [self showPasswordIssuesPage];
+    return;
+  }
+
+  PopoverLabelViewController* errorInfoPopover =
+      [[PopoverLabelViewController alloc] initWithPrimaryAttributedString:info
+                                                secondaryAttributedString:nil];
+  errorInfoPopover.delegate = self;
+
+  errorInfoPopover.popoverPresentationController.sourceView = buttonView;
+  errorInfoPopover.popoverPresentationController.sourceRect = buttonView.bounds;
+  errorInfoPopover.popoverPresentationController.permittedArrowDirections =
+      UIPopoverArrowDirectionAny;
+  [self presentViewController:errorInfoPopover animated:YES completion:nil];
+}
+
 #pragma mark - PasswordsConsumer
 
 - (void)setPasswordCheckUIState:(PasswordCheckUIState)state {
@@ -884,6 +922,7 @@
     case PasswordCheckStateSafe:
     case PasswordCheckStateUnSafe:
     case PasswordCheckStateDefault:
+    case PasswordCheckStateError:
       _checkForProblemsItem.textColor = [UIColor colorNamed:kBlueColor];
       _checkForProblemsItem.accessibilityTraits &=
           ~UIAccessibilityTraitNotEnabled;
@@ -916,6 +955,7 @@
   _passwordProblemsItem.trailingImage = nil;
   _passwordProblemsItem.enabled = YES;
   _passwordProblemsItem.indicatorHidden = YES;
+  _passwordProblemsItem.infoButtonHidden = YES;
   _passwordProblemsItem.accessoryType = UITableViewCellAccessoryNone;
   _passwordProblemsItem.detailText =
       l10n_util::GetNSString(IDS_IOS_CHECK_PASSWORDS_DESCRIPTION);
@@ -952,7 +992,12 @@
           [UIColor colorNamed:kGreenColor];
       break;
     }
-    case PasswordCheckStateDefault: {
+    case PasswordCheckStateDefault:
+      break;
+    case PasswordCheckStateError: {
+      _passwordProblemsItem.detailText =
+          l10n_util::GetNSString(IDS_IOS_PASSWORD_CHECK_ERROR);
+      _passwordProblemsItem.infoButtonHidden = NO;
       break;
     }
   }
@@ -1276,6 +1321,15 @@
           forControlEvents:UIControlEventTouchUpInside];
       break;
     }
+    case ItemTypePasswordCheckStatus: {
+      SettingsCheckCell* passwordCheckCell =
+          base::mac::ObjCCastStrict<SettingsCheckCell>(cell);
+      [passwordCheckCell.infoButton
+                 addTarget:self
+                    action:@selector(didTapPasswordCheckInfoButton:)
+          forControlEvents:UIControlEventTouchUpInside];
+      break;
+    }
   }
   return cell;
 }
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm
index 9bbba3af..3b67139 100644
--- a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm
@@ -31,6 +31,7 @@
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
 #import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h"
 #import "ios/chrome/common/ui/colors/semantic_color_names.h"
+#include "ios/chrome/grit/ios_chromium_strings.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "ios/web/public/test/web_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -590,6 +591,26 @@
   EXPECT_FALSE(checkPassword.trailingImage);
 }
 
+// Test verifies error state of password check cell.
+TEST_P(PasswordsTableViewControllerTest, PasswordCheckStateError) {
+  if (!GetParam().password_check_enabled)
+    return;
+
+  ChangePasswordCheckState(PasswordCheckStateError);
+
+  CheckTextCellTextWithId(IDS_IOS_CHECK_PASSWORDS_NOW_BUTTON,
+                          GetSectionIndex(PasswordCheck), 1);
+  CheckDetailItemTextWithIds(IDS_IOS_CHECK_PASSWORDS,
+                             IDS_IOS_PASSWORD_CHECK_ERROR,
+                             GetSectionIndex(PasswordCheck), 0);
+  SettingsCheckItem* checkPassword =
+      GetTableViewItem(GetSectionIndex(PasswordCheck), 0);
+  EXPECT_TRUE(checkPassword.enabled);
+  EXPECT_TRUE(checkPassword.indicatorHidden);
+  EXPECT_FALSE(checkPassword.trailingImage);
+  EXPECT_FALSE(checkPassword.infoButtonHidden);
+}
+
 // Test verifies tapping start with no saved passwords has no effect.
 TEST_P(PasswordsTableViewControllerTest, DisabledPasswordCheck) {
   if (!GetParam().password_check_enabled)
diff --git a/ios/chrome/browser/web/BUILD.gn b/ios/chrome/browser/web/BUILD.gn
index 38d520b..144ba5ac 100644
--- a/ios/chrome/browser/web/BUILD.gn
+++ b/ios/chrome/browser/web/BUILD.gn
@@ -347,6 +347,14 @@
   ]
 }
 
+source_set("constants") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  sources = [
+    "lookalike_url_constants.h",
+    "lookalike_url_constants.mm",
+  ]
+}
+
 source_set("eg_test_support+eg2") {
   defines = [ "CHROME_EARL_GREY_2" ]
   configs += [
@@ -355,7 +363,10 @@
   ]
   testonly = true
 
-  sources = [ "progress_indicator_app_interface.h" ]
+  sources = [
+    "lookalike_url_app_interface.h",
+    "progress_indicator_app_interface.h",
+  ]
 
   deps = [
     "//ios/chrome/test/earl_grey:eg_test_support+eg2",
@@ -372,15 +383,23 @@
   defines = [ "CHROME_EARL_GREY_2" ]
 
   sources = [
+    "lookalike_url_app_interface.h",
+    "lookalike_url_app_interface.mm",
     "progress_indicator_app_interface.h",
     "progress_indicator_app_interface.mm",
   ]
 
   deps = [
+    ":constants",
     "//base",
+    "//components/lookalikes/core",
+    "//ios/chrome/test/app:test_support",
+    "//ios/components/security_interstitials/lookalikes",
     "//ios/testing/earl_grey:eg_app_support+eg2",
     "//ios/third_party/earl_grey2:app_framework+link",
     "//ios/third_party/material_components_ios",
+    "//ios/web/public",
+    "//net",
   ]
 }
 
@@ -402,6 +421,7 @@
     "forms_egtest.mm",
     "http_auth_egtest.mm",
     "js_print_egtest.mm",
+    "lookalike_url_egtest.mm",
     "navigation_egtest.mm",
     "progress_indicator_egtest.mm",
     "push_and_replace_state_navigation_egtest.mm",
@@ -414,6 +434,7 @@
   ]
 
   deps = [
+    ":constants",
     ":eg_test_support+eg2",
     "//components/content_settings/core/common",
     "//components/strings",
diff --git a/ios/chrome/browser/web/lookalike_url_app_interface.h b/ios/chrome/browser/web/lookalike_url_app_interface.h
new file mode 100644
index 0000000..a4f864c
--- /dev/null
+++ b/ios/chrome/browser/web/lookalike_url_app_interface.h
@@ -0,0 +1,28 @@
+// Copyright 2020 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_WEB_LOOKALIKE_URL_APP_INTERFACE_H_
+#define IOS_CHROME_BROWSER_WEB_LOOKALIKE_URL_APP_INTERFACE_H_
+
+#import <Foundation/Foundation.h>
+
+// The app interface for lookalike URL blocking page tests. It sets
+// up LookalikeUrlDecider, which does the following:
+//   - Lets a navigation proceed if the domain is explicitly allowed
+//   - Cancels the navigation and shows error page with a suggested URL
+//      for the /lookalike.html path
+//   - Cancels the navigation and shows error page with no suggested URL
+//      for the /lookalike-empty.html path
+//   - Allows other navigations to proceed
+@interface LookalikeUrlAppInterface : NSObject
+
+// Sets up lookalike policy decider. Used for testing.
++ (void)setUpLookalikeUrlDeciderForWebState;
+
+// Tear down lookalike policy decider. Used for testing.
++ (void)tearDownLookalikeUrlDeciderForWebState;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_WEB_LOOKALIKE_URL_APP_INTERFACE_H_
diff --git a/ios/chrome/browser/web/lookalike_url_app_interface.mm b/ios/chrome/browser/web/lookalike_url_app_interface.mm
new file mode 100644
index 0000000..b2ec43e
--- /dev/null
+++ b/ios/chrome/browser/web/lookalike_url_app_interface.mm
@@ -0,0 +1,90 @@
+// Copyright 2020 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/web/lookalike_url_app_interface.h"
+
+#include "components/lookalikes/core/lookalike_url_util.h"
+#import "ios/chrome/browser/web/lookalike_url_constants.h"
+#import "ios/chrome/test/app/chrome_test_util.h"
+#import "ios/chrome/test/app/tab_test_util.h"
+#include "ios/components/security_interstitials/lookalikes/lookalike_url_container.h"
+#include "ios/components/security_interstitials/lookalikes/lookalike_url_error.h"
+#include "ios/components/security_interstitials/lookalikes/lookalike_url_tab_allow_list.h"
+#import "ios/web/public/navigation/web_state_policy_decider.h"
+#import "ios/web/public/web_state_user_data.h"
+#import "net/base/mac/url_conversions.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+
+// This decider determines whether a URL is a lookalike. If so, it cancels
+// navigation and shows an error.
+class LookalikeUrlDecider : public web::WebStatePolicyDecider,
+                            public web::WebStateUserData<LookalikeUrlDecider> {
+ public:
+  LookalikeUrlDecider(web::WebState* web_state)
+      : web::WebStatePolicyDecider(web_state), web_state_(web_state) {}
+
+  void ShouldAllowResponse(
+      NSURLResponse* response,
+      bool for_main_frame,
+      web::WebStatePolicyDecider::PolicyDecisionCallback callback) override {
+    LookalikeUrlContainer* lookalike_container =
+        LookalikeUrlContainer::FromWebState(web_state_);
+    LookalikeUrlTabAllowList* allow_list =
+        LookalikeUrlTabAllowList::FromWebState(web_state_);
+
+    GURL response_url = net::GURLWithNSURL(response.URL);
+    if (allow_list->IsDomainAllowed(response_url.host())) {
+      return std::move(callback).Run(
+          web::WebStatePolicyDecider::PolicyDecision::Allow());
+    }
+    if (response_url.path() == kLookalikePagePathForTesting) {
+      GURL::Replacements safeReplacements;
+      safeReplacements.SetPathStr("echo");
+      lookalike_container->SetLookalikeUrlInfo(
+          response_url.ReplaceComponents(safeReplacements), response_url,
+          LookalikeUrlMatchType::kSkeletonMatchTop5k);
+      std::move(callback).Run(CreateLookalikeErrorDecision());
+      return;
+    }
+    if (response_url.path() == kLookalikePageEmptyUrlPathForTesting) {
+      lookalike_container->SetLookalikeUrlInfo(
+          GURL::EmptyGURL(), response_url,
+          LookalikeUrlMatchType::kSkeletonMatchTop5k);
+      std::move(callback).Run(CreateLookalikeErrorDecision());
+      return;
+    }
+    return std::move(callback).Run(
+        web::WebStatePolicyDecider::PolicyDecision::Allow());
+  }
+
+  WEB_STATE_USER_DATA_KEY_DECL();
+
+ private:
+  web::WebState* web_state_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(LookalikeUrlDecider);
+};
+
+WEB_STATE_USER_DATA_KEY_IMPL(LookalikeUrlDecider)
+
+}  // namespace
+
+@implementation LookalikeUrlAppInterface
+
++ (void)setUpLookalikeUrlDeciderForWebState {
+  LookalikeUrlDecider::CreateForWebState(
+      chrome_test_util::GetCurrentWebState());
+}
+
++ (void)tearDownLookalikeUrlDeciderForWebState {
+  LookalikeUrlDecider::RemoveFromWebState(
+      chrome_test_util::GetCurrentWebState());
+}
+
+@end
diff --git a/ios/chrome/browser/web/lookalike_url_constants.h b/ios/chrome/browser/web/lookalike_url_constants.h
new file mode 100644
index 0000000..c8b88d4
--- /dev/null
+++ b/ios/chrome/browser/web/lookalike_url_constants.h
@@ -0,0 +1,14 @@
+// Copyright 2020 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_WEB_LOOKALIKE_URL_CONSTANTS_H_
+#define IOS_CHROME_BROWSER_WEB_LOOKALIKE_URL_CONSTANTS_H_
+
+// Constant used for testing a lookalike URL interstitial.
+extern const char kLookalikePagePathForTesting[];
+
+// Constant used for testing a lookalike URL interstitial with no suggested URL.
+extern const char kLookalikePageEmptyUrlPathForTesting[];
+
+#endif  // IOS_CHROME_BROWSER_WEB_LOOKALIKE_URL_CONSTANTS_H_
diff --git a/ios/chrome/browser/web/lookalike_url_constants.mm b/ios/chrome/browser/web/lookalike_url_constants.mm
new file mode 100644
index 0000000..eec1f20d
--- /dev/null
+++ b/ios/chrome/browser/web/lookalike_url_constants.mm
@@ -0,0 +1,12 @@
+// Copyright 2020 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/web/lookalike_url_constants.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+const char kLookalikePagePathForTesting[] = "/lookalike.html";
+const char kLookalikePageEmptyUrlPathForTesting[] = "/lookalike-empty.html";
diff --git a/ios/chrome/browser/web/lookalike_url_egtest.mm b/ios/chrome/browser/web/lookalike_url_egtest.mm
new file mode 100644
index 0000000..ef0147cc
--- /dev/null
+++ b/ios/chrome/browser/web/lookalike_url_egtest.mm
@@ -0,0 +1,300 @@
+// Copyright 2020 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 <string>
+
+#include "base/bind.h"
+#include "base/strings/stringprintf.h"
+#include "components/strings/grit/components_strings.h"
+#import "ios/chrome/browser/web/lookalike_url_app_interface.h"
+#import "ios/chrome/browser/web/lookalike_url_constants.h"
+#import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
+#import "ios/chrome/test/earl_grey/chrome_matchers.h"
+#import "ios/chrome/test/earl_grey/chrome_test_case.h"
+#import "ios/testing/earl_grey/earl_grey_test.h"
+#include "ios/testing/embedded_test_server_handlers.h"
+#include "ios/web/common/features.h"
+#include "ios/web/public/test/element_selector.h"
+#include "net/test/embedded_test_server/default_handlers.h"
+#include "net/test/embedded_test_server/http_request.h"
+#include "net/test/embedded_test_server/http_response.h"
+#include "net/test/embedded_test_server/request_handler_util.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+#if defined(CHROME_EARL_GREY_2)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++98-compat-extra-semi"
+GREY_STUB_CLASS_IN_APP_MAIN_QUEUE(LookalikeUrlAppInterface);
+#pragma clang diagnostic pop
+#endif  // defined(CHROME_EARL_GREY_2)
+
+using chrome_test_util::BackButton;
+using chrome_test_util::ForwardButton;
+
+namespace {
+// Relative paths used for a page that opens a lookalike in a new tab.
+const char kLookalikeInNewTab[] = "/lookalike-newtab.html";
+
+// Text that is found on the lookalike page.
+const char kLookalikeContent[] = "Lookalike - Safety warning bypassed";
+// Text that is found on a page that opens a lookalike in a new tab.
+const char kLookalikeInNewTabContent[] = "New tab";
+}  // namespace
+
+// Tests lookalike URL blocking.
+@interface LookalikeUrlTestCase : ChromeTestCase {
+  // A URL that is treated as a lookalike.
+  GURL _lookalikeURL;
+  // A URL that is treated as a safe page.
+  GURL _safeURL;
+  // Text that is found on the safe page.
+  std::string _safeContent;
+  // Text that is found on the lookalike interstitial.
+  std::string _lookalikeBlockingPageContent;
+}
+@end
+
+@implementation LookalikeUrlTestCase
+
+- (AppLaunchConfiguration)appConfigurationForTestCase {
+  AppLaunchConfiguration config;
+  config.features_enabled.push_back(
+      web::features::kIOSLookalikeUrlNavigationSuggestionsUI);
+  config.features_enabled.push_back(web::features::kSSLCommittedInterstitials);
+  config.relaunch_policy = NoForceRelaunchAndResetState;
+  return config;
+}
+
+- (void)setUp {
+  [super setUp];
+  [LookalikeUrlAppInterface setUpLookalikeUrlDeciderForWebState];
+  std::string lookalikeHTML =
+      base::StringPrintf("<html><body>%s</body></html>", kLookalikeContent);
+  self.testServer->RegisterRequestHandler(base::BindRepeating(
+      &net::test_server::HandlePrefixedRequest, kLookalikePagePathForTesting,
+      base::BindRepeating(&testing::HandlePageWithHtml, lookalikeHTML)));
+  self.testServer->RegisterRequestHandler(base::BindRepeating(
+      &net::test_server::HandlePrefixedRequest,
+      kLookalikePageEmptyUrlPathForTesting,
+      base::BindRepeating(&testing::HandlePageWithHtml, lookalikeHTML)));
+  std::string lookalikeNewTabHTML = base::StringPrintf(
+      "<html><body><a target=\"_blank\" href=\"%s\" "
+      "id=\"lookalike-newtab\">%s</a></body></html>",
+      kLookalikePageEmptyUrlPathForTesting, kLookalikeInNewTabContent);
+  self.testServer->RegisterRequestHandler(base::BindRepeating(
+      &net::test_server::HandlePrefixedRequest, kLookalikeInNewTab,
+      base::BindRepeating(&testing::HandlePageWithHtml, lookalikeNewTabHTML)));
+  GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
+  _safeURL = self.testServer->GetURL("/echo");
+  _safeContent = "Echo";
+  _lookalikeURL = self.testServer->GetURL(kLookalikePagePathForTesting);
+  _lookalikeBlockingPageContent =
+      l10n_util::GetStringUTF8(IDS_LOOKALIKE_URL_PRIMARY_PARAGRAPH);
+}
+
+- (void)tearDown {
+  [LookalikeUrlAppInterface tearDownLookalikeUrlDeciderForWebState];
+  [super tearDown];
+}
+
+// Tests that non-lookalike URLs are not blocked.
+- (void)testSafePage {
+  [ChromeEarlGrey loadURL:_safeURL];
+  [ChromeEarlGrey waitForWebStateContainingText:_safeContent];
+}
+
+// Tests that a lookalike URL navigation is blocked, and the Go to suggested
+// site button works. Also tests that navigating back to the site shows the
+// interstitial and that navigating forward again works.
+- (void)testLookalikeUrlPage {
+  // Load the lookalike page and verify a warning is shown.
+  [ChromeEarlGrey loadURL:_lookalikeURL];
+  [ChromeEarlGrey waitForWebStateContainingText:_lookalikeBlockingPageContent];
+
+  // Tap on the "Go to" button and verify that the suggested page
+  // contents are loaded.
+  [ChromeEarlGrey tapWebStateElementWithID:@"primary-button"];
+  [ChromeEarlGrey waitForWebStateContainingText:_safeContent];
+
+  // Verify that the warning is shown when navigating back and that safe
+  // content is shown when navigating forward again.
+  [[EarlGrey selectElementWithMatcher:BackButton()] performAction:grey_tap()];
+  [ChromeEarlGrey waitForWebStateContainingText:_lookalikeBlockingPageContent];
+  [[EarlGrey selectElementWithMatcher:ForwardButton()]
+      performAction:grey_tap()];
+  [ChromeEarlGrey waitForWebStateContainingText:_safeContent];
+}
+
+// Tests that a lookalike URL navigation is blocked, and the text link for
+// suggested site works. Also tests that navigating back to the site shows
+// the interstitial and that navigating forward again works.
+- (void)testLookalikeUrlPageSiteLink {
+  // Load the lookalike page and verify a warning is shown.
+  [ChromeEarlGrey loadURL:_lookalikeURL];
+  [ChromeEarlGrey waitForWebStateContainingText:_lookalikeBlockingPageContent];
+
+  // Tap on the site suggestion link and verify that the suggested page
+  // contents are loaded.
+  [ChromeEarlGrey tapWebStateElementWithID:@"dont-proceed-link"];
+  [ChromeEarlGrey waitForWebStateContainingText:_safeContent];
+
+  // Verify that the warning is shown when navigating back and that safe
+  // content is shown when navigating forward again.
+  [[EarlGrey selectElementWithMatcher:BackButton()] performAction:grey_tap()];
+  [ChromeEarlGrey waitForWebStateContainingText:_lookalikeBlockingPageContent];
+  [[EarlGrey selectElementWithMatcher:ForwardButton()]
+      performAction:grey_tap()];
+  [ChromeEarlGrey waitForWebStateContainingText:_safeContent];
+}
+
+// Tests that Back to safety works when there is no suggested URL. Also tests
+// that navigating forward to the site shows the interstitial and that
+// navigating back again works.
+- (void)testLookalikeUrlPageNoSuggestion {
+  // Navigate to safe page first to enable later verification of
+  // back/forward navigation.
+  [ChromeEarlGrey loadURL:_safeURL];
+  [ChromeEarlGrey waitForWebStateContainingText:_safeContent];
+
+  // Navigate to a lookalike page with no suggestion and verify that a warning
+  // and the correct button is shown.
+  [ChromeEarlGrey
+      loadURL:self.testServer->GetURL(kLookalikePageEmptyUrlPathForTesting)];
+  [ChromeEarlGrey waitForWebStateContainingText:_lookalikeBlockingPageContent];
+  [ChromeEarlGrey
+      waitForWebStateContainingText:l10n_util::GetStringUTF8(
+                                        IDS_LOOKALIKE_URL_BACK_TO_SAFETY)];
+
+  // Tap on the "Back to safety" button and verify that the safe content
+  // is loaded.
+  [ChromeEarlGrey tapWebStateElementWithID:@"primary-button"];
+  [ChromeEarlGrey waitForWebStateContainingText:_safeContent];
+
+  // Verify that the warning is shown when navigating forward and that safe
+  // content is shown when navigating back again.
+  [[EarlGrey selectElementWithMatcher:ForwardButton()]
+      performAction:grey_tap()];
+  [ChromeEarlGrey waitForWebStateContainingText:_lookalikeBlockingPageContent];
+  [[EarlGrey selectElementWithMatcher:BackButton()] performAction:grey_tap()];
+  [ChromeEarlGrey waitForWebStateContainingText:_safeContent];
+}
+
+// Tests that Close page works when there is no suggested URL and unable
+// to go back.
+- (void)testLookalikeUrlPageNoSuggestionClosePage {
+  // First navigate to a page that will open the lookalike URL in a new tab,
+  // then open the lookalike page.
+  [ChromeEarlGrey loadURL:self.testServer->GetURL(kLookalikeInNewTab)];
+  [ChromeEarlGrey tapWebStateElementWithID:@"lookalike-newtab"];
+
+  // Verify that the new tab has loaded before setting up the policy decider
+  // for the new web state. Then reload to make sure the interstitial is
+  // displayed.
+  [ChromeEarlGrey waitForWebStateContainingText:kLookalikeContent];
+  [LookalikeUrlAppInterface setUpLookalikeUrlDeciderForWebState];
+  [ChromeEarlGrey reload];
+
+  // Verify that a warning and the correct button is shown.
+  [ChromeEarlGrey waitForWebStateContainingText:_lookalikeBlockingPageContent];
+  [ChromeEarlGrey
+      waitForWebStateContainingText:l10n_util::GetStringUTF8(
+                                        IDS_LOOKALIKE_URL_CLOSE_PAGE)];
+
+  // Tap on the "Close" button and verify that the page closes.
+  [ChromeEarlGrey tapWebStateElementWithID:@"primary-button"];
+  [ChromeEarlGrey waitForWebStateContainingText:kLookalikeInNewTabContent];
+}
+
+// Tests proceeding past the lookalike warning and that opening the page in
+// a new tab will bypass the warning.
+- (void)testProceedingPastLookalikeUrlWarning {
+  // Load the lookalike page and verify a warning is shown.
+  [ChromeEarlGrey loadURL:_lookalikeURL];
+  [ChromeEarlGrey waitForWebStateContainingText:_lookalikeBlockingPageContent];
+
+  // Tap on the link to ignore the warning, and verify that the page is loaded.
+  [ChromeEarlGrey tapWebStateElementWithID:@"proceed-button"];
+  [ChromeEarlGrey waitForWebStateContainingText:kLookalikeContent];
+
+  // In a new tab, the warning should not be shown.
+  [ChromeEarlGrey openNewTab];
+  [ChromeEarlGrey loadURL:_lookalikeURL];
+  [ChromeEarlGrey waitForWebStateContainingText:kLookalikeContent];
+}
+
+// Tests displaying a warning for an lookalike URL, proceeding past the warning,
+// and navigating back/forward, in incognito.
+- (void)testProceedingPastLookalikeWarningInIncognito {
+  [ChromeEarlGrey openNewIncognitoTab];
+  [LookalikeUrlAppInterface setUpLookalikeUrlDeciderForWebState];
+
+  // Navigate to safe page first to enable later verification of
+  // back/forward navigation.
+  [ChromeEarlGrey loadURL:_safeURL];
+  [ChromeEarlGrey waitForWebStateContainingText:_safeContent];
+
+  // Load the lookalike page and verify a warning is shown.
+  [ChromeEarlGrey loadURL:_lookalikeURL];
+  [ChromeEarlGrey waitForWebStateContainingText:_lookalikeBlockingPageContent];
+
+  // Tap on the link to ignore the warning, and verify that the page is loaded.
+  [ChromeEarlGrey tapWebStateElementWithID:@"proceed-button"];
+  [ChromeEarlGrey waitForWebStateContainingText:kLookalikeContent];
+
+  // Verify that no warning is shown when navigating back and then forward to
+  // the unsafe page.
+  [[EarlGrey selectElementWithMatcher:BackButton()] performAction:grey_tap()];
+  [ChromeEarlGrey waitForWebStateContainingText:_safeContent];
+  [[EarlGrey selectElementWithMatcher:ForwardButton()]
+      performAction:grey_tap()];
+  [ChromeEarlGrey waitForWebStateContainingText:kLookalikeContent];
+}
+
+// Tests that performing session restoration to a lookalike URL warning page
+// preserves navigation history.
+- (void)testRestoreToWarningPagePreservesHistory {
+  // Build up navigation history that consists of a safe URL, a warning page,
+  // and the suggested safe URL.
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/echoall")];
+  std::string safeContent2 = "Request Body";
+  [ChromeEarlGrey waitForWebStateContainingText:safeContent2];
+
+  // Load the lookalike URL page and verify a warning is shown.
+  [ChromeEarlGrey loadURL:_lookalikeURL];
+  [ChromeEarlGrey waitForWebStateContainingText:_lookalikeBlockingPageContent];
+
+  // Tap on the "Go to" button and verify that the suggested page contents
+  // are loaded.
+  [ChromeEarlGrey tapWebStateElementWithID:@"primary-button"];
+  [ChromeEarlGrey waitForWebStateContainingText:_safeContent];
+
+  // Navigate back to the interstitial. Now both the back list and the forward
+  // list are non-empty.
+  [ChromeEarlGrey goBack];
+  [ChromeEarlGrey waitForWebStateContainingText:_lookalikeBlockingPageContent];
+
+  // Do a session restoration and verify that all navigation history is
+  // preserved. For this test, the policy decider doesn't get installed for
+  // the first page load, so expect the page content instead of the warning.
+  [ChromeEarlGrey triggerRestoreViaTabGridRemoveAllUndo];
+  [ChromeEarlGrey waitForWebStateContainingText:kLookalikeContent];
+  [LookalikeUrlAppInterface setUpLookalikeUrlDeciderForWebState];
+
+  [ChromeEarlGrey goBack];
+  [ChromeEarlGrey waitForWebStateContainingText:safeContent2];
+
+  // The policy decider will trigger at this point, so the warning should
+  // be shown.
+  [ChromeEarlGrey goForward];
+  [ChromeEarlGrey waitForWebStateContainingText:_lookalikeBlockingPageContent];
+
+  [ChromeEarlGrey goForward];
+  [ChromeEarlGrey waitForWebStateContainingText:_safeContent];
+}
+
+@end
diff --git a/ios/components/security_interstitials/lookalikes/lookalike_url_controller_client.mm b/ios/components/security_interstitials/lookalikes/lookalike_url_controller_client.mm
index a11b3eb..769ff52a 100644
--- a/ios/components/security_interstitials/lookalikes/lookalike_url_controller_client.mm
+++ b/ios/components/security_interstitials/lookalikes/lookalike_url_controller_client.mm
@@ -46,9 +46,10 @@
   if (!safe_url_.is_valid()) {
     IOSBlockingPageControllerClient::GoBack();
   } else {
-    // TODO(crbug.com/1058898): Replace the last committed navigation
-    // (the interstitial) with the safe URL navigation to prevent the
-    // back button from returning to the bad site.
+    // For simplicity and because replacement doesn't always work, the
+    // navigation to the safe URL does not replace the navigation to
+    // the interstitial. However, this is acceptable since if a user
+    // navigates back to the lookalike, the interstitial will be shown.
     OpenUrlInCurrentTab(safe_url_);
   }
 }
diff --git a/ios/components/security_interstitials/lookalikes/lookalike_url_error.h b/ios/components/security_interstitials/lookalikes/lookalike_url_error.h
index 5183cf70..e8606a0f 100644
--- a/ios/components/security_interstitials/lookalikes/lookalike_url_error.h
+++ b/ios/components/security_interstitials/lookalikes/lookalike_url_error.h
@@ -7,10 +7,16 @@
 
 #import <Foundation/Foundation.h>
 
+#import "ios/web/public/navigation/web_state_policy_decider.h"
+
 // The error domain for lookalike URL errors.
 extern const NSErrorDomain kLookalikeUrlErrorDomain;
 
 // Error code for navigations to lookalike URLs.
 extern const NSInteger kLookalikeUrlErrorCode;
 
+// Creates a PolicyDecision that cancels a navigation to show a lookalike
+// error.
+web::WebStatePolicyDecider::PolicyDecision CreateLookalikeErrorDecision();
+
 #endif  // IOS_COMPONENTS_SECURITY_INTERSTITIALS_LOOKALIKES_LOOKALIKE_URL_ERROR_H_
diff --git a/ios/components/security_interstitials/lookalikes/lookalike_url_error.mm b/ios/components/security_interstitials/lookalikes/lookalike_url_error.mm
index fffae48..00e19439 100644
--- a/ios/components/security_interstitials/lookalikes/lookalike_url_error.mm
+++ b/ios/components/security_interstitials/lookalikes/lookalike_url_error.mm
@@ -11,3 +11,10 @@
 const NSErrorDomain kLookalikeUrlErrorDomain =
     @"com.google.chrome.lookalike_url";
 const NSInteger kLookalikeUrlErrorCode = -1003;
+
+web::WebStatePolicyDecider::PolicyDecision CreateLookalikeErrorDecision() {
+  return web::WebStatePolicyDecider::PolicyDecision::CancelAndDisplayError(
+      [NSError errorWithDomain:kLookalikeUrlErrorDomain
+                          code:kLookalikeUrlErrorCode
+                      userInfo:nil]);
+}
diff --git a/ios/components/security_interstitials/lookalikes/lookalike_url_tab_helper.mm b/ios/components/security_interstitials/lookalikes/lookalike_url_tab_helper.mm
index 555ed74e..371c01e 100644
--- a/ios/components/security_interstitials/lookalikes/lookalike_url_tab_helper.mm
+++ b/ios/components/security_interstitials/lookalikes/lookalike_url_tab_helper.mm
@@ -19,15 +19,6 @@
 #endif
 
 namespace {
-// Creates a PolicyDecision that cancels a navigation to show a lookalike
-// error.
-web::WebStatePolicyDecider::PolicyDecision CreateLookalikeErrorDecision() {
-  return web::WebStatePolicyDecider::PolicyDecision::CancelAndDisplayError(
-      [NSError errorWithDomain:kLookalikeUrlErrorDomain
-                          code:kLookalikeUrlErrorCode
-                      userInfo:nil]);
-}
-
 // Creates a PolicyDecision that allows the navigation.
 web::WebStatePolicyDecider::PolicyDecision CreateAllowDecision() {
   return web::WebStatePolicyDecider::PolicyDecision::Allow();
@@ -50,7 +41,7 @@
     return;
   }
 
-  // TODO(crbug.com/1058898): Create container and ReleaseInterstitialParams.
+  // TODO(crbug.com/1104386): Create container and ReleaseInterstitialParams.
   // Get stored interstitial parameters early. Doing so ensures that a
   // navigation to an irrelevant (for this interstitial's purposes) URL such as
   // chrome://settings while the lookalike interstitial is being shown clears
@@ -78,7 +69,7 @@
     return;
   }
 
-  // TODO(crbug.com/1058898): If this is a reload and if the current
+  // TODO(crbug.com/1104386): If this is a reload and if the current
   // URL is the last URL of the stored redirect chain, the interstitial
   // was probably reloaded. Stop the reload and navigate back to the
   // original lookalike URL so that the full checks are exercised again.
@@ -91,7 +82,7 @@
     return;
   }
 
-  // TODO(crbug.com/1058898): After site engagement has been componentized,
+  // TODO(crbug.com/1104384): After site engagement has been componentized,
   // fetch and set |engaged_sites| here so that an interstitial won't be
   // shown on engaged sites, and so that the interstitial will be shown on
   // lookalikes of engaged sites.
diff --git a/ios/web/web_state/js/resources/all_frames_context_menu.js b/ios/web/web_state/js/resources/all_frames_context_menu.js
index 27b78bb44..ae5c39f 100644
--- a/ios/web/web_state/js/resources/all_frames_context_menu.js
+++ b/ios/web/web_state/js/resources/all_frames_context_menu.js
@@ -247,20 +247,7 @@
 
   if (currentElement.tagName.toLowerCase() === 'iframe' ||
       currentElement.tagName.toLowerCase() === 'frame') {
-    // Check if the frame is in a different domain using only information
-    // visible to the current frame (i.e. currentElement.src) to avoid
-    // triggering a SecurityError in the console.
-    if (!__gCrWeb.common.isSameOrigin(
-        window.location.href, currentElement.src)) {
-      return currentElement;
-    }
-    var framePosition = getPositionInWindow(currentElement);
-    coordinates.viewPortX -= framePosition.x - coordinates.window.pageXOffset;
-    coordinates.viewPortY -= framePosition.y - coordinates.window.pageYOffset;
-    coordinates.window = currentElement.contentWindow;
-    coordinates.x -= framePosition.x + coordinates.window.pageXOffset;
-    coordinates.y -= framePosition.y + coordinates.window.pageYOffset;
-    return elementsFromCoordinates(coordinates.window.document, coordinates);
+    return currentElement;
   }
 
   if (currentElement.shadowRoot) {
@@ -366,9 +353,10 @@
   var payload = message.data;
   if (payload.hasOwnProperty('type') &&
       payload.type == 'org.chromium.contextMenuMessage') {
-    __gCrWeb.findElementAtPointInPageCoordinates(payload.requestId,
-                                                 payload.x,
-                                                 payload.y);
+    __gCrWeb.findElementAtPointInPageCoordinates(
+        payload.requestId,
+        payload.x + window.pageXOffset,
+        payload.y + window.pageYOffset);
   }
 });
 
diff --git a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
index c88392e..25af94a4 100644
--- a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
@@ -689,8 +689,11 @@
     value_name_cppname = (value, parameter_name, cpp_parameter_name)
     # TODO(crbug.com/1103623): Support more involved types.
     if mojom.IsEnumKind(kind):
-      # TODO(crbug.com/1103623): Pretty-print enums.
-      yield '%s->SetInteger("%s", static_cast<int>(%s));' % value_name_cppname
+      if self._IsTypemappedKind(kind) or IsNativeOnlyKind(kind):
+        yield '%s->SetInteger("%s", static_cast<int>(%s));' % value_name_cppname
+      else:
+        yield '%s->SetString("%s", base::trace_event::'\
+            'TracedValue::ValueToString(%s));' % value_name_cppname
       return
     if mojom.IsStringKind(kind):
       if self.for_blink:
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index a1828087..3a65c23 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -521,7 +521,6 @@
       {
         "args": [
           "--enable-features=BackForwardCache,BackForwardCacheNoTimeEviction,ServiceWorkerOnUI,ProactivelySwapBrowsingInstance",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.android_browsertests.filter",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -676,7 +675,6 @@
       {
         "args": [
           "--enable-features=BackForwardCache,BackForwardCacheNoTimeEviction,ServiceWorkerOnUI,ProactivelySwapBrowsingInstance",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.content_shell_test_apk.filter",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
diff --git a/testing/buildbot/chromium.ci.json b/testing/buildbot/chromium.ci.json
index 93402f2a..d7a114e 100644
--- a/testing/buildbot/chromium.ci.json
+++ b/testing/buildbot/chromium.ci.json
@@ -166345,7 +166345,6 @@
       {
         "args": [
           "--enable-features=BackForwardCache,BackForwardCacheNoTimeEviction,ServiceWorkerOnUI,ProactivelySwapBrowsingInstance",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.android_browsertests.filter",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -166500,7 +166499,6 @@
       {
         "args": [
           "--enable-features=BackForwardCache,BackForwardCacheNoTimeEviction,ServiceWorkerOnUI,ProactivelySwapBrowsingInstance",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.content_shell_test_apk.filter",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn
index a3900d8..c6ca12b 100644
--- a/testing/buildbot/filters/BUILD.gn
+++ b/testing/buildbot/filters/BUILD.gn
@@ -16,12 +16,6 @@
 # $ for i in $(ls -1 testing/buildbot/filters/*.browser_tests.*filter ); \
 #   do echo "    \"//$i\","; done | sort
 
-source_set("android_browsertests_filters") {
-  testonly = true
-
-  data = [ "//testing/buildbot/filters/bfcache.android_browsertests.filter" ]
-}
-
 source_set("cc_unittests_filters") {
   testonly = true
 
@@ -111,10 +105,7 @@
 source_set("content_shell_test_apk_filters") {
   testonly = true
 
-  data = [
-    "//testing/buildbot/filters/bfcache.content_shell_test_apk.filter",
-    "//testing/buildbot/filters/android.emulator_m.content_shell_test_apk.filter",
-  ]
+  data = [ "//testing/buildbot/filters/android.emulator_m.content_shell_test_apk.filter" ]
 }
 
 source_set("content_unittests_filters") {
diff --git a/testing/buildbot/filters/bfcache.android_browsertests.filter b/testing/buildbot/filters/bfcache.android_browsertests.filter
deleted file mode 100644
index 2d8f82a..0000000
--- a/testing/buildbot/filters/bfcache.android_browsertests.filter
+++ /dev/null
@@ -1 +0,0 @@
-# These tests currently fail when run with --enable-features=BackForwardCache
diff --git a/testing/buildbot/filters/bfcache.content_shell_test_apk.filter b/testing/buildbot/filters/bfcache.content_shell_test_apk.filter
deleted file mode 100644
index 2d8f82a..0000000
--- a/testing/buildbot/filters/bfcache.content_shell_test_apk.filter
+++ /dev/null
@@ -1 +0,0 @@
-# These tests currently fail when run with --enable-features=BackForwardCache
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index ae642cdd..62ed4a3 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -294,7 +294,6 @@
       'bf_cache_android_browsertests': {
         'args': [
           '--enable-features=BackForwardCache,BackForwardCacheNoTimeEviction,ServiceWorkerOnUI,ProactivelySwapBrowsingInstance',
-          '--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.android_browsertests.filter'
         ],
         'test': 'android_browsertests',
       },
@@ -315,7 +314,6 @@
       'bf_cache_content_shell_test_apk': {
         'args': [
           '--enable-features=BackForwardCache,BackForwardCacheNoTimeEviction,ServiceWorkerOnUI,ProactivelySwapBrowsingInstance',
-          '--test-launcher-filter-file=../../testing/buildbot/filters/bfcache.content_shell_test_apk.filter'
         ],
         'swarming': {
           'shards': 5,
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 745d31c..76f7b2a 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -5328,6 +5328,21 @@
             ]
         }
     ],
+    "PrivacyElevatedAndroid": [
+        {
+            "platforms": [
+                "android"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "PrivacyElevatedAndroid"
+                    ]
+                }
+            ]
+        }
+    ],
     "ProactivelySwapBrowsingInstance": [
         {
             "platforms": [
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn
index 7bfdbb57..23bb354 100644
--- a/third_party/blink/public/mojom/BUILD.gn
+++ b/third_party/blink/public/mojom/BUILD.gn
@@ -81,6 +81,7 @@
     "loader/navigation_predictor.mojom",
     "loader/pause_subresource_loading_handle.mojom",
     "loader/previews_resource_loading_hints.mojom",
+    "loader/referrer.mojom",
     "loader/request_context_frame_type.mojom",
     "loader/resource_load_info.mojom",
     "loader/resource_load_info_notifier.mojom",
@@ -123,7 +124,6 @@
     "push_messaging/push_messaging_status.mojom",
     "quota/quota_manager_host.mojom",
     "quota/quota_types.mojom",
-    "referrer.mojom",
     "renderer_preference_watcher.mojom",
     "renderer_preferences.mojom",
     "reporting/reporting.mojom",
diff --git a/third_party/blink/public/mojom/fetch/fetch_api_request.mojom b/third_party/blink/public/mojom/fetch/fetch_api_request.mojom
index 175bbf6..f1431686 100644
--- a/third_party/blink/public/mojom/fetch/fetch_api_request.mojom
+++ b/third_party/blink/public/mojom/fetch/fetch_api_request.mojom
@@ -14,7 +14,7 @@
 import "services/network/public/mojom/url_loader.mojom";
 import "third_party/blink/public/mojom/blob/serialized_blob.mojom";
 import "third_party/blink/public/mojom/loader/request_context_frame_type.mojom";
-import "third_party/blink/public/mojom/referrer.mojom";
+import "third_party/blink/public/mojom/loader/referrer.mojom";
 import "url/mojom/url.mojom";
 
 
diff --git a/third_party/blink/public/mojom/frame/frame.mojom b/third_party/blink/public/mojom/frame/frame.mojom
index 994e24b..b8fce51 100644
--- a/third_party/blink/public/mojom/frame/frame.mojom
+++ b/third_party/blink/public/mojom/frame/frame.mojom
@@ -37,7 +37,7 @@
 import "third_party/blink/public/mojom/input/focus_type.mojom";
 import "third_party/blink/public/mojom/input/scroll_direction.mojom";
 import "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom";
-import "third_party/blink/public/mojom/referrer.mojom";
+import "third_party/blink/public/mojom/loader/referrer.mojom";
 import "third_party/blink/public/mojom/timing/resource_timing.mojom";
 import "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom";
 import "third_party/blink/public/mojom/web_feature/web_feature.mojom";
diff --git a/third_party/blink/public/mojom/referrer.mojom b/third_party/blink/public/mojom/loader/referrer.mojom
similarity index 100%
rename from third_party/blink/public/mojom/referrer.mojom
rename to third_party/blink/public/mojom/loader/referrer.mojom
diff --git a/third_party/blink/public/mojom/portal/portal.mojom b/third_party/blink/public/mojom/portal/portal.mojom
index 731da40..9b6a7279 100644
--- a/third_party/blink/public/mojom/portal/portal.mojom
+++ b/third_party/blink/public/mojom/portal/portal.mojom
@@ -7,7 +7,7 @@
 import "mojo/public/mojom/base/time.mojom";
 import "mojo/public/mojom/base/unguessable_token.mojom";
 import "third_party/blink/public/mojom/messaging/transferable_message.mojom";
-import "third_party/blink/public/mojom/referrer.mojom";
+import "third_party/blink/public/mojom/loader/referrer.mojom";
 import "url/mojom/origin.mojom";
 import "url/mojom/url.mojom";
 import "url/mojom/origin.mojom";
diff --git a/third_party/blink/public/mojom/prerender/prerender.mojom b/third_party/blink/public/mojom/prerender/prerender.mojom
index 6b1564e..1ff74e8 100644
--- a/third_party/blink/public/mojom/prerender/prerender.mojom
+++ b/third_party/blink/public/mojom/prerender/prerender.mojom
@@ -4,7 +4,7 @@
 
 module blink.mojom;
 
-import "third_party/blink/public/mojom/referrer.mojom";
+import "third_party/blink/public/mojom/loader/referrer.mojom";
 import "ui/gfx/geometry/mojom/geometry.mojom";
 import "url/mojom/origin.mojom";
 import "url/mojom/url.mojom";
diff --git a/third_party/blink/public/platform/web_isolated_world_info.h b/third_party/blink/public/platform/web_isolated_world_info.h
index 71c66ec..1f1ba5f6 100644
--- a/third_party/blink/public/platform/web_isolated_world_info.h
+++ b/third_party/blink/public/platform/web_isolated_world_info.h
@@ -2,8 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "third_party/blink/public/platform/web_common.h"
 #include "third_party/blink/public/platform/web_security_origin.h"
 #include "third_party/blink/public/platform/web_string.h"
+#include "v8/include/v8.h"
 
 #ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_ISOLATED_WORLD_INFO_H_
 #define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_ISOLATED_WORLD_INFO_H_
@@ -49,6 +51,19 @@
   WebString stable_id;
 };
 
+// Sets up an isolated world by associating a |world_id| with |info|.
+// worldID must be > 0 (as 0 represents the main world).
+// worldID must be < kEmbedderWorldIdLimit, high number used internally.
+BLINK_EXPORT void SetIsolatedWorldInfo(int32_t world_id,
+                                       const WebIsolatedWorldInfo& info);
+
+// Returns the stable ID that was set with SetIsolatedWorldInfo.
+BLINK_EXPORT WebString GetIsolatedWorldStableId(v8::Local<v8::Context>);
+
+// Returns the human readable name that was set with SetIsolatedWorldInfo.
+BLINK_EXPORT WebString
+    GetIsolatedWorldHumanReadableName(v8::Local<v8::Context>);
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_ISOLATED_WORLD_INFO_H_
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h
index 179221fb..a6b33cc 100644
--- a/third_party/blink/public/web/web_local_frame.h
+++ b/third_party/blink/public/web/web_local_frame.h
@@ -316,21 +316,6 @@
   // Document.
   virtual void ClearIsolatedWorldCSPForTesting(int32_t world_id) = 0;
 
-  // Sets up an isolated world by associating a |world_id| with |info|.
-  // worldID must be > 0 (as 0 represents the main world).
-  // worldID must be < kEmbedderWorldIdLimit, high number used internally.
-  // TODO(karandeepb): This modifies the global isolated world info and hence
-  // should ideally be moved out of WebLocalFrame.
-  virtual void SetIsolatedWorldInfo(int32_t world_id,
-                                    const WebIsolatedWorldInfo& info) = 0;
-
-  // Returns the stable ID that was set with SetIsolatedWorldInfo.
-  virtual WebString GetIsolatedWorldStableId(v8::Local<v8::Context>) const = 0;
-
-  // Returns the human readable name that was set with SetIsolatedWorldInfo.
-  virtual WebString GetIsolatedWorldHumanReadableName(
-      v8::Local<v8::Context>) const = 0;
-
   // Executes script in the context of the current page and returns the value
   // that the script evaluated to.
   // DEPRECATED: Use WebLocalFrame::requestExecuteScriptAndReturnValue.
diff --git a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
index 17ebe5e..4e2f84be 100644
--- a/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
+++ b/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
@@ -31,6 +31,7 @@
 #include "third_party/blink/renderer/bindings/core/v8/local_window_proxy.h"
 
 #include "base/debug/dump_without_crashing.h"
+#include "base/memory/scoped_refptr.h"
 #include "third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
 #include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
@@ -181,22 +182,23 @@
         V8String(GetIsolate(), csp->EvalDisabledErrorMessage()));
   }
 
-  const SecurityOrigin* origin = nullptr;
+  scoped_refptr<const SecurityOrigin> origin;
   if (world_->IsMainWorld()) {
     // ActivityLogger for main world is updated within updateDocumentInternal().
     UpdateDocumentInternal();
     origin = GetFrame()->DomWindow()->GetSecurityOrigin();
   } else {
     UpdateActivityLogger();
-    origin = world_->IsolatedWorldSecurityOrigin();
-    SetSecurityToken(origin);
+    origin = world_->IsolatedWorldSecurityOrigin(
+        GetFrame()->DomWindow()->GetAgentClusterID());
+    SetSecurityToken(origin.get());
   }
 
   {
     TRACE_EVENT1("v8", "ContextCreatedNotification", "IsMainFrame",
                  GetFrame()->IsMainFrame());
     MainThreadDebugger::Instance()->ContextCreated(script_state_, GetFrame(),
-                                                   origin);
+                                                   origin.get());
     GetFrame()->Client()->DidCreateScriptContext(context, world_->GetWorldId());
   }
 
diff --git a/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.cc b/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.cc
index b302d33b..90083d1f 100644
--- a/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.cc
+++ b/third_party/blink/renderer/bindings/core/v8/window_proxy_manager.cc
@@ -113,9 +113,10 @@
   for (auto& entry : isolated_worlds_) {
     auto* isolated_window_proxy =
         static_cast<LocalWindowProxy*>(entry.value.Get());
-    const SecurityOrigin* isolated_security_origin =
-        isolated_window_proxy->World().IsolatedWorldSecurityOrigin();
-    isolated_window_proxy->UpdateSecurityOrigin(isolated_security_origin);
+    scoped_refptr<SecurityOrigin> isolated_security_origin =
+        isolated_window_proxy->World().IsolatedWorldSecurityOrigin(
+            security_origin->AgentClusterId());
+    isolated_window_proxy->UpdateSecurityOrigin(isolated_security_origin.get());
   }
 }
 
diff --git a/third_party/blink/renderer/core/clipboard/system_clipboard.cc b/third_party/blink/renderer/core/clipboard/system_clipboard.cc
index 3f61e32..d272728 100644
--- a/third_party/blink/renderer/core/clipboard/system_clipboard.cc
+++ b/third_party/blink/renderer/core/clipboard/system_clipboard.cc
@@ -49,7 +49,7 @@
 }
 
 bool SystemClipboard::CanSmartReplace() {
-  if (!IsValidBufferType(buffer_))
+  if (!IsValidBufferType(buffer_) || !clipboard_.is_bound())
     return false;
   bool result = false;
   clipboard_->IsFormatAvailable(mojom::ClipboardFormat::kSmartPaste, buffer_,
@@ -58,7 +58,7 @@
 }
 
 bool SystemClipboard::IsHTMLAvailable() {
-  if (!IsValidBufferType(buffer_))
+  if (!IsValidBufferType(buffer_) || !clipboard_.is_bound())
     return false;
   bool result = false;
   clipboard_->IsFormatAvailable(mojom::ClipboardFormat::kHtml, buffer_,
@@ -67,7 +67,7 @@
 }
 
 uint64_t SystemClipboard::SequenceNumber() {
-  if (!IsValidBufferType(buffer_))
+  if (!IsValidBufferType(buffer_) || !clipboard_.is_bound())
     return 0;
   uint64_t result = 0;
   clipboard_->GetSequenceNumber(buffer_, &result);
@@ -75,7 +75,7 @@
 }
 
 Vector<String> SystemClipboard::ReadAvailableTypes() {
-  if (!IsValidBufferType(buffer_))
+  if (!IsValidBufferType(buffer_) || !clipboard_.is_bound())
     return {};
   Vector<String> types;
   clipboard_->ReadAvailableTypes(buffer_, &types);
@@ -87,7 +87,7 @@
 }
 
 String SystemClipboard::ReadPlainText(mojom::ClipboardBuffer buffer) {
-  if (!IsValidBufferType(buffer))
+  if (!IsValidBufferType(buffer) || !clipboard_.is_bound())
     return String();
   String text;
   clipboard_->ReadText(buffer, &text);
@@ -131,7 +131,7 @@
 }
 
 String SystemClipboard::ReadRTF() {
-  if (!IsValidBufferType(buffer_))
+  if (!IsValidBufferType(buffer_) || !clipboard_.is_bound())
     return String();
   String rtf;
   clipboard_->ReadRtf(buffer_, &rtf);
@@ -139,7 +139,7 @@
 }
 
 SkBitmap SystemClipboard::ReadImage(mojom::ClipboardBuffer buffer) {
-  if (!IsValidBufferType(buffer))
+  if (!IsValidBufferType(buffer) || !clipboard_.is_bound())
     return SkBitmap();
   SkBitmap image;
   clipboard_->ReadImage(buffer, &image);
@@ -185,7 +185,7 @@
 }
 
 String SystemClipboard::ReadCustomData(const String& type) {
-  if (!IsValidBufferType(buffer_))
+  if (!IsValidBufferType(buffer_) || !clipboard_.is_bound())
     return String();
   String data;
   clipboard_->ReadCustomData(buffer_, NonNullString(type), &data);
diff --git a/third_party/blink/renderer/core/clipboard/system_clipboard.h b/third_party/blink/renderer/core/clipboard/system_clipboard.h
index 1fdda23..8f4979d 100644
--- a/third_party/blink/renderer/core/clipboard/system_clipboard.h
+++ b/third_party/blink/renderer/core/clipboard/system_clipboard.h
@@ -9,7 +9,6 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
 #include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
-#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -22,7 +21,7 @@
 class LocalFrame;
 
 // SystemClipboard:
-// - is a singleton.
+// - is a LocalFrame bounded object.
 // - provides sanitized, platform-neutral read/write access to the clipboard.
 // - mediates between core classes and mojom::ClipboardHost.
 //
@@ -79,9 +78,7 @@
  private:
   bool IsValidBufferType(mojom::ClipboardBuffer);
 
-  HeapMojoRemote<mojom::blink::ClipboardHost,
-                 HeapMojoWrapperMode::kForceWithoutContextObserver>
-      clipboard_;
+  HeapMojoRemote<mojom::blink::ClipboardHost> clipboard_;
   // In X11, |buffer_| may equal ClipboardBuffer::kStandard or kSelection.
   // Outside X11, |buffer_| always equals ClipboardBuffer::kStandard.
   mojom::ClipboardBuffer buffer_ = mojom::ClipboardBuffer::kStandard;
diff --git a/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc b/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc
index 48d17cbde..440fbdef 100644
--- a/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc
+++ b/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc
@@ -343,11 +343,13 @@
   if (!src_markers)
     return;
 
-  if (!markers_.Contains(&dst_node)) {
-    markers_.insert(&dst_node, MakeGarbageCollected<MarkerLists>(
-                                   DocumentMarker::kMarkerTypeIndexesCount));
+  auto& dst_marker_entry =
+      markers_.insert(&dst_node, nullptr).stored_value->value;
+  if (!dst_marker_entry) {
+    dst_marker_entry = MakeGarbageCollected<MarkerLists>(
+        DocumentMarker::kMarkerTypeIndexesCount);
   }
-  MarkerLists* const dst_markers = markers_.at(&dst_node);
+  MarkerLists* const dst_markers = dst_marker_entry;
 
   bool doc_dirty = false;
   for (DocumentMarker::MarkerType type : DocumentMarker::MarkerTypes::All()) {
diff --git a/third_party/blink/renderer/core/exported/BUILD.gn b/third_party/blink/renderer/core/exported/BUILD.gn
index e597f82..3181148 100644
--- a/third_party/blink/renderer/core/exported/BUILD.gn
+++ b/third_party/blink/renderer/core/exported/BUILD.gn
@@ -42,6 +42,7 @@
     "web_input_element.cc",
     "web_input_method_controller_impl.cc",
     "web_input_method_controller_impl.h",
+    "web_isolated_world_info.cc",
     "web_label_element.cc",
     "web_language_detection_details.cc",
     "web_local_frame_client.cc",
diff --git a/third_party/blink/renderer/core/exported/web_isolated_world_info.cc b/third_party/blink/renderer/core/exported/web_isolated_world_info.cc
new file mode 100644
index 0000000..d47897d
--- /dev/null
+++ b/third_party/blink/renderer/core/exported/web_isolated_world_info.cc
@@ -0,0 +1,42 @@
+// Copyright 2020 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 "third_party/blink/public/platform/web_isolated_world_info.h"
+
+#include "third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h"
+#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
+
+namespace blink {
+
+void SetIsolatedWorldInfo(int32_t world_id, const WebIsolatedWorldInfo& info) {
+  CHECK_GT(world_id, DOMWrapperWorld::kMainWorldId);
+  CHECK_LT(world_id, DOMWrapperWorld::kDOMWrapperWorldEmbedderWorldIdLimit);
+
+  scoped_refptr<SecurityOrigin> security_origin =
+      info.security_origin.Get() ? info.security_origin.Get()->IsolatedCopy()
+                                 : nullptr;
+
+  CHECK(info.content_security_policy.IsNull() || security_origin);
+
+  DOMWrapperWorld::SetIsolatedWorldSecurityOrigin(world_id, security_origin);
+  DOMWrapperWorld::SetNonMainWorldStableId(world_id, info.stable_id);
+  DOMWrapperWorld::SetNonMainWorldHumanReadableName(world_id,
+                                                    info.human_readable_name);
+  IsolatedWorldCSP::Get().SetContentSecurityPolicy(
+      world_id, info.content_security_policy, security_origin);
+}
+
+WebString GetIsolatedWorldStableId(v8::Local<v8::Context> context) {
+  const DOMWrapperWorld& world = DOMWrapperWorld::World(context);
+  DCHECK(!world.IsMainWorld());
+  return world.NonMainWorldStableId();
+}
+
+WebString GetIsolatedWorldHumanReadableName(v8::Local<v8::Context> context) {
+  const DOMWrapperWorld& world = DOMWrapperWorld::World(context);
+  DCHECK(!world.IsMainWorld());
+  return world.NonMainWorldHumanReadableName();
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/fetch/request.cc b/third_party/blink/renderer/core/fetch/request.cc
index 9fdf4da..82e0ac0 100644
--- a/third_party/blink/renderer/core/fetch/request.cc
+++ b/third_party/blink/renderer/core/fetch/request.cc
@@ -66,16 +66,18 @@
 FetchRequestData* CreateCopyOfFetchRequestDataForFetch(
     ScriptState* script_state,
     const FetchRequestData* original) {
-  auto* request = MakeGarbageCollected<FetchRequestData>(
-      ExecutionContext::From(script_state));
+  ExecutionContext* context = ExecutionContext::From(script_state);
+  auto* request = MakeGarbageCollected<FetchRequestData>(context);
   request->SetURL(original->Url());
   request->SetMethod(original->Method());
   request->SetHeaderList(original->HeaderList()->Clone());
-  request->SetOrigin(ExecutionContext::From(script_state)->GetSecurityOrigin());
+  request->SetOrigin(context->GetSecurityOrigin());
   // FIXME: Set client.
   DOMWrapperWorld& world = script_state->World();
-  if (world.IsIsolatedWorld())
-    request->SetIsolatedWorldOrigin(world.IsolatedWorldSecurityOrigin());
+  if (world.IsIsolatedWorld()) {
+    request->SetIsolatedWorldOrigin(
+        world.IsolatedWorldSecurityOrigin(context->GetAgentClusterID()));
+  }
   // FIXME: Set ForceOriginHeaderFlag.
   request->SetReferrerString(original->ReferrerString());
   request->SetReferrerPolicy(original->GetReferrerPolicy());
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index 4b62d4f..971224f 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -720,8 +720,16 @@
 
 void LocalFrame::SetDOMWindow(LocalDOMWindow* dom_window) {
   DCHECK(dom_window);
-  if (this->DomWindow())
+  if (this->DomWindow()) {
     this->DomWindow()->Reset();
+    // SystemClipboard and RawSystemClipboard uses HeapMojo wrappers. HeapMojo
+    // wrappers uses LocalDOMWindow (ExecutionContext) to reset the mojo
+    // objects when the ExecutionContext was destroyed. So when new
+    // LocalDOMWindow was set, we need to create new SystemClipboard and
+    // RawSystemClipboard.
+    system_clipboard_ = nullptr;
+    raw_system_clipboard_ = nullptr;
+  }
   GetScriptController().ClearWindowProxy();
   dom_window_ = dom_window;
 }
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index 3b9a026..5f49317 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -813,47 +813,6 @@
   GetFrame()->DomWindow()->ClearIsolatedWorldCSPForTesting(world_id);
 }
 
-void WebLocalFrameImpl::SetIsolatedWorldInfo(int32_t world_id,
-                                             const WebIsolatedWorldInfo& info) {
-  DCHECK(GetFrame());
-  CHECK_GT(world_id, DOMWrapperWorld::kMainWorldId);
-  CHECK_LT(world_id, DOMWrapperWorld::kDOMWrapperWorldEmbedderWorldIdLimit);
-
-  // The security origin received via IPC doesn't contain the agent cluster
-  // ID so we need to make sure it contains the cluster agent ID from
-  // the current document.
-  scoped_refptr<SecurityOrigin> security_origin =
-      info.security_origin.Get()
-          ? info.security_origin.Get()
-                ->IsolatedCopy()
-                ->GetOriginForAgentCluster(
-                    GetFrame()->DomWindow()->GetAgentClusterID())
-          : nullptr;
-
-  CHECK(info.content_security_policy.IsNull() || security_origin);
-
-  DOMWrapperWorld::SetIsolatedWorldSecurityOrigin(world_id, security_origin);
-  DOMWrapperWorld::SetNonMainWorldStableId(world_id, info.stable_id);
-  DOMWrapperWorld::SetNonMainWorldHumanReadableName(world_id,
-                                                    info.human_readable_name);
-  IsolatedWorldCSP::Get().SetContentSecurityPolicy(
-      world_id, info.content_security_policy, security_origin);
-}
-
-WebString WebLocalFrameImpl::GetIsolatedWorldStableId(
-    v8::Local<v8::Context> context) const {
-  const DOMWrapperWorld& world = DOMWrapperWorld::World(context);
-  DCHECK(!world.IsMainWorld());
-  return world.NonMainWorldStableId();
-}
-
-WebString WebLocalFrameImpl::GetIsolatedWorldHumanReadableName(
-    v8::Local<v8::Context> context) const {
-  const DOMWrapperWorld& world = DOMWrapperWorld::World(context);
-  DCHECK(!world.IsMainWorld());
-  return world.NonMainWorldHumanReadableName();
-}
-
 void WebLocalFrameImpl::Alert(const WebString& message) {
   DCHECK(GetFrame());
   ScriptState* script_state = ToScriptStateForMainWorld(GetFrame());
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
index 670dff25..93dacfa 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -150,12 +150,6 @@
   ExecuteScriptInIsolatedWorldAndReturnValue(int32_t world_id,
                                              const WebScriptSource&) override;
   void ClearIsolatedWorldCSPForTesting(int32_t world_id) override;
-  void SetIsolatedWorldInfo(int32_t world_id,
-                            const WebIsolatedWorldInfo&) override;
-  WebString GetIsolatedWorldStableId(
-      v8::Local<v8::Context> context) const override;
-  WebString GetIsolatedWorldHumanReadableName(
-      v8::Local<v8::Context> context) const override;
   v8::Local<v8::Value> ExecuteScriptAndReturnValue(
       const WebScriptSource&) override;
   v8::MaybeLocal<v8::Value> CallFunctionEvenIfScriptDisabled(
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 01ebb86d..fa4d18a 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
@@ -5,7 +5,7 @@
 #include "third_party/blink/renderer/core/html/portal/html_portal_element.h"
 
 #include <utility>
-#include "third_party/blink/public/mojom/referrer.mojom-blink.h"
+#include "third_party/blink/public/mojom/loader/referrer.mojom-blink.h"
 #include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_event_listener.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
diff --git a/third_party/blink/renderer/core/html/portal/portal_contents.cc b/third_party/blink/renderer/core/html/portal/portal_contents.cc
index d38cbc0..31402e1 100644
--- a/third_party/blink/renderer/core/html/portal/portal_contents.cc
+++ b/third_party/blink/renderer/core/html/portal/portal_contents.cc
@@ -6,8 +6,8 @@
 
 #include "base/compiler_specific.h"
 #include "base/time/time.h"
+#include "third_party/blink/public/mojom/loader/referrer.mojom-blink.h"
 #include "third_party/blink/public/mojom/portal/portal.mojom-blink-forward.h"
-#include "third_party/blink/public/mojom/referrer.mojom-blink.h"
 #include "third_party/blink/renderer/core/dom/increment_load_event_delay_count.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
 #include "third_party/blink/renderer/core/frame/remote_frame.h"
diff --git a/third_party/blink/renderer/core/layout/BUILD.gn b/third_party/blink/renderer/core/layout/BUILD.gn
index 238744e..63c40273 100644
--- a/third_party/blink/renderer/core/layout/BUILD.gn
+++ b/third_party/blink/renderer/core/layout/BUILD.gn
@@ -314,6 +314,8 @@
     "ng/exclusions/ng_layout_opportunity.h",
     "ng/exclusions/ng_line_layout_opportunity.h",
     "ng/exclusions/ng_shape_exclusions.h",
+    "ng/flex/layout_ng_button.cc",
+    "ng/flex/layout_ng_button.h",
     "ng/flex/layout_ng_flexible_box.cc",
     "ng/flex/layout_ng_flexible_box.h",
     "ng/flex/ng_flex_child_iterator.cc",
diff --git a/third_party/blink/renderer/core/layout/layout_button.cc b/third_party/blink/renderer/core/layout/layout_button.cc
index 29ddba1..59118813 100644
--- a/third_party/blink/renderer/core/layout/layout_button.cc
+++ b/third_party/blink/renderer/core/layout/layout_button.cc
@@ -59,6 +59,12 @@
 void LayoutButton::UpdateAnonymousChildStyle(const LayoutObject* child,
                                              ComputedStyle& child_style) const {
   DCHECK_EQ(inner_, child);
+  UpdateAnonymousChildStyle(StyleRef(), child_style);
+}
+
+// This function is shared with LayoutNGButton.
+void LayoutButton::UpdateAnonymousChildStyle(const ComputedStyle& parent_style,
+                                             ComputedStyle& child_style) {
   child_style.SetFlexGrow(1.0f);
   // min-width: 0; is needed for correct shrinking.
   child_style.SetMinWidth(Length::Fixed(0));
@@ -66,13 +72,13 @@
   // when the content overflows, treat it the same as align-items: flex-start.
   child_style.SetMarginTop(Length());
   child_style.SetMarginBottom(Length());
-  child_style.SetFlexDirection(StyleRef().FlexDirection());
-  child_style.SetJustifyContent(StyleRef().JustifyContent());
-  child_style.SetFlexWrap(StyleRef().FlexWrap());
+  child_style.SetFlexDirection(parent_style.FlexDirection());
+  child_style.SetJustifyContent(parent_style.JustifyContent());
+  child_style.SetFlexWrap(parent_style.FlexWrap());
   // TODO (lajava): An anonymous box must not be used to resolve children's auto
   // values.
-  child_style.SetAlignItems(StyleRef().AlignItems());
-  child_style.SetAlignContent(StyleRef().AlignContent());
+  child_style.SetAlignItems(parent_style.AlignItems());
+  child_style.SetAlignContent(parent_style.AlignContent());
 }
 
 LayoutUnit LayoutButton::BaselinePosition(
diff --git a/third_party/blink/renderer/core/layout/layout_button.h b/third_party/blink/renderer/core/layout/layout_button.h
index 60ce95b..e0f91004 100644
--- a/third_party/blink/renderer/core/layout/layout_button.h
+++ b/third_party/blink/renderer/core/layout/layout_button.h
@@ -53,6 +53,9 @@
                               LineDirectionMode,
                               LinePositionMode) const override;
 
+  static void UpdateAnonymousChildStyle(const ComputedStyle& parent_sytle,
+                                        ComputedStyle& child_style);
+
  private:
   void UpdateAnonymousChildStyle(const LayoutObject* child,
                                  ComputedStyle& child_style) const override;
@@ -60,8 +63,6 @@
   LayoutBlock* inner_;
 };
 
-DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutButton, IsLayoutButton());
-
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_BUTTON_H_
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index 870ec24..b0cba3c 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -717,6 +717,7 @@
   bool IsProgress() const { return IsOfType(kLayoutObjectProgress); }
   bool IsQuote() const { return IsOfType(kLayoutObjectQuote); }
   bool IsLayoutButton() const { return IsOfType(kLayoutObjectLayoutButton); }
+  bool IsLayoutNGButton() const { return IsOfType(kLayoutObjectNGButton); }
   bool IsLayoutNGCustom() const {
     return IsOfType(kLayoutObjectLayoutNGCustom);
   }
@@ -2653,6 +2654,7 @@
     kLayoutObjectMathMLRoot,
     kLayoutObjectMedia,
     kLayoutObjectNGBlockFlow,
+    kLayoutObjectNGButton,
     kLayoutObjectNGFieldset,
     kLayoutObjectNGFlexibleBox,
     kLayoutObjectNGGrid,
diff --git a/third_party/blink/renderer/core/layout/ng/flex/layout_ng_button.cc b/third_party/blink/renderer/core/layout/ng/flex/layout_ng_button.cc
new file mode 100644
index 0000000..dad1b953
--- /dev/null
+++ b/third_party/blink/renderer/core/layout/ng/flex/layout_ng_button.cc
@@ -0,0 +1,50 @@
+// Copyright 2020 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 "third_party/blink/renderer/core/layout/ng/flex/layout_ng_button.h"
+
+#include "third_party/blink/renderer/core/layout/layout_button.h"
+
+namespace blink {
+
+LayoutNGButton::LayoutNGButton(Element* element)
+    : LayoutNGFlexibleBox(element), inner_(nullptr) {}
+
+LayoutNGButton::~LayoutNGButton() = default;
+
+void LayoutNGButton::AddChild(LayoutObject* new_child,
+                              LayoutObject* before_child) {
+  if (!inner_) {
+    // Create an anonymous block.
+    DCHECK(!FirstChild());
+    inner_ = CreateAnonymousBlock(StyleRef().Display());
+    LayoutNGFlexibleBox::AddChild(inner_);
+  }
+
+  inner_->AddChild(new_child, before_child);
+}
+
+void LayoutNGButton::RemoveChild(LayoutObject* old_child) {
+  if (old_child == inner_ || !inner_) {
+    LayoutNGFlexibleBox::RemoveChild(old_child);
+    inner_ = nullptr;
+
+  } else if (old_child->Parent() == this) {
+    // We aren't the inner node, but we're getting removed from the button, this
+    // can happen with things like scrollable area resizer's.
+    LayoutNGFlexibleBox::RemoveChild(old_child);
+
+  } else {
+    inner_->RemoveChild(old_child);
+  }
+}
+
+void LayoutNGButton::UpdateAnonymousChildStyle(
+    const LayoutObject* child,
+    ComputedStyle& child_style) const {
+  DCHECK_EQ(inner_, child);
+  LayoutButton::UpdateAnonymousChildStyle(StyleRef(), child_style);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/flex/layout_ng_button.h b/third_party/blink/renderer/core/layout/ng/flex/layout_ng_button.h
new file mode 100644
index 0000000..080b502
--- /dev/null
+++ b/third_party/blink/renderer/core/layout/ng/flex/layout_ng_button.h
@@ -0,0 +1,37 @@
+// Copyright 2020 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_LAYOUT_NG_FLEX_LAYOUT_NG_BUTTON_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_FLEX_LAYOUT_NG_BUTTON_H_
+
+#include "third_party/blink/renderer/core/layout/ng/flex/layout_ng_flexible_box.h"
+
+namespace blink {
+
+class LayoutNGButton final : public LayoutNGFlexibleBox {
+ public:
+  explicit LayoutNGButton(Element*);
+  ~LayoutNGButton() override;
+
+  const char* GetName() const override { return "LayoutNGButton"; }
+  void AddChild(LayoutObject* new_child,
+                LayoutObject* before_child = nullptr) override;
+  void RemoveChild(LayoutObject*) override;
+  void RemoveLeftoverAnonymousBlock(LayoutBlock*) override {}
+  bool CreatesAnonymousWrapper() const override { return true; }
+
+ private:
+  void UpdateAnonymousChildStyle(const LayoutObject* child,
+                                 ComputedStyle& child_style) const override;
+
+  bool IsOfType(LayoutObjectType type) const override {
+    return type == kLayoutObjectNGButton || LayoutNGFlexibleBox::IsOfType(type);
+  }
+
+  LayoutBlock* inner_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_FLEX_LAYOUT_NG_BUTTON_H_
diff --git a/third_party/blink/renderer/core/paint/file_upload_control_painter.cc b/third_party/blink/renderer/core/paint/file_upload_control_painter.cc
index 45080722..1f5cb0a0 100644
--- a/third_party/blink/renderer/core/paint/file_upload_control_painter.cc
+++ b/third_party/blink/renderer/core/paint/file_upload_control_painter.cc
@@ -5,7 +5,7 @@
 #include "third_party/blink/renderer/core/paint/file_upload_control_painter.h"
 
 #include "base/optional.h"
-#include "third_party/blink/renderer/core/layout/layout_button.h"
+#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
 #include "third_party/blink/renderer/core/layout/layout_file_upload_control.h"
 #include "third_party/blink/renderer/core/layout/text_run_constructor.h"
 #include "third_party/blink/renderer/core/paint/paint_info.h"
@@ -57,8 +57,7 @@
     LayoutUnit text_y;
     // We want to match the button's baseline
     // FIXME: Make this work with transforms.
-    if (LayoutButton* button_layout_object =
-            ToLayoutButton(button->GetLayoutObject()))
+    if (LayoutBox* button_layout_object = button->GetLayoutBox())
       text_y = paint_offset.top + layout_file_upload_control_.BorderTop() +
                layout_file_upload_control_.PaddingTop() +
                button_layout_object->BaselinePosition(
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 ffcf5c5..260fc6f 100644
--- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
+++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
@@ -276,11 +276,12 @@
   DOMWrapperWorld& world = script_state->World();
   v8::Isolate* isolate = script_state->GetIsolate();
 
-  return world.IsIsolatedWorld()
-             ? MakeGarbageCollected<XMLHttpRequest>(
-                   context, isolate, true, world.IsolatedWorldSecurityOrigin())
-             : MakeGarbageCollected<XMLHttpRequest>(context, isolate, false,
-                                                    nullptr);
+  return world.IsIsolatedWorld() ? MakeGarbageCollected<XMLHttpRequest>(
+                                       context, isolate, true,
+                                       world.IsolatedWorldSecurityOrigin(
+                                           context->GetAgentClusterID()))
+                                 : MakeGarbageCollected<XMLHttpRequest>(
+                                       context, isolate, false, nullptr);
 }
 
 XMLHttpRequest* XMLHttpRequest::Create(ExecutionContext* context) {
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_attribute_instance_map.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth_attribute_instance_map.cc
index d36fc78..cf74e1aa 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_attribute_instance_map.cc
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_attribute_instance_map.cc
@@ -20,17 +20,14 @@
     mojom::blink::WebBluetoothRemoteGATTServicePtr remote_gatt_service,
     bool is_primary,
     const String& device_instance_id) {
-  String service_instance_id = remote_gatt_service->instance_id;
-  BluetoothRemoteGATTService* service =
-      service_id_to_object_.at(service_instance_id);
-
+  auto& service =
+      service_id_to_object_.insert(remote_gatt_service->instance_id, nullptr)
+          .stored_value->value;
   if (!service) {
     service = MakeGarbageCollected<BluetoothRemoteGATTService>(
         std::move(remote_gatt_service), is_primary, device_instance_id,
         device_);
-    service_id_to_object_.insert(service_instance_id, service);
   }
-
   return service;
 }
 
@@ -45,16 +42,14 @@
     mojom::blink::WebBluetoothRemoteGATTCharacteristicPtr
         remote_gatt_characteristic,
     BluetoothRemoteGATTService* service) {
-  String instance_id = remote_gatt_characteristic->instance_id;
-  BluetoothRemoteGATTCharacteristic* characteristic =
-      characteristic_id_to_object_.at(instance_id);
-
+  auto& characteristic =
+      characteristic_id_to_object_
+          .insert(remote_gatt_characteristic->instance_id, nullptr)
+          .stored_value->value;
   if (!characteristic) {
     characteristic = MakeGarbageCollected<BluetoothRemoteGATTCharacteristic>(
         context, std::move(remote_gatt_characteristic), service, device_);
-    characteristic_id_to_object_.insert(instance_id, characteristic);
   }
-
   return characteristic;
 }
 
@@ -65,19 +60,16 @@
 
 BluetoothRemoteGATTDescriptor*
 BluetoothAttributeInstanceMap::GetOrCreateBluetoothRemoteGATTDescriptor(
-    mojom::blink::WebBluetoothRemoteGATTDescriptorPtr descriptor,
+    mojom::blink::WebBluetoothRemoteGATTDescriptorPtr remote_gatt_descriptor,
     BluetoothRemoteGATTCharacteristic* characteristic) {
-  String instance_id = descriptor->instance_id;
-  BluetoothRemoteGATTDescriptor* result =
-      descriptor_id_to_object_.at(instance_id);
-
-  if (result)
-    return result;
-
-  result = MakeGarbageCollected<BluetoothRemoteGATTDescriptor>(
-      std::move(descriptor), characteristic);
-  descriptor_id_to_object_.insert(instance_id, result);
-  return result;
+  auto& descriptor = descriptor_id_to_object_
+                         .insert(remote_gatt_descriptor->instance_id, nullptr)
+                         .stored_value->value;
+  if (!descriptor) {
+    descriptor = MakeGarbageCollected<BluetoothRemoteGATTDescriptor>(
+        std::move(remote_gatt_descriptor), characteristic);
+  }
+  return descriptor;
 }
 
 bool BluetoothAttributeInstanceMap::ContainsDescriptor(
diff --git a/third_party/blink/renderer/modules/push_messaging/push_messaging_type_converter.cc b/third_party/blink/renderer/modules/push_messaging/push_messaging_type_converter.cc
index 403eaca2b..21c85a9e 100644
--- a/third_party/blink/renderer/modules/push_messaging/push_messaging_type_converter.cc
+++ b/third_party/blink/renderer/modules/push_messaging/push_messaging_type_converter.cc
@@ -28,13 +28,4 @@
       input->userVisibleOnly(), std::move(application_server_key));
 }
 
-// TODO(viviy): implement conversion
-// static
-blink::PushSubscription*
-TypeConverter<blink::PushSubscription*,
-              blink::mojom::blink::PushSubscriptionPtr>::
-    Convert(const blink::mojom::blink::PushSubscriptionPtr& input) {
-  return nullptr;
-}
-
 }  // namespace mojo
diff --git a/third_party/blink/renderer/modules/push_messaging/push_messaging_type_converter.h b/third_party/blink/renderer/modules/push_messaging/push_messaging_type_converter.h
index 2c5f79aa..f155f25 100644
--- a/third_party/blink/renderer/modules/push_messaging/push_messaging_type_converter.h
+++ b/third_party/blink/renderer/modules/push_messaging/push_messaging_type_converter.h
@@ -29,15 +29,6 @@
       const blink::PushSubscriptionOptions* input);
 };
 
-// Converts a {blink::mojom::blink::PushSubscriptionPtr} object into a
-// {blink::PushSubscription*}, currently returning nullptr
-template <>
-struct TypeConverter<blink::PushSubscription*,
-                     blink::mojom::blink::PushSubscriptionPtr> {
-  static blink::PushSubscription* Convert(
-      const blink::mojom::blink::PushSubscriptionPtr& input);
-};
-
 }  // namespace mojo
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_PUSH_MESSAGING_PUSH_MESSAGING_TYPE_CONVERTER_H_
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
index 4d060db..32f07e0 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
@@ -96,7 +96,6 @@
 #include "third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.h"
 #include "third_party/blink/renderer/modules/push_messaging/push_event.h"
 #include "third_party/blink/renderer/modules/push_messaging/push_message_data.h"
-#include "third_party/blink/renderer/modules/push_messaging/push_messaging_type_converter.h"
 #include "third_party/blink/renderer/modules/push_messaging/push_subscription_change_event.h"
 #include "third_party/blink/renderer/modules/service_worker/cross_origin_resource_policy_checker.h"
 #include "third_party/blink/renderer/modules/service_worker/extendable_event.h"
@@ -2063,8 +2062,9 @@
       this, WaitUntilObserver::kPushSubscriptionChange, event_id);
   Event* event = PushSubscriptionChangeEvent::Create(
       event_type_names::kPushsubscriptionchange,
-      new_subscription.To<blink::PushSubscription*>(),
-      old_subscription.To<blink::PushSubscription*>(), observer);
+      PushSubscription::Create(std::move(new_subscription), registration_),
+      PushSubscription::Create(std::move(old_subscription), registration_),
+      observer);
   DispatchExtendableEvent(event, observer);
 }
 
diff --git a/third_party/blink/renderer/modules/speech/speech_synthesis.h b/third_party/blink/renderer/modules/speech/speech_synthesis.h
index 83f91cfb..2a14b0c 100644
--- a/third_party/blink/renderer/modules/speech/speech_synthesis.h
+++ b/third_party/blink/renderer/modules/speech/speech_synthesis.h
@@ -35,7 +35,6 @@
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
 #include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
-#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
 #include "third_party/blink/renderer/platform/supplementable.h"
 
 namespace blink {
@@ -130,12 +129,9 @@
   void InitializeMojomSynthesisIfNeeded();
 
   HeapMojoReceiver<mojom::blink::SpeechSynthesisVoiceListObserver,
-                   SpeechSynthesis,
-                   HeapMojoWrapperMode::kForceWithoutContextObserver>
+                   SpeechSynthesis>
       receiver_;
-  HeapMojoRemote<mojom::blink::SpeechSynthesis,
-                 HeapMojoWrapperMode::kForceWithoutContextObserver>
-      mojom_synthesis_;
+  HeapMojoRemote<mojom::blink::SpeechSynthesis> mojom_synthesis_;
   HeapVector<Member<SpeechSynthesisVoice>> voice_list_;
   HeapDeque<Member<SpeechSynthesisUtterance>> utterance_queue_;
   bool is_paused_ = false;
diff --git a/third_party/blink/renderer/platform/bindings/dom_wrapper_world.cc b/third_party/blink/renderer/platform/bindings/dom_wrapper_world.cc
index bd63794..99693ac 100644
--- a/third_party/blink/renderer/platform/bindings/dom_wrapper_world.cc
+++ b/third_party/blink/renderer/platform/bindings/dom_wrapper_world.cc
@@ -156,11 +156,15 @@
   return map;
 }
 
-SecurityOrigin* DOMWrapperWorld::IsolatedWorldSecurityOrigin() {
+scoped_refptr<SecurityOrigin> DOMWrapperWorld::IsolatedWorldSecurityOrigin(
+    const base::UnguessableToken& cluster_id) {
   DCHECK(this->IsIsolatedWorld());
   IsolatedWorldSecurityOriginMap& origins = IsolatedWorldSecurityOrigins();
   IsolatedWorldSecurityOriginMap::iterator it = origins.find(GetWorldId());
-  return it == origins.end() ? nullptr : it->value.get();
+  if (it == origins.end())
+    return nullptr;
+
+  return it->value->GetOriginForAgentCluster(cluster_id);
 }
 
 void DOMWrapperWorld::SetIsolatedWorldSecurityOrigin(
diff --git a/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h b/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h
index 571e3f6..0cfb818 100644
--- a/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h
+++ b/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h
@@ -44,6 +44,10 @@
 #include "third_party/blink/renderer/platform/wtf/ref_counted.h"
 #include "v8/include/v8.h"
 
+namespace base {
+class UnguessableToken;
+}  // namespace base
+
 namespace blink {
 
 class DOMDataStore;
@@ -129,7 +133,11 @@
   static void SetIsolatedWorldSecurityOrigin(
       int32_t world_id,
       scoped_refptr<SecurityOrigin> security_origin);
-  SecurityOrigin* IsolatedWorldSecurityOrigin();
+
+  // Returns the security origin for the given world with the given
+  // |cluster_id|.
+  scoped_refptr<SecurityOrigin> IsolatedWorldSecurityOrigin(
+      const base::UnguessableToken& cluster_id);
 
   static bool HasWrapperInAnyWorldInMainThread(ScriptWrappable*);
 
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-features=OutOfBlinkCors b/third_party/blink/web_tests/FlagExpectations/disable-features=OutOfBlinkCors
index c2d1369..4e6e2076 100644
--- a/third_party/blink/web_tests/FlagExpectations/disable-features=OutOfBlinkCors
+++ b/third_party/blink/web_tests/FlagExpectations/disable-features=OutOfBlinkCors
@@ -98,3 +98,5 @@
 crbug.com/688906 virtual/omt-worker-fetch/external/wpt/fetch/api/basic/request-upload.any.worker.html [ Failure ]
 crbug.com/688906 external/wpt/service-workers/service-worker/fetch-event.https.html [ Failure ]
 
+# Subresource WBN is only supported with OOR-CORS.
+crbug.com/1082020 virtual/subresource-web-bundles/external/wpt/web-bundle/subresource-loading/subresource-loading-from-web-bundle.tentative.html [ Failure ]
diff --git a/third_party/blink/web_tests/css3/selectors3/html/css3-modsel-23.html b/third_party/blink/web_tests/css3/selectors3/html/css3-modsel-23.html
deleted file mode 100644
index 62ce1946..0000000
--- a/third_party/blink/web_tests/css3/selectors3/html/css3-modsel-23.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
-<html>
- <head>
-  <title>:enabled pseudo-class</title>
-  <style type="text/css">button { background-color : red }
-input { background-color : red }
-button:enabled { background-color : lime }
-input:enabled { background-color : lime }</style>
-  <link rel="first" href="css3-modsel-1.html" title="Groups of selectors">
-  <link rel="prev" href="css3-modsel-22.html" title=":lang() pseudo-class">
-  <link rel="next" href="css3-modsel-24.html" title=":disabled pseudo-class">
-  <link rel="last" href="css3-modsel-d4.html" title="Dynamic updating of :first-child and :last-child">
-  <link rel="up" href="./index.html">
-  <link rel="top" href="../../index.html">
- </head>
- <body>
-<p>
- <button>A button (enabled) with green background</button>
- <br>
- <input type="text" size="36" value="a text area (enabled) with green background">
-</p>
-</body>
-</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/css3/selectors3/html/css3-modsel-24.html b/third_party/blink/web_tests/css3/selectors3/html/css3-modsel-24.html
deleted file mode 100644
index 67420fc0..0000000
--- a/third_party/blink/web_tests/css3/selectors3/html/css3-modsel-24.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
-<html>
- <head>
-  <title>:disabled pseudo-class</title>
-  <style type="text/css">button { background-color : red }
-input { background-color : red }
-button:disabled { background-color : lime }
-input:disabled { background-color : lime }</style>
-  <link rel="first" href="css3-modsel-1.html" title="Groups of selectors">
-  <link rel="prev" href="css3-modsel-23.html" title=":enabled pseudo-class">
-  <link rel="next" href="css3-modsel-25.html" title=":checked pseudo-class">
-  <link rel="last" href="css3-modsel-d4.html" title="Dynamic updating of :first-child and :last-child">
-  <link rel="up" href="./index.html">
-  <link rel="top" href="../../index.html">
- </head>
- <body>
-<p>
- <button disabled="disabled">A button (disabled) with green background</button>
- <br>
- <input disabled="disabled" type="text" size="36" value="a text area (disabled) with green background">
-</p>
-</body>
-</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/css3/selectors3/html/css3-modsel-68.html b/third_party/blink/web_tests/css3/selectors3/html/css3-modsel-68.html
deleted file mode 100644
index 70118fa..0000000
--- a/third_party/blink/web_tests/css3/selectors3/html/css3-modsel-68.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
-<html>
- <head>
-  <title>NEGATED :enabled pseudo-class</title>
-  <style type="text/css">button { background-color : red }
-input { background-color : red }
-button:not(:enabled) { background-color : lime }
-input:not(:enabled)  { background-color : lime }</style>
-  <link rel="first" href="css3-modsel-1.html" title="Groups of selectors">
-  <link rel="prev" href="css3-modsel-67.html" title="NEGATED :lang() pseudo-class">
-  <link rel="next" href="css3-modsel-69.html" title="NEGATED :disabled pseudo-class">
-  <link rel="last" href="css3-modsel-d4.html" title="Dynamic updating of :first-child and :last-child">
-  <link rel="up" href="./index.html">
-  <link rel="top" href="../../index.html">
- </head>
- <body>
-<p>
- <button disabled="disabled">A button (disabled) with green background</button>
- <br>
- <input disabled="disabled" type="text" size="36" value="a text area (disabled) with green background">
-</p>
-</body>
-</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/css3/selectors3/html/css3-modsel-69.html b/third_party/blink/web_tests/css3/selectors3/html/css3-modsel-69.html
deleted file mode 100644
index 1760324a..0000000
--- a/third_party/blink/web_tests/css3/selectors3/html/css3-modsel-69.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
-<html>
- <head>
-  <title>NEGATED :disabled pseudo-class</title>
-  <style type="text/css">button { background-color : red }
-input { background-color : red }
-button:not(:disabled) { background-color : lime }
-input:not(:disabled) { background-color : lime }</style>
-  <link rel="first" href="css3-modsel-1.html" title="Groups of selectors">
-  <link rel="prev" href="css3-modsel-68.html" title="NEGATED :enabled pseudo-class">
-  <link rel="next" href="css3-modsel-70.html" title="NEGATED :checked pseudo-class">
-  <link rel="last" href="css3-modsel-d4.html" title="Dynamic updating of :first-child and :last-child">
-  <link rel="up" href="./index.html">
-  <link rel="top" href="../../index.html">
- </head>
- <body>
-<p>
- <button>A button (enabled) with green background</button>
- <br>
- <input type="text" size="36" value="a text area (enabled) with green background">
-</p>
-</body>
-</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/css3/selectors3/xhtml/css3-modsel-23.xml b/third_party/blink/web_tests/css3/selectors3/xhtml/css3-modsel-23.xml
deleted file mode 100644
index 14ce6ee..0000000
--- a/third_party/blink/web_tests/css3/selectors3/xhtml/css3-modsel-23.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
-  <title>:enabled pseudo-class</title>
-  <style type="text/css"><![CDATA[button { background-color : red }
-input { background-color : red }
-button:enabled { background-color : lime }
-input:enabled { background-color : lime }]]></style>
-  <link rel="first" href="css3-modsel-1.xml" title="Groups of selectors"/>
-  <link rel="prev" href="css3-modsel-22.xml" title=":lang() pseudo-class"/>
-  <link rel="next" href="css3-modsel-24.xml" title=":disabled pseudo-class"/>
-  <link rel="last" href="css3-modsel-d4.xml" title="Dynamic updating of :first-child and :last-child"/>
-  <link rel="up" href="./index.html"/>
-  <link rel="top" href="../../index.html"/>
- </head>
- <body>
-<p>
- <button>A button (enabled) with green background</button>
- <br></br>
- <input type="text" size="36" value="a text area (enabled) with green background"></input>
-</p>
-</body>
-</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/css3/selectors3/xhtml/css3-modsel-24.xml b/third_party/blink/web_tests/css3/selectors3/xhtml/css3-modsel-24.xml
deleted file mode 100644
index 226517e..0000000
--- a/third_party/blink/web_tests/css3/selectors3/xhtml/css3-modsel-24.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
-  <title>:disabled pseudo-class</title>
-  <style type="text/css"><![CDATA[button { background-color : red }
-input { background-color : red }
-button:disabled { background-color : lime }
-input:disabled { background-color : lime }]]></style>
-  <link rel="first" href="css3-modsel-1.xml" title="Groups of selectors"/>
-  <link rel="prev" href="css3-modsel-23.xml" title=":enabled pseudo-class"/>
-  <link rel="next" href="css3-modsel-25.xml" title=":checked pseudo-class"/>
-  <link rel="last" href="css3-modsel-d4.xml" title="Dynamic updating of :first-child and :last-child"/>
-  <link rel="up" href="./index.html"/>
-  <link rel="top" href="../../index.html"/>
- </head>
- <body>
-<p>
- <button disabled="disabled">A button (disabled) with green background</button>
- <br></br>
- <input disabled="disabled" type="text" size="36" value="a text area (disabled) with green background"></input>
-</p>
-</body>
-</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/css3/selectors3/xhtml/css3-modsel-68.xml b/third_party/blink/web_tests/css3/selectors3/xhtml/css3-modsel-68.xml
deleted file mode 100644
index 45741ceb..0000000
--- a/third_party/blink/web_tests/css3/selectors3/xhtml/css3-modsel-68.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
-  <title>NEGATED :enabled pseudo-class</title>
-  <style type="text/css"><![CDATA[button { background-color : red }
-input { background-color : red }
-button:not(:enabled) { background-color : lime }
-input:not(:enabled)  { background-color : lime }]]></style>
-  <link rel="first" href="css3-modsel-1.xml" title="Groups of selectors"/>
-  <link rel="prev" href="css3-modsel-67.xml" title="NEGATED :lang() pseudo-class"/>
-  <link rel="next" href="css3-modsel-69.xml" title="NEGATED :disabled pseudo-class"/>
-  <link rel="last" href="css3-modsel-d4.xml" title="Dynamic updating of :first-child and :last-child"/>
-  <link rel="up" href="./index.html"/>
-  <link rel="top" href="../../index.html"/>
- </head>
- <body>
-<p>
- <button disabled="disabled">A button (disabled) with green background</button>
- <br></br>
- <input disabled="disabled" type="text" size="36" value="a text area (disabled) with green background"></input>
-</p>
-</body>
-</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/css3/selectors3/xhtml/css3-modsel-69.xml b/third_party/blink/web_tests/css3/selectors3/xhtml/css3-modsel-69.xml
deleted file mode 100644
index 92d7116..0000000
--- a/third_party/blink/web_tests/css3/selectors3/xhtml/css3-modsel-69.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
-  <title>NEGATED :disabled pseudo-class</title>
-  <style type="text/css"><![CDATA[button { background-color : red }
-input { background-color : red }
-button:not(:disabled) { background-color : lime }
-input:not(:disabled) { background-color : lime }]]></style>
-  <link rel="first" href="css3-modsel-1.xml" title="Groups of selectors"/>
-  <link rel="prev" href="css3-modsel-68.xml" title="NEGATED :enabled pseudo-class"/>
-  <link rel="next" href="css3-modsel-70.xml" title="NEGATED :checked pseudo-class"/>
-  <link rel="last" href="css3-modsel-d4.xml" title="Dynamic updating of :first-child and :last-child"/>
-  <link rel="up" href="./index.html"/>
-  <link rel="top" href="../../index.html"/>
- </head>
- <body>
-<p>
- <button>A button (enabled) with green background</button>
- <br></br>
- <input type="text" size="36" value="a text area (enabled) with green background"></input>
-</p>
-</body>
-</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-23.css b/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-23.css
deleted file mode 100644
index ebf9dd1..0000000
--- a/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-23.css
+++ /dev/null
@@ -1,4 +0,0 @@
-button { background-color : red }
-input { background-color : red }
-button:enabled { background-color : lime }
-input:enabled { background-color : lime }
\ No newline at end of file
diff --git a/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-23.xml b/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-23.xml
deleted file mode 100644
index 55fdffb..0000000
--- a/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-23.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml-stylesheet href="css3-modsel-23.css" type="text/css"?>
-<test>
-<p xmlns="http://www.w3.org/1999/xhtml">
- <button>A button (enabled) with green background</button>
- <br></br>
- <input type="text" size="36" value="a text area (enabled) with green background"></input>
-</p>
-</test>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-24.css b/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-24.css
deleted file mode 100644
index 9a0d1f5..0000000
--- a/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-24.css
+++ /dev/null
@@ -1,4 +0,0 @@
-button { background-color : red }
-input { background-color : red }
-button:disabled { background-color : lime }
-input:disabled { background-color : lime }
\ No newline at end of file
diff --git a/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-24.xml b/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-24.xml
deleted file mode 100644
index f276f4e..0000000
--- a/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-24.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml-stylesheet href="css3-modsel-24.css" type="text/css"?>
-<test>
-<p xmlns="http://www.w3.org/1999/xhtml">
- <button disabled="disabled">A button (disabled) with green background</button>
- <br></br>
- <input disabled="disabled" type="text" size="36" value="a text area (disabled) with green background"></input>
-</p>
-</test>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-68.css b/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-68.css
deleted file mode 100644
index 7ab9632..0000000
--- a/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-68.css
+++ /dev/null
@@ -1,4 +0,0 @@
-button { background-color : red }
-input { background-color : red }
-button:not(:enabled) { background-color : lime }
-input:not(:enabled)  { background-color : lime }
\ No newline at end of file
diff --git a/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-68.xml b/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-68.xml
deleted file mode 100644
index 442d39612..0000000
--- a/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-68.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml-stylesheet href="css3-modsel-68.css" type="text/css"?>
-<test>
-<p xmlns="http://www.w3.org/1999/xhtml">
- <button disabled="disabled">A button (disabled) with green background</button>
- <br></br>
- <input disabled="disabled" type="text" size="36" value="a text area (disabled) with green background"></input>
-</p>
-</test>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-69.css b/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-69.css
deleted file mode 100644
index 39108ae..0000000
--- a/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-69.css
+++ /dev/null
@@ -1,4 +0,0 @@
-button { background-color : red }
-input { background-color : red }
-button:not(:disabled) { background-color : lime }
-input:not(:disabled) { background-color : lime }
\ No newline at end of file
diff --git a/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-69.xml b/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-69.xml
deleted file mode 100644
index 9a5fcd05..0000000
--- a/third_party/blink/web_tests/css3/selectors3/xml/css3-modsel-69.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml-stylesheet href="css3-modsel-69.css" type="text/css"?>
-<test>
-<p xmlns="http://www.w3.org/1999/xhtml">
- <button>A button (enabled) with green background</button>
- <br></br>
- <input type="text" size="36" value="a text area (enabled) with green background"></input>
-</p>
-</test>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/old-tests/css3-modsel-23.xml b/third_party/blink/web_tests/external/wpt/css/selectors/old-tests/css3-modsel-23.xml
deleted file mode 100644
index 663ec09e..0000000
--- a/third_party/blink/web_tests/external/wpt/css/selectors/old-tests/css3-modsel-23.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
-  <title>:enabled pseudo-class</title>
-  <style type="text/css"><![CDATA[button { background-color : red }
-input { background-color : red }
-button:enabled { background-color : lime }
-input:enabled { background-color : lime }]]></style>
-  <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
-  <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
-  <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
-  <meta name="flags" content="" />
- </head>
- <body>
-<p>
- <button>A button (enabled) with green background</button>
- <br></br>
- <input type="text" size="36" value="a text area (enabled) with green background"></input>
-</p>
-</body>
-</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/old-tests/css3-modsel-24.xml b/third_party/blink/web_tests/external/wpt/css/selectors/old-tests/css3-modsel-24.xml
deleted file mode 100644
index d20a011..0000000
--- a/third_party/blink/web_tests/external/wpt/css/selectors/old-tests/css3-modsel-24.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
-  <title>:disabled pseudo-class</title>
-  <style type="text/css"><![CDATA[button { background-color : red }
-input { background-color : red }
-button:disabled { background-color : lime }
-input:disabled { background-color : lime }]]></style>
-  <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
-  <link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
-  <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
-  <meta name="flags" content="" />
- </head>
- <body>
-<p>
- <button disabled="disabled">A button (disabled) with green background</button>
- <br></br>
- <input disabled="disabled" type="text" size="36" value="a text area (disabled) with green background"></input>
-</p>
-</body>
-</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/old-tests/css3-modsel-68.xml b/third_party/blink/web_tests/external/wpt/css/selectors/old-tests/css3-modsel-68.xml
deleted file mode 100644
index 99c28261..0000000
--- a/third_party/blink/web_tests/external/wpt/css/selectors/old-tests/css3-modsel-68.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
-  <title>NEGATED :enabled pseudo-class</title>
-  <style type="text/css"><![CDATA[button { background-color : red }
-input { background-color : red }
-button:not(:enabled) { background-color : lime }
-input:not(:enabled)  { background-color : lime }]]></style>
-  <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
-  <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
-  <meta name="flags" content="" />
- </head>
- <body>
-<p>
- <button disabled="disabled">A button (disabled) with green background</button>
- <br></br>
- <input disabled="disabled" type="text" size="36" value="a text area (disabled) with green background"></input>
-</p>
-</body>
-</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/old-tests/css3-modsel-69.xml b/third_party/blink/web_tests/external/wpt/css/selectors/old-tests/css3-modsel-69.xml
deleted file mode 100644
index 3da2a7f4..0000000
--- a/third_party/blink/web_tests/external/wpt/css/selectors/old-tests/css3-modsel-69.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
-  <title>NEGATED :disabled pseudo-class</title>
-  <style type="text/css"><![CDATA[button { background-color : red }
-input { background-color : red }
-button:not(:disabled) { background-color : lime }
-input:not(:disabled) { background-color : lime }]]></style>
-  <link rel="author" title="Daniel Glazman" href="http://glazman.org/"/>
-  <link rel="help" href="https://www.w3.org/TR/css3-selectors/#selectors"/> <!-- bogus link to make sure it gets found -->
-  <meta name="flags" content="" />
- </head>
- <body>
-<p>
- <button>A button (enabled) with green background</button>
- <br></br>
- <input type="text" size="36" value="a text area (enabled) with green background"></input>
-</p>
-</body>
-</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/pseudo-enabled-disabled.html b/third_party/blink/web_tests/external/wpt/css/selectors/pseudo-enabled-disabled.html
new file mode 100644
index 0000000..521767d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/selectors/pseudo-enabled-disabled.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#enableddisabled">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div id="container">
+<button id="button_enabled"></button>
+<button id="button_disabled" disabled></button>
+<input id="input_enabled">
+<input id="input_disabled" disabled>
+<select id="select_enabled"></select>
+<select id="select_disabled" disabled></select>
+<textarea id="textarea_enabled"></textarea>
+<textarea id="textarea_disabled" disabled></textarea>
+<span id="incapable"></span>
+</div>
+
+<script>
+test(() => {
+  const container = document.querySelector('#container');
+  const matched = container.querySelectorAll(':enabled');
+  for (let element of matched) {
+    assert_true(element.id.endsWith('_enabled'), element.id);
+  }
+}, ':enabeld should match to enabled controls');
+
+test(() => {
+  const container = document.querySelector('#container');
+  const matched = container.querySelectorAll(':disabled');
+  for (let element of matched) {
+    assert_true(element.id.endsWith('_disabled'), element.id);
+  }
+}, ':disabled should match to enabled controls');
+
+test(() => {
+  const container = document.querySelector('#container');
+  const matched = container.querySelectorAll(':not(:enabled)');
+  for (let element of matched) {
+    assert_true(element.id.endsWith('_disabled') || element.id == 'incapable', element.id);
+  }
+}, ':not(:enabeld) should match to disabled controls and non-controls');
+
+test(() => {
+  const container = document.querySelector('#container');
+  const matched = container.querySelectorAll(':not(:disabled)');
+  for (let element of matched) {
+    assert_true(element.id.endsWith('_enabled') || element.id == 'incapable', element.id);
+  }
+}, ':not(:disabled) should match to enabled controls and non-controls');
+</script>
+</body>
diff --git a/third_party/blink/web_tests/inspector-protocol/emulation/device-emulation-window-segments-expected.txt b/third_party/blink/web_tests/inspector-protocol/emulation/device-emulation-window-segments-expected.txt
new file mode 100644
index 0000000..f33d0450
--- /dev/null
+++ b/third_party/blink/web_tests/inspector-protocol/emulation/device-emulation-window-segments-expected.txt
@@ -0,0 +1,41 @@
+Tests that device emulation of window segments is propagated and powers getWindowSegments API.
+No segments:
+Main frame segments:
+1
+0 0 800 600
+Iframe segments:
+1
+0 0 800 600
+Side-by-side segments
+Main frame segments:
+2
+0 0 390 600
+410 0 390 600
+Iframe segments:
+2
+0 0 390 600
+410 0 390 600
+Unspecified display feature
+Main frame segments:
+1
+0 0 800 600
+Iframe segments:
+1
+0 0 800 600
+Stacked segments
+Main frame segments:
+2
+0 0 800 290
+0 310 800 290
+Iframe segments:
+2
+0 0 800 290
+0 310 800 290
+Emulation disabled
+Main frame segments:
+1
+0 0 800 600
+Iframe segments:
+1
+0 0 800 600
+
diff --git a/third_party/blink/web_tests/inspector-protocol/emulation/device-emulation-window-segments.js b/third_party/blink/web_tests/inspector-protocol/emulation/device-emulation-window-segments.js
new file mode 100644
index 0000000..a7903af
--- /dev/null
+++ b/third_party/blink/web_tests/inspector-protocol/emulation/device-emulation-window-segments.js
@@ -0,0 +1,52 @@
+(async function(testRunner) {
+  let {page, session, dp} = await testRunner.startBlank('Tests that device emulation of window segments is propagated and powers getWindowSegments API.');
+
+  let deviceMetrics = {
+    width: 800,
+    height: 600,
+    deviceScaleFactor: 2,
+    mobile: false,
+    fitWindow: false,
+    scale: 2,
+    screenWidth: 1200,
+    screenHeight: 1000,
+    positionX: 110,
+    positionY: 120,
+  };
+
+  await session.protocol.Emulation.setDeviceMetricsOverride(deviceMetrics);
+
+  await session.navigate('../resources/device-emulation.html');
+
+  testRunner.log("No segments:");
+  testRunner.log(await session.evaluate(`dumpWindowSegments()`));
+
+  testRunner.log("Side-by-side segments");
+  deviceMetrics.displayFeature = {
+      orientation: "vertical",
+      offset: 390,
+      maskLength: 20
+  };
+  await session.protocol.Emulation.setDeviceMetricsOverride(deviceMetrics);
+  testRunner.log(await session.evaluate(`dumpWindowSegments()`));
+
+  testRunner.log("Unspecified display feature");
+  delete deviceMetrics.displayFeature;
+  await session.protocol.Emulation.setDeviceMetricsOverride(deviceMetrics);
+  testRunner.log(await session.evaluate(`dumpWindowSegments()`));
+
+  testRunner.log("Stacked segments");
+  deviceMetrics.displayFeature = {
+      orientation: "horizontal",
+      offset: 290,
+      maskLength: 20
+  };
+  await session.protocol.Emulation.setDeviceMetricsOverride(deviceMetrics);
+  testRunner.log(await session.evaluate(`dumpWindowSegments()`));
+
+  testRunner.log("Emulation disabled");
+  await dp.Emulation.clearDeviceMetricsOverride();
+  testRunner.log(await session.evaluate(`dumpWindowSegments()`));
+
+  testRunner.completeTest();
+})
diff --git a/third_party/blink/web_tests/inspector-protocol/resources/device-emulation.html b/third_party/blink/web_tests/inspector-protocol/resources/device-emulation.html
index d36e0b8..f01cd3a4 100644
--- a/third_party/blink/web_tests/inspector-protocol/resources/device-emulation.html
+++ b/third_party/blink/web_tests/inspector-protocol/resources/device-emulation.html
@@ -111,6 +111,25 @@
     return results.join("\n");
 }
 
+function dumpWindowSegments() {
+    let output = [];
+    output.push("Main frame segments:");
+    output = output.concat(dumpWindowSegmentsForWindow(this));
+    output.push("Iframe segments:");
+    output = output.concat(dumpWindowSegmentsForWindow(window.frames[0]));
+    return output.join("\n");
+}
+
+function dumpWindowSegmentsForWindow(window_object) {
+    let output = [];
+    output.push(window_object.getWindowSegments().length);
+    window_object.getWindowSegments().forEach((segment) => {
+        let segmentString = `${segment.x} ${segment.y} ${segment.width} ${segment.height}`;
+        output.push(segmentString);
+    });
+    return output;
+}
+
 function testJS(expr, unit)
 {
     if (unit === undefined)
@@ -209,5 +228,6 @@
 </head>
 
 <body>
+<iframe src="about:blank"></iframe>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/platform/linux/css3/selectors3/html/css3-modsel-23-expected.png b/third_party/blink/web_tests/platform/linux/css3/selectors3/html/css3-modsel-23-expected.png
deleted file mode 100644
index ee296bb..0000000
--- a/third_party/blink/web_tests/platform/linux/css3/selectors3/html/css3-modsel-23-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/css3/selectors3/html/css3-modsel-24-expected.png b/third_party/blink/web_tests/platform/linux/css3/selectors3/html/css3-modsel-24-expected.png
deleted file mode 100644
index f6e4663a..0000000
--- a/third_party/blink/web_tests/platform/linux/css3/selectors3/html/css3-modsel-24-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/css3/selectors3/html/css3-modsel-68-expected.png b/third_party/blink/web_tests/platform/linux/css3/selectors3/html/css3-modsel-68-expected.png
deleted file mode 100644
index f6e4663a..0000000
--- a/third_party/blink/web_tests/platform/linux/css3/selectors3/html/css3-modsel-68-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/css3/selectors3/html/css3-modsel-69-expected.png b/third_party/blink/web_tests/platform/linux/css3/selectors3/html/css3-modsel-69-expected.png
deleted file mode 100644
index ee296bb..0000000
--- a/third_party/blink/web_tests/platform/linux/css3/selectors3/html/css3-modsel-69-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/css3/selectors3/xhtml/css3-modsel-23-expected.png b/third_party/blink/web_tests/platform/linux/css3/selectors3/xhtml/css3-modsel-23-expected.png
deleted file mode 100644
index ee296bb..0000000
--- a/third_party/blink/web_tests/platform/linux/css3/selectors3/xhtml/css3-modsel-23-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/css3/selectors3/xhtml/css3-modsel-24-expected.png b/third_party/blink/web_tests/platform/linux/css3/selectors3/xhtml/css3-modsel-24-expected.png
deleted file mode 100644
index f6e4663a..0000000
--- a/third_party/blink/web_tests/platform/linux/css3/selectors3/xhtml/css3-modsel-24-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/css3/selectors3/xhtml/css3-modsel-68-expected.png b/third_party/blink/web_tests/platform/linux/css3/selectors3/xhtml/css3-modsel-68-expected.png
deleted file mode 100644
index f6e4663a..0000000
--- a/third_party/blink/web_tests/platform/linux/css3/selectors3/xhtml/css3-modsel-68-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/css3/selectors3/xhtml/css3-modsel-69-expected.png b/third_party/blink/web_tests/platform/linux/css3/selectors3/xhtml/css3-modsel-69-expected.png
deleted file mode 100644
index ee296bb..0000000
--- a/third_party/blink/web_tests/platform/linux/css3/selectors3/xhtml/css3-modsel-69-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/css3/selectors3/xml/css3-modsel-23-expected.png b/third_party/blink/web_tests/platform/linux/css3/selectors3/xml/css3-modsel-23-expected.png
deleted file mode 100644
index f1aa8ed..0000000
--- a/third_party/blink/web_tests/platform/linux/css3/selectors3/xml/css3-modsel-23-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/css3/selectors3/xml/css3-modsel-24-expected.png b/third_party/blink/web_tests/platform/linux/css3/selectors3/xml/css3-modsel-24-expected.png
deleted file mode 100644
index 4b1f534a..0000000
--- a/third_party/blink/web_tests/platform/linux/css3/selectors3/xml/css3-modsel-24-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/css3/selectors3/xml/css3-modsel-68-expected.png b/third_party/blink/web_tests/platform/linux/css3/selectors3/xml/css3-modsel-68-expected.png
deleted file mode 100644
index 4b1f534a..0000000
--- a/third_party/blink/web_tests/platform/linux/css3/selectors3/xml/css3-modsel-68-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/css3/selectors3/xml/css3-modsel-69-expected.png b/third_party/blink/web_tests/platform/linux/css3/selectors3/xml/css3-modsel-69-expected.png
deleted file mode 100644
index f1aa8ed..0000000
--- a/third_party/blink/web_tests/platform/linux/css3/selectors3/xml/css3-modsel-69-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/css3/selectors3/html/css3-modsel-23-expected.png b/third_party/blink/web_tests/platform/mac/css3/selectors3/html/css3-modsel-23-expected.png
deleted file mode 100644
index 066b2e4..0000000
--- a/third_party/blink/web_tests/platform/mac/css3/selectors3/html/css3-modsel-23-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/css3/selectors3/html/css3-modsel-24-expected.png b/third_party/blink/web_tests/platform/mac/css3/selectors3/html/css3-modsel-24-expected.png
deleted file mode 100644
index c1f904d..0000000
--- a/third_party/blink/web_tests/platform/mac/css3/selectors3/html/css3-modsel-24-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/css3/selectors3/html/css3-modsel-68-expected.png b/third_party/blink/web_tests/platform/mac/css3/selectors3/html/css3-modsel-68-expected.png
deleted file mode 100644
index c1f904d..0000000
--- a/third_party/blink/web_tests/platform/mac/css3/selectors3/html/css3-modsel-68-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/css3/selectors3/html/css3-modsel-69-expected.png b/third_party/blink/web_tests/platform/mac/css3/selectors3/html/css3-modsel-69-expected.png
deleted file mode 100644
index 066b2e4..0000000
--- a/third_party/blink/web_tests/platform/mac/css3/selectors3/html/css3-modsel-69-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/css3/selectors3/xhtml/css3-modsel-23-expected.png b/third_party/blink/web_tests/platform/mac/css3/selectors3/xhtml/css3-modsel-23-expected.png
deleted file mode 100644
index 066b2e4..0000000
--- a/third_party/blink/web_tests/platform/mac/css3/selectors3/xhtml/css3-modsel-23-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/css3/selectors3/xhtml/css3-modsel-24-expected.png b/third_party/blink/web_tests/platform/mac/css3/selectors3/xhtml/css3-modsel-24-expected.png
deleted file mode 100644
index c1f904d..0000000
--- a/third_party/blink/web_tests/platform/mac/css3/selectors3/xhtml/css3-modsel-24-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/css3/selectors3/xhtml/css3-modsel-68-expected.png b/third_party/blink/web_tests/platform/mac/css3/selectors3/xhtml/css3-modsel-68-expected.png
deleted file mode 100644
index c1f904d..0000000
--- a/third_party/blink/web_tests/platform/mac/css3/selectors3/xhtml/css3-modsel-68-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/css3/selectors3/xhtml/css3-modsel-69-expected.png b/third_party/blink/web_tests/platform/mac/css3/selectors3/xhtml/css3-modsel-69-expected.png
deleted file mode 100644
index 066b2e4..0000000
--- a/third_party/blink/web_tests/platform/mac/css3/selectors3/xhtml/css3-modsel-69-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/css3/selectors3/xml/css3-modsel-23-expected.png b/third_party/blink/web_tests/platform/mac/css3/selectors3/xml/css3-modsel-23-expected.png
deleted file mode 100644
index bb58fd1..0000000
--- a/third_party/blink/web_tests/platform/mac/css3/selectors3/xml/css3-modsel-23-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/css3/selectors3/xml/css3-modsel-24-expected.png b/third_party/blink/web_tests/platform/mac/css3/selectors3/xml/css3-modsel-24-expected.png
deleted file mode 100644
index b1423c3..0000000
--- a/third_party/blink/web_tests/platform/mac/css3/selectors3/xml/css3-modsel-24-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/css3/selectors3/xml/css3-modsel-68-expected.png b/third_party/blink/web_tests/platform/mac/css3/selectors3/xml/css3-modsel-68-expected.png
deleted file mode 100644
index b1423c3..0000000
--- a/third_party/blink/web_tests/platform/mac/css3/selectors3/xml/css3-modsel-68-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/css3/selectors3/xml/css3-modsel-69-expected.png b/third_party/blink/web_tests/platform/mac/css3/selectors3/xml/css3-modsel-69-expected.png
deleted file mode 100644
index bb58fd1..0000000
--- a/third_party/blink/web_tests/platform/mac/css3/selectors3/xml/css3-modsel-69-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css3/selectors3/html/css3-modsel-23-expected.png b/third_party/blink/web_tests/platform/win/css3/selectors3/html/css3-modsel-23-expected.png
deleted file mode 100644
index 9feeef77..0000000
--- a/third_party/blink/web_tests/platform/win/css3/selectors3/html/css3-modsel-23-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css3/selectors3/html/css3-modsel-24-expected.png b/third_party/blink/web_tests/platform/win/css3/selectors3/html/css3-modsel-24-expected.png
deleted file mode 100644
index 1040346..0000000
--- a/third_party/blink/web_tests/platform/win/css3/selectors3/html/css3-modsel-24-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css3/selectors3/html/css3-modsel-68-expected.png b/third_party/blink/web_tests/platform/win/css3/selectors3/html/css3-modsel-68-expected.png
deleted file mode 100644
index 1040346..0000000
--- a/third_party/blink/web_tests/platform/win/css3/selectors3/html/css3-modsel-68-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css3/selectors3/html/css3-modsel-69-expected.png b/third_party/blink/web_tests/platform/win/css3/selectors3/html/css3-modsel-69-expected.png
deleted file mode 100644
index 9feeef77..0000000
--- a/third_party/blink/web_tests/platform/win/css3/selectors3/html/css3-modsel-69-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css3/selectors3/xhtml/css3-modsel-23-expected.png b/third_party/blink/web_tests/platform/win/css3/selectors3/xhtml/css3-modsel-23-expected.png
deleted file mode 100644
index 9feeef77..0000000
--- a/third_party/blink/web_tests/platform/win/css3/selectors3/xhtml/css3-modsel-23-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css3/selectors3/xhtml/css3-modsel-24-expected.png b/third_party/blink/web_tests/platform/win/css3/selectors3/xhtml/css3-modsel-24-expected.png
deleted file mode 100644
index 1040346..0000000
--- a/third_party/blink/web_tests/platform/win/css3/selectors3/xhtml/css3-modsel-24-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css3/selectors3/xhtml/css3-modsel-68-expected.png b/third_party/blink/web_tests/platform/win/css3/selectors3/xhtml/css3-modsel-68-expected.png
deleted file mode 100644
index 1040346..0000000
--- a/third_party/blink/web_tests/platform/win/css3/selectors3/xhtml/css3-modsel-68-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css3/selectors3/xhtml/css3-modsel-69-expected.png b/third_party/blink/web_tests/platform/win/css3/selectors3/xhtml/css3-modsel-69-expected.png
deleted file mode 100644
index 9feeef77..0000000
--- a/third_party/blink/web_tests/platform/win/css3/selectors3/xhtml/css3-modsel-69-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css3/selectors3/xml/css3-modsel-23-expected.png b/third_party/blink/web_tests/platform/win/css3/selectors3/xml/css3-modsel-23-expected.png
deleted file mode 100644
index 0b56648b..0000000
--- a/third_party/blink/web_tests/platform/win/css3/selectors3/xml/css3-modsel-23-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css3/selectors3/xml/css3-modsel-24-expected.png b/third_party/blink/web_tests/platform/win/css3/selectors3/xml/css3-modsel-24-expected.png
deleted file mode 100644
index f2210a10..0000000
--- a/third_party/blink/web_tests/platform/win/css3/selectors3/xml/css3-modsel-24-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css3/selectors3/xml/css3-modsel-68-expected.png b/third_party/blink/web_tests/platform/win/css3/selectors3/xml/css3-modsel-68-expected.png
deleted file mode 100644
index f2210a10..0000000
--- a/third_party/blink/web_tests/platform/win/css3/selectors3/xml/css3-modsel-68-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/css3/selectors3/xml/css3-modsel-69-expected.png b/third_party/blink/web_tests/platform/win/css3/selectors3/xml/css3-modsel-69-expected.png
deleted file mode 100644
index 0b56648b..0000000
--- a/third_party/blink/web_tests/platform/win/css3/selectors3/xml/css3-modsel-69-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/libgav1/README.chromium b/third_party/libgav1/README.chromium
index a24df95..dd7aca0c 100644
--- a/third_party/libgav1/README.chromium
+++ b/third_party/libgav1/README.chromium
@@ -2,9 +2,9 @@
 Short Name: libgav1
 URL: https://chromium.googlesource.com/codecs/libgav1/
 Version: 0
-Date: Friday June 26 2020
+Date: Tuesday July 14 2020
 Branch: master
-Commit: ba8dd2919fcaf65646858a6d7fd5e75ed4946cb1
+Commit: e46493b9148e0d1e63f55b5890bff503822616e5
 License: Apache 2.0
 License File: libgav1/LICENSE
 Security Critical: yes
diff --git a/third_party/nearby/BUILD.gn b/third_party/nearby/BUILD.gn
index 4b30d8c..5b08764e 100644
--- a/third_party/nearby/BUILD.gn
+++ b/third_party/nearby/BUILD.gn
@@ -360,7 +360,6 @@
 }
 
 # src/cpp/core_v2/internal/mediums
-# TODO(himanshujaju) - Add bloom filter after resolving smhasher dependency.
 source_set("core_v2_internal_mediums") {
   public_configs = [ ":nearby_include_config" ]
   sources = [
@@ -368,6 +367,7 @@
     "src/cpp/core_v2/internal/mediums/ble_advertisement.cc",
     "src/cpp/core_v2/internal/mediums/ble_advertisement_header.cc",
     "src/cpp/core_v2/internal/mediums/ble_packet.cc",
+    "src/cpp/core_v2/internal/mediums/bloom_filter.cc",
     "src/cpp/core_v2/internal/mediums/bluetooth_classic.cc",
     "src/cpp/core_v2/internal/mediums/bluetooth_radio.cc",
     "src/cpp/core_v2/internal/mediums/mediums.cc",
@@ -381,6 +381,7 @@
     "src/cpp/core_v2/internal/mediums/ble_advertisement_header.h",
     "src/cpp/core_v2/internal/mediums/ble_packet.h",
     "src/cpp/core_v2/internal/mediums/ble_peripheral.h",
+    "src/cpp/core_v2/internal/mediums/bloom_filter.h",
     "src/cpp/core_v2/internal/mediums/bluetooth_classic.h",
     "src/cpp/core_v2/internal/mediums/bluetooth_radio.h",
     "src/cpp/core_v2/internal/mediums/lost_entity_tracker.h",
diff --git a/third_party/nearby/README.chromium b/third_party/nearby/README.chromium
index f72f227..610e1ba 100644
--- a/third_party/nearby/README.chromium
+++ b/third_party/nearby/README.chromium
@@ -1,7 +1,7 @@
 Name: Nearby Connections Library
 Short Name: Nearby
 URL: https://github.com/google/nearby-connections
-Version: 31ab07b5d7183572a4250be2e0ff26a03f920e77
+Version: ae277748ce068ef1730d5104002d4324fc4ed89e
 License: Apache 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/tools/json_schema_compiler/cpp_bundle_generator.py b/tools/json_schema_compiler/cpp_bundle_generator.py
index 9d77888..9d2c0f2 100644
--- a/tools/json_schema_compiler/cpp_bundle_generator.py
+++ b/tools/json_schema_compiler/cpp_bundle_generator.py
@@ -334,6 +334,11 @@
     c.Append('#include "%s"' % (os.path.join(self._bundle._source_file_dir,
                                              'generated_schemas.h')))
     c.Append()
+    c.Append('#include <algorithm>')
+    c.Append('#include <iterator>')
+    c.Append()
+    c.Append('#include "base/stl_util.h"')
+    c.Append()
     c.Append('namespace {')
     for api in self._bundle._api_defs:
       namespace = self._bundle._model.namespaces[api.get('namespace')]
@@ -348,8 +353,9 @@
           json_content[i:i + max_length]
           for i in range(0, len(json_content), max_length)
       ]
-      c.Append('const char %s[] = R"R(%s)R";' % (_FormatNameAsConstant(
-          namespace.name), ')R" R"R('.join(segments)))
+      c.Append(
+          'constexpr char %s[] = R"R(%s)R";' %
+          (_FormatNameAsConstant(namespace.name), ')R" R"R('.join(segments)))
     c.Append('}  // namespace')
     c.Append()
     c.Concat(cpp_util.OpenNamespace(self._bundle._cpp_namespace))
@@ -363,9 +369,13 @@
     c.Append('// static')
     c.Sblock('base::StringPiece %s::Get(base::StringPiece name) {' %
              self._bundle._GenerateBundleClass('GeneratedSchemas'))
-    c.Append('static const struct {')
-    c.Append('  base::StringPiece name;')
-    c.Append('  base::StringPiece schema;')
+    c.Sblock('static constexpr struct kSchemaMapping {')
+    c.Append('const base::StringPiece name;')
+    c.Append('const base::StringPiece schema;')
+    c.Sblock('constexpr bool operator<(const kSchemaMapping& that) const {')
+    c.Append('return name < that.name;')
+    c.Eblock('}')
+    c.Eblock()
     c.Sblock('} kSchemas[] = {')
     namespaces = [self._bundle._model.namespaces[api.get('namespace')].name
                   for api in self._bundle._api_defs]
@@ -373,11 +383,18 @@
       schema_constant_name = _FormatNameAsConstant(namespace)
       c.Append('{"%s", %s},' % (namespace, schema_constant_name))
     c.Eblock('};')
-    c.Sblock('for (const auto& schema : kSchemas) {')
-    c.Sblock('if (schema.name == name)')
-    c.Append('return schema.schema;')
+    c.Append('static_assert(base::STLIsSorted(kSchemas), "|kSchemas| should be '
+             'sorted.");')
+
+    c.Sblock('auto it = std::lower_bound(std::begin(kSchemas), '
+             'std::end(kSchemas),')
+    c.Append('kSchemaMapping{name, base::StringPiece()});')
     c.Eblock()
-    c.Eblock('}')
+
+    c.Sblock('if (it != std::end(kSchemas) && it->name == name)')
+    c.Append('return it->schema;')
+    c.Eblock()
+
     c.Append('return base::StringPiece();')
     c.Eblock('}')
     c.Append()
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index da7b584..6b5a7a8 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -41608,6 +41608,7 @@
   <int value="64942701" label="OfflinePagesSvelteConcurrentLoading:disabled"/>
   <int value="66897259" label="ModalPermissionDialogView:enabled"/>
   <int value="67639499" label="stop-loading-in-background:disabled"/>
+  <int value="73436710" label="EditPasswordsInDesktopSettings:disabled"/>
   <int value="73929836" label="VrBrowsingInCustomTab:enabled"/>
   <int value="75207621" label="enable-stylus-virtual-keyboard:enabled"/>
   <int value="75237697" label="ash-enable-new-overview-ui"/>
@@ -43285,6 +43286,7 @@
   <int value="1933376478" label="IsolatePrerenders:enabled"/>
   <int value="1935405622" label="AppServiceInstanceRegistry:disabled"/>
   <int value="1936810062" label="WebVrVsyncAlign:enabled"/>
+  <int value="1936816247" label="EditPasswordsInDesktopSettings:enabled"/>
   <int value="1938279796" label="PromosOnLocalNtp:disabled"/>
   <int value="1939413645" label="enable-invalid-cert-collection"/>
   <int value="1939884866" label="web-otp-backend"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index f6f7173..0f7e54e6 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -118566,42 +118566,6 @@
   </summary>
 </histogram>
 
-<histogram name="PageLoad.Clients.Ads.AdDensity.MaxPercentByArea" units="%"
-    expires_after="2020-10-08">
-  <owner>justinmron@chromium.org</owner>
-  <owner>johnidel@chromium.org</owner>
-  <summary>
-    The page's maximum ad density by area over its lifecycle as a percent from
-    0-100. The density measurement is throttled in page load metrics propagation
-    from renderer to browser and in the ads page load metrics observer, this may
-    lead to inaccurate maximum density. Recorded at the time a page is
-    destroyed.
-  </summary>
-</histogram>
-
-<histogram name="PageLoad.Clients.Ads.AdDensity.MaxPercentByHeight" units="%"
-    expires_after="2020-10-08">
-  <owner>justinmron@chromium.org</owner>
-  <owner>johnidel@chromium.org</owner>
-  <summary>
-    The page's maximum ad density by height over its lifecycle as a percent from
-    0-100. The density measurement is throttled in page load metrics propagation
-    from renderer to browser and in the ads page load metrics observer, this may
-    lead to inaccurate maximum density. Recorded at the time a page is
-    destroyed.
-  </summary>
-</histogram>
-
-<histogram name="PageLoad.Clients.Ads.AdDensity.Recorded" units="Boolean"
-    expires_after="2020-10-08">
-  <owner>justinmron@chromium.org</owner>
-  <owner>johnidel@chromium.org</owner>
-  <summary>
-    Whether the ad density was recorded on the page for both density by area and
-    density by height. Recorded at the time a page is destroyed.
-  </summary>
-</histogram>
-
 <histogram name="PageLoad.Clients.Ads.All.Navigations.AdFrameRenavigatedToAd"
     enum="DidNavigateToAd" expires_after="2018-07-13">
   <obsolete>
@@ -124296,7 +124260,7 @@
 </histogram>
 
 <histogram name="PasswordManager.BulkCheck.CanceledCredentials"
-    units="credentials" expires_after="M86">
+    units="credentials" expires_after="2021-02-01">
   <owner>vasilii@chromium.org</owner>
   <owner>jdoerrie@chromium.org</owner>
   <summary>
@@ -124306,7 +124270,7 @@
 </histogram>
 
 <histogram name="PasswordManager.BulkCheck.CanceledTime" units="ms"
-    expires_after="M86">
+    expires_after="2021-02-01">
   <owner>vasilii@chromium.org</owner>
   <owner>jdoerrie@chromium.org</owner>
   <summary>
@@ -124315,7 +124279,7 @@
 </histogram>
 
 <histogram name="PasswordManager.BulkCheck.CheckedCredentials"
-    units="credentials" expires_after="M86">
+    units="credentials" expires_after="2021-02-01">
   <owner>vasilii@chromium.org</owner>
   <owner>jdoerrie@chromium.org</owner>
   <summary>
@@ -124325,14 +124289,14 @@
 </histogram>
 
 <histogram name="PasswordManager.BulkCheck.Error"
-    enum="PasswordLeakDetectionError" expires_after="M86">
+    enum="PasswordLeakDetectionError" expires_after="2021-02-01">
   <owner>vasilii@chromium.org</owner>
   <owner>jdoerrie@chromium.org</owner>
   <summary>Error encountered during the password bulk check.</summary>
 </histogram>
 
 <histogram name="PasswordManager.BulkCheck.LeaksFound" units="credentials"
-    expires_after="M86">
+    expires_after="2021-02-01">
   <owner>vasilii@chromium.org</owner>
   <owner>jdoerrie@chromium.org</owner>
   <summary>
@@ -124350,7 +124314,8 @@
   </summary>
 </histogram>
 
-<histogram name="PasswordManager.BulkCheck.Time" units="ms" expires_after="M86">
+<histogram name="PasswordManager.BulkCheck.Time" units="ms"
+    expires_after="2021-02-01">
   <owner>vasilii@chromium.org</owner>
   <owner>jdoerrie@chromium.org</owner>
   <summary>
@@ -124359,7 +124324,7 @@
 </histogram>
 
 <histogram name="PasswordManager.BulkCheck.TimePerCredential" units="ms"
-    expires_after="M86">
+    expires_after="2021-02-01">
   <owner>vasilii@chromium.org</owner>
   <owner>jdoerrie@chromium.org</owner>
   <summary>
@@ -124369,7 +124334,7 @@
 </histogram>
 
 <histogram name="PasswordManager.BulkCheck.UserAction"
-    enum="PasswordCheckInteraction" expires_after="M86">
+    enum="PasswordCheckInteraction" expires_after="2021-02-01">
   <owner>jdoerrie@chromium.org</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>User actions performed on the Password Check settings page.</summary>
@@ -125017,6 +124982,24 @@
   </summary>
 </histogram>
 
+<histogram name="PasswordManager.iOS.InfoBar.PasswordSave" enum="Boolean"
+    expires_after="2021-07-01">
+  <owner>djean@chromium.org</owner>
+  <owner>sczs@google.com</owner>
+  <summary>
+    This metric counts how many times the Save Password infobar is shown.
+  </summary>
+</histogram>
+
+<histogram name="PasswordManager.iOS.InfoBar.PasswordUpdate" enum="Boolean"
+    expires_after="2021-07-01">
+  <owner>djean@chromium.org</owner>
+  <owner>sczs@google.com</owner>
+  <summary>
+    This metric counts how many times the Update Password infobar is shown.
+  </summary>
+</histogram>
+
 <histogram name="PasswordManager.IsSyncPasswordHashSaved"
     enum="IsSyncPasswordHashSaved" expires_after="2021-02-01">
   <owner>vakh@chromium.org</owner>
@@ -126571,7 +126554,7 @@
 </histogram>
 
 <histogram base="true" name="PasswordManager.TotalAccountsHiRes.ByType"
-    units="units" expires_after="M86">
+    units="units" expires_after="2020-12-12">
   <owner>battre@chromium.org</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -126583,7 +126566,7 @@
 </histogram>
 
 <histogram base="true" name="PasswordManager.TotalAccountsHiRes.WithScheme"
-    units="accounts" expires_after="M86">
+    units="accounts" expires_after="2020-12-12">
   <owner>battre@chromium.org</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index ac51054..7b78668 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -345,22 +345,6 @@
       bucket (with a bucket ratio of 1.3).
     </summary>
   </metric>
-  <metric name="MaxAdDensityByArea">
-    <summary>
-      The estimated maximum density of ads on a page by area. Calculated as the
-      area of ads on the page * 100 / page area. This counts each overlapping
-      area once, it may be inaccurate due to updates and calculations being
-      throttled.
-    </summary>
-  </metric>
-  <metric name="MaxAdDensityByHeight">
-    <summary>
-      The estimated maximum density of ads on a page by height. Calculated as
-      the combined height of ads on the page * 100 / page height. This counts
-      each overlapping area once, it may be inaccurate due to updates and
-      calculations being throttled.
-    </summary>
-  </metric>
   <metric name="TotalBytes">
     <summary>
       Amount of network bytes used to load resources on the page. Includes
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 4fa13b74..9b7e8fc 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -2,15 +2,15 @@
     "trace_processor_shell": {
         "win": {
             "hash": "011aacdd55d1deab186a4c37b06f11ccc04a5e97",
-            "remote_path": "perfetto_binaries/trace_processor_shell/win/1a82e68482aacc6cdeeeab15c4d95185b49a05ac/trace_processor_shell.exe"
+            "remote_path": "perfetto_binaries/trace_processor_shell/win/c63cdce64c9e4dc5fb9fa4f820b39bac1de8553b/trace_processor_shell.exe"
         },
         "mac": {
             "hash": "dca76ba55b453f63fac42fc51946fc3d8a076b92",
-            "remote_path": "perfetto_binaries/trace_processor_shell/mac/1a82e68482aacc6cdeeeab15c4d95185b49a05ac/trace_processor_shell"
+            "remote_path": "perfetto_binaries/trace_processor_shell/mac/c63cdce64c9e4dc5fb9fa4f820b39bac1de8553b/trace_processor_shell"
         },
         "linux": {
             "hash": "066f8c275b0c6b23b36eb933b42a1e2070176a30",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/ddc86ef759d8e5f1c46324aab820427a4a9e444d/trace_processor_shell"
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/c63cdce64c9e4dc5fb9fa4f820b39bac1de8553b/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/style_variable_generator/base_generator.py b/tools/style_variable_generator/base_generator.py
index f3bcd80..2090ace 100644
--- a/tools/style_variable_generator/base_generator.py
+++ b/tools/style_variable_generator/base_generator.py
@@ -75,7 +75,10 @@
 
     def __init__(self):
         self.out_file_path = None
-        self.in_files = []
+        # A map of input filepaths to their context object.
+        self.in_file_to_context = dict()
+
+        # If specified, only generates the given mode.
         self.generate_single_mode = None
 
         # The mode that colors will fallback to when not specified in a
@@ -117,19 +120,28 @@
             raise ValueError('Error parsing color "%s": %s' % (value_obj, err))
 
     def AddJSONFileToModel(self, path):
-        self.in_files.append(path)
         try:
             with open(path, 'r') as f:
-                self.AddJSONToModel(f.read(), self.GetName())
+                return self.AddJSONToModel(f.read(), self.GetName(), path)
         except ValueError as err:
             raise ValueError('\n%s:\n    %s' % (path, err))
 
-    def AddJSONToModel(self, json_string, generator_name=None):
+    def AddJSONToModel(self, json_string, generator_name=None, in_file=None):
+        '''Adds a |json_string| with variable definitions to the model.
+
+        See *test.json5 files for a defacto format reference.
+
+        |generator_name| is used to get the generator-specific context from the
+        'options' object.
+        |in_file| is used to populate a file-to-context map.
+        '''
         # TODO(calamity): Add allow_duplicate_keys=False once pyjson5 is
         # rolled.
         data = json5.loads(json_string,
                            object_pairs_hook=collections.OrderedDict)
         generator_context = data.get('options', {}).get(generator_name, None)
+        self.in_file_to_context[in_file] = generator_context
+
         for name, value in data['colors'].items():
             if not re.match('^[a-z0-9_]+$', name):
                 raise ValueError(
@@ -138,6 +150,7 @@
 
             self.AddColor(name, value, generator_context)
 
+        return generator_context
 
     def ApplyTemplate(self, style_generator, path_to_template, params):
         loader_root_dir = path_overrides.GetFileSystemLoaderRootDirectory()
diff --git a/tools/style_variable_generator/colors_test.json5 b/tools/style_variable_generator/colors_test.json5
index 5021c97..948ac1e 100644
--- a/tools/style_variable_generator/colors_test.json5
+++ b/tools/style_variable_generator/colors_test.json5
@@ -5,12 +5,12 @@
     }
   },
   colors: {
-    default_text_color: {
+    text_color_primary: {
       light: "$google_grey_900",
       dark: "rgb(255, 255, 255)",
     },
     toggle_color: {
-      light: "rgba($default_text_color_rgb, 0.1)"
+      light: "rgba($text_color_primary_rgb, 0.1)"
     }
   },
 }
diff --git a/tools/style_variable_generator/colors_test_dark_only_expected.css b/tools/style_variable_generator/colors_test_dark_only_expected.css
index 18cc27e..cac2df9 100644
--- a/tools/style_variable_generator/colors_test_dark_only_expected.css
+++ b/tools/style_variable_generator/colors_test_dark_only_expected.css
@@ -11,10 +11,10 @@
   --google-grey-900-rgb: 32, 33, 36;
   --google-grey-900: rgb(var(--google-grey-900-rgb));
 
-  --cros-default-text-color-rgb: 255, 255, 255;
-  --cros-default-text-color: rgb(var(--cros-default-text-color-rgb));
+  --cros-text-color-primary-rgb: 255, 255, 255;
+  --cros-text-color-primary: rgb(var(--cros-text-color-primary-rgb));
 
-  --cros-toggle-color-rgb: var(--cros-default-text-color-rgb);
+  --cros-toggle-color-rgb: var(--cros-text-color-primary-rgb);
   --cros-toggle-color: rgba(var(--cros-toggle-color-rgb), 0.1);
 
 }
diff --git a/tools/style_variable_generator/colors_test_expected.css b/tools/style_variable_generator/colors_test_expected.css
index bbab0956..bf4867a 100644
--- a/tools/style_variable_generator/colors_test_expected.css
+++ b/tools/style_variable_generator/colors_test_expected.css
@@ -11,18 +11,18 @@
   --google-grey-900-rgb: 32, 33, 36;
   --google-grey-900: rgb(var(--google-grey-900-rgb));
 
-  --cros-default-text-color-rgb: var(--google-grey-900-rgb);
-  --cros-default-text-color: rgb(var(--cros-default-text-color-rgb));
+  --cros-text-color-primary-rgb: var(--google-grey-900-rgb);
+  --cros-text-color-primary: rgb(var(--cros-text-color-primary-rgb));
 
-  --cros-toggle-color-rgb: var(--cros-default-text-color-rgb);
+  --cros-toggle-color-rgb: var(--cros-text-color-primary-rgb);
   --cros-toggle-color: rgba(var(--cros-toggle-color-rgb), 0.1);
 
 }
 
 @media (prefers-color-scheme: dark) {
   html:not(body) {
-    --cros-default-text-color-rgb: 255, 255, 255;
-    --cros-default-text-color: rgb(var(--cros-default-text-color-rgb));
+    --cros-text-color-primary-rgb: 255, 255, 255;
+    --cros-text-color-primary: rgb(var(--cros-text-color-primary-rgb));
 
   }
 }
diff --git a/tools/style_variable_generator/colors_test_expected.h b/tools/style_variable_generator/colors_test_expected.h
index 3b823634..f703fdb5 100644
--- a/tools/style_variable_generator/colors_test_expected.h
+++ b/tools/style_variable_generator/colors_test_expected.h
@@ -17,7 +17,7 @@
 
 enum class ColorName {
   kGoogleGrey900,
-  kDefaultTextColor,
+  kTextColorPrimary,
   kToggleColor,
 };
 
@@ -25,14 +25,14 @@
   switch (color_name) {
     case ColorName::kGoogleGrey900:
       return SkColorSetRGB(0x20, 0x21, 0x24);
-    case ColorName::kDefaultTextColor:
+    case ColorName::kTextColorPrimary:
       if (color_mode == AshColorMode::kLight) {
         return ResolveColor(ColorName::kGoogleGrey900, color_mode);
       } else {
         return SkColorSetRGB(0xFF, 0xFF, 0xFF);
       }
     case ColorName::kToggleColor:
-      return SkColorSetA(ResolveColor(ColorName::kDefaultTextColor, color_mode), 0x19);
+      return SkColorSetA(ResolveColor(ColorName::kTextColorPrimary, color_mode), 0x19);
   }
 }
 
diff --git a/tools/style_variable_generator/css_generator.py b/tools/style_variable_generator/css_generator.py
index 1c40a3a..587f4ca 100644
--- a/tools/style_variable_generator/css_generator.py
+++ b/tools/style_variable_generator/css_generator.py
@@ -55,9 +55,17 @@
     def GetGlobals(self):
         return {
             'css_color_from_rgb_var': self._CssColorFromRGBVar,
-            'in_files': self.in_files,
+            'in_files': self.in_file_to_context.keys(),
         }
 
+    def GetCSSVarNames(self):
+        '''Returns generated CSS variable names (excluding the rgb versions)'''
+        names = set()
+        for name in self.model[VariableType.COLOR].keys():
+            names.add(self._ToCSSVarName(name))
+
+        return names
+
     def _GetCSSVarPrefix(self, model_name):
         prefix = self.context_map[model_name].get('prefix')
         return prefix + '-' if prefix else ''
diff --git a/tools/style_variable_generator/find_invalid_css_variables.py b/tools/style_variable_generator/find_invalid_css_variables.py
new file mode 100644
index 0000000..439ce42e
--- /dev/null
+++ b/tools/style_variable_generator/find_invalid_css_variables.py
@@ -0,0 +1,80 @@
+# Copyright 2020 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.
+
+from __future__ import print_function
+
+import argparse
+import os
+import subprocess
+import sys
+from css_generator import CSSStyleGenerator
+
+
+def RunGit(command):
+    """Run a git subcommand, returning its output."""
+    command = ['git'] + command
+    proc = subprocess.Popen(command, stdout=subprocess.PIPE)
+    out = proc.communicate()[0].strip()
+    return out
+
+
+# TODO(calamity): extend this checker to find unused C++ variables
+def FindInvalidCSSVariables(json_string, input_file, git_runner=RunGit):
+    style_generator = CSSStyleGenerator()
+    style_generator.AddJSONToModel(json_string, style_generator.GetName(),
+                                   input_file)
+
+    context = style_generator.in_file_to_context[input_file]
+    if (not context or 'prefix' not in context):
+        raise KeyError('This tool only works on files with a CSS prefix.')
+
+    css_prefix = '--' + context['prefix'] + '-'
+
+    valid_names = style_generator.GetCSSVarNames()
+
+    found_names_list = git_runner([
+        'grep', '-ho',
+        '\\%s[a-z-]*' % css_prefix, '--', '*.css', '*.html', '*.js'
+    ]).splitlines()
+    found_names = set()
+    for name in found_names_list:
+        rgb_suffix = '-rgb'
+        if name.endswith(rgb_suffix):
+            name = name[:-len(rgb_suffix)]
+        found_names.add(name)
+    return {
+        'unspecified': found_names.difference(valid_names),
+        'unused': valid_names.difference(found_names),
+        'css_prefix': css_prefix,
+    }
+
+
+def main():
+    parser = argparse.ArgumentParser(
+        description='''Finds CSS variables in the codebase that are prefixed
+        with |input_file|'s CSS prefix but aren't specified in |input_file|.'''
+    )
+    # TODO(calamity): support multiple files if multiple json5 files have the
+    # same prefix.
+    parser.add_argument('target', help='source json5 color file')
+    args = parser.parse_args()
+
+    input_file = args.target
+
+    with open(input_file, 'r') as f:
+        result = FindInvalidCSSVariables(f.read(), input_file)
+
+    print('Has prefix %s but not in %s:' % (result['css_prefix'], input_file))
+    for name in sorted(result['unspecified']):
+        print(name)
+
+    print('\nGenerated by %s but not used in codebase:' % input_file)
+    for name in sorted(result['unused']):
+        print(name)
+
+    return 0
+
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/tools/style_variable_generator/find_invalid_css_variables_test.py b/tools/style_variable_generator/find_invalid_css_variables_test.py
new file mode 100644
index 0000000..0a411d7b
--- /dev/null
+++ b/tools/style_variable_generator/find_invalid_css_variables_test.py
@@ -0,0 +1,83 @@
+# Copyright 2020 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.
+
+from find_invalid_css_variables import FindInvalidCSSVariables
+import unittest
+
+
+class FindInvalidCSSVariablesTest(unittest.TestCase):
+    def testUnspecified(self):
+        def GitResult(command):
+            return '''--test-not-specified
+--test-only-rgb-used-rgb
+--test-toolbar'''
+
+        json_string = '''
+{
+  options: {
+    CSS: {
+      prefix: 'test'
+    }
+  },
+  colors: {
+    toolbar: "rgb(255, 255, 255)",
+    only_rgb_used: "rgb(255, 255, 255)",
+  }
+}
+        '''
+
+        result = FindInvalidCSSVariables(json_string,
+                                         'test',
+                                         git_runner=GitResult)
+        unused = set()
+        self.assertEqual(result['unused'], unused)
+        unspecified = set(['--test-not-specified'])
+        self.assertEqual(result['unspecified'], unspecified)
+
+    def testUnused(self):
+        def GitResult(command):
+            return '''--test-toolbar'''
+
+        json_string = '''
+{
+  options: {
+    CSS: {
+      prefix: 'test'
+    }
+  },
+  colors: {
+    toolbar: "rgb(255, 255, 255)",
+    unused: "rgb(255, 255, 255)",
+  }
+}
+        '''
+
+        result = FindInvalidCSSVariables(json_string,
+                                         'test',
+                                         git_runner=GitResult)
+        unused = set(['--test-unused'])
+        self.assertEqual(result['unused'], unused)
+        unspecified = set()
+        self.assertEqual(result['unspecified'], unspecified)
+
+    def testNoPrefix(self):
+        def GitResult(command):
+            return ''
+
+        json_string = '''
+{
+  colors: {
+    toolbar: "rgb(255, 255, 255)",
+  }
+}
+        '''
+        self.assertRaises(KeyError,
+                          FindInvalidCSSVariables,
+                          json_string,
+                          'test',
+                          git_runner=GitResult)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tools/style_variable_generator/views_generator.py b/tools/style_variable_generator/views_generator.py
index 3a284d5d..e9cb4d9 100644
--- a/tools/style_variable_generator/views_generator.py
+++ b/tools/style_variable_generator/views_generator.py
@@ -34,7 +34,7 @@
             'Modes': Modes,
             'out_file_path': None,
             'namespace_name': None,
-            'in_files': self.in_files,
+            'in_files': self.in_file_to_context.keys(),
         }
         if self.out_file_path:
             globals['out_file_path'] = self.out_file_path
diff --git a/ui/base/clipboard/clipboard_ozone.cc b/ui/base/clipboard/clipboard_ozone.cc
index b65e17e..12ca4cc 100644
--- a/ui/base/clipboard/clipboard_ozone.cc
+++ b/ui/base/clipboard/clipboard_ozone.cc
@@ -38,6 +38,12 @@
 
 namespace {
 
+// TODO(crbug.com/1105892): those three constants can be found in a few other
+// places.  Perhaps it would be worth finding some common place for them?
+constexpr char kMimeTypeX11String[] = "STRING";
+constexpr char kMimeTypeX11Text[] = "TEXT";
+constexpr char kMimeTypeX11Utf8String[] = "UTF8_STRING";
+
 // The amount of time to wait for a request to complete before aborting it.
 constexpr base::TimeDelta kRequestTimeout = base::TimeDelta::FromSeconds(10);
 
@@ -102,7 +108,7 @@
       auto it = offered_data_[buffer].find(mime_type);
       if (it == offered_data_[buffer].end())
         return {};
-      return base::make_span(it->second.data(), it->second.size());
+      return base::make_span(it->second->front(), it->second->size());
     }
 
     Request request(RequestType::kRead);
@@ -113,7 +119,7 @@
     auto it = offered_data_[buffer].find(mime_type);
     if (it == offered_data_[buffer].end())
       return {};
-    return base::make_span(it->second.data(), it->second.size());
+    return base::make_span(it->second->front(), it->second->size());
   }
 
   std::vector<std::string> RequestMimeTypes(ClipboardBuffer buffer) {
@@ -145,9 +151,14 @@
     ClipboardMonitor::GetInstance()->NotifyClipboardDataChanged();
   }
 
-  void InsertData(std::vector<uint8_t> data, const std::string& mime_type) {
-    DCHECK_EQ(data_to_offer_.count(mime_type), 0U);
-    data_to_offer_[mime_type] = std::move(data);
+  void InsertData(std::vector<uint8_t> data,
+                  const std::set<std::string>& mime_types) {
+    auto wrapped_data = scoped_refptr<base::RefCountedBytes>(
+        base::RefCountedBytes::TakeVector(&data));
+    for (const auto& mime_type : mime_types) {
+      DCHECK_EQ(data_to_offer_.count(mime_type), 0U);
+      data_to_offer_[mime_type] = wrapped_data;
+    }
     ClipboardMonitor::GetInstance()->NotifyClipboardDataChanged();
   }
 
@@ -248,7 +259,7 @@
     platform_clipboard_->GetAvailableMimeTypes(buffer, std::move(callback));
   }
 
-  void OnTextRead(const base::Optional<std::vector<uint8_t>>& data) {
+  void OnTextRead(const base::Optional<PlatformClipboard::Data>& data) {
     // |data| is already set in request's data_map, so just finish request
     // processing.
     CompleteRequest();
@@ -543,7 +554,9 @@
 
 void ClipboardOzone::WriteText(const char* text_data, size_t text_len) {
   std::vector<uint8_t> data(text_data, text_data + text_len);
-  async_clipboard_ozone_->InsertData(std::move(data), kMimeTypeText);
+  async_clipboard_ozone_->InsertData(
+      std::move(data), {kMimeTypeText, kMimeTypeX11Text, kMimeTypeX11String,
+                        kMimeTypeX11Utf8String});
 }
 
 void ClipboardOzone::WriteHTML(const char* markup_data,
@@ -551,12 +564,12 @@
                                const char* url_data,
                                size_t url_len) {
   std::vector<uint8_t> data(markup_data, markup_data + markup_len);
-  async_clipboard_ozone_->InsertData(std::move(data), kMimeTypeHTML);
+  async_clipboard_ozone_->InsertData(std::move(data), {kMimeTypeHTML});
 }
 
 void ClipboardOzone::WriteRTF(const char* rtf_data, size_t data_len) {
   std::vector<uint8_t> data(rtf_data, rtf_data + data_len);
-  async_clipboard_ozone_->InsertData(std::move(data), kMimeTypeRTF);
+  async_clipboard_ozone_->InsertData(std::move(data), {kMimeTypeRTF});
 }
 
 void ClipboardOzone::WriteBookmark(const char* title_data,
@@ -572,25 +585,25 @@
   std::vector<uint8_t> data(
       reinterpret_cast<const uint8_t*>(bookmark.data()),
       reinterpret_cast<const uint8_t*>(bookmark.data() + bookmark.size()));
-  async_clipboard_ozone_->InsertData(std::move(data), kMimeTypeMozillaURL);
+  async_clipboard_ozone_->InsertData(std::move(data), {kMimeTypeMozillaURL});
 }
 
 void ClipboardOzone::WriteWebSmartPaste() {
   async_clipboard_ozone_->InsertData(std::vector<uint8_t>(),
-                                     kMimeTypeWebkitSmartPaste);
+                                     {kMimeTypeWebkitSmartPaste});
 }
 
 void ClipboardOzone::WriteBitmap(const SkBitmap& bitmap) {
   std::vector<unsigned char> output;
   if (gfx::PNGCodec::FastEncodeBGRASkBitmap(bitmap, false, &output))
-    async_clipboard_ozone_->InsertData(std::move(output), kMimeTypePNG);
+    async_clipboard_ozone_->InsertData(std::move(output), {kMimeTypePNG});
 }
 
 void ClipboardOzone::WriteData(const ClipboardFormatType& format,
                                const char* data_data,
                                size_t data_len) {
   std::vector<uint8_t> data(data_data, data_data + data_len);
-  async_clipboard_ozone_->InsertData(std::move(data), format.GetName());
+  async_clipboard_ozone_->InsertData(std::move(data), {format.GetName()});
 }
 
 SkBitmap ClipboardOzone::ReadImageInternal(ClipboardBuffer buffer) const {
diff --git a/ui/file_manager/file_manager/cws_widget/cws_widget_container.css b/ui/file_manager/file_manager/cws_widget/cws_widget_container.css
index 1d785104f6..f707ac1 100644
--- a/ui/file_manager/file_manager/cws_widget/cws_widget_container.css
+++ b/ui/file_manager/file_manager/cws_widget/cws_widget_container.css
@@ -48,7 +48,7 @@
 
 body.files-ng .cws-widget-buttons {
   align-items: center;
-  background: var(--cros-default-bg-color);
+  background: var(--cros-bg-color);
   display: flex;
   /* subtract the bottom padding from the container outside */
   height: calc(64px - 20px);
@@ -67,7 +67,7 @@
 }
 
 body.files-ng .cws-widget-webstore-button {
-  color: var(--cros-default-button-background-color-primary);
+  color: var(--cros-button-background-color-primary);
   height: 24px;
   padding-inline-start: 0;
 }
diff --git a/ui/file_manager/file_manager/foreground/css/common.css b/ui/file_manager/file_manager/foreground/css/common.css
index 4e9f4aa..9586aaf 100644
--- a/ui/file_manager/file_manager/foreground/css/common.css
+++ b/ui/file_manager/file_manager/foreground/css/common.css
@@ -161,7 +161,7 @@
 }
 
 .cr-dialog-container.files-ng .cr-dialog-buttons > button {
-  background-color: var(--cros-default-button-background-color-secondary);
+  background-color: var(--cros-button-background-color-secondary);
   border: 0;
   border-radius: 4px;
   box-sizing: border-box;
@@ -184,76 +184,76 @@
 
 .cr-dialog-container:not(.files-ng) .cr-dialog-buttons > button.cr-dialog-ok,
 .cr-dialog-container:not(.files-ng) .cr-dialog-buttons > button.cr-dialog-ok:hover {
-  background-color: var(--cros-default-button-background-color-primary);
-  color: var(--cros-default-button-label-color-primary);
+  background-color: var(--cros-button-background-color-primary);
+  color: var(--cros-button-label-color-primary);
   order: 1;
 }
 
 .cr-dialog-container.files-ng .cr-dialog-buttons > button.cr-dialog-ok,
 .cr-dialog-container.files-ng .cr-dialog-buttons > button.cr-dialog-ok:hover {
-  background-color: var(--cros-default-button-background-color-primary);
-  color: var(--cros-default-button-label-color-primary);
+  background-color: var(--cros-button-background-color-primary);
+  color: var(--cros-button-label-color-primary);
   order: 1;
 }
 
 .cr-dialog-container:not(.files-ng) .cr-dialog-buttons > button.cr-dialog-ok:hover {
   background:
-      linear-gradient(var(--cros-default-button-background-color-primary-hover-overlay),
-                      var(--cros-default-button-background-color-primary-hover-overlay));
-              var(--cros-default-button-background-color-primary),
+      linear-gradient(var(--cros-button-background-color-primary-hover-overlay),
+                      var(--cros-button-background-color-primary-hover-overlay));
+              var(--cros-button-background-color-primary),
 }
 
 .cr-dialog-container.files-ng .cr-dialog-buttons > button.cr-dialog-ok:hover {
   background:
-      linear-gradient(var(--cros-default-button-background-color-primary-hover-overlay),
-                      var(--cros-default-button-background-color-primary-hover-overlay)),
-              var(--cros-default-button-background-color-primary);
+      linear-gradient(var(--cros-button-background-color-primary-hover-overlay),
+                      var(--cros-button-background-color-primary-hover-overlay)),
+              var(--cros-button-background-color-primary);
 }
 
 .cr-dialog-container:not(.files-ng) .cr-dialog-buttons > button.cr-dialog-ok[disabled],
 .cr-dialog-container:not(.files-ng) .cr-dialog-buttons > button.cr-dialog-ok[disabled]:hover {
   background-color:
-      var(--cros-default-button-background-color-primary-disabled);
-  color: var(--cros-default-button-label-color-primary-disabled);
+      var(--cros-button-background-color-primary-disabled);
+  color: var(--cros-button-label-color-primary-disabled);
 }
 
 .cr-dialog-container.files-ng .cr-dialog-buttons > button.cr-dialog-ok[disabled],
 .cr-dialog-container.files-ng .cr-dialog-buttons > button.cr-dialog-ok[disabled]:hover {
   background-color:
-      var(--cros-default-button-background-color-primary-disabled);
-  color: var(--cros-default-button-label-color-primary-disabled);
+      var(--cros-button-background-color-primary-disabled);
+  color: var(--cros-button-label-color-primary-disabled);
 }
 
 .cr-dialog-container:not(.files-ng) .cr-dialog-buttons > button.cr-dialog-cancel {
-  border: 1px solid var(--cros-default-button-stroke-color-secondary);
-  color: var(--cros-default-button-label-color-secondary);
+  border: 1px solid var(--cros-button-stroke-color-secondary);
+  color: var(--cros-button-label-color-secondary);
   order: 0;
 }
 
 .cr-dialog-container.files-ng .cr-dialog-buttons > button.cr-dialog-cancel {
-  border: 1px solid var(--cros-default-button-stroke-color-secondary);
-  color: var(--cros-default-button-label-color-secondary);
+  border: 1px solid var(--cros-button-stroke-color-secondary);
+  color: var(--cros-button-label-color-secondary);
   order: 0;
 }
 
 .cr-dialog-container:not(.files-ng) .cr-dialog-buttons > button.cr-dialog-cancel:hover {
-  background: var(--cros-default-button-background-color-secondary-hover);
+  background: var(--cros-button-background-color-secondary-hover);
 }
 
 .cr-dialog-container.files-ng .cr-dialog-buttons > button.cr-dialog-cancel:hover {
-  background: var(--cros-default-button-background-color-secondary-hover);
+  background: var(--cros-button-background-color-secondary-hover);
 }
 
 .cr-dialog-container:not(.files-ng) .cr-dialog-buttons > button.cr-dialog-cancel[disabled],
 .cr-dialog-container:not(.files-ng) .cr-dialog-buttons > button.cr-dialog-cancel[disabled]:hover  {
-  border: 1px solid var(--cros-default-button-stroke-color-secondary-disabled);
-  color: var(--cros-default-button-label-color-secondary-disabled);
+  border: 1px solid var(--cros-button-stroke-color-secondary-disabled);
+  color: var(--cros-button-label-color-secondary-disabled);
 }
 
 .cr-dialog-container.files-ng .cr-dialog-buttons > button.cr-dialog-cancel[disabled],
 .cr-dialog-container.files-ng .cr-dialog-buttons > button.cr-dialog-cancel[disabled]:hover  {
-  border: 1px solid var(--cros-default-button-stroke-color-secondary-disabled);
-  color: var(--cros-default-button-label-color-secondary-disabled);
+  border: 1px solid var(--cros-button-stroke-color-secondary-disabled);
+  color: var(--cros-button-label-color-secondary-disabled);
 }
 
 .cr-dialog-container:not(.files-ng) .cr-dialog-buttons > button:not(:active):focus {
@@ -327,11 +327,11 @@
 }
 
 .cr-dialog-container:not(.files-ng) .cr-dialog-frame {
-  background-color: var(--cros-default-bg-color);
+  background-color: var(--cros-bg-color);
   border-radius: 2px;
   box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
               0 2px 6px 0 rgba(0, 0, 0, 0.1);
-  color: var(--cros-default-text-color);
+  color: var(--cros-text-color-primary);
   cursor: default;
   display: flex;
   flex-direction: column;
@@ -342,11 +342,11 @@
 }
 
 .cr-dialog-container.files-ng .cr-dialog-frame {
-  background-color: var(--cros-default-bg-color);
+  background-color: var(--cros-bg-color);
   border-radius: 12px;
   box-shadow: 0 4px 8px 3px rgba(var(--google-grey-800-rgb), 15%),
               0 1px 3px 0 rgba(var(--google-grey-800-rgb), 30%);
-  color: var(--cros-default-text-color);
+  color: var(--cros-text-color-primary);
   cursor: default;
   display: flex;
   flex-direction: column;
@@ -420,7 +420,7 @@
 }
 
 .cr-dialog-container.files-ng .cr-dialog-title {
-  color: var(--cros-default-text-color);
+  color: var(--cros-text-color-primary);
   display: block;
   font-size: 16px;
   font-weight: 500;
@@ -438,7 +438,7 @@
 
 .cr-dialog-container:not(.files-ng) .cr-dialog-text,
 .cr-dialog-container:not(.files-ng) .cr-dialog-title {
-  color: var(--cros-default-text-color);
+  color: var(--cros-text-color-primary);
   overflow: hidden;
   text-overflow: ellipsis;
 }
@@ -449,11 +449,11 @@
 }
 
 .cr-dialog-container.files-ng .cr-dialog-text {
-  color: var(--cros-default-text-color-secondary);
+  color: var(--cros-text-color-secondary);
 }
 
 .cr-dialog-container.files-ng .no-title .cr-dialog-text {
-  color: var(--cros-default-text-color);
+  color: var(--cros-text-color-primary);
 }
 
 .cr-dialog-container:not(.files-ng) .cr-dialog-frame input {
@@ -563,7 +563,7 @@
 
 /* Common typography styles for ChromeOS. */
 body.files-ng .headline2 {
-  color: var(--cros-default-text-color);
+  color: var(--cros-text-color-primary);
   font-family: Roboto;
   font-size: 15px;
   font-weight: 500;
@@ -571,7 +571,7 @@
 }
 
 body.files-ng .button2 {
-  color: var(--cros-default-text-color);
+  color: var(--cros-text-color-primary);
   font-family: Roboto;
   font-size: 13px;
   font-weight: 500;
@@ -579,14 +579,14 @@
 }
 
 body.files-ng .body2-primary {
-  color: var(--cros-default-text-color);
+  color: var(--cros-text-color-primary);
   font-family: Roboto;
   font-size: 13px;
   line-height: 20px;
 }
 
 body.files-ng .annotation1-primary {
-  color: var(--cros-default-text-color);
+  color: var(--cros-text-color-primary);
   font-family: Roboto;
   font-size: 12px;
   line-height: 18px;
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager.css b/ui/file_manager/file_manager/foreground/css/file_manager.css
index 2d6061b7..0c2b974 100644
--- a/ui/file_manager/file_manager/foreground/css/file_manager.css
+++ b/ui/file_manager/file_manager/foreground/css/file_manager.css
@@ -78,7 +78,7 @@
 }
 
 body.files-ng .dialog-container {
-  background-color: var(--cros-default-bg-color);
+  background-color: var(--cros-bg-color);
 }
 
 /* List and grid are inside this container. */
@@ -1393,8 +1393,8 @@
 
 body.files-ng .dialog-footer .primary,
 body.files-ng .dialog-footer .primary:hover {
-  background-color: var(--cros-default-button-background-color-primary);
-  color: var(--cros-default-button-label-color-primary);
+  background-color: var(--cros-button-background-color-primary);
+  color: var(--cros-button-label-color-primary);
 }
 
 body:not(.files-ng) .dialog-footer .secondary {
@@ -1402,9 +1402,9 @@
 }
 
 body.files-ng .dialog-footer .secondary {
-  background-color: var(--cros-default-button-background-color-secondary);
-  border: 1px solid var(--cros-default-button-stroke-color-secondary);
-  color: var(--cros-default-button-label-color-secondary);
+  background-color: var(--cros-button-background-color-secondary);
+  border: 1px solid var(--cros-button-stroke-color-secondary);
+  color: var(--cros-button-label-color-secondary);
   margin-inline-end: 8px;
 }
 
@@ -1413,7 +1413,7 @@
 }
 
 body.files-ng .dialog-footer .secondary:hover {
-  background: var(--cros-default-button-background-color-secondary-hover);
+  background: var(--cros-button-background-color-secondary-hover);
 }
 
 body:not(.files-ng) .dialog-footer .select {
@@ -3222,7 +3222,7 @@
 }
 
 body.files-ng .table-row-cell .filename-label {
-  color: var(--cros-default-text-color);
+  color: var(--cros-text-color-primary);
 
   padding-top: 0;
 }
@@ -3312,7 +3312,7 @@
 }
 
 .cr-dialog-container.files-ng .install-linux-package-detail-label {
-  color: var(--cros-default-text-color);
+  color: var(--cros-text-color-primary);
   display: inline;
   margin-inline-end: 5px;
 }
@@ -3324,7 +3324,7 @@
 }
 
 .cr-dialog-container.files-ng .install-linux-package-detail-value {
-  color: var(--cros-default-text-color-secondary);
+  color: var(--cros-text-color-secondary);
   display: inline;
   margin-bottom: 5px;
   white-space: pre-wrap;
@@ -3385,13 +3385,20 @@
   background-color: rgba(0, 0, 0, 8%);
 }
 
-#gear-menu,
-#share-menu,
-#sort-menu,
-#tasks-menu {
+body:not(.files-ng) #gear-menu,
+body:not(.files-ng) #share-menu,
+body:not(.files-ng) #sort-menu,
+body:not(.files-ng) #tasks-menu {
   margin-top: 2px;
 }
 
+/*
+ * TODO(files-ng): remove these rules and do them in the multi-menu JS because
+ * #tasks-menu is distinguished here: it is used as a menu and a submenu, thus
+ * gets 8px margin-top in all cases.  It should only have this 8px gap when it
+ * is shown as a menu; it should have no margin-top when it is a submenu (just
+ * like every other submenu in files app - none of them have margin-top).
+ */
 body.files-ng #gear-menu,
 body.files-ng #share-menu,
 body.files-ng #sort-menu,
diff --git a/ui/ozone/platform/wayland/common/data_util.cc b/ui/ozone/platform/wayland/common/data_util.cc
index 55e594a..9077366 100644
--- a/ui/ozone/platform/wayland/common/data_util.cc
+++ b/ui/ozone/platform/wayland/common/data_util.cc
@@ -46,34 +46,32 @@
 
 // Converts raw data to either narrow or wide string.
 template <typename StringType>
-StringType BytesTo(const PlatformClipboard::Data& bytes) {
-  if (bytes.size() % sizeof(typename StringType::value_type) != 0U) {
+StringType BytesTo(PlatformClipboard::Data bytes) {
+  using ValueType = typename StringType::value_type;
+  if (bytes->size() % sizeof(ValueType) != 0U) {
     // This is suspicious.
     LOG(WARNING)
         << "Data is possibly truncated, or a wrong conversion is requested.";
   }
 
-  StringType result;
-  result.assign(reinterpret_cast<typename StringType::const_pointer>(&bytes[0]),
-                bytes.size() / sizeof(typename StringType::value_type));
+  StringType result(bytes->front_as<ValueType>(),
+                    bytes->size() / sizeof(ValueType));
   return result;
 }
 
-void AddString(const PlatformClipboard::Data& data,
-               OSExchangeData* os_exchange_data) {
+void AddString(PlatformClipboard::Data data, OSExchangeData* os_exchange_data) {
   DCHECK(os_exchange_data);
 
-  if (data.empty())
+  if (data->data().empty())
     return;
 
   os_exchange_data->SetString(base::UTF8ToUTF16(BytesTo<std::string>(data)));
 }
 
-void AddHtml(const PlatformClipboard::Data& data,
-             OSExchangeData* os_exchange_data) {
+void AddHtml(PlatformClipboard::Data data, OSExchangeData* os_exchange_data) {
   DCHECK(os_exchange_data);
 
-  if (data.empty())
+  if (data->data().empty())
     return;
 
   os_exchange_data->SetHtml(base::UTF8ToUTF16(BytesTo<std::string>(data)),
@@ -85,8 +83,7 @@
 // 2.  Non-comment lines shall be URIs (URNs or URLs).
 // 3.  Lines are terminated with a CRLF pair.
 // 4.  URL encoding is used.
-void AddFiles(const PlatformClipboard::Data& data,
-              OSExchangeData* os_exchange_data) {
+void AddFiles(PlatformClipboard::Data data, OSExchangeData* os_exchange_data) {
   DCHECK(os_exchange_data);
 
   std::string data_as_string = BytesTo<std::string>(data);
@@ -124,11 +121,10 @@
 // two lines separated with newline, where the first line is the URL and
 // the second one is page title.  The unpleasant feature of text/x-moz-url is
 // that the URL has UTF-16 encoding.
-void AddUrl(const PlatformClipboard::Data& data,
-            OSExchangeData* os_exchange_data) {
+void AddUrl(PlatformClipboard::Data data, OSExchangeData* os_exchange_data) {
   DCHECK(os_exchange_data);
 
-  if (data.empty())
+  if (data->data().empty())
     return;
 
   base::string16 data_as_string16 = BytesTo<base::string16>(data);
@@ -163,9 +159,10 @@
   return exchange_data.HasAnyFormat(MimeTypeToFormat(mime_type), {});
 }
 
-void AddToOSExchangeData(const PlatformClipboard::Data& data,
+void AddToOSExchangeData(PlatformClipboard::Data data,
                          const std::string& mime_type,
                          OSExchangeData* exchange_data) {
+  DCHECK(data);
   DCHECK(IsMimeTypeSupported(mime_type));
   DCHECK(exchange_data);
   int format = MimeTypeToFormat(mime_type);
diff --git a/ui/ozone/platform/wayland/common/data_util.h b/ui/ozone/platform/wayland/common/data_util.h
index d6c2d10e7..39c0308 100644
--- a/ui/ozone/platform/wayland/common/data_util.h
+++ b/ui/ozone/platform/wayland/common/data_util.h
@@ -24,7 +24,7 @@
 
 // Add clipboard |data| content with |mime_type| format to the |exchange_data|.
 // |mime_type| is assumed to be supported (See IsMimeTypeSupported for more).
-void AddToOSExchangeData(const ui::PlatformClipboard::Data& data,
+void AddToOSExchangeData(ui::PlatformClipboard::Data data,
                          const std::string& mime_type,
                          ui::OSExchangeData* exchange_data);
 
diff --git a/ui/ozone/platform/wayland/host/wayland_clipboard.cc b/ui/ozone/platform/wayland/host/wayland_clipboard.cc
index a0e848a..cd99fdd 100644
--- a/ui/ozone/platform/wayland/host/wayland_clipboard.cc
+++ b/ui/ozone/platform/wayland/host/wayland_clipboard.cc
@@ -109,7 +109,7 @@
     if (it == data_.end() && mime_type == ui::kMimeTypeTextUtf8)
       it = data_.find(ui::kMimeTypeText);
     if (it != data_.end())
-      contents->assign(it->second.begin(), it->second.end());
+      contents->assign(it->second->data().begin(), it->second->data().end());
   }
 
   // The device manager used to access data device and create data sources.
@@ -157,8 +157,10 @@
   data_map_ = data_map;
   read_clipboard_closure_ = std::move(callback);
   auto* clipboard = GetClipboard(buffer);
-  if (!clipboard || !clipboard->Read(mime_type))
-    SetData({}, mime_type);
+  if (!clipboard || !clipboard->Read(mime_type)) {
+    SetData(scoped_refptr<base::RefCountedBytes>(new base::RefCountedBytes()),
+            mime_type);
+  }
 }
 
 bool WaylandClipboard::IsSelectionOwner(ClipboardBuffer buffer) {
@@ -183,11 +185,12 @@
   std::move(callback).Run(mime_types);
 }
 
-void WaylandClipboard::SetData(const std::vector<uint8_t>& contents,
+void WaylandClipboard::SetData(PlatformClipboard::Data contents,
                                const std::string& mime_type) {
   if (!data_map_)
     return;
 
+  DCHECK(contents);
   (*data_map_)[mime_type] = contents;
 
   if (!read_clipboard_closure_.is_null()) {
diff --git a/ui/ozone/platform/wayland/host/wayland_clipboard.h b/ui/ozone/platform/wayland/host/wayland_clipboard.h
index d464140..c8b724d 100644
--- a/ui/ozone/platform/wayland/host/wayland_clipboard.h
+++ b/ui/ozone/platform/wayland/host/wayland_clipboard.h
@@ -56,8 +56,7 @@
 
   // TODO(nickdiego): Get rid of these methods once DataDevice implementations
   // are decoupled from WaylandClipboard.
-  void SetData(const std::vector<uint8_t>& contents,
-               const std::string& mime_type);
+  void SetData(PlatformClipboard::Data contents, const std::string& mime_type);
   void UpdateSequenceNumber(ClipboardBuffer buffer);
 
  private:
diff --git a/ui/ozone/platform/wayland/host/wayland_data_device.cc b/ui/ozone/platform/wayland/host/wayland_data_device.cc
index 1edd356..edbb6d472 100644
--- a/ui/ozone/platform/wayland/host/wayland_data_device.cc
+++ b/ui/ozone/platform/wayland/host/wayland_data_device.cc
@@ -81,12 +81,12 @@
   connection()->ScheduleFlush();
 }
 
-void WaylandDataDevice::ReadDragDataFromFD(
-    base::ScopedFD fd,
-    base::OnceCallback<void(const PlatformClipboard::Data&)> callback) {
-  PlatformClipboard::Data contents;
+void WaylandDataDevice::ReadDragDataFromFD(base::ScopedFD fd,
+                                           RequestDataCallback callback) {
+  std::vector<uint8_t> contents;
   wl::ReadDataFromFD(std::move(fd), &contents);
-  std::move(callback).Run(contents);
+  std::move(callback).Run(scoped_refptr<base::RefCountedBytes>(
+      base::RefCountedBytes::TakeVector(&contents)));
 }
 
 // static
diff --git a/ui/ozone/platform/wayland/host/wayland_data_device.h b/ui/ozone/platform/wayland/host/wayland_data_device.h
index 8aac88ae..12b84cf 100644
--- a/ui/ozone/platform/wayland/host/wayland_data_device.h
+++ b/ui/ozone/platform/wayland/host/wayland_data_device.h
@@ -33,8 +33,7 @@
 // such as copy-and-paste and drag-and-drop mechanisms.
 class WaylandDataDevice : public WaylandDataDeviceBase {
  public:
-  using RequestDataCallback =
-      base::OnceCallback<void(const PlatformClipboard::Data&)>;
+  using RequestDataCallback = base::OnceCallback<void(PlatformClipboard::Data)>;
 
   // DragDelegate is responsible for handling drag and drop sessions.
   class DragDelegate {
diff --git a/ui/ozone/platform/wayland/host/wayland_data_device_base.cc b/ui/ozone/platform/wayland/host/wayland_data_device_base.cc
index 3e020a3..7df5d9e 100644
--- a/ui/ozone/platform/wayland/host/wayland_data_device_base.cc
+++ b/ui/ozone/platform/wayland/host/wayland_data_device_base.cc
@@ -56,7 +56,10 @@
     const std::string& mime_type) {
   std::vector<uint8_t> contents;
   wl::ReadDataFromFD(std::move(fd), &contents);
-  connection_->clipboard()->SetData(contents, mime_type);
+  connection_->clipboard()->SetData(
+      scoped_refptr<base::RefCountedBytes>(
+          base::RefCountedBytes::TakeVector(&contents)),
+      mime_type);
 }
 
 void WaylandDataDeviceBase::RegisterDeferredReadCallback() {
diff --git a/ui/ozone/platform/wayland/host/wayland_data_device_unittest.cc b/ui/ozone/platform/wayland/host/wayland_data_device_unittest.cc
index b4bedb5..13329fe 100644
--- a/ui/ozone/platform/wayland/host/wayland_data_device_unittest.cc
+++ b/ui/ozone/platform/wayland/host/wayland_data_device_unittest.cc
@@ -34,13 +34,10 @@
 
 template <typename StringType>
 ui::PlatformClipboard::Data ToClipboardData(const StringType& data_string) {
-  ui::PlatformClipboard::Data result;
-  auto* begin =
-      reinterpret_cast<typename ui::PlatformClipboard::Data::const_pointer>(
-          data_string.data());
-  result.assign(begin, begin + (data_string.size() *
-                                sizeof(typename StringType::value_type)));
-  return result;
+  std::vector<uint8_t> data_vector;
+  data_vector.assign(data_string.begin(), data_string.end());
+  return scoped_refptr<base::RefCountedBytes>(
+      base::RefCountedBytes::TakeVector(&data_vector));
 }
 
 }  // namespace
@@ -64,7 +61,7 @@
   ~MockClipboardClient() = default;
 
   // Fill the clipboard backing store with sample data.
-  void SetData(const PlatformClipboard::Data& data,
+  void SetData(PlatformClipboard::Data data,
                const std::string& mime_type,
                PlatformClipboard::OfferDataClosure callback) {
     data_types_[mime_type] = data;
@@ -115,17 +112,19 @@
 
 TEST_P(WaylandDataDeviceManagerTest, WriteToClipboard) {
   // The client writes data to the clipboard ...
-  PlatformClipboard::Data data;
-  data.assign(wl::kSampleClipboardText,
-              wl::kSampleClipboardText + strlen(wl::kSampleClipboardText));
-  clipboard_client_->SetData(data, wl::kTextMimeTypeUtf8,
-                             base::BindOnce([]() {}));
+  std::vector<uint8_t> data_vector(
+      wl::kSampleClipboardText,
+      wl::kSampleClipboardText + strlen(wl::kSampleClipboardText));
+  clipboard_client_->SetData(
+      scoped_refptr<base::RefCountedBytes>(
+          base::RefCountedBytes::TakeVector(&data_vector)),
+      {wl::kTextMimeTypeUtf8}, base::BindOnce([]() {}));
   Sync();
 
   // ... and the server reads it.
   base::RunLoop run_loop;
   auto callback = base::BindOnce(
-      [](base::RunLoop* loop, PlatformClipboard::Data&& data) {
+      [](base::RunLoop* loop, std::vector<uint8_t>&& data) {
         std::string string_data(data.begin(), data.end());
         EXPECT_EQ(wl::kSampleClipboardText, string_data);
         loop->Quit();
@@ -150,7 +149,8 @@
   // expectation.
   auto callback =
       base::BindOnce([](const base::Optional<PlatformClipboard::Data>& data) {
-        std::string string_data = std::string(data->begin(), data->end());
+        auto& bytes = data->get()->data();
+        std::string string_data = std::string(bytes.begin(), bytes.end());
         EXPECT_EQ(wl::kSampleClipboardText, string_data);
       });
   clipboard_client_->ReadData(wl::kTextMimeTypeUtf8, std::move(callback));
@@ -163,7 +163,8 @@
   // an empty string.
   auto callback =
       base::BindOnce([](const base::Optional<PlatformClipboard::Data>& data) {
-        std::string string_data = std::string(data->begin(), data->end());
+        auto& bytes = data->get()->data();
+        std::string string_data = std::string(bytes.begin(), bytes.end());
         EXPECT_EQ("", string_data);
       });
   clipboard_client_->ReadData(wl::kTextMimeTypeUtf8, std::move(callback));
@@ -171,10 +172,13 @@
 
 TEST_P(WaylandDataDeviceManagerTest, IsSelectionOwner) {
   auto callback = base::BindOnce([]() {});
-  PlatformClipboard::Data data;
-  data.assign(wl::kSampleClipboardText,
-              wl::kSampleClipboardText + strlen(wl::kSampleClipboardText));
-  clipboard_client_->SetData(data, wl::kTextMimeTypeUtf8, std::move(callback));
+  std::vector<uint8_t> data_vector(
+      wl::kSampleClipboardText,
+      wl::kSampleClipboardText + strlen(wl::kSampleClipboardText));
+  clipboard_client_->SetData(
+      scoped_refptr<base::RefCountedBytes>(
+          base::RefCountedBytes::TakeVector(&data_vector)),
+      {wl::kTextMimeTypeUtf8}, std::move(callback));
   Sync();
   ASSERT_TRUE(clipboard_client_->IsSelectionOwner());
 
diff --git a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
index f844fe9..6403855e 100644
--- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
+++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.cc
@@ -295,9 +295,10 @@
 }
 
 void WaylandDataDragController::OnMimeTypeDataTransferred(
-    const PlatformClipboard::Data& contents) {
+    PlatformClipboard::Data contents) {
   DCHECK_EQ(state_, State::kTransferring);
-  if (!contents.empty()) {
+  DCHECK(contents);
+  if (!contents->data().empty()) {
     std::string mime_type = unprocessed_mime_types_.front();
     wl::AddToOSExchangeData(contents, mime_type, received_data_.get());
   }
diff --git a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h
index 9dcf515..5e4c15dd 100644
--- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h
+++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller.h
@@ -80,7 +80,7 @@
   void Offer(const OSExchangeData& data, int operation);
   void CreateIconSurfaceIfNeeded(const OSExchangeData& data);
   void HandleUnprocessedMimeTypes();
-  void OnMimeTypeDataTransferred(const PlatformClipboard::Data& contents);
+  void OnMimeTypeDataTransferred(PlatformClipboard::Data contents);
   void OnDataTransferFinished(
       std::unique_ptr<ui::OSExchangeData> received_data);
   std::string GetNextUnprocessedMimeType();
diff --git a/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc b/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc
index 8b1115b..15e43c8 100644
--- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc
+++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc
@@ -52,13 +52,13 @@
 
 template <typename StringType>
 PlatformClipboard::Data ToClipboardData(const StringType& data_string) {
-  PlatformClipboard::Data result;
-  auto* begin =
-      reinterpret_cast<typename PlatformClipboard::Data::const_pointer>(
-          data_string.data());
-  result.assign(begin, begin + (data_string.size() *
-                                sizeof(typename StringType::value_type)));
-  return result;
+  auto* begin = reinterpret_cast<typename std::vector<uint8_t>::const_pointer>(
+      data_string.data());
+  std::vector<uint8_t> result(
+      begin,
+      begin + (data_string.size() * sizeof(typename StringType::value_type)));
+  return scoped_refptr<base::RefCountedBytes>(
+      base::RefCountedBytes::TakeVector(&result));
 }
 
 }  // namespace
@@ -155,7 +155,7 @@
     // Now the server can read the data and give it to our callback.
     base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
     auto callback = base::BindOnce(
-        [](base::RunLoop* loop, PlatformClipboard::Data&& data) {
+        [](base::RunLoop* loop, std::vector<uint8_t>&& data) {
           std::string result(data.begin(), data.end());
           EXPECT_EQ(wl::kSampleTextForDragAndDrop, result);
           loop->Quit();
@@ -215,7 +215,7 @@
   // to read it with a different mime type.
   base::RunLoop run_loop;
   auto callback = base::BindOnce(
-      [](base::RunLoop* loop, PlatformClipboard::Data&& data) {
+      [](base::RunLoop* loop, std::vector<uint8_t>&& data) {
         std::string result(data.begin(), data.end());
         EXPECT_TRUE(result.empty());
         loop->Quit();
@@ -243,7 +243,7 @@
   // |kTextMimeTypeUtf8|.
   base::RunLoop run_loop;
   auto callback = base::BindOnce(
-      [](base::RunLoop* loop, PlatformClipboard::Data&& data) {
+      [](base::RunLoop* loop, std::vector<uint8_t>&& data) {
         std::string result(data.begin(), data.end());
         EXPECT_EQ(wl::kSampleTextForDragAndDrop, result);
         loop->Quit();
@@ -278,10 +278,10 @@
 
   Sync();
 
-  auto callback = base::BindOnce([](const PlatformClipboard::Data& contents) {
+  auto callback = base::BindOnce([](PlatformClipboard::Data contents) {
     std::string result;
-    result.assign(reinterpret_cast<std::string::const_pointer>(&contents[0]),
-                  contents.size());
+    EXPECT_TRUE(contents);
+    result.assign(contents->front_as<char>(), contents->size());
     EXPECT_EQ(wl::kSampleTextForDragAndDrop, result);
   });
 
diff --git a/ui/ozone/platform/wayland/test/test_data_offer.cc b/ui/ozone/platform/wayland/test/test_data_offer.cc
index b830dad..4ba0bc14 100644
--- a/ui/ozone/platform/wayland/test/test_data_offer.cc
+++ b/ui/ozone/platform/wayland/test/test_data_offer.cc
@@ -21,9 +21,9 @@
 namespace {
 
 void WriteDataOnWorkerThread(base::ScopedFD fd,
-                             const ui::PlatformClipboard::Data& data) {
-  if (!base::WriteFileDescriptor(
-          fd.get(), reinterpret_cast<const char*>(data.data()), data.size())) {
+                             ui::PlatformClipboard::Data data) {
+  if (!base::WriteFileDescriptor(fd.get(), data->front_as<char>(),
+                                 data->size())) {
     LOG(ERROR) << "Failed to write selection data to clipboard.";
   }
 }
@@ -81,7 +81,7 @@
 }
 
 void TestDataOffer::OnOffer(const std::string& mime_type,
-                            const ui::PlatformClipboard::Data& data) {
+                            ui::PlatformClipboard::Data data) {
   data_to_offer_[mime_type] = data;
   wl_data_offer_send_offer(resource(), mime_type.c_str());
 }
diff --git a/ui/ozone/platform/wayland/test/test_data_offer.h b/ui/ozone/platform/wayland/test/test_data_offer.h
index 67080d3a..6b96582 100644
--- a/ui/ozone/platform/wayland/test/test_data_offer.h
+++ b/ui/ozone/platform/wayland/test/test_data_offer.h
@@ -33,8 +33,7 @@
   ~TestDataOffer() override;
 
   void Receive(const std::string& mime_type, base::ScopedFD fd);
-  void OnOffer(const std::string& mime_type,
-               const ui::PlatformClipboard::Data& data);
+  void OnOffer(const std::string& mime_type, ui::PlatformClipboard::Data data);
 
  private:
   const scoped_refptr<base::SequencedTaskRunner> task_runner_;
diff --git a/ui/ozone/platform/x11/x11_clipboard_ozone.cc b/ui/ozone/platform/x11/x11_clipboard_ozone.cc
index fba01a8..e23c83b 100644
--- a/ui/ozone/platform/x11/x11_clipboard_ozone.cc
+++ b/ui/ozone/platform/x11/x11_clipboard_ozone.cc
@@ -65,7 +65,7 @@
   std::vector<std::string> mime_types;
 
   // Data most recently read from remote clipboard.
-  std::vector<unsigned char> data;
+  PlatformClipboard::Data data;
 
   // Mime type of most recently read data from remote clipboard.
   std::string data_mime_type;
@@ -171,7 +171,7 @@
     auto it = offer_data_map.find(key);
     if (it != offer_data_map.end()) {
       ui::SetArrayProperty(event.requestor, event.property, event.target,
-                           it->second);
+                           it->second->data());
     }
   }
 
@@ -228,7 +228,8 @@
     ui::GetArrayProperty(x_window_, x_property_, &data, &type);
     ui::DeleteProperty(x_window_, x_property_);
     if (type != x11::Atom::None)
-      selection_state.data = std::move(data);
+      selection_state.data = scoped_refptr<base::RefCountedBytes>(
+          base::RefCountedBytes::TakeVector(&data));
 
     // If we have a saved callback, invoke it now, otherwise this was a prefetch
     // and we have already saved |data_| for the next call to
@@ -253,7 +254,7 @@
     auto& selection_state = GetSelectionState(selection);
     selection_state.mime_types.clear();
     selection_state.data_mime_type.clear();
-    selection_state.data.clear();
+    selection_state.data.reset();
     QueryTargets(selection);
   }
 
@@ -301,7 +302,7 @@
 
 void X11ClipboardOzone::ReadRemoteClipboard(x11::Atom selection) {
   auto& selection_state = GetSelectionState(selection);
-  selection_state.data.clear();
+  selection_state.data.reset();
   // Allow conversions for text/plain[;charset=utf-8] <=> [UTF8_]STRING.
   std::string target = selection_state.data_mime_type;
   if (!Contains(selection_state.mime_types, target)) {
@@ -346,8 +347,9 @@
   // If we have already prefetched the clipboard for the correct mime type,
   // then send it right away, otherwise save the callback and attempt to get the
   // requested mime type from the remote clipboard.
-  if (!using_xfixes_ || (selection_state.data_mime_type == mime_type &&
-                         !selection_state.data.empty())) {
+  if (!using_xfixes_ ||
+      (selection_state.data_mime_type == mime_type && selection_state.data &&
+       !selection_state.data->data().empty())) {
     data_map->emplace(mime_type, selection_state.data);
     std::move(callback).Run(selection_state.data);
     return;
diff --git a/ui/ozone/public/platform_clipboard.h b/ui/ozone/public/platform_clipboard.h
index 5ef3fb3d..7390222 100644
--- a/ui/ozone/public/platform_clipboard.h
+++ b/ui/ozone/public/platform_clipboard.h
@@ -12,6 +12,7 @@
 #include "base/callback_forward.h"
 #include "base/component_export.h"
 #include "base/macros.h"
+#include "base/memory/ref_counted_memory.h"
 #include "base/optional.h"
 #include "ui/base/clipboard/clipboard_buffer.h"
 
@@ -30,7 +31,7 @@
 
   // DataMap is a map from "mime type" to associated data, whereas
   // the data can be organized differently for each mime type.
-  using Data = std::vector<uint8_t>;
+  using Data = scoped_refptr<base::RefCountedBytes>;
   using DataMap = std::unordered_map<std::string, Data>;
 
   // SequenceNumberUpdateCb is a repeating callback, which can be used to tell
@@ -63,7 +64,7 @@
   // RequestDataClosure is invoked to acknowledge that the requested clipboard
   // data has been read and stored into 'data_map'.
   using RequestDataClosure =
-      base::OnceCallback<void(const base::Optional<std::vector<uint8_t>>&)>;
+      base::OnceCallback<void(const base::Optional<Data>&)>;
   virtual void RequestClipboardData(ClipboardBuffer buffer,
                                     const std::string& mime_type,
                                     DataMap* data_map,
diff --git a/ui/webui/resources/css/cros_colors.json5 b/ui/webui/resources/css/cros_colors.json5
index 47a2c34..817153c9 100644
--- a/ui/webui/resources/css/cros_colors.json5
+++ b/ui/webui/resources/css/cros_colors.json5
@@ -18,26 +18,26 @@
     /*
      * Core colors.
      */
-    default_text_color: {
+    text_color_primary: {
       light: "$google_grey_900",
       dark: "$google_grey_200",
     },
-    default_text_color_secondary: {
+    text_color_secondary: {
       light: "$google_grey_700",
       dark: "$google_grey_500",
     },
 
-    default_bg_color: {
+    bg_color: {
       light: "#ffffff",
       dark: "$google_grey_900",
     },
 
-    default_icon_color_primary: {
+    icon_color_primary: {
       light: "$google_grey_700",
       dark: "$google_grey_200",
     },
 
-    default_icon_color_prominent: {
+    icon_color_prominent: {
       light: "$google_blue_600",
       dark: "$google_blue_300",
     },
@@ -45,20 +45,20 @@
     /*
      * Component colors.
      */
-    default_toolbar_bg_color: "#ffffff",
-    default_toolbar_search_bg_color: "$google_grey_100",
+    toolbar_bg_color: "#ffffff",
+    toolbar_search_bg_color: "$google_grey_100",
 
     menu_button_bg_color_active: "$google_blue_50",
     menu_button_bg_color_hover: "$google_grey_100",
     menu_button_outline_color_focused: "$google_blue_600",
 
-    toggle_color: "$default_icon_color_prominent",
+    toggle_color: "$icon_color_prominent",
     toggle_bg_color_inactive: "$google_grey_400",
     toggle_button_color_inactive: "#ffffff",
     toggle_ripple_color: "rgba($toggle_color_rgb, .2)",
     toggle_ripple_color_inactive: "rgba($google_grey_600_rgb, .15)",
 
-    radio_button_color: "$default_icon_color_prominent",
+    radio_button_color: "$icon_color_prominent",
     radio_button_ripple_color: "rgba($radio_button_color_rgb, .2)",
     radio_button_color_unchecked: "$google_grey_700",
     radio_button_ripple_color_unchecked: "rgba($google_grey_600_rgb, .15)",
@@ -68,79 +68,79 @@
     link_color: "$google_blue_700",
 
     /* button-primary */
-    default_button_background_color_primary:
-        "$default_icon_color_prominent",
-    default_button_label_color_primary: {
+    button_background_color_primary:
+        "$icon_color_prominent",
+    button_label_color_primary: {
       light: "$google_grey_200",
       dark: "$google_grey_900",
     },
     /* button-primary:hover */
     /* TODO(calamity): Generate a linear-gradient() to use for compositing
        backgrounds */
-    default_button_background_color_primary_hover_overlay: {
+    button_background_color_primary_hover_overlay: {
       light: "rgba(255, 255, 255, 0.08)",
       dark: "rgba(0, 0, 0, 0.08)",
     },
     /* button-primary[disabled] */
-    default_button_background_color_primary_disabled: {
+    button_background_color_primary_disabled: {
       light: "$google_grey_100",
       dark: "$google_grey_800",
     },
-    default_button_label_color_primary_disabled: {
+    button_label_color_primary_disabled: {
       light: "$google_grey_600",
       dark: "$google_grey_500",
     },
 
     /* button-secondary */
-    default_button_label_color_secondary:
-        "$default_icon_color_prominent",
-    default_button_stroke_color_secondary: {
+    button_label_color_secondary:
+        "$icon_color_prominent",
+    button_stroke_color_secondary: {
       light: "$google_grey_300",
       dark: "$google_grey_700",
     },
     /* button-secondary:hover */
-    default_button_background_color_secondary_hover:
-        "rgba($default_icon_color_prominent_rgb, 0.04)",
+    button_background_color_secondary_hover:
+        "rgba($icon_color_prominent_rgb, 0.04)",
     /* button-secondary[disabled] */
-    default_button_label_color_secondary_disabled: {
+    button_label_color_secondary_disabled: {
       light: "$google_grey_600",
       dark: "$google_grey_500",
     },
-    default_button_stroke_color_secondary_disabled: {
+    button_stroke_color_secondary_disabled: {
       light: "$google_grey_100",
       dark: "$google_grey_800",
     },
 
     /* textfield */
-    default_textfield_background_color: {
+    textfield_background_color: {
       light: "$google_grey_100",
       dark: "rgba(0, 0, 0, 0.3)",
     },
-    default_texfield_label_color: {
+    textfield_label_color: {
       light: "$google_grey_700",
       dark: "rgba(255, 255, 255, 0.6)",
     },
-    default_texfield_input_color: {
+    textfield_input_color: {
       light: "$google_grey_900",
       dark: "rgba(255, 255, 255, 0.87)",
     },
     /* textfield:focus */
-    default_texfield_label_color_focus: "$default_icon_color_prominent",
+    textfield_label_color_focus: "$icon_color_prominent",
     /* textfield[error] */
-    default_texfield_label_color_error: {
+    textfield_label_color_error: {
       light: "$google_red_600",
       dark: "$google_red_300",
     },
     /* textfield[disabled] */
-    default_textfield_background_color_disabled: {
+    textfield_background_color_disabled: {
       light: "rgba($google_grey_100_rgb, 0.38)",
       dark: "rgba(0, 0, 0, 0.11)",
     },
-    default_texfield_label_color_disabled: {
+    textfield_label_color_disabled: {
       light: "rgba($google_grey_700_rgb, 0.38)",
       dark: "rgba(0, 0, 0, 0.23)",
     },
-    default_texfield_input_color_disabled: {
+    textfield_input_color_disabled: {
       light: "rgba($google_grey_900_rgb, 0.38)",
       dark: "rgba(255, 255, 255, 0.33)",
     },